@exodus/react-native-webview 11.26.1-exodus.3 → 11.26.1-exodus.31
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 +130 -268
- package/android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java +1 -8
- 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 +49 -125
- package/apple/RNCWebViewManager.m +3 -12
- package/index.js +5 -2
- package/lib/WebView.android.js +53 -26
- package/lib/WebView.ios.js +28 -22
- package/lib/WebViewShared.d.ts +14 -14
- package/lib/WebViewShared.js +140 -43
- package/lib/WebViewTypes.d.ts +43 -155
- package/package.json +2 -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,19 @@ 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
|
+
cameraPermissionOriginWhitelist.add("https://magic.veriff.me/");
|
|
175
|
+
|
|
170
176
|
mWebViewConfig = new WebViewConfig() {
|
|
171
177
|
public void configWebView(WebView webView) {
|
|
172
178
|
}
|
|
@@ -201,10 +207,9 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
201
207
|
|
|
202
208
|
settings.setAllowFileAccess(false);
|
|
203
209
|
settings.setAllowContentAccess(false);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
210
|
+
settings.setAllowFileAccessFromFileURLs(false);
|
|
211
|
+
settings.setJavaScriptCanOpenWindowsAutomatically(false);
|
|
212
|
+
settings.setAllowUniversalAccessFromFileURLs(false);
|
|
208
213
|
setMixedContentMode(webView, "never");
|
|
209
214
|
|
|
210
215
|
// Fixes broken full-screen modals/galleries due to body height being 0.
|
|
@@ -212,7 +217,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
212
217
|
new LayoutParams(LayoutParams.MATCH_PARENT,
|
|
213
218
|
LayoutParams.MATCH_PARENT));
|
|
214
219
|
|
|
215
|
-
if (ReactBuildConfig.DEBUG
|
|
220
|
+
if (ReactBuildConfig.DEBUG) {
|
|
216
221
|
WebView.setWebContentsDebuggingEnabled(true);
|
|
217
222
|
}
|
|
218
223
|
|
|
@@ -340,9 +345,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
340
345
|
|
|
341
346
|
@ReactProp(name = "thirdPartyCookiesEnabled")
|
|
342
347
|
public void setThirdPartyCookiesEnabled(WebView view, boolean enabled) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
348
|
+
CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
@ReactProp(name = "webviewDebuggingEnabled")
|
|
352
|
+
public void setWebviewDebuggingEnabled(WebView view, boolean value) {
|
|
353
|
+
((RNCWebView) view).setWebContentsDebuggingEnabled(value);
|
|
346
354
|
}
|
|
347
355
|
|
|
348
356
|
@ReactProp(name = "textZoom")
|
|
@@ -371,26 +379,13 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
371
379
|
this.setUserAgentString(view);
|
|
372
380
|
}
|
|
373
381
|
|
|
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
382
|
protected void setUserAgentString(WebView view) {
|
|
388
383
|
if(mUserAgent != null) {
|
|
389
384
|
view.getSettings().setUserAgentString(mUserAgent);
|
|
390
385
|
} else if(mUserAgentWithApplicationName != null) {
|
|
391
386
|
view.getSettings().setUserAgentString(mUserAgentWithApplicationName);
|
|
392
|
-
} else
|
|
393
|
-
// handle unsets of `userAgent` prop
|
|
387
|
+
} else {
|
|
388
|
+
// handle unsets of `userAgent` prop
|
|
394
389
|
view.getSettings().setUserAgentString(WebSettings.getDefaultUserAgent(view.getContext()));
|
|
395
390
|
}
|
|
396
391
|
}
|
|
@@ -401,21 +396,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
401
396
|
view.getSettings().setMediaPlaybackRequiresUserGesture(requires);
|
|
402
397
|
}
|
|
403
398
|
|
|
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
399
|
@ReactProp(name = "saveFormDataDisabled")
|
|
420
400
|
public void setSaveFormDataDisabled(WebView view, boolean disable) {
|
|
421
401
|
view.getSettings().setSaveFormData(!disable);
|
|
@@ -431,16 +411,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
431
411
|
((RNCWebView) view).setInjectedJavaScriptBeforeContentLoaded(injectedJavaScriptBeforeContentLoaded);
|
|
432
412
|
}
|
|
433
413
|
|
|
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
414
|
@ReactProp(name = "messagingEnabled")
|
|
445
415
|
public void setMessagingEnabled(WebView view, boolean enabled) {
|
|
446
416
|
((RNCWebView) view).setMessagingEnabled(enabled);
|
|
@@ -459,11 +429,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
459
429
|
}
|
|
460
430
|
|
|
461
431
|
// Remove all previous cookies
|
|
462
|
-
|
|
463
|
-
CookieManager.getInstance().removeAllCookies(null);
|
|
464
|
-
} else {
|
|
465
|
-
CookieManager.getInstance().removeAllCookie();
|
|
466
|
-
}
|
|
432
|
+
CookieManager.getInstance().removeAllCookies(null);
|
|
467
433
|
|
|
468
434
|
// Disable caching
|
|
469
435
|
view.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
|
|
@@ -546,14 +512,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
546
512
|
|
|
547
513
|
@ReactProp(name = "mixedContentMode")
|
|
548
514
|
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
|
-
}
|
|
515
|
+
if (mixedContentMode == null || "never".equals(mixedContentMode)) {
|
|
516
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
|
|
517
|
+
} else if ("always".equals(mixedContentMode)) {
|
|
518
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
|
519
|
+
} else if ("compatibility".equals(mixedContentMode)) {
|
|
520
|
+
view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
|
|
557
521
|
}
|
|
558
522
|
}
|
|
559
523
|
|
|
@@ -567,21 +531,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
567
531
|
}
|
|
568
532
|
}
|
|
569
533
|
|
|
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
534
|
@ReactProp(name = "geolocationEnabled")
|
|
586
535
|
public void setGeolocationEnabled(
|
|
587
536
|
WebView view,
|
|
@@ -656,8 +605,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
656
605
|
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
|
|
657
606
|
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
|
|
658
607
|
export.put(ScrollEventType.getJSEventName(ScrollEventType.SCROLL), MapBuilder.of("registrationName", "onScroll"));
|
|
659
|
-
export.put(
|
|
660
|
-
export.put(TopRenderProcessGoneEvent.EVENT_NAME, MapBuilder.of("registrationName", "onRenderProcessGone"));
|
|
608
|
+
export.put(TopOpenWindowEvent.EVENT_NAME, MapBuilder.of("registrationName", "onOpenWindow"));
|
|
661
609
|
return export;
|
|
662
610
|
}
|
|
663
611
|
|
|
@@ -699,17 +647,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
699
647
|
RNCWebView reactWebView = (RNCWebView) root;
|
|
700
648
|
JSONObject eventInitDict = new JSONObject();
|
|
701
649
|
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
|
-
"})();");
|
|
650
|
+
reactWebView.evaluateJavascriptWithFallback("document.dispatchEvent(new MessageEvent('message', " + eventInitDict.toString() + "));");
|
|
713
651
|
} catch (JSONException e) {
|
|
714
652
|
throw new RuntimeException(e);
|
|
715
653
|
}
|
|
@@ -756,101 +694,16 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
756
694
|
|
|
757
695
|
protected void setupWebChromeClient(ReactContext reactContext, WebView webView) {
|
|
758
696
|
Activity activity = reactContext.getCurrentActivity();
|
|
697
|
+
if (mWebChromeClient != null) {
|
|
698
|
+
mWebChromeClient.onHideCustomView();
|
|
699
|
+
}
|
|
759
700
|
|
|
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();
|
|
701
|
+
mWebChromeClient = new RNCWebChromeClient(reactContext, webView) {
|
|
702
|
+
@Override
|
|
703
|
+
public Bitmap getDefaultVideoPoster() {
|
|
704
|
+
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
845
705
|
}
|
|
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
|
-
}
|
|
706
|
+
};
|
|
854
707
|
mWebChromeClient.setAllowsProtectedMedia(mAllowsProtectedMedia);
|
|
855
708
|
webView.setWebChromeClient(mWebChromeClient);
|
|
856
709
|
}
|
|
@@ -912,6 +765,8 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
912
765
|
|
|
913
766
|
final WritableMap event = createWebViewEvent(view, url);
|
|
914
767
|
event.putInt("lockIdentifier", lockIdentifier);
|
|
768
|
+
// Android does not raise shouldOverrideUrlLoading for inner frames
|
|
769
|
+
event.putBoolean("isTopFrame", true);
|
|
915
770
|
rncWebView.sendDirectMessage("onShouldStartLoadWithRequest", event);
|
|
916
771
|
|
|
917
772
|
try {
|
|
@@ -1061,60 +916,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1061
916
|
new TopLoadingErrorEvent(webView.getId(), eventData));
|
|
1062
917
|
}
|
|
1063
918
|
|
|
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
919
|
protected void emitFinishEvent(WebView webView, String url) {
|
|
1119
920
|
((RNCWebView) webView).dispatchEvent(
|
|
1120
921
|
webView,
|
|
@@ -1201,6 +1002,20 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1201
1002
|
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
|
|
1202
1003
|
|
|
1203
1004
|
final WebView newWebView = new WebView(view.getContext());
|
|
1005
|
+
newWebView.setWebViewClient(new WebViewClient(){
|
|
1006
|
+
@Override
|
|
1007
|
+
public boolean shouldOverrideUrlLoading (WebView subview, String url) {
|
|
1008
|
+
WritableMap event = Arguments.createMap();
|
|
1009
|
+
event.putString("targetUrl", url);
|
|
1010
|
+
|
|
1011
|
+
((RNCWebView) view).dispatchEvent(
|
|
1012
|
+
view,
|
|
1013
|
+
new TopOpenWindowEvent(view.getId(), event)
|
|
1014
|
+
);
|
|
1015
|
+
|
|
1016
|
+
return true;
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1204
1019
|
final WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
|
|
1205
1020
|
transport.setWebView(newWebView);
|
|
1206
1021
|
resultMsg.sendToTarget();
|
|
@@ -1241,7 +1056,79 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1241
1056
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
1242
1057
|
@Override
|
|
1243
1058
|
public void onPermissionRequest(final PermissionRequest request) {
|
|
1244
|
-
|
|
1059
|
+
grantedPermissions = new ArrayList<>();
|
|
1060
|
+
|
|
1061
|
+
ArrayList<String> requestedAndroidPermissions = new ArrayList<>();
|
|
1062
|
+
|
|
1063
|
+
for (String requestedResource : request.getResources()) {
|
|
1064
|
+
String androidPermission = null;
|
|
1065
|
+
|
|
1066
|
+
if (cameraPermissionOriginWhitelist.contains(request.getOrigin().toString())) {
|
|
1067
|
+
if (requestedResource.equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
|
|
1068
|
+
androidPermission = Manifest.permission.CAMERA;
|
|
1069
|
+
} else if (requestedResource.equals(PermissionRequest.RESOURCE_AUDIO_CAPTURE)) {
|
|
1070
|
+
androidPermission = Manifest.permission.RECORD_AUDIO;
|
|
1071
|
+
} else {
|
|
1072
|
+
continue;
|
|
1073
|
+
}
|
|
1074
|
+
} else {
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
if (androidPermission != null) {
|
|
1079
|
+
if (ContextCompat.checkSelfPermission(mReactContext,
|
|
1080
|
+
androidPermission) == PackageManager.PERMISSION_GRANTED) {
|
|
1081
|
+
grantedPermissions.add(requestedResource);
|
|
1082
|
+
} else {
|
|
1083
|
+
requestedAndroidPermissions.add(androidPermission);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// If all the permissions are already granted, send the response to the WebView
|
|
1089
|
+
// synchronously
|
|
1090
|
+
if (requestedAndroidPermissions.isEmpty()) {
|
|
1091
|
+
if (grantedPermissions.isEmpty()) {
|
|
1092
|
+
request.deny();
|
|
1093
|
+
} else {
|
|
1094
|
+
request.grant(grantedPermissions.toArray(new String[0]));
|
|
1095
|
+
}
|
|
1096
|
+
grantedPermissions = null;
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// Otherwise, ask to Android System for native permissions asynchronously
|
|
1101
|
+
PermissionAwareActivity activity = getPermissionAwareActivity();
|
|
1102
|
+
activity.requestPermissions(
|
|
1103
|
+
requestedAndroidPermissions.toArray(new String[0]),
|
|
1104
|
+
COMMON_PERMISSION_REQUEST,
|
|
1105
|
+
new PermissionListener() {
|
|
1106
|
+
@Override
|
|
1107
|
+
public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
1108
|
+
if (requestCode != COMMON_PERMISSION_REQUEST) {
|
|
1109
|
+
return false;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
for (int i = 0; i < permissions.length; i++) {
|
|
1113
|
+
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
|
|
1114
|
+
if (permissions[i].equals(Manifest.permission.CAMERA)) {
|
|
1115
|
+
grantedPermissions.add(PermissionRequest.RESOURCE_VIDEO_CAPTURE);
|
|
1116
|
+
} else if (permissions[i].equals(Manifest.permission.RECORD_AUDIO)) {
|
|
1117
|
+
grantedPermissions.add(PermissionRequest.RESOURCE_AUDIO_CAPTURE);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
if (grantedPermissions.size() == requestedAndroidPermissions.size()) {
|
|
1123
|
+
request.grant(grantedPermissions.toArray(new String[0]));
|
|
1124
|
+
} else {
|
|
1125
|
+
request.deny();
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
grantedPermissions = null;
|
|
1129
|
+
return true;
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1245
1132
|
}
|
|
1246
1133
|
|
|
1247
1134
|
|
|
@@ -1285,7 +1172,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1285
1172
|
|
|
1286
1173
|
@Override
|
|
1287
1174
|
public void onHostResume() {
|
|
1288
|
-
if (
|
|
1175
|
+
if (mVideoView != null && mVideoView.getSystemUiVisibility() != FULLSCREEN_SYSTEM_UI_VISIBILITY) {
|
|
1289
1176
|
mVideoView.setSystemUiVisibility(FULLSCREEN_SYSTEM_UI_VISIBILITY);
|
|
1290
1177
|
}
|
|
1291
1178
|
}
|
|
@@ -1324,13 +1211,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1324
1211
|
protected @Nullable
|
|
1325
1212
|
String injectedJSBeforeContentLoaded;
|
|
1326
1213
|
|
|
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
1214
|
protected boolean messagingEnabled = false;
|
|
1335
1215
|
protected @Nullable
|
|
1336
1216
|
String messagingModuleName;
|
|
@@ -1447,14 +1327,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1447
1327
|
injectedJSBeforeContentLoaded = js;
|
|
1448
1328
|
}
|
|
1449
1329
|
|
|
1450
|
-
public void setInjectedJavaScriptForMainFrameOnly(boolean enabled) {
|
|
1451
|
-
injectedJavaScriptForMainFrameOnly = enabled;
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
public void setInjectedJavaScriptBeforeContentLoadedForMainFrameOnly(boolean enabled) {
|
|
1455
|
-
injectedJavaScriptBeforeContentLoadedForMainFrameOnly = enabled;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
1330
|
protected RNCWebViewBridge createRNCWebViewBridge(RNCWebView webView) {
|
|
1459
1331
|
return new RNCWebViewBridge(webView);
|
|
1460
1332
|
}
|
|
@@ -1487,17 +1359,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
|
|
1487
1359
|
}
|
|
1488
1360
|
|
|
1489
1361
|
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
|
-
}
|
|
1362
|
+
evaluateJavascript(script, null);
|
|
1501
1363
|
}
|
|
1502
1364
|
|
|
1503
1365
|
public void callInjectedJavaScript() {
|
|
@@ -108,13 +108,6 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
|
|
|
108
108
|
@ReactMethod
|
|
109
109
|
public void isFileUploadSupported(final Promise promise) {
|
|
110
110
|
Boolean result = false;
|
|
111
|
-
int current = Build.VERSION.SDK_INT;
|
|
112
|
-
if (current >= Build.VERSION_CODES.LOLLIPOP) {
|
|
113
|
-
result = true;
|
|
114
|
-
}
|
|
115
|
-
if (current >= Build.VERSION_CODES.JELLY_BEAN && current <= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
116
|
-
result = true;
|
|
117
|
-
}
|
|
118
111
|
promise.resolve(result);
|
|
119
112
|
}
|
|
120
113
|
|
|
@@ -212,7 +205,7 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
|
|
|
212
205
|
}
|
|
213
206
|
|
|
214
207
|
// we have one file selected
|
|
215
|
-
if (data.getData() != null && resultCode == RESULT_OK
|
|
208
|
+
if (data.getData() != null && resultCode == RESULT_OK) {
|
|
216
209
|
return WebChromeClient.FileChooserParams.parseResult(resultCode, data);
|
|
217
210
|
}
|
|
218
211
|
|
|
@@ -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
|
+
}
|