Chromium Code Reviews| Index: customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
| diff --git a/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java b/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
| index aea63b5b0e8eb22c07e4072dfa76afe9edce49f2..e8a6887fc8a70535ab48140c44b7ee5077dcbb60 100644 |
| --- a/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
| +++ b/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
| @@ -20,6 +20,7 @@ import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.content.pm.ResolveInfo; |
| +import android.graphics.Bitmap; |
| import android.net.Uri; |
| import android.os.Build; |
| import android.os.Bundle; |
| @@ -28,6 +29,7 @@ import android.support.annotation.NonNull; |
| import android.support.customtabs.CustomTabsIntent; |
| import android.support.customtabs.CustomTabsSession; |
| import android.support.v4.content.ContextCompat; |
| +import android.util.Log; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| @@ -42,6 +44,7 @@ import java.util.List; |
| * You are strongly encouraged to use {@link BrowserActionsIntent.Builder}.</p> |
| */ |
| public class BrowserActionsIntent { |
| + private final static String TAG = "BrowserActions"; |
| private final static String TEST_URL = "https://www.example.com"; |
| /** |
| @@ -83,6 +86,13 @@ public class BrowserActionsIntent { |
| public static final String EXTRA_MENU_ITEMS = |
| "android.support.customtabs.browseractions.extra.MENU_ITEMS"; |
| + /** |
| + * Extra that specifies the PendingIntent to be launched when a browser specified menu item is |
| + * selected. The id of the chosen item will be notified through the data of its Intent. |
| + */ |
| + public static final String EXTRA_SELECTED_ACTION_PENDING_INTENT = |
| + "android.support.customtabs.browseractions.extra.DEFAULT_ACTION"; |
|
Yusuf
2017/07/07 21:36:35
pls change the wording in the actual string also.
ltian
2017/07/10 18:45:55
Oh, sorry I forgot changing it!
|
| + |
| /** |
| * The maximum allowed number of custom items. |
| */ |
| @@ -102,10 +112,24 @@ public class BrowserActionsIntent { |
| public static final int URL_TYPE_FILE = 4; |
| public static final int URL_TYPE_PLUGIN = 5; |
| + /** |
|
Yusuf
2017/07/07 21:36:35
TODO() to find a long term solution for this, sinc
ltian
2017/07/10 18:45:55
Done.
|
| + * Defines the the ids of the browser specified menu items in Browser Actions. |
| + */ |
| + @IntDef({ITEM_INVALID_ITEM, ITEM_OPEN_IN_NEW_TAB, ITEM_OPEN_IN_INCOGNITO, ITEM_DOWNLOAD, |
| + ITEM_COPY, ITEM_SHARE}) |
| + @Retention(RetentionPolicy.SOURCE) |
| + public @interface BrowserActionsItemId {} |
| + public static final int ITEM_INVALID_ITEM = -1; |
| + public static final int ITEM_OPEN_IN_NEW_TAB = 0; |
| + public static final int ITEM_OPEN_IN_INCOGNITO = 1; |
| + public static final int ITEM_DOWNLOAD = 2; |
| + public static final int ITEM_COPY = 3; |
| + public static final int ITEM_SHARE = 4; |
| + |
| /** |
| * An {@link Intent} used to start the Browser Actions Activity. |
| */ |
| - private final Intent mIntent; |
| + public final Intent mIntent; |
| /** |
| * Gets the Intent of {@link BrowserActionsIntent}. |
| @@ -129,6 +153,7 @@ public class BrowserActionsIntent { |
| @BrowserActionsUrlType |
| private int mType; |
| private ArrayList<Bundle> mMenuItems = null; |
| + private PendingIntent mPendingIntent = null; |
|
Yusuf
2017/07/07 21:36:35
mOnItemSelectedPendingIntent
ltian
2017/07/10 18:45:55
Done.
|
| /** |
| * Constructs a {@link BrowserActionsIntent.Builder} object associated with default setting |
| @@ -164,11 +189,22 @@ public class BrowserActionsIntent { |
| "Exceeded maximum toolbar item count of " + MAX_CUSTOM_ITEMS); |
| } |
| for (int i = 0; i < items.size(); i++) { |
| + assert items.get(i).getTitle() != null; |
| + assert items.get(i).getAction() != null; |
| mMenuItems.add(getBundleFromItem(items.get(i))); |
| } |
| return this; |
| } |
| + /** |
| + * Set the PendingIntent to be launched when a a browser specified menu item is selected. |
| + * @param pendingIntent The PendingIntent to be launched. |
| + */ |
| + public Builder setDefaultActions(PendingIntent pendingIntent) { |
|
Yusuf
2017/07/07 21:36:35
default->SelectedAction
DefaultAction really gets
ltian
2017/07/10 18:45:55
Done.
|
| + mPendingIntent = pendingIntent; |
| + return this; |
| + } |
| + |
| /** |
| * Populates a {@link Bundle} to hold a custom item for Browser Actions menu. |
| * @param item A custom item for Browser Actions menu. |
| @@ -192,6 +228,7 @@ public class BrowserActionsIntent { |
| mIntent.putParcelableArrayListExtra(EXTRA_MENU_ITEMS, mMenuItems); |
| PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); |
| mIntent.putExtra(EXTRA_APP_ID, pendingIntent); |
| + mIntent.putExtra(EXTRA_SELECTED_ACTION_PENDING_INTENT, mPendingIntent); |
| return new BrowserActionsIntent(mIntent); |
| } |
| } |
| @@ -204,9 +241,10 @@ public class BrowserActionsIntent { |
| * @param uri The url for Browser Actions menu. |
| */ |
| public static void openBrowserAction(Context context, Uri uri) { |
|
Yusuf
2017/07/07 21:36:35
I would say openBrowserAction(*) types here need s
ltian
2017/07/10 18:45:55
The reason I have launches with BrowserActionInten
|
| - if (hasBrowserActionsIntentHandler(context)) { |
| + List<ResolveInfo> handlers = getBrowserActionsIntentHandlers(context); |
| + if (handlers != null && !handlers.isEmpty()) { |
|
Yusuf
2017/07/07 21:36:35
maybe launchIntent has some of this logic about fa
ltian
2017/07/10 18:45:55
Done.
|
| BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri).build(); |
| - ContextCompat.startActivity(context, intent.getIntent(), null); |
| + launchIntent(context, intent.getIntent(), handlers); |
| } else { |
| openFallbackBrowserActionsMenu( |
| context, uri, URL_TYPE_NONE, new ArrayList<BrowserActionItem>()); |
| @@ -221,33 +259,105 @@ public class BrowserActionsIntent { |
| * @param uri The url for Browser Actions menu. |
| * @param type The type of the url for context menu to be opened. |
| * @param items List of custom items to be added to Browser Actions menu. |
| + * @param pendingIntent The PendingIntent to be launched when a browser specified menu item is |
| + * selected. The browser will perform the PendingIntent so this should only go to a {@link |
| + * BroadcastReceiver}. |
| */ |
| - public static void openBrowserAction( |
| - Context context, Uri uri, int type, ArrayList<BrowserActionItem> items) { |
| - if (hasBrowserActionsIntentHandler(context)) { |
| + public static void openBrowserAction(Context context, Uri uri, int type, |
| + ArrayList<BrowserActionItem> items, PendingIntent pendingIntent) { |
| + List<ResolveInfo> handlers = getBrowserActionsIntentHandlers(context); |
| + if (handlers != null && !handlers.isEmpty()) { |
| BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri) |
| - .setUrlType(type) |
| - .setCustomItems(items) |
| - .build(); |
| - ContextCompat.startActivity(context, intent.getIntent(), null); |
| + .setUrlType(type) |
| + .setCustomItems(items) |
| + .setDefaultActions(pendingIntent) |
| + .build(); |
| + launchIntent(context, intent.getIntent(), handlers); |
| } else { |
| openFallbackBrowserActionsMenu(context, uri, type, items); |
| } |
| } |
| /** |
| - * Check whether any Browser Actions provider is available to handle the {@link |
| + * Open a Browser Actions menu by a {@link BrowserActionsIntent}. |
| + * @param context The context requesting for a Browser Actions menu. |
| + * @param intent The {@link BrowserActionsIntent} holds the setting for Browser Actions menu. |
| + */ |
| + public static void openBrowserAction(Context context, BrowserActionsIntent intent) { |
| + List<ResolveInfo> handlers = getBrowserActionsIntentHandlers(context); |
| + if (handlers != null && !handlers.isEmpty()) { |
| + launchIntent(context, intent.getIntent(), handlers); |
| + } else { |
| + openFallbackBrowserActionsMenu(context, intent); |
| + } |
| + } |
| + |
| + /** |
| + * Open a Browser Actions menu by a {@link Intent}. |
| + * @param context The context requesting for a Browser Actions menu. |
| + * @param intent The {@link Intent} holds the setting for Browser Actions menu. |
| + */ |
| + public static void openBrowserAction(Context context, Intent intent) { |
| + List<ResolveInfo> handlers = getBrowserActionsIntentHandlers(context); |
| + if (handlers != null && !handlers.isEmpty()) { |
| + launchIntent(context, intent, handlers); |
| + } else { |
| + openFallbackBrowserActionsMenu(context, intent); |
| + } |
| + } |
| + |
| + /** |
| + * Launch the Intent to open a Browser Actions menu from list of handler. |
| + * If the default Browser is in the list, the menu will be opened by the default Browser, |
| + * otherwise show a intent picker. |
| + * @param context The context requesting for a Browser Actions menu. |
| + * @param intent The {@link Intent} holds the setting for Browser Actions menu. |
| + * @param handlers List of providers available to handle the intent. |
| + */ |
| + private static void launchIntent(Context context, Intent intent, List<ResolveInfo> handlers) { |
| + if (handlers.size() == 1) { |
| + intent.setPackage(handlers.get(0).activityInfo.packageName); |
| + } else { |
| + Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(TEST_URL)); |
| + ResolveInfo defaultHandler = context.getPackageManager().resolveActivity( |
|
Yusuf
2017/07/07 21:36:35
maybe we can have a shared, getDefaultHandlerForAc
ltian
2017/07/10 18:45:55
Done.
|
| + viewIntent, PackageManager.MATCH_DEFAULT_ONLY); |
| + if (defaultHandler != null) { |
| + String defaultPackageName = defaultHandler.activityInfo.packageName; |
| + for (int i = 0; i < handlers.size(); i++) { |
| + if (defaultPackageName.equals(handlers.get(i).activityInfo.packageName)) { |
| + intent.setPackage(defaultPackageName); |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + ContextCompat.startActivity(context, intent, null); |
| + } |
| + |
| + /** |
| + * Returns a list of Browser Actions providers available to handle the {@link |
| * BrowserActionsIntent}. |
| * @param context The context requesting for a Browser Actions menu. |
| - * @return true If a Browser Actions provider is available handle the intent. |
| + * @return List of Browser Actions providers available to handle the intent. |
| */ |
| - private static boolean hasBrowserActionsIntentHandler(Context context) { |
| + private static List<ResolveInfo> getBrowserActionsIntentHandlers(Context context) { |
| Intent intent = |
| new Intent(BrowserActionsIntent.ACTION_BROWSER_ACTIONS_OPEN, Uri.parse(TEST_URL)); |
| PackageManager pm = context.getPackageManager(); |
| - List<ResolveInfo> resolveInfoList = |
| - pm.queryIntentActivities(intent, PackageManager.MATCH_ALL); |
| - return resolveInfoList.size() > 0 ? true : false; |
| + return pm.queryIntentActivities(intent, PackageManager.MATCH_ALL); |
| + } |
| + |
| + private static void openFallbackBrowserActionsMenu( |
| + Context context, BrowserActionsIntent browserActionsIntent) { |
| + openFallbackBrowserActionsMenu(context, browserActionsIntent.getIntent()); |
| + } |
| + |
| + private static void openFallbackBrowserActionsMenu(Context context, Intent intent) { |
| + Uri uri = intent.getData(); |
| + int type = intent.getIntExtra(EXTRA_TYPE, URL_TYPE_NONE); |
| + ArrayList<Bundle> bundles = intent.getParcelableArrayListExtra(EXTRA_MENU_ITEMS); |
| + List<BrowserActionItem> items = bundles != null ? parseBrowserActionItems(bundles) : null; |
| + openFallbackBrowserActionsMenu(context, uri, type, items); |
| } |
| /** |
| @@ -258,10 +368,39 @@ public class BrowserActionsIntent { |
| * @param items List of custom items to add to Browser Actions menu. |
| */ |
| private static void openFallbackBrowserActionsMenu( |
| - Context context, Uri uri, int type, ArrayList<BrowserActionItem> items) { |
| + Context context, Uri uri, int type, List<BrowserActionItem> items) { |
| return; |
| } |
| + /** |
| + * Gets custom item list for browser action menu. |
| + * @param bundles Data for custom items from {@link BrowserActionsIntent}. |
| + * @return List of {@link BrowserActionItem} |
| + */ |
| + public static List<BrowserActionItem> parseBrowserActionItems(ArrayList<Bundle> bundles) { |
| + List<BrowserActionItem> mActions = new ArrayList<>(); |
| + for (int i = 0; i < bundles.size(); i++) { |
| + Bundle bundle = bundles.get(i); |
| + String title = bundle.getString(BrowserActionsIntent.KEY_TITLE); |
| + PendingIntent action = bundle.getParcelable(BrowserActionsIntent.KEY_ACTION); |
| + Bitmap icon = bundle.getParcelable(BrowserActionsIntent.KEY_ICON); |
| + if (title != null && action != null) { |
| + BrowserActionItem item = new BrowserActionItem(title, action); |
| + if (icon != null) { |
| + item.setIcon(icon); |
| + } |
| + mActions.add(item); |
| + } else if (title != null) { |
| + Log.e(TAG, "Missing action for item: " + i); |
| + } else if (action != null) { |
| + Log.e(TAG, "Missing title for item: " + i); |
| + } else { |
| + Log.e(TAG, "Missing title and action for item: " + i); |
| + } |
| + } |
| + return mActions; |
| + } |
| + |
| /** |
| * Get the package name of the creator application. |
| * @param intent The {@link BrowserActionsIntent}. |