@exodus/react-native-webview 11.26.1-exodus.3 → 11.26.1-exodus.30

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,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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
205
- settings.setAllowFileAccessFromFileURLs(false);
206
- setAllowUniversalAccessFromFileURLs(webView, false);
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 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
344
- CookieManager.getInstance().setAcceptThirdPartyCookies(view, enabled);
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 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
393
- // handle unsets of `userAgent` prop as long as device is >= API 17
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
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
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 (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
- }
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(TopHttpErrorEvent.EVENT_NAME, MapBuilder.of("registrationName", "onHttpError"));
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("(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
- "})();");
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
- 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();
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
- request.deny();
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 (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mVideoView != null && mVideoView.getSystemUiVisibility() != FULLSCREEN_SYSTEM_UI_VISIBILITY) {
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
- 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
- }
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 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
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
+ }