Skip to content

Keep the Android bridge out of third-party frames (E8); pin abaplint 2.120.75 - #11

Merged
oblomov-dev merged 2 commits into
mainfrom
claude/beautiful-turing-wxr303
Oct 12, 2026
Merged

oblomov-dev merged 2 commits into
mainfrom
claude/beautiful-turing-wxr303

Conversation

@oblomov-dev

Copy link
Copy Markdown
Member

Two commits:

  1. Pin abaplint to 2.120.75 - abap.yml (and the commands in AGENTS.md / CONTRIBUTING.md) ran @abaplint/cli@latest; CONVENTIONS §4 pins one version ecosystem-wide, so the known gap in AGENTS.md is closed. abaplint 2.120.75 against abap2UI5 main: 0 issues.

  2. E8: Android bridge only for frames of the endpoint's origin (maintainer decision from round 5).

    • Before: addJavascriptInterface hands __a2u5Android to every frame; the shell could only check the main frame's URL, so a third-party frame inside an app page (an embedded site) reached scan, push token and biometric confirm.
    • Now the transport is WebViewCompat.addWebMessageListener (new dependency androidx.webkit:webkit:1.12.1, from google(), no account needed; minSdk 26 / targetSdk 35 unchanged). The allowed-origin rule is the configured endpoint's origin (BridgeOrigin.allowedOriginRule, default port dropped as the rule syntax wants), so the WebView injects __a2u5AndroidChannel into frames of that origin only. The listener additionally answers the main frame only (like iOS) and re-checks the origin against the endpoint configured now; anything else rejects with forbidden.
    • A new endpoint origin (manual entry, QR onboarding, managed config) re-registers the channel; it takes effect from the next navigation, which is the endpoint load that follows.
    • Fallback: feature-detected with WebViewFeature.WEB_MESSAGE_LISTENER. Without it the shell keeps the old @JavascriptInterface transport with the main-frame check and logs that it does. The WebView floor (MINIMUM_MAJOR 100) is far above the feature's minimum, so a managed fleet pinned to the floor (E4a) never runs the fallback.
    • Shim (bridge/native-bridge.js + both byte-identical copies): a third transport path. Calls go out as a JSON string {id, method, text?, reason?}, answers come back through the calling frame's reply proxy as {id, result, error}. The contract (window.abap2ui5Native, v1) is unchanged; the channel wins should a page see both Android objects. The shim settles via a closure now instead of looking __a2u5BridgeResolve up on window again.
    • Tests: contract tests run every generic case for the new android-channel transport too, plus channel-specific ones (answers via onmessage, forbidden, foreign messages ignored, throwing channel rejects, channel preferred) - 38/38 locally. New JVM tests: BridgeMessageTest (wire format) and the origin-rule case in BridgeOriginTest (run on CI; no Android SDK in this sandbox).
    • Docs: bridge/README.md (new "Transports" section, frame rule), AGENTS.md, PLAN.md, DISTRIBUTION.md, TESTING.md (foreign-origin and foreign-frame checks), NEXT_STEPS.md (E8 moved to Recently completed).

Not tested on a device - CI proves the APK builds and the contract holds; TESTING.md §1 has the frame check for the next device run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Te3BRpRpxNhZAYnrQL6Gdt


Generated by Claude Code

The abap workflow ran @abaplint/cli@latest, so a new abaplint release could
turn the weekly run red without any change here. CONVENTIONS §4 pins one
version everywhere; AGENTS.md no longer lists this as a known gap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Te3BRpRpxNhZAYnrQL6Gdt
addJavascriptInterface hands __a2u5Android to every frame, so a frame of
another origin inside an app page (an embedded site) reached the bridge
transport; the shell could only check the main frame's URL. The transport
is now the message channel of androidx.webkit
(WebViewCompat.addWebMessageListener) with the endpoint's origin as the
only allowed-origin rule: the WebView injects __a2u5AndroidChannel into
frames of that origin only, and the listener answers the main frame only,
like iOS. A new endpoint origin re-registers the channel.

A WebView without WEB_MESSAGE_LISTENER keeps the @JavascriptInterface
transport with the main-frame check as before, and logs that it does.

The shim speaks both Android transports (contract tests for the channel),
BridgeMessage is the channel's JSON wire format (JVM-tested), and the
bridge contract, AGENTS.md, PLAN.md, DISTRIBUTION.md, TESTING.md and
NEXT_STEPS.md describe the new transport. Not yet tested on a device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Te3BRpRpxNhZAYnrQL6Gdt
@oblomov-dev
oblomov-dev merged commit ef7fb3e into main Oct 12, 2026
7 checks passed
@oblomov-dev
oblomov-dev deleted the claude/beautiful-turing-wxr303 branch October 12, 2026 09:51
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