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:
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
executeJavascript and 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:
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)
Phase 2 — Windows (→ #542 immunity)
Phase 3 — Linux (→ drop the external driver)
Cross-cutting
Related
Out of scope
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.
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:
msedgedriver/--remote-debugging-port, so the WebView2 Runtime-150 elevated-host hardening that breaks the CDP-attach path is simply not in the loop.Model already shipped for other surface-less webviews:
tauri-plugin-wdio-webdriver(packages/tauri-plugin-webdriver) andwdio-dioxus-embedded-driver. Not upstream-blocked — the mechanism is entirely ours.Why an embedded driver, per OS
0.1.0), but broken by Runtime-150 elevated-host hardening (#542)WebKitWebDriverattach (W3C)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_inspectorselector used toshow/closethe local Web Inspector GUI (the code notes "WKWebView doesn't have public DevTools API"); the publicinspectableproperty isn't set; there is no CDP, no W3C WebDriver, nosafaridriverattach for embedded webviews, and noWKAutomation/automationSessionglue. Unlike WebKitGTK — which exposeswebkit_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
executeJavascriptand returns results over the existing webview → Bun RPC channel.executeJavascript/RPC abstracts the underlying engine, one Bun-side implementation covers all three OSes (contrast: the Tauri embedded driver carries per-OS native code).Caveats (all OSes — inherent to JS-synthesised automation)
Already seen on our other embedded drivers; document them, don't treat as blockers:
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.Optional trusted-input augmentation (follow-up): regain trusted input per OS via native input synthesis — on Windows, WebView2's in-process
CallDevToolsProtocolMethodAPI (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
AdditionalBrowserArgumentsfix 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)
SevereServiceErrorfast-fail for this configurationexecute+ mocking + log capture against macOS-nativeisTrusted/screenshot caveatsPhase 2 — Windows (→ #542 immunity)
Phase 3 — Linux (→ drop the external driver)
WebKitWebDriverdependency for the in-process pathCross-cutting
Related
Out of scope
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.