Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(850)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java

Issue 2747453002: Split context menu display and population/handling (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
index 5352ed1ad824e045a1fb6529adb4db81915e9f27..e8200a6bf8aa7cce8f35d851952bf9cd8c6ed554 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -8,9 +8,8 @@ import android.content.Context;
import android.net.MailTo;
import android.support.annotation.IntDef;
import android.text.TextUtils;
+import android.util.Pair;
import android.view.ContextMenu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.webkit.MimeTypeMap;
import org.chromium.base.CollectionUtil;
@@ -25,7 +24,11 @@ import org.chromium.chrome.browser.util.UrlUtilities;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Set;
/**
@@ -40,9 +43,9 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
- NORMAL_MODE, /* Default mode */
- CUSTOM_TAB_MODE, /* Custom tab mode */
- FULLSCREEN_TAB_MODE /* Full screen mode */
+ NORMAL_MODE, /* Default mode */
+ CUSTOM_TAB_MODE, /* Custom tab mode */
+ FULLSCREEN_TAB_MODE /* Full screen mode */
})
public @interface ContextMenuMode {}
@@ -50,32 +53,80 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
public static final int CUSTOM_TAB_MODE = 1;
public static final int FULLSCREEN_TAB_MODE = 2;
+ /**
+ * Defines the Groups of each Context Menu Item
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ LINK,
+ IMAGE,
+ VIDEO,
+ CUSTOM,
+ OTHER
+ })
+ public @interface ContextMenuGroup {}
+
+ public static final int LINK = 0;
+ public static final int IMAGE = 1;
+ public static final int VIDEO = 2;
+ public static final int CUSTOM = 3;
+ public static final int OTHER = 4;
+
// Items that are included in all context menus.
- private static final Set<Integer> BASE_WHITELIST = CollectionUtil.newHashSet(
- R.id.contextmenu_copy_link_address, R.id.contextmenu_call,
- R.id.contextmenu_send_message, R.id.contextmenu_add_to_contacts, R.id.contextmenu_copy,
- R.id.contextmenu_copy_link_text, R.id.contextmenu_load_original_image,
- R.id.contextmenu_save_link_as, R.id.contextmenu_save_image,
- R.id.contextmenu_share_image, R.id.contextmenu_save_video);
+ private static final Set<ContextMenuItems> BASE_WHITELIST = Collections.unmodifiableSet(
+ CollectionUtil.newHashSet(ContextMenuItems.COPY_LINK_ADDRESS, ContextMenuItems.CALL,
+ ContextMenuItems.SEND_MESSAGE, ContextMenuItems.ADD_TO_CONTACTS,
+ ContextMenuItems.COPY, ContextMenuItems.COPY_LINK_TEXT,
+ ContextMenuItems.LOAD_ORIGINAL_IMAGE, ContextMenuItems.SAVE_LINK_AS,
+ ContextMenuItems.SAVE_IMAGE, ContextMenuItems.SHARE_IMAGE,
+ ContextMenuItems.SAVE_VIDEO));
// Items that are included for normal Chrome browser mode.
- private static final Set<Integer> NORMAL_MODE_WHITELIST = CollectionUtil.newHashSet(
- R.id.contextmenu_open_in_new_tab, R.id.contextmenu_open_in_other_window,
- R.id.contextmenu_open_in_incognito_tab, R.id.contextmenu_save_link_as,
- R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_by_image);
+ private static final Set<ContextMenuItems> NORMAL_MODE_WHITELIST =
+ Collections.unmodifiableSet(CollectionUtil.newHashSet(ContextMenuItems.OPEN_IN_NEW_TAB,
+ ContextMenuItems.OPEN_IN_OTHER_WINDOW, ContextMenuItems.OPEN_IN_INCOGNITO_TAB,
+ ContextMenuItems.SAVE_LINK_AS, ContextMenuItems.OPEN_IMAGE_IN_NEW_TAB,
+ ContextMenuItems.SEARCH_BY_IMAGE));
// Additional items for custom tabs mode.
- private static final Set<Integer> CUSTOM_TAB_MODE_WHITELIST = CollectionUtil.newHashSet(
- R.id.contextmenu_open_image, R.id.contextmenu_search_by_image,
- R.id.contextmenu_open_in_new_chrome_tab, R.id.contextmenu_open_in_chrome_incognito_tab,
- R.id.contextmenu_open_in_browser_id);
+ private static final Set<ContextMenuItems> CUSTOM_TAB_MODE_WHITELIST =
+ Collections.unmodifiableSet(CollectionUtil.newHashSet(ContextMenuItems.OPEN_IMAGE,
+ ContextMenuItems.SEARCH_BY_IMAGE, ContextMenuItems.OPEN_IN_NEW_CHROME_TAB,
+ ContextMenuItems.OPEN_IN_CHROME_INCOGNITO_TAB,
+ ContextMenuItems.OPEN_IN_BROWSER_ID));
// Additional items for fullscreen tabs mode.
- private static final Set<Integer> FULLSCREEN_TAB_MODE_WHITELIST =
- CollectionUtil.newHashSet(R.id.menu_id_open_in_chrome);
+ private static final Set<ContextMenuItems> FULLSCREEN_TAB_MODE_WHITELIST =
+ Collections.unmodifiableSet(CollectionUtil.newHashSet(ContextMenuItems.OPEN_IN_CHROME));
+
+ public static final List<ContextMenuItems> CUSTOM_TAB_GROUP = Collections.unmodifiableList(
+ CollectionUtil.newArrayList(ContextMenuItems.OPEN_IN_NEW_CHROME_TAB,
+ ContextMenuItems.OPEN_IN_CHROME_INCOGNITO_TAB,
+ ContextMenuItems.OPEN_IN_BROWSER_ID));
+
+ public static final List<ContextMenuItems> LINK_GROUP =
+ Collections.unmodifiableList(CollectionUtil.newArrayList(
+ ContextMenuItems.OPEN_IN_OTHER_WINDOW, ContextMenuItems.OPEN_IN_NEW_TAB,
+ ContextMenuItems.OPEN_IN_INCOGNITO_TAB, ContextMenuItems.COPY_LINK_ADDRESS,
+ ContextMenuItems.COPY_LINK_TEXT, ContextMenuItems.SAVE_LINK_AS));
+
+ public static final List<ContextMenuItems> IMAGE_GROUP =
+ Collections.unmodifiableList(CollectionUtil.newArrayList(
+ ContextMenuItems.LOAD_ORIGINAL_IMAGE, ContextMenuItems.SAVE_IMAGE,
+ ContextMenuItems.OPEN_IMAGE, ContextMenuItems.OPEN_IMAGE_IN_NEW_TAB,
+ ContextMenuItems.SEARCH_BY_IMAGE, ContextMenuItems.SHARE_IMAGE));
+
+ public static final List<ContextMenuItems> MESSAGE_GROUP = Collections.unmodifiableList(
+ CollectionUtil.newArrayList(ContextMenuItems.CALL, ContextMenuItems.SEND_MESSAGE,
+ ContextMenuItems.ADD_TO_CONTACTS, ContextMenuItems.COPY));
+
+ public static final List<ContextMenuItems> VIDEO_GROUP =
+ Collections.unmodifiableList(CollectionUtil.newArrayList(ContextMenuItems.SAVE_VIDEO));
+
+ public static final List<ContextMenuItems> OTHER_GROUP = Collections.unmodifiableList(
+ CollectionUtil.newArrayList(ContextMenuItems.OPEN_IN_CHROME));
private final ContextMenuItemDelegate mDelegate;
- private MenuInflater mMenuInflater;
private final int mMode;
static class ContextMenuUma {
@@ -178,141 +229,196 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
mDelegate.onDestroy();
}
- @Override
- public void buildContextMenu(ContextMenu menu, Context context, ContextMenuParams params) {
+ public static String createHeaderText(ContextMenuParams params) {
+ String titleText = "";
if (!TextUtils.isEmpty(params.getLinkUrl())
&& !params.getLinkUrl().equals(UrlConstants.ABOUT_BLANK_DISPLAY_URL)) {
- setHeaderText(context, menu, params.getLinkUrl());
+ titleText = params.getLinkUrl();
} else if (!TextUtils.isEmpty(params.getTitleText())) {
- setHeaderText(context, menu, params.getTitleText());
+ titleText = params.getTitleText();
}
+ return titleText;
+ }
- if (params.isFile()) return;
-
- if (mMenuInflater == null) mMenuInflater = new MenuInflater(context);
-
- mMenuInflater.inflate(R.menu.chrome_context_menu, menu);
-
- menu.setGroupVisible(R.id.contextmenu_group_anchor, params.isAnchor());
- menu.setGroupVisible(R.id.contextmenu_group_image, params.isImage());
- menu.setGroupVisible(R.id.contextmenu_group_video, params.isVideo());
- menu.setGroupVisible(R.id.contextmenu_group_message,
- MailTo.isMailTo(params.getLinkUrl())
- || UrlUtilities.isTelScheme(params.getLinkUrl()));
-
- Set<Integer> supportedOptions = new HashSet<>();
+ @Override
+ public List<Pair<Integer, List<ContextMenuItems>>> buildContextMenu(
+ ContextMenu menu, Context context, ContextMenuParams params) {
+ if (params.isFile()) return new ArrayList<>();
+ // Add all items in a group
+ Set<ContextMenuItems> supportedOptions = new HashSet<>();
supportedOptions.addAll(BASE_WHITELIST);
if (mMode == FULLSCREEN_TAB_MODE) {
supportedOptions.addAll(FULLSCREEN_TAB_MODE_WHITELIST);
} else if (mMode == CUSTOM_TAB_MODE) {
supportedOptions.addAll(CUSTOM_TAB_MODE_WHITELIST);
- if (!ChromePreferenceManager.getInstance().getCachedChromeDefaultBrowser()) {
- menu.findItem(R.id.contextmenu_open_in_browser_id)
- .setTitle(mDelegate.getTitleForOpenTabInExternalApp());
- }
} else {
supportedOptions.addAll(NORMAL_MODE_WHITELIST);
}
- Set<Integer> disabledOptions = getDisabledOptions(params);
- // Iterate through the entire menu list, if if doesn't exist in the map, don't show it.
- for (int i = 0; i < menu.size(); i++) {
- MenuItem item = menu.getItem(i);
- if (!item.isVisible()) continue;
- item.setVisible(supportedOptions.contains(item.getItemId())
- && !disabledOptions.contains(item.getItemId()));
+ Set<ContextMenuItems> disabledOptions = getDisabledOptions(params);
+ Set<ContextMenuItems> menuOptions = new HashSet<>();
+ for (ContextMenuItems item : supportedOptions) {
+ if (!disabledOptions.contains(item)) {
+ menuOptions.add(item);
+ }
+ }
+
+ // Split the items into their respective groups.
+ List<Pair<Integer, List<ContextMenuItems>>> groupedItems = new ArrayList<>();
+ if (params.isAnchor()) {
+ groupedItems.add(new Pair<>(
+ R.string.contextmenu_link_title, filterMenuItems(menuOptions, LINK)));
+ }
+ if (params.isImage()) {
+ groupedItems.add(new Pair<>(
+ R.string.contextmenu_image_title, filterMenuItems(menuOptions, IMAGE)));
+ }
+ if (params.isVideo()) {
+ groupedItems.add(new Pair<>(
+ R.string.contextmenu_video_title, filterMenuItems(menuOptions, VIDEO)));
+ }
+ if (!groupedItems.isEmpty()) {
+ groupedItems.get(0).second.addAll(filterMenuItems(menuOptions, OTHER));
+ if (mMode == CUSTOM_TAB_MODE) {
+ groupedItems.get(0).second.addAll(filterMenuItems(menuOptions, CUSTOM));
+ }
+ }
+
+ return groupedItems;
+ }
+
+ /**
+ * Takes a set of items and returns a list of items depending on the display type.
+ * @param items A set of menu items that should be shown.
+ * @param contextMenuType The type of link pressed. Will filter based off the context type.
+ * @return Returns a list of items
+ */
+ private static List<ContextMenuItems> filterMenuItems(
+ Set<ContextMenuItems> items, @ContextMenuGroup int contextMenuType) {
+ List<ContextMenuItems> itemGroup = new ArrayList<>();
+ List<ContextMenuItems> whichGroup = new ArrayList<>();
+ switch (contextMenuType) {
+ case LINK:
+ whichGroup.addAll(LINK_GROUP);
+ whichGroup.addAll(MESSAGE_GROUP);
+ break;
+ case IMAGE:
+ whichGroup.addAll(IMAGE_GROUP);
+ break;
+ case VIDEO:
+ whichGroup.addAll(VIDEO_GROUP);
+ break;
+ case CUSTOM:
+ whichGroup.addAll(CUSTOM_TAB_GROUP);
+ break;
+ case OTHER:
+ whichGroup.addAll(OTHER_GROUP);
+ break;
}
+ itemGroup.addAll(whichGroup);
- // Special case for searching by image element.
- if (supportedOptions.contains(R.id.contextmenu_search_by_image)) {
- menu.findItem(R.id.contextmenu_search_by_image)
- .setTitle(context.getString(R.string.contextmenu_search_web_for_image,
- TemplateUrlService.getInstance()
- .getDefaultSearchEngineTemplateUrl()
- .getShortName()));
+ for (Iterator<ContextMenuItems> iterator = itemGroup.iterator(); iterator.hasNext();) {
+ ContextMenuItems item = iterator.next();
+ if (!items.contains(item)) {
+ iterator.remove();
+ }
}
+ return itemGroup;
}
/**
* Given a set of params. It creates a list of items that should not be accessible in specific
- * instances. Since it doesn't have access to the menu groups, they need to be filtered outside
- * of this method.
+ * instances.
* @param params The parameters used to create a list of items that should not be allowed.
*/
- private Set<Integer> getDisabledOptions(ContextMenuParams params) {
- Set<Integer> disabledOptions = new HashSet<>();
+ private Set<ContextMenuItems> getDisabledOptions(ContextMenuParams params) {
+ Set<ContextMenuItems> disabledOptions = new HashSet<>();
+ if (!params.isAnchor()) {
+ disabledOptions.addAll(LINK_GROUP);
+ }
+ if (!params.isImage()) {
+ disabledOptions.addAll(IMAGE_GROUP);
+ }
+ if (!params.isVideo()) {
+ disabledOptions.addAll(VIDEO_GROUP);
+ }
+ if (!MailTo.isMailTo(params.getLinkUrl())
+ && !UrlUtilities.isTelScheme(params.getLinkUrl())) {
+ disabledOptions.addAll(MESSAGE_GROUP);
+ }
+
if (params.isAnchor() && !mDelegate.isOpenInOtherWindowSupported()) {
- disabledOptions.add(R.id.contextmenu_open_in_other_window);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_OTHER_WINDOW);
}
if (mDelegate.isIncognito() || !mDelegate.isIncognitoSupported()) {
- disabledOptions.add(R.id.contextmenu_open_in_incognito_tab);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_INCOGNITO_TAB);
}
if (params.getLinkText().trim().isEmpty() || params.isImage()) {
- disabledOptions.add(R.id.contextmenu_copy_link_text);
+ disabledOptions.add(ContextMenuItems.COPY_LINK_TEXT);
}
if (params.isAnchor() && !UrlUtilities.isAcceptedScheme(params.getLinkUrl())) {
- disabledOptions.add(R.id.contextmenu_open_in_other_window);
- disabledOptions.add(R.id.contextmenu_open_in_new_tab);
- disabledOptions.add(R.id.contextmenu_open_in_incognito_tab);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_OTHER_WINDOW);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_NEW_TAB);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_INCOGNITO_TAB);
}
if (MailTo.isMailTo(params.getLinkUrl())) {
- disabledOptions.add(R.id.contextmenu_copy_link_text);
- disabledOptions.add(R.id.contextmenu_copy_link_address);
+ disabledOptions.add(ContextMenuItems.COPY_LINK_TEXT);
+ disabledOptions.add(ContextMenuItems.COPY_LINK_ADDRESS);
if (!mDelegate.supportsSendEmailMessage()) {
- disabledOptions.add(R.id.contextmenu_send_message);
+ disabledOptions.add(ContextMenuItems.SEND_MESSAGE);
}
if (TextUtils.isEmpty(MailTo.parse(params.getLinkUrl()).getTo())
|| !mDelegate.supportsAddToContacts()) {
- disabledOptions.add(R.id.contextmenu_add_to_contacts);
+ disabledOptions.add(ContextMenuItems.ADD_TO_CONTACTS);
}
- disabledOptions.add(R.id.contextmenu_call);
+ disabledOptions.add(ContextMenuItems.CALL);
} else if (UrlUtilities.isTelScheme(params.getLinkUrl())) {
- disabledOptions.add(R.id.contextmenu_copy_link_text);
- disabledOptions.add(R.id.contextmenu_copy_link_address);
+ disabledOptions.add(ContextMenuItems.COPY_LINK_TEXT);
+ disabledOptions.add(ContextMenuItems.COPY_LINK_ADDRESS);
if (!mDelegate.supportsCall()) {
- disabledOptions.add(R.id.contextmenu_call);
+ disabledOptions.add(ContextMenuItems.CALL);
}
if (!mDelegate.supportsSendTextMessage()) {
- disabledOptions.add(R.id.contextmenu_send_message);
+ disabledOptions.add(ContextMenuItems.SEND_MESSAGE);
}
if (!mDelegate.supportsAddToContacts()) {
- disabledOptions.add(R.id.contextmenu_add_to_contacts);
+ disabledOptions.add(ContextMenuItems.ADD_TO_CONTACTS);
}
}
if (!UrlUtilities.isDownloadableScheme(params.getLinkUrl())) {
- disabledOptions.add(R.id.contextmenu_save_link_as);
+ disabledOptions.add(ContextMenuItems.SAVE_LINK_AS);
}
boolean isSrcDownloadableScheme = UrlUtilities.isDownloadableScheme(params.getSrcUrl());
if (params.isVideo()) {
boolean saveableAndDownloadable = params.canSaveMedia() && isSrcDownloadableScheme;
if (!saveableAndDownloadable) {
- disabledOptions.add(R.id.contextmenu_save_video);
+ disabledOptions.add(ContextMenuItems.SAVE_VIDEO);
}
} else if (params.isImage() && params.imageWasFetchedLoFi()) {
DataReductionProxyUma.previewsLoFiContextMenuAction(
DataReductionProxyUma.ACTION_LOFI_LOAD_IMAGE_CONTEXT_MENU_SHOWN);
// All image context menu items other than "Load image," "Open original image in
// new tab," and "Copy image URL" should be disabled on Lo-Fi images.
- disabledOptions.add(R.id.contextmenu_save_image);
- disabledOptions.add(R.id.contextmenu_open_image);
- disabledOptions.add(R.id.contextmenu_search_by_image);
- disabledOptions.add(R.id.contextmenu_share_image);
+ disabledOptions.add(ContextMenuItems.SAVE_IMAGE);
+ disabledOptions.add(ContextMenuItems.OPEN_IMAGE);
+ disabledOptions.add(ContextMenuItems.SEARCH_BY_IMAGE);
+ disabledOptions.add(ContextMenuItems.SHARE_IMAGE);
} else if (params.isImage() && !params.imageWasFetchedLoFi()) {
- disabledOptions.add(R.id.contextmenu_load_original_image);
+ disabledOptions.add(ContextMenuItems.LOAD_ORIGINAL_IMAGE);
if (!isSrcDownloadableScheme) {
- disabledOptions.add(R.id.contextmenu_save_image);
+ disabledOptions.add(ContextMenuItems.SAVE_IMAGE);
}
// Avoid showing open image option for same image which is already opened.
if (mDelegate.getPageUrl().equals(params.getSrcUrl())) {
- disabledOptions.add(R.id.contextmenu_open_image);
+ disabledOptions.add(ContextMenuItems.OPEN_IMAGE);
}
final TemplateUrlService templateUrlServiceInstance = TemplateUrlService.getInstance();
final boolean isSearchByImageAvailable = isSrcDownloadableScheme
@@ -321,26 +427,26 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
&& templateUrlServiceInstance.getDefaultSearchEngineTemplateUrl() != null;
if (!isSearchByImageAvailable) {
- disabledOptions.add(R.id.contextmenu_search_by_image);
+ disabledOptions.add(ContextMenuItems.SEARCH_BY_IMAGE);
}
}
// Hide all items that could spawn additional tabs until FRE has been completed.
if (!FirstRunStatus.getFirstRunFlowComplete()) {
- disabledOptions.add(R.id.contextmenu_open_image_in_new_tab);
- disabledOptions.add(R.id.contextmenu_open_in_other_window);
- disabledOptions.add(R.id.contextmenu_open_in_new_tab);
- disabledOptions.add(R.id.contextmenu_open_in_incognito_tab);
- disabledOptions.add(R.id.contextmenu_search_by_image);
- disabledOptions.add(R.id.menu_id_open_in_chrome);
+ disabledOptions.add(ContextMenuItems.OPEN_IMAGE_IN_NEW_TAB);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_OTHER_WINDOW);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_NEW_TAB);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_INCOGNITO_TAB);
+ disabledOptions.add(ContextMenuItems.SEARCH_BY_IMAGE);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_CHROME);
}
if (mMode == CUSTOM_TAB_MODE) {
if (ChromePreferenceManager.getInstance().getCachedChromeDefaultBrowser()) {
- disabledOptions.add(R.id.contextmenu_open_in_browser_id);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_BROWSER_ID);
} else {
- disabledOptions.add(R.id.contextmenu_open_in_new_chrome_tab);
- disabledOptions.add(R.id.contextmenu_open_in_chrome_incognito_tab);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_NEW_CHROME_TAB);
+ disabledOptions.add(ContextMenuItems.OPEN_IN_CHROME_INCOGNITO_TAB);
}
}

Powered by Google App Engine
This is Rietveld 408576698