Bug 940997: Support showAsAction "ifRoom" in custom menu. [r=mfinkle]
authorSriram Ramasubramanian <sriram@mozilla.com>
Wed, 18 Dec 2013 18:49:48 -0800
changeset 161210 63cac76f5f7fcc5be0f993d7f623b68cb017bde0
parent 161209 0e84f8ba1333e284be097902ae9308ad3e82f597
child 161211 90699ba761fb5291698f2b5664dc7bf042d8e53c
push id25871
push usercbook@mozilla.com
push dateThu, 19 Dec 2013 09:34:02 +0000
treeherdermozilla-central@5c7fa2bfea8b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle
bugs940997
milestone29.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 940997: Support showAsAction "ifRoom" in custom menu. [r=mfinkle]
mobile/android/base/TextSelection.java
mobile/android/base/menu/GeckoMenu.java
mobile/android/base/menu/GeckoMenuItem.java
mobile/android/base/menu/MenuItemActionBar.java
mobile/android/base/menu/MenuItemActionView.java
mobile/android/base/resources/layout/menu_item_action_view.xml
mobile/android/base/resources/layout/menu_secondary_action_bar.xml
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-xlarge-v11/browser_app_menu.xml
mobile/android/base/resources/values-v11/themes.xml
mobile/android/base/resources/values/attrs.xml
mobile/android/base/resources/values/styles.xml
mobile/android/base/widget/GeckoActionProvider.java
--- a/mobile/android/base/TextSelection.java
+++ b/mobile/android/base/TextSelection.java
@@ -241,17 +241,18 @@ class TextSelection extends Layer implem
             // action mode.
             menu.clear();
 
             int length = mItems.length();
             for (int i = 0; i < length; i++) {
                 try {
                     final JSONObject obj = mItems.getJSONObject(i);
                     final GeckoMenuItem menuitem = (GeckoMenuItem) menu.add(0, i, 0, obj.optString("label"));
-                    menuitem.setShowAsAction(obj.optBoolean("showAsAction") ? 1 : 0, R.attr.menuItemActionModeStyle);
+                    final int actionEnum = obj.optBoolean("showAsAction") ? GeckoMenuItem.SHOW_AS_ACTION_ALWAYS : GeckoMenuItem.SHOW_AS_ACTION_NEVER;
+                    menuitem.setShowAsAction(actionEnum, R.attr.menuItemActionModeStyle);
 
                     BitmapUtils.getDrawable(mStartHandle.getContext(), obj.optString("icon"), new BitmapLoader() {
                         public void onBitmapFound(Drawable d) {
                             if (d != null) {
                                 menuitem.setIcon(d);
                             }
                         }
                     });
--- a/mobile/android/base/menu/GeckoMenu.java
+++ b/mobile/android/base/menu/GeckoMenu.java
@@ -73,27 +73,33 @@ public class GeckoMenu extends ListView
         public void removeActionItem(View actionItem);
     }
 
     protected static final int NO_ID = 0;
 
     // List of all menu items.
     private List<GeckoMenuItem> mItems;
 
-    // Map of items in action-bar and their views.
-    private Map<GeckoMenuItem, View> mActionItems;
+    // Map of "always" action-items in action-bar and their views.
+    private Map<GeckoMenuItem, View> mPrimaryActionItems;
+
+    // Map of "ifRoom" action-items in action-bar and their views.
+    private Map<GeckoMenuItem, View> mSecondaryActionItems;
 
     // Reference to a callback for menu events.
     private Callback mCallback;
 
     // Reference to menu presenter.
     private MenuPresenter mMenuPresenter;
 
-    // Reference to action-items bar in action-bar.
-    private ActionItemBarPresenter mActionItemBarPresenter;
+    // Reference to "always" action-items bar in action-bar.
+    private ActionItemBarPresenter mPrimaryActionItemBar;
+
+    // Reference to "ifRoom" action-items bar in action-bar.
+    private final ActionItemBarPresenter mSecondaryActionItemBar;
 
     // Adapter to hold the list of menu items.
     private MenuItemsAdapter mAdapter;
 
     public GeckoMenu(Context context) {
         this(context, null);
     }
 
@@ -108,19 +114,21 @@ public class GeckoMenu extends ListView
                                          LayoutParams.FILL_PARENT));
 
         // Attach an adapter.
         mAdapter = new MenuItemsAdapter();
         setAdapter(mAdapter);
         setOnItemClickListener(this);
 
         mItems = new ArrayList<GeckoMenuItem>();
-        mActionItems = new HashMap<GeckoMenuItem, View>();
+        mPrimaryActionItems = new HashMap<GeckoMenuItem, View>();
+        mSecondaryActionItems = new HashMap<GeckoMenuItem, View>();
 
-        mActionItemBarPresenter = (DefaultActionItemBar) LayoutInflater.from(context).inflate(R.layout.menu_action_bar, null);
+        mPrimaryActionItemBar = (DefaultActionItemBar) LayoutInflater.from(context).inflate(R.layout.menu_action_bar, null);
+        mSecondaryActionItemBar = (DefaultActionItemBar) LayoutInflater.from(context).inflate(R.layout.menu_secondary_action_bar, null);
     }
 
     @Override
     public MenuItem add(CharSequence title) {
         GeckoMenuItem menuItem = new GeckoMenuItem(this, NO_ID, 0, title);
         addItem(menuItem);
         return menuItem;
     }
@@ -150,38 +158,65 @@ public class GeckoMenu extends ListView
         menuItem.setOnShowAsActionChangedListener(this);
         mAdapter.addMenuItem(menuItem);
         mItems.add(menuItem);
     }
 
     private boolean addActionItem(final GeckoMenuItem menuItem) {
         menuItem.setOnShowAsActionChangedListener(this);
 
-        if (mActionItems.size() == 0 && 
-            mActionItemBarPresenter instanceof DefaultActionItemBar) {
-            // Reset the adapter before adding the header view to a list.
-            setAdapter(null);
-            addHeaderView((DefaultActionItemBar) mActionItemBarPresenter);
-            setAdapter(mAdapter);
+        final View actionView = menuItem.getActionView();
+        final int actionEnum = menuItem.getActionEnum();
+        boolean added = false;
+
+        if (actionEnum == GeckoMenuItem.SHOW_AS_ACTION_ALWAYS) {
+            if (mPrimaryActionItems.size() == 0 &&
+                mPrimaryActionItemBar instanceof DefaultActionItemBar) {
+                // Reset the adapter before adding the header view to a list.
+                setAdapter(null);
+                addHeaderView((DefaultActionItemBar) mPrimaryActionItemBar);
+                setAdapter(mAdapter);
+            }
+
+            if (added = mPrimaryActionItemBar.addActionItem(actionView)) {
+                mPrimaryActionItems.put(menuItem, actionView);
+                mItems.add(menuItem);
+            }
+        } else if (actionEnum == GeckoMenuItem.SHOW_AS_ACTION_IF_ROOM) {
+            if (mSecondaryActionItems.size() == 0) {
+                // Reset the adapter before adding the header view to a list.
+                setAdapter(null);
+                addHeaderView((DefaultActionItemBar) mSecondaryActionItemBar);
+                setAdapter(mAdapter);
+            }
+
+            if (added = mSecondaryActionItemBar.addActionItem(actionView)) {
+                mSecondaryActionItems.put(menuItem, actionView);
+                mItems.add(menuItem);
+            }
         }
 
-        View actionView = menuItem.getActionView();
-        actionView.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                handleMenuItemClick(menuItem);
-            }
-        });
+        // Set the listeners.
+        if (actionView instanceof MenuItemActionBar) {
+            ((MenuItemActionBar) actionView).setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View view) {
+                    handleMenuItemClick(menuItem);
+                }
+            });
+        } else if (actionView instanceof MenuItemActionView) {
+            ((MenuItemActionView) actionView).setMenuItemClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View view) {
+                    handleMenuItemClick(menuItem);
+                }
+            });
+        }
 
-        if (mActionItemBarPresenter.addActionItem(actionView)) {
-            mActionItems.put(menuItem, actionView);
-            mItems.add(menuItem);
-            return true;
-        }
-        return false;
+        return added;
     }
 
     @Override
     public int addIntentOptions(int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
         return 0;
     }
 
     @Override
@@ -212,20 +247,27 @@ public class GeckoMenu extends ListView
         GeckoSubMenu subMenu = new GeckoSubMenu(getContext());
         subMenu.setMenuItem(menuItem);
         subMenu.setCallback(mCallback);
         subMenu.setMenuPresenter(mMenuPresenter);
         ((GeckoMenuItem) menuItem).setSubMenu(subMenu);
         return subMenu;
     }
 
-    private void removeActionBarView() {
+    private void removePrimaryActionBarView() {
         // Reset the adapter before removing the header view from a list.
         setAdapter(null);
-        removeHeaderView((DefaultActionItemBar) mActionItemBarPresenter);
+        removeHeaderView((DefaultActionItemBar) mPrimaryActionItemBar);
+        setAdapter(mAdapter);
+    }
+
+    private void removeSecondaryActionBarView() {
+        // Reset the adapter before removing the header view from a list.
+        setAdapter(null);
+        removeHeaderView((DefaultActionItemBar) mSecondaryActionItemBar);
         setAdapter(mAdapter);
     }
 
     @Override
     public void clear() {
         for (GeckoMenuItem menuItem : mItems) {
             if (menuItem.hasSubMenu()) {
                 SubMenu sub = menuItem.getSubMenu();
@@ -243,28 +285,37 @@ public class GeckoMenu extends ListView
         mAdapter.clear();
         mItems.clear();
 
         /*
          * Reinflating the menu will re-add any action items to the toolbar, so
          * remove the old ones. This also ensures that any text associated with
          * these is switched to the correct locale.
          */
-        if (mActionItemBarPresenter != null) {
-            for (View item : mActionItems.values()) {
-                mActionItemBarPresenter.removeActionItem(item);
+        if (mPrimaryActionItemBar != null) {
+            for (View item : mPrimaryActionItems.values()) {
+                mPrimaryActionItemBar.removeActionItem(item);
             }
         }
-        mActionItems.clear();
+        mPrimaryActionItems.clear();
+
+        if (mSecondaryActionItemBar != null) {
+            for (View item : mSecondaryActionItems.values()) {
+                mSecondaryActionItemBar.removeActionItem(item);
+            }
+        }
+        mSecondaryActionItems.clear();
 
         // Remove the view, too -- the first addActionItem will re-add it,
         // and this is simpler than changing that logic.
-        if (mActionItemBarPresenter instanceof DefaultActionItemBar) {
-            removeActionBarView();
+        if (mPrimaryActionItemBar instanceof DefaultActionItemBar) {
+            removePrimaryActionBarView();
         }
+
+        removeSecondaryActionBarView();
     }
 
     @Override
     public void close() {
         if (mMenuPresenter != null)
             mMenuPresenter.closeMenu();
     }
 
@@ -296,17 +347,19 @@ public class GeckoMenu extends ListView
             return mItems.get(index);
 
         return null;
     }
 
     @Override
     public boolean hasVisibleItems() {
         for (GeckoMenuItem menuItem : mItems) {
-            if (menuItem.isVisible() && !mActionItems.containsKey(menuItem))
+            if (menuItem.isVisible() &&
+                !mPrimaryActionItems.containsKey(menuItem) &&
+                !mSecondaryActionItems.containsKey(menuItem))
                 return true;
         }
 
         return false;
     }
 
     @Override
     public boolean isShortcutKey(int keyCode, KeyEvent event) {
@@ -340,26 +393,40 @@ public class GeckoMenu extends ListView
                 if (subMenu != null && subMenu.findItem(id) != null) {
                     subMenu.removeItem(id);
                     return;
                 }
             }
         }
 
         // Remove it from own menu.
-        if (mActionItems.containsKey(item)) {
-            if (mActionItemBarPresenter != null)
-                mActionItemBarPresenter.removeActionItem(mActionItems.get(item));
+        if (mPrimaryActionItems.containsKey(item)) {
+            if (mPrimaryActionItemBar != null)
+                mPrimaryActionItemBar.removeActionItem(mPrimaryActionItems.get(item));
 
-            mActionItems.remove(item);
+            mPrimaryActionItems.remove(item);
             mItems.remove(item);
 
-            if (mActionItems.size() == 0 && 
-                mActionItemBarPresenter instanceof DefaultActionItemBar) {
-                removeActionBarView();
+            if (mPrimaryActionItems.size() == 0 && 
+                mPrimaryActionItemBar instanceof DefaultActionItemBar) {
+                removePrimaryActionBarView();
+            }
+
+            return;
+        }
+
+        if (mSecondaryActionItems.containsKey(item)) {
+            if (mSecondaryActionItemBar != null)
+                mSecondaryActionItemBar.removeActionItem(mSecondaryActionItems.get(item));
+
+            mSecondaryActionItems.remove(item);
+            mItems.remove(item);
+
+            if (mSecondaryActionItems.size() == 0) {
+                removeSecondaryActionBarView();
             }
 
             return;
         }
 
         mAdapter.removeMenuItem(item);
         mItems.remove(item);
     }
@@ -382,49 +449,59 @@ public class GeckoMenu extends ListView
 
     @Override
     public int size() {
         return mItems.size();
     }
 
     @Override
     public boolean hasActionItemBar() {
-         return (mActionItemBarPresenter != null);
+         return (mPrimaryActionItemBar != null) && (mSecondaryActionItemBar != null);
     }
 
     @Override
-    public void onShowAsActionChanged(GeckoMenuItem item, boolean isActionItem) {
+    public void onShowAsActionChanged(GeckoMenuItem item) {
         removeItem(item.getItemId());
 
-        if (isActionItem && addActionItem(item)) {
+        if (item.isActionItem() && addActionItem(item)) {
             return;
         }
 
         addItem(item);
     }
 
     public void onItemChanged(GeckoMenuItem item) {
         if (item.isActionItem()) {
-           final MenuItemActionBar actionView = (MenuItemActionBar) mActionItems.get(item);
-           if (actionView != null) {
-               // The update could be coming from the background thread.
-               // Post a runnable on the UI thread of the view for it to update.
-               final GeckoMenuItem menuItem = item;
-               actionView.post(new Runnable() {
-                   @Override
-                   public void run() {
-                       if (menuItem.isVisible()) {
-                           actionView.setVisibility(View.VISIBLE);
-                           actionView.initialize(menuItem);
-                       } else {
-                           actionView.setVisibility(View.GONE);
-                       }
-                   }
-               });
-           } 
+            final View actionView;
+            if (item.getActionEnum() == GeckoMenuItem.SHOW_AS_ACTION_ALWAYS) {
+                actionView = mPrimaryActionItems.get(item);
+            } else {
+                actionView = mSecondaryActionItems.get(item);
+            }
+
+            if (actionView != null) {
+                // The update could be coming from the background thread.
+                // Post a runnable on the UI thread of the view for it to update.
+                final GeckoMenuItem menuItem = item;
+                actionView.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (menuItem.isVisible()) {
+                            actionView.setVisibility(View.VISIBLE);
+                            if (actionView instanceof MenuItemActionBar) {
+                                ((MenuItemActionBar) actionView).initialize(menuItem);
+                            } else {
+                                ((MenuItemActionView) actionView).initialize(menuItem);
+                            }
+                        } else {
+                            actionView.setVisibility(View.GONE);
+                        }
+                    }
+                });
+            }
         } else {
             mAdapter.notifyDataSetChanged();
         }
     }
 
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         // We might be showing headers. Account them while using the position.
@@ -486,57 +563,69 @@ public class GeckoMenu extends ListView
             if (menuItem.hasSubMenu()) {
                 GeckoSubMenu subMenu = (GeckoSubMenu) menuItem.getSubMenu();
                 subMenu.setMenuPresenter(mMenuPresenter);
             }
         }
     }
 
     public void setActionItemBarPresenter(ActionItemBarPresenter presenter) {
-        mActionItemBarPresenter = presenter;
+        mPrimaryActionItemBar = presenter;
     }
 
     // Action Items are added to the header view by default.
     // URL bar can register itself as a presenter, in case it has a different place to show them.
     public static class DefaultActionItemBar extends LinearLayout
                                              implements ActionItemBarPresenter {
         private final int mRowHeight;
+        private float mWeightSum;
 
         public DefaultActionItemBar(Context context) {
             this(context, null);
         }
 
         public DefaultActionItemBar(Context context, AttributeSet attrs) {
             super(context, attrs);
 
             mRowHeight = getResources().getDimensionPixelSize(R.dimen.menu_item_row_height);
-            setWeightSum(3.0f);
         }
 
         @Override
         public boolean addActionItem(View actionItem) {
             ViewGroup.LayoutParams actualParams = actionItem.getLayoutParams();
             LinearLayout.LayoutParams params;
 
             if (actualParams != null) {
                 params = new LinearLayout.LayoutParams(actionItem.getLayoutParams());
                 params.width = 0;
             } else {
                 params = new LinearLayout.LayoutParams(0, mRowHeight);
             }
 
-            params.weight = 1.0f;
+            if (actionItem instanceof MenuItemActionView) {
+                params.weight = ((MenuItemActionView) actionItem).getChildCount();
+            } else {
+                params.weight = 1.0f;
+            }
+
+            mWeightSum += params.weight;
+
             actionItem.setLayoutParams(params);
             addView(actionItem);
+            setWeightSum(mWeightSum);
             return true;
         }
 
         @Override
         public void removeActionItem(View actionItem) {
-            removeView(actionItem);
+            if (indexOfChild(actionItem) != -1) {
+                LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) actionItem.getLayoutParams();
+                mWeightSum -= params.weight;
+                removeView(actionItem);
+            }
         }
     }
 
     // Adapter to bind menu items to the list.
     private class MenuItemsAdapter extends BaseAdapter {
         private static final int VIEW_TYPE_DEFAULT = 0;
         private static final int VIEW_TYPE_ACTION_MODE = 1;
 
--- a/mobile/android/base/menu/GeckoMenuItem.java
+++ b/mobile/android/base/menu/GeckoMenuItem.java
@@ -1,43 +1,48 @@
 /* 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.menu;
 
+import org.mozilla.gecko.R;
 import org.mozilla.gecko.widget.GeckoActionProvider;
 
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.view.ActionProvider;
 import android.view.ContextMenu;
 import android.view.MenuItem;
 import android.view.SubMenu;
 import android.view.View;
 
 public class GeckoMenuItem implements MenuItem {
     private static final String LOGTAG = "GeckoMenuItem";
 
+    public static final int SHOW_AS_ACTION_NEVER = 0;
+    public static final int SHOW_AS_ACTION_IF_ROOM = 1;
+    public static final int SHOW_AS_ACTION_ALWAYS = 2;
+
     // A View that can show a MenuItem should be able to initialize from 
     // the properties of the MenuItem.
     public static interface Layout {
         public void initialize(GeckoMenuItem item);
     }
 
     public static interface OnShowAsActionChangedListener {
         public boolean hasActionItemBar();
-        public void onShowAsActionChanged(GeckoMenuItem item, boolean isActionItem);
+        public void onShowAsActionChanged(GeckoMenuItem item);
     }
 
     private int mId;
     private int mOrder;
     private View mActionView;
-    private boolean mActionItem = false;
+    private int mActionEnum;
     private CharSequence mTitle;
     private CharSequence mTitleCondensed;
     private boolean mCheckable = false;
     private boolean mChecked = false;
     private boolean mVisible = true;
     private boolean mEnabled = true;
     private Drawable mIcon;
     private int mIconRes;
@@ -74,16 +79,20 @@ public class GeckoMenuItem implements Me
     public boolean hasActionProvider() {
         if (Build.VERSION.SDK_INT < 14) {
             return false;
         }
 
         return (mActionProvider != null);
     }
 
+    public int getActionEnum() {
+        return mActionEnum;
+    }
+
     @Override
     public ActionProvider getActionProvider() {
         return mActionProvider;
     }
 
     @Override
     public View getActionView() {
         if (mActionProvider != null && mActionProvider instanceof GeckoActionProvider) {
@@ -159,17 +168,17 @@ public class GeckoMenuItem implements Me
     public boolean hasSubMenu() {
         if (mActionProvider != null)
             return mActionProvider.hasSubMenu();
 
         return (mSubMenu != null);
     }
 
     public boolean isActionItem() {
-        return mActionItem;
+        return (mActionEnum > 0);
     }
 
     @Override
     public boolean isActionViewExpanded() {
         return false;
     }
 
     @Override
@@ -196,20 +205,24 @@ public class GeckoMenuItem implements Me
     public MenuItem setActionProvider(ActionProvider actionProvider) {
         mActionProvider = actionProvider;
         if (mActionProvider != null && mActionProvider instanceof GeckoActionProvider) {
             GeckoActionProvider provider = (GeckoActionProvider) mActionProvider;
             provider.setOnTargetSelectedListener(new GeckoActionProvider.OnTargetSelectedListener() {
                 @Override
                 public void onTargetSelected() {
                     mMenu.close();
+
+                    // Refresh the menu item to show the high frequency apps.
+                    mShowAsActionChangedListener.onShowAsActionChanged(GeckoMenuItem.this);
                 }
             });
         }
 
+        mShowAsActionChangedListener.onShowAsActionChanged(this);
         return this;
     }
 
     @Override
     public MenuItem setActionView(int resId) {
         return this;
     }
 
@@ -288,37 +301,44 @@ public class GeckoMenuItem implements Me
     public void setShowAsAction(int actionEnum) {
         setShowAsAction(actionEnum, 0);
     }
 
     public void setShowAsAction(int actionEnum, int style) {
         if (mShowAsActionChangedListener == null)
             return;
 
-        if (mActionItem == (actionEnum > 0))
+        if (mActionEnum == actionEnum)
             return;
 
         if (actionEnum > 0) {
             if (!mShowAsActionChangedListener.hasActionItemBar())
                 return;
 
-            // Change the type to just an icon
-            MenuItemActionBar actionView;
-            if (style != 0) {
-                actionView = new MenuItemActionBar(mMenu.getContext(), null, style);
-            } else {
-                actionView = new MenuItemActionBar(mMenu.getContext());
+            if (!hasActionProvider()) {
+                // Change the type to just an icon
+                MenuItemActionBar actionView;
+                if (style != 0) {
+                    actionView = new MenuItemActionBar(mMenu.getContext(), null, style);
+                } else {
+                    if (actionEnum == SHOW_AS_ACTION_ALWAYS) {
+                        actionView = new MenuItemActionBar(mMenu.getContext());
+                    } else {
+                        actionView = new MenuItemActionBar(mMenu.getContext(), null, R.attr.menuItemSecondaryActionBarStyle);
+                    }
+                }
+
+                actionView.initialize(this);
+                mActionView = actionView;
             }
-            actionView.initialize(this);
-            mActionView = actionView;
 
-            mActionItem = (actionEnum > 0);
+            mActionEnum = actionEnum;
         }
 
-        mShowAsActionChangedListener.onShowAsActionChanged(this, mActionItem);
+        mShowAsActionChangedListener.onShowAsActionChanged(this);
     }
 
     @Override
     public MenuItem setShowAsActionFlags(int actionEnum) {
         return this;
     }
 
     public MenuItem setSubMenu(GeckoSubMenu subMenu) {
--- a/mobile/android/base/menu/MenuItemActionBar.java
+++ b/mobile/android/base/menu/MenuItemActionBar.java
@@ -34,35 +34,35 @@ public class MenuItemActionBar extends I
             return;
 
         setIcon(item.getIcon());
         setTitle(item.getTitle());
         setEnabled(item.isEnabled());
         setId(item.getItemId());
     }
 
-    private void setIcon(Drawable icon) {
+    void setIcon(Drawable icon) {
         if (icon != null) {
             setImageDrawable(icon);
             setVisibility(VISIBLE);
         } else {
             setVisibility(GONE);
         }
     }
 
-    private void setIcon(int icon) {
+    void setIcon(int icon) {
         if (icon != 0) {
             setImageResource(icon);
             setVisibility(VISIBLE);
         } else {
             setVisibility(GONE);
         }
     }
 
-    private void setTitle(CharSequence title) {
+    void setTitle(CharSequence title) {
         // set accessibility contentDescription here
         setContentDescription(title);
     }
 
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
         setColorFilter(enabled ? 0 : 0xFF999999);
--- a/mobile/android/base/menu/MenuItemActionView.java
+++ b/mobile/android/base/menu/MenuItemActionView.java
@@ -20,74 +20,84 @@ import android.widget.ImageButton;
 import java.util.ArrayList;
 import java.util.List;
 
 public class MenuItemActionView extends LinearLayout
                                 implements GeckoMenuItem.Layout {
     private static final String LOGTAG = "GeckoMenuItemActionView";
 
     private MenuItemDefault mMenuItem;
-    private ImageButton mMenuButton;
+    private MenuItemActionBar mMenuButton;
     private List<ImageButton> mActionButtons;
     private View.OnClickListener mActionButtonListener;
 
     public MenuItemActionView(Context context) {
         this(context, null);
     }
 
     public MenuItemActionView(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.menuItemActionViewStyle);
     }
 
     @TargetApi(11)
     public MenuItemActionView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        Resources res = context.getResources();
-        int width = res.getDimensionPixelSize(R.dimen.menu_item_row_width);
-        int height = res.getDimensionPixelSize(R.dimen.menu_item_row_height);
-        setMinimumWidth(width);
-        setMinimumHeight(height);
-
         LayoutInflater.from(context).inflate(R.layout.menu_item_action_view, this);
         mMenuItem = (MenuItemDefault) findViewById(R.id.menu_item);
-        mMenuButton = (ImageButton) findViewById(R.id.menu_item_button);
+        mMenuButton = (MenuItemActionBar) findViewById(R.id.menu_item_button);
         mActionButtons = new ArrayList<ImageButton>();
     }
 
     @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        View parent = (View) getParent();
+        if ((right - left) < parent.getMeasuredWidth() || mActionButtons.size() != 0) {
+            // Use the icon.
+            mMenuItem.setVisibility(View.GONE);
+            mMenuButton.setVisibility(View.VISIBLE);
+        } else {
+            // Use the button.
+            mMenuItem.setVisibility(View.VISIBLE);
+            mMenuButton.setVisibility(View.GONE);
+        }
+
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
     public void initialize(GeckoMenuItem item) {
         if (item == null)
             return;
 
         setTitle(item.getTitle());
         setIcon(item.getIcon());
         setEnabled(item.isEnabled());
     }
 
     private void setIcon(Drawable icon) {
         mMenuItem.setIcon(icon);
-        mMenuButton.setImageDrawable(icon);
+        mMenuButton.setIcon(icon);
     }
 
     private void setIcon(int icon) {
         mMenuItem.setIcon(icon);
-        mMenuButton.setImageResource(icon);
+        mMenuButton.setIcon(icon);
     }
 
     private void setTitle(CharSequence title) {
         mMenuItem.setTitle(title);
+        mMenuButton.setTitle(title);
     }
 
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
         mMenuItem.setEnabled(enabled);
         mMenuButton.setEnabled(enabled);
-        mMenuButton.setAlpha(enabled ? 255 : 99);
 
         for (ImageButton button : mActionButtons) {
              button.setEnabled(enabled);
              button.setAlpha(enabled ? 255 : 99);
         }
     }
 
     public void setMenuItemClickListener(View.OnClickListener listener) {
@@ -102,32 +112,28 @@ public class MenuItemActionView extends 
             button.setOnClickListener(listener);
         }
     }
 
     public void addActionButton(Drawable drawable) {
         // If this is the first icon, retain the text.
         // If not, make the menu item an icon.
         final int count = mActionButtons.size();
-        if (count == 0) {
-            mMenuItem.setVisibility(View.VISIBLE);
-            mMenuButton.setVisibility(View.GONE);
-        } else {
-            mMenuItem.setVisibility(View.GONE);
-            mMenuButton.setVisibility(View.VISIBLE);
-        }
+        mMenuItem.setVisibility(View.GONE);
+        mMenuButton.setVisibility(View.VISIBLE);
 
         if (drawable != null) {
             ImageButton button = new ImageButton(getContext(), null, R.attr.menuItemShareActionButtonStyle);
             button.setImageDrawable(drawable);
             button.setOnClickListener(mActionButtonListener);
             button.setTag(count);
 
             final int height = (int) (getResources().getDimension(R.dimen.menu_item_row_height));
             LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, height);
             params.weight = 1.0f;
             button.setLayoutParams(params);
 
+            // Fill in the action-buttons to the left of the actual menu button.
             mActionButtons.add(button);
-            addView(button);
+            addView(button, count);
         }
     }
 }
--- a/mobile/android/base/resources/layout/menu_item_action_view.xml
+++ b/mobile/android/base/resources/layout/menu_item_action_view.xml
@@ -1,27 +1,33 @@
 <?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/. -->
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <org.mozilla.gecko.menu.MenuItemDefault
-            android:id="@+id/menu_item"
-            android:layout_width="0dip"
-            android:layout_height="fill_parent"
-            android:layout_weight="2.0"
-            android:background="@drawable/action_bar_button"
-            android:clickable="true"
-            android:focusable="true"/>
+    <!-- Application icons will be added dynamically -->
+
+    <FrameLayout android:layout_width="0dip"
+                 android:layout_height="@dimen/menu_item_row_height"
+                 android:layout_weight="1.0">
 
-    <ImageButton android:id="@+id/menu_item_button"
-                 android:layout_width="0dip"
-                 android:layout_height="@dimen/menu_item_row_height"
-                 android:layout_weight="1.0"
-                 android:padding="8dip"
-                 android:scaleType="centerInside"
-                 android:background="@drawable/action_bar_button"
-                 android:layout_gravity="center_vertical"
-                 android:visibility="gone"/>
+        <org.mozilla.gecko.menu.MenuItemDefault
+                android:id="@+id/menu_item"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:background="@drawable/action_bar_button"
+                android:clickable="true"
+                android:focusable="true"/>
+
+        <org.mozilla.gecko.menu.MenuItemActionBar
+                style="@style/Widget.MenuItemSecondaryActionBar"
+                android:id="@+id/menu_item_button"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                android:background="@drawable/action_bar_button"
+                android:layout_gravity="center_vertical"
+                android:visibility="gone"/>
+
+    </FrameLayout>
 
 </merge>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/menu_secondary_action_bar.xml
@@ -0,0 +1,17 @@
+<?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/. -->
+
+<!--
+     Note: This layout is intended to be used only above 11+.
+     android:showDividers are available only 11+
+-->
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+      class="org.mozilla.gecko.menu.GeckoMenu$DefaultActionItemBar"
+      android:layout_width="@dimen/menu_item_row_width"
+      android:layout_height="@dimen/browser_toolbar_height"
+      android:orientation="horizontal"
+      android:divider="@drawable/divider_vertical"
+      android:showDividers="middle"
+      android:dividerPadding="0dip"/>
--- a/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml
+++ b/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml
@@ -15,23 +15,25 @@
           android:title="@string/back"
           android:visible="false"/>
 
     <item android:id="@+id/forward"
           android:icon="@drawable/ic_menu_forward"
           android:title="@string/forward"
           android:visible="false"/>
 
+    <item android:id="@+id/bookmark"
+          android:icon="@drawable/ic_menu_bookmark_add"
+          android:title="@string/bookmark"
+          android:showAsAction="ifRoom"/>
+
     <item android:id="@+id/share"
           android:icon="@drawable/ic_menu_share"
-          android:title="@string/share" />
-
-    <item android:id="@+id/bookmark"
-          android:icon="@drawable/ic_menu_bookmark_add"
-          android:title="@string/bookmark"/>
+          android:title="@string/share"
+          android:showAsAction="ifRoom"/>
 
     <item android:id="@+id/new_tab"
           android:icon="@drawable/ic_menu_new_tab"
           android:title="@string/new_tab"/>
 
     <item android:id="@+id/new_private_tab"
           android:icon="@drawable/ic_menu_new_private_tab"
           android:title="@string/new_private_tab"/>
--- a/mobile/android/base/resources/menu-v11/browser_app_menu.xml
+++ b/mobile/android/base/resources/menu-v11/browser_app_menu.xml
@@ -15,23 +15,25 @@
           android:title="@string/forward"
           android:showAsAction="always"/>
 
     <item android:id="@+id/reload"
           android:icon="@drawable/ic_menu_reload"
           android:title="@string/reload"
           android:showAsAction="always"/>
 
+    <item android:id="@+id/bookmark"
+          android:icon="@drawable/ic_menu_bookmark_add"
+          android:title="@string/bookmark"
+          android:showAsAction="ifRoom"/>
+
     <item android:id="@+id/share"
           android:icon="@drawable/ic_menu_share"
-          android:title="@string/share" />
-
-    <item android:id="@+id/bookmark"
-          android:icon="@drawable/ic_menu_bookmark_add"
-          android:title="@string/bookmark"/>
+          android:title="@string/share"
+          android:showAsAction="ifRoom"/>
 
     <item android:id="@+id/new_tab"
           android:icon="@drawable/ic_menu_new_tab"
           android:title="@string/new_tab"/>
 
     <item android:id="@+id/new_private_tab"
           android:icon="@drawable/ic_menu_new_private_tab"
           android:title="@string/new_private_tab"/>
--- a/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml
+++ b/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml
@@ -22,17 +22,18 @@
 
     <item android:id="@+id/bookmark"
           android:icon="@drawable/ic_menu_bookmark_add"
           android:title="@string/bookmark"
           android:showAsAction="always"/>
 
     <item android:id="@+id/share"
           android:icon="@drawable/ic_menu_share"
-          android:title="@string/share" />
+          android:title="@string/share"
+          android:showAsAction="ifRoom"/>
 
     <item android:id="@+id/new_tab"
           android:icon="@drawable/ic_menu_new_tab"
           android:title="@string/new_tab"/>
 
     <item android:id="@+id/new_private_tab"
           android:icon="@drawable/ic_menu_new_private_tab"
           android:title="@string/new_private_tab"/>
--- a/mobile/android/base/resources/values-v11/themes.xml
+++ b/mobile/android/base/resources/values-v11/themes.xml
@@ -37,17 +37,18 @@
         <item name="android:listViewStyle">@style/Widget.ListView</item>
         <item name="android:gridViewStyle">@style/Widget.GridView</item>
         <item name="android:spinnerStyle">@style/Widget.Spinner</item>
         <item name="android:spinnerItemStyle">@style/Widget.TextView.SpinnerItem</item>
         <item name="android:spinnerDropDownItemStyle">@style/Widget.DropDownItem.Spinner</item>
         <item name="menuItemActionBarStyle">@style/Widget.MenuItemActionBar</item>
         <item name="menuItemActionViewStyle">@style/Widget.MenuItemActionView</item>
         <item name="menuItemDefaultStyle">@style/Widget.MenuItemDefault</item>
-        <item name="menuItemShareActionButtonStyle">@style/Widget.MenuItemShareActionButton</item>
+        <item name="menuItemSecondaryActionBarStyle">@style/Widget.MenuItemSecondaryActionBar</item>
+        <item name="menuItemShareActionButtonStyle">@style/Widget.MenuItemSecondaryActionBar</item>
         <item name="bookmarksListViewStyle">@style/Widget.BookmarksListView</item>
         <item name="topSitesGridItemViewStyle">@style/Widget.TopSitesGridItemView</item>
         <item name="topSitesGridViewStyle">@style/Widget.TopSitesGridView</item>
         <item name="topSitesThumbnailViewStyle">@style/Widget.TopSitesThumbnailView</item>
         <item name="homeListViewStyle">@style/Widget.HomeListView</item>
         <item name="geckoMenuListViewStyle">@style/Widget.GeckoMenuListView</item>
         <item name="menuItemActionModeStyle">@style/GeckoActionBar.Button</item>
         <item name="android:actionModeStyle">@style/GeckoActionBar</item>
--- a/mobile/android/base/resources/values/attrs.xml
+++ b/mobile/android/base/resources/values/attrs.xml
@@ -18,16 +18,19 @@
         <attr name="menuItemActionModeStyle" format="reference"/>
 
         <!-- Style for MenuItemActionView -->
         <attr name="menuItemActionViewStyle" format="reference"/>
 
         <!-- Style for MenuItemDefault -->
         <attr name="menuItemDefaultStyle" format="reference"/>
 
+        <!-- Style for MenuItemActionBar when shown in SecondaryActionBar -->
+        <attr name="menuItemSecondaryActionBarStyle" format="reference"/>
+
         <!-- Style for MenuItemActionView's ShareActionButton -->
         <attr name="menuItemShareActionButtonStyle" format="reference"/>
 
         <!-- Default style for the BookmarksListView -->
         <attr name="bookmarksListViewStyle" format="reference" />
 
         <!-- Default style for the TopSitesGridItemView -->
         <attr name="topSitesGridItemViewStyle" format="reference" />
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -79,29 +79,29 @@
     </style>
 
     <style name="Widget.MenuItemActionBar">
         <item name="android:padding">8dip</item>
         <item name="android:background">@drawable/action_bar_button</item>
         <item name="android:scaleType">fitCenter</item>
     </style>
 
+    <style name="Widget.MenuItemSecondaryActionBar">
+        <item name="android:padding">8dip</item>
+        <item name="android:background">@drawable/action_bar_button</item>
+        <item name="android:scaleType">centerInside</item>
+    </style>
+
     <style name="Widget.MenuItemActionView">
         <item name="android:divider">@drawable/divider_vertical</item>
         <item name="android:showDividers">middle</item>
-        <item name="android:dividerPadding">12dip</item>
+        <item name="android:dividerPadding">0dip</item>
         <item name="android:gravity">left</item>
     </style>
 
-    <style name="Widget.MenuItemShareActionButton">
-        <item name="android:padding">8dip</item>
-        <item name="android:background">@drawable/action_bar_button</item>
-        <item name="android:scaleType">centerInside</item>
-    </style>
-
     <style name="Widget.MenuItemDefault">
         <item name="android:paddingLeft">10dip</item>
         <item name="android:paddingRight">10dip</item>
         <item name="android:drawablePadding">6dip</item>
         <item name="android:gravity">center_vertical</item>
         <item name="android:textAppearance">@style/TextAppearance</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">middle</item>
--- a/mobile/android/base/widget/GeckoActionProvider.java
+++ b/mobile/android/base/widget/GeckoActionProvider.java
@@ -54,16 +54,24 @@ public class GeckoActionProvider extends
         view.setActionButtonClickListener(mCallbacks);
 
         final PackageManager packageManager = mContext.getPackageManager();
         int historySize = dataModel.getDistinctActivityCountInHistory();
         if (historySize > 2) {
             historySize = 2;
         }
 
+        // Historical data is dependent on past selection of activities.
+        // Activity count is determined by the number of activities that can handle
+        // the particular intent. When no intent is set, the activity count is 0,
+        // while the history count can be a valid number.
+        if (historySize > dataModel.getActivityCount()) {
+            return view;
+        }
+
         for (int i = 0; i < historySize; i++) {
             view.addActionButton(dataModel.getActivity(i).loadIcon(packageManager));
         }
 
         return view;
     }
 
     public View getView() {
@@ -100,37 +108,43 @@ public class GeckoActionProvider extends
     public Intent getIntent() {
         ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
         return dataModel.getIntent();
     }
 
     public void setIntent(Intent intent) {
         ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
         dataModel.setIntent(intent);
+
+        // Inform the target listener to refresh it's UI, if needed.
+        if (mOnTargetListener != null) {
+            mOnTargetListener.onTargetSelected();
+        }
     }
 
     public void setOnTargetSelectedListener(OnTargetSelectedListener listener) {
         mOnTargetListener = listener;
     }
 
     /**
      * Listener for handling default activity / menu item clicks.
      */
     private class Callbacks implements OnMenuItemClickListener,
                                        OnClickListener {
         private void chooseActivity(int index) { 
-            if (mOnTargetListener != null)
-                mOnTargetListener.onTargetSelected();
-
             ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
             Intent launchIntent = dataModel.chooseActivity(index);
             if (launchIntent != null) {
                 launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
                 mContext.startActivity(launchIntent);
             }
+
+            if (mOnTargetListener != null) {
+                mOnTargetListener.onTargetSelected();
+            }
         }
 
         @Override
         public boolean onMenuItemClick(MenuItem item) {
             chooseActivity(item.getItemId());
             return true;
         }