2020-03-17 21:01:20 +00:00
import React , { Component } from 'react' ;
import { Text , View , ScrollView } from 'react-native' ;
import WebView from 'react-native-webview' ;
2020-06-13 20:54:48 +00:00
const HTML = `
< ! DOCTYPE html >
< html >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< title > iframe test < / title >
< / head >
< body >
< p style = "" > beforeContentLoaded on the top frame < span id = "before_failed" style = "display: inline-block;" > failed < / span > < span id = "before_succeeded" style = "display: none;" > succeeded < / span > ! < / p >
< p style = "" > afterContentLoaded on the top frame < span id = "after_failed" style = "display: inline-block;" > failed < / span > < span id = "after_succeeded" style = "display: none;" > succeeded < / span > ! < / p >
< iframe src = "https://birchlabs.co.uk/linguabrowse/infopages/obsol/iframe.html?v=1" name = "iframe_0" style = "width: 100%; height: 25px;" > < / iframe >
< iframe src = "https://birchlabs.co.uk/linguabrowse/infopages/obsol/iframe2.html?v=1" name = "iframe_1" style = "width: 100%; height: 25px;" > < / iframe >
< iframe src = "https://www.ebay.co.uk" name = "iframe_2" style = "width: 100%; height: 25px;" > < / iframe >
< / body >
< / html >
` ;
2020-03-17 21:01:20 +00:00
type Props = { } ;
type State = {
backgroundColor : string ,
} ;
export default class Injection extends Component < Props , State > {
state = {
backgroundColor : '#FF00FF00'
} ;
render() {
return (
< ScrollView >
< View style = { { } } >
2020-06-13 20:54:48 +00:00
< View style = { { height : 400 } } >
2020-03-17 21:01:20 +00:00
< WebView
/ * *
2020-06-13 20:54:48 +00:00
* This HTML is a copy of the hosted multi - frame JS injection test .
* I have found that Android doesn ' t support beforeContentLoaded for a hosted HTML webpage , yet does for a static source .
* The cause of this is unresolved .
2020-03-17 21:01:20 +00:00
* /
// source={{ html: HTML }}
source = { { uri : "https://birchlabs.co.uk/linguabrowse/infopages/obsol/rnw_iframe_test.html" } }
automaticallyAdjustContentInsets = { false }
style = { { backgroundColor : '#00000000' } }
/ * M u s t b e p o p u l a t e d i n o r d e r f o r ` m e s s a g i n g E n a b l e d ` t o b e ` t r u e ` t o a c t i v a t e t h e
* JS injection user scripts , consistent with current behaviour . This is undesirable ,
* so needs addressing in a follow - up PR . * /
onMessage = { ( ) = > { } }
2020-06-13 20:54:48 +00:00
injectedJavaScriptBeforeContentLoadedForMainFrameOnly = { false }
injectedJavaScriptForMainFrameOnly = { false }
2020-03-17 21:01:20 +00:00
/* We set this property in each frame */
injectedJavaScriptBeforeContentLoaded = { `
2020-06-13 20:54:48 +00:00
console . log ( "executing injectedJavaScriptBeforeContentLoaded... " + ( new Date ( ) ) . toString ( ) ) ;
2020-03-17 21:01:20 +00:00
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 = { `
2020-06-13 20:54:48 +00:00
console . log ( "executing injectedJavaScript... " + ( new Date ( ) ) . toString ( ) ) ;
2020-03-17 21:01:20 +00:00
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' ) ;
2020-06-13 20:54:48 +00:00
namedFramesAtBeforeContentLoadedEle . textContent = "Names of iframes that called beforeContentLoaded: " + JSON . stringify ( window . top . injectedIframesBeforeContentLoaded || [ ] ) ;
2020-03-17 21:01:20 +00:00
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 ) ;
}
` }
/ >
< / View >
< / View >
< Text > This test presents three iframes : iframe_0 ( yellow ) ; iframe_1 ( pink ) ; and iframe_2 ( transparent , because its 'X-Frame-Options' is set to 'SAMEORIGIN' ) . < / Text >
< Text > Before injection , the main frame 's background is the browser' s default value ( transparent or white ) and each frame has its natural colour . < / Text >
{ /*<Text>1a) At injection time "beforeContentLoaded", a variable will be set in each frame to set 'orange' as the "colour to be used".</Text>*/ }
{ /*<Text>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.</Text>*/ }
{ /*<Text>2a) At injection time "afterContentLoaded", that variable will be read – if present, the colour orange will be injected into all frames. Otherwise, cyan.</Text>*/ }
{ /*<Text>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.</Text>*/ }
< Text > ✅ If the main frame becomes orange , then top - frame injection both beforeContentLoaded and afterContentLoaded is supported . < / Text >
< Text > ✅ If iframe_0 , and iframe_1 become orange , then multi - frame injection beforeContentLoaded and afterContentLoaded is supported . < / Text >
< Text > ✅ 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 . < / Text >
2020-06-13 20:54:48 +00:00
< Text > ❌ 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 . < / Text >
< Text > ❌ If "Names of iframes that called beforeContentLoaded: " is [ ] , then see above . < / Text >
2020-03-17 21:01:20 +00:00
< Text > ❌ If "Names of iframes that called afterContentLoaded: " is [ ] , then afterContentLoaded is not supported in iframes . < / Text >
< Text > ❌ If the main frame becomes coloured cyan , then JS injection succeeded after the content loaded , but didn ' t occur before the content loaded . < / Text >
< Text > ❌ If the text "beforeContentLoaded on the top frame failed" remains unchanged , then JS injection has failed on the main frame before the content loaded . < / Text >
< Text > ❌ If the text "afterContentLoaded on the top frame failed" remains unchanged , then JS injection has failed on the main frame after the content loaded . < / Text >
< Text > ❌ If the iframes remain their original colours ( yellow and pink ) , then multi - frame injection is not supported at all . < / Text >
< / ScrollView >
) ;
}
}