Custom URL schemes on macOS, Linux and Windows (story 8, Canvases 30–32) - #59
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
Applications can register a scheme (e.g. demo://) before the first
WebView and answer every request to it in Java, with no local server.
- WebViewSchemes: static registry with name rules, reserved web schemes,
the freeze at the first engine, and an isSupported() capability probe.
- WebViewSchemeRequest/Response/Handler/Responder: the handler contract.
- SchemeDispatcher: runs handlers on webview-scheme-N daemon threads and
answers each request exactly once (500 on throw, 504 after 30 s, 404
unknown scheme, 413 over 16 MB, 500 over 64 MB); drops Content-Length,
defaults Content-Type, sets CORS to the request's own origin.
- macOS: a WKURLSchemeHandler installed on each engine's configuration;
responses applied on the main queue, never after a stop.
- Linux and Windows: stub exports (isSupported() is false) until
Canvases 31 and 32.
- EmbeddedWebView/OffscreenWebView freeze the registry before native create.
- Tests: WebViewSchemesTest, SchemeDispatcherTest, WebViewSchemeResponseTest.
- Demo WebViewSchemeDemo with run-{mac,linux}-scheme-demo.sh and
run-windows-scheme-demo.bat; README "Custom URL schemes" section.
- Canvas 30 O5.1 amended to name the Installer test seam.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
WebViewSchemes.isSupported() and register() are meant to be called at start-up, before any window. Their probe loaded WebViewNative, which loads libjawt; on macOS under JDK 8 that pulls in libawt_lwawt, whose JNI_OnLoad segfaults when the AWT toolkit has not started. The demo hit this in main(). The default probe now answers false when headless without loading the native library, and otherwise calls Toolkit.getDefaultToolkit() before touching WebViewNative. Canvas 30 D4, O5.2 and Safeguard 6 amended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
Registers each scheme once on WebKitGTK's default web context (secure, CORS-enabled) before the first view, answers requests through Canvas 30's dispatcher, and applies responses on the GTK pump thread. Adds an optional-symbol list to the Linux loader so request bodies (2.40) and response status/headers (2.36) are used where present without failing the load on older engines. Adds an automatic mode to the scheme demo so the engine can be checked under Xvfb. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
- Register each scheme once on WebKitGTK's default web context, as secure and CORS-enabled, on the pump thread before the first view; every view, popup and adopted popup shares that context. Both lightweight and heavyweight modes are covered. - Requests are held (ref'd) by id and handed to Canvas 30's dispatcher; answers are applied on the pump thread only if still pending. - The Linux loader gains an optional-symbol list (WK_WEBKIT_OPT_SYMS, WK_HAS): request method (2.12), headers and the response object with status/headers (2.36, plus libsoup via the WebKit handle) and request bodies (2.40) are used where present and never fail the load. - webview_scheme_available() is true on GTK. - Demo: SCHEMEDEMO_AUTO=1 runs 8 page-observable checks and exits 0/1/2; the report travels as a GET so it works on every engine. - READMEs: Linux coverage and limitations of older WebKitGTK. - Canvas 31 D10 amended: same-origin 404 check instead of a cross-host fetch (blocked by CORS by design), and the report sent as a GET. Verified under Xvfb on WebKitGTK 2.52: all checks pass in lightweight and heavyweight modes; a build with the optional gates forced off loads, serves pages and degrades as documented without crashing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
Declares the registered schemes on the WebView2 environment (secure, with an authority, accepting requests from their own scheme) through the SDK's own WRL options helper, only when something is registered; hooks WebResourceRequested on the engine's webview and every popup child, ignoring other schemes; answers through a deferral completed on the engine thread with CreateWebResourceResponse. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
- Declare registered schemes on the WebView2 environment through the SDK's own WRL helpers (CoreWebView2EnvironmentOptions and CoreWebView2CustomSchemeRegistration): secure, with an authority, accepting requests from pages on the same scheme. Null options, as before, when nothing is registered. - Filter and hook WebResourceRequested on the engine's webview and on every popup child (both dispositions); adoption keeps the child's hook. The handler ignores requests of unregistered schemes. - Each request is held by a deferral and handed to Canvas 30's dispatcher on a detached thread; the answer is built with CreateWebResourceResponse and completed on the engine thread, once. - webview_scheme_available() is true on Windows. - READMEs and the Windows run script: Windows coverage and notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
javac on Windows reads sources as Cp1252 by default, which cannot map the closing curly quote (0x9D byte) in WebViewSchemes' refusal messages. - WebViewSchemes: spell the three messages' quotes and dash as \u escapes; the strings are identical (tests assert them verbatim). - run-windows-scheme-demo.bat: pass -encoding UTF-8 to both javac calls. - /spdd-sync: Canvas 30 Norm 7 (source encoding) and O11 note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V
shannah
marked this pull request as ready for review
September 26, 2026 15:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lets an application register its own URL scheme, such as
aaf, before the first WebView exists. Every request toaaf://…is then answered by a Java handler, with no local HTTP server, port or token.Built with SPDD:
requirements/[User-story-8]serve-pages-from-a-custom-url-scheme.md;spdd/analysis/GGQPA-XXX-202609261430-[Analysis]-serve-pages-from-a-custom-url-scheme.md;Java API (Canvas 30)
WebViewSchemes—register(scheme, handler),isSupported()andregisteredSchemes().+,-or..libawt_lwawt.\uescapes, so the source compiles under javac's Cp1252 default on Windows.WebViewSchemeRequest,WebViewSchemeResponse,WebViewSchemeHandlerandWebViewSchemeResponder.SchemeDispatcher:webview-scheme-Ndaemon threads;Content-Length, adds a defaultContent-Type, and setsAccess-Control-Allow-Originto the request's own origin.Native
WKURLSchemeHandleris installed on each engine's configuration, and popups inherit it.WebResourceRequestedfilter and handler go on the engine's webview and on every popup child;CreateWebResourceResponse.Tests and verification
WebViewSchemesTest,SchemeDispatcherTestandWebViewSchemeResponseTest. The full suite passes: 236 tests, 0 failures.SCHEMEDEMO_AUTO=1. It runs 8 checks the page can observe and exits 0 only if all pass.Motivation: the Agentic App Framework will serve its local-database browser at
aaf://db/(webliteca/agentic-app-framework#378).🤖 Generated with Claude Code
https://claude.ai/code/session_01EvuvnSZ2qxgNJkF4T5eD6V