Bug 958517 - Create a 'Page' menu and move some of the URL context menu actions there r=lucasr
authorMark Finkle <mfinkle@mozilla.com>
Fri, 07 Feb 2014 14:49:32 -0500
changeset 184793 36ba4edc24160704371983c874406af1bb642d1a
parent 184792 949b41f324da1175601256ed4b785d1470f73287
child 184794 95bb0412c8785dfaaae46497e0193cb2adac4cc9
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslucasr
bugs958517
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 958517 - Create a 'Page' menu and move some of the URL context menu actions there r=lucasr
mobile/android/base/BrowserApp.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/moz.build
mobile/android/base/resources/menu-large-v11/browser_app_menu.xml
mobile/android/base/resources/menu-v11/browser_app_menu.xml
mobile/android/base/resources/menu-v11/titlebar_contextmenu.xml
mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml
mobile/android/base/strings.xml.in
mobile/android/base/toolbar/BrowserToolbar.java
mobile/android/base/util/MenuUtils.java
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -29,16 +29,17 @@ import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.prompts.Prompt;
 import org.mozilla.gecko.toolbar.AutocompleteHandler;
 import org.mozilla.gecko.toolbar.BrowserToolbar;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.EventDispatcher;
 import org.mozilla.gecko.util.GamepadUtils;
 import org.mozilla.gecko.util.HardwareUtils;
+import org.mozilla.gecko.util.MenuUtils;
 import org.mozilla.gecko.util.StringUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.UiAsyncTask;
 import org.mozilla.gecko.widget.GeckoActionProvider;
 import org.mozilla.gecko.widget.ButtonToast;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -2127,16 +2128,25 @@ abstract public class BrowserApp extends
 
         if (tab == null || tab.getURL() == null) {
             bookmark.setEnabled(false);
             back.setEnabled(false);
             forward.setEnabled(false);
             share.setEnabled(false);
             saveAsPDF.setEnabled(false);
             findInPage.setEnabled(false);
+
+            // NOTE: Use MenuUtils.safeSetEnabled because some actions might
+            // be on the BrowserToolbar context menu
+            MenuUtils.safeSetEnabled(aMenu, R.id.page, false);
+            MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, false);
+            MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, false);
+            MenuUtils.safeSetEnabled(aMenu, R.id.site_settings, false);
+            MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, false);
+
             return true;
         }
 
         bookmark.setEnabled(!AboutPages.isAboutReader(tab.getURL()));
         bookmark.setCheckable(true);
         bookmark.setChecked(tab.isBookmark());
         bookmark.setIcon(tab.isBookmark() ? R.drawable.ic_menu_bookmark_remove : R.drawable.ic_menu_bookmark_add);
 
@@ -2154,16 +2164,24 @@ abstract public class BrowserApp extends
         }
 
         // Disable share menuitem for about:, chrome:, file:, and resource: URIs
         String scheme = Uri.parse(url).getScheme();
         share.setVisible(!GeckoProfile.get(this).inGuestMode());
         share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") ||
                            scheme.equals("file") || scheme.equals("resource")));
 
+        // NOTE: Use MenuUtils.safeSetEnabled because some actions might
+        // be on the BrowserToolbar context menu
+        MenuUtils.safeSetEnabled(aMenu, R.id.page, !isAboutHome(tab));
+        MenuUtils.safeSetEnabled(aMenu, R.id.subscribe, tab.hasFeeds());
+        MenuUtils.safeSetEnabled(aMenu, R.id.add_search_engine, tab.hasOpenSearch());
+        MenuUtils.safeSetEnabled(aMenu, R.id.site_settings, !isAboutHome(tab));
+        MenuUtils.safeSetEnabled(aMenu, R.id.add_to_launcher, !isAboutHome(tab));
+
         // Action providers are available only ICS+.
         if (Build.VERSION.SDK_INT >= 14) {
             GeckoActionProvider provider = (GeckoActionProvider) share.getActionProvider();
             if (provider != null) {
                 Intent shareIntent = provider.getIntent();
 
                 // For efficiency, the provider's intent is only set once
                 if (shareIntent == null) {
@@ -2350,16 +2368,23 @@ abstract public class BrowserApp extends
             return true;
         }
 
         if (itemId == R.id.exit_guest_session) {
             showGuestModeDialog(GuestModeDialog.LEAVING);
             return true;
         }
 
+        // We have a few menu items that can also be in the context menu. If
+        // we have not already handled the item, give the context menu handler
+        // a chance.
+        if (onContextItemSelected(item)) {
+            return true;
+        }
+
         return super.onOptionsItemSelected(item);
     }
 
     private void showGuestModeDialog(final GuestModeDialog type) {
         final Prompt ps = new Prompt(this, new Prompt.PromptCallback() {
             @Override
             public void onPromptFinished(String result) {
                 try {
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -205,16 +205,17 @@ size. -->
 <!ENTITY char_encoding "Character Encoding">
 
 <!ENTITY share "Share">
 <!ENTITY share_title "Share via">
 <!ENTITY share_image_failed "Unable to share this image">
 <!ENTITY save_as_pdf "Save as PDF">
 <!ENTITY find_in_page "Find in Page">
 <!ENTITY desktop_mode "Request Desktop Site">
+<!ENTITY page "Page">
 <!ENTITY tools "Tools">
 <!ENTITY new_tab "New Tab">
 <!ENTITY new_private_tab "New Private Tab">
 <!ENTITY close_all_tabs "Close All Tabs">
 <!ENTITY tabs_normal "Tabs">
 <!ENTITY tabs_private "Private">
 <!ENTITY tabs_synced "Synced">
 <!ENTITY set_image_fail "Unable to set image">
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -47,16 +47,17 @@ gujar.sources += [
     'util/GeckoBackgroundThread.java',
     'util/GeckoEventListener.java',
     'util/GeckoEventResponder.java',
     'util/GeckoJarReader.java',
     'util/HardwareUtils.java',
     'util/INIParser.java',
     'util/INISection.java',
     'util/JSONUtils.java',
+    'util/MenuUtils.java',
     'util/NonEvictingLruCache.java',
     'util/ProxySelector.java',
     'util/StringUtils.java',
     'util/ThreadUtils.java',
     'util/UiAsyncTask.java',
 ]
 gujar.extra_jars = [
     'gecko-mozglue.jar'
--- a/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml
+++ b/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml
@@ -42,16 +42,38 @@
           android:icon="@drawable/ic_menu_find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
+    <item android:id="@+id/page"
+          android:title="@string/page"
+          android:icon="@drawable/ic_menu_tools">
+
+        <menu>
+
+            <item android:id="@+id/subscribe"
+                  android:title="@string/contextmenu_subscribe"/>
+
+            <item android:id="@+id/add_search_engine"
+                  android:title="@string/contextmenu_add_search_engine"/>
+
+            <item android:id="@+id/site_settings"
+                  android:title="@string/contextmenu_site_settings" />
+
+            <item android:id="@+id/add_to_launcher"
+                  android:title="@string/contextmenu_add_to_launcher"/>
+
+        </menu>
+
+    </item>
+
     <item android:id="@+id/tools"
           android:title="@string/tools"
           android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
                   android:icon="@drawable/ic_menu_save_as_pdf"
--- a/mobile/android/base/resources/menu-v11/browser_app_menu.xml
+++ b/mobile/android/base/resources/menu-v11/browser_app_menu.xml
@@ -42,16 +42,38 @@
           android:icon="@drawable/ic_menu_find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
+    <item android:id="@+id/page"
+          android:title="@string/page"
+          android:icon="@drawable/ic_menu_tools">
+
+        <menu>
+
+            <item android:id="@+id/subscribe"
+                  android:title="@string/contextmenu_subscribe"/>
+
+            <item android:id="@+id/add_search_engine"
+                  android:title="@string/contextmenu_add_search_engine"/>
+
+            <item android:id="@+id/site_settings"
+                  android:title="@string/contextmenu_site_settings" />
+
+            <item android:id="@+id/add_to_launcher"
+                  android:title="@string/contextmenu_add_to_launcher"/>
+
+        </menu>
+
+    </item>
+
     <item android:id="@+id/tools"
           android:title="@string/tools"
           android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
                   android:icon="@drawable/ic_menu_save_as_pdf"
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/menu-v11/titlebar_contextmenu.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@+id/pasteandgo"
+          android:title="@string/contextmenu_pasteandgo"/>
+
+    <item android:id="@+id/paste"
+          android:title="@string/contextmenu_paste"/>
+
+    <item android:id="@+id/copyurl"
+          android:title="@string/contextmenu_copyurl"/>
+
+    <item android:id="@+id/add_to_launcher"
+          android:title="@string/contextmenu_add_to_launcher"/>
+
+</menu>
--- a/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml
+++ b/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml
@@ -42,16 +42,39 @@
           android:icon="@drawable/ic_menu_find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
           android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
+
+    <item android:id="@+id/page"
+          android:title="@string/page"
+          android:icon="@drawable/ic_menu_tools">
+
+        <menu>
+
+            <item android:id="@+id/subscribe"
+                  android:title="@string/contextmenu_subscribe"/>
+
+            <item android:id="@+id/add_search_engine"
+                  android:title="@string/contextmenu_add_search_engine"/>
+
+            <item android:id="@+id/site_settings"
+                  android:title="@string/contextmenu_site_settings" />
+
+            <item android:id="@+id/add_to_launcher"
+                  android:title="@string/contextmenu_add_to_launcher"/>
+
+        </menu>
+
+    </item>
+
     <item android:id="@+id/tools"
           android:title="@string/tools"
           android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
                   android:icon="@drawable/ic_menu_save_as_pdf"
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -72,16 +72,17 @@
   <string name="history_older_section">&history_older_section;</string>
 
   <string name="share">&share;</string>
   <string name="share_title">&share_title;</string>
   <string name="share_image_failed">&share_image_failed;</string>
   <string name="save_as_pdf">&save_as_pdf;</string>
   <string name="find_in_page">&find_in_page;</string>
   <string name="desktop_mode">&desktop_mode;</string>
+  <string name="page">&page;</string>
   <string name="tools">&tools;</string>
 
   <string name="find_text">&find_text;</string>
   <string name="find_prev">&find_prev;</string>
   <string name="find_next">&find_next;</string>
   <string name="find_close">&find_close;</string>
 
   <string name="media_casting_to">&media_casting_to;</string>
--- a/mobile/android/base/toolbar/BrowserToolbar.java
+++ b/mobile/android/base/toolbar/BrowserToolbar.java
@@ -19,16 +19,17 @@ import org.mozilla.gecko.animation.Prope
 import org.mozilla.gecko.animation.ViewHelper;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.menu.MenuPopup;
 import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnStopListener;
 import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnTitleChangeListener;
 import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.UpdateFlags;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.HardwareUtils;
+import org.mozilla.gecko.util.MenuUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.widget.GeckoImageButton;
 import org.mozilla.gecko.widget.GeckoImageView;
 import org.mozilla.gecko.widget.GeckoRelativeLayout;
 
 import org.json.JSONObject;
 
@@ -244,46 +245,49 @@ public class BrowserToolbar extends Geck
         setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
             @Override
             public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
                 // We don't the context menu while editing
                 if (isEditing()) {
                     return;
                 }
 
+                // NOTE: Use MenuUtils.safeSetVisible because some actions might
+                // be on the Page menu
+
                 MenuInflater inflater = mActivity.getMenuInflater();
                 inflater.inflate(R.menu.titlebar_contextmenu, menu);
 
                 String clipboard = Clipboard.getText();
                 if (TextUtils.isEmpty(clipboard)) {
                     menu.findItem(R.id.pasteandgo).setVisible(false);
                     menu.findItem(R.id.paste).setVisible(false);
                 }
 
                 Tab tab = Tabs.getInstance().getSelectedTab();
                 if (tab != null) {
                     String url = tab.getURL();
                     if (url == null) {
                         menu.findItem(R.id.copyurl).setVisible(false);
-                        menu.findItem(R.id.share).setVisible(false);
                         menu.findItem(R.id.add_to_launcher).setVisible(false);
+                        MenuUtils.safeSetVisible(menu, R.id.share, false);
                     }
 
-                    menu.findItem(R.id.subscribe).setVisible(tab.hasFeeds());
-                    menu.findItem(R.id.add_search_engine).setVisible(tab.hasOpenSearch());
+                    MenuUtils.safeSetVisible(menu, R.id.subscribe, tab.hasFeeds());
+                    MenuUtils.safeSetVisible(menu, R.id.add_search_engine, tab.hasOpenSearch());
                 } else {
                     // if there is no tab, remove anything tab dependent
                     menu.findItem(R.id.copyurl).setVisible(false);
-                    menu.findItem(R.id.share).setVisible(false);
                     menu.findItem(R.id.add_to_launcher).setVisible(false);
-                    menu.findItem(R.id.subscribe).setVisible(false);
-                    menu.findItem(R.id.add_search_engine).setVisible(false);
+                    MenuUtils.safeSetVisible(menu, R.id.share, false);
+                    MenuUtils.safeSetVisible(menu, R.id.subscribe, false);
+                    MenuUtils.safeSetVisible(menu, R.id.add_search_engine, false);
                 }
 
-                menu.findItem(R.id.share).setVisible(!GeckoProfile.get(getContext()).inGuestMode());
+                MenuUtils.safeSetVisible(menu, R.id.share, !GeckoProfile.get(getContext()).inGuestMode());
             }
         });
 
         mUrlDisplayLayout.setOnStopListener(new OnStopListener() {
             @Override
             public Tab onStop() {
                 final Tab tab = Tabs.getInstance().getSelectedTab();
                 if (tab != null) {
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/util/MenuUtils.java
@@ -0,0 +1,33 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.util;
+
+import android.view.Menu;
+import android.view.MenuItem;
+
+public class MenuUtils {
+    /*
+     * This method looks for a menuitem and sets it's visible state, if
+     * it exists.
+     */
+    public static void safeSetVisible(Menu menu, int id, boolean visible) {
+        MenuItem item = menu.findItem(id);
+        if (item != null) {
+            item.setVisible(visible);
+        }
+    }
+
+    /*
+     * This method looks for a menuitem and sets it's enabled state, if
+     * it exists.
+     */
+    public static void safeSetEnabled(Menu menu, int id, boolean enabled) {
+        MenuItem item = menu.findItem(id);
+        if (item != null) {
+            item.setEnabled(enabled);
+        }
+    }
+}