Updates to SWE browser's options menu

- Changed the contents of the menu
- Iconified frequently used items
- Changes to layout and menu animation
- Removed popup menu from History and Bookmarks page
-- Added buttons to these pages to replace menu items
- Updated icons used in popup menu
- Added menu option to save link to homepage
- Add bookmark icon color depicts if bookmark exists

Change-Id: I37226506737647367f71159f1a439cc3fca4ae03
diff --git a/src/com/android/browser/ActivityController.java b/src/com/android/browser/ActivityController.java
index ac248b8..817857a 100644
--- a/src/com/android/browser/ActivityController.java
+++ b/src/com/android/browser/ActivityController.java
@@ -71,4 +71,5 @@
 
     boolean dispatchGenericMotionEvent(MotionEvent ev);
 
+    void invalidateOptionsMenu();
 }
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 351cb96..3b95ee9 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -297,9 +297,9 @@
     }
 
     @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        return mController.onCreateOptionsMenu(menu);
+    public void invalidateOptionsMenu() {
+        super.invalidateOptionsMenu();
+        mController.invalidateOptionsMenu();
     }
 
     @Override
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 16eae77..7abe07b 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -45,6 +45,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Button;
 import android.widget.ExpandableListView;
 import android.widget.ExpandableListView.OnChildClickListener;
 import android.widget.Toast;
@@ -169,31 +170,6 @@
         }
     }
 
-    //add for carrier feature which adds new bookmark/folder function.
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        super.onCreateOptionsMenu(menu, inflater);
-        inflater.inflate(R.menu.bookmark, menu);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        final Activity activity = getActivity();
-        if (item.getItemId() == R.id.add_bookmark_menu_id) {
-            Intent intent = new Intent(activity, AddBookmarkPage.class);
-            intent.putExtra(BrowserContract.Bookmarks.URL, "http://");
-            intent.putExtra(BrowserContract.Bookmarks.TITLE, "");
-            intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
-            activity.startActivity(intent);
-        }
-        if (item.getItemId() == R.id.new_bmfolder_menu_id) {
-            Intent intent = new Intent(activity, AddBookmarkFolder.class);
-            intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
-            activity.startActivity(intent);
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
     @Override
     public boolean onContextItemSelected(MenuItem item) {
         if (!(item.getMenuInfo() instanceof BookmarkContextMenuInfo)) {
@@ -373,7 +349,6 @@
         }
         Bundle args = getArguments();
         mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false);
-        setHasOptionsMenu(true);
         if (mCallbacks == null && getActivity() instanceof CombinedBookmarksCallbacks) {
             mCallbacks = new CombinedBookmarksCallbackWrapper(
                     (CombinedBookmarksCallbacks) getActivity());
@@ -423,6 +398,7 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
+        final Activity activity = getActivity();
         mRoot = inflater.inflate(R.layout.bookmarks, container, false);
         mEmptyView = mRoot.findViewById(android.R.id.empty);
 
@@ -432,6 +408,28 @@
         mGrid.setBreadcrumbController(this);
         setEnableContextMenu(mEnableContextMenu);
 
+        Button btn = (Button) mRoot.findViewById(R.id.add_bookmark_button);
+        btn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                Intent intent = new Intent(activity, AddBookmarkPage.class);
+                intent.putExtra(BrowserContract.Bookmarks.URL, "http://");
+                intent.putExtra(BrowserContract.Bookmarks.TITLE, "");
+                intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
+                activity.startActivity(intent);
+            }
+        });
+
+        btn = (Button) mRoot.findViewById(R.id.new_bmfolder_button);
+        btn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                Intent intent = new Intent(activity, AddBookmarkFolder.class);
+                intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId);
+                activity.startActivity(intent);
+            }
+        });
+
         // Start the loaders
         LoaderManager lm = getLoaderManager();
         lm.restartLoader(LOADER_ACCOUNTS, null, this);
@@ -604,7 +602,6 @@
         mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail);
         int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop);
         mRoot.setPadding(0, paddingTop, 0, 0);
-        getActivity().invalidateOptionsMenu();
     }
 
     /**
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index fa25aca..193d040 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -51,6 +51,7 @@
 import android.widget.AdapterView.AdapterContextMenuInfo;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
+import android.widget.Button;
 import android.widget.ExpandableListView;
 import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
 import android.widget.ExpandableListView.OnChildClickListener;
@@ -196,8 +197,6 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
-        setHasOptionsMenu(true);
-
         Bundle args = getArguments();
         mDisableNewWindow = args.getBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, false);
         int mvlimit = getResources().getInteger(R.integer.most_visits_limit);
@@ -216,6 +215,13 @@
         } else {
             inflateSinglePane();
         }
+        Button btn = (Button) mRoot.findViewById(R.id.clear_history_button);
+        btn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                promptToClearHistory();
+            }
+        });
 
         // Start the loaders
         getLoaderManager().restartLoader(LOADER_HISTORY, null, this);
@@ -285,12 +291,6 @@
         getLoaderManager().destroyLoader(LOADER_MOST_VISITED);
     }
 
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        super.onCreateOptionsMenu(menu, inflater);
-        inflater.inflate(R.menu.history, menu);
-    }
-
     void promptToClearHistory() {
         final ContentResolver resolver = getActivity().getContentResolver();
         final ClearHistoryTask clear = new ClearHistoryTask(resolver);
@@ -310,15 +310,6 @@
         dialog.show();
     }
 
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == R.id.clear_history_menu_id) {
-            promptToClearHistory();
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
     static class ClearHistoryTask extends Thread {
         ContentResolver mResolver;
 
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 292a46d..b0657c9 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -79,6 +79,8 @@
 import android.webkit.MimeTypeMap;
 import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient.CustomViewCallback;
+import android.widget.Button;
+import android.widget.EditText;
 import android.widget.Toast;
 
 import org.codeaurora.swe.CookieManager;
@@ -103,6 +105,8 @@
 import com.android.browser.provider.BrowserProvider2.Thumbnails;
 import com.android.browser.provider.SnapshotProvider.Snapshots;
 import com.android.browser.reflect.ReflectHelper;
+import com.android.browser.appmenu.AppMenuHandler;
+import com.android.browser.appmenu.AppMenuPropertiesDelegate;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -123,7 +127,8 @@
  * Controller for browser
  */
 public class Controller
-        implements WebViewController, UiController, ActivityController {
+        implements WebViewController, UiController, ActivityController,
+        AppMenuPropertiesDelegate {
 
     private static final String LOGTAG = "Controller";
     private static final String SEND_APP_ID_EXTRA =
@@ -206,6 +211,9 @@
 
     private boolean mMenuIsDown;
 
+    private boolean mWasInPageLoad = false;
+    private AppMenuHandler mAppMenuHandler;
+
     // For select and find, we keep track of the ActionMode so that
     // finish() can be called as desired.
     private ActionMode mActionMode;
@@ -275,6 +283,7 @@
 
         mNetworkHandler = new NetworkStateHandler(mActivity, this);
         mHomepageHandler = new HomepageHandler(browser, this);
+        mAppMenuHandler = new AppMenuHandler(browser, this, R.menu.browser);
     }
 
     @Override
@@ -654,6 +663,7 @@
         mConfigChanged = true;
         // update the menu in case of a locale change
         mActivity.invalidateOptionsMenu();
+        mAppMenuHandler.hideAppMenu();
         if (mOptionsMenuOpen) {
             mActivity.closeOptionsMenu();
             mHandler.sendMessageDelayed(mHandler.obtainMessage(OPEN_MENU), 100);
@@ -973,8 +983,14 @@
             // any sub frames so calls to onProgressChanges may continue after
             // onPageFinished has executed)
             if (tab.inPageLoad()) {
+                mWasInPageLoad = true;
                 updateInLoadMenuItems(mCachedMenu, tab);
-            } else if (mActivityPaused && pauseWebViewTimers(tab)) {
+            } else if (mWasInPageLoad) {
+                mWasInPageLoad = false;
+                updateInLoadMenuItems(mCachedMenu, tab);
+            }
+
+            if (mActivityPaused && pauseWebViewTimers(tab)) {
                 // pause the WebView timer and release the wake lock if it is
                 // finished while BrowserActivity is in pause state.
                 releaseWakeLock();
@@ -1001,7 +1017,10 @@
                 // still loading
                 // updating the progress and
                 // update the menu items.
+                mWasInPageLoad = false;
                 updateInLoadMenuItems(mCachedMenu, tab);
+            } else {
+                mWasInPageLoad = true;
             }
         }
         mUi.onProgressChanged(tab);
@@ -1780,10 +1799,22 @@
             dest.setIcon(src.getIcon());
             dest.setTitle(src.getTitle());
         }
+        mActivity.invalidateOptionsMenu();
+    }
+
+    public void invalidateOptionsMenu() {
+        mAppMenuHandler.invalidateAppMenu();
     }
 
     @Override
     public boolean onPrepareOptionsMenu(Menu menu) {
+        // Software menu key (toolbar key)
+        mAppMenuHandler.showAppMenu(mActivity.findViewById(R.id.more_browser_settings), false, false);
+        return true;
+    }
+
+    @Override
+    public void prepareMenu(Menu menu) {
         updateInLoadMenuItems(menu, getCurrentTab());
         // hold on to the menu reference here; it is used by the page callbacks
         // to update the menu based on loading state
@@ -1809,12 +1840,53 @@
                 break;
         }
         mCurrentMenuState = mMenuState;
-        return mUi.onPrepareOptionsMenu(menu);
+        mUi.onPrepareOptionsMenu(menu);
+    }
+
+    private void setMenuItemVisibility(Menu menu, int id,
+                                       boolean visibility) {
+        MenuItem item = menu.findItem(id);
+        if (item != null) {
+            item.setVisible(visibility);
+        }
+    }
+
+    private int lookupBookmark(String title, String url) {
+        final ContentResolver cr = getActivity().getContentResolver();
+
+        Cursor cursor = cr.query(BrowserContract.Bookmarks.CONTENT_URI,
+                BookmarksLoader.PROJECTION,
+                "title = ? OR url = ?",
+                new String[] {
+                        title, url
+                },
+                null);
+
+        if (cursor == null) {
+            return 0;
+        }
+
+        return cursor.getCount();
+    }
+
+    private void resetMenuItems(Menu menu) {
+        setMenuItemVisibility(menu, R.id.history_menu_id, true);
+        setMenuItemVisibility(menu, R.id.find_menu_id, true);
+
+        WebView w = getCurrentTopWebView();
+        MenuItem bookmark_icon = menu.findItem(R.id.bookmark_this_page_id);
+
+        String title = w.getTitle();
+        String url = w.getUrl();
+        if (title != null && url != null && lookupBookmark(title, url) > 0) {
+            bookmark_icon.setChecked(true);
+        } else {
+            bookmark_icon.setChecked(false);
+        }
     }
 
     @Override
     public void updateMenuState(Tab tab, Menu menu) {
-        boolean canGoBack = false;
         boolean canGoForward = false;
         boolean isDesktopUa = false;
         boolean isLive = false;
@@ -1822,33 +1894,20 @@
         // items defined in res/menu/browser.xml should be enabled
         boolean isLiveScheme = false;
         boolean isPageFinished = false;
-        boolean isSavable = false;
+
+        resetMenuItems(menu);
+
         if (tab != null) {
-            canGoBack = tab.canGoBack();
             canGoForward = tab.canGoForward();
             isDesktopUa = mSettings.hasDesktopUseragent(tab.getWebView());
             isLive = !tab.isSnapshot();
             isLiveScheme = UrlUtils.isLiveScheme(tab.getWebView().getUrl());
-            isPageFinished = tab.getPageFinishedStatus();
-            isSavable = tab.getWebView().isSavable();
+            isPageFinished = (tab.getPageFinishedStatus() || !tab.inPageLoad());
         }
-        final MenuItem back = menu.findItem(R.id.back_menu_id);
-        back.setEnabled(canGoBack);
-
-        final MenuItem home = menu.findItem(R.id.homepage_menu_id);
 
         final MenuItem forward = menu.findItem(R.id.forward_menu_id);
         forward.setEnabled(canGoForward);
 
-        final MenuItem source = menu.findItem(isInLoad() ? R.id.stop_menu_id
-                : R.id.reload_menu_id);
-        final MenuItem dest = menu.findItem(R.id.stop_reload_menu_id);
-        if (source != null && dest != null) {
-            dest.setTitle(source.getTitle());
-            dest.setIcon(source.getIcon());
-        }
-        menu.setGroupVisible(R.id.NAV_MENU, isLive);
-
         // decide whether to show the share link option
         PackageManager pm = mActivity.getPackageManager();
         Intent send = new Intent(Intent.ACTION_SEND);
@@ -1866,8 +1925,13 @@
         final MenuItem uaSwitcher = menu.findItem(R.id.ua_desktop_menu_id);
         uaSwitcher.setChecked(isDesktopUa);
         menu.setGroupVisible(R.id.LIVE_MENU, isLive && isLiveScheme);
+        menu.setGroupVisible(R.id.NAV_MENU, isLive && isLiveScheme);
+        setMenuItemVisibility(menu, R.id.find_menu_id, isLive && isLiveScheme);
         menu.setGroupVisible(R.id.SNAPSHOT_MENU, !isLive);
-        menu.setGroupEnabled(R.id.OFFLINE_READING, isLive && isLiveScheme && isPageFinished && isSavable);
+        setMenuItemVisibility(menu, R.id.add_to_homescreen,
+                isLive && isLiveScheme && isPageFinished);
+        setMenuItemVisibility(menu, R.id.save_snapshot_menu_id,
+                isLive && isLiveScheme && isPageFinished);
         // history and snapshots item are the members of COMBO menu group,
         // so if show history item, only make snapshots item invisible.
         menu.findItem(R.id.snapshots_menu_id).setVisible(false);
@@ -1901,10 +1965,6 @@
                 openIncognitoTab();
                 break;
 
-            case R.id.close_other_tabs_id:
-                closeOtherTabs();
-                break;
-
             case R.id.goto_menu_id:
                 editUrl();
                 break;
@@ -1921,7 +1981,7 @@
                 bookmarksOrHistoryPicker(ComboViews.Snapshots);
                 break;
 
-            case R.id.add_bookmark_menu_id:
+            case R.id.bookmark_this_page_id:
                 bookmarkCurrentPage();
                 break;
 
@@ -1938,10 +1998,6 @@
                 }
                 break;
 
-            case R.id.back_menu_id:
-                getCurrentTab().goBack();
-                break;
-
             case R.id.forward_menu_id:
                 getCurrentTab().goForward();
                 break;
@@ -2068,6 +2124,34 @@
                 builder.create().show();
                 break;
 
+            case R.id.add_to_homescreen:
+                final WebView w = getCurrentTopWebView();
+                final EditText input = new EditText(getContext());
+                input.setText(w.getTitle());
+                new AlertDialog.Builder(getContext())
+                        .setTitle("Add to homescreen")
+                        .setMessage("Title")
+                        .setView(input)
+                        .setPositiveButton("Add", new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int whichButton) {
+                                mActivity.sendBroadcast(BookmarkUtils.createAddToHomeIntent(
+                                        getContext(),
+                                        w.getUrl(),
+                                        input.getText().toString(),
+                                        w.getViewportBitmap(),
+                                        w.getFavicon()));
+
+                                mActivity.startActivity(new Intent(Intent.ACTION_MAIN)
+                                        .addCategory(Intent.CATEGORY_HOME));
+                            }})
+                        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int whichButton) {
+                                // Do nothing.
+                            }
+                        })
+                        .show();
+                break;
+
             default:
                 return false;
         }
@@ -3130,6 +3214,13 @@
      */
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0) {
+            // Hardware menu key
+            mAppMenuHandler.showAppMenu(mActivity.findViewById(R.id.more_browser_settings),
+                    true, false);
+            return true;
+        }
+
         boolean noModifiers = event.hasNoModifiers();
         // Even if MENU is already held down, we need to call to super to open
         // the IME on long press.
@@ -3359,4 +3450,13 @@
         return mBlockEvents;
     }
 
+    @Override
+    public boolean shouldShowAppMenu() {
+        return true;
+    }
+
+    @Override
+    public int getMenuThemeResourceId() {
+        return R.style.OverflowMenuTheme;
+    }
 }
diff --git a/src/com/android/browser/NavScreen.java b/src/com/android/browser/NavScreen.java
index b11cc4a..64243e3 100644
--- a/src/com/android/browser/NavScreen.java
+++ b/src/com/android/browser/NavScreen.java
@@ -80,12 +80,13 @@
     }
 
     protected void showMenu() {
-        PopupMenu popup = new PopupMenu(getContext(), mMore);
-        Menu menu = popup.getMenu();
-        popup.getMenuInflater().inflate(R.menu.browser, menu);
-        mUiController.updateMenuState(mUiController.getCurrentTab(), menu);
-        popup.setOnMenuItemClickListener(this);
-        popup.show();
+        if (mUiController instanceof Controller) {
+            PopupMenu popup = new PopupMenu(getContext(), mMore);
+            Menu menu = popup.getMenu();
+
+            Controller controller = (Controller) mUiController;
+            controller.onPrepareOptionsMenu(menu);
+        }
     }
 
     @Override
diff --git a/src/com/android/browser/NavigationBarPhone.java b/src/com/android/browser/NavigationBarPhone.java
index 076e4ad..fe5ca28 100644
--- a/src/com/android/browser/NavigationBarPhone.java
+++ b/src/com/android/browser/NavigationBarPhone.java
@@ -192,7 +192,6 @@
         Menu menu = mPopupMenu.getMenu();
         if (activity.onPrepareOptionsMenu(menu)) {
             mOverflowMenuShowing = true;
-            mPopupMenu.show();
         }
     }
 
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index a2799b3..ca478c2 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -160,42 +160,32 @@
         return true;
     }
 
+    private void setMenuItemVisibility(Menu menu, int id,
+                                       boolean visibility) {
+        MenuItem item = menu.findItem(id);
+        if (item != null) {
+            item.setVisible(visibility);
+        }
+    }
+
     @Override
     public void updateMenuState(Tab tab, Menu menu) {
         MenuItem bm = menu.findItem(R.id.bookmarks_menu_id);
         if (bm != null) {
             bm.setVisible(!showingNavScreen());
         }
-        MenuItem abm = menu.findItem(R.id.add_bookmark_menu_id);
-        if (abm != null) {
-            abm.setVisible((tab != null) && !tab.isSnapshot() && !showingNavScreen());
-        }
         MenuItem info = menu.findItem(R.id.page_info_menu_id);
         if (info != null) {
             info.setVisible(false);
         }
-        MenuItem newtab = menu.findItem(R.id.new_tab_menu_id);
-        if (newtab != null) {
-            newtab.setVisible(false);
-        }
-        MenuItem incognito = menu.findItem(R.id.incognito_menu_id);
-        if (incognito != null) {
-            incognito.setVisible(showingNavScreen());
-        }
-        MenuItem closeOthers = menu.findItem(R.id.close_other_tabs_id);
-        if (closeOthers != null) {
-            boolean isLastTab = true;
-            if (tab != null) {
-                isLastTab = (mTabControl.getTabCount() <= 1);
-            }
-            closeOthers.setEnabled(!isLastTab);
-        }
+
         if (showingNavScreen()) {
+            setMenuItemVisibility(menu, R.id.history_menu_id, false);
+            setMenuItemVisibility(menu, R.id.find_menu_id, false);
             menu.setGroupVisible(R.id.LIVE_MENU, false);
-            menu.setGroupVisible(R.id.OFFLINE_READING, false);
+            setMenuItemVisibility(menu, R.id.save_snapshot_menu_id, false);
             menu.setGroupVisible(R.id.SNAPSHOT_MENU, false);
             menu.setGroupVisible(R.id.NAV_MENU, false);
-            menu.setGroupVisible(R.id.COMBO_MENU, true);
         }
     }
 
diff --git a/src/com/android/browser/appmenu/AppMenu.java b/src/com/android/browser/appmenu/AppMenu.java
index 3f3ac68..a0ff710 100644
--- a/src/com/android/browser/appmenu/AppMenu.java
+++ b/src/com/android/browser/appmenu/AppMenu.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -26,7 +26,7 @@
 import android.widget.PopupWindow.OnDismissListener;
 
 import org.chromium.base.SysUtils;
-import org.chromium.chrome.R;
+import com.android.browser.R;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -112,13 +112,7 @@
         // drawable here even though our style says @null we should use this padding instead...
         Drawable originalBgDrawable = mPopup.getBackground();
 
-        // Need to explicitly set the background here.  Relying on it being set in the style caused
-        // an incorrectly drawn background.
-        if (isByHardwareButton) {
-            mPopup.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.menu_bg));
-        } else {
-            mPopup.setBackgroundDrawable(
-                    context.getResources().getDrawable(R.drawable.edge_menu_bg));
+        if (!isByHardwareButton) {
             mPopup.setAnimationStyle(R.style.OverflowMenuAnim);
         }
 
@@ -189,6 +183,30 @@
         }
     }
 
+    public void invalidate(Context context, Menu menu) {
+        assert(mMenu == menu);
+        // Extract visible items from the Menu.
+        int numItems = mMenu.size();
+        List<MenuItem> menuItems = new ArrayList<MenuItem>();
+        for (int i = 0; i < numItems; ++i) {
+            MenuItem item = mMenu.getItem(i);
+            if (item.isVisible()) {
+                menuItems.add(item);
+            }
+        }
+
+        boolean showMenuButton = !mIsByHardwareButton;
+        if (!SHOW_SW_MENU_BUTTON) showMenuButton = false;
+
+        mAdapter = new AppMenuAdapter(
+                this, menuItems, LayoutInflater.from(context), showMenuButton);
+        mPopup.setAdapter(mAdapter);
+
+        mPopup.show();
+        mPopup.getListView().setItemsCanFocus(true);
+        mPopup.getListView().setOnKeyListener(this);
+    }
+
     private void setPopupOffset(
             ListPopupWindow popup, int screenRotation, Rect appRect, Rect padding) {
         int[] anchorLocation = new int[2];
@@ -202,10 +220,10 @@
             switch (screenRotation) {
                 case Surface.ROTATION_0:
                 case Surface.ROTATION_180:
-                    horizontalOffset += (appRect.width() - mPopup.getWidth()) / 2;
+                    horizontalOffset += (appRect.width() - popup.getWidth()) / 2;
                     break;
                 case Surface.ROTATION_90:
-                    horizontalOffset += appRect.width() - mPopup.getWidth();
+                    horizontalOffset += appRect.width() - popup.getWidth();
                     break;
                 case Surface.ROTATION_270:
                     break;
@@ -216,7 +234,8 @@
             popup.setHorizontalOffset(horizontalOffset);
             // The menu is displayed above the anchored view, so shift the menu up by the bottom
             // padding of the background.
-            popup.setVerticalOffset(-padding.bottom);
+            int verticalOffset = appRect.height() - popup.getHeight() + padding.bottom;
+            popup.setVerticalOffset(verticalOffset);
         } else {
             // The menu is displayed over and below the anchored view, so shift the menu up by the
             // height of the anchor view.
@@ -321,7 +340,8 @@
                         padding.top + padding.bottom);
             }
         } else {
-            mPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+            mPopup.setHeight(numMenuItems * (mItemRowHeight + mItemDividerHeight) +
+                        padding.top + padding.bottom);
         }
     }
 
diff --git a/src/com/android/browser/appmenu/AppMenuAdapter.java b/src/com/android/browser/appmenu/AppMenuAdapter.java
index 2b60292..6a8cdb4 100644
--- a/src/com/android/browser/appmenu/AppMenuAdapter.java
+++ b/src/com/android/browser/appmenu/AppMenuAdapter.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -15,6 +15,7 @@
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.CheckBox;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
@@ -22,7 +23,7 @@
 import android.widget.TextView;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import com.android.browser.R;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.interpolators.BakedBezierInterpolator;
 
@@ -32,7 +33,7 @@
  * ListAdapter to customize the view of items in the list.
  */
 class AppMenuAdapter extends BaseAdapter {
-    private static final int VIEW_TYPE_COUNT = 5;
+    private static final int VIEW_TYPE_COUNT = 9;
 
     /**
      * Regular Android menu item that contains a title and an icon if icon is specified.
@@ -44,18 +45,34 @@
      */
     private static final int TITLE_BUTTON_MENU_ITEM = 1;
     /**
+     * Menu item that has one button plus menu button. Every one of these buttons is displayed as an icon.
+     */
+    private static final int ONE_BUTTON_PLUS_MENU_ITEM = 2;
+    /**
+     * Menu item that has two buttons. Every one of these buttons is displayed as an icon.
+     */
+    private static final int TWO_BUTTON_MENU_ITEM = 3;
+    /**
+     * Menu item that has two buttons plus menu. Every one of these buttons is displayed as an icon.
+     */
+    private static final int TWO_BUTTON_PLUS_MENU_ITEM = 4;
+    /**
      * Menu item that has three buttons. Every one of these buttons is displayed as an icon.
      */
-    private static final int THREE_BUTTON_MENU_ITEM = 2;
+    private static final int THREE_BUTTON_MENU_ITEM = 5;
+    /**
+     * Menu item that has three buttons plus menu. Every one of these buttons is displayed as an icon.
+     */
+    private static final int THREE_BUTTON_PLUS_MENU_ITEM = 6;
     /**
      * Menu item that has four buttons. Every one of these buttons is displayed as an icon.
      */
-    private static final int FOUR_BUTTON_MENU_ITEM = 3;
+    private static final int FOUR_BUTTON_MENU_ITEM = 7;
     /**
      * Menu item that has two buttons, the first one is a title and the second is a menu icon.
      * This is similar to {@link #TITLE_BUTTON_MENU_ITEM} but has some slight layout differences.
      */
-    private static final int MENU_BUTTON_MENU_ITEM = 4;
+    private static final int MENU_BUTTON_MENU_ITEM = 8;
 
     /** MenuItem Animation Constants */
     private static final int ENTER_ITEM_DURATION_MS = 350;
@@ -100,14 +117,21 @@
         MenuItem item = getItem(position);
         boolean hasMenuButton = mShowMenuButton && position == 0;
         int viewCount = item.hasSubMenu() ? item.getSubMenu().size() : 1;
-        if (hasMenuButton) viewCount++;
 
         if (viewCount == 4) {
             return FOUR_BUTTON_MENU_ITEM;
         } else if (viewCount == 3) {
+            if (hasMenuButton) {
+                return THREE_BUTTON_PLUS_MENU_ITEM;
+            }
             return THREE_BUTTON_MENU_ITEM;
         } else if (viewCount == 2) {
-            return hasMenuButton ? MENU_BUTTON_MENU_ITEM : TITLE_BUTTON_MENU_ITEM;
+            if (hasMenuButton) {
+                return TWO_BUTTON_PLUS_MENU_ITEM;
+            }
+            return TWO_BUTTON_MENU_ITEM;
+        } else if (hasMenuButton) {
+            return ONE_BUTTON_PLUS_MENU_ITEM;
         }
         return STANDARD_MENU_ITEM;
     }
@@ -137,6 +161,7 @@
                     convertView = mInflater.inflate(R.layout.menu_item, parent, false);
                     holder.text = (TextView) convertView.findViewById(R.id.menu_item_text);
                     holder.image = (AppMenuItemIcon) convertView.findViewById(R.id.menu_item_icon);
+                    holder.checkbox = (CheckBox) convertView.findViewById(R.id.menu_item_checkbox);
                     convertView.setTag(holder);
                     convertView.setTag(R.id.menu_item_enter_anim_id,
                             buildStandardItemEnterAnimator(convertView, position));
@@ -154,7 +179,15 @@
                 Drawable icon = item.getIcon();
                 holder.image.setImageDrawable(icon);
                 holder.image.setVisibility(icon == null ? View.GONE : View.VISIBLE);
-                holder.image.setChecked(item.isChecked());
+
+                holder.checkbox.setVisibility(item.isCheckable() ? View.VISIBLE : View.GONE);
+                holder.checkbox.setChecked(item.isChecked());
+                holder.checkbox.setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mAppMenu.onItemClick(item);
+                    }
+                });
 
                 holder.text.setText(item.getTitle());
                 boolean isEnabled = item.isEnabled();
@@ -164,6 +197,65 @@
                 convertView.setEnabled(isEnabled);
                 break;
             }
+            case ONE_BUTTON_PLUS_MENU_ITEM: {
+                TwoButtonMenuItemViewHolder holder = null;
+                if (convertView == null) {
+                    holder = new TwoButtonMenuItemViewHolder();
+                    convertView = mInflater.inflate(R.layout.one_button_plus_menu_item, parent, false);
+                    holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one);
+                    holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two);
+                    convertView.setTag(holder);
+                    convertView.setTag(R.id.menu_item_enter_anim_id,
+                            buildIconItemEnterAnimator(holder.buttons, hasMenuButton));
+                } else {
+                    holder = (TwoButtonMenuItemViewHolder) convertView.getTag();
+                }
+                setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0));
+                setupMenuButton(holder.buttons[1]);
+                convertView.setFocusable(false);
+                convertView.setEnabled(false);
+                break;
+            }
+            case TWO_BUTTON_MENU_ITEM: {
+                TwoButtonMenuItemViewHolder holder = null;
+                if (convertView == null) {
+                    holder = new TwoButtonMenuItemViewHolder();
+                    convertView = mInflater.inflate(R.layout.two_button_menu_item, parent, false);
+                    holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one);
+                    holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two);
+                    convertView.setTag(holder);
+                    convertView.setTag(R.id.menu_item_enter_anim_id,
+                            buildIconItemEnterAnimator(holder.buttons, hasMenuButton));
+                } else {
+                    holder = (TwoButtonMenuItemViewHolder) convertView.getTag();
+                }
+                setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0));
+                setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1));
+                convertView.setFocusable(false);
+                convertView.setEnabled(false);
+                break;
+            }
+            case TWO_BUTTON_PLUS_MENU_ITEM: {
+                ThreeButtonMenuItemViewHolder holder = null;
+                if (convertView == null) {
+                    holder = new ThreeButtonMenuItemViewHolder();
+                    convertView = mInflater.inflate(R.layout.two_button_plus_menu_item, parent, false);
+                    holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one);
+                    holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two);
+                    holder.buttons[2] = (ImageButton) convertView.findViewById(R.id.button_three);
+                    convertView.setTag(holder);
+                    convertView.setTag(R.id.menu_item_enter_anim_id,
+                            buildIconItemEnterAnimator(holder.buttons, hasMenuButton));
+                } else {
+                    holder = (ThreeButtonMenuItemViewHolder) convertView.getTag();
+                }
+                setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0));
+                setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1));
+                setupMenuButton(holder.buttons[2]);
+                convertView.setFocusable(false);
+                convertView.setEnabled(false);
+                break;
+            }
             case THREE_BUTTON_MENU_ITEM: {
                 ThreeButtonMenuItemViewHolder holder = null;
                 if (convertView == null) {
@@ -180,12 +272,31 @@
                 }
                 setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0));
                 setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1));
-                if (hasMenuButton) {
-                    setupMenuButton(holder.buttons[3]);
+                setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2));
+                convertView.setFocusable(false);
+                convertView.setEnabled(false);
+                break;
+            }
+            case THREE_BUTTON_PLUS_MENU_ITEM: {
+                FourButtonMenuItemViewHolder holder = null;
+                if (convertView == null) {
+                    holder = new FourButtonMenuItemViewHolder();
+                    convertView = mInflater.inflate(R.layout.three_button_plus_menu_item, parent, false);
+                    holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one);
+                    holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two);
+                    holder.buttons[2] = (ImageButton) convertView.findViewById(R.id.button_three);
+                    holder.buttons[3] = (ImageButton) convertView.findViewById(R.id.button_four);
+                    convertView.setTag(holder);
+                    convertView.setTag(R.id.menu_item_enter_anim_id,
+                            buildIconItemEnterAnimator(holder.buttons, hasMenuButton));
                 } else {
-                    setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2));
+                    holder = (FourButtonMenuItemViewHolder) convertView.getTag();
                 }
 
+                setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0));
+                setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1));
+                setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2));
+                setupMenuButton(holder.buttons[3]);
                 convertView.setFocusable(false);
                 convertView.setEnabled(false);
                 break;
@@ -208,11 +319,7 @@
                 setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0));
                 setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1));
                 setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2));
-                if (hasMenuButton) {
-                    setupMenuButton(holder.buttons[3]);
-                } else {
-                    setupImageButton(holder.buttons[3], item.getSubMenu().getItem(3));
-                }
+                setupImageButton(holder.buttons[3], item.getSubMenu().getItem(3));
                 convertView.setFocusable(false);
                 convertView.setEnabled(false);
                 break;
@@ -274,6 +381,7 @@
         button.setContentDescription(item.getTitle());
         button.setEnabled(item.isEnabled());
         button.setFocusable(item.isEnabled());
+        button.setSelected(item.isChecked());
         button.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -283,8 +391,7 @@
     }
 
     private void setupMenuButton(ImageButton button) {
-        button.setImageResource(R.drawable.btn_menu_pressed);
-        button.setContentDescription(button.getResources().getString(R.string.menu_dismiss_btn));
+        button.setImageResource(R.drawable.ic_menu_overflow);
         button.setEnabled(true);
         button.setFocusable(true);
         button.setOnClickListener(new OnClickListener() {
@@ -294,10 +401,6 @@
             }
         });
 
-        // Set the button layout to make it properly line up with any underlying menu button
-        ApiCompatibilityUtils.setPaddingRelative(
-                button, (int) (MENU_BUTTON_START_PADDING_DP * mDpToPx), 0, 0, 0);
-        button.getLayoutParams().width = (int) (MENU_BUTTON_WIDTH_DP * mDpToPx);
         button.setScaleType(ScaleType.CENTER);
     }
 
@@ -339,7 +442,7 @@
      * @return             The {@link Animator}.
      */
     private Animator buildIconItemEnterAnimator(final ImageView[] views, boolean skipLastItem) {
-        final boolean rtl = LocalizationUtils.isLayoutRtl();
+        final boolean rtl = false; //LocalizationUtils.isLayoutRtl();
         final float offsetXPx = ENTER_STANDARD_ITEM_OFFSET_X_DP * mDpToPx * (rtl ? -1.f : 1.f);
         final int maxViewsToAnimate = views.length - (skipLastItem ? 1 : 0);
 
@@ -379,6 +482,11 @@
     static class StandardMenuItemViewHolder {
         public TextView text;
         public AppMenuItemIcon image;
+        public CheckBox checkbox;
+    }
+
+    static class TwoButtonMenuItemViewHolder {
+        public ImageButton[] buttons = new ImageButton[2];
     }
 
     static class ThreeButtonMenuItemViewHolder {
diff --git a/src/com/android/browser/appmenu/AppMenuButtonHelper.java b/src/com/android/browser/appmenu/AppMenuButtonHelper.java
index a63e2a5..364183a 100644
--- a/src/com/android/browser/appmenu/AppMenuButtonHelper.java
+++ b/src/com/android/browser/appmenu/AppMenuButtonHelper.java
@@ -2,14 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnTouchListener;
 
-import org.chromium.chrome.browser.UmaBridge;
-
 /**
  * A helper class for a menu button to decide when to show the app menu and forward touch
  * events.
@@ -46,10 +44,6 @@
     private boolean showAppMenu(boolean startDragging) {
         if (!mMenuHandler.isAppMenuShowing() &&
                 mMenuHandler.showAppMenu(mMenuButton, false, startDragging)) {
-            // Initial start dragging can be canceled in case if it was just single tap.
-            // So we only record non-dragging here, and will deal with those dragging cases in
-            // AppMenuDragHelper class.
-            if (!startDragging) UmaBridge.usingMenu(false, false);
 
             if (mOnAppMenuShownListener != null) {
                 mOnAppMenuShownListener.run();
@@ -94,13 +88,6 @@
             default:
         }
 
-        // If user starts to drag on this menu button, ACTION_DOWN and all the subsequent touch
-        // events are received here. We need to forward this event to the app menu to handle
-        // dragging correctly.
-        AppMenuDragHelper dragHelper = mMenuHandler.getAppMenuDragHelper();
-        if (dragHelper != null) {
-            isTouchEventConsumed |= dragHelper.handleDragging(event);
-        }
         return isTouchEventConsumed;
     }
 }
\ No newline at end of file
diff --git a/src/com/android/browser/appmenu/AppMenuDragHelper.java b/src/com/android/browser/appmenu/AppMenuDragHelper.java
index 44e642a..ee2a8c7 100644
--- a/src/com/android/browser/appmenu/AppMenuDragHelper.java
+++ b/src/com/android/browser/appmenu/AppMenuDragHelper.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.animation.TimeAnimator;
 import android.annotation.SuppressLint;
@@ -18,8 +18,7 @@
 import android.widget.ListPopupWindow;
 import android.widget.ListView;
 
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UmaBridge;
+import com.android.browser.R;
 
 import java.util.ArrayList;
 
@@ -158,7 +157,6 @@
         if (!mIsSingleTapUpHappened) {
             mGestureSingleTapDetector.onTouchEvent(event);
             if (mIsSingleTapUpHappened) {
-                UmaBridge.usingMenu(false, false);
                 finishDragging();
             }
         }
@@ -182,7 +180,6 @@
         didPerformClick = menuItemAction(roundedRawX, roundedRawY, itemAction);
 
         if (eventActionMasked == MotionEvent.ACTION_UP && !didPerformClick) {
-            UmaBridge.usingMenu(false, true);
             mAppMenu.dismiss();
         } else if (eventActionMasked == MotionEvent.ACTION_MOVE) {
             // Auto scrolling on the top or the bottom of the listView.
@@ -245,7 +242,6 @@
                     break;
                 case ITEM_ACTION_PERFORM:
                     if (shouldPerform) {
-                        UmaBridge.usingMenu(false, true);
                         itemView.performClick();
                         didPerformClick = true;
                     }
diff --git a/src/com/android/browser/appmenu/AppMenuHandler.java b/src/com/android/browser/appmenu/AppMenuHandler.java
index 4e2c465..94a429a 100644
--- a/src/com/android/browser/appmenu/AppMenuHandler.java
+++ b/src/com/android/browser/appmenu/AppMenuHandler.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.app.Activity;
 import android.content.res.TypedArray;
@@ -17,8 +17,6 @@
 
 import com.google.common.annotations.VisibleForTesting;
 
-import org.chromium.chrome.browser.UmaBridge;
-
 import java.util.ArrayList;
 
 /**
@@ -34,6 +32,7 @@
 
     private final AppMenuPropertiesDelegate mDelegate;
     private final Activity mActivity;
+    private boolean mInvalidateInProgress = false;
 
     /**
      * Constructs an AppMenuHandler object.
@@ -107,13 +106,27 @@
         Point pt = new Point();
         mActivity.getWindowManager().getDefaultDisplay().getSize(pt);
         mAppMenu.show(wrapper, anchorView, isByHardwareButton, rotation, appRect, pt.y);
-        mAppMenuDragHelper.onShow(startDragging);
-        UmaBridge.menuShow();
         return true;
     }
 
+    public void invalidateAppMenu() {
+        if (!isAppMenuShowing()) return;
+        if (mInvalidateInProgress) return;
+
+        mInvalidateInProgress = true;
+
+        assert(mMenu != null);
+        assert(mAppMenu != null);
+        mDelegate.prepareMenu(mMenu);
+
+        ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity,
+                mDelegate.getMenuThemeResourceId());
+
+        mAppMenu.invalidate(wrapper, mMenu);
+        mInvalidateInProgress = false;
+    }
+
     void appMenuDismissed() {
-        mAppMenuDragHelper.finishDragging();
     }
 
     /**
@@ -132,7 +145,7 @@
     }
 
     AppMenuDragHelper getAppMenuDragHelper() {
-        return mAppMenuDragHelper;
+        return null;
     }
 
     /**
diff --git a/src/com/android/browser/appmenu/AppMenuItemIcon.java b/src/com/android/browser/appmenu/AppMenuItemIcon.java
index eddcc0d..ceecf10 100644
--- a/src/com/android/browser/appmenu/AppMenuItemIcon.java
+++ b/src/com/android/browser/appmenu/AppMenuItemIcon.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.content.Context;
 import android.util.AttributeSet;
diff --git a/src/com/android/browser/appmenu/AppMenuObserver.java b/src/com/android/browser/appmenu/AppMenuObserver.java
index c133bc3..febca8f 100644
--- a/src/com/android/browser/appmenu/AppMenuObserver.java
+++ b/src/com/android/browser/appmenu/AppMenuObserver.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 /**
  * Allows monitoring of application menu actions.
diff --git a/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java b/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java
index 00dcdfc..e094a82 100644
--- a/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java
+++ b/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.appmenu;
+package com.android.browser.appmenu;
 
 import android.view.Menu;
 
diff --git a/src/com/android/browser/stub/NullController.java b/src/com/android/browser/stub/NullController.java
index 149fe4e..1df77db 100644
--- a/src/com/android/browser/stub/NullController.java
+++ b/src/com/android/browser/stub/NullController.java
@@ -149,4 +149,6 @@
         return false;
     }
 
+    public void invalidateOptionsMenu() {}
+
 }