import React, {Component} from 'react'; import {Text, View, ScrollView} from 'react-native'; import WebView from 'react-native-webview'; const HTML = ` iframe test

beforeContentLoaded on the top frame failed!

afterContentLoaded on the top frame failed!

`; type Props = {}; type State = { backgroundColor: string, }; export default class Injection extends Component { state = { backgroundColor: '#FF00FF00' }; render() { return ( {}} injectedJavaScriptBeforeContentLoadedForMainFrameOnly={false} injectedJavaScriptForMainFrameOnly={false} /* We set this property in each frame */ injectedJavaScriptBeforeContentLoaded={` console.log("executing injectedJavaScriptBeforeContentLoaded... " + (new Date()).toString()); if(typeof window.top.injectedIframesBeforeContentLoaded === "undefined"){ window.top.injectedIframesBeforeContentLoaded = []; } window.self.colourToUse = "orange"; if(window.self === window.top){ console.log("Was window.top. window.frames.length is:", window.frames.length); window.self.numberOfFramesAtBeforeContentLoaded = window.frames.length; function declareSuccessOfBeforeContentLoaded(head){ var style = window.self.document.createElement('style'); style.type = 'text/css'; style.innerHTML = "#before_failed { display: none !important; }#before_succeeded { display: inline-block !important; }"; head.appendChild(style); } const head = (window.self.document.head || window.self.document.getElementsByTagName('head')[0]); if(head){ declareSuccessOfBeforeContentLoaded(head); } else { window.self.document.addEventListener("DOMContentLoaded", function (event) { const head = (window.self.document.head || window.self.document.getElementsByTagName('head')[0]); declareSuccessOfBeforeContentLoaded(head); }); } } else { window.top.injectedIframesBeforeContentLoaded.push(window.self.name); console.log("wasn't window.top."); console.log("wasn't window.top. Still going..."); } `} /* We read the colourToUse property in each frame to recolour each frame */ injectedJavaScript={` console.log("executing injectedJavaScript... " + (new Date()).toString()); if(typeof window.top.injectedIframesAfterContentLoaded === "undefined"){ window.top.injectedIframesAfterContentLoaded = []; } if(window.self.colourToUse){ window.self.document.body.style.backgroundColor = window.self.colourToUse; } else { window.self.document.body.style.backgroundColor = "cyan"; } if(window.self === window.top){ function declareSuccessOfAfterContentLoaded(head){ var style = window.self.document.createElement('style'); style.type = 'text/css'; style.innerHTML = "#after_failed { display: none !important; }#after_succeeded { display: inline-block !important; }"; head.appendChild(style); } declareSuccessOfAfterContentLoaded(window.self.document.head || window.self.document.getElementsByTagName('head')[0]); // var numberOfFramesAtBeforeContentLoadedEle = document.createElement('p'); // numberOfFramesAtBeforeContentLoadedEle.textContent = "Number of iframes upon the main frame's beforeContentLoaded: " + // window.self.numberOfFramesAtBeforeContentLoaded; // var numberOfFramesAtAfterContentLoadedEle = document.createElement('p'); // numberOfFramesAtAfterContentLoadedEle.textContent = "Number of iframes upon the main frame's afterContentLoaded: " + window.frames.length; // numberOfFramesAtAfterContentLoadedEle.id = "numberOfFramesAtAfterContentLoadedEle"; var namedFramesAtBeforeContentLoadedEle = document.createElement('p'); namedFramesAtBeforeContentLoadedEle.textContent = "Names of iframes that called beforeContentLoaded: " + JSON.stringify(window.top.injectedIframesBeforeContentLoaded || []); namedFramesAtBeforeContentLoadedEle.id = "namedFramesAtBeforeContentLoadedEle"; var namedFramesAtAfterContentLoadedEle = document.createElement('p'); namedFramesAtAfterContentLoadedEle.textContent = "Names of iframes that called afterContentLoaded: " + JSON.stringify(window.top.injectedIframesAfterContentLoaded); namedFramesAtAfterContentLoadedEle.id = "namedFramesAtAfterContentLoadedEle"; // document.body.appendChild(numberOfFramesAtBeforeContentLoadedEle); // document.body.appendChild(numberOfFramesAtAfterContentLoadedEle); document.body.appendChild(namedFramesAtBeforeContentLoadedEle); document.body.appendChild(namedFramesAtAfterContentLoadedEle); } else { window.top.injectedIframesAfterContentLoaded.push(window.self.name); window.top.document.getElementById('namedFramesAtAfterContentLoadedEle').textContent = "Names of iframes that called afterContentLoaded: " + JSON.stringify(window.top.injectedIframesAfterContentLoaded); } `} /> This test presents three iframes: iframe_0 (yellow); iframe_1 (pink); and iframe_2 (transparent, because its 'X-Frame-Options' is set to 'SAMEORIGIN'). Before injection, the main frame's background is the browser's default value (transparent or white) and each frame has its natural colour. {/*1a) At injection time "beforeContentLoaded", a variable will be set in each frame to set 'orange' as the "colour to be used".*/} {/*1b) Also upon "beforeContentLoaded", a style element to change the text "beforeContentLoaded failed" -> "beforeContentLoaded succeeded" will be applied as soon as the head has loaded.*/} {/*2a) At injection time "afterContentLoaded", that variable will be read – if present, the colour orange will be injected into all frames. Otherwise, cyan.*/} {/*2b) Also upon "afterContentLoaded", a style element to change the text "afterContentLoaded failed" -> "afterContentLoaded succeeded" will be applied as soon as the head has loaded.*/} ✅ If the main frame becomes orange, then top-frame injection both beforeContentLoaded and afterContentLoaded is supported. ✅ If iframe_0, and iframe_1 become orange, then multi-frame injection beforeContentLoaded and afterContentLoaded is supported. ✅ If the two texts say "beforeContentLoaded on the top frame succeeded!" and "afterContentLoaded on the top frame succeeded!", then both injection times are supported at least on the main frame. ❌ If either of the two iframes become coloured cyan, then for that given frame, JS injection succeeded after the content loaded, but didn't occur before the content loaded. ❌ If "Names of iframes that called beforeContentLoaded: " is [], then see above. ❌ If "Names of iframes that called afterContentLoaded: " is [], then afterContentLoaded is not supported in iframes. ❌ If the main frame becomes coloured cyan, then JS injection succeeded after the content loaded, but didn't occur before the content loaded. ❌ If the text "beforeContentLoaded on the top frame failed" remains unchanged, then JS injection has failed on the main frame before the content loaded. ❌ If the text "afterContentLoaded on the top frame failed" remains unchanged, then JS injection has failed on the main frame after the content loaded. ❌ If the iframes remain their original colours (yellow and pink), then multi-frame injection is not supported at all. ); } }