@exodus/react-native-webview 11.26.1-exodus.1 → 11.26.1-exodus.11
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 +28 -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
|
@@ -30,7 +30,6 @@ import android.webkit.DownloadListener;
|
|
|
30
30
|
import android.webkit.GeolocationPermissions;
|
|
31
31
|
import android.webkit.HttpAuthHandler;
|
|
32
32
|
import android.webkit.JavascriptInterface;
|
|
33
|
-
import android.webkit.RenderProcessGoneDetail;
|
|
34
33
|
import android.webkit.SslErrorHandler;
|
|
35
34
|
import android.webkit.PermissionRequest;
|
|
36
35
|
import android.webkit.ValueCallback;
|
|
@@ -78,13 +77,11 @@ import com.facebook.react.uimanager.events.Event;
|
|
|
78
77
|
import com.facebook.react.uimanager.events.EventDispatcher;
|
|
79
78
|
import com.reactnativecommunity.webview.RNCWebViewModule.ShouldOverrideUrlLoadingLock.ShouldOverrideCallbackState;
|
|
80
79
|
import com.reactnativecommunity.webview.events.TopLoadingErrorEvent;
|
|
81
|
-
import com.reactnativecommunity.webview.events.TopHttpErrorEvent;
|
|
82
80
|
import com.reactnativecommunity.webview.events.TopLoadingFinishEvent;
|
|
83
81
|
import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
|
|
84
82
|
import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
|
|
85
83
|
import com.reactnativecommunity.webview.events.TopMessageEvent;
|
|
86
84
|
import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
|
|
87
|
-
import com.reactnativecommunity.webview.events.TopRenderProcessGoneEvent;
|
|
88
85
|
|
|
89
86
|
import org.json.JSONException;
|
|
90
87
|
import org.json.JSONObject;
|
|
@@ -159,7 +156,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
159
156
|
protected WebViewConfig mWebViewConfig;
|
|
160
157
|
|
|
161
158
|
protected RNCWebChromeClient mWebChromeClient = null;
|
|
162
|
-
protected boolean mAllowsFullscreenVideo = false;
|
|
163
159
|
protected boolean mAllowsProtectedMedia = false;
|
|
164
160
|
protected @Nullable String mUserAgent = null;
|
|
165
161
|
protected @Nullable String mUserAgentWithApplicationName = null;
|
|
@@ -201,10 +197,9 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
201
197
|
|
|
202
198
|
settings.setAllowFileAccess(false);
|
|
203
199
|
settings.setAllowContentAccess(false);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
200
|
+
settings.setAllowFileAccessFromFileURLs(false);
|
|
201
|
+
settings.setJavaScriptCanOpenWindowsAutomatically(false);
|
|
202
|
+
settings.setAllowUniversalAccessFromFileURLs(false);
|
|
208
203
|
setMixedContentMode(webView, "never");
|
|
209
204
|
|
|
210
205
|
// Fixes broken full-screen modals/galleries due to body height being 0.
|
|
@@ -212,7 +207,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
212
207
|
new LayoutParams(LayoutParams.MATCH_PARENT,
|
|
213
208
|
LayoutParams.MATCH_PARENT));
|
|
214
209
|
|
|
215
|
-
if (ReactBuildConfig.DEBUG
|
|
210
|
+
if (ReactBuildConfig.DEBUG) {
|
|
216
211
|
WebView.setWebContentsDebuggingEnabled(true);
|
|
217
212
|
}
|
|
218
213
|
|
|
@@ -340,9 +335,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
340
335
|
|
|
341
336
|
@ReactProp(name = "thirdPartyCookiesEnabled")
|
|
342
337
|
public void setThirdPartyCookiesEnabled(WebView view, boolean enabled) {
|
|
343
|
-
|
|
344
|
-
CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
|
|
345
|
-
}
|
|
338
|
+
CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
|
|
346
339
|
}
|
|
347
340
|
|
|
348
341
|
@ReactProp(name = "textZoom")
|
|
@@ -371,26 +364,13 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
371
364
|
this.setUserAgentString(view);
|
|
372
365
|
}
|
|
373
366
|
|
|
374
|
-
@ReactProp(name = "applicationNameForUserAgent")
|
|
375
|
-
public void setApplicationNameForUserAgent(WebView view, @Nullable String applicationName) {
|
|
376
|
-
if(applicationName != null) {
|
|
377
|
-
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
|
378
|
-
String defaultUserAgent = WebSettings.getDefaultUserAgent(view.getContext());
|
|
379
|
-
mUserAgentWithApplicationName = defaultUserAgent + " " + applicationName;
|
|
380
|
-
}
|
|
381
|
-
} else {
|
|
382
|
-
mUserAgentWithApplicationName = null;
|
|
383
|
-
}
|
|
384
|
-
this.setUserAgentString(view);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
367
|
protected void setUserAgentString(WebView view) {
|
|
388
368
|
if(mUserAgent != null) {
|
|
389
369
|
view.getSettings().setUserAgentString(mUserAgent);
|
|
390
370
|
} else if(mUserAgentWithApplicationName != null) {
|
|
391
371
|
view.getSettings().setUserAgentString(mUserAgentWithApplicationName);
|
|
392
|
-
} else
|
|
393
|
-
// handle unsets of `userAgent` prop
|
|
372
|
+
} else {
|
|
373
|
+
// handle unsets of `userAgent` prop
|
|
394
374
|
view.getSettings().setUserAgentString(WebSettings.getDefaultUserAgent(view.getContext()));
|
|
395
375
|
}
|
|
396
376
|
}
|
|
@@ -401,21 +381,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
401
381
|
view.getSettings().setMediaPlaybackRequiresUserGesture(requires);
|
|
402
382
|
}
|
|
403
383
|
|
|
404
|
-
@ReactProp(name = "javaScriptCanOpenWindowsAutomatically")
|
|
405
|
-
public void setJavaScriptCanOpenWindowsAutomatically(WebView view, boolean enabled) {
|
|
406
|
-
view.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
@ReactProp(name = "allowFileAccessFromFileURLs")
|
|
410
|
-
public void setAllowFileAccessFromFileURLs(WebView view, boolean allow) {
|
|
411
|
-
view.getSettings().setAllowFileAccessFromFileURLs(allow);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
@ReactProp(name = "allowUniversalAccessFromFileURLs")
|
|
415
|
-
public void setAllowUniversalAccessFromFileURLs(WebView view, boolean allow) {
|
|
416
|
-
view.getSettings().setAllowUniversalAccessFromFileURLs(allow);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
384
|
@ReactProp(name = "saveFormDataDisabled")
|
|
420
385
|
public void setSaveFormDataDisabled(WebView view, boolean disable) {
|
|
421
386
|
view.getSettings().setSaveFormData(!disable);
|
|
@@ -431,16 +396,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
431
396
|
((RNCWebView) view).setInjectedJavaScriptBeforeContentLoaded(injectedJavaScriptBeforeContentLoaded);
|
|
432
397
|
}
|
|
433
398
|
|
|
434
|
-
@ReactProp(name = "injectedJavaScriptForMainFrameOnly")
|
|
435
|
-
public void setInjectedJavaScriptForMainFrameOnly(WebView view, boolean enabled) {
|
|
436
|
-
((RNCWebView) view).setInjectedJavaScriptForMainFrameOnly(enabled);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
@ReactProp(name = "injectedJavaScriptBeforeContentLoadedForMainFrameOnly")
|
|
440
|
-
public void setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly(WebView view, boolean enabled) {
|
|
441
|
-
((RNCWebView) view).setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly(enabled);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
399
|
@ReactProp(name = "messagingEnabled")
|
|
445
400
|
public void setMessagingEnabled(WebView view, boolean enabled) {
|
|
446
401
|
((RNCWebView) view).setMessagingEnabled(enabled);
|
|
@@ -459,11 +414,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
459
414
|
}
|
|
460
415
|
|
|
461
416
|
// Remove all previous cookies
|
|
462
|
-
|
|
463
|
-
CookieManager.getInstance().removeAllCookies(null);
|
|
464
|
-
} else {
|
|
465
|
-
CookieManager.getInstance().removeAllCookie();
|
|
466
|
-
}
|
|
417
|
+
CookieManager.getInstance().removeAllCookies(null);
|
|
467
418
|
|
|
468
419
|
// Disable caching
|
|
469
420
|
view.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
|
|
@@ -546,14 +497,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
546
497
|
|
|
547
498
|
@ReactProp(name = "mixedContentMode")
|
|
548
499
|
public void setMixedContentMode(WebView view, @Nullable String mixedContentMode) {
|
|
549
|
-
if (
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
|
|
556
|
-
}
|
|
500
|
+
if (mixedContentMode == null || "never".equals(mixedContentMode)) {
|
|
501
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
|
|
502
|
+
} else if ("always".equals(mixedContentMode)) {
|
|
503
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
|
504
|
+
} else if ("compatibility".equals(mixedContentMode)) {
|
|
505
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
|
|
557
506
|
}
|
|
558
507
|
}
|
|
559
508
|
|
|
@@ -567,21 +516,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
567
516
|
}
|
|
568
517
|
}
|
|
569
518
|
|
|
570
|
-
@ReactProp(name = "allowsFullscreenVideo")
|
|
571
|
-
public void setAllowsFullscreenVideo(
|
|
572
|
-
WebView view,
|
|
573
|
-
@Nullable Boolean allowsFullscreenVideo) {
|
|
574
|
-
mAllowsFullscreenVideo = allowsFullscreenVideo != null && allowsFullscreenVideo;
|
|
575
|
-
setupWebChromeClient((ReactContext)view.getContext(), view);
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
@ReactProp(name = "allowFileAccess")
|
|
579
|
-
public void setAllowFileAccess(
|
|
580
|
-
WebView view,
|
|
581
|
-
@Nullable Boolean allowFileAccess) {
|
|
582
|
-
view.getSettings().setAllowFileAccess(allowFileAccess != null && allowFileAccess);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
519
|
@ReactProp(name = "geolocationEnabled")
|
|
586
520
|
public void setGeolocationEnabled(
|
|
587
521
|
WebView view,
|
|
@@ -656,8 +590,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
656
590
|
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
|
|
657
591
|
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
|
|
658
592
|
export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
|
|
659
|
-
export.put(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
|
|
660
|
-
export.put(TopRenderProcessGoneEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRenderProcessGone"));
|
|
661
593
|
return export;
|
|
662
594
|
}
|
|
663
595
|
|
|
@@ -699,17 +631,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
699
631
|
RNCWebView reactWebView = (RNCWebView) root;
|
|
700
632
|
JSONObject eventInitDict = new JSONObject();
|
|
701
633
|
eventInitDict.put("data", args.getString(0));
|
|
702
|
-
reactWebView.evaluateJavascriptWithFallback("(
|
|
703
|
-
"var event;" +
|
|
704
|
-
"var data = " + eventInitDict.toString() + ";" +
|
|
705
|
-
"try {" +
|
|
706
|
-
"event = new MessageEvent('message', data);" +
|
|
707
|
-
"} catch (e) {" +
|
|
708
|
-
"event = document.createEvent('MessageEvent');" +
|
|
709
|
-
"event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" +
|
|
710
|
-
"}" +
|
|
711
|
-
"document.dispatchEvent(event);" +
|
|
712
|
-
"})();");
|
|
634
|
+
reactWebView.evaluateJavascriptWithFallback("document.dispatchEvent(new MessageEvent('message', " + eventInitDict.toString() + "));");
|
|
713
635
|
} catch (JSONException e) {
|
|
714
636
|
throw new RuntimeException(e);
|
|
715
637
|
}
|
|
@@ -756,101 +678,16 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
756
678
|
|
|
757
679
|
protected void setupWebChromeClient(ReactContext reactContext, WebView webView) {
|
|
758
680
|
Activity activity = reactContext.getCurrentActivity();
|
|
681
|
+
if (mWebChromeClient != null) {
|
|
682
|
+
mWebChromeClient.onHideCustomView();
|
|
683
|
+
}
|
|
759
684
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
@Override
|
|
765
|
-
public Bitmap getDefaultVideoPoster() {
|
|
766
|
-
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
@Override
|
|
770
|
-
public void onShowCustomView(View view, CustomViewCallback callback) {
|
|
771
|
-
if (mVideoView != null) {
|
|
772
|
-
callback.onCustomViewHidden();
|
|
773
|
-
return;
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
mVideoView = view;
|
|
777
|
-
mCustomViewCallback = callback;
|
|
778
|
-
|
|
779
|
-
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
|
780
|
-
|
|
781
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
782
|
-
mVideoView.setSystemUiVisibility(FULLSCREEN_SYSTEM_UI_VISIBILITY);
|
|
783
|
-
activity.getWindow().setFlags(
|
|
784
|
-
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
|
785
|
-
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
|
786
|
-
);
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
mVideoView.setBackgroundColor(Color.BLACK);
|
|
790
|
-
|
|
791
|
-
// Since RN's Modals interfere with the View hierarchy
|
|
792
|
-
// we will decide which View to hide if the hierarchy
|
|
793
|
-
// does not match (i.e., the WebView is within a Modal)
|
|
794
|
-
// NOTE: We could use `mWebView.getRootView()` instead of `getRootView()`
|
|
795
|
-
// but that breaks the Modal's styles and layout, so we need this to render
|
|
796
|
-
// in the main View hierarchy regardless
|
|
797
|
-
ViewGroup rootView = getRootView();
|
|
798
|
-
rootView.addView(mVideoView, FULLSCREEN_LAYOUT_PARAMS);
|
|
799
|
-
|
|
800
|
-
// Different root views, we are in a Modal
|
|
801
|
-
if (rootView.getRootView() != mWebView.getRootView()) {
|
|
802
|
-
mWebView.getRootView().setVisibility(View.GONE);
|
|
803
|
-
} else {
|
|
804
|
-
// Same view hierarchy (no Modal), just hide the WebView then
|
|
805
|
-
mWebView.setVisibility(View.GONE);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
mReactContext.addLifecycleEventListener(this);
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
@Override
|
|
812
|
-
public void onHideCustomView() {
|
|
813
|
-
if (mVideoView == null) {
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
// Same logic as above
|
|
818
|
-
ViewGroup rootView = getRootView();
|
|
819
|
-
|
|
820
|
-
if (rootView.getRootView() != mWebView.getRootView()) {
|
|
821
|
-
mWebView.getRootView().setVisibility(View.VISIBLE);
|
|
822
|
-
} else {
|
|
823
|
-
// Same view hierarchy (no Modal)
|
|
824
|
-
mWebView.setVisibility(View.VISIBLE);
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
828
|
-
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
rootView.removeView(mVideoView);
|
|
832
|
-
mCustomViewCallback.onCustomViewHidden();
|
|
833
|
-
|
|
834
|
-
mVideoView = null;
|
|
835
|
-
mCustomViewCallback = null;
|
|
836
|
-
|
|
837
|
-
activity.setRequestedOrientation(initialRequestedOrientation);
|
|
838
|
-
|
|
839
|
-
mReactContext.removeLifecycleEventListener(this);
|
|
840
|
-
}
|
|
841
|
-
};
|
|
842
|
-
} else {
|
|
843
|
-
if (mWebChromeClient != null) {
|
|
844
|
-
mWebChromeClient.onHideCustomView();
|
|
685
|
+
mWebChromeClient = new RNCWebChromeClient(reactContext, webView) {
|
|
686
|
+
@Override
|
|
687
|
+
public Bitmap getDefaultVideoPoster() {
|
|
688
|
+
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
845
689
|
}
|
|
846
|
-
|
|
847
|
-
mWebChromeClient = new RNCWebChromeClient(reactContext, webView) {
|
|
848
|
-
@Override
|
|
849
|
-
public Bitmap getDefaultVideoPoster() {
|
|
850
|
-
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
851
|
-
}
|
|
852
|
-
};
|
|
853
|
-
}
|
|
690
|
+
};
|
|
854
691
|
mWebChromeClient.setAllowsProtectedMedia(mAllowsProtectedMedia);
|
|
855
692
|
webView.setWebChromeClient(mWebChromeClient);
|
|
856
693
|
}
|
|
@@ -912,6 +749,8 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
912
749
|
|
|
913
750
|
final WritableMap event = createWebViewEvent(view, url);
|
|
914
751
|
event.putInt("lockIdentifier", lockIdentifier);
|
|
752
|
+
// Android does not raise shouldOverrideUrlLoading for inner frames
|
|
753
|
+
event.putBoolean("isTopFrame", true);
|
|
915
754
|
rncWebView.sendDirectMessage("onShouldStartLoadWithRequest", event);
|
|
916
755
|
|
|
917
756
|
try {
|
|
@@ -1061,60 +900,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1061
900
|
new TopLoadingErrorEvent(webView.getId(), eventData));
|
|
1062
901
|
}
|
|
1063
902
|
|
|
1064
|
-
@RequiresApi(api = Build.VERSION_CODES.M)
|
|
1065
|
-
@Override
|
|
1066
|
-
public void onReceivedHttpError(
|
|
1067
|
-
WebView webView,
|
|
1068
|
-
WebResourceRequest request,
|
|
1069
|
-
WebResourceResponse errorResponse) {
|
|
1070
|
-
super.onReceivedHttpError(webView, request, errorResponse);
|
|
1071
|
-
|
|
1072
|
-
if (request.isForMainFrame()) {
|
|
1073
|
-
WritableMap eventData = createWebViewEvent(webView, request.getUrl().toString());
|
|
1074
|
-
eventData.putInt("statusCode", errorResponse.getStatusCode());
|
|
1075
|
-
eventData.putString("description", errorResponse.getReasonPhrase());
|
|
1076
|
-
|
|
1077
|
-
((RNCWebView) webView).dispatchEvent(
|
|
1078
|
-
webView,
|
|
1079
|
-
new TopHttpErrorEvent(webView.getId(), eventData));
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
@TargetApi(Build.VERSION_CODES.O)
|
|
1084
|
-
@Override
|
|
1085
|
-
public boolean onRenderProcessGone(WebView webView, RenderProcessGoneDetail detail) {
|
|
1086
|
-
// WebViewClient.onRenderProcessGone was added in O.
|
|
1087
|
-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
|
1088
|
-
return false;
|
|
1089
|
-
}
|
|
1090
|
-
super.onRenderProcessGone(webView, detail);
|
|
1091
|
-
|
|
1092
|
-
if(detail.didCrash()){
|
|
1093
|
-
Log.e(TAG, "The WebView rendering process crashed.");
|
|
1094
|
-
}
|
|
1095
|
-
else{
|
|
1096
|
-
Log.w(TAG, "The WebView rendering process was killed by the system.");
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
// if webView is null, we cannot return any event
|
|
1100
|
-
// since the view is already dead/disposed
|
|
1101
|
-
// still prevent the app crash by returning true.
|
|
1102
|
-
if(webView == null){
|
|
1103
|
-
return true;
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
WritableMap event = createWebViewEvent(webView, webView.getUrl());
|
|
1107
|
-
event.putBoolean("didCrash", detail.didCrash());
|
|
1108
|
-
|
|
1109
|
-
((RNCWebView) webView).dispatchEvent(
|
|
1110
|
-
webView,
|
|
1111
|
-
new TopRenderProcessGoneEvent(webView.getId(), event)
|
|
1112
|
-
);
|
|
1113
|
-
|
|
1114
|
-
// returning false would crash the app.
|
|
1115
|
-
return true;
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
903
|
protected void emitFinishEvent(WebView webView, String url) {
|
|
1119
904
|
((RNCWebView) webView).dispatchEvent(
|
|
1120
905
|
webView,
|
|
@@ -1249,7 +1034,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1249
1034
|
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
|
|
1250
1035
|
|
|
1251
1036
|
// Always deny
|
|
1252
|
-
callback.invoke(origin,
|
|
1037
|
+
callback.invoke(origin, false, false);
|
|
1253
1038
|
|
|
1254
1039
|
}
|
|
1255
1040
|
|
|
@@ -1285,7 +1070,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1285
1070
|
|
|
1286
1071
|
@Override
|
|
1287
1072
|
public void onHostResume() {
|
|
1288
|
-
if (
|
|
1073
|
+
if (mVideoView != null && mVideoView.getSystemUiVisibility() != FULLSCREEN_SYSTEM_UI_VISIBILITY) {
|
|
1289
1074
|
mVideoView.setSystemUiVisibility(FULLSCREEN_SYSTEM_UI_VISIBILITY);
|
|
1290
1075
|
}
|
|
1291
1076
|
}
|
|
@@ -1324,13 +1109,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1324
1109
|
protected @Nullable
|
|
1325
1110
|
String injectedJSBeforeContentLoaded;
|
|
1326
1111
|
|
|
1327
|
-
/**
|
|
1328
|
-
* android.webkit.WebChromeClient fundamentally does not support JS injection into frames other
|
|
1329
|
-
* than the main frame, so these two properties are mostly here just for parity with iOS & macOS.
|
|
1330
|
-
*/
|
|
1331
|
-
protected boolean injectedJavaScriptForMainFrameOnly = true;
|
|
1332
|
-
protected boolean injectedJavaScriptBeforeContentLoadedForMainFrameOnly = true;
|
|
1333
|
-
|
|
1334
1112
|
protected boolean messagingEnabled = false;
|
|
1335
1113
|
protected @Nullable
|
|
1336
1114
|
String messagingModuleName;
|
|
@@ -1447,14 +1225,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1447
1225
|
injectedJSBeforeContentLoaded = js;
|
|
1448
1226
|
}
|
|
1449
1227
|
|
|
1450
|
-
public void setInjectedJavaScriptForMainFrameOnly(boolean enabled) {
|
|
1451
|
-
injectedJavaScriptForMainFrameOnly = enabled;
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
public void setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly(boolean enabled) {
|
|
1455
|
-
injectedJavaScriptBeforeContentLoadedForMainFrameOnly = enabled;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
1228
|
protected RNCWebViewBridge createRNCWebViewBridge(RNCWebView webView) {
|
|
1459
1229
|
return new RNCWebViewBridge(webView);
|
|
1460
1230
|
}
|
|
@@ -1487,17 +1257,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1487
1257
|
}
|
|
1488
1258
|
|
|
1489
1259
|
protected void evaluateJavascriptWithFallback(String script) {
|
|
1490
|
-
|
|
1491
|
-
evaluateJavascript(script, null);
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
try {
|
|
1496
|
-
loadUrl("javascript:" + URLEncoder.encode(script, "UTF-8"));
|
|
1497
|
-
} catch (UnsupportedEncodingException e) {
|
|
1498
|
-
// UTF-8 should always be supported
|
|
1499
|
-
throw new RuntimeException(e);
|
|
1500
|
-
}
|
|
1260
|
+
evaluateJavascript(script, null);
|
|
1501
1261
|
}
|
|
1502
1262
|
|
|
1503
1263
|
public void callInjectedJavaScript() {
|
|
@@ -95,28 +95,6 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
private PermissionListener getWebviewFileDownloaderPermissionListener(String downloadingMessage, String lackPermissionToDownloadMessage) {
|
|
99
|
-
return new PermissionListener() {
|
|
100
|
-
@Override
|
|
101
|
-
public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
102
|
-
switch (requestCode) {
|
|
103
|
-
case FILE_DOWNLOAD_PERMISSION_REQUEST: {
|
|
104
|
-
// If request is cancelled, the result arrays are empty.
|
|
105
|
-
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
|
106
|
-
if (downloadRequest != null) {
|
|
107
|
-
downloadFile(downloadingMessage);
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
Toast.makeText(getCurrentActivity().getApplicationContext(), lackPermissionToDownloadMessage, Toast.LENGTH_LONG).show();
|
|
111
|
-
}
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
98
|
public RNCWebViewModule(ReactApplicationContext reactContext) {
|
|
121
99
|
super(reactContext);
|
|
122
100
|
reactContext.addActivityEventListener(this);
|
|
@@ -130,13 +108,6 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
|
|
|
130
108
|
@ReactMethod
|
|
131
109
|
public void isFileUploadSupported(final Promise promise) {
|
|
132
110
|
Boolean result = false;
|
|
133
|
-
int current = Build.VERSION.SDK_INT;
|
|
134
|
-
if (current >= Build.VERSION_CODES.LOLLIPOP) {
|
|
135
|
-
result = true;
|
|
136
|
-
}
|
|
137
|
-
if (current >= Build.VERSION_CODES.JELLY_BEAN && current <= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
138
|
-
result = true;
|
|
139
|
-
}
|
|
140
111
|
promise.resolve(result);
|
|
141
112
|
}
|
|
142
113
|
|
|
@@ -234,7 +205,7 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
|
|
|
234
205
|
}
|
|
235
206
|
|
|
236
207
|
// we have one file selected
|
|
237
|
-
if (data.getData() != null && resultCode == RESULT_OK
|
|
208
|
+
if (data.getData() != null && resultCode == RESULT_OK) {
|
|
238
209
|
return WebChromeClient.FileChooserParams.parseResult(resultCode, data);
|
|
239
210
|
}
|
|
240
211
|
|
|
@@ -321,21 +292,6 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
|
|
|
321
292
|
Toast.makeText(getCurrentActivity().getApplicationContext(), downloadingMessage, Toast.LENGTH_LONG).show();
|
|
322
293
|
}
|
|
323
294
|
|
|
324
|
-
public boolean grantFileDownloaderPermissions(String downloadingMessage, String lackPermissionToDownloadMessage) {
|
|
325
|
-
// Permission not required for Android Q and above
|
|
326
|
-
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
boolean result = ContextCompat.checkSelfPermission(getCurrentActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
|
331
|
-
if (!result && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
332
|
-
PermissionAwareActivity activity = getPermissionAwareActivity();
|
|
333
|
-
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, FILE_DOWNLOAD_PERMISSION_REQUEST, getWebviewFileDownloaderPermissionListener(downloadingMessage, lackPermissionToDownloadMessage));
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return result;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
295
|
protected boolean needsCameraPermission() {
|
|
340
296
|
boolean needed = false;
|
|
341
297
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package com.reactnativecommunity.webview;
|
|
2
|
+
|
|
3
|
+
import java.util.Arrays;
|
|
4
|
+
import java.util.Collections;
|
|
5
|
+
import java.util.List;
|
|
6
|
+
|
|
7
|
+
import com.facebook.react.ReactPackage;
|
|
8
|
+
import com.facebook.react.bridge.NativeModule;
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
11
|
+
|
|
12
|
+
public class RNCWebViewPackage implements ReactPackage {
|
|
13
|
+
@Override
|
|
14
|
+
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
|
15
|
+
return Arrays.<NativeModule>asList(
|
|
16
|
+
new RNCWebViewModule(reactContext),
|
|
17
|
+
new RNCWebViewUtils(reactContext)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Override
|
|
22
|
+
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
23
|
+
return Arrays.<ViewManager>asList(new RNCWebViewManager());
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package com.reactnativecommunity.webview;
|
|
2
|
+
|
|
3
|
+
import android.webkit.WebView;
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.Promise;
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
7
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
8
|
+
import com.facebook.react.uimanager.ThemedReactContext;
|
|
9
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
10
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
11
|
+
|
|
12
|
+
public class RNCWebViewUtils extends ReactContextBaseJavaModule {
|
|
13
|
+
public static final String NAME = "RNCWebViewUtils";
|
|
14
|
+
|
|
15
|
+
ReactApplicationContext mCallerContext;
|
|
16
|
+
|
|
17
|
+
public RNCWebViewUtils(ReactApplicationContext reactContext) {
|
|
18
|
+
super(reactContext);
|
|
19
|
+
mCallerContext = reactContext;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Override
|
|
23
|
+
public String getName() {
|
|
24
|
+
return NAME;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@ReactMethod
|
|
28
|
+
public void getWebViewDefaultUserAgent(final Promise promise) {
|
|
29
|
+
UiThreadUtil.runOnUiThread(new Runnable() {
|
|
30
|
+
@Override
|
|
31
|
+
public void run() {
|
|
32
|
+
try {
|
|
33
|
+
WebView webView = new WebView(mCallerContext);
|
|
34
|
+
|
|
35
|
+
// in case we ever use our own UA we need to unset it first the get the original
|
|
36
|
+
String currentUA = webView.getSettings().getUserAgentString();
|
|
37
|
+
webView.getSettings().setUserAgentString(null);
|
|
38
|
+
String webViewUA = webView.getSettings().getUserAgentString();
|
|
39
|
+
|
|
40
|
+
// Revert to overriden UA string
|
|
41
|
+
webView.getSettings().setUserAgentString(currentUA);
|
|
42
|
+
|
|
43
|
+
promise.resolve(webViewUA);
|
|
44
|
+
}
|
|
45
|
+
catch (Exception e) {
|
|
46
|
+
promise.reject(NAME, e.getMessage());
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
package/apple/RNCWebView.h
CHANGED
|
@@ -42,15 +42,12 @@ shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *_Nonnull)request
|
|
|
42
42
|
@property (nonatomic, assign) BOOL messagingEnabled;
|
|
43
43
|
@property (nonatomic, copy) NSString * _Nullable injectedJavaScript;
|
|
44
44
|
@property (nonatomic, copy) NSString * _Nullable injectedJavaScriptBeforeContentLoaded;
|
|
45
|
-
@property (nonatomic, assign) BOOL injectedJavaScriptForMainFrameOnly;
|
|
46
|
-
@property (nonatomic, assign) BOOL injectedJavaScriptBeforeContentLoadedForMainFrameOnly;
|
|
47
45
|
@property (nonatomic, assign) BOOL scrollEnabled;
|
|
48
46
|
@property (nonatomic, assign) BOOL sharedCookiesEnabled;
|
|
49
47
|
@property (nonatomic, assign) BOOL autoManageStatusBarEnabled;
|
|
50
48
|
@property (nonatomic, assign) BOOL pagingEnabled;
|
|
51
49
|
@property (nonatomic, assign) CGFloat decelerationRate;
|
|
52
50
|
@property (nonatomic, assign) BOOL allowsInlineMediaPlayback;
|
|
53
|
-
@property (nonatomic, assign) BOOL allowsAirPlayForMediaPlayback;
|
|
54
51
|
@property (nonatomic, assign) BOOL bounces;
|
|
55
52
|
@property (nonatomic, assign) BOOL mediaPlaybackRequiresUserAction;
|
|
56
53
|
#if WEBKIT_IOS_10_APIS_AVAILABLE
|
|
@@ -64,17 +61,12 @@ shouldStartLoadForRequest:(NSMutableDictionary<NSString *, id> *_Nonnull)request
|
|
|
64
61
|
@property (nonatomic, assign) BOOL incognito;
|
|
65
62
|
@property (nonatomic, assign) BOOL useSharedProcessPool;
|
|
66
63
|
@property (nonatomic, copy) NSString * _Nullable userAgent;
|
|
67
|
-
@property (nonatomic, copy) NSString * _Nullable applicationNameForUserAgent;
|
|
68
64
|
@property (nonatomic, assign) BOOL cacheEnabled;
|
|
69
65
|
@property (nonatomic, assign) BOOL javaScriptEnabled;
|
|
70
|
-
@property (nonatomic, assign) BOOL allowFileAccessFromFileURLs;
|
|
71
|
-
@property (nonatomic, assign) BOOL allowUniversalAccessFromFileURLs;
|
|
72
66
|
@property (nonatomic, assign) BOOL allowsLinkPreview;
|
|
73
67
|
@property (nonatomic, assign) BOOL showsHorizontalScrollIndicator;
|
|
74
68
|
@property (nonatomic, assign) BOOL showsVerticalScrollIndicator;
|
|
75
69
|
@property (nonatomic, assign) BOOL directionalLockEnabled;
|
|
76
|
-
@property (nonatomic, assign) BOOL ignoreSilentHardwareSwitch;
|
|
77
|
-
@property (nonatomic, copy) NSString * _Nullable allowingReadAccessToURL;
|
|
78
70
|
@property (nonatomic, copy) NSDictionary * _Nullable basicAuthCredential;
|
|
79
71
|
@property (nonatomic, assign) BOOL pullToRefreshEnabled;
|
|
80
72
|
@property (nonatomic, assign) BOOL enableApplePay;
|