[GH-ISSUE #375] Capture Electron main/preload/utility process lifecycle and shell events #221

Open
opened 2026-10-15 18:22:36 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Jul 20, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/375

Capture Electron BrowserWindow/WebContents lifecycle, main/preload/utility processes, navigation/permission/download/crash/external-open events, deep-link delivery, and main/renderer errors.

Part of #64.

Reconstruction requirements

Renderer-only CDP observation is insufficient for reconstructing an Electron application. The capture must connect activity across process roles while preserving the distinction between observation and inferred ownership.

Capture at least:

  • app ready/activate/window-all-closed/before-quit/will-quit/quit lifecycle;
  • BrowserWindow creation, options projection, load/show/hide/focus/blur/close/destroy;
  • WebContents creation, navigation, frame, renderer-process-gone, unresponsive/responsive, console, and load failures;
  • preload identity and exact contextBridge/IPC channel observations where available;
  • utilityProcess and child-process spawn/exit/signal/stdio ownership;
  • session permission, navigation, popup, download, and certificate decisions;
  • shell.openExternal/openPath and external-protocol attempts;
  • protocol handlers and deep-link delivery;
  • main/preload/renderer uncaught errors and rejected promises;
  • native-addon load requests tied to exact artifact digests;
  • updater/relaunch attempts without allowing uncontrolled mutation.

Evidence model

  • Correlate process IDs, WebContents IDs, frame IDs, window IDs, and exact script/preload identities.
  • Record a lifecycle timeline with raw source events and monotonic capture order.
  • Distinguish observed IPC send/receive from static unique-literal pairing and from inferred handler ownership.
  • Preserve payload shapes/approved values according to the existing privacy boundary.
  • Make incomplete attach history explicit; activity before capture is unavailable.
  • Reconcile with JavaScript Application Graph and passive renderer Evidence using exact identities/digests.
  • Support partial-order comparison for concurrent main/renderer/utility events.

Safety

  • Requires explicit approval and isolated user-data/HOME.
  • External protocols, navigation, downloads, updater actions, and arbitrary shell effects are blocked by default.
  • Capture must not click, navigate, execute page JavaScript, or close unrelated user-owned Electron applications unless separately authorized.
  • Cleanup is restricted to owned processes and profiles.

Acceptance criteria

  • Real Electron fixtures cover main, preload, renderer, utilityProcess, and ordinary child-process roles.
  • Window/WebContents/process identifiers correlate across the timeline.
  • IPC observations preserve channel, direction, sender/receiver identity, and approved payload evidence.
  • Navigation, popup, permission, download, protocol, shell, crash, and error events are captured.
  • Native-addon requests cite exact artifact digests without claiming verified exports.
  • Static/runtime reconciliation keeps unique, ambiguous, dynamic, unavailable, and contradicted mappings distinct, integrating with JavaScript runtime semantic tracing in #404 where available.
  • Capture comparison supports concurrent lifecycle schedules without broad sorting, using the partial-order model in #403.
  • External effects are blocked and recorded as attempted/denied by default.
  • Cancellation and cleanup terminate only owned processes and remove the isolated profile.
  • Documentation includes reconstruction-oriented main/preload/renderer and deep-link examples.

Capture architecture

Use multiple evidence sources and label their authority rather than flattening them into one inferred stream:

  • Electron/main-process hooks for application, window, WebContents, session, protocol, shell, updater, and utility-process APIs;
  • debugger/CDP attachment for renderer targets, frames, console, network, and crash state;
  • preload instrumentation for contextBridge and IPC boundaries when injection is explicitly enabled;
  • process-tree observation for OS processes, exits, signals, and stdio;
  • passive filesystem/network observation where already authorized;
  • static application-graph correlation as a separate inference layer.

Every normalized event must retain source, capture method, authority, raw Evidence reference, and any loss/attach caveat.

Identity and lifecycle state

Define stable capture-scoped identities for app, session, window, web_contents, frame, renderer_process, utility_process, child_process, preload, and download. Never correlate solely by PID because renderer processes can be reused and IDs can outlive or precede attachment.

Useful edges include:

window -> owns -> web_contents
web_contents -> contains -> frame
frame -> executes -> preload/script
web_contents -> hosted_by -> renderer_process
utility_process -> spawned_by -> main_process
ipc_event -> sender/receiver -> frame|web_contents|main
navigation -> replaces/preserves -> document

Lifecycle events should include both attempted and completed phases, for example window.close_requested versus window.closed, navigation.requested versus did_finish_load, and shell.open_external_attempted versus blocked/completed.

IPC and boundary evidence

  • Cover ipcMain.on/once/handle, ipcRenderer.send/sendSync/invoke/postMessage, webContents.send, ports/message channels, and contextBridge exposure where observable.
  • Preserve channel values only when allowed; otherwise retain stable keyed hashes plus shape metadata.
  • Record direction, sync/async mode, call/result/error phase, sender frame/document identity, receiver registration candidate, and transfer-list metadata.
  • Do not pair a send with a handler merely because their channel literals match. Report unique, ambiguous, contradicted, and unobserved candidates separately.
  • Treat dynamic channels, custom wrappers, sandboxed preloads, isolated worlds, and late attachment as explicit limitations.

Interception policy

Classify effects as observe, allow, block, or emulate. Defaults should be conservative:

  • external navigation, shell opens, downloads, updater mutation, relaunch, OS integration, and non-loopback traffic: block and record;
  • loopback fixtures and isolated-profile writes: allow only within the active grant;
  • permission/certificate/dialog handlers: return configured deterministic responses and record both request and decision;
  • application quit/crash: observe and preserve teardown evidence without restarting unless the scenario explicitly requests it.

An interception must preserve the attempted arguments and synthetic outcome; it must not masquerade as a real external success.

Failure and completeness model

Return typed states such as complete, partial_attach, unsupported_electron, hook_conflict, target_exited, capture_truncated, cancelled, and cleanup_failed. A capture manifest should state which roles and event families were observed, unavailable, blocked, or possibly missed.

Version and fixture matrix

  • Test supported Electron major ranges and document the compatibility strategy for API drift.
  • Include context isolation on/off, sandbox on/off, multiple windows, cross-origin frames, renderer reuse/crash, utility processes, custom protocols, deep links before/after ready, and packaged ASAR applications.
  • Include negative fixtures proving blocked shell/updater/download effects did not occur.
  • Include a late-attach fixture that produces partial evidence without a false completeness claim.
  • Verify ordering through #403 rather than expecting one global byte order.

Delivery slices

  1. App/window/WebContents/process identities and lifecycle journal.
  2. IPC/contextBridge/preload observation and static correlation.
  3. Session, navigation, permission, download, shell, protocol, and deep-link interception.
  4. Utility processes, crashes/errors, native-addon requests, and teardown completeness.
  5. Comparison, conformance export, compatibility matrix, and reconstruction documentation.
Originally created by @morluto on GitHub (Jul 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/375 Capture Electron BrowserWindow/WebContents lifecycle, main/preload/utility processes, navigation/permission/download/crash/external-open events, deep-link delivery, and main/renderer errors. Part of #64. ## Reconstruction requirements Renderer-only CDP observation is insufficient for reconstructing an Electron application. The capture must connect activity across process roles while preserving the distinction between observation and inferred ownership. Capture at least: - app ready/activate/window-all-closed/before-quit/will-quit/quit lifecycle; - BrowserWindow creation, options projection, load/show/hide/focus/blur/close/destroy; - WebContents creation, navigation, frame, renderer-process-gone, unresponsive/responsive, console, and load failures; - preload identity and exact contextBridge/IPC channel observations where available; - utilityProcess and child-process spawn/exit/signal/stdio ownership; - session permission, navigation, popup, download, and certificate decisions; - shell.openExternal/openPath and external-protocol attempts; - protocol handlers and deep-link delivery; - main/preload/renderer uncaught errors and rejected promises; - native-addon load requests tied to exact artifact digests; - updater/relaunch attempts without allowing uncontrolled mutation. ## Evidence model - Correlate process IDs, WebContents IDs, frame IDs, window IDs, and exact script/preload identities. - Record a lifecycle timeline with raw source events and monotonic capture order. - Distinguish observed IPC send/receive from static unique-literal pairing and from inferred handler ownership. - Preserve payload shapes/approved values according to the existing privacy boundary. - Make incomplete attach history explicit; activity before capture is unavailable. - Reconcile with JavaScript Application Graph and passive renderer Evidence using exact identities/digests. - Support partial-order comparison for concurrent main/renderer/utility events. ## Safety - Requires explicit approval and isolated user-data/HOME. - External protocols, navigation, downloads, updater actions, and arbitrary shell effects are blocked by default. - Capture must not click, navigate, execute page JavaScript, or close unrelated user-owned Electron applications unless separately authorized. - Cleanup is restricted to owned processes and profiles. ## Acceptance criteria - [ ] Real Electron fixtures cover main, preload, renderer, utilityProcess, and ordinary child-process roles. - [ ] Window/WebContents/process identifiers correlate across the timeline. - [ ] IPC observations preserve channel, direction, sender/receiver identity, and approved payload evidence. - [ ] Navigation, popup, permission, download, protocol, shell, crash, and error events are captured. - [ ] Native-addon requests cite exact artifact digests without claiming verified exports. - [ ] Static/runtime reconciliation keeps unique, ambiguous, dynamic, unavailable, and contradicted mappings distinct, integrating with JavaScript runtime semantic tracing in #404 where available. - [ ] Capture comparison supports concurrent lifecycle schedules without broad sorting, using the partial-order model in #403. - [ ] External effects are blocked and recorded as attempted/denied by default. - [ ] Cancellation and cleanup terminate only owned processes and remove the isolated profile. - [ ] Documentation includes reconstruction-oriented main/preload/renderer and deep-link examples. ## Capture architecture Use multiple evidence sources and label their authority rather than flattening them into one inferred stream: - Electron/main-process hooks for application, window, WebContents, session, protocol, shell, updater, and utility-process APIs; - debugger/CDP attachment for renderer targets, frames, console, network, and crash state; - preload instrumentation for contextBridge and IPC boundaries when injection is explicitly enabled; - process-tree observation for OS processes, exits, signals, and stdio; - passive filesystem/network observation where already authorized; - static application-graph correlation as a separate inference layer. Every normalized event must retain source, capture method, authority, raw Evidence reference, and any loss/attach caveat. ## Identity and lifecycle state Define stable capture-scoped identities for `app`, `session`, `window`, `web_contents`, `frame`, `renderer_process`, `utility_process`, `child_process`, `preload`, and `download`. Never correlate solely by PID because renderer processes can be reused and IDs can outlive or precede attachment. Useful edges include: ```text window -> owns -> web_contents web_contents -> contains -> frame frame -> executes -> preload/script web_contents -> hosted_by -> renderer_process utility_process -> spawned_by -> main_process ipc_event -> sender/receiver -> frame|web_contents|main navigation -> replaces/preserves -> document ``` Lifecycle events should include both attempted and completed phases, for example `window.close_requested` versus `window.closed`, `navigation.requested` versus `did_finish_load`, and `shell.open_external_attempted` versus `blocked`/`completed`. ## IPC and boundary evidence - Cover `ipcMain.on/once/handle`, `ipcRenderer.send/sendSync/invoke/postMessage`, `webContents.send`, ports/message channels, and contextBridge exposure where observable. - Preserve channel values only when allowed; otherwise retain stable keyed hashes plus shape metadata. - Record direction, sync/async mode, call/result/error phase, sender frame/document identity, receiver registration candidate, and transfer-list metadata. - Do not pair a send with a handler merely because their channel literals match. Report unique, ambiguous, contradicted, and unobserved candidates separately. - Treat dynamic channels, custom wrappers, sandboxed preloads, isolated worlds, and late attachment as explicit limitations. ## Interception policy Classify effects as `observe`, `allow`, `block`, or `emulate`. Defaults should be conservative: - external navigation, shell opens, downloads, updater mutation, relaunch, OS integration, and non-loopback traffic: block and record; - loopback fixtures and isolated-profile writes: allow only within the active grant; - permission/certificate/dialog handlers: return configured deterministic responses and record both request and decision; - application quit/crash: observe and preserve teardown evidence without restarting unless the scenario explicitly requests it. An interception must preserve the attempted arguments and synthetic outcome; it must not masquerade as a real external success. ## Failure and completeness model Return typed states such as `complete`, `partial_attach`, `unsupported_electron`, `hook_conflict`, `target_exited`, `capture_truncated`, `cancelled`, and `cleanup_failed`. A capture manifest should state which roles and event families were observed, unavailable, blocked, or possibly missed. ## Version and fixture matrix - Test supported Electron major ranges and document the compatibility strategy for API drift. - Include context isolation on/off, sandbox on/off, multiple windows, cross-origin frames, renderer reuse/crash, utility processes, custom protocols, deep links before/after ready, and packaged ASAR applications. - Include negative fixtures proving blocked shell/updater/download effects did not occur. - Include a late-attach fixture that produces partial evidence without a false completeness claim. - Verify ordering through #403 rather than expecting one global byte order. ## Delivery slices 1. App/window/WebContents/process identities and lifecycle journal. 2. IPC/contextBridge/preload observation and static correlation. 3. Session, navigation, permission, download, shell, protocol, and deep-link interception. 4. Utility processes, crashes/errors, native-addon requests, and teardown completeness. 5. Comparison, conformance export, compatibility matrix, and reconstruction documentation.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#221
No description provided.