ReviewOS

craft-native/craft

fix(android): injecting the bridge is not idempotent, and a stale injection callback can mark the wrong page ready

#228
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Two gaps in how CraftBridge.injectBridge marks a page ready, found while fixing #215. Both matter more now that deep links queue until the bridge is ready.

A same-document navigation may inject the bridge again

MainActivity's onPageFinished calls craftBridge.injectBridge() for every trusted URL, with no check that this document already has the bridge. Chromium's WebView is known to call onPageFinished, without a matching onPageStarted, for same-document navigations such as fragment changes and history.pushState. This is not yet reproduced here.

If it happens, the whole page script runs again in the same document:

  • window.craft is replaced;
  • craftReady fires a second time;
  • every in-flight promise is rejected with "Android bridge reinitialized".

#215 makes the deep-link replay survive this, because its state lives on window. Nothing else does.

Suggested:

  1. Verify on an emulator with a pushState navigation.
  2. Then skip re-injection when the document already has the bridge, for example with a marker injectBridge checks, or make each installer idempotent.

A stale injection callback can mark the wrong page ready

bridgeReady = true is set in the evaluateJavascript(script) completion callback. onPageStarted resets it with markBridgeLoading(). If that callback runs after the next navigation's onPageStarted, it marks a page that has not been injected as ready. Queued shortcut events, and since #215 queued deep links, are then flushed into a document with no bridge and no replay listener, and lost.

Suggested: a navigation generation that markBridgeLoading increments and the completion callback compares before setting bridgeReady.

Sign in to comment on this issue.