@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.
@@ -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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
205
- settings.setAllowFileAccessFromFileURLs(false);
206
- setAllowUniversalAccessFromFileURLs(webView, false);
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 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
344
- CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
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 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
393
- // handle unsets of `userAgent` prop as long as device is >= API 17
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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
550
- if (mixedContentMode == null || "never".equals(mixedContentMode)) {
551
- view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
552
- } else if ("always".equals(mixedContentMode)) {
553
- view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
554
- } else if ("compatibility".equals(mixedContentMode)) {
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(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
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("(function () {" +
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
- if (mAllowsFullscreenVideo && activity != null) {
761
- int initialRequestedOrientation = activity.getRequestedOrientation();
762
-
763
- mWebChromeClient = new RNCWebChromeClient(reactContext, webView) {
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
- request.deny();
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, true, false);
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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mVideoView != null && mVideoView.getSystemUiVisibility() != FULLSCREEN_SYSTEM_UI_VISIBILITY) {
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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
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 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
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
+ }