public class

BrowserActionsIntent

extends java.lang.Object

 java.lang.Object

↳androidx.browser.browseractions.BrowserActionsIntent

Gradle dependencies

compile group: 'androidx.browser', name: 'browser', version: '1.4.0'

  • groupId: androidx.browser
  • artifactId: browser
  • version: 1.4.0

Artifact androidx.browser:browser:1.4.0 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.browser:browser com.android.support:customtabs

Overview

Class holding the and start bundle for a Browser Actions Activity.

Note: The constants below are public for the browser implementation's benefit. You are strongly encouraged to use BrowserActionsIntent.Builder.

Summary

Fields
public static final java.lang.StringACTION_BROWSER_ACTIONS_OPEN

Indicates that the user explicitly opted out of Browser Actions in the calling application.

public static final java.lang.StringEXTRA_APP_ID

Extra that specifies PendingIntent indicating which Application sends the BrowserActionsIntent.

public static final java.lang.StringEXTRA_MENU_ITEMS

Extra that specifies List used for adding custom items to the Browser Actions menu.

public static final java.lang.StringEXTRA_SELECTED_ACTION_PENDING_INTENT

Extra that specifies the PendingIntent to be launched when a browser specified menu item is selected.

public static final java.lang.StringEXTRA_TYPE

Extra that specifies the type of url for the Browser Actions menu.

public static final intITEM_COPY

public static final intITEM_DOWNLOAD

public static final intITEM_INVALID_ITEM

public static final intITEM_OPEN_IN_INCOGNITO

public static final intITEM_OPEN_IN_NEW_TAB

public static final intITEM_SHARE

public static final java.lang.StringKEY_ACTION

Extra PendingIntent to be launched when a custom item is selected in the Browser Actions menu.

public static final java.lang.StringKEY_ICON_ID

Extra resource id that specifies the icon of a custom item shown in the Browser Actions menu.

public static final java.lang.StringKEY_TITLE

Extra string that specifies the title of a custom item shown in the Browser Actions menu.

public static final intMAX_CUSTOM_ITEMS

The maximum allowed number of custom items.

public static final intURL_TYPE_AUDIO

public static final intURL_TYPE_FILE

public static final intURL_TYPE_IMAGE

public static final intURL_TYPE_NONE

public static final intURL_TYPE_PLUGIN

public static final intURL_TYPE_VIDEO

Methods
public static java.util.List<ResolveInfo>getBrowserActionsIntentHandlers(Context context)

Returns a list of Browser Actions providers available to handle the BrowserActionsIntent.

public static java.lang.StringgetCreatorPackageName(Intent intent)

public IntentgetIntent()

Gets the Intent of BrowserActionsIntent.

public static java.lang.StringgetUntrustedCreatorPackageName(Intent intent)

Get the package name of the creator application.

public static voidlaunchIntent(Context context, Intent intent)

Launch an Intent to open a Browser Actions menu.

public static voidopenBrowserAction(Context context, Uri uri)

Construct a BrowserActionsIntent with default settings and launch it to open a Browser Actions menu.

public static voidopenBrowserAction(Context context, Uri uri, int type, java.util.ArrayList<BrowserActionItem> items, PendingIntent pendingIntent)

Construct a BrowserActionsIntent with custom settings and launch it to open a Browser Actions menu.

public static java.util.List<BrowserActionItem>parseBrowserActionItems(java.util.ArrayList<Bundle> bundles)

Gets custom item list for browser action menu.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final java.lang.String EXTRA_APP_ID

Extra that specifies PendingIntent indicating which Application sends the BrowserActionsIntent.

Note: The PendingIntent is self-reported and untrusted, sending application can modify it to use PendingIntent from other apps. This would return the package name from the app who creates the PendintIntent.

public static final java.lang.String ACTION_BROWSER_ACTIONS_OPEN

Indicates that the user explicitly opted out of Browser Actions in the calling application.

public static final java.lang.String KEY_ICON_ID

Extra resource id that specifies the icon of a custom item shown in the Browser Actions menu.

public static final java.lang.String KEY_TITLE

Extra string that specifies the title of a custom item shown in the Browser Actions menu.

public static final java.lang.String KEY_ACTION

Extra PendingIntent to be launched when a custom item is selected in the Browser Actions menu.

public static final java.lang.String EXTRA_TYPE

Extra that specifies the type of url for the Browser Actions menu.

public static final java.lang.String EXTRA_MENU_ITEMS

Extra that specifies List used for adding custom items to the Browser Actions menu.

public static final java.lang.String EXTRA_SELECTED_ACTION_PENDING_INTENT

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 int MAX_CUSTOM_ITEMS

The maximum allowed number of custom items.

public static final int URL_TYPE_NONE

public static final int URL_TYPE_IMAGE

public static final int URL_TYPE_VIDEO

public static final int URL_TYPE_AUDIO

public static final int URL_TYPE_FILE

public static final int URL_TYPE_PLUGIN

public static final int ITEM_INVALID_ITEM

public static final int ITEM_OPEN_IN_NEW_TAB

public static final int ITEM_OPEN_IN_INCOGNITO

public static final int ITEM_DOWNLOAD

public static final int ITEM_COPY

public static final int ITEM_SHARE

Methods

public Intent getIntent()

Gets the Intent of BrowserActionsIntent.

Returns:

the Intent of BrowserActionsIntent.

public static void openBrowserAction(Context context, Uri uri)

Construct a BrowserActionsIntent with default settings and launch it to open a Browser Actions menu.

Parameters:

context: The context requesting for a Browser Actions menu.
uri: The url for Browser Actions menu.

public static void openBrowserAction(Context context, Uri uri, int type, java.util.ArrayList<BrowserActionItem> items, PendingIntent pendingIntent)

Construct a BrowserActionsIntent with custom settings and launch it to open a Browser Actions menu.

Parameters:

context: The context requesting for a Browser Actions menu.
uri: The url for Browser Actions menu.
type: The type of the url for context menu to be opened.
items: List of custom items to be added to Browser Actions menu.
pendingIntent: The PendingIntent to be launched when a browser specified menu item is selected.

public static void launchIntent(Context context, Intent intent)

Launch an Intent to open a Browser Actions menu. It first checks if any Browser Actions provider is available to create the menu. If the default Browser supports Browser Actions, menu will be opened by the default Browser, otherwise show a intent picker. If not provider, a Browser Actions menu is opened locally from support library.

Parameters:

context: The context requesting for a Browser Actions menu.
intent: The holds the setting for Browser Actions menu.

public static java.util.List<ResolveInfo> getBrowserActionsIntentHandlers(Context context)

Returns a list of Browser Actions providers available to handle the BrowserActionsIntent.

Parameters:

context: The context requesting for a Browser Actions menu.

Returns:

List of Browser Actions providers available to handle the intent.

public static java.util.List<BrowserActionItem> parseBrowserActionItems(java.util.ArrayList<Bundle> bundles)

Gets custom item list for browser action menu.

Parameters:

bundles: Data for custom items from BrowserActionsIntent.

Returns:

List of BrowserActionItem

public static java.lang.String getUntrustedCreatorPackageName(Intent intent)

Get the package name of the creator application.

Note: This is self-reported and could be untrusted. Intent sender can modify it to return the package name from a different application.

Parameters:

intent: The BrowserActionsIntent.

Returns:

The creator package name.

public static java.lang.String getCreatorPackageName(Intent intent)

Deprecated: This return value of this method cannot be trusted, it is kept around for compatibility. Use BrowserActionsIntent.getUntrustedCreatorPackageName(Intent), or an alternative method if you rely on the return value.

Source

/*
 * Copyright 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.browser.browseractions;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;

import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;

import androidx.annotation.DrawableRes;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.core.content.ContextCompat;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Class holding the {@link Intent} and start bundle for a Browser Actions Activity.
 *
 * <p>
 * <strong>Note:</strong> The constants below are public for the browser implementation's benefit.
 * You are strongly encouraged to use {@link BrowserActionsIntent.Builder}.
 *
 * @deprecated Browser Actions are deprecated as of release 1.2.0.
 */
@SuppressWarnings("deprecation")
@Deprecated
public class BrowserActionsIntent {
    private static final String TAG = "BrowserActions";
    // Used to verify that an URL intent handler exists.
    private static final String TEST_URL = "https://www.example.com";

    /**
     * Extra that specifies {@link PendingIntent} indicating which Application sends the {@link
     * BrowserActionsIntent}.
     * <p>
     * <strong>Note:</strong> The PendingIntent is self-reported and untrusted, sending application
     * can modify it to use PendingIntent from other apps. This would return the package name from
     * the app who creates the PendintIntent.
     */
    public static final String EXTRA_APP_ID = "androidx.browser.browseractions.APP_ID";

    /**
     * Indicates that the user explicitly opted out of Browser Actions in the calling application.
     */
    public static final String ACTION_BROWSER_ACTIONS_OPEN =
            "androidx.browser.browseractions.browser_action_open";

    /**
     * Extra resource id that specifies the icon of a custom item shown in the Browser Actions menu.
     */
    public static final String KEY_ICON_ID = "androidx.browser.browseractions.ICON_ID";

    /**
     * Extra {@link Uri} that specifies location of file for the icon of a custom item shown in the
     * Browser Actions menu.
     */
    private static final String KEY_ICON_URI = "androidx.browser.browseractions.ICON_URI";

    /**
     * Extra string that specifies the title of a custom item shown in the Browser Actions menu.
     */
    public static final String KEY_TITLE = "androidx.browser.browseractions.TITLE";

    /**
     * Extra PendingIntent to be launched when a custom item is selected in the Browser Actions
     * menu.
     */
    public static final String KEY_ACTION = "androidx.browser.browseractions.ACTION";

    /**
     * Extra that specifies the type of url for the Browser Actions menu.
     */
    public static final String EXTRA_TYPE = "androidx.browser.browseractions.extra.TYPE";

    /**
     * Extra that specifies List<Bundle> used for adding custom items to the Browser Actions menu.
     */
    public static final String EXTRA_MENU_ITEMS =
            "androidx.browser.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 =
            "androidx.browser.browseractions.extra.SELECTED_ACTION_PENDING_INTENT";

    /**
     * The maximum allowed number of custom items.
     */
    @SuppressLint("MinMaxConstant")
    public static final int MAX_CUSTOM_ITEMS = 5;

    /**
     * Defines the types of url for Browser Actions menu.
     */
    /** @hide */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @IntDef({URL_TYPE_NONE, URL_TYPE_IMAGE, URL_TYPE_VIDEO, URL_TYPE_AUDIO, URL_TYPE_FILE,
            URL_TYPE_PLUGIN})
    @Retention(RetentionPolicy.SOURCE)
    public @interface BrowserActionsUrlType {}
    public static final int URL_TYPE_NONE = 0;
    public static final int URL_TYPE_IMAGE = 1;
    public static final int URL_TYPE_VIDEO = 2;
    public static final int URL_TYPE_AUDIO = 3;
    public static final int URL_TYPE_FILE = 4;
    public static final int URL_TYPE_PLUGIN = 5;

    /**
     * Defines the the ids of the browser specified menu items in Browser Actions.
     * TODO(ltian): A long term solution need, since other providers might have customized menus.
     */
    /** @hide */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @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.
     */
    @NonNull private final Intent mIntent;

    /**
     * Gets the Intent of {@link BrowserActionsIntent}.
     * @return the Intent of {@link BrowserActionsIntent}.
     */
    @NonNull public Intent getIntent() {
        return mIntent;
    }

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    BrowserActionsIntent(@NonNull Intent intent) {
        this.mIntent = intent;
    }

    /** @hide */
    @VisibleForTesting
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    interface BrowserActionsFallDialogListener {
        void onDialogShown();
    }

    @Nullable
    private static BrowserActionsFallDialogListener sDialogListenter;

    /**
     * Builder class for opening a Browser Actions context menu.
     */
    public static final class Builder {
        private final Intent mIntent = new Intent(BrowserActionsIntent.ACTION_BROWSER_ACTIONS_OPEN);
        private Context mContext;
        private Uri mUri;
        @BrowserActionsUrlType
        private int mType = URL_TYPE_NONE;
        private ArrayList<Bundle> mMenuItems = new ArrayList<>();
        @Nullable private PendingIntent mOnItemSelectedPendingIntent = null;
        private List<Uri> mImageUris = new ArrayList<>();

        /**
         * Constructs a {@link BrowserActionsIntent.Builder} object associated with default setting
         * for a selected url.
         * @param context The context requesting the Browser Actions context menu.
         * @param uri The selected url for Browser Actions menu.
         */
        public Builder(@NonNull Context context, @NonNull Uri uri) {
            mContext = context;
            mUri = uri;
        }

        /**
         * Sets the type of Browser Actions context menu.
         * @param type The type of url.
         */
        @NonNull
        public Builder setUrlType(@BrowserActionsUrlType int type) {
            mType = type;
            return this;
        }

        /**
         * Sets the custom items list.
         * Only maximum MAX_CUSTOM_ITEMS custom items are allowed,
         * otherwise throws an {@link IllegalStateException}.
         * @param items The list of {@link BrowserActionItem} for custom items.
         */
        @NonNull
        public Builder setCustomItems(@NonNull ArrayList<BrowserActionItem> items) {
            if (items.size() > MAX_CUSTOM_ITEMS) {
                throw new IllegalStateException(
                        "Exceeded maximum toolbar item count of " + MAX_CUSTOM_ITEMS);
            }
            for (int i = 0; i < items.size(); i++) {
                if (TextUtils.isEmpty(items.get(i).getTitle())
                        || items.get(i).getAction() == null) {
                    throw new IllegalArgumentException(
                            "Custom item should contain a non-empty title and non-null intent.");
                } else {
                    mMenuItems.add(getBundleFromItem(items.get(i)));
                    if (items.get(i).getIconUri() != null) {
                        mImageUris.add(items.get(i).getIconUri());
                    }
                }
            }
            return this;
        }

        /**
         * Sets the custom items list.
         * Only maximum MAX_CUSTOM_ITEMS custom items are allowed,
         * otherwise throws an {@link IllegalStateException}.
         * @param items The varargs of {@link BrowserActionItem} for custom items.
         */
        @NonNull
        public Builder setCustomItems(@NonNull BrowserActionItem... items) {
            return setCustomItems(new ArrayList<BrowserActionItem>(Arrays.asList(items)));
        }

        /**
         * Set the PendingIntent to be launched when a a browser specified menu item is selected.
         * @param onItemSelectedPendingIntent The PendingIntent to be launched.
         */
        @NonNull
        public Builder setOnItemSelectedAction(@NonNull PendingIntent onItemSelectedPendingIntent) {
            mOnItemSelectedPendingIntent = onItemSelectedPendingIntent;
            return this;
        }

        /**
         * Populates a {@link Bundle} to hold a custom item for Browser Actions menu.
         * @param item A custom item for Browser Actions menu.
         * @return The Bundle of custom item.
         */
        @NonNull
        private Bundle getBundleFromItem(@NonNull BrowserActionItem item) {
            Bundle bundle = new Bundle();
            bundle.putString(KEY_TITLE, item.getTitle());
            bundle.putParcelable(KEY_ACTION, item.getAction());
            if (item.getIconId() != 0) bundle.putInt(KEY_ICON_ID, item.getIconId());
            if (item.getIconUri() != null) bundle.putParcelable(KEY_ICON_URI, item.getIconUri());
            return bundle;
        }

        /**
         * Combines all the options that have been set and returns a new {@link
         * BrowserActionsIntent} object.
         */
        @NonNull
        public BrowserActionsIntent build() {
            mIntent.setData(mUri);
            mIntent.putExtra(EXTRA_TYPE, mType);
            mIntent.putParcelableArrayListExtra(EXTRA_MENU_ITEMS, mMenuItems);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                    mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE);
            mIntent.putExtra(EXTRA_APP_ID, pendingIntent);
            if (mOnItemSelectedPendingIntent != null) {
                mIntent.putExtra(
                        EXTRA_SELECTED_ACTION_PENDING_INTENT, mOnItemSelectedPendingIntent);
            }
            BrowserServiceFileProvider.grantReadPermission(mIntent, mImageUris, mContext);
            return new BrowserActionsIntent(mIntent);
        }
    }

    /**
     * Construct a BrowserActionsIntent with default settings and launch it to open a Browser
     * Actions menu.
     * @param context The context requesting for a Browser Actions menu.
     * @param uri The url for Browser Actions menu.
     */
    public static void openBrowserAction(@NonNull Context context, @NonNull Uri uri) {
        BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri).build();
        launchIntent(context, intent.getIntent());
    }

    /**
     * Construct a BrowserActionsIntent with custom settings and launch it to open a Browser Actions
     * menu.
     * @param context The context requesting for a Browser Actions menu.
     * @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.
     */
    public static void openBrowserAction(@NonNull Context context, @NonNull Uri uri, int type,
            @NonNull ArrayList<BrowserActionItem> items, @NonNull PendingIntent pendingIntent) {
        BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri)
                .setUrlType(type)
                .setCustomItems(items)
                .setOnItemSelectedAction(pendingIntent)
                .build();
        launchIntent(context, intent.getIntent());
    }

    /**
     * Launch an Intent to open a Browser Actions menu.
     * It first checks if any Browser Actions provider is available to create the menu.
     * If the default Browser supports Browser Actions, menu will be opened by the default Browser,
     * otherwise show a intent picker.
     * If not provider, a Browser Actions menu is opened locally from support library.
     * @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 launchIntent(@NonNull Context context, @NonNull Intent intent) {
        List<ResolveInfo> handlers = getBrowserActionsIntentHandlers(context);
        launchIntent(context, intent, handlers);
    }

    /** @hide */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @VisibleForTesting
    static void launchIntent(Context context, Intent intent, List<ResolveInfo> handlers) {
        if (handlers == null || handlers.size() == 0) {
            openFallbackBrowserActionsMenu(context, intent);
            return;
        } else if (handlers.size() == 1) {
            intent.setPackage(handlers.get(0).activityInfo.packageName);
        } else {
            Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(TEST_URL));
            PackageManager pm = context.getPackageManager();
            ResolveInfo defaultHandler =
                    pm.resolveActivity(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 List of Browser Actions providers available to handle the intent.
     * @hide
     */
    @RestrictTo(LIBRARY)
    @NonNull
    public static List<ResolveInfo> getBrowserActionsIntentHandlers(@NonNull Context context) {
        Intent intent =
                new Intent(BrowserActionsIntent.ACTION_BROWSER_ACTIONS_OPEN, Uri.parse(TEST_URL));
        PackageManager pm = context.getPackageManager();
        return pm.queryIntentActivities(intent, PackageManager.MATCH_ALL);
    }

    @SuppressWarnings("NullAway") // TODO: b/141869398
    private static void openFallbackBrowserActionsMenu(Context context, Intent intent) {
        Uri uri = intent.getData();
        ArrayList<Bundle> bundles = intent.getParcelableArrayListExtra(EXTRA_MENU_ITEMS);
        List<BrowserActionItem> items = bundles != null ? parseBrowserActionItems(bundles) : null;
        openFallbackBrowserActionsMenu(context, uri, items);
    }

    /** @hide */
    @RestrictTo(LIBRARY_GROUP_PREFIX)
    @VisibleForTesting
    static void setDialogShownListenter(BrowserActionsFallDialogListener dialogListener) {
        sDialogListenter = dialogListener;
    }

    /**
     * Open a Browser Actions menu from support library.
     * @param context The context requesting for a Browser Actions menu.
     * @param uri The url for Browser Actions menu.
     * @param menuItems List of {@link BrowserActionItem} to add to the fallback menu.
     */
    private static void openFallbackBrowserActionsMenu(
            Context context, Uri uri, List<BrowserActionItem> menuItems) {
        BrowserActionsFallbackMenuUi menuUi =
                new BrowserActionsFallbackMenuUi(context, uri, menuItems);
        menuUi.displayMenu();
        if (sDialogListenter != null) {
            sDialogListenter.onDialogShown();
        }
    }

    /**
     * Gets custom item list for browser action menu.
     * @param bundles Data for custom items from {@link BrowserActionsIntent}.
     * @return List of {@link BrowserActionItem}
     */
    @NonNull
    public static List<BrowserActionItem> parseBrowserActionItems(
            @NonNull 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(KEY_TITLE);
            PendingIntent action = bundle.getParcelable(KEY_ACTION);
            @DrawableRes
            int iconId = bundle.getInt(KEY_ICON_ID);
            Uri iconUri = bundle.getParcelable(KEY_ICON_URI);
            if (!TextUtils.isEmpty(title) && action != null) {
                BrowserActionItem item;
                if (iconId != 0) {
                    item = new BrowserActionItem(title, action, iconId);
                } else {
                    item = new BrowserActionItem(title, action, iconUri);
                }
                mActions.add(item);
            } else {
                throw new IllegalArgumentException(
                        "Custom item should contain a non-empty title and non-null intent.");
            }
        }
        return mActions;
    }

    /**
     * Get the package name of the creator application.
     * <p>
     * <strong> Note:</strong> This is self-reported and could be untrusted. Intent sender can
     * modify it to return the package name from a different application.
     *
     * @param intent The {@link BrowserActionsIntent}.
     * @return The creator package name.
     */
    @SuppressWarnings("deprecation")
    @Nullable
    public static String getUntrustedCreatorPackageName(@NonNull Intent intent) {
        PendingIntent pendingIntent = intent.getParcelableExtra(BrowserActionsIntent.EXTRA_APP_ID);
        if (pendingIntent != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                return pendingIntent.getCreatorPackage();
            } else {
                return pendingIntent.getTargetPackage();
            }
        }
        return null;
    }

    /**
     * @deprecated This return value of this method cannot be trusted, it is kept around for
     *             compatibility. Use {@link #getUntrustedCreatorPackageName}, or an alternative
     *             method if you rely on the return value.
     */
    @Deprecated
    @Nullable
    public static String getCreatorPackageName(@NonNull Intent intent) {
        return getUntrustedCreatorPackageName(intent);
    }
}