cordova-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CB-14188) Callback to decide whether to open link or not.
Date Wed, 03 Oct 2018 22:45:00 GMT

    [ https://issues.apache.org/jira/browse/CB-14188?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16637578#comment-16637578
] 

ASF GitHub Bot commented on CB-14188:
-------------------------------------

brodybits closed pull request #276: CB-14188: Add beforeload event, catching navigation before
it happens
URL: https://github.com/apache/cordova-plugin-inappbrowser/pull/276
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/README.md b/README.md
index eade58a37..9aa1a4382 100644
--- a/README.md
+++ b/README.md
@@ -115,6 +115,7 @@ instance, or the system browser.
     Android supports these additional options:
 
     - __hidden__: set to `yes` to create the browser and load the page, but not show it.
The loadstop event fires when loading is complete. Omit or set to `no` (default) to have the
browser open and load normally.
+    - __beforeload__: set to `yes` to enable the `beforeload` event to modify which pages
are actually loaded in the browser.
     - __clearcache__: set to `yes` to have the browser's cookie cache cleared before the
new window is opened
     - __clearsessioncache__: set to `yes` to have the session cookie cache cleared before
the new window is opened
     - __closebuttoncaption__: set to a string to use as the close button's caption instead
of a X. Note that you need to localize this value yourself.
@@ -137,6 +138,7 @@ instance, or the system browser.
     iOS supports these additional options:
 
     - __hidden__: set to `yes` to create the browser and load the page, but not show it.
The loadstop event fires when loading is complete. Omit or set to `no` (default) to have the
browser open and load normally.
+    - __beforeload__: set to `yes` to enable the `beforeload` event to modify which pages
are actually loaded in the browser.
     - __clearcache__: set to `yes` to have the browser's cookie cache cleared before the
new window is opened
     - __clearsessioncache__: set to `yes` to have the session cookie cache cleared before
the new window is opened    
     - __closebuttoncolor__: set as a valid hex color string, for example: `#00ff00`, to change
from the default __Done__ button's color. Only applicable if toolbar is not disabled.
@@ -217,6 +219,7 @@ The object returned from a call to `cordova.InAppBrowser.open` when the
target i
   - __loadstop__: event fires when the `InAppBrowser` finishes loading a URL.
   - __loaderror__: event fires when the `InAppBrowser` encounters an error when loading a
URL.
   - __exit__: event fires when the `InAppBrowser` window is closed.
+  - __beforeload__: event fires when the `InAppBrowser` decides whether to load an URL or
not (only with option `beforeload=yes`).
 
 - __callback__: the function that executes when the event fires. The function is passed an
`InAppBrowserEvent` object as a parameter.
 
@@ -230,7 +233,7 @@ function showHelp(url) {
 
     var target = "_blank";
 
-    var options = "location=yes,hidden=yes";
+    var options = "location=yes,hidden=yes,beforeload=yes";
 
     inAppBrowserRef = cordova.InAppBrowser.open(url, target, options);
 
@@ -240,6 +243,8 @@ function showHelp(url) {
 
     inAppBrowserRef.addEventListener('loaderror', loadErrorCallBack);
 
+    inAppBrowserRef.addEventListener('beforeload', beforeloadCallBack);
+
 }
 
 function loadStartCallBack() {
@@ -288,6 +293,20 @@ function executeScriptCallBack(params) {
 
 }
 
+function beforeloadCallback(params, callback) {
+
+    if (params.url.startsWith("http://www.example.com/")) {
+
+        // Load this URL in the inAppBrowser.
+        callback(params.url);
+    } else {
+
+        // The callback is not invoked, so the page will not be loaded.
+        $('#status-message').text("This browser only opens pages on http://www.example.com/");
+    }
+
+}
+
 ```
 
 ### InAppBrowserEvent Properties
diff --git a/src/android/InAppBrowser.java b/src/android/InAppBrowser.java
index 92ca3c1a1..93d946089 100644
--- a/src/android/InAppBrowser.java
+++ b/src/android/InAppBrowser.java
@@ -110,6 +110,7 @@ Licensed to the Apache Software Foundation (ASF) under one
     private static final String HIDE_URL = "hideurlbar";
     private static final String FOOTER = "footer";
     private static final String FOOTER_COLOR = "footercolor";
+    private static final String BEFORELOAD = "beforeload";
 
     private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR,
NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
 
@@ -138,6 +139,7 @@ Licensed to the Apache Software Foundation (ASF) under one
     private boolean hideUrlBar = false;
     private boolean showFooter = false;
     private String footerColor = "";
+    private boolean useBeforeload = false;
     private String[] allowedSchemes;
 
     /**
@@ -246,6 +248,20 @@ else if (SYSTEM.equals(target)) {
         else if (action.equals("close")) {
             closeDialog();
         }
+        else if (action.equals("loadAfterBeforeload")) {
+            if (!useBeforeload) {
+              LOG.e(LOG_TAG, "unexpected loadAfterBeforeload called without feature beforeload=yes");
+            }
+            final String url = args.getString(0);
+            this.cordova.getActivity().runOnUiThread(new Runnable() {
+                @SuppressLint("NewApi")
+                @Override
+                public void run() {
+                    ((InAppBrowserClient)inAppWebView.getWebViewClient()).waitForBeforeload
= false;
+                    inAppWebView.loadUrl(url);
+                }
+            });
+        }
         else if (action.equals("injectScriptCode")) {
             String jsWrapper = null;
             if (args.getBoolean(1)) {
@@ -674,6 +690,10 @@ public String showWebPage(final String url, HashMap<String, String>
features) {
             if (footerColorSet != null) {
                 footerColor = footerColorSet;
             }
+            String beforeload = features.get(BEFORELOAD);
+            if (beforeload != null) {
+                useBeforeload = beforeload.equals("yes") ? true : false;
+            }
         }
 
         final CordovaWebView thatWebView = this.webView;
@@ -924,7 +944,7 @@ public void openFileChooser(ValueCallback<Uri> uploadMsg, String
acceptType)
                     }
 
                 });
-                WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
+                WebViewClient client = new InAppBrowserClient(thatWebView, edittext, useBeforeload);
                 inAppWebView.setWebViewClient(client);
                 WebSettings settings = inAppWebView.getSettings();
                 settings.setJavaScriptEnabled(true);
@@ -1085,6 +1105,8 @@ public void onActivityResult(int requestCode, int resultCode, Intent
intent) {
     public class InAppBrowserClient extends WebViewClient {
         EditText edittext;
         CordovaWebView webView;
+        boolean useBeforeload;
+        boolean waitForBeforeload;
 
         /**
          * Constructor.
@@ -1092,9 +1114,11 @@ public void onActivityResult(int requestCode, int resultCode, Intent
intent) {
          * @param webView
          * @param mEditText
          */
-        public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
+        public InAppBrowserClient(CordovaWebView webView, EditText mEditText, boolean useBeforeload)
{
             this.webView = webView;
             this.edittext = mEditText;
+            this.useBeforeload = useBeforeload;
+            this.waitForBeforeload = useBeforeload;
         }
 
         /**
@@ -1107,12 +1131,27 @@ public InAppBrowserClient(CordovaWebView webView, EditText mEditText)
{
          */
         @Override
         public boolean shouldOverrideUrlLoading(WebView webView, String url) {
+            boolean override = false;
+
+            // On first URL change, initiate JS callback. Only after the beforeload event,
continue.
+            if (this.waitForBeforeload) {
+                try {
+                    JSONObject obj = new JSONObject();
+                    obj.put("type", "beforeload");
+                    obj.put("url", url);
+                    sendUpdate(obj, true);
+                    return true;
+                } catch (JSONException ex) {
+                    LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
+                }
+            }
+
             if (url.startsWith(WebView.SCHEME_TEL)) {
                 try {
                     Intent intent = new Intent(Intent.ACTION_DIAL);
                     intent.setData(Uri.parse(url));
                     cordova.getActivity().startActivity(intent);
-                    return true;
+                    override = true;
                 } catch (android.content.ActivityNotFoundException e) {
                     LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
                 }
@@ -1121,7 +1160,7 @@ public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
                     Intent intent = new Intent(Intent.ACTION_VIEW);
                     intent.setData(Uri.parse(url));
                     cordova.getActivity().startActivity(intent);
-                    return true;
+                    override = true;
                 } catch (android.content.ActivityNotFoundException e) {
                     LOG.e(LOG_TAG, "Error with " + url + ": " + e.toString());
                 }
@@ -1152,7 +1191,7 @@ else if (url.startsWith("sms:")) {
                     intent.putExtra("address", address);
                     intent.setType("vnd.android-dir/mms-sms");
                     cordova.getActivity().startActivity(intent);
-                    return true;
+                    override = true;
                 } catch (android.content.ActivityNotFoundException e) {
                     LOG.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
                 }
@@ -1173,7 +1212,7 @@ else if (!url.startsWith("http:") && !url.startsWith("https:")
&& url.matches("^
                                 obj.put("type", "customscheme");
                                 obj.put("url", url);
                                 sendUpdate(obj, true);
-                                return true;
+                                override = true;
                             } catch (JSONException ex) {
                                 LOG.e(LOG_TAG, "Custom Scheme URI passed in has caused a
JSON error.");
                             }
@@ -1182,7 +1221,10 @@ else if (!url.startsWith("http:") && !url.startsWith("https:")
&& url.matches("^
                 }
             }
 
-            return false;
+            if (this.useBeforeload) {
+                this.waitForBeforeload = true;
+            }
+            return override;
         }
 
 
@@ -1304,4 +1346,4 @@ public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler
handler, Str
             super.onReceivedHttpAuthRequest(view, handler, host, realm);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/ios/CDVInAppBrowser.h b/src/ios/CDVInAppBrowser.h
index 66066b9ba..e415f40b8 100644
--- a/src/ios/CDVInAppBrowser.h
+++ b/src/ios/CDVInAppBrowser.h
@@ -30,7 +30,11 @@
 @class CDVInAppBrowserViewController;
 
 @interface CDVInAppBrowser : CDVPlugin {
-  UIWindow * tmpWindow;
+    UIWindow * tmpWindow;
+
+    @private
+    BOOL _useBeforeload;
+    BOOL _waitForBeforeload;
 }
 
 @property (nonatomic, retain) CDVInAppBrowserViewController* inAppBrowserViewController;
@@ -42,6 +46,7 @@
 - (void)injectScriptCode:(CDVInvokedUrlCommand*)command;
 - (void)show:(CDVInvokedUrlCommand*)command;
 - (void)hide:(CDVInvokedUrlCommand*)command;
+- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command;
 
 @end
 
@@ -70,6 +75,7 @@
 @property (nonatomic, assign) BOOL suppressesincrementalrendering;
 @property (nonatomic, assign) BOOL hidden;
 @property (nonatomic, assign) BOOL disallowoverscroll;
+@property (nonatomic, assign) BOOL beforeload;
 
 + (CDVInAppBrowserOptions*)parseOptions:(NSString*)options;
 
diff --git a/src/ios/CDVInAppBrowser.m b/src/ios/CDVInAppBrowser.m
index 0ca3feb15..afb5d215c 100644
--- a/src/ios/CDVInAppBrowser.m
+++ b/src/ios/CDVInAppBrowser.m
@@ -46,6 +46,8 @@ - (void)pluginInitialize
 {
     _previousStatusBarStyle = -1;
     _callbackIdPattern = nil;
+    _useBeforeload = NO;
+    _waitForBeforeload = NO;
 }
 
 - (id)settingForKey:(NSString*)key
@@ -209,6 +211,10 @@ - (void)openInInAppBrowser:(NSURL*)url withOptions:(NSString*)options
         self.inAppBrowserViewController.webView.suppressesIncrementalRendering = browserOptions.suppressesincrementalrendering;
     }
 
+    // use of beforeload event
+    _useBeforeload = browserOptions.beforeload;
+    _waitForBeforeload = browserOptions.beforeload;
+
     [self.inAppBrowserViewController navigateTo:url];
     if (!browserOptions.hidden) {
         [self show:nil];
@@ -304,6 +310,27 @@ - (void)openInSystem:(NSURL*)url
     }
 }
 
+- (void)loadAfterBeforeload:(CDVInvokedUrlCommand*)command
+{
+    NSString* urlStr = [command argumentAtIndex:0];
+
+    if (!_useBeforeload) {
+        NSLog(@"unexpected loadAfterBeforeload called without feature beforeload=yes");
+    }
+    if (self.inAppBrowserViewController == nil) {
+        NSLog(@"Tried to invoke loadAfterBeforeload on IAB after it was closed.");
+        return;
+    }
+    if (urlStr == nil) {
+        NSLog(@"loadAfterBeforeload called with nil argument, ignoring.");
+        return;
+    }
+
+    NSURL* url = [NSURL URLWithString:urlStr];
+    _waitForBeforeload = NO;
+    [self.inAppBrowserViewController navigateTo:url];
+}
+
 // This is a helper method for the inject{Script|Style}{Code|File} API calls, which
 // provides a consistent method for injecting JavaScript code into the document.
 //
@@ -413,6 +440,7 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
 {
     NSURL* url = request.URL;
     BOOL isTopLevelNavigation = [request.URL isEqual:[request mainDocumentURL]];
+    BOOL shouldStart = YES;
 
     // See if the url uses the 'gap-iab' protocol. If so, the host should be the id of a
callback to execute,
     // and the path, if present, should be a JSON-encoded value to pass to the callback.
@@ -440,11 +468,22 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
             return NO;
         }
     }
+
+    // When beforeload=yes, on first URL change, initiate JS callback. Only after the beforeload
event, continue.
+    if (_waitForBeforeload && isTopLevelNavigation) {
+        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                                      messageAsDictionary:@{@"type":@"beforeload",
@"url":[url absoluteString]}];
+        [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
+
+        [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
+        return NO;
+    }
+
     //if is an app store link, let the system handle it, otherwise it fails to load it
-    else if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"])
{
+    if ([[ url scheme] isEqualToString:@"itms-appss"] || [[ url scheme] isEqualToString:@"itms-apps"])
{
         [theWebView stopLoading];
         [self openInSystem:url];
-        return NO;
+        shouldStart = NO;
     }
     else if ((self.callbackId != nil) && isTopLevelNavigation) {
         // Send a loadstart event for each top-level navigation (includes redirects).
@@ -455,7 +494,11 @@ - (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*
         [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
     }
 
-    return YES;
+    if (_useBeforeload && isTopLevelNavigation) {
+        _waitForBeforeload = YES;
+    }
+
+    return shouldStart;
 }
 
 - (void)webViewDidStartLoad:(UIWebView*)theWebView
diff --git a/www/inappbrowser.js b/www/inappbrowser.js
index 3619f173f..7764765ad 100644
--- a/www/inappbrowser.js
+++ b/www/inappbrowser.js
@@ -33,6 +33,7 @@
 
     function InAppBrowser () {
         this.channels = {
+            'beforeload': channel.create('beforeload'),
             'loadstart': channel.create('loadstart'),
             'loadstop': channel.create('loadstop'),
             'loaderror': channel.create('loaderror'),
@@ -44,9 +45,17 @@
     InAppBrowser.prototype = {
         _eventHandler: function (event) {
             if (event && (event.type in this.channels)) {
-                this.channels[event.type].fire(event);
+                if (event.type === 'beforeload') {
+                    this.channels[event.type].fire(event, this._loadAfterBeforeload);
+                } else {
+                    this.channels[event.type].fire(event);
+                }
             }
         },
+        _loadAfterBeforeload: function (strUrl) {
+            strUrl = urlutil.makeAbsolute(strUrl);
+            exec(null, null, 'InAppBrowser', 'loadAfterBeforeload', [strUrl]);
+        },
         close: function (eventname) {
             exec(null, null, 'InAppBrowser', 'close', []);
         },


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Callback to decide whether to open link or not.
> -----------------------------------------------
>
>                 Key: CB-14188
>                 URL: https://issues.apache.org/jira/browse/CB-14188
>             Project: Apache Cordova
>          Issue Type: New Feature
>          Components: cordova-plugin-inappbrowser
>    Affects Versions: 3.0.0
>            Reporter: wvengen
>            Priority: Major
>
> Several times I've found myself wanting to tell inAppBrowser whether it can open a link
in the embedded webview or using the system web browser. It would be great if there's a callback
_before_ loading a page (loadstart is too late there), where I can tell inAppBrowser to load
the page or not.
> CB-14013 introduced AllowedSchemes, but excluded the use of http and https. -It would
be useful to allow intercepting http and https links, e.g. to decide whether to open the link
in the system web browser or not.- At first I thought this mechanism could be used, but because
of the asynchronous nature of Cordova callbacks, this didn't work out, and I added a beforeload
callback. See comment for an example.
> I've submitted a PR -(my approach would be to generate a regexp based on AllowedSchemes
and match the URL on that, instead of the current if logic)-.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@cordova.apache.org
For additional commands, e-mail: issues-help@cordova.apache.org


Mime
View raw message