Visakeswaran il y a 4 ans
Parent
révision
30ec1b2a47
No account linked to committer's email address

+ 117
- 41
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java Voir le fichier

@@ -1,45 +1,56 @@
1 1
 package com.reactnativecommunity.webview;
2
-
3 2
 import android.annotation.SuppressLint;
4
-import android.annotation.TargetApi;
5 3
 import android.app.DownloadManager;
6
-import android.content.Context;
7
-import android.content.Intent;
8 4
 import android.content.pm.ActivityInfo;
9
-import android.content.pm.PackageManager;
10
-import android.graphics.Bitmap;
11 5
 import android.graphics.Color;
12 6
 import android.Manifest;
13
-import android.net.Uri;
14
-import android.os.Build;
15 7
 import android.os.Environment;
16 8
 import androidx.annotation.RequiresApi;
17 9
 import androidx.core.content.ContextCompat;
18
-import android.text.TextUtils;
19 10
 import android.view.Gravity;
20
-import android.view.View;
21 11
 import android.view.ViewGroup;
22
-import android.view.ViewGroup.LayoutParams;
23 12
 import android.view.WindowManager;
24
-import android.webkit.ConsoleMessage;
25
-import android.webkit.CookieManager;
26 13
 import android.webkit.DownloadListener;
27
-import android.webkit.GeolocationPermissions;
28
-import android.webkit.JavascriptInterface;
29 14
 import android.webkit.PermissionRequest;
30 15
 import android.webkit.URLUtil;
31
-import android.webkit.ValueCallback;
32
-import android.webkit.WebChromeClient;
33 16
 import android.webkit.WebResourceRequest;
34 17
 import android.webkit.WebResourceResponse;
35
-import android.webkit.WebSettings;
36
-import android.webkit.WebView;
37
-import android.webkit.WebViewClient;
38 18
 import android.widget.FrameLayout;
39
-
40 19
 import com.facebook.react.views.scroll.ScrollEvent;
41 20
 import com.facebook.react.views.scroll.ScrollEventType;
42 21
 import com.facebook.react.views.scroll.OnScrollDispatchHelper;
22
+import com.reactnativecommunity.webview.events.TopLoadingErrorEvent;
23
+import com.reactnativecommunity.webview.events.TopHttpErrorEvent;
24
+import com.reactnativecommunity.webview.events.TopLoadingFinishEvent;
25
+import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
26
+import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
27
+import com.reactnativecommunity.webview.events.TopMessageEvent;
28
+import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
29
+import java.net.MalformedURLException;
30
+import java.net.URL;
31
+import android.annotation.TargetApi;
32
+import android.content.ActivityNotFoundException;
33
+import android.content.Context;
34
+import android.content.Intent;
35
+import android.content.pm.PackageManager;
36
+import android.content.pm.ResolveInfo;
37
+import android.graphics.Bitmap;
38
+import android.graphics.Picture;
39
+import android.net.Uri;
40
+import android.os.Build;
41
+import android.text.TextUtils;
42
+import android.view.View;
43
+import android.view.ViewGroup.LayoutParams;
44
+import android.webkit.ConsoleMessage;
45
+import android.webkit.CookieManager;
46
+import android.webkit.GeolocationPermissions;
47
+import android.webkit.JavascriptInterface;
48
+import android.webkit.ValueCallback;
49
+import android.webkit.WebChromeClient;
50
+import android.webkit.WebSettings;
51
+import android.webkit.WebView;
52
+import android.webkit.WebViewClient;
53
+import com.facebook.common.logging.FLog;
43 54
 import com.facebook.react.bridge.Arguments;
44 55
 import com.facebook.react.bridge.LifecycleEventListener;
45 56
 import com.facebook.react.bridge.ReactContext;
@@ -48,6 +59,7 @@ import com.facebook.react.bridge.ReadableMap;
48 59
 import com.facebook.react.bridge.ReadableMapKeySetIterator;
49 60
 import com.facebook.react.bridge.WritableMap;
50 61
 import com.facebook.react.common.MapBuilder;
62
+import com.facebook.react.common.ReactConstants;
51 63
 import com.facebook.react.common.build.ReactBuildConfig;
52 64
 import com.facebook.react.module.annotations.ReactModule;
53 65
 import com.facebook.react.uimanager.SimpleViewManager;
@@ -57,27 +69,23 @@ import com.facebook.react.uimanager.annotations.ReactProp;
57 69
 import com.facebook.react.uimanager.events.ContentSizeChangeEvent;
58 70
 import com.facebook.react.uimanager.events.Event;
59 71
 import com.facebook.react.uimanager.events.EventDispatcher;
60
-import com.reactnativecommunity.webview.events.TopLoadingErrorEvent;
61
-import com.reactnativecommunity.webview.events.TopHttpErrorEvent;
62
-import com.reactnativecommunity.webview.events.TopLoadingFinishEvent;
63
-import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
64
-import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
65
-import com.reactnativecommunity.webview.events.TopMessageEvent;
66
-import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
67
-
68
-import org.json.JSONException;
69
-import org.json.JSONObject;
70
-
72
+// import com.facebook.react.views.webview.events.TopLoadingErrorEvent;
73
+// import com.facebook.react.views.webview.events.TopLoadingFinishEvent;
74
+// import com.facebook.react.views.webview.events.TopLoadingStartEvent;
75
+// import com.facebook.react.views.webview.events.TopMessageEvent;
71 76
 import java.io.UnsupportedEncodingException;
72
-import java.net.MalformedURLException;
73
-import java.net.URL;
77
+import java.net.URISyntaxException;
74 78
 import java.net.URLEncoder;
75 79
 import java.util.ArrayList;
76 80
 import java.util.HashMap;
81
+import java.util.LinkedList;
82
+import java.util.List;
77 83
 import java.util.Locale;
78 84
 import java.util.Map;
79
-
85
+import java.util.regex.Pattern;
80 86
 import javax.annotation.Nullable;
87
+import org.json.JSONException;
88
+import org.json.JSONObject;
81 89
 
82 90
 /**
83 91
  * Manages instances of {@link WebView}
@@ -129,6 +137,10 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
129 137
   // Use `webView.loadUrl("about:blank")` to reliably reset the view
130 138
   // state and release page resources (including any running JavaScript).
131 139
   protected static final String BLANK_URL = "about:blank";
140
+  
141
+  // Intent urls are a type of deeplinks which start with: intent://
142
+  private static final String INTENT_URL_PREFIX = "intent://";
143
+  
132 144
   protected WebViewConfig mWebViewConfig;
133 145
 
134 146
   protected RNCWebChromeClient mWebChromeClient = null;
@@ -739,18 +751,82 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
739 751
           createWebViewEvent(webView, url)));
740 752
     }
741 753
 
754
+
742 755
     @Override
743 756
     public boolean shouldOverrideUrlLoading(WebView view, String url) {
744
-      activeUrl = url;
745
-      dispatchEvent(
746
-        view,
747
-        new TopShouldStartLoadWithRequestEvent(
748
-          view.getId(),
749
-          createWebViewEvent(view, url)));
757
+      if (url.equals(BLANK_URL)) return false;
758
+
759
+      // url blacklisting
760
+      if (mUrlPrefixesForDefaultIntent != null && mUrlPrefixesForDefaultIntent.size() > 0) {
761
+        ArrayList<Object> urlPrefixesForDefaultIntent = mUrlPrefixesForDefaultIntent.toArrayList();
762
+        for (Object urlPrefix : urlPrefixesForDefaultIntent) {
763
+          if (url.startsWith((String) urlPrefix)) {
764
+            launchIntent(view.getContext(), url);
765
+            return true;
766
+          }
767
+        }
768
+      }
769
+
770
+      launchIntent(view.getContext(), url);
750 771
       return true;
751 772
     }
752 773
 
753 774
 
775
+    private void launchIntent(Context context, String url) {
776
+      Intent intent = null;
777
+
778
+      // URLs starting with 'intent://' require special handling.
779
+      if (url.startsWith(INTENT_URL_PREFIX)) {
780
+        try {
781
+          intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
782
+        } catch (URISyntaxException e) {
783
+          FLog.e(ReactConstants.TAG, "Can't parse intent:// URI", e);
784
+        }
785
+      }
786
+
787
+      if (intent != null) {
788
+        // This is needed to prevent security issue where non-exported activities from the same process can be started with intent:// URIs.
789
+        // See: T10607927/S136245
790
+        intent.addCategory(Intent.CATEGORY_BROWSABLE);
791
+        intent.setComponent(null);
792
+        intent.setSelector(null);
793
+
794
+        PackageManager packageManager = context.getPackageManager();
795
+        ResolveInfo info = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
796
+        if (info != null) {
797
+            // App is installed.
798
+            context.startActivity(intent);
799
+        } else {
800
+            String fallbackUrl = intent.getStringExtra("browser_fallback_url");
801
+            intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fallbackUrl));
802
+        }
803
+      } else {
804
+        intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
805
+      }
806
+
807
+      try {
808
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
809
+        intent.addCategory(Intent.CATEGORY_BROWSABLE);
810
+        context.startActivity(intent);
811
+      } catch (ActivityNotFoundException e) {
812
+        FLog.w(ReactConstants.TAG, "activity not found to handle uri scheme for: " + url, e);
813
+      }
814
+    }
815
+
816
+    private boolean shouldHandleURL(List<Pattern> originWhitelist, String url) {
817
+      Uri uri = Uri.parse(url);
818
+      String scheme = uri.getScheme() != null ? uri.getScheme() : "";
819
+      String authority = uri.getAuthority() != null ? uri.getAuthority() : "";
820
+      String urlToCheck = scheme + "://" + authority;
821
+      for (Pattern pattern : originWhitelist) {
822
+        if (pattern.matcher(urlToCheck).matches()) {
823
+          return true;
824
+        }
825
+      }
826
+      return false;
827
+    }
828
+
829
+
754 830
     @TargetApi(Build.VERSION_CODES.N)
755 831
     @Override
756 832
     public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {