injectedJavaScriptForMainFrameOnly={false} is ignored on Android. No way to inject into (cross-origin) iframes.
Bug description:
On Android, injectedJavaScriptForMainFrameOnly={false} and injectedJavaScriptBeforeContentLoadedForMainFrameOnly={false} have no effect: the injected script always runs in the main frame only, and there is no supported way to reach a (cross-origin) . The props are accepted by the API and stored on the native view, but the Android implementation never reads them. So this is a silent no-op, not a documented "iOS/macOS-only" feature.
This blocks any page that keeps logic inside a cross-origin iframe (e.g. embedded payment/bank flows) where a JS bridge must be present inside that iframe.
Current behaviour:
injectedJavaScript/injectedJavaScriptBeforeContentLoadedare delivered viaWebView.evaluateJavascript(...)(RNCWebView.evaluateJavascriptWithFallback, called at fromonPageFinished/onPageStarted).evaluateJavascriptis inherently main-frame-only.The
*ForMainFrameOnlybooleans are only written by the ViewManager setters and are never read anywhere in the Android sources. Setting the prop therefore changes nothing.The Reference docs note that the all-frames behaviour is iOS/macOS only, but the props remain exposed and silently accepted on Android, which is misleading.
All-frames delivery is already used on Android by this library:
window.ReactNativeWebViewreaches every frame because it is registered viaWebViewCompat.addWebMessageListener(webView, "ReactNativeWebView", Set.of("*"), …). "*" origin rule matches all frames, main and sub.injectedJavaScriptObjectis likewise exposed to all frames through that same message-listener channel.
To Reproduce:
The repository's own injection example is the cleanest reproduction: example/examples/Injection.tsx. It already sets both injectedJavaScriptForMainFrameOnly={false} and injectedJavaScriptBeforeContentLoadedForMainFrameOnly={false}, loads a page containing three iframes (one cross-origin), and its injected scripts branch on window.self === window.top to apply per-iframe effects — i.e. it is explicitly written to demonstrate all-frames injection.
- Run the Injection example on iOS -> the per-iframe effects (the beforeContentLoaded/afterContentLoaded styling applied inside each frame) appear in the iframes.
- Run the same example on Android -> the per-iframe effects do not appear inside the iframes; only the main frame is affected, because the injected scripts never run in the subframes (and the *ForMainFrameOnly={false} props are ignored).
Or minimal variant:
- On Android, load a page in a that embeds a cross-origin .
- Set
injectedJavaScriptBeforeContentLoadedForMainFrameOnly={false}and inject a script that setswindow.__marker = 'hit'. - From inside the iframe, evaluate
window.__marker. It will be undefined; the script never ran there. For contrast, from the same iframe, window.ReactNativeWebView is defined.
Expected behavior:
Injection is applied to all iframes.
Screenshots/Videos:
Environment:
- OS: Android
- OS version: All
- react-native version: 0.85.3
- react-native-webview version: 13.16.1 (the same behaviour is in current master as well)
Source: react-native-webview/react-native-webview