You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ja...@apache.org on 2018/09/20 20:43:58 UTC

[cordova-plugin-inappbrowser] branch master updated: [CB-10795] Exclude current app from external intent list (#154)

This is an automated email from the ASF dual-hosted git repository.

janpio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-plugin-inappbrowser.git


The following commit(s) were added to refs/heads/master by this push:
     new a078337  [CB-10795] Exclude current app from external intent list (#154)
a078337 is described below

commit a0783378fc901a84294dc66908a91f78014d3fb6
Author: Dan Polivy <da...@cellartracker.com>
AuthorDate: Thu Sep 20 13:43:52 2018 -0700

    [CB-10795] Exclude current app from external intent list (#154)
    
    On Android, if the app defines an intent-filter for a given URL, and
    then tries to use inappbrowser to launch that URL via the _system
    target, the default handler for that intent is the app itself.
    
    That behavior can lead to circular loops, and ultimately is not what the
    developer wants -- the link should be launched in a browser.
    
    Because there is no easy way to find the "default" system browser on a
    device, this solution will do two things:
    1) Check if the app is one of the targets for this intent
    2) If so, create a custom chooser with all other targets, excluding the
    current app.
    
    If the app is not a target, then the current (existing) behavior is
    preserved.
    
    The only real "downside" to this approach is that a default handler can no longer be set for these URLs within the app, and a chooser will be shown each time the user taps a link that opens in a new browser.
    
    Fixes https://issues.apache.org/jira/browse/CB-10795
---
 src/android/InAppBrowser.java | 48 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/src/android/InAppBrowser.java b/src/android/InAppBrowser.java
index 9a695db..92ca3c1 100644
--- a/src/android/InAppBrowser.java
+++ b/src/android/InAppBrowser.java
@@ -19,8 +19,12 @@
 package org.apache.cordova.inappbrowser;
 
 import android.annotation.SuppressLint;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Parcelable;
 import android.provider.Browser;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -71,6 +75,7 @@ import org.json.JSONObject;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.HashMap;
@@ -432,7 +437,8 @@ public class InAppBrowser extends CordovaPlugin {
                 intent.setData(uri);
             }
             intent.putExtra(Browser.EXTRA_APPLICATION_ID, cordova.getActivity().getPackageName());
-            this.cordova.getActivity().startActivity(intent);
+            // CB-10795: Avoid circular loops by preventing it from opening in the current app
+            this.openExternalExcludeCurrentApp(intent);
             return "";
             // not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
         } catch (java.lang.RuntimeException e) {
@@ -442,6 +448,46 @@ public class InAppBrowser extends CordovaPlugin {
     }
 
     /**
+     * Opens the intent, providing a chooser that excludes the current app to avoid
+     * circular loops.
+     */
+    private void openExternalExcludeCurrentApp(Intent intent) {
+        String currentPackage = cordova.getActivity().getPackageName();
+        boolean hasCurrentPackage = false;
+
+        PackageManager pm = cordova.getActivity().getPackageManager();
+        List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
+        ArrayList<Intent> targetIntents = new ArrayList<Intent>();
+
+        for (ResolveInfo ri : activities) {
+            if (!currentPackage.equals(ri.activityInfo.packageName)) {
+                Intent targetIntent = (Intent)intent.clone();
+                targetIntent.setPackage(ri.activityInfo.packageName);
+                targetIntents.add(targetIntent);
+            }
+            else {
+                hasCurrentPackage = true;
+            }
+        }
+
+        // If the current app package isn't a target for this URL, then use
+        // the normal launch behavior
+        if (hasCurrentPackage == false || targetIntents.size() == 0) {
+            this.cordova.getActivity().startActivity(intent);
+        }
+        // If there's only one possible intent, launch it directly
+        else if (targetIntents.size() == 1) {
+            this.cordova.getActivity().startActivity(targetIntents.get(0));
+        }
+        // Otherwise, show a custom chooser without the current app listed
+        else if (targetIntents.size() > 0) {
+            Intent chooser = Intent.createChooser(targetIntents.remove(targetIntents.size()-1), null);
+            chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[] {}));
+            this.cordova.getActivity().startActivity(chooser);
+        }
+    }
+
+    /**
      * Closes the dialog
      */
     public void closeDialog() {


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