rea-agents 1.7.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -59
- package/bridge/ghidra/ReaGhidraBridge.java +96 -11
- package/dist/application/ArtifactExtraction.js +1 -1
- package/dist/application/ArtifactInventory/classify.js +42 -0
- package/dist/application/ArtifactInventory/hash.js +43 -0
- package/dist/application/ArtifactInventory/reader.js +41 -0
- package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
- package/dist/application/ArtifactInventory/scanReader.js +124 -0
- package/dist/application/ArtifactInventory/types.js +10 -0
- package/dist/application/ArtifactInventory.js +9 -351
- package/dist/application/AuthorizedArtifactInventory.js +2 -2
- package/dist/application/BinarySession.js +47 -270
- package/dist/application/BinarySessionExecution.js +28 -0
- package/dist/application/BinarySessionOpen.js +39 -0
- package/dist/application/BinarySessionRecords.js +149 -0
- package/dist/application/BinarySessionStatus.js +75 -0
- package/dist/application/CapabilityInventory.js +42 -2
- package/dist/application/ClientRegistrationStatus.js +1 -1
- package/dist/application/CrossVersionInventory.js +8 -2
- package/dist/application/CrossVersionInvestigation.js +11 -29
- package/dist/application/CrossVersionInvestigationCollections.js +23 -0
- package/dist/application/DirectAnalysis.js +47 -44
- package/dist/application/Doctor.js +165 -197
- package/dist/application/DoctorDiagnostics.js +180 -0
- package/dist/application/ElectronBoundaryAnalysis.js +112 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
- package/dist/application/EnhancedToolPagination.js +22 -0
- package/dist/application/EnhancedToolTypes.js +4 -0
- package/dist/application/EnhancedTools.js +58 -50
- package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
- package/dist/application/InvestigationProviders.js +30 -0
- package/dist/application/InvestigationWorkspaceStore.js +24 -10
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
- package/dist/application/JavaScriptArtifactFiles.js +6 -2
- package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
- package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
- package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
- package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
- package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
- package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
- package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
- package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
- package/dist/application/JavaScriptJsonModules.js +39 -0
- package/dist/application/JavaScriptModuleRelationships.js +262 -0
- package/dist/application/JavaScriptReplayPermission.js +16 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +292 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/LinuxHopper.js +10 -0
- package/dist/application/MacHopper.js +22 -11
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
- package/dist/application/PermissionAuthority.js +106 -63
- package/dist/application/ProcessCaptureCapability.js +1 -1
- package/dist/application/ProcessCapturePermission.js +13 -0
- package/dist/application/ProcessCli.js +2 -12
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +15 -11
- package/dist/application/ProjectPermissionStore.js +49 -9
- package/dist/application/RealHopperAssertions.js +76 -0
- package/dist/application/ReconstructionCoverageService.js +69 -0
- package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
- package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
- package/dist/application/Setup.js +147 -259
- package/dist/application/SetupClientConfiguration.js +220 -0
- package/dist/application/SetupClients.js +24 -2
- package/dist/application/SetupPlan.js +123 -12
- package/dist/application/SetupSkill.js +26 -12
- package/dist/application/SupportedClients.js +1 -0
- package/dist/application/Uninstall.js +6 -3
- package/dist/application/WindowsCapabilities.js +86 -0
- package/dist/application/runtime.js +2 -0
- package/dist/artifacts/AsarArtifactReader.js +11 -0
- package/dist/browser/BrowserProcessStartup.js +88 -0
- package/dist/browser/CdpCaptureDocuments.js +12 -8
- package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
- package/dist/browser/CdpCaptureEventHandlers.js +336 -0
- package/dist/browser/CdpCaptureEventHelpers.js +71 -0
- package/dist/browser/CdpCaptureEventState.js +1 -0
- package/dist/browser/CdpCaptureEventTypes.js +1 -0
- package/dist/browser/CdpCaptureEvents.js +46 -464
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +5 -1
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpObservationSession.js +51 -8
- package/dist/browser/CdpPageCapture.js +12 -129
- package/dist/browser/CdpPageCaptureScripts.js +97 -0
- package/dist/browser/CdpPageCaptureWorkers.js +46 -0
- package/dist/browser/CdpWebMcpDiscovery.js +38 -14
- package/dist/browser/PngVisualDiff.js +9 -2
- package/dist/catalogIdentity.js +8 -1
- package/dist/cli/artifactCommands.js +82 -0
- package/dist/cli/coreAnalysisCommands.js +232 -0
- package/dist/cli/managedCommands.js +397 -0
- package/dist/cli/managedProjectGraphCommand.js +24 -0
- package/dist/cli/options.js +9 -0
- package/dist/cli/setupCommands.js +108 -0
- package/dist/cli/types.js +1 -0
- package/dist/cli/utilityCommands.js +122 -0
- package/dist/cli.js +13 -383
- package/dist/cliApplicationCommands.js +176 -0
- package/dist/cliBrowserAdvancedCommands.js +73 -16
- package/dist/cliBrowserCommands.js +39 -115
- package/dist/cliCommandNames.js +17 -0
- package/dist/cliElectronCommands.js +100 -27
- package/dist/cliEvidenceCommands.js +13 -2
- package/dist/cliInvestigationCommands.js +53 -10
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliObservationOptions.js +137 -0
- package/dist/cliPolicyCommands.js +80 -46
- package/dist/cliSetup.js +289 -0
- package/dist/config/environment.js +107 -0
- package/dist/config/parseConfig.js +228 -0
- package/dist/config/parsers.js +68 -0
- package/dist/config/permissions.js +30 -0
- package/dist/config/types.js +1 -0
- package/dist/config.js +1 -292
- package/dist/contracts/applicationToolContracts.js +225 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +49 -47
- package/dist/contracts/toolEffects.js +174 -0
- package/dist/contracts/toolOutputSchemaGroups.js +232 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
- package/dist/contracts/toolOutputSchemas.js +2 -535
- package/dist/doctorRuntime.js +42 -1
- package/dist/domain/analysisErrorPresentation.js +234 -0
- package/dist/domain/analysisErrorProjection.js +284 -0
- package/dist/domain/artifactComparison.js +37 -19
- package/dist/domain/binaryTarget.js +87 -37
- package/dist/domain/browserObservation.js +1 -282
- package/dist/domain/browserObservationSchemas.js +286 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +32 -448
- package/dist/domain/functionComparison.js +4 -165
- package/dist/domain/functionComparisonDimensions.js +164 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
- package/dist/domain/javascriptApplicationGraph.js +2 -1
- package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +233 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptExportInstrumentation.js +97 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +100 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
- package/dist/domain/javascriptSemanticAnalysis.js +386 -0
- package/dist/domain/javascriptSemanticIr.js +30 -0
- package/dist/domain/javascriptSemanticProjection.js +366 -0
- package/dist/domain/javascriptSemanticState.js +40 -0
- package/dist/domain/javascriptSemanticTraversal.js +22 -0
- package/dist/domain/javascriptSemanticValues.js +352 -0
- package/dist/domain/javascriptStaticAnalysis.js +26 -254
- package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
- package/dist/domain/javascriptStaticAnalysisState.js +6 -0
- package/dist/domain/knownPageCoverage.js +21 -0
- package/dist/domain/managedApplicationGraph.js +206 -0
- package/dist/domain/managedApplicationGraphCoverage.js +170 -0
- package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
- package/dist/domain/managedApplicationGraphNodes.js +336 -0
- package/dist/domain/managedArtifact.js +452 -0
- package/dist/domain/managedMemberComparison.js +211 -0
- package/dist/domain/managedMemberComparisonCoverage.js +72 -0
- package/dist/domain/managedMemberComparisonMatch.js +356 -0
- package/dist/domain/managedNativeVerification.js +46 -0
- package/dist/domain/managedNativeVerificationMatch.js +272 -0
- package/dist/domain/managedNativeVerificationSchemas.js +141 -0
- package/dist/domain/managedReconstruction.js +196 -0
- package/dist/domain/managedRuntimeCorrelation.js +184 -0
- package/dist/domain/nodeRuntimeCharacterization.js +66 -0
- package/dist/domain/permissionPolicy.js +2 -0
- package/dist/domain/reconstructionCoverage.js +387 -0
- package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
- package/dist/domain/reconstructionVerificationSchemas.js +9 -3
- package/dist/domain/runtimeCharacterization.js +85 -0
- package/dist/domain/webBundleAnalyzer.js +3 -409
- package/dist/domain/webBundleAnalyzerAst.js +77 -0
- package/dist/domain/webBundleAnalyzerInspection.js +307 -0
- package/dist/domain/webBundleAnalyzerResult.js +120 -0
- package/dist/dotnet/ManagedArtifactInspector.js +339 -0
- package/dist/dotnet/ManagedMemberInspector.js +153 -0
- package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
- package/dist/dotnet/ManagedMemberRows.js +120 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +104 -0
- package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
- package/dist/dotnet/ManagedMetadataLayout.js +259 -0
- package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
- package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
- package/dist/dotnet/ManagedPeReader.js +188 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraClient.js +76 -91
- package/dist/ghidra/GhidraClientStartup.js +29 -0
- package/dist/ghidra/GhidraClientWire.js +34 -0
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraDiagnostics.js +6 -1
- package/dist/ghidra/GhidraInstallation.js +20 -15
- package/dist/ghidra/GhidraLauncher.js +93 -29
- package/dist/ghidra/GhidraProvider.js +67 -161
- package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
- package/dist/ghidra/GhidraSessionValues.js +2 -0
- package/dist/ghidra/GhidraSocketConnection.js +44 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
- package/dist/ghidra/GhidraTransport.js +71 -0
- package/dist/identity.js +3 -2
- package/dist/main/messages.js +5 -0
- package/dist/main/reload.js +49 -0
- package/dist/main/shutdown.js +25 -0
- package/dist/main/startup.js +14 -0
- package/dist/main/state.js +26 -0
- package/dist/main/transport.js +61 -0
- package/dist/main/types.js +1 -0
- package/dist/main.js +35 -132
- package/dist/process/PrivateRuntimeRoot.js +3 -2
- package/dist/process/ProcessOwnership.js +35 -0
- package/dist/process/ProviderProcess.js +2 -0
- package/dist/replay/JavaScriptReplayWorker.js +300 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
- package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayOutcome.js +95 -0
- package/dist/replay/ReplayProcessLifecycle.js +71 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/ProcessCaptureElicitation.js +157 -0
- package/dist/server/createServer.js +158 -41
- package/dist/server/registerApplicationTools/characterization.js +57 -0
- package/dist/server/registerApplicationTools/compareVersions.js +34 -0
- package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
- package/dist/server/registerApplicationTools/coverage.js +84 -0
- package/dist/server/registerApplicationTools/helpers.js +42 -0
- package/dist/server/registerApplicationTools/traceFeature.js +26 -0
- package/dist/server/registerApplicationTools/types.js +1 -0
- package/dist/server/registerApplicationTools.js +13 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +61 -60
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +39 -12
- package/dist/server/registerEnhancedTools.js +52 -15
- package/dist/server/registerEvidenceResources.js +54 -0
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools/helpers.js +74 -0
- package/dist/server/registerInvestigationTools/types.js +1 -0
- package/dist/server/registerInvestigationTools.js +103 -132
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
- package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
- package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
- package/dist/server/registerManagedWorkflowTools/types.js +1 -0
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
- package/dist/server/registerManagedWorkflowTools.js +13 -0
- package/dist/server/registerOfficialTools.js +81 -67
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionRecordTools.js +137 -0
- package/dist/server/registerSessionStatusTool.js +9 -8
- package/dist/server/registerSessionTools.js +77 -216
- package/dist/server/sessionAvailabilityPolicy.js +10 -0
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +177 -2
- package/dist/server/toolResult.js +30 -17
- package/package.json +21 -14
- package/scripts/rea.mjs +1 -1
- package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
- package/scripts/prepare-node-pty.mjs +0 -35
- package/scripts/rebuild-native.mjs +0 -22
|
@@ -1,78 +1,126 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
3
|
import { BrowserObservationError } from "../domain/errors.js";
|
|
4
|
-
import { createWebTextArtifact } from "../domain/webContentArtifact.js";
|
|
5
4
|
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
6
|
-
import {
|
|
5
|
+
import { delayWithCancellation, numberValue, recordValue, recordsValue, requiredRecord, stringValue, } from "./CdpCaptureValues.js";
|
|
6
|
+
import { ingestElectronScriptEvent, } from "./CdpElectronScriptEvents.js";
|
|
7
|
+
import { captureElectronScripts } from "./CdpElectronScripts.js";
|
|
8
|
+
import { captureElectronWorkers } from "./CdpElectronWorkers.js";
|
|
7
9
|
import { authorizedElectronFile, canonicalElectronRoots, } from "./ElectronFileScope.js";
|
|
8
10
|
/** Passively inspect one root-confined Electron file page. */
|
|
9
11
|
export const inspectCdpElectronPage = async (context) => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const state = {
|
|
13
|
+
roots: await canonicalElectronRoots(context.input.allowed_file_roots),
|
|
14
|
+
completeness: new CdpCaptureCompleteness(),
|
|
15
|
+
scripts: [],
|
|
16
|
+
executionContextFrames: new Map(),
|
|
17
|
+
limitations: [
|
|
18
|
+
"Only canonical file paths contained by an approved root are retained.",
|
|
19
|
+
"REA does not evaluate renderer JavaScript, invoke Electron APIs, navigate, click, or close the page.",
|
|
20
|
+
"Script contents require separate source-capture approval and remain byte bounded.",
|
|
21
|
+
],
|
|
22
|
+
mainFrameId: undefined,
|
|
23
|
+
navigationDuringCapture: false,
|
|
24
|
+
};
|
|
15
25
|
const removeListener = context.connection.onEvent((event) => {
|
|
16
26
|
if (event.sessionId !== context.sessionId)
|
|
17
27
|
return;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
ingestElectronScriptEvent({
|
|
29
|
+
event,
|
|
30
|
+
scripts: state.scripts,
|
|
31
|
+
executionContextFrames: state.executionContextFrames,
|
|
32
|
+
completeness: state.completeness,
|
|
33
|
+
});
|
|
34
|
+
if (state.mainFrameId !== undefined &&
|
|
35
|
+
navigatedFrameId(event) === state.mainFrameId)
|
|
36
|
+
state.navigationDuringCapture = true;
|
|
21
37
|
});
|
|
22
|
-
const startedAt = new Date().toISOString();
|
|
23
38
|
try {
|
|
24
|
-
await
|
|
25
|
-
await context.connection.send("Page.enable", {}, context.sessionId, context.signal);
|
|
26
|
-
const before = await context.connection.send("Page.getFrameTree", {}, context.sessionId, context.signal);
|
|
27
|
-
const frames = await captureFrames(before, roots, context.input.limits.max_frames, completeness);
|
|
28
|
-
const main = frames[0];
|
|
29
|
-
if (main === undefined)
|
|
30
|
-
throw new BrowserObservationError("inspect_web_page", "target_not_allowed");
|
|
31
|
-
mainFrameId = main.frame_id;
|
|
32
|
-
await context.connection.send("Debugger.enable", { maxScriptsCacheSize: 4 * 1_024 * 1_024 }, context.sessionId, context.signal);
|
|
33
|
-
await delayWithCancellation(context.input.observation_ms, "inspect_electron_page", context.signal);
|
|
34
|
-
await report(context.progress, 2, "Capturing Electron structure");
|
|
35
|
-
const resources = await captureResources(context, roots, completeness);
|
|
36
|
-
const dom = await captureDom(context, roots, completeness);
|
|
37
|
-
const normalizedScripts = await captureScripts(context, roots, scripts, completeness);
|
|
38
|
-
const after = await context.connection.send("Page.getFrameTree", {}, context.sessionId, context.signal);
|
|
39
|
-
const afterMain = await mainFilePath(after, roots);
|
|
40
|
-
if (afterMain === undefined)
|
|
41
|
-
throw new BrowserObservationError("inspect_web_page", "target_not_allowed");
|
|
42
|
-
if (navigationDuringCapture || afterMain !== main.file_path)
|
|
43
|
-
throw new BrowserObservationError("inspect_web_page", "target_changed");
|
|
44
|
-
await report(context.progress, 3, "Electron inspection complete");
|
|
45
|
-
return {
|
|
46
|
-
schema_version: 1,
|
|
47
|
-
browser: context.discovery.version,
|
|
48
|
-
target: {
|
|
49
|
-
target_id: context.target.id,
|
|
50
|
-
type: context.target.type,
|
|
51
|
-
title: context.target.title.slice(0, 16_384),
|
|
52
|
-
file_path: main.file_path,
|
|
53
|
-
attached: context.target.attached,
|
|
54
|
-
},
|
|
55
|
-
capture_window: {
|
|
56
|
-
started_at: startedAt,
|
|
57
|
-
ended_at: new Date().toISOString(),
|
|
58
|
-
observation_ms: context.input.observation_ms,
|
|
59
|
-
},
|
|
60
|
-
completeness: completeness.snapshot(),
|
|
61
|
-
frames,
|
|
62
|
-
dom,
|
|
63
|
-
scripts: normalizedScripts,
|
|
64
|
-
resources,
|
|
65
|
-
limitations: [
|
|
66
|
-
"Only canonical file paths contained by an approved root are retained.",
|
|
67
|
-
"REA does not evaluate renderer JavaScript, invoke Electron APIs, navigate, click, or close the page.",
|
|
68
|
-
"Script contents require separate source-capture approval and remain byte bounded.",
|
|
69
|
-
],
|
|
70
|
-
};
|
|
39
|
+
return await runElectronInspection(context, state, new Date().toISOString());
|
|
71
40
|
}
|
|
72
41
|
finally {
|
|
73
42
|
removeListener();
|
|
74
43
|
}
|
|
75
44
|
};
|
|
45
|
+
const runElectronInspection = async (context, state, startedAt) => {
|
|
46
|
+
const frames = await authorizeInitialFrames(context, state);
|
|
47
|
+
const main = frames[0];
|
|
48
|
+
state.mainFrameId = main.frame_id;
|
|
49
|
+
await enableElectronCapture(context);
|
|
50
|
+
await delayWithCancellation(context.input.observation_ms, "inspect_electron_page", context.signal);
|
|
51
|
+
const captured = await captureElectronContent(context, state, frames);
|
|
52
|
+
await assertStableMainFrame(context, state, main.file_path);
|
|
53
|
+
await report(context.progress, 3, "Electron inspection complete");
|
|
54
|
+
return {
|
|
55
|
+
schema_version: 1,
|
|
56
|
+
browser: context.discovery.version,
|
|
57
|
+
target: {
|
|
58
|
+
target_id: context.target.id,
|
|
59
|
+
type: context.target.type,
|
|
60
|
+
title: context.target.title.slice(0, 16_384),
|
|
61
|
+
file_path: main.file_path,
|
|
62
|
+
attached: context.target.attached,
|
|
63
|
+
},
|
|
64
|
+
capture_window: {
|
|
65
|
+
started_at: startedAt,
|
|
66
|
+
ended_at: new Date().toISOString(),
|
|
67
|
+
observation_ms: context.input.observation_ms,
|
|
68
|
+
},
|
|
69
|
+
completeness: state.completeness.snapshot(),
|
|
70
|
+
frames,
|
|
71
|
+
...captured,
|
|
72
|
+
limitations: state.limitations,
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const authorizeInitialFrames = async (context, state) => {
|
|
76
|
+
await report(context.progress, 1, "Authorizing Electron file frames");
|
|
77
|
+
await context.connection.send("Page.enable", {}, context.sessionId, context.signal);
|
|
78
|
+
const result = await context.connection.send("Page.getFrameTree", {}, context.sessionId, context.signal);
|
|
79
|
+
const frames = await captureFrames(result, state.roots, context.input.limits.max_frames, state.completeness);
|
|
80
|
+
if (frames[0] === undefined)
|
|
81
|
+
throw new BrowserObservationError("inspect_web_page", "target_not_allowed");
|
|
82
|
+
return frames;
|
|
83
|
+
};
|
|
84
|
+
const enableElectronCapture = async (context) => {
|
|
85
|
+
await context.connection.send("Runtime.enable", {}, context.sessionId, context.signal);
|
|
86
|
+
await context.connection.send("Debugger.enable", { maxScriptsCacheSize: 4 * 1_024 * 1_024 }, context.sessionId, context.signal);
|
|
87
|
+
};
|
|
88
|
+
const captureElectronContent = async (context, state, frames) => {
|
|
89
|
+
await report(context.progress, 2, "Capturing Electron structure");
|
|
90
|
+
const frameIds = new Set(frames.map((frame) => frame.frame_id));
|
|
91
|
+
const resources = await captureResources(context, state.roots, state.completeness);
|
|
92
|
+
const dom = await captureDom(context, state.roots, state.completeness);
|
|
93
|
+
const scripts = await captureElectronScripts({
|
|
94
|
+
connection: context.connection,
|
|
95
|
+
sessionId: context.sessionId,
|
|
96
|
+
...(context.signal === undefined ? {} : { signal: context.signal }),
|
|
97
|
+
request: context.input,
|
|
98
|
+
roots: state.roots,
|
|
99
|
+
scripts: state.scripts,
|
|
100
|
+
executionContextFrames: state.executionContextFrames,
|
|
101
|
+
frameIds,
|
|
102
|
+
completeness: state.completeness,
|
|
103
|
+
});
|
|
104
|
+
const workers = await captureElectronWorkers({
|
|
105
|
+
connection: context.connection,
|
|
106
|
+
...(context.signal === undefined ? {} : { signal: context.signal }),
|
|
107
|
+
target: context.target,
|
|
108
|
+
request: context.input,
|
|
109
|
+
roots: state.roots,
|
|
110
|
+
frameIds,
|
|
111
|
+
completeness: state.completeness,
|
|
112
|
+
limitations: state.limitations,
|
|
113
|
+
});
|
|
114
|
+
return { dom, scripts, resources, workers };
|
|
115
|
+
};
|
|
116
|
+
const assertStableMainFrame = async (context, state, expectedPath) => {
|
|
117
|
+
const result = await context.connection.send("Page.getFrameTree", {}, context.sessionId, context.signal);
|
|
118
|
+
const afterPath = await mainFilePath(result, state.roots);
|
|
119
|
+
if (afterPath === undefined)
|
|
120
|
+
throw new BrowserObservationError("inspect_web_page", "target_not_allowed");
|
|
121
|
+
if (state.navigationDuringCapture || afterPath !== expectedPath)
|
|
122
|
+
throw new BrowserObservationError("inspect_web_page", "target_changed");
|
|
123
|
+
};
|
|
76
124
|
const navigatedFrameId = (event) => {
|
|
77
125
|
const params = recordValue(event.params);
|
|
78
126
|
if (params === undefined)
|
|
@@ -83,33 +131,6 @@ const navigatedFrameId = (event) => {
|
|
|
83
131
|
return stringValue(params.frameId);
|
|
84
132
|
return undefined;
|
|
85
133
|
};
|
|
86
|
-
const ingestScript = (event, scripts, completeness) => {
|
|
87
|
-
if (event.method !== "Debugger.scriptParsed")
|
|
88
|
-
return;
|
|
89
|
-
const value = recordValue(event.params);
|
|
90
|
-
const scriptId = stringValue(value?.scriptId);
|
|
91
|
-
const rawUrl = stringValue(value?.url);
|
|
92
|
-
if (scriptId === undefined || scriptId.length > 256) {
|
|
93
|
-
completeness.exclude("scripts", "invalid_protocol_value");
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
if (rawUrl === undefined || rawUrl === "") {
|
|
97
|
-
completeness.exclude("scripts", "unattributed_origin");
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (scripts.length >= 2_000) {
|
|
101
|
-
completeness.drop("scripts");
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
scripts.push({
|
|
105
|
-
scriptId,
|
|
106
|
-
rawUrl,
|
|
107
|
-
hash: (stringValue(value?.hash) ?? "").slice(0, 512),
|
|
108
|
-
length: nonnegativeInteger(value?.length),
|
|
109
|
-
isModule: value?.isModule === true,
|
|
110
|
-
language: boundedText(value?.scriptLanguage, 100),
|
|
111
|
-
});
|
|
112
|
-
};
|
|
113
134
|
const captureFrames = async (result, roots, maximum, completeness) => {
|
|
114
135
|
const frameTree = recordValue(requiredRecord(result).frameTree);
|
|
115
136
|
if (frameTree === undefined)
|
|
@@ -227,82 +248,6 @@ const captureDom = async (context, roots, completeness) => {
|
|
|
227
248
|
completeness.truncate("dom");
|
|
228
249
|
return { total_nodes: total, nodes };
|
|
229
250
|
};
|
|
230
|
-
const captureScripts = async (context, roots, scripts, completeness) => {
|
|
231
|
-
let total = 0;
|
|
232
|
-
let sourceBytes = 0;
|
|
233
|
-
const items = [];
|
|
234
|
-
const seen = new Set();
|
|
235
|
-
for (const script of scripts) {
|
|
236
|
-
const path = await authorizedElectronFile(script.rawUrl, roots);
|
|
237
|
-
if (path === undefined) {
|
|
238
|
-
completeness.exclude("scripts", "out_of_target_scope");
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
const identity = {
|
|
242
|
-
file_path: path,
|
|
243
|
-
cdp_hash: script.hash,
|
|
244
|
-
length: script.length,
|
|
245
|
-
is_module: script.isModule,
|
|
246
|
-
language: script.language,
|
|
247
|
-
};
|
|
248
|
-
const scriptKey = `electron_script_${digest(identity)}`;
|
|
249
|
-
if (seen.has(scriptKey))
|
|
250
|
-
continue;
|
|
251
|
-
seen.add(scriptKey);
|
|
252
|
-
total += 1;
|
|
253
|
-
if (items.length >= context.input.limits.max_scripts) {
|
|
254
|
-
completeness.drop("scripts");
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
let source = {
|
|
258
|
-
included: false,
|
|
259
|
-
reason: "source capture was not approved",
|
|
260
|
-
};
|
|
261
|
-
if (context.input.include_script_sources) {
|
|
262
|
-
if (script.length > context.input.limits.max_script_source_bytes ||
|
|
263
|
-
sourceBytes + script.length >
|
|
264
|
-
context.input.limits.max_total_script_source_bytes) {
|
|
265
|
-
source = {
|
|
266
|
-
included: false,
|
|
267
|
-
reason: "script source byte limit reached",
|
|
268
|
-
};
|
|
269
|
-
completeness.truncate("script_sources");
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
const result = requiredRecord(await context.connection.send("Debugger.getScriptSource", { scriptId: script.scriptId }, context.sessionId, context.signal));
|
|
273
|
-
const text = stringValue(result.scriptSource) ?? "";
|
|
274
|
-
const bytes = Buffer.byteLength(text);
|
|
275
|
-
if (bytes > context.input.limits.max_script_source_bytes ||
|
|
276
|
-
sourceBytes + bytes >
|
|
277
|
-
context.input.limits.max_total_script_source_bytes) {
|
|
278
|
-
source = {
|
|
279
|
-
included: false,
|
|
280
|
-
reason: "script source byte limit reached",
|
|
281
|
-
};
|
|
282
|
-
completeness.truncate("script_sources");
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
source = {
|
|
286
|
-
included: true,
|
|
287
|
-
artifact: createWebTextArtifact(text, "text/javascript"),
|
|
288
|
-
};
|
|
289
|
-
sourceBytes += bytes;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
items.push({
|
|
294
|
-
script_key: scriptKey,
|
|
295
|
-
...identity,
|
|
296
|
-
source,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
if (!context.input.include_script_sources)
|
|
300
|
-
completeness.exclude("script_sources", "not_approved", total);
|
|
301
|
-
return {
|
|
302
|
-
total,
|
|
303
|
-
items: items.sort((left, right) => left.script_key.localeCompare(right.script_key)),
|
|
304
|
-
};
|
|
305
|
-
};
|
|
306
251
|
const mainFilePath = async (result, roots) => {
|
|
307
252
|
const frameTree = recordValue(requiredRecord(result).frameTree);
|
|
308
253
|
const frame = recordValue(frameTree?.frame);
|
|
@@ -314,7 +259,6 @@ const integer = (value, fallback) => {
|
|
|
314
259
|
const number = numberValue(value);
|
|
315
260
|
return number === undefined ? fallback : Math.trunc(number);
|
|
316
261
|
};
|
|
317
|
-
const nonnegativeInteger = (value) => Math.max(0, integer(value, 0));
|
|
318
262
|
const digest = (value) => {
|
|
319
263
|
const encoded = canonicalize(value);
|
|
320
264
|
if (encoded === undefined)
|
|
@@ -108,7 +108,11 @@ export class CdpElectronProvider {
|
|
|
108
108
|
}
|
|
109
109
|
finally {
|
|
110
110
|
if (targetSession !== undefined)
|
|
111
|
-
await closeCdpTargetSession(targetSession, [
|
|
111
|
+
await closeCdpTargetSession(targetSession, [
|
|
112
|
+
"Debugger",
|
|
113
|
+
"Runtime",
|
|
114
|
+
"Page",
|
|
115
|
+
]);
|
|
112
116
|
}
|
|
113
117
|
}
|
|
114
118
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
2
|
+
import { boundedText, numberValue, recordValue, stringValue, } from "./CdpCaptureValues.js";
|
|
3
|
+
/** Retain only bounded script/frame metadata from passive Electron events. */
|
|
4
|
+
export const ingestElectronScriptEvent = (input) => {
|
|
5
|
+
if (input.event.method === "Runtime.executionContextsCleared") {
|
|
6
|
+
input.executionContextFrames.clear();
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (input.event.method === "Runtime.executionContextDestroyed") {
|
|
10
|
+
const parameters = recordValue(input.event.params);
|
|
11
|
+
const key = executionContextKey(parameters?.executionContextId);
|
|
12
|
+
if (key !== null)
|
|
13
|
+
input.executionContextFrames.delete(key);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (input.event.method === "Runtime.executionContextCreated") {
|
|
17
|
+
retainExecutionContext(input.event, input.executionContextFrames, input.completeness);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (input.event.method !== "Debugger.scriptParsed")
|
|
21
|
+
return;
|
|
22
|
+
const value = recordValue(input.event.params);
|
|
23
|
+
const scriptId = stringValue(value?.scriptId);
|
|
24
|
+
const rawUrl = stringValue(value?.url);
|
|
25
|
+
if (scriptId === undefined || scriptId.length > 256) {
|
|
26
|
+
input.completeness.exclude("scripts", "invalid_protocol_value");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (rawUrl === undefined || rawUrl === "") {
|
|
30
|
+
input.completeness.exclude("scripts", "unattributed_origin");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (input.scripts.length >= 2_000) {
|
|
34
|
+
input.completeness.drop("scripts");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
input.scripts.push({
|
|
38
|
+
scriptId,
|
|
39
|
+
rawUrl,
|
|
40
|
+
hash: (stringValue(value?.hash) ?? "").slice(0, 512),
|
|
41
|
+
length: nonnegativeInteger(value?.length),
|
|
42
|
+
isModule: value?.isModule === true,
|
|
43
|
+
language: boundedText(value?.scriptLanguage, 100),
|
|
44
|
+
executionContextKey: executionContextKey(value?.executionContextId),
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const retainExecutionContext = (event, frames, completeness) => {
|
|
48
|
+
const parameters = recordValue(event.params);
|
|
49
|
+
const runtimeContext = recordValue(parameters?.context);
|
|
50
|
+
const contextKey = executionContextKey(runtimeContext?.id);
|
|
51
|
+
const frameId = stringValue(recordValue(runtimeContext?.auxData)?.frameId);
|
|
52
|
+
if (contextKey === null || frameId === undefined || frameId.length > 256)
|
|
53
|
+
return;
|
|
54
|
+
if (frames.size >= 2_000 && !frames.has(contextKey)) {
|
|
55
|
+
completeness.truncate("scripts");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
frames.set(contextKey, frameId);
|
|
59
|
+
};
|
|
60
|
+
const nonnegativeInteger = (value) => {
|
|
61
|
+
const number = numberValue(value);
|
|
62
|
+
return number === undefined ? 0 : Math.max(0, Math.trunc(number));
|
|
63
|
+
};
|
|
64
|
+
const executionContextKey = (value) => {
|
|
65
|
+
const identifier = numberValue(value);
|
|
66
|
+
return identifier !== undefined && Number.isSafeInteger(identifier)
|
|
67
|
+
? String(identifier)
|
|
68
|
+
: null;
|
|
69
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import canonicalize from "canonicalize";
|
|
3
|
+
import { createWebTextArtifact } from "../domain/webContentArtifact.js";
|
|
4
|
+
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
5
|
+
import { requiredRecord, stringValue } from "./CdpCaptureValues.js";
|
|
6
|
+
import { authorizedElectronFile } from "./ElectronFileScope.js";
|
|
7
|
+
/** Normalize root-confined script metadata and optionally approved source. */
|
|
8
|
+
export const captureElectronScripts = async (input) => {
|
|
9
|
+
let total = 0;
|
|
10
|
+
let sourceBytes = 0;
|
|
11
|
+
const items = [];
|
|
12
|
+
const seen = new Set();
|
|
13
|
+
for (const script of input.scripts) {
|
|
14
|
+
const path = await authorizedElectronFile(script.rawUrl, input.roots);
|
|
15
|
+
if (path === undefined) {
|
|
16
|
+
input.completeness.exclude("scripts", "out_of_target_scope");
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const mappedFrame = script.executionContextKey === null
|
|
20
|
+
? undefined
|
|
21
|
+
: input.executionContextFrames.get(script.executionContextKey);
|
|
22
|
+
const identity = {
|
|
23
|
+
frame_id: mappedFrame !== undefined && input.frameIds.has(mappedFrame)
|
|
24
|
+
? mappedFrame
|
|
25
|
+
: null,
|
|
26
|
+
file_path: path,
|
|
27
|
+
cdp_hash: script.hash,
|
|
28
|
+
length: script.length,
|
|
29
|
+
is_module: script.isModule,
|
|
30
|
+
language: script.language,
|
|
31
|
+
};
|
|
32
|
+
const scriptKey = `electron_script_${digest(identity)}`;
|
|
33
|
+
if (seen.has(scriptKey))
|
|
34
|
+
continue;
|
|
35
|
+
seen.add(scriptKey);
|
|
36
|
+
total += 1;
|
|
37
|
+
if (items.length >= input.request.limits.max_scripts) {
|
|
38
|
+
input.completeness.drop("scripts");
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const capturedSource = await captureScriptSource(input, script, sourceBytes);
|
|
42
|
+
sourceBytes += capturedSource.bytes;
|
|
43
|
+
items.push({
|
|
44
|
+
script_key: scriptKey,
|
|
45
|
+
...identity,
|
|
46
|
+
source: capturedSource.source,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (!input.request.include_script_sources)
|
|
50
|
+
input.completeness.exclude("script_sources", "not_approved", total);
|
|
51
|
+
return {
|
|
52
|
+
total,
|
|
53
|
+
items: items.sort((left, right) => left.script_key.localeCompare(right.script_key)),
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const captureScriptSource = async (input, script, sourceBytes) => {
|
|
57
|
+
if (!input.request.include_script_sources)
|
|
58
|
+
return {
|
|
59
|
+
source: {
|
|
60
|
+
included: false,
|
|
61
|
+
reason: "source capture was not approved",
|
|
62
|
+
},
|
|
63
|
+
bytes: 0,
|
|
64
|
+
};
|
|
65
|
+
if (sourceLimitReached(input.request.limits, script.length, sourceBytes))
|
|
66
|
+
return sourceLimitResult(input.completeness);
|
|
67
|
+
const result = requiredRecord(await input.connection.send("Debugger.getScriptSource", { scriptId: script.scriptId }, input.sessionId, input.signal));
|
|
68
|
+
const text = stringValue(result.scriptSource) ?? "";
|
|
69
|
+
const bytes = Buffer.byteLength(text);
|
|
70
|
+
if (sourceLimitReached(input.request.limits, bytes, sourceBytes))
|
|
71
|
+
return sourceLimitResult(input.completeness);
|
|
72
|
+
return {
|
|
73
|
+
source: {
|
|
74
|
+
included: true,
|
|
75
|
+
artifact: createWebTextArtifact(text, "text/javascript"),
|
|
76
|
+
},
|
|
77
|
+
bytes,
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const sourceLimitReached = (limits, bytes, previousBytes) => bytes > limits.max_script_source_bytes ||
|
|
81
|
+
previousBytes + bytes > limits.max_total_script_source_bytes;
|
|
82
|
+
const sourceLimitResult = (completeness) => {
|
|
83
|
+
completeness.truncate("script_sources");
|
|
84
|
+
return {
|
|
85
|
+
source: { included: false, reason: "script source byte limit reached" },
|
|
86
|
+
bytes: 0,
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
const digest = (value) => {
|
|
90
|
+
const encoded = canonicalize(value);
|
|
91
|
+
if (encoded === undefined)
|
|
92
|
+
throw new TypeError("Expected canonical JSON");
|
|
93
|
+
return createHash("sha256").update(encoded).digest("hex");
|
|
94
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
2
|
+
import { boundedText, recordValue, recordsValue, stringValue, } from "./CdpCaptureValues.js";
|
|
3
|
+
import { optionalCdpCommand } from "./CdpOptionalCommand.js";
|
|
4
|
+
import { authorizedElectronFile } from "./ElectronFileScope.js";
|
|
5
|
+
/** Inventory root-confined worker targets without attaching to them. */
|
|
6
|
+
export const captureElectronWorkers = async (input) => {
|
|
7
|
+
const result = await optionalCdpCommand({
|
|
8
|
+
connection: input.connection,
|
|
9
|
+
sessionId: undefined,
|
|
10
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
11
|
+
}, "Target.getTargets", {}, input.limitations);
|
|
12
|
+
if (result === undefined) {
|
|
13
|
+
input.completeness.unavailable("workers");
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
const workers = [];
|
|
17
|
+
for (const target of recordsValue(recordValue(result)?.targetInfos)) {
|
|
18
|
+
const type = stringValue(target.type) ?? "";
|
|
19
|
+
if (!type.includes("worker"))
|
|
20
|
+
continue;
|
|
21
|
+
const openerTargetId = boundedTargetField(target.openerId);
|
|
22
|
+
const parentFrameId = boundedTargetField(target.parentFrameId);
|
|
23
|
+
if (openerTargetId !== input.target.id &&
|
|
24
|
+
(parentFrameId === null || !input.frameIds.has(parentFrameId))) {
|
|
25
|
+
input.completeness.exclude("workers", "out_of_target_scope");
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const path = await authorizedElectronFile(stringValue(target.url) ?? "", input.roots);
|
|
29
|
+
if (path === undefined) {
|
|
30
|
+
input.completeness.exclude("workers", "out_of_target_scope");
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (workers.length >= input.request.limits.max_workers) {
|
|
34
|
+
input.completeness.truncate("workers");
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const targetId = boundedTargetField(target.targetId);
|
|
38
|
+
if (targetId === null) {
|
|
39
|
+
input.completeness.exclude("workers", "invalid_protocol_value");
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
workers.push({
|
|
43
|
+
target_id: targetId,
|
|
44
|
+
type: type.slice(0, 100),
|
|
45
|
+
file_path: path,
|
|
46
|
+
attached: target.attached === true,
|
|
47
|
+
opener_target_id: openerTargetId,
|
|
48
|
+
parent_frame_id: parentFrameId,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return workers.sort((left, right) => left.target_id.localeCompare(right.target_id));
|
|
52
|
+
};
|
|
53
|
+
const boundedTargetField = (value) => {
|
|
54
|
+
const field = boundedText(value, 256);
|
|
55
|
+
return field === null || field === "" ? null : field;
|
|
56
|
+
};
|
|
@@ -133,7 +133,13 @@ class TimelineCapture {
|
|
|
133
133
|
targetTerminated() {
|
|
134
134
|
if (this.#endReason !== undefined)
|
|
135
135
|
return;
|
|
136
|
-
this.#add(
|
|
136
|
+
this.#add({
|
|
137
|
+
type: "target_terminated",
|
|
138
|
+
params: {},
|
|
139
|
+
rawUrl: null,
|
|
140
|
+
requestId: null,
|
|
141
|
+
detail: "target_terminated",
|
|
142
|
+
});
|
|
137
143
|
this.end("target_terminated");
|
|
138
144
|
}
|
|
139
145
|
setFinalUrl(rawUrl) {
|
|
@@ -145,7 +151,13 @@ class TimelineCapture {
|
|
|
145
151
|
return;
|
|
146
152
|
const reason = safeDetail(params.reason);
|
|
147
153
|
this.#pendingReload = reason === "reload";
|
|
148
|
-
this.#add(
|
|
154
|
+
this.#add({
|
|
155
|
+
type: "navigation_requested",
|
|
156
|
+
params,
|
|
157
|
+
rawUrl: stringValue(params.url) ?? null,
|
|
158
|
+
requestId: null,
|
|
159
|
+
detail: reason,
|
|
160
|
+
});
|
|
149
161
|
}
|
|
150
162
|
#navigationCommitted(params) {
|
|
151
163
|
const frame = recordValue(params.frame);
|
|
@@ -153,7 +165,13 @@ class TimelineCapture {
|
|
|
153
165
|
return;
|
|
154
166
|
const rawUrl = stringValue(frame?.url);
|
|
155
167
|
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
|
156
|
-
this.#add(
|
|
168
|
+
this.#add({
|
|
169
|
+
type: this.#pendingReload ? "same_origin_reload" : "navigation_committed",
|
|
170
|
+
params: { ...params, frameId: frame?.id, loaderId: frame?.loaderId },
|
|
171
|
+
rawUrl: rawUrl ?? null,
|
|
172
|
+
requestId: null,
|
|
173
|
+
detail: safeDetail(frame?.transitionType),
|
|
174
|
+
});
|
|
157
175
|
this.#pendingReload = false;
|
|
158
176
|
if (destination.scope === "approved")
|
|
159
177
|
this.finalUrl = destination.url;
|
|
@@ -168,7 +186,13 @@ class TimelineCapture {
|
|
|
168
186
|
return;
|
|
169
187
|
const rawUrl = stringValue(params.url);
|
|
170
188
|
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
|
171
|
-
this.#add(
|
|
189
|
+
this.#add({
|
|
190
|
+
type: "same_document_navigation",
|
|
191
|
+
params,
|
|
192
|
+
rawUrl: rawUrl ?? null,
|
|
193
|
+
requestId: null,
|
|
194
|
+
detail: null,
|
|
195
|
+
});
|
|
172
196
|
if (destination.scope === "approved")
|
|
173
197
|
this.finalUrl = destination.url;
|
|
174
198
|
else {
|
|
@@ -184,7 +208,13 @@ class TimelineCapture {
|
|
|
184
208
|
const request = recordValue(params.request);
|
|
185
209
|
const rawUrl = stringValue(request?.url);
|
|
186
210
|
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
|
187
|
-
this.#add(
|
|
211
|
+
this.#add({
|
|
212
|
+
type: "redirect",
|
|
213
|
+
params,
|
|
214
|
+
rawUrl: rawUrl ?? null,
|
|
215
|
+
requestId: stringValue(params.requestId) ?? null,
|
|
216
|
+
detail: null,
|
|
217
|
+
});
|
|
188
218
|
if (destination.scope !== "approved") {
|
|
189
219
|
this.completeness.exclude("timeline", "out_of_target_scope");
|
|
190
220
|
this.end("target_left_scope");
|
|
@@ -194,14 +224,27 @@ class TimelineCapture {
|
|
|
194
224
|
const frame = stringValue(params.frameId);
|
|
195
225
|
if (frame !== undefined && frame !== this.mainFrameId)
|
|
196
226
|
return;
|
|
197
|
-
this.#add(
|
|
227
|
+
this.#add({
|
|
228
|
+
type: "load_failed",
|
|
229
|
+
params,
|
|
230
|
+
rawUrl: null,
|
|
231
|
+
requestId: stringValue(params.requestId) ?? null,
|
|
232
|
+
detail: safeNetworkError(params.errorText),
|
|
233
|
+
});
|
|
198
234
|
}
|
|
199
235
|
#lifecycle(params) {
|
|
200
236
|
if (stringValue(params.frameId) !== this.mainFrameId)
|
|
201
237
|
return;
|
|
202
|
-
this.#add(
|
|
238
|
+
this.#add({
|
|
239
|
+
type: "lifecycle",
|
|
240
|
+
params,
|
|
241
|
+
rawUrl: null,
|
|
242
|
+
requestId: null,
|
|
243
|
+
detail: safeDetail(params.name),
|
|
244
|
+
});
|
|
203
245
|
}
|
|
204
|
-
#add(
|
|
246
|
+
#add(options) {
|
|
247
|
+
const { type, params, rawUrl = null, requestId = null, detail = null, } = options;
|
|
205
248
|
const destination = rawUrl == null ? null : scopedUrl(rawUrl, this.allowedOrigins);
|
|
206
249
|
if (this.timeline.length >= this.maximum) {
|
|
207
250
|
this.completeness.drop("timeline_events");
|