diff --git a/Libraries/Components/WebView/WebView.android.js b/Libraries/Components/WebView/WebView.android.js index 1735adf63..6a5b7521a 100644 --- a/Libraries/Components/WebView/WebView.android.js +++ b/Libraries/Components/WebView/WebView.android.js @@ -195,6 +195,15 @@ class WebView extends React.Component { * @platform android */ saveFormDataDisabled: PropTypes.bool, + + /** + * Used on Android only, controls whether the given list of URL prefixes should + * make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a + * default activity intent for those URL instead of loading it within the webview. + * Use this to list URLs that WebView cannot handle, e.g. a PDF url. + * @platform android + */ + urlPrefixesForDefaultIntent: PropTypes.arrayOf(PropTypes.string), }; static defaultProps = { @@ -276,6 +285,7 @@ class WebView extends React.Component { allowUniversalAccessFromFileURLs={this.props.allowUniversalAccessFromFileURLs} mixedContentMode={this.props.mixedContentMode} saveFormDataDisabled={this.props.saveFormDataDisabled} + urlPrefixesForDefaultIntent={this.props.urlPrefixesForDefaultIntent} />; return ( diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java index c25987bc9..73b6a4564 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/webview/ReactWebViewManager.java @@ -12,6 +12,7 @@ package com.facebook.react.views.webview; import javax.annotation.Nullable; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -110,6 +111,7 @@ public class ReactWebViewManager extends SimpleViewManager { protected static class ReactWebViewClient extends WebViewClient { protected boolean mLastLoadFailed = false; + protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent; @Override public void onPageFinished(WebView webView, String url) { @@ -137,8 +139,21 @@ public class ReactWebViewManager extends SimpleViewManager { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - if (url.startsWith("http://") || url.startsWith("https://") || - url.startsWith("file://") || url.equals("about:blank")) { + boolean useDefaultIntent = false; + if (mUrlPrefixesForDefaultIntent != null && mUrlPrefixesForDefaultIntent.size() > 0) { + ArrayList urlPrefixesForDefaultIntent = + mUrlPrefixesForDefaultIntent.toArrayList(); + for (Object urlPrefix : urlPrefixesForDefaultIntent) { + if (url.startsWith((String) urlPrefix)) { + useDefaultIntent = true; + break; + } + } + } + + if (!useDefaultIntent && + (url.startsWith("http://") || url.startsWith("https://") || + url.startsWith("file://") || url.equals("about:blank"))) { return false; } else { try { @@ -205,6 +220,10 @@ public class ReactWebViewManager extends SimpleViewManager { event.putBoolean("canGoForward", webView.canGoForward()); return event; } + + public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) { + mUrlPrefixesForDefaultIntent = specialUrls; + } } /** @@ -214,6 +233,7 @@ public class ReactWebViewManager extends SimpleViewManager { protected static class ReactWebView extends WebView implements LifecycleEventListener { protected @Nullable String injectedJS; protected boolean messagingEnabled = false; + protected @Nullable ReactWebViewClient mReactWebViewClient; protected class ReactWebViewBridge { ReactWebView mContext; @@ -254,6 +274,16 @@ public class ReactWebViewManager extends SimpleViewManager { cleanupCallbacksAndDestroy(); } + @Override + public void setWebViewClient(WebViewClient client) { + super.setWebViewClient(client); + mReactWebViewClient = (ReactWebViewClient)client; + } + + public @Nullable ReactWebViewClient getReactWebViewClient() { + return mReactWebViewClient; + } + public void setInjectedJavaScript(@Nullable String js) { injectedJS = js; } @@ -413,7 +443,7 @@ public class ReactWebViewManager extends SimpleViewManager { public void setAllowUniversalAccessFromFileURLs(WebView view, boolean allow) { view.getSettings().setAllowUniversalAccessFromFileURLs(allow); } - + @ReactProp(name = "saveFormDataDisabled") public void setSaveFormDataDisabled(WebView view, boolean disable) { view.getSettings().setSaveFormData(!disable); @@ -507,7 +537,17 @@ public class ReactWebViewManager extends SimpleViewManager { view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } else if ("compatibility".equals(mixedContentMode)) { view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE); - } + } + } + } + + @ReactProp(name = "urlPrefixesForDefaultIntent") + public void setUrlPrefixesForDefaultIntent( + WebView view, + @Nullable ReadableArray urlPrefixesForDefaultIntent) { + ReactWebViewClient client = ((ReactWebView) view).getReactWebViewClient(); + if (client != null && urlPrefixesForDefaultIntent != null) { + client.setUrlPrefixesForDefaultIntent(urlPrefixesForDefaultIntent); } }