Repository navigation
Electrobun: self-shipped embedded WebDriver server for all OSes (native automation + WebView2 CDP-hardening immunity) #629
Description
Summary
Ship a self-shipped embedded W3C WebDriver server for Electrobun that drives the app's webview in-process — over Electrobun's Bun-side executeJavascript / webview→Bun RPC channel — on all three OSes (macOS WKWebView, Windows WebView2, Linux WebKitGTK). One mechanism, no external driver, no CDP debug port.
This collapses several separate problems into one line of work:
- macOS native (WKWebView) automation without requiring a CEF build — the deferred "out of scope" item from Electrobun: support non-CEF (native-renderer) apps #317.
- Windows immunity to WebView2 Runtime 150 breaks Windows WebDriver automation (Tauri + Electrobun) #542 — the embedded server never uses
msedgedriver/--remote-debugging-port, so the WebView2 Runtime-150 elevated-host hardening that breaks the CDP-attach path is simply not in the loop. - Transport unification — replaces today's per-OS patchwork (CEF/chromedriver on macOS, WebView2/msedgedriver on Windows, WebKitGTK/W3C on Linux) with a single in-process driver.
- Sidesteps the CEF-track gaps on macOS (Electrobun: track upstream CEF fixes (Linux/Windows, multiremote, multi-window, deeplink) #320) — it isn't CEF at all.
Model already shipped for other surface-less webviews: tauri-plugin-wdio-webdriver (packages/tauri-plugin-webdriver) and wdio-dioxus-embedded-driver. Not upstream-blocked — the mechanism is entirely ours.
Why an embedded driver, per OS
| OS | Native renderer | Automation today | With the embedded driver |
|---|---|---|---|
| macOS | WKWebView | none → CEF-only | native automation, no CEF — and the only option (see below) |
| Windows | WebView2 (Chromium) | CDP-attach (shipped 0.1.0), but broken by Runtime-150 elevated-host hardening (#542) |
in-process, no debug port → #542-immune |
| Linux | WebKitGTK | external WebKitWebDriver attach (W3C) |
in-process → drops the external-driver dependency |
macOS is the one that must have this
macOS WKWebView exposes no remote automation surface — verified against the electrobun v2.0.1 source (package/src/native/macos/nativeWrapper.mm): the only inspector hook is the private _inspector selector used to show/close the local Web Inspector GUI (the code notes "WKWebView doesn't have public DevTools API"); the public inspectable property isn't set; there is no CDP, no W3C WebDriver, no safaridriver attach for embedded webviews, and no WKAutomation/automationSession glue. Unlike WebKitGTK — which exposes webkit_web_context_set_automation_allowed() publicly (what upstream blackboardsh/electrobun#467 / 2.0.1 wired up) — Apple's equivalent (WebAutomationSession / _WKAutomationController) is private and Safari-only, never wired for third-party embedders. So macOS cannot be closed by an attach archetype or an upstream Electrobun fix; the embedded driver is mandatory there and beneficial on Windows/Linux.
Proposed approach
- A Bun-side embedded W3C WebDriver server package (built on Electrobun's Zig-core socket transport / webview RPC) that the app registers.
- Serves W3C WebDriver from the app process; drives the webview via
executeJavascriptand returns results over the existing webview → Bun RPC channel. - Largely engine-agnostic — because
executeJavascript/RPC abstracts the underlying engine, one Bun-side implementation covers all three OSes (contrast: the Tauri embedded driver carries per-OS native code). - Service: add an embedded-driver archetype + attach-over-W3C path (like the Linux external-driver archetype, but the driver is in-process and ours), available on all three OSes.
Caveats (all OSes — inherent to JS-synthesised automation)
Already seen on our other embedded drivers; document them, don't treat as blockers:
- JS-synthesised input is
isTrusted: false— trusted-input gates reject it (native dialogs, trusted-event-gated handlers). See tauri: synthesized keys arrive isTrusted:false on Windows/WebView2 — Escape never closes a modal <dialog> (works on macOS/WKWebView) #612 for the Windows CDP-keys work on our Tauri/Dioxus embedded drivers. - No screenshot API from this channel.
- Result return is bounded by what serialises over the RPC channel.
Optional trusted-input augmentation (follow-up): regain trusted input per OS via native input synthesis — on Windows, WebView2's in-process CallDevToolsProtocolMethod API (which is also #542-immune, no debug port, exactly how the Tauri driver gets trusted keys). Bigger lift (needs native/Zig access, not just the JS-eval channel); can come later.
Relationship to the existing CDP/W3C paths
The embedded driver complements rather than fully replaces the attach paths: it's the immune / consistent / native default. Keep the CDP/W3C paths for full-fidelity (trusted input, screenshots) where they work. On macOS it's the only option; on Windows it removes the #542 dependency (the Electrobun-side AdditionalBrowserArguments fix in #542 stays the near-term full-fidelity Windows path); on Linux it's a simplification. Per-OS defaults to be decided in docs.
Scope / acceptance (phased)
Phase 1 — macOS (proves the pattern; the only OS that must have it)
- Bun-side embedded W3C WebDriver server package (execute + result-return over the webview RPC channel)
- Service: macOS-native embedded-driver archetype + attach path; lift the macOS WKWebView
SevereServiceErrorfast-fail for this configuration - Fixture: a macOS native (non-CEF) Electrobun build to drive
- E2E:
execute+ mocking + log capture against macOS-native - README: macOS-native row in the coverage matrix; document the
isTrusted/screenshot caveats
Phase 2 — Windows (→ #542 immunity)
- Windows embedded-driver archetype + fixture + e2e; retire the Windows allow-fail from WebView2 Runtime 150 breaks Windows WebDriver automation (Tauri + Electrobun) #542
- Decide whether embedded becomes the Windows default given WebView2 Runtime 150 breaks Windows WebDriver automation (Tauri + Electrobun) #542
Phase 3 — Linux (→ drop the external driver)
- Linux embedded-driver archetype + fixture + e2e; drop the external
WebKitWebDriverdependency for the in-process path
Cross-cutting
- Per-OS default guidance (embedded vs existing CDP/W3C) in the README coverage matrix
Related
- Electrobun: support non-CEF (native-renderer) apps #317 — Electrobun non-CEF (native-renderer) support (this is its deferred out-of-scope item, broadened).
- WebView2 Runtime 150 breaks Windows WebDriver automation (Tauri + Electrobun) #542 — WebView2 Runtime-150 CDP hardening (Windows immunity is a primary driver here).
- Electrobun: track upstream CEF fixes (Linux/Windows, multiremote, multi-window, deeplink) #320 — CEF-track gaps (multi-window/multiremote/deeplink); the native path sidesteps them on macOS.
- tauri: synthesized keys arrive isTrusted:false on Windows/WebView2 — Escape never closes a modal <dialog> (works on macOS/WKWebView) #612 — trusted-input via in-process CDP on our Tauri/Dioxus embedded drivers (the augmentation model).
Out of scope
- CEF-track fixes (Electrobun: track upstream CEF fixes (Linux/Windows, multiremote, multi-window, deeplink) #320 / upstream macOS CEF persistent partitions using custom request-context cache paths for cookies blackboardsh/electrobun#380, perf(tauri-service): batch updateAllMocks into a single scheduler (#429) #465).
- The macOS CEF path stays available as the full-fidelity option; the embedded driver is the lighter, caveat-bound native alternative.
Status
Not upstream-blocked (mechanism is ours). Rides Electrobun's Bun-core RPC, so it carries some coupling to a pre-1.0 upstream (churn risk). Prioritise-if-wanted; macOS (Phase 1) is the highest-value slice.
Activity
[-]Electrobun: macOS native (WKWebView) automation via a self-shipped embedded WebDriver server[/-][+]Electrobun: self-shipped embedded WebDriver server for all OSes (native automation + WebView2 CDP-hardening immunity)[/+]