From 41f98342899ce4cd965a7f99b3a7f849b8f73f43 Mon Sep 17 00:00:00 2001 From: jcesarmobile Date: Wed, 6 May 2020 11:39:43 +0200 Subject: [PATCH] feat: Allow plugins to override navigation (#2872) Co-authored-by: Sean Bannigan --- .../main/java/com/getcapacitor/Bridge.java | 13 ++++++++++ .../main/java/com/getcapacitor/Plugin.java | 10 ++++++++ .../Capacitor/CAPBridgeViewController.swift | 25 +++++++++++++++++-- ios/Capacitor/Capacitor/CAPPlugin.h | 7 ++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java index 8254e9e07d..b49bbb8fdd 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java @@ -224,6 +224,19 @@ private void loadWebView() { } public boolean launchIntent(Uri url) { + /* + * Give plugins the chance to handle the url + */ + for (Map.Entry entry : plugins.entrySet()) { + Plugin plugin = entry.getValue().getInstance(); + if (plugin != null) { + Boolean shouldOverrideLoad = plugin.shouldOverrideLoad(url); + if (shouldOverrideLoad != null) { + return shouldOverrideLoad; + } + } + } + if (!url.toString().contains(appUrl) && !appAllowNavigationMask.matches(url.getHost())) { try { Intent openIntent = new Intent(Intent.ACTION_VIEW, url); diff --git a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java index bb9b062823..9ea818fea9 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Plugin.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Plugin.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; @@ -548,6 +549,15 @@ protected void handleOnStop() {} */ protected void handleOnDestroy() {} + /** + * Give the plugins a chance to take control when a URL is about to be loaded in the WebView. + * Returning true causes the WebView to abort loading the URL. + * Returning false causes the WebView to continue loading the URL. + * Returning null will defer to the default Capacitor policy + */ + @SuppressWarnings("unused") + public Boolean shouldOverrideLoad(Uri url) { return null; } + /** * Start a new Activity. * diff --git a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift index b09b3b5ee3..4c315ccd50 100644 --- a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift +++ b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift @@ -252,6 +252,29 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DecidePolicyForNavigationAction.name()), object: navigationAction) let navUrl = navigationAction.request.url! + + /* + * Give plugins the chance to handle the url + */ + if let plugins = bridge?.plugins { + for pluginObject in plugins { + let plugin = pluginObject.value + let selector = NSSelectorFromString("shouldOverrideLoad:") + if plugin.responds(to: selector) { + let shouldOverrideLoad = plugin.shouldOverrideLoad(navigationAction) + if (shouldOverrideLoad != nil) { + if (shouldOverrideLoad == true) { + decisionHandler(.cancel) + return + } else if shouldOverrideLoad == false { + decisionHandler(.allow) + return + } + } + } + } + } + if let allowNavigation = allowNavigationConfig, let requestHost = navUrl.host { for pattern in allowNavigation { if matchHost(host: requestHost, pattern: pattern.lowercased()) { @@ -267,8 +290,6 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr return } - // TODO: Allow plugins to handle this. See - // https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/608d64191405b233c01a939f5755f8b1fdd97f8c/src/ios/CDVWKWebViewEngine.m#L609 decisionHandler(.allow) } diff --git a/ios/Capacitor/Capacitor/CAPPlugin.h b/ios/Capacitor/Capacitor/CAPPlugin.h index b41c4585b3..ae073f2a18 100644 --- a/ios/Capacitor/Capacitor/CAPPlugin.h +++ b/ios/Capacitor/Capacitor/CAPPlugin.h @@ -24,6 +24,13 @@ - (void)addListener:(CAPPluginCall *)call; - (void)removeListener:(CAPPluginCall *)call; - (void)removeAllListeners:(CAPPluginCall *)call; +/** + * Give the plugins a chance to take control when a URL is about to be loaded in the WebView. + * Returning true causes the WebView to abort loading the URL. + * Returning false causes the WebView to continue loading the URL. + * Returning nil will defer to the default Capacitor policy + */ +- (NSNumber *)shouldOverrideLoad:(WKNavigationAction *)navigationAction; // Called after init if the plugin wants to do // some loading so the plugin author doesn't