react-native-webview.git

Injection.tsx 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import React, {Component} from 'react';
  2. import {Text, View, ScrollView} from 'react-native';
  3. import WebView from 'react-native-webview';
  4. const HTML = `
  5. <!DOCTYPE html>
  6. <html>
  7. <head>
  8. <meta charset="utf-8">
  9. <meta name="viewport" content="width=device-width, initial-scale=1">
  10. <title>iframe test</title>
  11. </head>
  12. <body>
  13. <p style="">beforeContentLoaded <span id="before_failed" style="display: inline-block;">failed</span><span id="before_succeeded" style="display: none;">succeeded</span>!</p>
  14. <p style="">afterContentLoaded <span id="after_failed" style="display: inline-block;">failed</span><span id="after_succeeded" style="display: none;">succeeded</span>!</p>
  15. <iframe src="https://birchlabs.co.uk/linguabrowse/infopages/obsol/iframe.html?v=1" name="iframe_0" style="width: 100%; height: 25px;"></iframe>
  16. <iframe src="https://birchlabs.co.uk/linguabrowse/infopages/obsol/iframe2.html?v=1" name="iframe_1" style="width: 100%; height: 25px;"></iframe>
  17. <iframe src="https://www.ebay.co.uk" name="iframe_2" style="width: 100%; height: 25px;"></iframe>
  18. </body>
  19. </html>
  20. `;
  21. type Props = {};
  22. type State = {
  23. backgroundColor: string,
  24. };
  25. export default class Injection extends Component<Props, State> {
  26. state = {
  27. backgroundColor: '#FF00FF00'
  28. };
  29. render() {
  30. return (
  31. <ScrollView>
  32. <View style={{ }}>
  33. <View style={{ height: 200 }}>
  34. <WebView
  35. /**
  36. * This HTML is a copy of a multi-frame JS injection test that I had lying around.
  37. * @see https://birchlabs.co.uk/linguabrowse/infopages/obsol/iframeTest.html
  38. */
  39. source={{ html: HTML }}
  40. automaticallyAdjustContentInsets={false}
  41. style={{backgroundColor:'#00000000'}}
  42. /* Must be populated in order for `messagingEnabled` to be `true` to activate the
  43. * JS injection user scripts, consistent with current behaviour. This is undesirable,
  44. * so needs addressing in a follow-up PR. */
  45. onMessage={() => {}}
  46. /* We set this property in each frame */
  47. injectedJavaScriptBeforeContentLoaded={`
  48. window.self.colourToUse = "green";
  49. function declareSuccessBeforeContentLoaded(head){
  50. var style = window.self.document.createElement('style');
  51. style.type = 'text/css';
  52. style.innerHTML = "#before_failed { display: none !important; }#before_succeeded { display: inline-block !important; }";
  53. head.appendChild(style);
  54. }
  55. const head = (window.self.document.head || window.self.document.getElementsByTagName('head')[0]);
  56. if(head){
  57. declareSuccessBeforeContentLoaded(head);
  58. } else {
  59. window.self.document.addEventListener("DOMContentLoaded", function (event) {
  60. const head = (window.self.document.head || window.self.document.getElementsByTagName('head')[0]);
  61. declareSuccessBeforeContentLoaded(head);
  62. });
  63. }
  64. `}
  65. injectedJavaScriptForMainFrameOnly={false}
  66. /* We read the colourToUse property in each frame to recolour each frame */
  67. injectedJavaScript={`
  68. function declareSuccessAfterContentLoaded(head){
  69. var style = window.self.document.createElement('style');
  70. style.type = 'text/css';
  71. style.innerHTML = "#after_failed { display: none !important; }#after_succeeded { display: inline-block !important; }";
  72. head.appendChild(style);
  73. }
  74. declareSuccessAfterContentLoaded(window.self.document.head || window.self.document.getElementsByTagName('head')[0]);
  75. if(window.self.colourToUse){
  76. window.self.document.body.style.backgroundColor = window.self.colourToUse;
  77. } else {
  78. window.self.document.body.style.backgroundColor = "cyan";
  79. }
  80. `}
  81. />
  82. </View>
  83. </View>
  84. <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>
  85. <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>
  86. <Text>1a) At injection time "beforeContentLoaded", a variable will be set in each frame to set 'green' as the "colour to be used".</Text>
  87. <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>
  88. <Text>2a) At injection time "afterContentLoaded", that variable will be read – if present, the colour green will be injected into all frames. Otherwise, cyan.</Text>
  89. <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>
  90. <Text>✅ If the main frame, iframe_0, and iframe_1 all become green or cyan, then multi-frame injection is supported.</Text>
  91. <Text>✅ If the two texts say "beforeContentLoaded succeeded!" and "afterContentLoaded succeeded!", then both injection times are supported.</Text>
  92. <Text>❌ If the text "beforeContentLoaded failed" remains unchanged, then JS injection has failed on the main frame before the content loaded.</Text>
  93. <Text>❌ If the text "afterContentLoaded failed" remains unchanged, then JS injection has failed on the main frame after the content loaded.</Text>
  94. <Text>❌ If any frames become coloured cyan, then JS injection has failed before the content loaded (but succeeded after the content loaded).</Text>
  95. <Text>❌ If only the main frame changes colour (to green or cyan), then multi-frame injection is not supported.</Text>
  96. </ScrollView>
  97. );
  98. }
  99. }