wip(chrome-ext): runtime-external polyfill checkpoint + harness diagnostics
Checkpoint of in-progress runtime-external work. Not load-bearing for any
shipping feature; the architecture documented here is incomplete and the
flow it targets (Proton Pass /auth-ext) still fails. Landing it so the
diagnostic instrumentation isn't lost.
Polyfill state:
- Page-side preload (runtime-external-preload.cjs) is in REDACT mode:
removes chrome.runtime.sendMessage on externally_connectable origins to
force webextension-polyfill-style senders down their postMessage +
content-script path. Verified by harness; the orchestrator content
script either isn't injected or doesn't forward to the BG SW, so the
redacted path produces the same Oops the native path does.
- The else branch that wholesale-replaced window.chrome.runtime with a
synthetic object has been removed. It was racing Chromium's
native_extension_bindings_system bindings install and producing
`ERROR:extensions/renderer/native_extension_bindings_system.cc:712
Failed to create API on Chrome object` log lines (one per API
namespace) on every preload attach. The redact-only path is the one
we want.
- Main-side runtime-external.js retains origin-fallback resolution
(findExtensionByOrigin) and per-SW listener attachment via
session.serviceWorkers.getWorkerFromVersionID — both reusable when the
bridge-page architecture lands.
- BG SW shim keeps the native-dispatch logging wrapper around captured
onMessageExternal listeners. It confirmed that native cross-origin
sendMessage dispatch in Electron 40 does not deliver to BG SW
listeners, even with the polyfill disabled.
Right architecture (untested, for next session): hidden BrowserWindow
loading a chrome-extension://<id>/peek-bridge.html page. Extension pages
have both ipcRenderer (regular renderer surface) and same-extension
chrome.runtime.connect, so they can pump main-process IPC into the BG
SW via a long-lived port — neither of which the BG SW context exposes.
PEEK_DISABLE_RUNTIME_EXTERNAL_POLYFILL=1 (entry.ts) skips installation
entirely for side-by-side testing.
Harness improvements:
- tests/manual/harness/tracer.ts: streams events to disk via a 500ms
drain so traces survive app shutdown; captures main-process
stdout/stderr; captures SW console + registration + running-status
events on the profile partition.
- tests/fixtures/desktop-app.ts: stable persistent profile path for
test-harness-* profiles in the manual project so login state survives
across runs; cleanupAllTempDirs skips them.