Skip to content

feat(android): allow scoping WebView bridge origin policy - #8701

Open
deggertsen wants to merge 1 commit into
ionic-team:mainfrom
deggertsen:feat/android-scoped-web-message-policy
Open

deggertsen wants to merge 1 commit into
ionic-team:mainfrom
deggertsen:feat/android-scoped-web-message-policy

Conversation

@deggertsen

Copy link
Copy Markdown

What

Apps using server.url often list additional hosts in server.allowNavigation (such as OAuth providers or marketing pages) so top-level flows stay inside the WebView instead of opening the system browser.

Today on Android, Bridge.setAllowedOriginRules() feeds every server.allowNavigation entry into MessageHandler's WebViewCompat.addWebMessageListener(...) registration, and MessageHandler falls back to webView.addJavascriptInterface(this, "androidBridge") if WEB_MESSAGE_LISTENER is unavailable or registration fails. CapacitorCookies.load() also unconditionally attaches CapacitorCookiesAndroidInterface via addJavascriptInterface, which has no caller-origin or frame check.

This adds an opt-in Bridge.Builder.setWebMessagePolicy(...) hook (MessageHandler.WebMessagePolicy) so Android host apps can scope native bridge access to a narrower set of trusted origins than server.allowNavigation without changing default behavior for existing apps:

  • Allows BridgeActivity / Bridge.Builder callers to supply a MessageHandler.WebMessagePolicy with explicit WebMessageListener originRules and a runtime sourceOrigin predicate (acceptsOrigin).
  • Updates javaScriptReplyProxy before dispatching accepted main-frame messages.
  • Fails closed when scopedWebMessages is configured: skips registering addJavascriptInterface(this, "androidBridge") and skips evaluateJavascript legacy responses when WEB_MESSAGE_LISTENER is unavailable or listener registration fails.
  • Skips registering CapacitorCookiesAndroidInterface in CapacitorCookies.load() when bridge.hasScopedWebMessages() is enabled (native-bridge.ts already guards typeof win.CapacitorCookiesAndroidInterface !== 'undefined').

Verification

  • Added unit tests in MessageHandlerTest and CapacitorCookiesTest covering trusted main-frame dispatch, subframe/untrusted/null-origin rejection, fail-closed handling when WEB_MESSAGE_LISTENER is unsupported or throws, empty origin rules, and CapacitorCookiesAndroidInterface registration gating.
  • Ran npm run eslint and npm run prettier -- --check (0 errors).
  • Ran npm run verify -w android (./gradlew clean lint build test -b capacitor/build.gradle on JDK 21): Android Lint found no new issues, and both testDebugUnitTest and testReleaseUnitTest pass.

This branch has not been deployed

No deployments
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.

1 participant