Skip to content

Decide where a page may navigate (story 10, Canvas 34) - #62

Merged
shannah merged 1 commit into
masterfrom
navigation-decisions
Oct 1, 2026
Merged

shannah merged 1 commit into
masterfrom
navigation-decisions

Conversation

@shannah

@shannah shannah commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

What

WebViewComponent.setNavigationHandler lets an application refuse a page's navigation before any request is sent. A content security policy confines what a page loads, but not where it goes: a link, location.href = …, a form posted to _top or a meta refresh sends whatever the page puts in the address. This closes that channel, which the Agentic App Framework needs before agents may hand data to user-built "creations".

  • The handler is asked about every navigation of the view and its frames: links (including download links), location.*, forms, meta refreshes, back/forward, reload and server redirects. New windows stay with the popup handler.
  • Frames are decided too, everywhere. A spike on WebKitGTK showed frame navigations arrive exactly like the view's own, with nothing to tell them apart. So the one portable choice is to decide both, which is also the safer one.
  • The event carries url(), currentUrl(), cause() (LINK, FORM, BACK_FORWARD, RELOAD, REDIRECT or OTHER) and applicationInitiated(). That last one is true for the application's own setUrl, and for a server redirect of one it allowed, so an address bar still works.
  • Failure and defaults:
    • a throwing handler refuses;
    • with no handler, nothing changes;
    • isNavigationHandlerSupported() is false against an older native.
  • Native:
    • Linux: WebKitGTK decide-policy on OffEngine, Engine and adopted popups. The four new symbols go through the runtime loader, so there is no new link dependency.
    • macOS: decidePolicyForNavigationAction. When it allows, it reproduces WebKit's own default (downloads, mailto: and external schemes).
    • Windows: NavigationStarting and FrameNavigationStarting.
  • Also: CLAUDE.md now says, in bold, that Linux is lightweight only, so agents stop running or debugging heavyweight on Linux.

Story, analysis and Canvas:

  • requirements/[User-story-10]decide-where-a-page-may-navigate.md;
  • spdd/analysis/GGQPA-XXX-202609301715-…;
  • spdd/prompt/34-20260930-1720-[Feat]-Decide-Where-A-Page-May-Navigate.md.

Checks

  • Unit tests: mvn test passes, 257 tests including the 21 new NavigationDispatcherTest cases.
  • Linux, lightweight, under Xvfb: NAVDEMO_AUTO=1 ./run-linux-navigation-demo.sh gives PASS on all 18 checks (AC1–AC10).
    • Every refused navigation reached the handler with the right cause and current URL, and the page stayed put.
    • The local listener received only the two requests it should: the application's own setUrl (AC5), and one after the handler was removed (AC8).
  • macOS and Windows: not run here. This PR's CI compiles both natives, and the WebView2 interfaces used were checked against the pinned SDK 1.0.2592.51. The demo's auto mode (NAVDEMO_AUTO=1 ./run-mac-navigation-demo.sh, run-windows-navigation-demo.bat) runs the same checks there.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JQdakxaBx7mVXvdCcKJdrw


Generated by Claude Code

WebViewComponent.setNavigationHandler asks the application, before any
request is sent, about every navigation of the view and its frames:
links, script navigation, forms, meta refreshes, back/forward, reload and
redirects. A refused navigation never starts. The event carries the
target and current URL, the cause, and whether the application itself
asked for it (setUrl, and redirects of it). A throwing handler refuses;
without a handler nothing changes; isNavigationHandlerSupported() reports
an older native.

Native: WebKitGTK decide-policy (lightweight and heavyweight engines,
adopted popups), WKWebView decidePolicyForNavigationAction (reproducing
WebKit's default when it allows), WebView2 NavigationStarting and
FrameNavigationStarting.

Also records in CLAUDE.md, in bold, that Linux is lightweight only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JQdakxaBx7mVXvdCcKJdrw
@shannah
shannah marked this pull request as ready for review October 1, 2026 22:36
@shannah
shannah merged commit e420426 into master Oct 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants