mirror of
https://github.com/stablyai/orca.git
synced 2026-09-29 08:03:20 +00:00
598 lines
23 KiB
JavaScript
598 lines
23 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { mkdirSync } from 'node:fs'
|
|
import path from 'node:path'
|
|
import process from 'node:process'
|
|
import { startCdpServer } from 'inspect-webkit'
|
|
import { resolveEmulatorOrcaCli } from './emulator-orca-cli-selection.mjs'
|
|
import {
|
|
createHostedAdversarialRuntimeFixture,
|
|
removeHostedAdversarialRuntimeFixture
|
|
} from './hosted-adversarial-runtime-fixture.mjs'
|
|
import {
|
|
verifyHostedAdversarialProviderReview,
|
|
verifyHostedAdversarialTasks
|
|
} from './hosted-adversarial-provider-content.mjs'
|
|
import { stopHostedChildProcess } from './hosted-child-process-shutdown.mjs'
|
|
import { findAvailableHostedLoopbackPort } from './hosted-loopback-port.mjs'
|
|
import { parseHostedWebViewSimulatorE2eOptions } from './hosted-webview-simulator-e2e-options.mjs'
|
|
import {
|
|
captureHostedAccountsParity,
|
|
captureNativeAccountsBaseline
|
|
} from './hosted-ios-accounts-parity.mjs'
|
|
import { startHostedIosEmulatorController } from './hosted-ios-emulator-controller.mjs'
|
|
import { createHostedIosNativeBaselineStep } from './hosted-ios-native-baseline-step.mjs'
|
|
import {
|
|
assertNoHostedMobileWebCdpTarget,
|
|
waitForVisibleHostedWebView
|
|
} from './hosted-webview-cdp-session.mjs'
|
|
import { verifyHostedWebViewPrivacyIsolation } from './hosted-webview-privacy-isolation.mjs'
|
|
import { captureNativeAgentHistoryBaseline } from './hosted-ios-agent-history-parity.mjs'
|
|
import {
|
|
createHostedIosAdversarialContentInspector,
|
|
registerHostedIosAdversarialRepository
|
|
} from './hosted-ios-adversarial-content.mjs'
|
|
import { enableHostedTerminalDiagnostics } from './hosted-adversarial-terminal-links.mjs'
|
|
import {
|
|
captureHostedCoreRouteParity,
|
|
captureNativeCoreRouteBaselines
|
|
} from './hosted-ios-core-route-parity.mjs'
|
|
import {
|
|
captureHostedFilesPreviewParity,
|
|
captureNativeFilesPreviewBaselines
|
|
} from './hosted-ios-files-preview-parity.mjs'
|
|
import {
|
|
captureHostedWorkspaceParity,
|
|
captureNativeWorkspaceBaseline
|
|
} from './hosted-ios-workspace-parity.mjs'
|
|
import { verifyHostedAgentHistoryJourney } from './hosted-ios-agent-history-journey.mjs'
|
|
import {
|
|
alignHostedIosSessionPoint,
|
|
verifyHostedIosAdversarialTerminalLinks
|
|
} from './hosted-ios-adversarial-terminal-links.mjs'
|
|
import {
|
|
tapHostedIosAccessibilityControlByLabelPrefix,
|
|
tapHostedIosPoint
|
|
} from './hosted-ios-emulator-accessibility.mjs'
|
|
import { openHostedIosHybridRoute } from './hosted-ios-hybrid-route-handoff.mjs'
|
|
import {
|
|
startHostedIosMobileLauncher,
|
|
waitForHostedIosMobileLauncher
|
|
} from './hosted-ios-mobile-launcher.mjs'
|
|
import { verifyHostedIosNativeSettingsJourney } from './hosted-ios-native-settings-journey.mjs'
|
|
import { verifyHostedIosNativeAlertJourney } from './hosted-ios-native-alert-journey.mjs'
|
|
import {
|
|
bootHostedIosSimulator,
|
|
resolveHostedIosSimulatorUdid
|
|
} from './hosted-ios-simulator-device.mjs'
|
|
import { verifyHostedSourceControlReviewJourney } from './hosted-ios-source-control-review-journey.mjs'
|
|
import { verifyHostedHostOriginSourceControlJourney } from './hosted-ios-host-origin-source-control-journey.mjs'
|
|
import { captureNativeSourceControlReviewBaselines } from './hosted-ios-source-control-review-parity.mjs'
|
|
import { resetHostedIosPhotosPermission } from './hosted-ios-photo-permission-denial.mjs'
|
|
import { verifyHostedIosTerminalInputJourney } from './hosted-ios-terminal-device-input-journey.mjs'
|
|
import { waitForHostedIosBuildActivation } from './hosted-ios-build-activation.mjs'
|
|
import { completeHostedIosNativeOnboarding } from './hosted-ios-native-onboarding.mjs'
|
|
import { resolveHostedWebViewRuntimeDirectory } from './hosted-webview-runtime-directory.mjs'
|
|
import {
|
|
clearHostedIosWebViewSecurityProbe,
|
|
configureHostedIosWebViewSecurityProbe,
|
|
startHostedIosWebViewSecurityProbe
|
|
} from './hosted-ios-webview-security-probe.mjs'
|
|
import { hostedIosSimulatorAppPreparation } from './hosted-ios-simulator-app-preparation.mjs'
|
|
import {
|
|
installHostedWebViewRouteExceptionCapture,
|
|
readHostedWebViewRouteExceptionEvidence
|
|
} from './hosted-webview-route-exception-evidence.mjs'
|
|
import { captureHostedWebViewSecurityEvidence } from './hosted-webview-security-evidence.mjs'
|
|
import { evidenceStep, printHostedWebViewE2eReport } from './hosted-webview-e2e-report.mjs'
|
|
|
|
const worktree = path.resolve(import.meta.dirname, '../..')
|
|
const options = parseHostedWebViewSimulatorE2eOptions(process.argv.slice(2))
|
|
const runtimeDirectory = resolveHostedWebViewRuntimeDirectory({
|
|
worktree,
|
|
override: process.env.ORCA_E2E_MOBILE_WEBVIEW_RUN_DIRECTORY
|
|
})
|
|
const orcaSelection = resolveEmulatorOrcaCli({
|
|
explicitCommand: process.env.ORCA_CLI,
|
|
managedCommand: process.env.ORCA_CLI_COMMAND,
|
|
devRepoRoot: process.env.ORCA_DEV_REPO_ROOT,
|
|
worktree,
|
|
cwd: worktree
|
|
})
|
|
|
|
async function main() {
|
|
if (process.platform !== 'darwin') {
|
|
throw new Error('Hosted iOS WebView automation requires macOS and Xcode.')
|
|
}
|
|
mkdirSync(runtimeDirectory, { recursive: true, mode: 0o700 })
|
|
const deviceUdid = await resolveHostedIosSimulatorUdid(options.device)
|
|
let launcher = null
|
|
let inspector = null
|
|
let networkProbe = null
|
|
let emulatorController = null
|
|
let nativeAppPath = null
|
|
let adversarialFixture = null
|
|
let adversarialInspector = null
|
|
let adversarialProviderContent = null
|
|
let adversarialSessionYOffset = 0
|
|
let adversarialTerminalLinks = null
|
|
let adversarialTerminalHandle = null
|
|
let hostedExceptionDocument = null
|
|
try {
|
|
networkProbe = await startHostedIosWebViewSecurityProbe()
|
|
if (options.adversarialContent) {
|
|
adversarialFixture = await createHostedAdversarialRuntimeFixture({
|
|
probePort: networkProbe.port
|
|
})
|
|
}
|
|
await bootHostedIosSimulator(deviceUdid)
|
|
emulatorController = await startHostedIosEmulatorController({
|
|
orcaCli: orcaSelection.command,
|
|
runtimeDirectory,
|
|
worktree
|
|
})
|
|
await configureHostedIosWebViewSecurityProbe(deviceUdid, networkProbe)
|
|
const appPreparation = hostedIosSimulatorAppPreparation({ deviceUdid, worktree, ...options })
|
|
nativeAppPath = await evidenceStep(appPreparation.label, appPreparation.run)
|
|
if (options.securityOnly) {
|
|
await evidenceStep('Photos permission reset', () =>
|
|
resetHostedIosPhotosPermission(deviceUdid)
|
|
)
|
|
}
|
|
launcher = startHostedIosMobileLauncher({
|
|
deviceUdid,
|
|
emulatorControlUserDataPath: emulatorController.userData,
|
|
environment: adversarialFixture?.environment,
|
|
orcaCli: orcaSelection.command,
|
|
runtimeDirectory,
|
|
worktree
|
|
})
|
|
await waitForHostedIosMobileLauncher(launcher, options.timeoutMs)
|
|
const emulator = {
|
|
deviceUdid,
|
|
orcaCli: orcaSelection.command,
|
|
userDataDir: emulatorController.userData,
|
|
worktree
|
|
}
|
|
const inspectorPort = await findAvailableHostedLoopbackPort()
|
|
const discoveryUrl = `http://127.0.0.1:${inspectorPort}`
|
|
inspector = await startCdpServer({ port: inspectorPort })
|
|
const nativeBaselineStep = createHostedIosNativeBaselineStep({
|
|
assertNoHostedMobileWebCdpTarget,
|
|
discoveryUrl,
|
|
evidenceStep
|
|
})
|
|
const expectedWorkspace = path.basename(worktree)
|
|
const nativeOnboarding = await evidenceStep('native onboarding', () =>
|
|
completeHostedIosNativeOnboarding(emulator, expectedWorkspace, options.timeoutMs)
|
|
)
|
|
if (adversarialFixture) {
|
|
adversarialTerminalHandle = await evidenceStep('adversarial repository registration', () =>
|
|
registerHostedIosAdversarialRepository({
|
|
fixture: adversarialFixture,
|
|
orcaCli: orcaSelection.command,
|
|
pairingRuntimeUserDataPath: path.join(runtimeDirectory, 'paired-host', 'userData'),
|
|
probe: networkProbe,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
adversarialInspector = createHostedIosAdversarialContentInspector({
|
|
emulator,
|
|
fixture: adversarialFixture,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
}
|
|
const nativeWorkspace =
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await nativeBaselineStep('native workspace baseline', () =>
|
|
captureNativeWorkspaceBaseline({
|
|
deviceUdid,
|
|
emulator,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const nativeAccounts =
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await nativeBaselineStep('native Accounts baseline', () =>
|
|
captureNativeAccountsBaseline({
|
|
deviceUdid,
|
|
emulator,
|
|
expectedWorkspace,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const nativeCoreRoutes =
|
|
options.accountsOnly ||
|
|
options.adversarialContent ||
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await nativeBaselineStep('native Tasks and Session baselines', () =>
|
|
captureNativeCoreRouteBaselines({
|
|
deviceUdid,
|
|
emulator,
|
|
expectedWorkspace,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const nativeFilesPreview =
|
|
options.accountsOnly ||
|
|
options.securityOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await nativeBaselineStep('native Files and Preview baselines', () =>
|
|
captureNativeFilesPreviewBaselines({
|
|
deviceUdid,
|
|
emulator,
|
|
expectedWorkspace,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const nativeSourceControlReview =
|
|
options.accountsOnly ||
|
|
options.adversarialContent ||
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly
|
|
? null
|
|
: await nativeBaselineStep('native Source Control and Review baselines', () =>
|
|
captureNativeSourceControlReviewBaselines({
|
|
deviceUdid,
|
|
emulator,
|
|
expectedWorkspace,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const nativeAgentHistory =
|
|
options.accountsOnly ||
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await nativeBaselineStep('native Agent History baseline', () =>
|
|
captureNativeAgentHistoryBaseline({
|
|
deviceUdid,
|
|
emulator,
|
|
expectedWorkspace,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
await evidenceStep('native hybrid route handoff', () =>
|
|
openHostedIosHybridRoute(emulator, options.timeoutMs)
|
|
)
|
|
let workspaceDocument = await waitForVisibleHostedWebView({
|
|
discoveryUrl,
|
|
expectedText: expectedWorkspace,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
hostedExceptionDocument = workspaceDocument
|
|
await installHostedWebViewRouteExceptionCapture(workspaceDocument)
|
|
const nativeAlert = await evidenceStep('native Alert bridge journey', () =>
|
|
verifyHostedIosNativeAlertJourney({
|
|
discoveryUrl,
|
|
emulator,
|
|
expectedWorkspace,
|
|
timeoutMs: options.timeoutMs,
|
|
workspaceDocument
|
|
})
|
|
)
|
|
workspaceDocument = nativeAlert.workspaceDocument
|
|
if (adversarialFixture) {
|
|
await enableHostedTerminalDiagnostics(workspaceDocument)
|
|
}
|
|
const workspacePrivacyIsolation = options.adversarialContent
|
|
? await evidenceStep('workspace privacy isolation probe', () =>
|
|
verifyHostedWebViewPrivacyIsolation({ document: workspaceDocument })
|
|
)
|
|
: null
|
|
if (adversarialFixture) {
|
|
const result = await evidenceStep('adversarial task and error presentation', () =>
|
|
verifyHostedAdversarialTasks({
|
|
activatePoint: (point) => tapHostedIosPoint(emulator, point),
|
|
discoveryUrl,
|
|
document: workspaceDocument,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
adversarialProviderContent = { tasks: result.evidence, review: null }
|
|
workspaceDocument = result.workspaceDocument
|
|
}
|
|
const securityJourney = {
|
|
deviceUdid,
|
|
discoveryUrl,
|
|
emulator,
|
|
orcaCli: orcaSelection.command,
|
|
pairingRuntimeUserDataPath: path.join(runtimeDirectory, 'paired-host', 'userData'),
|
|
timeoutMs: options.timeoutMs,
|
|
worktree
|
|
}
|
|
const terminalDeviceInput =
|
|
options.securityOnly && !options.isolationOnly
|
|
? await evidenceStep('hosted terminal device input journey', () =>
|
|
verifyHostedIosTerminalInputJourney(
|
|
{ ...securityJourney, expectedWorkspace, workspaceDocument },
|
|
options
|
|
)
|
|
)
|
|
: null
|
|
const hostedWorkspace =
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await evidenceStep('hosted workspace parity', () =>
|
|
captureHostedWorkspaceParity({
|
|
deviceUdid,
|
|
document: workspaceDocument,
|
|
nativeBaseline: nativeWorkspace,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const hostedAccounts =
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await evidenceStep('hosted Accounts parity', () =>
|
|
captureHostedAccountsParity({
|
|
deviceUdid,
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
emulator,
|
|
nativeBaseline: nativeAccounts,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs,
|
|
expectedWorkspace,
|
|
workspaceDocument
|
|
})
|
|
)
|
|
workspaceDocument = hostedAccounts?.workspaceDocument ?? workspaceDocument
|
|
const hostedCoreRoutes =
|
|
options.accountsOnly ||
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await evidenceStep('hosted Tasks and Session parity', () =>
|
|
captureHostedCoreRouteParity({
|
|
deviceUdid,
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
emulator,
|
|
expectedWorkspace,
|
|
nativeBaselines: nativeCoreRoutes,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs,
|
|
workspaceDocument
|
|
})
|
|
)
|
|
const activeWorkspaceDocument = hostedCoreRoutes?.workspaceDocument ?? workspaceDocument
|
|
const hostedFilesPreview =
|
|
options.accountsOnly ||
|
|
options.securityOnly ||
|
|
options.nativeSettingsOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: await evidenceStep('hosted Files and Preview parity', () =>
|
|
captureHostedFilesPreviewParity({
|
|
deviceUdid,
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
emulator,
|
|
expectedWorkspace,
|
|
nativeBaselines: nativeFilesPreview,
|
|
runtimeDirectory,
|
|
timeoutMs: options.timeoutMs,
|
|
workspaceDocument: activeWorkspaceDocument
|
|
})
|
|
)
|
|
const parityWorkspaceDocument = hostedFilesPreview?.workspaceDocument ?? activeWorkspaceDocument
|
|
const historyEvidence =
|
|
options.accountsOnly ||
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.sourceControlOnly
|
|
? null
|
|
: options.nativeSettingsOnly
|
|
? await evidenceStep('native Terminal Settings journey', () =>
|
|
verifyHostedIosNativeSettingsJourney({
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
emulator,
|
|
workspaceDocument: parityWorkspaceDocument,
|
|
expectedWorkspace,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
: await evidenceStep('Agent History journey', () =>
|
|
verifyHostedAgentHistoryJourney({
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
launcher,
|
|
emulator,
|
|
nativeAgentHistory,
|
|
runtimeDirectory,
|
|
workspaceDocument: parityWorkspaceDocument,
|
|
expectedWorkspace,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
)
|
|
const sourceControlReview =
|
|
options.accountsOnly ||
|
|
options.securityOnly ||
|
|
options.filesPreviewOnly ||
|
|
options.nativeSettingsOnly
|
|
? null
|
|
: await evidenceStep('Source Control and Review journey', async () => {
|
|
let hostOrigin
|
|
if (options.sourceControlOnly) {
|
|
hostOrigin = await evidenceStep('host-origin Source Control journey', () =>
|
|
verifyHostedHostOriginSourceControlJourney({
|
|
discoveryUrl,
|
|
emulator,
|
|
nativeBaseline: nativeSourceControlReview.sourceControl,
|
|
timeoutMs: options.timeoutMs,
|
|
workspaceName: expectedWorkspace
|
|
})
|
|
)
|
|
workspaceDocument = hostOrigin.workspaceDocument
|
|
await tapHostedIosAccessibilityControlByLabelPrefix(
|
|
emulator,
|
|
adversarialFixture?.workspaceRowName ?? expectedWorkspace,
|
|
options.timeoutMs
|
|
)
|
|
}
|
|
let sessionDocument = await waitForVisibleHostedWebView({
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
expectedText: options.sourceControlOnly ? '1 tab' : '2 tabs',
|
|
expectedHrefIncludes: '/session/',
|
|
requireInteractiveControls: false,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
if (adversarialInspector) {
|
|
const result = await evidenceStep('adversarial terminal links', () =>
|
|
verifyHostedIosAdversarialTerminalLinks({
|
|
...securityJourney,
|
|
deviceUdid,
|
|
document: sessionDocument,
|
|
emulator,
|
|
positiveFilePath: adversarialFixture.repositoryFiles[0].filename,
|
|
probe: networkProbe,
|
|
stagedTerminalHandle: adversarialTerminalHandle,
|
|
worktree: adversarialFixture.root
|
|
})
|
|
)
|
|
adversarialTerminalLinks = result.evidence
|
|
adversarialSessionYOffset = result.yOffset
|
|
sessionDocument = result.sessionDocument
|
|
}
|
|
const sessionOrigin = await verifyHostedSourceControlReviewJourney({
|
|
deviceUdid,
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
emulator,
|
|
expectedSessionDiffText: adversarialInspector
|
|
? '3 tabs'
|
|
: options.sourceControlOnly
|
|
? '2 tabs'
|
|
: '3 tabs',
|
|
nativeBaselines: nativeSourceControlReview,
|
|
inspectChangedContent: adversarialInspector?.inspect,
|
|
inspectProviderContent: adversarialProviderContent
|
|
? async ({ document }) => {
|
|
adversarialProviderContent.review = await verifyHostedAdversarialProviderReview(
|
|
{
|
|
document,
|
|
timeoutMs: options.timeoutMs
|
|
}
|
|
)
|
|
}
|
|
: undefined,
|
|
runtimeDirectory,
|
|
sessionDocument,
|
|
transformPoint: adversarialInspector
|
|
? (point, document) =>
|
|
alignHostedIosSessionPoint(point, adversarialSessionYOffset, document)
|
|
: undefined,
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
return { ...sessionOrigin, ...(hostOrigin ? { hostOrigin } : {}) }
|
|
})
|
|
const adversarialContent = adversarialInspector
|
|
? await evidenceStep('adversarial filename and diff presentation', () =>
|
|
adversarialInspector.evidence()
|
|
)
|
|
: null
|
|
const securityDocument =
|
|
options.securityOnly && terminalDeviceInput
|
|
? (terminalDeviceInput.terminalClipboardImagePaste?.sessionDocument ??
|
|
terminalDeviceInput.photoPermissionRevocation?.sessionDocument ??
|
|
terminalDeviceInput.terminalClipboardPaste.sessionDocument)
|
|
: options.accountsOnly || options.filesPreviewOnly || options.isolationOnly
|
|
? parityWorkspaceDocument
|
|
: await waitForVisibleHostedWebView({
|
|
discoveryUrl: `http://127.0.0.1:${inspectorPort}`,
|
|
expectedText: options.nativeSettingsOnly ? 'Mobile Emulator' : 'reviewed',
|
|
expectedHrefIncludes: options.nativeSettingsOnly ? '/session/' : '/review/',
|
|
timeoutMs: options.timeoutMs
|
|
})
|
|
const { executableIsolation, navigationIsolation, networkIsolation, privacyIsolation } =
|
|
await captureHostedWebViewSecurityEvidence({
|
|
document: securityDocument,
|
|
evidenceStep,
|
|
probeId: networkProbe.token,
|
|
workspacePrivacyIsolation
|
|
})
|
|
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
if (networkProbe.observations.length > 0) {
|
|
throw new Error(
|
|
`Hosted WebView reached the network probe: ${networkProbe.observations.join(', ')}`
|
|
)
|
|
}
|
|
await waitForHostedIosBuildActivation(deviceUdid, options, runtimeDirectory)
|
|
printHostedWebViewE2eReport({
|
|
adversarialContent,
|
|
adversarialProviderContent,
|
|
adversarialTerminalLinks,
|
|
deviceUdid,
|
|
executableIsolation,
|
|
expectedWorkspace,
|
|
historyEvidence,
|
|
hostedAccounts,
|
|
hostedCoreRoutes,
|
|
hostedFilesPreview,
|
|
hostedWorkspace,
|
|
nativeAlert,
|
|
nativeAppPath,
|
|
nativeOnboarding,
|
|
navigationIsolation,
|
|
networkIsolation,
|
|
privacyIsolation,
|
|
sourceControlReview,
|
|
terminalDeviceInput,
|
|
workspaceDocument
|
|
})
|
|
} catch (error) {
|
|
const evidence = hostedExceptionDocument
|
|
? await readHostedWebViewRouteExceptionEvidence(hostedExceptionDocument).catch(() => [])
|
|
: []
|
|
if (evidence.length > 0) {
|
|
throw new Error(
|
|
`${error instanceof Error ? error.message : String(error)} Hosted exception evidence: ${JSON.stringify(evidence)}`,
|
|
{ cause: error }
|
|
)
|
|
}
|
|
throw error
|
|
} finally {
|
|
inspector?.stop()
|
|
await stopHostedChildProcess(launcher)
|
|
if (adversarialFixture) {
|
|
await removeHostedAdversarialRuntimeFixture(adversarialFixture)
|
|
}
|
|
await emulatorController?.stop()
|
|
await clearHostedIosWebViewSecurityProbe(deviceUdid)
|
|
await networkProbe?.stop()
|
|
}
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error instanceof Error ? (error.stack ?? error.message) : String(error))
|
|
process.exitCode = 1
|
|
})
|