Browse Source

feat(iOS): user scripts can be updated on prop change

Jamie Birch 4 years ago
parent
commit
ec0ed516b9
6 changed files with 222 additions and 107 deletions
  1. 27
    1
      docs/Reference.md
  2. 2
    0
      ios/RNCWebView.h
  3. 169
    106
      ios/RNCWebView.m
  4. 2
    0
      ios/RNCWebViewManager.m
  5. 6
    0
      src/WebView.ios.tsx
  6. 16
    0
      src/WebViewTypes.ts

+ 27
- 1
docs/Reference.md View File

@@ -7,7 +7,9 @@ This document lays out the current public properties and methods for the React N
7 7
 - [`source`](Reference.md#source)
8 8
 - [`automaticallyAdjustContentInsets`](Reference.md#automaticallyadjustcontentinsets)
9 9
 - [`injectedJavaScript`](Reference.md#injectedjavascript)
10
-- [`injectedJavaScriptBeforeContentLoaded`](Reference.md#injectedJavaScriptBeforeContentLoaded)
10
+- [`injectedJavaScriptBeforeContentLoaded`](Reference.md#injectedjavascriptbeforecontentloaded)
11
+- [`injectedJavaScriptForMainFrameOnly`](Reference.md#injectedjavascriptformainframeonly)
12
+- [`injectedJavaScriptBeforeContentLoadedForMainFrameOnly`](Reference.md#injectedjavascriptbeforecontentloadedformainframeonly)
11 13
 - [`mediaPlaybackRequiresUserAction`](Reference.md#mediaplaybackrequiresuseraction)
12 14
 - [`nativeConfig`](Reference.md#nativeconfig)
13 15
 - [`onError`](Reference.md#onerror)
@@ -174,6 +176,30 @@ const INJECTED_JAVASCRIPT = `(function() {
174 176
 
175 177
 ---
176 178
 
179
+### `injectedJavaScriptForMainFrameOnly`
180
+
181
+If `true` (default), loads the `injectedJavaScript` only into the main frame.
182
+
183
+If `false`, loads it into all frames (e.g. iframes).
184
+
185
+| Type   | Required | Platform |
186
+| ------ | -------- | -------- |
187
+| bool | No       | iOS       |
188
+
189
+---
190
+
191
+### `injectedJavaScriptBeforeContentLoadedForMainFrameOnly`
192
+
193
+If `true` (default), loads the `injectedJavaScriptBeforeContentLoaded` only into the main frame.
194
+
195
+If `false`, loads it into all frames (e.g. iframes).
196
+
197
+| Type   | Required | Platform |
198
+| ------ | -------- | -------- |
199
+| bool | No       | iOS       |
200
+
201
+---
202
+
177 203
 ### `mediaPlaybackRequiresUserAction`
178 204
 
179 205
 Boolean that determines whether HTML5 audio and video requires the user to tap them before they start playing. The default value is `true`. (Android API minimum version 17).

+ 2
- 0
ios/RNCWebView.h View File

@@ -31,6 +31,8 @@
31 31
 @property (nonatomic, assign) BOOL messagingEnabled;
32 32
 @property (nonatomic, copy) NSString * _Nullable injectedJavaScript;
33 33
 @property (nonatomic, copy) NSString * _Nullable injectedJavaScriptBeforeContentLoaded;
34
+@property (nonatomic, assign) BOOL injectedJavaScriptForMainFrameOnly;
35
+@property (nonatomic, assign) BOOL injectedJavaScriptBeforeContentLoadedForMainFrameOnly;
34 36
 @property (nonatomic, assign) BOOL scrollEnabled;
35 37
 @property (nonatomic, assign) BOOL sharedCookiesEnabled;
36 38
 @property (nonatomic, assign) BOOL pagingEnabled;

+ 169
- 106
ios/RNCWebView.m View File

@@ -51,6 +51,9 @@ static NSDictionary* customCertificatesForHost;
51 51
 @property (nonatomic, copy) RCTDirectEventBlock onScroll;
52 52
 @property (nonatomic, copy) RCTDirectEventBlock onContentProcessDidTerminate;
53 53
 @property (nonatomic, copy) WKWebView *webView;
54
+@property (nonatomic, strong) WKUserScript *postMessageScript;
55
+@property (nonatomic, strong) WKUserScript *atStartScript;
56
+@property (nonatomic, strong) WKUserScript *atEndScript;
54 57
 @end
55 58
 
56 59
 @implementation RNCWebView
@@ -84,6 +87,10 @@ static NSDictionary* customCertificatesForHost;
84 87
     _savedKeyboardDisplayRequiresUserAction = YES;
85 88
     _savedStatusBarStyle = RCTSharedApplication().statusBarStyle;
86 89
     _savedStatusBarHidden = RCTSharedApplication().statusBarHidden;
90
+    _injectedJavaScript = nil;
91
+    _injectedJavaScriptForMainFrameOnly = YES;
92
+    _injectedJavaScriptBeforeContentLoaded = nil;
93
+    _injectedJavaScriptBeforeContentLoadedForMainFrameOnly = YES;
87 94
 
88 95
 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
89 96
     _savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
@@ -163,50 +170,8 @@ static NSDictionary* customCertificatesForHost;
163 170
   // Shim the HTML5 history API:
164 171
   [wkWebViewConfig.userContentController addScriptMessageHandler:[[RNCWeakScriptMessageDelegate alloc] initWithDelegate:self]
165 172
                                                             name:HistoryShimName];
166
-  NSString *source = [NSString stringWithFormat:
167
-    @"(function(history) {\n"
168
-    "  function notify(type) {\n"
169
-    "    setTimeout(function() {\n"
170
-    "      window.webkit.messageHandlers.%@.postMessage(type)\n"
171
-    "    }, 0)\n"
172
-    "  }\n"
173
-    "  function shim(f) {\n"
174
-    "    return function pushState() {\n"
175
-    "      notify('other')\n"
176
-    "      return f.apply(history, arguments)\n"
177
-    "    }\n"
178
-    "  }\n"
179
-    "  history.pushState = shim(history.pushState)\n"
180
-    "  history.replaceState = shim(history.replaceState)\n"
181
-    "  window.addEventListener('popstate', function() {\n"
182
-    "    notify('backforward')\n"
183
-    "  })\n"
184
-    "})(window.history)\n", HistoryShimName
185
-  ];
186
-  WKUserScript *script = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
187
-  [wkWebViewConfig.userContentController addUserScript:script];
188
-
189
-  if (_messagingEnabled) {
190
-    [wkWebViewConfig.userContentController addScriptMessageHandler:[[RNCWeakScriptMessageDelegate alloc] initWithDelegate:self]
191
-                                                              name:MessageHandlerName];
192
-
193
-    NSString *source = [NSString stringWithFormat:
194
-      @"window.%@ = {"
195
-       "  postMessage: function (data) {"
196
-       "    window.webkit.messageHandlers.%@.postMessage(String(data));"
197
-       "  }"
198
-       "};", MessageHandlerName, MessageHandlerName
199
-    ];
200
-
201
-    WKUserScript *script = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
202
-    [wkWebViewConfig.userContentController addUserScript:script];
203
-      
204
-    if (_injectedJavaScriptBeforeContentLoaded) {
205
-      // If user has provided an injectedJavascript prop, execute it at the start of the document
206
-      WKUserScript *injectedScript = [[WKUserScript alloc] initWithSource:_injectedJavaScriptBeforeContentLoaded injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
207
-      [wkWebViewConfig.userContentController addUserScript:injectedScript];
208
-    }
209
-  }
173
+
174
+  [self resetupScripts];
210 175
 
211 176
   wkWebViewConfig.allowsInlineMediaPlayback = _allowsInlineMediaPlayback;
212 177
 #if WEBKIT_IOS_10_APIS_AVAILABLE
@@ -221,68 +186,6 @@ static NSDictionary* customCertificatesForHost;
221 186
   if (_applicationNameForUserAgent) {
222 187
       wkWebViewConfig.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", wkWebViewConfig.applicationNameForUserAgent, _applicationNameForUserAgent];
223 188
   }
224
-
225
-  if(_sharedCookiesEnabled) {
226
-    // More info to sending cookies with WKWebView
227
-    // https://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview/26577303#26577303
228
-    if (@available(iOS 11.0, *)) {
229
-      // Set Cookies in iOS 11 and above, initialize websiteDataStore before setting cookies
230
-      // See also https://forums.developer.apple.com/thread/97194
231
-      // check if websiteDataStore has not been initialized before
232
-      if(!_incognito && !_cacheEnabled) {
233
-        wkWebViewConfig.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
234
-      }
235
-      for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
236
-        [wkWebViewConfig.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:nil];
237
-      }
238
-    } else {
239
-      NSMutableString *script = [NSMutableString string];
240
-
241
-      // Clear all existing cookies in a direct called function. This ensures that no
242
-      // javascript error will break the web content javascript.
243
-      // We keep this code here, if someone requires that Cookies are also removed within the
244
-      // the WebView and want to extends the current sharedCookiesEnabled option with an
245
-      // additional property.
246
-      // Generates JS: document.cookie = "key=; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"
247
-      // for each cookie which is already available in the WebView context.
248
-      /*
249
-      [script appendString:@"(function () {\n"];
250
-      [script appendString:@"  var cookies = document.cookie.split('; ');\n"];
251
-      [script appendString:@"  for (var i = 0; i < cookies.length; i++) {\n"];
252
-      [script appendString:@"    if (cookies[i].indexOf('=') !== -1) {\n"];
253
-      [script appendString:@"      document.cookie = cookies[i].split('=')[0] + '=; Expires=Thu, 01 Jan 1970 00:00:01 GMT';\n"];
254
-      [script appendString:@"    }\n"];
255
-      [script appendString:@"  }\n"];
256
-      [script appendString:@"})();\n\n"];
257
-      */
258
-
259
-      // Set cookies in a direct called function. This ensures that no
260
-      // javascript error will break the web content javascript.
261
-        // Generates JS: document.cookie = "key=value; Path=/; Expires=Thu, 01 Jan 20xx 00:00:01 GMT;"
262
-      // for each cookie which is available in the application context.
263
-      [script appendString:@"(function () {\n"];
264
-      for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
265
-        [script appendFormat:@"document.cookie = %@ + '=' + %@",
266
-          RCTJSONStringify(cookie.name, NULL),
267
-          RCTJSONStringify(cookie.value, NULL)];
268
-        if (cookie.path) {
269
-          [script appendFormat:@" + '; Path=' + %@", RCTJSONStringify(cookie.path, NULL)];
270
-        }
271
-        if (cookie.expiresDate) {
272
-          [script appendFormat:@" + '; Expires=' + new Date(%f).toUTCString()",
273
-            cookie.expiresDate.timeIntervalSince1970 * 1000
274
-          ];
275
-        }
276
-        [script appendString:@";\n"];
277
-      }
278
-      [script appendString:@"})();\n"];
279
-
280
-      WKUserScript* cookieInScript = [[WKUserScript alloc] initWithSource:script
281
-                                                            injectionTime:WKUserScriptInjectionTimeAtDocumentStart
282
-                                                         forMainFrameOnly:YES];
283
-      [wkWebViewConfig.userContentController addUserScript:cookieInScript];
284
-    }
285
-  }
286 189
   
287 190
   return wkWebViewConfig;
288 191
 }
@@ -1064,6 +967,166 @@ static NSDictionary* customCertificatesForHost;
1064 967
   _webView.scrollView.bounces = bounces;
1065 968
 }
1066 969
 
970
+
971
+- (void)setInjectedJavaScript:(NSString *)script {
972
+  _injectedJavaScript = script;
973
+  
974
+  self.atStartScript = script == nil ? nil : [[WKUserScript alloc] initWithSource:script
975
+      injectionTime:WKUserScriptInjectionTimeAtDocumentStart
976
+    forMainFrameOnly:_injectedJavaScriptForMainFrameOnly];
977
+  
978
+  [self resetupScripts];
979
+}
980
+
981
+- (void)setInjectedJavaScriptBeforeContentLoaded:(NSString *)script {
982
+  _injectedJavaScriptBeforeContentLoaded = script;
983
+  
984
+  self.atEndScript = script == nil ? nil : [[WKUserScript alloc] initWithSource:script
985
+       injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
986
+    forMainFrameOnly:_injectedJavaScriptBeforeContentLoadedForMainFrameOnly];
987
+  
988
+  [self resetupScripts];
989
+}
990
+
991
+- (void)setInjectedJavaScriptForMainFrameOnly:(BOOL)inject {
992
+  _injectedJavaScriptForMainFrameOnly = inject;
993
+  [self setInjectedJavaScript:_injectedJavaScript];
994
+}
995
+
996
+- (void)setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly:(BOOL)inject {
997
+  _injectedJavaScriptBeforeContentLoadedForMainFrameOnly = inject;
998
+  [self setInjectedJavaScriptBeforeContentLoaded:_injectedJavaScriptBeforeContentLoaded];
999
+}
1000
+
1001
+- (void)setMessagingEnabled:(BOOL)messagingEnabled {
1002
+  _messagingEnabled = messagingEnabled;
1003
+  
1004
+  self.postMessageScript = _messagingEnabled ?
1005
+  [
1006
+   [WKUserScript alloc]
1007
+   initWithSource: [
1008
+                    NSString
1009
+                    stringWithFormat:
1010
+                    @"window.%@ = {"
1011
+                    "  postMessage: function (data) {"
1012
+                    "    window.webkit.messageHandlers.%@.postMessage(String(data));"
1013
+                    "  }"
1014
+                    "};", MessageHandlerName, MessageHandlerName
1015
+                    ]
1016
+   injectionTime:WKUserScriptInjectionTimeAtDocumentStart
1017
+   /* This was previously YES, but I'm following react-native-wkwebview's approach on this;
1018
+    * It's very useful to be able to inject postMessage into iframes. */
1019
+   forMainFrameOnly:_injectedJavaScriptBeforeContentLoadedForMainFrameOnly
1020
+   ] :
1021
+  nil;
1022
+  
1023
+  [self resetupScripts];
1024
+}
1025
+
1026
+- (void)resetupScripts {
1027
+  [_webView.configuration.userContentController removeAllUserScripts];
1028
+  [_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
1029
+  
1030
+  NSString *html5HistoryAPIShimSource = [NSString stringWithFormat:
1031
+    @"(function(history) {\n"
1032
+    "  function notify(type) {\n"
1033
+    "    setTimeout(function() {\n"
1034
+    "      window.webkit.messageHandlers.%@.postMessage(type)\n"
1035
+    "    }, 0)\n"
1036
+    "  }\n"
1037
+    "  function shim(f) {\n"
1038
+    "    return function pushState() {\n"
1039
+    "      notify('other')\n"
1040
+    "      return f.apply(history, arguments)\n"
1041
+    "    }\n"
1042
+    "  }\n"
1043
+    "  history.pushState = shim(history.pushState)\n"
1044
+    "  history.replaceState = shim(history.replaceState)\n"
1045
+    "  window.addEventListener('popstate', function() {\n"
1046
+    "    notify('backforward')\n"
1047
+    "  })\n"
1048
+    "})(window.history)\n", HistoryShimName
1049
+  ];
1050
+  WKUserScript *script = [[WKUserScript alloc] initWithSource:html5HistoryAPIShimSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
1051
+  [_webView.configuration.userContentController addUserScript:script];
1052
+  
1053
+  if(_sharedCookiesEnabled) {
1054
+    // More info to sending cookies with WKWebView
1055
+    // https://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview/26577303#26577303
1056
+    if (@available(iOS 11.0, *)) {
1057
+      // Set Cookies in iOS 11 and above, initialize websiteDataStore before setting cookies
1058
+      // See also https://forums.developer.apple.com/thread/97194
1059
+      // check if websiteDataStore has not been initialized before
1060
+      if(!_incognito && !_cacheEnabled) {
1061
+        _webView.configuration.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
1062
+      }
1063
+      for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
1064
+        [_webView.configuration.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:nil];
1065
+      }
1066
+    } else {
1067
+      NSMutableString *script = [NSMutableString string];
1068
+
1069
+      // Clear all existing cookies in a direct called function. This ensures that no
1070
+      // javascript error will break the web content javascript.
1071
+      // We keep this code here, if someone requires that Cookies are also removed within the
1072
+      // the WebView and want to extends the current sharedCookiesEnabled option with an
1073
+      // additional property.
1074
+      // Generates JS: document.cookie = "key=; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"
1075
+      // for each cookie which is already available in the WebView context.
1076
+      /*
1077
+      [script appendString:@"(function () {\n"];
1078
+      [script appendString:@"  var cookies = document.cookie.split('; ');\n"];
1079
+      [script appendString:@"  for (var i = 0; i < cookies.length; i++) {\n"];
1080
+      [script appendString:@"    if (cookies[i].indexOf('=') !== -1) {\n"];
1081
+      [script appendString:@"      document.cookie = cookies[i].split('=')[0] + '=; Expires=Thu, 01 Jan 1970 00:00:01 GMT';\n"];
1082
+      [script appendString:@"    }\n"];
1083
+      [script appendString:@"  }\n"];
1084
+      [script appendString:@"})();\n\n"];
1085
+      */
1086
+
1087
+      // Set cookies in a direct called function. This ensures that no
1088
+      // javascript error will break the web content javascript.
1089
+        // Generates JS: document.cookie = "key=value; Path=/; Expires=Thu, 01 Jan 20xx 00:00:01 GMT;"
1090
+      // for each cookie which is available in the application context.
1091
+      [script appendString:@"(function () {\n"];
1092
+      for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
1093
+        [script appendFormat:@"document.cookie = %@ + '=' + %@",
1094
+          RCTJSONStringify(cookie.name, NULL),
1095
+          RCTJSONStringify(cookie.value, NULL)];
1096
+        if (cookie.path) {
1097
+          [script appendFormat:@" + '; Path=' + %@", RCTJSONStringify(cookie.path, NULL)];
1098
+        }
1099
+        if (cookie.expiresDate) {
1100
+          [script appendFormat:@" + '; Expires=' + new Date(%f).toUTCString()",
1101
+            cookie.expiresDate.timeIntervalSince1970 * 1000
1102
+          ];
1103
+        }
1104
+        [script appendString:@";\n"];
1105
+      }
1106
+      [script appendString:@"})();\n"];
1107
+
1108
+      WKUserScript* cookieInScript = [[WKUserScript alloc] initWithSource:script
1109
+                                                            injectionTime:WKUserScriptInjectionTimeAtDocumentStart
1110
+                                                         forMainFrameOnly:YES];
1111
+      [_webView.configuration.userContentController addUserScript:cookieInScript];
1112
+    }
1113
+  }
1114
+  
1115
+  if(_messagingEnabled){
1116
+    if (self.postMessageScript){
1117
+      [_webView.configuration.userContentController addScriptMessageHandler:[[RNCWeakScriptMessageDelegate alloc] initWithDelegate:self]
1118
+                                                                       name:MessageHandlerName];
1119
+      [_webView.configuration.userContentController addUserScript:self.postMessageScript];
1120
+    }
1121
+    if (self.atStartScript) {
1122
+      [_webView.configuration.userContentController addUserScript:self.atStartScript];
1123
+    }
1124
+    if (self.atEndScript) {
1125
+      [_webView.configuration.userContentController addUserScript:self.atEndScript];
1126
+    }
1127
+  }
1128
+}
1129
+
1067 1130
 - (NSURLRequest *)requestForSource:(id)json {
1068 1131
   NSURLRequest *request = [RCTConvert NSURLRequest:self.source];
1069 1132
 

+ 2
- 0
ios/RNCWebViewManager.m View File

@@ -52,6 +52,8 @@ RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock)
52 52
 RCT_EXPORT_VIEW_PROPERTY(onContentProcessDidTerminate, RCTDirectEventBlock)
53 53
 RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString)
54 54
 RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptBeforeContentLoaded, NSString)
55
+RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptForMainFrameOnly, BOOL)
56
+RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptForMainFrameOnlyBeforeContentLoaded, BOOL)
55 57
 RCT_EXPORT_VIEW_PROPERTY(javaScriptEnabled, BOOL)
56 58
 RCT_EXPORT_VIEW_PROPERTY(allowFileAccessFromFileURLs, BOOL)
57 59
 RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL)

+ 6
- 0
src/WebView.ios.tsx View File

@@ -290,6 +290,8 @@ class WebView extends React.Component<IOSWebViewProps, State> {
290 290
       originWhitelist,
291 291
       renderError,
292 292
       renderLoading,
293
+      injectedJavaScriptForMainFrameOnly = true,
294
+      injectedJavaScriptBeforeContentLoadedForMainFrameOnly = true,
293 295
       style,
294 296
       containerStyle,
295 297
       ...otherProps
@@ -344,6 +346,10 @@ class WebView extends React.Component<IOSWebViewProps, State> {
344 346
         onScroll={this.props.onScroll}
345 347
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
346 348
         onContentProcessDidTerminate={this.onContentProcessDidTerminate}
349
+        injectedJavaScript={this.props.injectedJavaScript}
350
+        injectedJavaScriptBeforeContentLoaded={this.props.injectedJavaScriptBeforeContentLoaded}
351
+        injectedJavaScriptForMainFrameOnly={injectedJavaScriptForMainFrameOnly}
352
+        injectedJavaScriptBeforeContentLoadedForMainFrameOnly={injectedJavaScriptBeforeContentLoadedForMainFrameOnly}
347 353
         ref={this.webViewRef}
348 354
         // TODO: find a better way to type this.
349 355
         source={resolveAssetSource(this.props.source as ImageSourcePropType)}

+ 16
- 0
src/WebViewTypes.ts View File

@@ -279,6 +279,8 @@ export interface IOSNativeWebViewProps extends CommonNativeWebViewProps {
279 279
   scrollEnabled?: boolean;
280 280
   useSharedProcessPool?: boolean;
281 281
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
282
+  injectedJavaScriptForMainFrameOnly?: boolean;
283
+  injectedJavaScriptBeforeContentLoadedForMainFrameOnly?: boolean;
282 284
 }
283 285
 
284 286
 export interface IOSWebViewProps extends WebViewSharedProps {
@@ -458,6 +460,20 @@ export interface IOSWebViewProps extends WebViewSharedProps {
458 460
    * @platform ios
459 461
    */
460 462
   onContentProcessDidTerminate?: (event: WebViewTerminatedEvent) => void;
463
+
464
+  /**
465
+   * If `true` (default), loads the `injectedJavaScript` only into the main frame.
466
+   * If `false`, loads it into all frames (e.g. iframes).
467
+   * @platform ios
468
+  */
469
+  injectedJavaScriptForMainFrameOnly?: boolean;
470
+
471
+  /**
472
+   * If `true` (default), loads the `injectedJavaScriptBeforeContentLoaded` only into the main frame.
473
+   * If `false`, loads it into all frames (e.g. iframes).
474
+   * @platform ios
475
+  */
476
+  injectedJavaScriptBeforeContentLoadedForMainFrameOnly?: boolean;
461 477
 }
462 478
 
463 479
 export interface AndroidWebViewProps extends WebViewSharedProps {