@exodus/react-native-webview 11.26.1-exodus.1 → 11.26.1-exodus.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java +26 -268
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java +1 -45
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.java +25 -0
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewUtils.java +51 -0
- package/apple/RNCWebView.h +0 -8
- package/apple/RNCWebView.m +17 -123
- package/apple/RNCWebViewManager.m +0 -10
- package/index.js +5 -2
- package/lib/WebView.android.js +83 -73
- package/lib/WebView.ios.js +64 -113
- package/lib/WebView.js +2 -2
- package/lib/WebView.styles.js +7 -7
- package/lib/WebViewNativeComponent.android.js +1 -1
- package/lib/WebViewNativeComponent.ios.js +1 -1
- package/lib/WebViewShared.d.ts +8 -12
- package/lib/WebViewShared.js +118 -88
- package/lib/WebViewTypes.d.ts +22 -157
- package/lib/WebViewTypes.js +4 -31
- package/package.json +1 -1
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewPackage.kt +0 -15
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopHttpErrorEvent.kt +0 -25
- package/android/src/main/java/com/reactnativecommunity/webview/events/TopRenderProcessGoneEvent.kt +0 -26
package/apple/RNCWebView.m
CHANGED
|
@@ -54,13 +54,11 @@ UIScrollViewDelegate,
|
|
|
54
54
|
#endif // !TARGET_OS_OSX
|
|
55
55
|
RCTAutoInsetsProtocol>
|
|
56
56
|
|
|
57
|
-
@property (nonatomic, copy) RCTDirectEventBlock onFileDownload;
|
|
58
57
|
@property (nonatomic, copy) RCTDirectEventBlock onLoadingStart;
|
|
59
58
|
@property (nonatomic, copy) RCTDirectEventBlock onLoadingFinish;
|
|
60
59
|
@property (nonatomic, copy) RCTDirectEventBlock onLoadingError;
|
|
61
60
|
@property (nonatomic, copy) RCTDirectEventBlock onLoadingProgress;
|
|
62
61
|
@property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest;
|
|
63
|
-
@property (nonatomic, copy) RCTDirectEventBlock onHttpError;
|
|
64
62
|
@property (nonatomic, copy) RCTDirectEventBlock onMessage;
|
|
65
63
|
@property (nonatomic, copy) RCTDirectEventBlock onScroll;
|
|
66
64
|
@property (nonatomic, copy) RCTDirectEventBlock onContentProcessDidTerminate;
|
|
@@ -122,9 +120,7 @@ RCTAutoInsetsProtocol>
|
|
|
122
120
|
_savedStatusBarHidden = RCTSharedApplication().statusBarHidden;
|
|
123
121
|
#endif // !TARGET_OS_OSX
|
|
124
122
|
_injectedJavaScript = nil;
|
|
125
|
-
_injectedJavaScriptForMainFrameOnly = YES;
|
|
126
123
|
_injectedJavaScriptBeforeContentLoaded = nil;
|
|
127
|
-
_injectedJavaScriptBeforeContentLoadedForMainFrameOnly = YES;
|
|
128
124
|
|
|
129
125
|
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
|
130
126
|
_savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
|
@@ -139,15 +135,6 @@ RCTAutoInsetsProtocol>
|
|
|
139
135
|
}
|
|
140
136
|
|
|
141
137
|
#if !TARGET_OS_OSX
|
|
142
|
-
[[NSNotificationCenter defaultCenter]addObserver:self
|
|
143
|
-
selector:@selector(appDidBecomeActive)
|
|
144
|
-
name:UIApplicationDidBecomeActiveNotification
|
|
145
|
-
object:nil];
|
|
146
|
-
|
|
147
|
-
[[NSNotificationCenter defaultCenter]addObserver:self
|
|
148
|
-
selector:@selector(appWillResignActive)
|
|
149
|
-
name:UIApplicationWillResignActiveNotification
|
|
150
|
-
object:nil];
|
|
151
138
|
if (@available(iOS 12.0, *)) {
|
|
152
139
|
// Workaround for a keyboard dismissal bug present in iOS 12
|
|
153
140
|
// https://openradar.appspot.com/radar?id=5018321736957952
|
|
@@ -306,30 +293,23 @@ RCTAutoInsetsProtocol>
|
|
|
306
293
|
{
|
|
307
294
|
WKWebViewConfiguration *wkWebViewConfig = [WKWebViewConfiguration new];
|
|
308
295
|
WKPreferences *prefs = [[WKPreferences alloc]init];
|
|
309
|
-
BOOL _prefsUsed = YES;
|
|
310
296
|
if (!_javaScriptEnabled) {
|
|
311
297
|
prefs.javaScriptEnabled = NO;
|
|
312
|
-
_prefsUsed = YES;
|
|
313
|
-
}
|
|
314
|
-
if (_allowUniversalAccessFromFileURLs) {
|
|
315
|
-
[wkWebViewConfig setValue:@TRUE forKey:@"allowUniversalAccessFromFileURLs"];
|
|
316
|
-
}
|
|
317
|
-
if (_allowFileAccessFromFileURLs) {
|
|
318
|
-
[prefs setValue:@TRUE forKey:@"allowFileAccessFromFileURLs"];
|
|
319
|
-
_prefsUsed = YES;
|
|
320
298
|
}
|
|
299
|
+
|
|
300
|
+
// NOTE: defaults, recheck?
|
|
301
|
+
// [wkWebViewConfig setValue:@FALSE forKey:@"allowUniversalAccessFromFileURLs"];
|
|
302
|
+
// [prefs setValue:@FALSE forKey:@"allowFileAccessFromFileURLs"];
|
|
303
|
+
|
|
321
304
|
[prefs setValue:@FALSE forKey:@"javaScriptCanOpenWindowsAutomatically"];
|
|
322
305
|
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500 /* iOS 14.5 */
|
|
323
306
|
if (@available(iOS 14.5, *)) {
|
|
324
307
|
if (!_textInteractionEnabled) {
|
|
325
308
|
[prefs setValue:@FALSE forKey:@"textInteractionEnabled"];
|
|
326
|
-
_prefsUsed = YES;
|
|
327
309
|
}
|
|
328
310
|
}
|
|
329
311
|
#endif
|
|
330
|
-
|
|
331
|
-
wkWebViewConfig.preferences = prefs;
|
|
332
|
-
}
|
|
312
|
+
wkWebViewConfig.preferences = prefs;
|
|
333
313
|
if (_incognito) {
|
|
334
314
|
wkWebViewConfig.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
|
|
335
315
|
} else if (_cacheEnabled) {
|
|
@@ -364,7 +344,7 @@ RCTAutoInsetsProtocol>
|
|
|
364
344
|
[self resetupScripts:wkWebViewConfig];
|
|
365
345
|
|
|
366
346
|
if(@available(ios 9.0, *)) {
|
|
367
|
-
wkWebViewConfig.allowsAirPlayForMediaPlayback =
|
|
347
|
+
wkWebViewConfig.allowsAirPlayForMediaPlayback = NO;
|
|
368
348
|
}
|
|
369
349
|
|
|
370
350
|
#if !TARGET_OS_OSX
|
|
@@ -379,10 +359,6 @@ RCTAutoInsetsProtocol>
|
|
|
379
359
|
#endif
|
|
380
360
|
#endif // !TARGET_OS_OSX
|
|
381
361
|
|
|
382
|
-
if (_applicationNameForUserAgent) {
|
|
383
|
-
wkWebViewConfig.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", wkWebViewConfig.applicationNameForUserAgent, _applicationNameForUserAgent];
|
|
384
|
-
}
|
|
385
|
-
|
|
386
362
|
return wkWebViewConfig;
|
|
387
363
|
}
|
|
388
364
|
|
|
@@ -466,10 +442,6 @@ RCTAutoInsetsProtocol>
|
|
|
466
442
|
_webView.scrollView.delegate = nil;
|
|
467
443
|
#endif // !TARGET_OS_OSX
|
|
468
444
|
_webView = nil;
|
|
469
|
-
if (_onContentProcessDidTerminate) {
|
|
470
|
-
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
|
|
471
|
-
_onContentProcessDidTerminate(event);
|
|
472
|
-
}
|
|
473
445
|
}
|
|
474
446
|
|
|
475
447
|
[super removeFromSuperview];
|
|
@@ -624,17 +596,6 @@ RCTAutoInsetsProtocol>
|
|
|
624
596
|
}
|
|
625
597
|
}
|
|
626
598
|
|
|
627
|
-
- (void)setAllowingReadAccessToURL:(NSString *)allowingReadAccessToURL
|
|
628
|
-
{
|
|
629
|
-
if (![_allowingReadAccessToURL isEqualToString:allowingReadAccessToURL]) {
|
|
630
|
-
_allowingReadAccessToURL = [allowingReadAccessToURL copy];
|
|
631
|
-
|
|
632
|
-
if (_webView != nil) {
|
|
633
|
-
[self visitSource];
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
599
|
#if !TARGET_OS_OSX
|
|
639
600
|
- (void)setContentInset:(UIEdgeInsets)contentInset
|
|
640
601
|
{
|
|
@@ -682,8 +643,10 @@ RCTAutoInsetsProtocol>
|
|
|
682
643
|
[_webView loadRequest:request];
|
|
683
644
|
}
|
|
684
645
|
else {
|
|
685
|
-
|
|
686
|
-
|
|
646
|
+
// WARNING: UNREACHABLE, non-host loads (file urls)
|
|
647
|
+
// Clear the webview
|
|
648
|
+
[_webView loadHTMLString:@"" baseURL:nil];
|
|
649
|
+
return;
|
|
687
650
|
}
|
|
688
651
|
}];
|
|
689
652
|
}
|
|
@@ -872,7 +835,7 @@ RCTAutoInsetsProtocol>
|
|
|
872
835
|
{
|
|
873
836
|
NSDictionary *eventInitDict = @{@"data": message};
|
|
874
837
|
NSString *source = [NSString
|
|
875
|
-
stringWithFormat:@"
|
|
838
|
+
stringWithFormat:@"document.dispatchEvent(new MessageEvent('message', %@));",
|
|
876
839
|
RCTJSONStringify(eventInitDict, NULL)
|
|
877
840
|
];
|
|
878
841
|
[self injectJavaScript: source];
|
|
@@ -1147,10 +1110,6 @@ RCTAutoInsetsProtocol>
|
|
|
1147
1110
|
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
|
|
1148
1111
|
{
|
|
1149
1112
|
RCTLogWarn(@"Webview Process Terminated");
|
|
1150
|
-
if (_onContentProcessDidTerminate) {
|
|
1151
|
-
NSMutableDictionary<NSString *, id> *event = [self baseEvent];
|
|
1152
|
-
_onContentProcessDidTerminate(event);
|
|
1153
|
-
}
|
|
1154
1113
|
}
|
|
1155
1114
|
|
|
1156
1115
|
/**
|
|
@@ -1162,36 +1121,19 @@ RCTAutoInsetsProtocol>
|
|
|
1162
1121
|
decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
|
|
1163
1122
|
{
|
|
1164
1123
|
WKNavigationResponsePolicy policy = WKNavigationResponsePolicyAllow;
|
|
1165
|
-
if (
|
|
1124
|
+
if (navigationResponse.forMainFrame) {
|
|
1166
1125
|
if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]]) {
|
|
1167
1126
|
NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
|
|
1168
1127
|
NSInteger statusCode = response.statusCode;
|
|
1169
1128
|
|
|
1170
|
-
if (statusCode >= 400) {
|
|
1171
|
-
NSMutableDictionary<NSString *, id> *httpErrorEvent = [self baseEvent];
|
|
1172
|
-
[httpErrorEvent addEntriesFromDictionary: @{
|
|
1173
|
-
@"url": response.URL.absoluteString,
|
|
1174
|
-
@"statusCode": @(statusCode)
|
|
1175
|
-
}];
|
|
1176
|
-
|
|
1177
|
-
_onHttpError(httpErrorEvent);
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
1129
|
NSString *disposition = nil;
|
|
1181
1130
|
if (@available(iOS 13, *)) {
|
|
1182
1131
|
disposition = [response valueForHTTPHeaderField:@"Content-Disposition"];
|
|
1183
1132
|
}
|
|
1184
1133
|
BOOL isAttachment = disposition != nil && [disposition hasPrefix:@"attachment"];
|
|
1185
1134
|
if (isAttachment || !navigationResponse.canShowMIMEType) {
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
NSMutableDictionary<NSString *, id> *downloadEvent = [self baseEvent];
|
|
1190
|
-
[downloadEvent addEntriesFromDictionary: @{
|
|
1191
|
-
@"downloadUrl": (response.URL).absoluteString,
|
|
1192
|
-
}];
|
|
1193
|
-
_onFileDownload(downloadEvent);
|
|
1194
|
-
}
|
|
1135
|
+
policy = WKNavigationResponsePolicyCancel;
|
|
1136
|
+
// File downloads are cancelled
|
|
1195
1137
|
}
|
|
1196
1138
|
}
|
|
1197
1139
|
}
|
|
@@ -1252,37 +1194,6 @@ RCTAutoInsetsProtocol>
|
|
|
1252
1194
|
}];
|
|
1253
1195
|
}
|
|
1254
1196
|
|
|
1255
|
-
-(void)forceIgnoreSilentHardwareSwitch:(BOOL)initialSetup
|
|
1256
|
-
{
|
|
1257
|
-
NSString *mp3Str = @"data:audio/mp3;base64,//tAxAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAAFAAAESAAzMzMzMzMzMzMzMzMzMzMzMzMzZmZmZmZmZmZmZmZmZmZmZmZmZmaZmZmZmZmZmZmZmZmZmZmZmZmZmczMzMzMzMzMzMzMzMzMzMzMzMzM//////////////////////////8AAAA5TEFNRTMuMTAwAZYAAAAAAAAAABQ4JAMGQgAAOAAABEhNIZS0AAAAAAD/+0DEAAPH3Yz0AAR8CPqyIEABp6AxjG/4x/XiInE4lfQDFwIIRE+uBgZoW4RL0OLMDFn6E5v+/u5ehf76bu7/6bu5+gAiIQGAABQIUJ0QolFghEn/9PhZQpcUTpXMjo0OGzRCZXyKxoIQzB2KhCtGobpT9TRVj/3Pmfp+f8X7Pu1B04sTnc3s0XhOlXoGVCMNo9X//9/r6a10TZEY5DsxqvO7mO5qFvpFCmKIjhpSItGsUYcRO//7QsQRgEiljQIAgLFJAbIhNBCa+JmorCbOi5q9nVd2dKnusTMQg4MFUlD6DQ4OFijwGAijRMfLbHG4nLVTjydyPlJTj8pfPflf9/5GD950A5e+jsrmNZSjSirjs1R7hnkia8vr//l/7Nb+crvr9Ok5ZJOylUKRxf/P9Zn0j2P4pJYXyKkeuy5wUYtdmOu6uobEtFqhIJViLEKIjGxchGev/L3Y0O3bwrIOszTBAZ7Ih28EUaSOZf/7QsQfg8fpjQIADN0JHbGgQBAZ8T//y//t/7d/2+f5m7MdCeo/9tdkMtGLbt1tqnabRroO1Qfvh20yEbei8nfDXP7btW7f9/uO9tbe5IvHQbLlxpf3DkAk0ojYcv///5/u3/7PTfGjPEPUvt5D6f+/3Lea4lz4tc4TnM/mFPrmalWbboeNiNyeyr+vufttZuvrVrt/WYv3T74JFo8qEDiJqJrmDTs///v99xDku2xG02jjunrICP/7QsQtA8kpkQAAgNMA/7FgQAGnobgfghgqA+uXwWQ3XFmGimSbe2X3ksY//KzK1a2k6cnNWOPJnPWUsYbKqkh8RJzrVf///P///////4vyhLKHLrCb5nIrYIUss4cthigL1lQ1wwNAc6C1pf1TIKRSkt+a//z+yLVcwlXKSqeSuCVQFLng2h4AFAFgTkH+Z/8jTX/zr//zsJV/5f//5UX/0ZNCNCCaf5lTCTRkaEdhNP//n/KUjf/7QsQ5AEhdiwAAjN7I6jGddBCO+WGTQ1mXrYatSAgaykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg==";
|
|
1258
|
-
NSString *scr;
|
|
1259
|
-
if (initialSetup) {
|
|
1260
|
-
scr = [NSString stringWithFormat:@"var s=new Audio('%@');s.id='wkwebviewAudio';s.controls=false;s.loop=true;s.play();document.body.appendChild(s);true", mp3Str];
|
|
1261
|
-
} else {
|
|
1262
|
-
scr = [NSString stringWithFormat:@"var s=document.getElementById('wkwebviewAudio');s.src=null;s.parentNode.removeChild(s);s=null;s=new Audio('%@');s.id='wkwebviewAudio';s.controls=false;s.loop=true;s.play();document.body.appendChild(s);true", mp3Str];
|
|
1263
|
-
}
|
|
1264
|
-
[self evaluateJS: scr thenCall: nil];
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
-(void)disableIgnoreSilentSwitch
|
|
1268
|
-
{
|
|
1269
|
-
[self evaluateJS: @"document.getElementById('wkwebviewAudio').src=null;true" thenCall: nil];
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
-(void)appDidBecomeActive
|
|
1273
|
-
{
|
|
1274
|
-
if (_ignoreSilentHardwareSwitch) {
|
|
1275
|
-
[self forceIgnoreSilentHardwareSwitch:false];
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
-(void)appWillResignActive
|
|
1280
|
-
{
|
|
1281
|
-
if (_ignoreSilentHardwareSwitch) {
|
|
1282
|
-
[self disableIgnoreSilentSwitch];
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
1197
|
/**
|
|
1287
1198
|
* Called when the navigation is complete.
|
|
1288
1199
|
* @see https://fburl.com/rtys6jlb
|
|
@@ -1290,10 +1201,6 @@ RCTAutoInsetsProtocol>
|
|
|
1290
1201
|
- (void)webView:(WKWebView *)webView
|
|
1291
1202
|
didFinishNavigation:(WKNavigation *)navigation
|
|
1292
1203
|
{
|
|
1293
|
-
if (_ignoreSilentHardwareSwitch) {
|
|
1294
|
-
[self forceIgnoreSilentHardwareSwitch:true];
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
1204
|
if (_onLoadingFinish) {
|
|
1298
1205
|
_onLoadingFinish([self baseEvent]);
|
|
1299
1206
|
}
|
|
@@ -1389,7 +1296,7 @@ didFinishNavigation:(WKNavigation *)navigation
|
|
|
1389
1296
|
|
|
1390
1297
|
self.atEndScript = source == nil ? nil : [[WKUserScript alloc] initWithSource:source
|
|
1391
1298
|
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
|
|
1392
|
-
forMainFrameOnly:
|
|
1299
|
+
forMainFrameOnly:YES];
|
|
1393
1300
|
|
|
1394
1301
|
if(_webView != nil){
|
|
1395
1302
|
[self resetupScripts:_webView.configuration];
|
|
@@ -1401,23 +1308,13 @@ didFinishNavigation:(WKNavigation *)navigation
|
|
|
1401
1308
|
|
|
1402
1309
|
self.atStartScript = source == nil ? nil : [[WKUserScript alloc] initWithSource:source
|
|
1403
1310
|
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
|
|
1404
|
-
forMainFrameOnly:
|
|
1311
|
+
forMainFrameOnly:YES];
|
|
1405
1312
|
|
|
1406
1313
|
if(_webView != nil){
|
|
1407
1314
|
[self resetupScripts:_webView.configuration];
|
|
1408
1315
|
}
|
|
1409
1316
|
}
|
|
1410
1317
|
|
|
1411
|
-
- (void)setInjectedJavaScriptForMainFrameOnly:(BOOL)mainFrameOnly {
|
|
1412
|
-
_injectedJavaScriptForMainFrameOnly = mainFrameOnly;
|
|
1413
|
-
[self setInjectedJavaScript:_injectedJavaScript];
|
|
1414
|
-
}
|
|
1415
|
-
|
|
1416
|
-
- (void)setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly:(BOOL)mainFrameOnly {
|
|
1417
|
-
_injectedJavaScriptBeforeContentLoadedForMainFrameOnly = mainFrameOnly;
|
|
1418
|
-
[self setInjectedJavaScriptBeforeContentLoaded:_injectedJavaScriptBeforeContentLoaded];
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
1318
|
- (void)setMessagingEnabled:(BOOL)messagingEnabled {
|
|
1422
1319
|
_messagingEnabled = messagingEnabled;
|
|
1423
1320
|
|
|
@@ -1434,9 +1331,6 @@ didFinishNavigation:(WKNavigation *)navigation
|
|
|
1434
1331
|
"};", MessageHandlerName, MessageHandlerName
|
|
1435
1332
|
]
|
|
1436
1333
|
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
|
|
1437
|
-
/* TODO: For a separate (minor) PR: use logic like this (as react-native-wkwebview does) so that messaging can be used in all frames if desired.
|
|
1438
|
-
* I am keeping it as YES for consistency with previous behaviour. */
|
|
1439
|
-
// forMainFrameOnly:_messagingEnabledForMainFrameOnly
|
|
1440
1334
|
forMainFrameOnly:YES
|
|
1441
1335
|
] :
|
|
1442
1336
|
nil;
|
|
@@ -54,23 +54,15 @@ RCT_EXPORT_MODULE()
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary)
|
|
57
|
-
RCT_EXPORT_VIEW_PROPERTY(onFileDownload, RCTDirectEventBlock)
|
|
58
57
|
RCT_EXPORT_VIEW_PROPERTY(onLoadingStart, RCTDirectEventBlock)
|
|
59
58
|
RCT_EXPORT_VIEW_PROPERTY(onLoadingFinish, RCTDirectEventBlock)
|
|
60
59
|
RCT_EXPORT_VIEW_PROPERTY(onLoadingError, RCTDirectEventBlock)
|
|
61
60
|
RCT_EXPORT_VIEW_PROPERTY(onLoadingProgress, RCTDirectEventBlock)
|
|
62
|
-
RCT_EXPORT_VIEW_PROPERTY(onHttpError, RCTDirectEventBlock)
|
|
63
61
|
RCT_EXPORT_VIEW_PROPERTY(onShouldStartLoadWithRequest, RCTDirectEventBlock)
|
|
64
|
-
RCT_EXPORT_VIEW_PROPERTY(onContentProcessDidTerminate, RCTDirectEventBlock)
|
|
65
62
|
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScript, NSString)
|
|
66
63
|
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptBeforeContentLoaded, NSString)
|
|
67
|
-
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptForMainFrameOnly, BOOL)
|
|
68
|
-
RCT_EXPORT_VIEW_PROPERTY(injectedJavaScriptBeforeContentLoadedForMainFrameOnly, BOOL)
|
|
69
64
|
RCT_EXPORT_VIEW_PROPERTY(javaScriptEnabled, BOOL)
|
|
70
|
-
RCT_EXPORT_VIEW_PROPERTY(allowFileAccessFromFileURLs, BOOL)
|
|
71
|
-
RCT_EXPORT_VIEW_PROPERTY(allowUniversalAccessFromFileURLs, BOOL)
|
|
72
65
|
RCT_EXPORT_VIEW_PROPERTY(allowsInlineMediaPlayback, BOOL)
|
|
73
|
-
RCT_EXPORT_VIEW_PROPERTY(allowsAirPlayForMediaPlayback, BOOL)
|
|
74
66
|
RCT_EXPORT_VIEW_PROPERTY(mediaPlaybackRequiresUserAction, BOOL)
|
|
75
67
|
#if WEBKIT_IOS_10_APIS_AVAILABLE
|
|
76
68
|
RCT_EXPORT_VIEW_PROPERTY(dataDetectorTypes, WKDataDetectorTypes)
|
|
@@ -82,10 +74,8 @@ RCT_EXPORT_VIEW_PROPERTY(hideKeyboardAccessoryView, BOOL)
|
|
|
82
74
|
RCT_EXPORT_VIEW_PROPERTY(allowsBackForwardNavigationGestures, BOOL)
|
|
83
75
|
RCT_EXPORT_VIEW_PROPERTY(incognito, BOOL)
|
|
84
76
|
RCT_EXPORT_VIEW_PROPERTY(pagingEnabled, BOOL)
|
|
85
|
-
RCT_EXPORT_VIEW_PROPERTY(applicationNameForUserAgent, NSString)
|
|
86
77
|
RCT_EXPORT_VIEW_PROPERTY(cacheEnabled, BOOL)
|
|
87
78
|
RCT_EXPORT_VIEW_PROPERTY(allowsLinkPreview, BOOL)
|
|
88
|
-
RCT_EXPORT_VIEW_PROPERTY(allowingReadAccessToURL, NSString)
|
|
89
79
|
RCT_EXPORT_VIEW_PROPERTY(basicAuthCredential, NSDictionary)
|
|
90
80
|
|
|
91
81
|
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
package/index.js
CHANGED
package/lib/WebView.android.js
CHANGED
|
@@ -1,50 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
|
-
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
|
13
|
-
import { Image, View, NativeModules, } from 'react-native';
|
|
1
|
+
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Text, View, NativeModules, } from 'react-native';
|
|
14
3
|
import BatchedBridge from 'react-native/Libraries/BatchedBridge/BatchedBridge';
|
|
15
4
|
// @ts-expect-error react-native doesn't have this type
|
|
16
5
|
import codegenNativeCommandsUntyped from 'react-native/Libraries/Utilities/codegenNativeCommands';
|
|
17
6
|
import invariant from 'invariant';
|
|
18
7
|
import RNCWebView from "./WebViewNativeComponent.android";
|
|
19
|
-
import { defaultOriginWhitelist, defaultRenderError, defaultRenderLoading, useWebWiewLogic, } from './WebViewShared';
|
|
8
|
+
import { defaultOriginWhitelist, defaultRenderError, defaultRenderLoading, useWebWiewLogic, versionPasses, } from './WebViewShared';
|
|
20
9
|
import styles from './WebView.styles';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
const { getWebViewDefaultUserAgent } = NativeModules.RNCWebViewUtils;
|
|
11
|
+
let userAgentPromise;
|
|
12
|
+
async function getUserAgent() {
|
|
13
|
+
if (!userAgentPromise)
|
|
14
|
+
userAgentPromise = getWebViewDefaultUserAgent();
|
|
15
|
+
const userAgent = await userAgentPromise;
|
|
16
|
+
return userAgent || 'unknown';
|
|
17
|
+
}
|
|
18
|
+
const codegenNativeCommands = codegenNativeCommandsUntyped;
|
|
19
|
+
const Commands = codegenNativeCommands({
|
|
20
|
+
supportedCommands: ['goBack', 'goForward', 'reload', 'stopLoading', /* 'injectJavaScript', */ 'requestFocus', 'postMessage', 'clearFormData', 'clearCache', 'clearHistory', 'loadUrl'],
|
|
24
21
|
});
|
|
25
|
-
var resolveAssetSource = Image.resolveAssetSource;
|
|
26
22
|
/**
|
|
27
23
|
* A simple counter to uniquely identify WebView instances. Do not use this for anything else.
|
|
28
24
|
*/
|
|
29
|
-
|
|
25
|
+
let uniqueRef = 0;
|
|
30
26
|
/**
|
|
31
27
|
* Harcoded default for security.
|
|
32
28
|
*/
|
|
33
|
-
|
|
34
|
-
var allowUniversalAccessFromFileURLs = false;
|
|
35
|
-
var injectedJavaScriptForMainFrameOnly = true;
|
|
36
|
-
var injectedJavaScriptBeforeContentLoadedForMainFrameOnly = true;
|
|
37
|
-
var mediaPlaybackRequiresUserAction = true;
|
|
29
|
+
const mediaPlaybackRequiresUserAction = true;
|
|
38
30
|
// Android only
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
var onShouldStartLoadWithRequestCallback = useCallback(function (shouldStart, url, lockIdentifier) {
|
|
31
|
+
const setSupportMultipleWindows = true;
|
|
32
|
+
const mixedContentMode = 'never';
|
|
33
|
+
const hardMinimumChromeVersion = '100.0'; // TODO: determinime a good lower bound
|
|
34
|
+
const WebViewComponent = forwardRef(({ overScrollMode = 'always', javaScriptEnabled = true, thirdPartyCookiesEnabled = true, scalesPageToFit = true, saveFormDataDisabled = false, cacheEnabled = true, androidHardwareAccelerationDisabled = false, androidLayerType = "none", originWhitelist = defaultOriginWhitelist, setBuiltInZoomControls = true, setDisplayZoomControls = false, nestedScrollEnabled = false, startInLoadingState, onLoadStart, onError, onLoad, onLoadEnd, onMessage: onMessageProp, renderLoading, renderError, style, containerStyle, source, onShouldStartLoadWithRequest: onShouldStartLoadWithRequestProp, validateMeta, validateData, minimumChromeVersion, unsupportedVersionComponent: UnsupportedVersionComponent, ...otherProps }, ref) => {
|
|
35
|
+
var _a;
|
|
36
|
+
const messagingModuleName = useRef(`WebViewMessageHandler${uniqueRef += 1}`).current;
|
|
37
|
+
const webViewRef = useRef(null);
|
|
38
|
+
const onShouldStartLoadWithRequestCallback = useCallback((shouldStart, url, lockIdentifier) => {
|
|
48
39
|
if (lockIdentifier) {
|
|
49
40
|
NativeModules.RNCWebView.onShouldStartLoadWithRequestCallback(shouldStart, lockIdentifier);
|
|
50
41
|
}
|
|
@@ -52,44 +43,59 @@ var WebViewComponent = forwardRef(function (_a, ref) {
|
|
|
52
43
|
Commands.loadUrl(webViewRef.current, url);
|
|
53
44
|
}
|
|
54
45
|
}, []);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
goBack: function () { return Commands.goBack(webViewRef.current); },
|
|
73
|
-
reload: function () {
|
|
46
|
+
const { onLoadingStart, onShouldStartLoadWithRequest, onMessage, viewState, setViewState, lastErrorEvent, onLoadingError, onLoadingFinish, onLoadingProgress, passesWhitelist } = useWebWiewLogic({
|
|
47
|
+
onLoad,
|
|
48
|
+
onError,
|
|
49
|
+
onLoadEnd,
|
|
50
|
+
onLoadStart,
|
|
51
|
+
onMessageProp,
|
|
52
|
+
startInLoadingState,
|
|
53
|
+
originWhitelist,
|
|
54
|
+
onShouldStartLoadWithRequestProp,
|
|
55
|
+
onShouldStartLoadWithRequestCallback,
|
|
56
|
+
validateMeta,
|
|
57
|
+
validateData,
|
|
58
|
+
});
|
|
59
|
+
useImperativeHandle(ref, () => ({
|
|
60
|
+
goForward: () => Commands.goForward(webViewRef.current),
|
|
61
|
+
goBack: () => Commands.goBack(webViewRef.current),
|
|
62
|
+
reload: () => {
|
|
74
63
|
setViewState('LOADING');
|
|
75
64
|
Commands.reload(webViewRef.current);
|
|
76
65
|
},
|
|
77
|
-
stopLoading:
|
|
78
|
-
postMessage:
|
|
66
|
+
stopLoading: () => Commands.stopLoading(webViewRef.current),
|
|
67
|
+
postMessage: (data) => Commands.postMessage(webViewRef.current, data),
|
|
79
68
|
// injectJavaScript: (data: string) => Commands.injectJavaScript(webViewRef.current, data),
|
|
80
|
-
requestFocus:
|
|
81
|
-
clearFormData:
|
|
82
|
-
clearCache:
|
|
83
|
-
clearHistory:
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
onShouldStartLoadWithRequest
|
|
87
|
-
onMessage
|
|
88
|
-
})
|
|
89
|
-
useEffect(
|
|
69
|
+
requestFocus: () => Commands.requestFocus(webViewRef.current),
|
|
70
|
+
clearFormData: () => Commands.clearFormData(webViewRef.current),
|
|
71
|
+
clearCache: (includeDiskFiles) => Commands.clearCache(webViewRef.current, includeDiskFiles),
|
|
72
|
+
clearHistory: () => Commands.clearHistory(webViewRef.current),
|
|
73
|
+
}), [setViewState, webViewRef]);
|
|
74
|
+
const directEventCallbacks = useMemo(() => ({
|
|
75
|
+
onShouldStartLoadWithRequest,
|
|
76
|
+
onMessage,
|
|
77
|
+
}), [onMessage, onShouldStartLoadWithRequest]);
|
|
78
|
+
useEffect(() => {
|
|
90
79
|
BatchedBridge.registerCallableModule(messagingModuleName, directEventCallbacks);
|
|
91
80
|
}, [messagingModuleName, directEventCallbacks]);
|
|
92
|
-
|
|
81
|
+
const [userAgent, setUserAgent] = useState();
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
getUserAgent().then(setUserAgent);
|
|
84
|
+
}, []);
|
|
85
|
+
if (!userAgent)
|
|
86
|
+
return null; // stop the rendering until userAgent is known
|
|
87
|
+
const version = (_a = userAgent.match(/chrome\/((?:[0-9]+\.)+[0-9]+)/i)) === null || _a === void 0 ? void 0 : _a[1];
|
|
88
|
+
if (!(versionPasses(version, minimumChromeVersion) && versionPasses(version, hardMinimumChromeVersion))) {
|
|
89
|
+
if (UnsupportedVersionComponent) {
|
|
90
|
+
return <UnsupportedVersionComponent />;
|
|
91
|
+
}
|
|
92
|
+
return (<View style={{ alignSelf: 'flex-start' }}>
|
|
93
|
+
<Text style={{ color: 'red' }}>
|
|
94
|
+
Chrome version is outdated and insecure. Update it to continue.
|
|
95
|
+
</Text>
|
|
96
|
+
</View>);
|
|
97
|
+
}
|
|
98
|
+
let otherView = null;
|
|
93
99
|
if (viewState === 'LOADING') {
|
|
94
100
|
otherView = (renderLoading || defaultRenderLoading)();
|
|
95
101
|
}
|
|
@@ -98,10 +104,10 @@ var WebViewComponent = forwardRef(function (_a, ref) {
|
|
|
98
104
|
otherView = (renderError || defaultRenderError)(lastErrorEvent.domain, lastErrorEvent.code, lastErrorEvent.description);
|
|
99
105
|
}
|
|
100
106
|
else if (viewState !== 'IDLE') {
|
|
101
|
-
console.error(
|
|
107
|
+
console.error(`RNCWebView invalid state encountered: ${viewState}`);
|
|
102
108
|
}
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
const webViewStyles = [styles.container, styles.webView, style];
|
|
110
|
+
const webViewContainerStyle = [styles.container, containerStyle];
|
|
105
111
|
if (typeof source !== "number" && source && 'method' in source) {
|
|
106
112
|
if (source.method === 'POST' && source.headers) {
|
|
107
113
|
console.warn('WebView: `source.headers` is not supported when using POST.');
|
|
@@ -110,16 +116,20 @@ var WebViewComponent = forwardRef(function (_a, ref) {
|
|
|
110
116
|
console.warn('WebView: `source.body` is not supported when using GET.');
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
if (typeof source === "object" && 'uri' in source && !passesWhitelist(source.uri)) {
|
|
120
|
+
// eslint-disable-next-line
|
|
121
|
+
source = { uri: "about:blank" };
|
|
122
|
+
}
|
|
123
|
+
const NativeWebView = RNCWebView;
|
|
124
|
+
const webView = <NativeWebView key="webViewKey" {...otherProps} messagingEnabled={typeof onMessageProp === 'function'} messagingModuleName={messagingModuleName} onLoadingError={onLoadingError} onLoadingFinish={onLoadingFinish} onLoadingProgress={onLoadingProgress} onLoadingStart={onLoadingStart} onMessage={onMessage} onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} ref={webViewRef}
|
|
115
125
|
// TODO: find a better way to type this.
|
|
116
|
-
source={
|
|
126
|
+
source={source} style={webViewStyles} overScrollMode={overScrollMode} javaScriptEnabled={javaScriptEnabled} thirdPartyCookiesEnabled={thirdPartyCookiesEnabled} scalesPageToFit={scalesPageToFit} saveFormDataDisabled={saveFormDataDisabled} cacheEnabled={cacheEnabled} androidHardwareAccelerationDisabled={androidHardwareAccelerationDisabled} androidLayerType={androidLayerType} setSupportMultipleWindows={setSupportMultipleWindows} setBuiltInZoomControls={setBuiltInZoomControls} setDisplayZoomControls={setDisplayZoomControls} mixedContentMode={mixedContentMode} nestedScrollEnabled={nestedScrollEnabled} mediaPlaybackRequiresUserAction={mediaPlaybackRequiresUserAction}/>;
|
|
117
127
|
return (<View style={webViewContainerStyle}>
|
|
118
128
|
{webView}
|
|
119
129
|
{otherView}
|
|
120
130
|
</View>);
|
|
121
131
|
});
|
|
122
132
|
// native implementation should return "true" only for Android 5+
|
|
123
|
-
|
|
124
|
-
|
|
133
|
+
const isFileUploadSupported = NativeModules.RNCWebView.isFileUploadSupported();
|
|
134
|
+
const WebView = Object.assign(WebViewComponent, { isFileUploadSupported });
|
|
125
135
|
export default WebView;
|