@exodus/react-native-webview 11.26.1-exodus.2 → 11.26.1-exodus.21
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 +123 -269
- 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/android/src/main/java/com/reactnativecommunity/webview/events/{TopHttpErrorEvent.kt → TopNewWindowEvent.kt} +5 -5
- package/apple/RNCWebView.h +1 -8
- package/apple/RNCWebView.m +34 -123
- package/apple/RNCWebViewManager.m +1 -10
- package/index.js +5 -2
- package/lib/WebView.android.js +53 -27
- package/lib/WebView.ios.js +29 -24
- package/lib/WebViewShared.d.ts +14 -14
- package/lib/WebViewShared.js +120 -46
- package/lib/WebViewTypes.d.ts +44 -155
- 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/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,12 @@ 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;
|
|
82
|
+
import com.reactnativecommunity.webview.events.TopOpenWindowEvent;
|
|
84
83
|
import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
|
|
85
84
|
import com.reactnativecommunity.webview.events.TopMessageEvent;
|
|
86
85
|
import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
|
|
87
|
-
import com.reactnativecommunity.webview.events.TopRenderProcessGoneEvent;
|
|
88
86
|
|
|
89
87
|
import org.json.JSONException;
|
|
90
88
|
import org.json.JSONObject;
|
|
@@ -100,6 +98,9 @@ import java.util.HashMap;
|
|
|
100
98
|
import java.util.List;
|
|
101
99
|
import java.util.Locale;
|
|
102
100
|
import java.util.Map;
|
|
101
|
+
import java.util.HashSet;
|
|
102
|
+
import java.util.Set;
|
|
103
|
+
|
|
103
104
|
import java.util.concurrent.atomic.AtomicReference;
|
|
104
105
|
|
|
105
106
|
/**
|
|
@@ -159,14 +160,18 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
159
160
|
protected WebViewConfig mWebViewConfig;
|
|
160
161
|
|
|
161
162
|
protected RNCWebChromeClient mWebChromeClient = null;
|
|
162
|
-
protected boolean mAllowsFullscreenVideo = false;
|
|
163
163
|
protected boolean mAllowsProtectedMedia = false;
|
|
164
164
|
protected @Nullable String mUserAgent = null;
|
|
165
165
|
protected @Nullable String mUserAgentWithApplicationName = null;
|
|
166
166
|
protected @Nullable String mDownloadingMessage = null;
|
|
167
167
|
protected @Nullable String mLackPermissionToDownloadMessage = null;
|
|
168
168
|
|
|
169
|
+
private static Set<String> cameraPermissionOriginWhitelist;
|
|
170
|
+
|
|
169
171
|
public RNCWebViewManager() {
|
|
172
|
+
cameraPermissionOriginWhitelist = new HashSet<>();
|
|
173
|
+
cameraPermissionOriginWhitelist.add("https://alchemy.veriff.com/");
|
|
174
|
+
|
|
170
175
|
mWebViewConfig = new WebViewConfig() {
|
|
171
176
|
public void configWebView(WebView webView) {
|
|
172
177
|
}
|
|
@@ -201,10 +206,9 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
201
206
|
|
|
202
207
|
settings.setAllowFileAccess(false);
|
|
203
208
|
settings.setAllowContentAccess(false);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
209
|
+
settings.setAllowFileAccessFromFileURLs(false);
|
|
210
|
+
settings.setJavaScriptCanOpenWindowsAutomatically(false);
|
|
211
|
+
settings.setAllowUniversalAccessFromFileURLs(false);
|
|
208
212
|
setMixedContentMode(webView, "never");
|
|
209
213
|
|
|
210
214
|
// Fixes broken full-screen modals/galleries due to body height being 0.
|
|
@@ -212,7 +216,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
212
216
|
new LayoutParams(LayoutParams.MATCH_PARENT,
|
|
213
217
|
LayoutParams.MATCH_PARENT));
|
|
214
218
|
|
|
215
|
-
if (ReactBuildConfig.DEBUG
|
|
219
|
+
if (ReactBuildConfig.DEBUG) {
|
|
216
220
|
WebView.setWebContentsDebuggingEnabled(true);
|
|
217
221
|
}
|
|
218
222
|
|
|
@@ -340,9 +344,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
340
344
|
|
|
341
345
|
@ReactProp(name = "thirdPartyCookiesEnabled")
|
|
342
346
|
public void setThirdPartyCookiesEnabled(WebView view, boolean enabled) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
347
|
+
CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
@ReactProp(name = "webviewDebuggingEnabled")
|
|
351
|
+
public void setWebviewDebuggingEnabled(WebView view, boolean value) {
|
|
352
|
+
((RNCWebView) view).setWebContentsDebuggingEnabled(value);
|
|
346
353
|
}
|
|
347
354
|
|
|
348
355
|
@ReactProp(name = "textZoom")
|
|
@@ -371,26 +378,13 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
371
378
|
this.setUserAgentString(view);
|
|
372
379
|
}
|
|
373
380
|
|
|
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
381
|
protected void setUserAgentString(WebView view) {
|
|
388
382
|
if(mUserAgent != null) {
|
|
389
383
|
view.getSettings().setUserAgentString(mUserAgent);
|
|
390
384
|
} else if(mUserAgentWithApplicationName != null) {
|
|
391
385
|
view.getSettings().setUserAgentString(mUserAgentWithApplicationName);
|
|
392
|
-
} else
|
|
393
|
-
// handle unsets of `userAgent` prop
|
|
386
|
+
} else {
|
|
387
|
+
// handle unsets of `userAgent` prop
|
|
394
388
|
view.getSettings().setUserAgentString(WebSettings.getDefaultUserAgent(view.getContext()));
|
|
395
389
|
}
|
|
396
390
|
}
|
|
@@ -401,21 +395,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
401
395
|
view.getSettings().setMediaPlaybackRequiresUserGesture(requires);
|
|
402
396
|
}
|
|
403
397
|
|
|
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
398
|
@ReactProp(name = "saveFormDataDisabled")
|
|
420
399
|
public void setSaveFormDataDisabled(WebView view, boolean disable) {
|
|
421
400
|
view.getSettings().setSaveFormData(!disable);
|
|
@@ -431,16 +410,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
431
410
|
((RNCWebView) view).setInjectedJavaScriptBeforeContentLoaded(injectedJavaScriptBeforeContentLoaded);
|
|
432
411
|
}
|
|
433
412
|
|
|
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
413
|
@ReactProp(name = "messagingEnabled")
|
|
445
414
|
public void setMessagingEnabled(WebView view, boolean enabled) {
|
|
446
415
|
((RNCWebView) view).setMessagingEnabled(enabled);
|
|
@@ -459,11 +428,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
459
428
|
}
|
|
460
429
|
|
|
461
430
|
// Remove all previous cookies
|
|
462
|
-
|
|
463
|
-
CookieManager.getInstance().removeAllCookies(null);
|
|
464
|
-
} else {
|
|
465
|
-
CookieManager.getInstance().removeAllCookie();
|
|
466
|
-
}
|
|
431
|
+
CookieManager.getInstance().removeAllCookies(null);
|
|
467
432
|
|
|
468
433
|
// Disable caching
|
|
469
434
|
view.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
|
|
@@ -546,14 +511,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
546
511
|
|
|
547
512
|
@ReactProp(name = "mixedContentMode")
|
|
548
513
|
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
|
-
}
|
|
514
|
+
if (mixedContentMode == null || "never".equals(mixedContentMode)) {
|
|
515
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
|
|
516
|
+
} else if ("always".equals(mixedContentMode)) {
|
|
517
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
|
518
|
+
} else if ("compatibility".equals(mixedContentMode)) {
|
|
519
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
|
|
557
520
|
}
|
|
558
521
|
}
|
|
559
522
|
|
|
@@ -567,21 +530,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
567
530
|
}
|
|
568
531
|
}
|
|
569
532
|
|
|
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
533
|
@ReactProp(name = "geolocationEnabled")
|
|
586
534
|
public void setGeolocationEnabled(
|
|
587
535
|
WebView view,
|
|
@@ -656,8 +604,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
656
604
|
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
|
|
657
605
|
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
|
|
658
606
|
export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
|
|
659
|
-
export.put(
|
|
660
|
-
export.put(TopRenderProcessGoneEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRenderProcessGone"));
|
|
607
|
+
export.put(TopOpenWindowEvent.EVENT_NAME, MapBuilder.of("registrationName", "onOpenWindow"));
|
|
661
608
|
return export;
|
|
662
609
|
}
|
|
663
610
|
|
|
@@ -699,17 +646,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
699
646
|
RNCWebView reactWebView = (RNCWebView) root;
|
|
700
647
|
JSONObject eventInitDict = new JSONObject();
|
|
701
648
|
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
|
-
"})();");
|
|
649
|
+
reactWebView.evaluateJavascriptWithFallback("document.dispatchEvent(new MessageEvent('message', " + eventInitDict.toString() + "));");
|
|
713
650
|
} catch (JSONException e) {
|
|
714
651
|
throw new RuntimeException(e);
|
|
715
652
|
}
|
|
@@ -756,101 +693,16 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
756
693
|
|
|
757
694
|
protected void setupWebChromeClient(ReactContext reactContext, WebView webView) {
|
|
758
695
|
Activity activity = reactContext.getCurrentActivity();
|
|
696
|
+
if (mWebChromeClient != null) {
|
|
697
|
+
mWebChromeClient.onHideCustomView();
|
|
698
|
+
}
|
|
759
699
|
|
|
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();
|
|
700
|
+
mWebChromeClient = new RNCWebChromeClient(reactContext, webView) {
|
|
701
|
+
@Override
|
|
702
|
+
public Bitmap getDefaultVideoPoster() {
|
|
703
|
+
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
845
704
|
}
|
|
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
|
-
}
|
|
705
|
+
};
|
|
854
706
|
mWebChromeClient.setAllowsProtectedMedia(mAllowsProtectedMedia);
|
|
855
707
|
webView.setWebChromeClient(mWebChromeClient);
|
|
856
708
|
}
|
|
@@ -912,6 +764,8 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
912
764
|
|
|
913
765
|
final WritableMap event = createWebViewEvent(view, url);
|
|
914
766
|
event.putInt("lockIdentifier", lockIdentifier);
|
|
767
|
+
// Android does not raise shouldOverrideUrlLoading for inner frames
|
|
768
|
+
event.putBoolean("isTopFrame", true);
|
|
915
769
|
rncWebView.sendDirectMessage("onShouldStartLoadWithRequest", event);
|
|
916
770
|
|
|
917
771
|
try {
|
|
@@ -1061,60 +915,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1061
915
|
new TopLoadingErrorEvent(webView.getId(), eventData));
|
|
1062
916
|
}
|
|
1063
917
|
|
|
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
918
|
protected void emitFinishEvent(WebView webView, String url) {
|
|
1119
919
|
((RNCWebView) webView).dispatchEvent(
|
|
1120
920
|
webView,
|
|
@@ -1201,6 +1001,20 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1201
1001
|
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
|
|
1202
1002
|
|
|
1203
1003
|
final WebView newWebView = new WebView(view.getContext());
|
|
1004
|
+
newWebView.setWebViewClient(new WebViewClient(){
|
|
1005
|
+
@Override
|
|
1006
|
+
public boolean shouldOverrideUrlLoading (WebView subview, String url) {
|
|
1007
|
+
WritableMap event = Arguments.createMap();
|
|
1008
|
+
event.putString("targetUrl", url);
|
|
1009
|
+
|
|
1010
|
+
((RNCWebView) view).dispatchEvent(
|
|
1011
|
+
view,
|
|
1012
|
+
new TopOpenWindowEvent(view.getId(), event)
|
|
1013
|
+
);
|
|
1014
|
+
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1204
1018
|
final WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
|
1205
1019
|
transport.setWebView(newWebView);
|
|
1206
1020
|
resultMsg.sendToTarget();
|
|
@@ -1241,7 +1055,72 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1241
1055
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
1242
1056
|
@Override
|
|
1243
1057
|
public void onPermissionRequest(final PermissionRequest request) {
|
|
1244
|
-
|
|
1058
|
+
grantedPermissions = new ArrayList<>();
|
|
1059
|
+
|
|
1060
|
+
ArrayList<String> requestedAndroidPermissions = new ArrayList<>();
|
|
1061
|
+
|
|
1062
|
+
for (String requestedResource : request.getResources()) {
|
|
1063
|
+
String androidPermission = null;
|
|
1064
|
+
|
|
1065
|
+
if (requestedResource.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)
|
|
1066
|
+
&& cameraPermissionOriginWhitelist.contains(request.getOrigin().toString())) {
|
|
1067
|
+
androidPermission = Manifest.permission.CAMERA;
|
|
1068
|
+
} else {
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
if (androidPermission != null) {
|
|
1073
|
+
if (ContextCompat.checkSelfPermission(mReactContext,
|
|
1074
|
+
androidPermission) == PackageManager.PERMISSION_GRANTED) {
|
|
1075
|
+
grantedPermissions.add(requestedResource);
|
|
1076
|
+
} else {
|
|
1077
|
+
requestedAndroidPermissions.add(androidPermission);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
// If all the permissions are already granted, send the response to the WebView
|
|
1083
|
+
// synchronously
|
|
1084
|
+
if (requestedAndroidPermissions.isEmpty()) {
|
|
1085
|
+
if (grantedPermissions.isEmpty()) {
|
|
1086
|
+
request.deny();
|
|
1087
|
+
} else {
|
|
1088
|
+
request.grant(grantedPermissions.toArray(new String[0]));
|
|
1089
|
+
}
|
|
1090
|
+
grantedPermissions = null;
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// Otherwise, ask to Android System for native permissions asynchronously
|
|
1095
|
+
PermissionAwareActivity activity = getPermissionAwareActivity();
|
|
1096
|
+
activity.requestPermissions(
|
|
1097
|
+
requestedAndroidPermissions.toArray(new String[0]),
|
|
1098
|
+
COMMON_PERMISSION_REQUEST,
|
|
1099
|
+
new PermissionListener() {
|
|
1100
|
+
@Override
|
|
1101
|
+
public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
1102
|
+
if (requestCode != COMMON_PERMISSION_REQUEST) {
|
|
1103
|
+
return false;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
for (int i = 0; i < permissions.length; i++) {
|
|
1107
|
+
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
|
1108
|
+
if (permissions[i].equals(Manifest.permission.CAMERA)) {
|
|
1109
|
+
grantedPermissions.add(PermissionRequest.RESOURCE_VIDEO_CAPTURE);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
if (grantedPermissions.size() == requestedAndroidPermissions.size()) {
|
|
1115
|
+
request.grant(grantedPermissions.toArray(new String[0]));
|
|
1116
|
+
} else {
|
|
1117
|
+
request.deny();
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
grantedPermissions = null;
|
|
1121
|
+
return true;
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1245
1124
|
}
|
|
1246
1125
|
|
|
1247
1126
|
|
|
@@ -1249,7 +1128,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1249
1128
|
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
|
|
1250
1129
|
|
|
1251
1130
|
// Always deny
|
|
1252
|
-
callback.invoke(origin,
|
|
1131
|
+
callback.invoke(origin, false, false);
|
|
1253
1132
|
|
|
1254
1133
|
}
|
|
1255
1134
|
|
|
@@ -1285,7 +1164,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1285
1164
|
|
|
1286
1165
|
@Override
|
|
1287
1166
|
public void onHostResume() {
|
|
1288
|
-
if (
|
|
1167
|
+
if (mVideoView != null && mVideoView.getSystemUiVisibility() != FULLSCREEN_SYSTEM_UI_VISIBILITY) {
|
|
1289
1168
|
mVideoView.setSystemUiVisibility(FULLSCREEN_SYSTEM_UI_VISIBILITY);
|
|
1290
1169
|
}
|
|
1291
1170
|
}
|
|
@@ -1324,13 +1203,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1324
1203
|
protected @Nullable
|
|
1325
1204
|
String injectedJSBeforeContentLoaded;
|
|
1326
1205
|
|
|
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
1206
|
protected boolean messagingEnabled = false;
|
|
1335
1207
|
protected @Nullable
|
|
1336
1208
|
String messagingModuleName;
|
|
@@ -1447,14 +1319,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1447
1319
|
injectedJSBeforeContentLoaded = js;
|
|
1448
1320
|
}
|
|
1449
1321
|
|
|
1450
|
-
public void setInjectedJavaScriptForMainFrameOnly(boolean enabled) {
|
|
1451
|
-
injectedJavaScriptForMainFrameOnly = enabled;
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
public void setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly(boolean enabled) {
|
|
1455
|
-
injectedJavaScriptBeforeContentLoadedForMainFrameOnly = enabled;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
1322
|
protected RNCWebViewBridge createRNCWebViewBridge(RNCWebView webView) {
|
|
1459
1323
|
return new RNCWebViewBridge(webView);
|
|
1460
1324
|
}
|
|
@@ -1487,17 +1351,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1487
1351
|
}
|
|
1488
1352
|
|
|
1489
1353
|
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
|
-
}
|
|
1354
|
+
evaluateJavascript(script, null);
|
|
1501
1355
|
}
|
|
1502
1356
|
|
|
1503
1357
|
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
|
+
}
|