Bug 917394 - Rearrange about:home tabs as per new design (r=sriram)
authorLucas Rocha <lucasr@mozilla.com>
Tue, 17 Sep 2013 16:58:12 -0400
changeset 148088 32b336be0bd7b4bd95a26b2babfec971e5967098
parent 147382 4471e331bb4fb75a4b7ec3bec672e83b2b08e2f5
child 148089 2839a4856902969091872526c590474150d6ab5e
push id25325
push userryanvm@gmail.com
push dateFri, 20 Sep 2013 22:13:11 +0000
treeherdermozilla-central@354c958ba7d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssriram
bugs917394
milestone27.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 917394 - Rearrange about:home tabs as per new design (r=sriram)
mobile/android/base/BrowserApp.java
mobile/android/base/Makefile.in
mobile/android/base/Tab.java
mobile/android/base/home/BookmarksPage.java
mobile/android/base/home/HistoryPage.java
mobile/android/base/home/HomePager.java
mobile/android/base/home/MostVisitedPage.java
mobile/android/base/home/TopSitesPage.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/layout-large-land-v11/home_history_page.xml
mobile/android/base/resources/layout-xlarge-v11/home_history_page.xml
mobile/android/base/resources/layout/home_bookmarks_page.xml
mobile/android/base/resources/layout/home_history_page.xml
mobile/android/base/resources/layout/home_most_visited_page.xml
mobile/android/base/resources/layout/home_top_sites_page.xml
mobile/android/base/resources/values-large-v11/styles.xml
mobile/android/base/resources/values/dimens.xml
mobile/android/base/resources/values/styles.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1396,17 +1396,17 @@ abstract public class BrowserApp extends
         if (url == null) {
             throw new IllegalArgumentException("Cannot handle null URLs in enterEditingMode");
         }
 
         final PropertyAnimator animator = new PropertyAnimator(250);
         animator.setUseHardwareLayer(false);
 
         mBrowserToolbar.startEditing(url, animator);
-        showHomePagerWithAnimator(HomePager.Page.HISTORY, animator);
+        showHomePagerWithAnimator(HomePager.Page.TOP_SITES, animator);
 
         animator.start();
     }
 
     private void commitEditingMode() {
         if (!mBrowserToolbar.isEditing()) {
             return;
         }
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -225,29 +225,29 @@ FENNEC_JAVA_FILES = \
   home/HomeListView.java \
   home/HomePager.java \
   home/HomePagerTabStrip.java \
   home/HomeBanner.java \
   home/FadedTextView.java \
   home/FaviconsLoader.java \
   home/LastTabsPage.java \
   home/MostRecentPage.java \
-  home/MostVisitedPage.java \
   home/MultiTypeCursorAdapter.java \
   home/PinBookmarkDialog.java \
   home/ReadingListPage.java \
   home/SearchEngine.java \
   home/SearchEngineRow.java \
   home/SearchLoader.java \
   home/SimpleCursorLoader.java \
   home/SuggestClient.java \
   home/TabMenuStrip.java \
   home/TopBookmarkItemView.java \
   home/TopBookmarksAdapter.java \
   home/TopBookmarksView.java \
+  home/TopSitesPage.java \
   home/TwoLinePageRow.java \
   menu/GeckoMenu.java \
   menu/GeckoMenuInflater.java \
   menu/GeckoMenuItem.java \
   menu/GeckoSubMenu.java \
   menu/MenuItemActionBar.java \
   menu/MenuItemActionView.java \
   menu/MenuItemDefault.java \
@@ -473,22 +473,22 @@ RES_LAYOUT = \
   res/layout/home_empty_reading_page.xml \
   res/layout/home_item_row.xml \
   res/layout/home_header_row.xml \
   res/layout/home_history_page.xml \
   res/layout/home_history_tabs_indicator.xml \
   res/layout/home_last_tabs_page.xml \
   res/layout/home_history_list.xml \
   res/layout/home_most_recent_page.xml \
-  res/layout/home_most_visited_page.xml \
   res/layout/home_pager.xml \
   res/layout/home_reading_list_page.xml \
   res/layout/home_search_item_row.xml \
   res/layout/home_banner.xml \
   res/layout/home_suggestion_prompt.xml \
+  res/layout/home_top_sites_page.xml \
   res/layout/web_app.xml \
   res/layout/launch_app_list.xml \
   res/layout/launch_app_listitem.xml \
   res/layout/menu_action_bar.xml \
   res/layout/menu_item_action_view.xml \
   res/layout/menu_popup.xml \
   res/layout/notification_icon_text.xml \
   res/layout/notification_progress.xml \
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -88,17 +88,17 @@ public class Tab {
         mAppContext = context.getApplicationContext();
         mId = id;
         mLastUsed = 0;
         mUrl = url;
         mBaseDomain = "";
         mUserSearch = "";
         mExternal = external;
         mParentId = parentId;
-        mAboutHomePage = HomePager.Page.BOOKMARKS;
+        mAboutHomePage = HomePager.Page.TOP_SITES;
         mTitle = title == null ? "" : title;
         mFavicon = null;
         mFaviconUrl = null;
         mFaviconSize = 0;
         mFeedsEnabled = false;
         mIdentityData = null;
         mReaderEnabled = false;
         mEnteringReaderMode = false;
--- a/mobile/android/base/home/BookmarksPage.java
+++ b/mobile/android/base/home/BookmarksPage.java
@@ -3,169 +3,95 @@
  * 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.home;
 
 import org.mozilla.gecko.favicons.Favicons;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tabs;
-import org.mozilla.gecko.animation.PropertyAnimator;
-import org.mozilla.gecko.animation.PropertyAnimator.Property;
-import org.mozilla.gecko.animation.ViewHelper;
 import org.mozilla.gecko.db.BrowserContract.Bookmarks;
-import org.mozilla.gecko.db.BrowserContract.Thumbnails;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.home.BookmarksListAdapter.OnRefreshFolderListener;
-import org.mozilla.gecko.home.HomeListView.HomeContextMenuInfo;
 import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
-import org.mozilla.gecko.home.PinBookmarkDialog.OnBookmarkSelectedListener;
-import org.mozilla.gecko.home.TopBookmarksAdapter.Thumbnail;
-import org.mozilla.gecko.home.TopBookmarksView.OnPinBookmarkListener;
-import org.mozilla.gecko.home.TopBookmarksView.TopBookmarksContextMenuInfo;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.os.Bundle;
-import android.support.v4.app.FragmentManager;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
-import android.support.v4.content.AsyncTaskLoader;
 import android.support.v4.content.Loader;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
-import android.widget.Toast;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * A page in about:home that displays a ListView of bookmarks.
  */
 public class BookmarksPage extends HomeFragment {
     public static final String LOGTAG = "GeckoBookmarksPage";
 
     // Cursor loader ID for list of bookmarks.
     private static final int LOADER_ID_BOOKMARKS_LIST = 0;
 
-    // Cursor loader ID for grid of bookmarks.
-    private static final int LOADER_ID_TOP_BOOKMARKS = 1;
-
-    // Loader ID for thumbnails.
-    private static final int LOADER_ID_THUMBNAILS = 2;
-
     // Key for bookmarks folder id.
     private static final String BOOKMARKS_FOLDER_KEY = "folder_id";
 
-    // Key for thumbnail urls.
-    private static final String THUMBNAILS_URLS_KEY = "urls";
-
     // List of bookmarks.
     private BookmarksListView mList;
 
-    // Grid of top bookmarks.
-    private TopBookmarksView mTopBookmarks;
-
-    // Banner to show snippets.
-    private HomeBanner mBanner;
-
     // Adapter for list of bookmarks.
     private BookmarksListAdapter mListAdapter;
 
-    // Adapter for grid of bookmarks.
-    private TopBookmarksAdapter mTopBookmarksAdapter;
-
     // Callback for cursor loaders.
     private CursorLoaderCallbacks mLoaderCallbacks;
 
-    // Callback for thumbnail loader.
-    private ThumbnailsLoaderCallbacks mThumbnailsLoaderCallbacks;
-
-    // Listener for pinning bookmarks.
-    private PinBookmarkListener mPinBookmarkListener;
-
-    // Raw Y value of the last event that happened on the list view.
-    private float mListTouchY = -1;
-
-    // Scrolling direction of the banner.
-    private boolean mSnapBannerToTop;
-
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         final View view = inflater.inflate(R.layout.home_bookmarks_page, container, false);
 
         mList = (BookmarksListView) view.findViewById(R.id.bookmarks_list);
 
-        mTopBookmarks = new TopBookmarksView(getActivity());
-        mList.addHeaderView(mTopBookmarks);
-
         return view;
     }
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
         OnUrlOpenListener listener = null;
         try {
             listener = (OnUrlOpenListener) getActivity();
         } catch (ClassCastException e) {
             throw new ClassCastException(getActivity().toString()
                     + " must implement HomePager.OnUrlOpenListener");
         }
 
-        mPinBookmarkListener = new PinBookmarkListener();
-
         mList.setTag(HomePager.LIST_TAG_BOOKMARKS);
         mList.setOnUrlOpenListener(listener);
         mList.setHeaderDividersEnabled(false);
 
-        mTopBookmarks.setOnUrlOpenListener(listener);
-        mTopBookmarks.setOnPinBookmarkListener(mPinBookmarkListener);
-
         registerForContextMenu(mList);
-        registerForContextMenu(mTopBookmarks);
-
-        mBanner = (HomeBanner) view.findViewById(R.id.home_banner);
-        mList.setOnTouchListener(new OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                BookmarksPage.this.handleListTouchEvent(event);
-                return false;
-            }
-        });
     }
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
         final Activity activity = getActivity();
 
-        // Setup the top bookmarks adapter.
-        mTopBookmarksAdapter = new TopBookmarksAdapter(activity, null);
-        mTopBookmarks.setAdapter(mTopBookmarksAdapter);
-
         // Setup the list adapter.
         mListAdapter = new BookmarksListAdapter(activity, null);
         mListAdapter.setOnRefreshFolderListener(new OnRefreshFolderListener() {
             @Override
             public void onRefreshFolder(int folderId) {
                 // Restart the loader with folder as the argument.
                 Bundle bundle = new Bundle();
                 bundle.putInt(BOOKMARKS_FOLDER_KEY, folderId);
@@ -175,27 +101,23 @@ public class BookmarksPage extends HomeF
         mList.setAdapter(mListAdapter);
 
         // Invalidate the cached value that keeps track of whether or
         // not desktop bookmarks (or reading list items) exist.
         BrowserDB.invalidateCachedState();
 
         // Create callbacks before the initial loader is started.
         mLoaderCallbacks = new CursorLoaderCallbacks(activity, getLoaderManager());
-        mThumbnailsLoaderCallbacks = new ThumbnailsLoaderCallbacks();
         loadIfVisible();
     }
 
     @Override
     public void onDestroyView() {
         mList = null;
         mListAdapter = null;
-        mTopBookmarks = null;
-        mTopBookmarksAdapter = null;
-        mPinBookmarkListener = null;
         super.onDestroyView();
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
         // Reattach the fragment, forcing a reinflation of its view.
@@ -209,214 +131,19 @@ public class BookmarksPage extends HomeF
         if (isVisible()) {
             getFragmentManager().beginTransaction()
                                 .detach(this)
                                 .attach(this)
                                 .commitAllowingStateLoss();
         }
     }
 
-    private void handleListTouchEvent(MotionEvent event) {
-        // Ignore the event if the banner is hidden for this session.
-        if (mBanner.isDismissed()) {
-            return;
-        }
-
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN: {
-                mListTouchY = event.getRawY();
-                break;
-             }
-
-            case MotionEvent.ACTION_MOVE: {
-                // There is a chance that we won't receive ACTION_DOWN, if the touch event
-                // actually started on the Grid instead of the List. Treat this as first event.
-                if (mListTouchY == -1) {
-                    mListTouchY = event.getRawY();
-                    return;
-                }
-
-                final float curY = event.getRawY();
-                final float delta = mListTouchY - curY;
-                mSnapBannerToTop = (delta > 0.0f) ? false : true;
-
-                final float height = mBanner.getHeight();
-                float newTranslationY = ViewHelper.getTranslationY(mBanner) + delta;
-
-                // Clamp the values to be between 0 and height.
-                if (newTranslationY < 0.0f) {
-                    newTranslationY = 0.0f;
-                } else if (newTranslationY > height) {
-                    newTranslationY = height;
-                }
-
-                ViewHelper.setTranslationY(mBanner, newTranslationY);
-                mListTouchY = curY;
-                break;
-            }
-
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL: {
-                mListTouchY = -1;
-                final float y = ViewHelper.getTranslationY(mBanner);
-                final float height = mBanner.getHeight();
-                if (y > 0.0f && y < height) {
-                    final PropertyAnimator animator = new PropertyAnimator(100);
-                    animator.attach(mBanner, Property.TRANSLATION_Y, mSnapBannerToTop ? 0 : height);
-                    animator.start();
-                }
-                break;
-            }
-        }
-    }
-
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
-        if (menuInfo == null) {
-            return;
-        }
-
-        // HomeFragment will handle the default case.
-        if (menuInfo instanceof HomeContextMenuInfo) {
-            super.onCreateContextMenu(menu, view, menuInfo);
-        }
-
-        if (!(menuInfo instanceof TopBookmarksContextMenuInfo)) {
-            return;
-        }
-
-        MenuInflater inflater = new MenuInflater(view.getContext());
-        inflater.inflate(R.menu.top_bookmarks_contextmenu, menu);
-
-        TopBookmarksContextMenuInfo info = (TopBookmarksContextMenuInfo) menuInfo;
-        menu.setHeaderTitle(info.getDisplayTitle());
-
-        if (!TextUtils.isEmpty(info.url)) {
-            if (info.isPinned) {
-                menu.findItem(R.id.top_bookmarks_pin).setVisible(false);
-            } else {
-                menu.findItem(R.id.top_bookmarks_unpin).setVisible(false);
-            }
-        } else {
-            menu.findItem(R.id.top_bookmarks_open_new_tab).setVisible(false);
-            menu.findItem(R.id.top_bookmarks_open_private_tab).setVisible(false);
-            menu.findItem(R.id.top_bookmarks_pin).setVisible(false);
-            menu.findItem(R.id.top_bookmarks_unpin).setVisible(false);
-        }
-    }
-
-    @Override
-    public boolean onContextItemSelected(MenuItem item) {
-        ContextMenuInfo menuInfo = item.getMenuInfo();
-
-        // HomeFragment will handle the default case.
-        if (menuInfo == null || !(menuInfo instanceof TopBookmarksContextMenuInfo)) {
-            return false;
-        }
-
-        TopBookmarksContextMenuInfo info = (TopBookmarksContextMenuInfo) menuInfo;
-        final Activity activity = getActivity();
-
-        final int itemId = item.getItemId();
-        if (itemId == R.id.top_bookmarks_open_new_tab || itemId == R.id.top_bookmarks_open_private_tab) {
-            if (info.url == null) {
-                Log.e(LOGTAG, "Can't open in new tab because URL is null");
-                return false;
-            }
-
-            int flags = Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_BACKGROUND;
-            if (item.getItemId() == R.id.top_bookmarks_open_private_tab)
-                flags |= Tabs.LOADURL_PRIVATE;
-
-            Tabs.getInstance().loadUrl(info.url, flags);
-            Toast.makeText(activity, R.string.new_tab_opened, Toast.LENGTH_SHORT).show();
-            return true;
-        }
-
-        if (itemId == R.id.top_bookmarks_pin) {
-            final String url = info.url;
-            final String title = info.title;
-            final int position = info.position;
-            final Context context = getActivity().getApplicationContext();
-
-            ThreadUtils.postToBackgroundThread(new Runnable() {
-                @Override
-                public void run() {
-                    BrowserDB.pinSite(context.getContentResolver(), url, title, position);
-                }
-            });
-
-            return true;
-        }
-
-        if (itemId == R.id.top_bookmarks_unpin) {
-            final int position = info.position;
-            final Context context = getActivity().getApplicationContext();
-
-            ThreadUtils.postToBackgroundThread(new Runnable() {
-                @Override
-                public void run() {
-                    BrowserDB.unpinSite(context.getContentResolver(), position);
-                }
-            });
-
-            return true;
-        }
-
-        if (itemId == R.id.top_bookmarks_edit) {
-            mPinBookmarkListener.onPinBookmark(info.position);
-            return true;
-        }
-
-        return false;
-    }
-
     @Override
     protected void load() {
-        final LoaderManager manager = getLoaderManager();
-        manager.initLoader(LOADER_ID_BOOKMARKS_LIST, null, mLoaderCallbacks);
-        manager.initLoader(LOADER_ID_TOP_BOOKMARKS, null, mLoaderCallbacks);
-    }
-
-    /**
-     * Listener for pinning bookmarks.
-     */
-    private class PinBookmarkListener implements OnPinBookmarkListener,
-                                                 OnBookmarkSelectedListener {
-        // Tag for the PinBookmarkDialog fragment.
-        private static final String TAG_PIN_BOOKMARK = "pin_bookmark";
-
-        // Position of the pin.
-        private int mPosition;
-
-        @Override
-        public void onPinBookmark(int position) {
-            mPosition = position;
-
-            final FragmentManager manager = getActivity().getSupportFragmentManager();
-            PinBookmarkDialog dialog = (PinBookmarkDialog) manager.findFragmentByTag(TAG_PIN_BOOKMARK);
-            if (dialog == null) {
-                dialog = PinBookmarkDialog.newInstance();
-            }
-
-            dialog.setOnBookmarkSelectedListener(this);
-            dialog.show(manager, TAG_PIN_BOOKMARK);
-        }
-
-        @Override
-        public void onBookmarkSelected(final String url, final String title) {
-            final int position = mPosition;
-            final Context context = getActivity().getApplicationContext();
-            ThreadUtils.postToBackgroundThread(new Runnable() {
-                @Override
-                public void run() {
-                    BrowserDB.pinSite(context.getContentResolver(), url, title, position);
-                }
-            });
-        }
+        getLoaderManager().initLoader(LOADER_ID_BOOKMARKS_LIST, null, mLoaderCallbacks);
     }
 
     /**
      * Loader for the list for bookmarks.
      */
     private static class BookmarksLoader extends SimpleCursorLoader {
         private final int mFolderId;
 
@@ -431,31 +158,16 @@ public class BookmarksPage extends HomeF
 
         @Override
         public Cursor loadCursor() {
             return BrowserDB.getBookmarksInFolder(getContext().getContentResolver(), mFolderId);
         }
     }
 
     /**
-     * Loader for the grid for top bookmarks.
-     */
-    private static class TopBookmarksLoader extends SimpleCursorLoader {
-        public TopBookmarksLoader(Context context) {
-            super(context);
-        }
-
-        @Override
-        public Cursor loadCursor() {
-            final int max = getContext().getResources().getInteger(R.integer.number_of_top_sites);
-            return BrowserDB.getTopBookmarks(getContext().getContentResolver(), max);
-        }
-    }
-
-    /**
      * Loader callbacks for the LoaderManager of this fragment.
      */
     private class CursorLoaderCallbacks extends HomeCursorLoaderCallbacks {
         public CursorLoaderCallbacks(Context context, LoaderManager loaderManager) {
             super(context, loaderManager);
         }
 
         @Override
@@ -464,20 +176,16 @@ public class BookmarksPage extends HomeF
                 case LOADER_ID_BOOKMARKS_LIST: {
                     if (args == null) {
                         return new BookmarksLoader(getActivity());
                     } else {
                         return new BookmarksLoader(getActivity(), args.getInt(BOOKMARKS_FOLDER_KEY));
                     }
                 }
 
-                case LOADER_ID_TOP_BOOKMARKS: {
-                    return new TopBookmarksLoader(getActivity());
-                }
-
                 default: {
                     return super.onCreateLoader(id, args);
                 }
             }
         }
 
         @Override
         public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
@@ -485,36 +193,16 @@ public class BookmarksPage extends HomeF
             switch(loaderId) {
                 case LOADER_ID_BOOKMARKS_LIST: {
                     mListAdapter.swapCursor(c);
                     loadFavicons(c);
                     mList.setHeaderDividersEnabled(c != null && c.getCount() > 0);
                     break;
                 }
 
-                case LOADER_ID_TOP_BOOKMARKS: {
-                    mTopBookmarksAdapter.swapCursor(c);
-
-                    // Load the thumbnails.
-                    if (c.getCount() > 0 && c.moveToFirst()) {
-                        final ArrayList<String> urls = new ArrayList<String>();
-                        do {
-                            final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
-                            urls.add(url);
-                        } while (c.moveToNext());
-
-                        if (urls.size() > 0) {
-                            Bundle bundle = new Bundle();
-                            bundle.putStringArrayList(THUMBNAILS_URLS_KEY, urls);
-                            getLoaderManager().restartLoader(LOADER_ID_THUMBNAILS, bundle, mThumbnailsLoaderCallbacks);
-                        }
-                    }
-                    break;
-                }
-
                 default: {
                     super.onLoadFinished(loader, c);
                     break;
                 }
             }
         }
 
         @Override
@@ -523,156 +211,21 @@ public class BookmarksPage extends HomeF
             switch(loaderId) {
                 case LOADER_ID_BOOKMARKS_LIST: {
                     if (mList != null) {
                         mListAdapter.swapCursor(null);
                     }
                     break;
                 }
 
-                case LOADER_ID_TOP_BOOKMARKS: {
-                    if (mTopBookmarks != null) {
-                        mTopBookmarksAdapter.swapCursor(null);
-                        break;
-                    }
-                }
-
                 default: {
                     super.onLoaderReset(loader);
                     break;
                 }
             }
         }
 
         @Override
         public void onFaviconsLoaded() {
             mListAdapter.notifyDataSetChanged();
         }
     }
-
-    /**
-     * An AsyncTaskLoader to load the thumbnails from a cursor.
-     */
-    private static class ThumbnailsLoader extends AsyncTaskLoader<Map<String, Thumbnail>> {
-        private Map<String, Thumbnail> mThumbnails;
-        private ArrayList<String> mUrls;
-
-        public ThumbnailsLoader(Context context, ArrayList<String> urls) {
-            super(context);
-            mUrls = urls;
-        }
-
-        @Override
-        public Map<String, Thumbnail> loadInBackground() {
-            if (mUrls == null || mUrls.size() == 0) {
-                return null;
-            }
-
-            final Map<String, Thumbnail> thumbnails = new HashMap<String, Thumbnail>();
-
-            // Query the DB for thumbnails.
-            final ContentResolver cr = getContext().getContentResolver();
-            final Cursor cursor = BrowserDB.getThumbnailsForUrls(cr, mUrls);
-
-            try {
-                if (cursor != null && cursor.moveToFirst()) {
-                    do {
-                        // Try to get the thumbnail, if cursor is valid.
-                        String url = cursor.getString(cursor.getColumnIndexOrThrow(Thumbnails.URL));
-                        final byte[] b = cursor.getBlob(cursor.getColumnIndexOrThrow(Thumbnails.DATA));
-                        final Bitmap bitmap = (b == null ? null : BitmapUtils.decodeByteArray(b));
-
-                        if (bitmap != null) {
-                            thumbnails.put(url, new Thumbnail(bitmap, true));
-                        }
-                    } while (cursor.moveToNext());
-                }
-            } finally {
-                if (cursor != null) {
-                    cursor.close();
-                }
-            }
-
-            // Query the DB for favicons for the urls without thumbnails.
-            for (String url : mUrls) {
-                if (!thumbnails.containsKey(url)) {
-                    final Bitmap bitmap = BrowserDB.getFaviconForUrl(cr, url);
-                    if (bitmap != null) {
-                        // Favicons.scaleImage can return several different size favicons,
-                        // but will at least prevent this from being too large.
-                        thumbnails.put(url, new Thumbnail(Favicons.scaleImage(bitmap), false));
-                    }
-                }
-            }
-
-            return thumbnails;
-        }
-
-        @Override
-        public void deliverResult(Map<String, Thumbnail> thumbnails) {
-            if (isReset()) {
-                mThumbnails = null;
-                return;
-            }
-
-            mThumbnails = thumbnails;
-
-            if (isStarted()) {
-                super.deliverResult(thumbnails);
-            }
-        }
-
-        @Override
-        protected void onStartLoading() {
-            if (mThumbnails != null) {
-                deliverResult(mThumbnails);
-            }
-
-            if (takeContentChanged() || mThumbnails == null) {
-                forceLoad();
-            }
-        }
-
-        @Override
-        protected void onStopLoading() {
-            cancelLoad();
-        }
-
-        @Override
-        public void onCanceled(Map<String, Thumbnail> thumbnails) {
-            mThumbnails = null;
-        }
-
-        @Override
-        protected void onReset() {
-            super.onReset();
-
-            // Ensure the loader is stopped.
-            onStopLoading();
-
-            mThumbnails = null;
-        }
-    }
-
-    /**
-     * Loader callbacks for the thumbnails on TopBookmarksView.
-     */
-    private class ThumbnailsLoaderCallbacks implements LoaderCallbacks<Map<String, Thumbnail>> {
-        @Override
-        public Loader<Map<String, Thumbnail>> onCreateLoader(int id, Bundle args) {
-            return new ThumbnailsLoader(getActivity(), args.getStringArrayList(THUMBNAILS_URLS_KEY));
-        }
-
-        @Override
-        public void onLoadFinished(Loader<Map<String, Thumbnail>> loader, Map<String, Thumbnail> thumbnails) {
-            if (mTopBookmarksAdapter != null) {
-                mTopBookmarksAdapter.updateThumbnails(thumbnails);
-            }
-        }
-
-        @Override
-        public void onLoaderReset(Loader<Map<String, Thumbnail>> loader) {
-            if (mTopBookmarksAdapter != null) {
-                mTopBookmarksAdapter.updateThumbnails(null);
-            }
-        }
-    }
 }
--- a/mobile/android/base/home/HistoryPage.java
+++ b/mobile/android/base/home/HistoryPage.java
@@ -20,60 +20,57 @@ import android.view.LayoutInflater;
 import android.widget.ImageButton;
 
 public class HistoryPage extends HomeFragment
                         implements IconTabWidget.OnTabChangedListener {
     // Logging tag name
     private static final String LOGTAG = "GeckoHistoryPage";
     private IconTabWidget mTabWidget;
     private int mSelectedTab;
-    private boolean initializeVisitedPage;
+    private boolean initializeRecentPage;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         return inflater.inflate(R.layout.home_history_page, container, false);
     }
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
         mTabWidget = (IconTabWidget) view.findViewById(R.id.tab_icon_widget);
 
-        mTabWidget.addTab(R.drawable.icon_most_visited, R.string.home_most_visited_title);
         mTabWidget.addTab(R.drawable.icon_most_recent, R.string.home_most_recent_title);
         mTabWidget.addTab(R.drawable.icon_last_tabs, R.string.home_last_tabs_title);
 
         mTabWidget.setTabSelectionListener(this);
         mTabWidget.setCurrentTab(mSelectedTab);
 
         loadIfVisible();
     }
 
     @Override
     public void load() {
-        // Show most visited page as the initial page.
+        // Show most recent page as the initial page.
         // Since we detach/attach on config change, this prevents from replacing current fragment.
-        if (!initializeVisitedPage) {
-            showMostVisitedPage();
-            initializeVisitedPage = true;
+        if (!initializeRecentPage) {
+            showMostRecentPage();
+            initializeRecentPage = true;
         }
     }
 
     @Override
     public void onTabChanged(int index) {
         if (index == mSelectedTab) {
             return;
         }
 
         if (index == 0) {
-            showMostVisitedPage();
+            showMostRecentPage();
         } else if (index == 1) {
-            showMostRecentPage();
-        } else if (index == 2) {
             showLastTabsPage();
         }
 
         mTabWidget.setCurrentTab(index);
         mSelectedTab = index;
     }
 
     @Override
@@ -90,25 +87,20 @@ public class HistoryPage extends HomeFra
     }
 
     private void showSubPage(Fragment subPage) {
         final Bundle args = new Bundle();
         args.putBoolean(HomePager.CAN_LOAD_ARG, getCanLoadHint());
         subPage.setArguments(args);
 
         getChildFragmentManager().beginTransaction()
-                .addToBackStack(null).replace(R.id.visited_page_container, subPage)
+                .addToBackStack(null).replace(R.id.history_page_container, subPage)
                 .commitAllowingStateLoss();
     }
 
-    private void showMostVisitedPage() {
-        final MostVisitedPage mostVisitedPage = MostVisitedPage.newInstance();
-        showSubPage(mostVisitedPage);
-    }
-
     private void showMostRecentPage() {
         final MostRecentPage mostRecentPage = MostRecentPage.newInstance();
         showSubPage(mostRecentPage);
     }
 
     private void showLastTabsPage() {
         final LastTabsPage lastTabsPage = LastTabsPage.newInstance();
         showSubPage(lastTabsPage);
--- a/mobile/android/base/home/HomePager.java
+++ b/mobile/android/base/home/HomePager.java
@@ -3,16 +3,17 @@
  * 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.home;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.animation.PropertyAnimator;
 import org.mozilla.gecko.animation.ViewHelper;
+import org.mozilla.gecko.util.HardwareUtils;
 
 import android.content.Context;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentStatePagerAdapter;
 import android.support.v4.view.PagerAdapter;
@@ -33,16 +34,17 @@ public class HomePager extends ViewPager
 
     private final Context mContext;
     private volatile boolean mLoaded;
     private Decor mDecor;
 
     // List of pages in order.
     public enum Page {
         HISTORY,
+        TOP_SITES,
         BOOKMARKS,
         READING_LIST
     }
 
     // This is mostly used by UI tests to easily fetch
     // specific list views at runtime.
     static final String LIST_TAG_HISTORY = "history";
     static final String LIST_TAG_BOOKMARKS = "bookmarks";
@@ -85,19 +87,19 @@ public class HomePager extends ViewPager
     public HomePager(Context context) {
         this(context, null);
     }
 
     public HomePager(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
 
-        // This is to keep all 3 pages in memory after they are
+        // This is to keep all 4 pages in memory after they are
         // selected in the pager.
-        setOffscreenPageLimit(2);
+        setOffscreenPageLimit(3);
     }
 
     @Override
     public void addView(View child, int index, ViewGroup.LayoutParams params) {
         if (child instanceof Decor) {
             ((ViewPager.LayoutParams) params).isDecor = true;
             mDecor = (Decor) child;
             setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@@ -126,24 +128,29 @@ public class HomePager extends ViewPager
      */
     public void show(FragmentManager fm, Page page, PropertyAnimator animator) {
         mLoaded = true;
         final TabsAdapter adapter = new TabsAdapter(fm);
 
         // Only animate on post-HC devices, when a non-null animator is given
         final boolean shouldAnimate = (animator != null && Build.VERSION.SDK_INT >= 11);
 
-        // Add the pages to the adapter in order.
-        adapter.addTab(Page.HISTORY, HistoryPage.class, new Bundle(),
-                getContext().getString(R.string.home_history_title));
+        adapter.addTab(Page.TOP_SITES, TopSitesPage.class, new Bundle(),
+                getContext().getString(R.string.home_top_sites_title));
         adapter.addTab(Page.BOOKMARKS, BookmarksPage.class, new Bundle(),
                 getContext().getString(R.string.bookmarks_title));
         adapter.addTab(Page.READING_LIST, ReadingListPage.class, new Bundle(),
                 getContext().getString(R.string.reading_list_title));
 
+        // On phones, the history tab is the first tab. On tablets, the
+        // history tab is the last tab.
+        adapter.addTab(HardwareUtils.isTablet() ? -1 : 0,
+                Page.HISTORY, HistoryPage.class, new Bundle(),
+                getContext().getString(R.string.home_history_title));
+
         adapter.setCanLoadHint(!shouldAnimate);
 
         setAdapter(adapter);
 
         setCurrentItem(adapter.getItemPosition(page), false);
         setVisibility(VISIBLE);
 
         if (shouldAnimate) {
@@ -221,18 +228,28 @@ public class HomePager extends ViewPager
 
             if (mDecor != null) {
                 mDecor.removeAllPagerViews();
                 mDecor.setOnTitleClickListener(this);
             }
         }
 
         public void addTab(Page page, Class<?> clss, Bundle args, String title) {
+            addTab(-1, page, clss, args, title);
+        }
+
+        public void addTab(int index, Page page, Class<?> clss, Bundle args, String title) {
             TabInfo info = new TabInfo(page, clss, args, title);
-            mTabs.add(info);
+
+            if (index >= 0) {
+                mTabs.add(index, info);
+            } else {
+                mTabs.add(info);
+            }
+
             notifyDataSetChanged();
 
             if (mDecor != null) {
                 mDecor.onAddPagerView(title);
             }
         }
 
         @Override
rename from mobile/android/base/home/MostVisitedPage.java
rename to mobile/android/base/home/TopSitesPage.java
--- a/mobile/android/base/home/MostVisitedPage.java
+++ b/mobile/android/base/home/TopSitesPage.java
@@ -1,72 +1,84 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.animation.PropertyAnimator;
+import org.mozilla.gecko.animation.PropertyAnimator.Property;
+import org.mozilla.gecko.animation.ViewHelper;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
 import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
 
 import android.app.Activity;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.content.Loader;
 import android.support.v4.widget.CursorAdapter;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.view.ViewStub;
 import android.widget.AdapterView;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
 
 import java.util.EnumSet;
 
 /**
  * Fragment that displays frecency search results in a ListView.
  */
-public class MostVisitedPage extends HomeFragment {
+public class TopSitesPage extends HomeFragment {
     // Logging tag name
-    private static final String LOGTAG = "GeckoMostVisitedPage";
+    private static final String LOGTAG = "GeckoTopSitesPage";
 
     // Cursor loader ID for search query
-    private static final int LOADER_ID_FRECENCY = 0;
+    private static final int LOADER_ID_TOP_SITES = 0;
 
     // Adapter for the list of search results
     private VisitedAdapter mAdapter;
 
     // The view shown by the fragment.
     private ListView mList;
 
-    // The title for this HomeFragment page.
-    private TextView mTitle;
-
     // Reference to the View to display when there are no results.
     private View mEmptyView;
 
+    // Banner to show snippets.
+    private HomeBanner mBanner;
+
+    // Raw Y value of the last event that happened on the list view.
+    private float mListTouchY = -1;
+
+    // Scrolling direction of the banner.
+    private boolean mSnapBannerToTop;
+
     // Callbacks used for the search and favicon cursor loaders
     private CursorLoaderCallbacks mCursorLoaderCallbacks;
 
     // On URL open listener
     private OnUrlOpenListener mUrlOpenListener;
 
-    public static MostVisitedPage newInstance() {
-        return new MostVisitedPage();
+    public static TopSitesPage newInstance() {
+        return new TopSitesPage();
     }
 
-    public MostVisitedPage() {
+    public TopSitesPage() {
         mUrlOpenListener = null;
     }
 
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
 
         try {
@@ -81,26 +93,21 @@ public class MostVisitedPage extends Hom
     public void onDetach() {
         super.onDetach();
 
         mUrlOpenListener = null;
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        return inflater.inflate(R.layout.home_most_visited_page, container, false);
+        return inflater.inflate(R.layout.home_top_sites_page, container, false);
     }
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
-        mTitle = (TextView) view.findViewById(R.id.title);
-        if (mTitle != null) {
-            mTitle.setText(R.string.home_most_visited_title);
-        }
-
         mList = (HomeListView) view.findViewById(R.id.list);
         mList.setTag(HomePager.LIST_TAG_MOST_VISITED);
 
         mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                 final Cursor c = mAdapter.getCursor();
                 if (c == null || !c.moveToPosition(position)) {
@@ -110,80 +117,146 @@ public class MostVisitedPage extends Hom
                 final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
 
                 // This item is a TwoLinePageRow, so we allow switch-to-tab.
                 mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
             }
         });
 
         registerForContextMenu(mList);
+
+        mBanner = (HomeBanner) view.findViewById(R.id.home_banner);
+        mList.setOnTouchListener(new OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                TopSitesPage.this.handleListTouchEvent(event);
+                return false;
+            }
+        });
     }
 
     @Override
     public void onDestroyView() {
         super.onDestroyView();
         mList = null;
-        mTitle = null;
         mEmptyView = null;
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        // Detach and reattach the fragment as the layout changes.
+        if (isVisible()) {
+            getFragmentManager().beginTransaction()
+                                .detach(this)
+                                .attach(this)
+                                .commitAllowingStateLoss();
+        }
+    }
+
+    @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
         final Activity activity = getActivity();
 
         // Intialize the search adapter
         mAdapter = new VisitedAdapter(activity, null);
         mList.setAdapter(mAdapter);
 
         // Create callbacks before the initial loader is started
         mCursorLoaderCallbacks = new CursorLoaderCallbacks(activity, getLoaderManager());
         loadIfVisible();
     }
 
     @Override
     protected void load() {
-        getLoaderManager().initLoader(LOADER_ID_FRECENCY, null, mCursorLoaderCallbacks);
+        getLoaderManager().initLoader(LOADER_ID_TOP_SITES, null, mCursorLoaderCallbacks);
+    }
+
+    private void handleListTouchEvent(MotionEvent event) {
+        // Ignore the event if the banner is hidden for this session.
+        if (mBanner.isDismissed()) {
+            return;
+        }
+
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN: {
+                mListTouchY = event.getRawY();
+                break;
+            }
+
+            case MotionEvent.ACTION_MOVE: {
+                // There is a chance that we won't receive ACTION_DOWN, if the touch event
+                // actually started on the Grid instead of the List. Treat this as first event.
+                if (mListTouchY == -1) {
+                    mListTouchY = event.getRawY();
+                    return;
+                }
+
+                final float curY = event.getRawY();
+                final float delta = mListTouchY - curY;
+                mSnapBannerToTop = (delta > 0.0f) ? false : true;
+
+                final float height = mBanner.getHeight();
+                float newTranslationY = ViewHelper.getTranslationY(mBanner) + delta;
+
+                // Clamp the values to be between 0 and height.
+                if (newTranslationY < 0.0f) {
+                    newTranslationY = 0.0f;
+                } else if (newTranslationY > height) {
+                    newTranslationY = height;
+                }
+
+                ViewHelper.setTranslationY(mBanner, newTranslationY);
+                mListTouchY = curY;
+                break;
+            }
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL: {
+                mListTouchY = -1;
+                final float y = ViewHelper.getTranslationY(mBanner);
+                final float height = mBanner.getHeight();
+                if (y > 0.0f && y < height) {
+                    final PropertyAnimator animator = new PropertyAnimator(100);
+                    animator.attach(mBanner, Property.TRANSLATION_Y, mSnapBannerToTop ? 0 : height);
+                    animator.start();
+                }
+                break;
+            }
+        }
     }
 
     private void updateUiFromCursor(Cursor c) {
         if (c != null && c.getCount() > 0) {
-            if (mTitle != null) {
-                mTitle.setVisibility(View.VISIBLE);
-            }
             return;
         }
 
-        // Cursor is empty, so hide the title and set the
-        // empty view if it hasn't been set already.
-        if (mTitle != null) {
-            mTitle.setVisibility(View.GONE);
-        }
-
         if (mEmptyView == null) {
             // Set empty page view. We delay this so that the empty view won't flash.
             ViewStub emptyViewStub = (ViewStub) getView().findViewById(R.id.home_empty_view_stub);
             mEmptyView = emptyViewStub.inflate();
 
             final ImageView emptyIcon = (ImageView) mEmptyView.findViewById(R.id.home_empty_image);
             emptyIcon.setImageResource(R.drawable.icon_most_visited_empty);
 
             final TextView emptyText = (TextView) mEmptyView.findViewById(R.id.home_empty_text);
             emptyText.setText(R.string.home_most_visited_empty);
 
             mList.setEmptyView(mEmptyView);
         }
     }
 
-    private static class FrecencyCursorLoader extends SimpleCursorLoader {
+    private static class TopSitesCursorLoader extends SimpleCursorLoader {
         // Max number of search results
         private static final int SEARCH_LIMIT = 50;
 
-        public FrecencyCursorLoader(Context context) {
+        public TopSitesCursorLoader(Context context) {
             super(context);
         }
 
         @Override
         public Cursor loadCursor() {
             final ContentResolver cr = getContext().getContentResolver();
             return BrowserDB.filter(cr, "", SEARCH_LIMIT);
         }
@@ -208,37 +281,37 @@ public class MostVisitedPage extends Hom
 
     private class CursorLoaderCallbacks extends HomeCursorLoaderCallbacks {
         public CursorLoaderCallbacks(Context context, LoaderManager loaderManager) {
             super(context, loaderManager);
         }
 
         @Override
         public Loader<Cursor> onCreateLoader(int id, Bundle args) {
-            if (id == LOADER_ID_FRECENCY) {
-                return new FrecencyCursorLoader(getActivity());
+            if (id == LOADER_ID_TOP_SITES) {
+                return new TopSitesCursorLoader(getActivity());
             } else {
                 return super.onCreateLoader(id, args);
             }
         }
 
         @Override
         public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
-            if (loader.getId() == LOADER_ID_FRECENCY) {
+            if (loader.getId() == LOADER_ID_TOP_SITES) {
                 mAdapter.swapCursor(c);
                 updateUiFromCursor(c);
                 loadFavicons(c);
             } else {
                 super.onLoadFinished(loader, c);
             }
         }
 
         @Override
         public void onLoaderReset(Loader<Cursor> loader) {
-            if (loader.getId() == LOADER_ID_FRECENCY) {
+            if (loader.getId() == LOADER_ID_TOP_SITES) {
                 mAdapter.swapCursor(null);
             } else {
                 super.onLoaderReset(loader);
             }
         }
 
         @Override
         public void onFaviconsLoaded() {
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -265,16 +265,17 @@ size. -->
 <!ENTITY button_ok "OK">
 <!ENTITY button_cancel "Cancel">
 <!ENTITY button_yes "Yes">
 <!ENTITY button_no "No">
 <!ENTITY button_clear_data "Clear data">
 <!ENTITY button_set "Set">
 <!ENTITY button_clear "Clear">
 
+<!ENTITY home_top_sites_title "Top Sites">
 <!ENTITY home_history_title "History">
 <!ENTITY home_last_tabs_title "Tabs from last time">
 <!ENTITY home_last_tabs_open "Open all tabs from last time">
 <!ENTITY home_last_tabs_empty "Your recent tabs show up here.">
 <!ENTITY home_most_recent_title "Most recent">
 <!ENTITY home_most_recent_empty "Websites you visited most recently show up here.">
 <!ENTITY home_most_visited_title "Most visited">
 <!ENTITY home_reading_list_empty "Articles you save for later show up here.">
--- a/mobile/android/base/resources/layout-large-land-v11/home_history_page.xml
+++ b/mobile/android/base/resources/layout-large-land-v11/home_history_page.xml
@@ -11,14 +11,14 @@
     <org.mozilla.gecko.widget.IconTabWidget android:id="@+id/tab_icon_widget"
                                             style="@style/Widget.Home.HistoryTabWidget"
                                             android:layout_width="@dimen/history_tab_widget_width"
                                             android:layout_height="@dimen/history_tab_widget_height"
                                             android:orientation="vertical"
                                             android:layout="@layout/home_history_tabs_indicator"
                                             gecko:display="text"/>
 
-    <FrameLayout android:id="@+id/visited_page_container"
+    <FrameLayout android:id="@+id/history_page_container"
                  android:layout_width="0dp"
                  android:layout_height="fill_parent"
                  android:layout_weight="1" />
 
 </LinearLayout>
--- a/mobile/android/base/resources/layout-xlarge-v11/home_history_page.xml
+++ b/mobile/android/base/resources/layout-xlarge-v11/home_history_page.xml
@@ -11,14 +11,14 @@
     <org.mozilla.gecko.widget.IconTabWidget android:id="@+id/tab_icon_widget"
                                             style="@style/Widget.Home.HistoryTabWidget"
                                             android:layout_width="@dimen/history_tab_widget_width"
                                             android:layout_height="@dimen/history_tab_widget_height"
                                             android:orientation="vertical"
                                             android:layout="@layout/home_history_tabs_indicator"
                                             gecko:display="text"/>
 
-    <FrameLayout android:id="@+id/visited_page_container"
+    <FrameLayout android:id="@+id/history_page_container"
                  android:layout_width="0dp"
                  android:layout_height="fill_parent"
                  android:layout_weight="1" />
 
 </LinearLayout>
--- a/mobile/android/base/resources/layout/home_bookmarks_page.xml
+++ b/mobile/android/base/resources/layout/home_bookmarks_page.xml
@@ -7,20 +7,9 @@
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">
 
     <org.mozilla.gecko.home.BookmarksListView
             android:id="@+id/bookmarks_list"
             android:layout_width="fill_parent"
             android:layout_height="fill_parent"/>
 
-    <org.mozilla.gecko.home.HomeBanner android:id="@+id/home_banner"
-                                       style="@style/Widget.HomeBanner"
-                                       android:layout_width="fill_parent"
-                                       android:layout_height="@dimen/home_banner_height"
-                                       android:background="@drawable/home_banner"
-                                       android:layout_gravity="bottom"
-                                       android:gravity="center_vertical"
-                                       android:visibility="gone"
-                                       android:clickable="true"
-                                       android:focusable="true"/>
-
 </FrameLayout>
--- a/mobile/android/base/resources/layout/home_history_page.xml
+++ b/mobile/android/base/resources/layout/home_history_page.xml
@@ -3,17 +3,17 @@
    - 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/. -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:orientation="vertical">
 
-    <FrameLayout android:id="@+id/visited_page_container"
+    <FrameLayout android:id="@+id/history_page_container"
                  android:layout_width="fill_parent"
                  android:layout_height="0dp"
                  android:layout_weight="1" />
 
     <org.mozilla.gecko.widget.IconTabWidget android:id="@+id/tab_icon_widget"
                                             android:layout_width="fill_parent"
                                             android:layout_height="@dimen/browser_toolbar_height"
                                             android:tabStripEnabled="false"
rename from mobile/android/base/resources/layout/home_most_visited_page.xml
rename to mobile/android/base/resources/layout/home_top_sites_page.xml
--- a/mobile/android/base/resources/layout/home_most_visited_page.xml
+++ b/mobile/android/base/resources/layout/home_top_sites_page.xml
@@ -3,11 +3,32 @@
    - 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/. -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:orientation="vertical">
 
-    <include layout="@layout/home_history_list"/>
+    <ViewStub android:id="@+id/home_empty_view_stub"
+              android:layout="@layout/home_empty_page"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"/>
+
+    <org.mozilla.gecko.home.HomeListView
+            android:id="@+id/list"
+            style="@style/Widget.TopSitesListView"
+            android:layout_width="fill_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
+
+    <org.mozilla.gecko.home.HomeBanner android:id="@+id/home_banner"
+                                       style="@style/Widget.HomeBanner"
+                                       android:layout_width="fill_parent"
+                                       android:layout_height="@dimen/home_banner_height"
+                                       android:background="@drawable/home_banner"
+                                       android:layout_gravity="bottom"
+                                       android:gravity="center_vertical"
+                                       android:visibility="gone"
+                                       android:clickable="true"
+                                       android:focusable="true"/>
 
 </LinearLayout>
--- a/mobile/android/base/resources/values-large-v11/styles.xml
+++ b/mobile/android/base/resources/values-large-v11/styles.xml
@@ -57,33 +57,34 @@
 
         <item name="android:paddingTop">0dp</item>
         <item name="android:paddingBottom">0dp</item>
         <item name="android:paddingLeft">0dp</item>
         <item name="android:paddingRight">0dp</item>
     </style>
 
     <style name="Widget.BookmarksListView" parent="Widget.HomeListView">
+        <item name="android:paddingTop">30dp</item>
         <item name="android:paddingLeft">32dp</item>
         <item name="android:paddingRight">32dp</item>
         <item name="android:scrollbarStyle">outsideOverlay</item>
+        <item name="topDivider">true</item>
     </style>
 
     <style name="Widget.TopBookmarksView" parent="Widget.GridView">
         <item name="android:paddingLeft">5dp</item>
         <item name="android:paddingRight">5dp</item>
         <item name="android:paddingTop">30dp</item>
         <item name="android:paddingBottom">30dp</item>
         <item name="android:horizontalSpacing">10dp</item>
         <item name="android:verticalSpacing">10dp</item>
     </style>
 
-    <style name="Widget.ReadingListView" parent="Widget.BookmarksListView">
-        <item name="android:paddingTop">30dp</item>
-        <item name="topDivider">true</item>
-    </style>
+    <style name="Widget.TopSitesListView" parent="Widget.BookmarksListView"/>
+
+    <style name="Widget.ReadingListView" parent="Widget.BookmarksListView"/>
 
     <style name="Widget.HomeBanner">
         <item name="android:paddingLeft">32dp</item>
         <item name="android:paddingRight">32dp</item>
     </style>
 
 </resources>
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -77,17 +77,17 @@
     <dimen name="forward_default_offset">-13dip</dimen>
     <dimen name="url_bar_offset_left">32dp</dimen>
     <dimen name="toast_button_padding">8dp</dimen>
     <dimen name="history_tab_indicator_height">50dp</dimen>
 
     <!-- We need to maintain height for the tab widget on History Page
          since android does not add footer/header divider height to its
          calculation for wrap_content in LinearLayout.
-         50dp * 3 Views + 30dp padding + 4dp dividers-->
-    <dimen name="history_tab_widget_height">184dp</dimen>
+         50dp * 2 Views + 30dp padding + 4dp dividers-->
+    <dimen name="history_tab_widget_height">134dp</dimen>
 
     <!-- PageActionButtons dimensions -->
     <dimen name="page_action_button_width">32dp</dimen>
 
     <!-- Banner -->
     <dimen name="home_banner_height">72dp</dimen>
 </resources>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -153,16 +153,18 @@
       <item name="android:paddingTop">5dip</item>
       <item name="android:gravity">left</item>
     </style>
 
     <style name="Widget.HomeListView" parent="Widget.ListView">
         <item name="android:divider">#E7ECF0</item>
     </style>
 
+    <style name="Widget.TopSitesListView" parent="Widget.BookmarksListView"/>
+
     <style name="Widget.ReadingListView" parent="Widget.BookmarksListView"/>
 
     <style name="Widget.HomeBanner"/>
 
     <style name="Widget.Home" />
 
     <style name="Widget.Home.HeaderItem">
         <item name="android:layout_width">fill_parent</item>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -247,16 +247,17 @@
   <string name="button_ok">&button_ok;</string>
   <string name="button_cancel">&button_cancel;</string>
   <string name="button_clear_data">&button_clear_data;</string>
   <string name="button_set">&button_set;</string>
   <string name="button_clear">&button_clear;</string>
   <string name="button_yes">&button_yes;</string>
   <string name="button_no">&button_no;</string>
 
+  <string name="home_top_sites_title">&home_top_sites_title;</string>
   <string name="home_history_title">&home_history_title;</string>
   <string name="home_last_tabs_title">&home_last_tabs_title;</string>
   <string name="home_last_tabs_open">&home_last_tabs_open;</string>
   <string name="home_last_tabs_empty">&home_last_tabs_empty;</string>
   <string name="home_most_recent_title">&home_most_recent_title;</string>
   <string name="home_most_recent_empty">&home_most_recent_empty;</string>
   <string name="home_most_visited_title">&home_most_visited_title;</string>
   <string name="home_most_visited_empty">&home_most_visited_empty;</string>