backout 793ffe6ed42e (bug 960359)
authorMargaret Leibovic <margaret.leibovic@gmail.com>
Mon, 03 Feb 2014 10:02:42 -0800
changeset 166625 5fb066c6d76c3ef0fc6c523fc0305b31fdac4f41
parent 166624 b1f8c61bb310023f88e9e8f6532bc66a4d8756eb
child 166629 ba2cc1eda988a1614d8986ae145d28e1268409b9
push id4806
push usermleibovic@mozilla.com
push dateMon, 03 Feb 2014 18:02:57 +0000
treeherderfx-team@5fb066c6d76c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs960359
milestone29.0a1
backs out793ffe6ed42ec1f0d554ab47150dba45f54282a3
backout 793ffe6ed42e (bug 960359)
mobile/android/base/BrowserApp.java
mobile/android/base/home/HomeBanner.java
mobile/android/base/home/HomePager.java
mobile/android/base/home/TopSitesPanel.java
mobile/android/base/resources/layout-large-v11/home_pager.xml
mobile/android/base/resources/layout/gecko_app.xml
mobile/android/base/resources/layout/home_pager.xml
mobile/android/base/resources/layout/home_top_sites_panel.xml
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1644,17 +1644,17 @@ abstract public class BrowserApp extends
         // Show the toolbar before hiding about:home so the
         // onMetricsChanged callback still works.
         if (isDynamicToolbarEnabled() && mLayerView != null) {
             mLayerView.getLayerMarginsAnimator().showMargins(true);
         }
 
         if (mHomePager == null) {
             final ViewStub homePagerStub = (ViewStub) findViewById(R.id.home_pager_stub);
-            mHomePager = (HomePager) homePagerStub.inflate().findViewById(R.id.home_pager);
+            mHomePager = (HomePager) homePagerStub.inflate();
         }
 
         mHomePager.show(getSupportLoaderManager(),
                         getSupportFragmentManager(),
                         pageId, animator);
 
         // Hide the web content so it cannot be focused by screen readers.
         hideWebContentOnPropertyAnimationEnd(animator);
--- a/mobile/android/base/home/HomeBanner.java
+++ b/mobile/android/base/home/HomeBanner.java
@@ -1,19 +1,15 @@
 /* -*- 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.animation.PropertyAnimator;
-import org.mozilla.gecko.animation.PropertyAnimator.Property;
-import org.mozilla.gecko.animation.PropertyAnimator.PropertyAnimationListener;
-import org.mozilla.gecko.animation.ViewHelper;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import org.json.JSONException;
@@ -22,229 +18,121 @@ import org.json.JSONObject;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.text.Html;
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.LayoutInflater;
-import android.view.MotionEvent;
 import android.view.View;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 public class HomeBanner extends LinearLayout
                         implements GeckoEventListener {
     private static final String LOGTAG = "GeckoHomeBanner";
 
-    final TextView mTextView;
-    final ImageView mIconView;
-    final ImageButton mCloseButton;
-
-    // Used for tracking scroll length
-    private float mTouchY = -1;
-
-    // Used to detect for upwards scroll to push banner all the way up
-    private boolean mSnapBannerToTop;
-
-    // Used so that we don't move the banner when scrolling between pages
-    private boolean mScrollingPages = false;
-
-    // User has dismissed the banner using the close button
-    private boolean mDismissed = false;
-
     public HomeBanner(Context context) {
         this(context, null);
     }
 
     public HomeBanner(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         LayoutInflater.from(context).inflate(R.layout.home_banner, this);
-        mTextView = (TextView) findViewById(R.id.text);
-        mIconView = (ImageView) findViewById(R.id.icon);
-        mCloseButton = (ImageButton) findViewById(R.id.close);
+    }
 
-        mCloseButton.getDrawable().setAlpha(127);
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
         // Tapping on the close button will ensure that the banner is never
         // showed again on this session.
-        mCloseButton.setOnClickListener(new View.OnClickListener() {
+        final ImageButton closeButton = (ImageButton) findViewById(R.id.close);
+
+        // The drawable should have 50% opacity.
+        closeButton.getDrawable().setAlpha(127);
+
+        closeButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                animateDown();
-                mDismissed = true;
+                HomeBanner.this.setVisibility(View.GONE);
             }
         });
 
         setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 // Send the current message id back to JS.
-                GeckoAppShell.sendEventToGecko(
-                    GeckoEvent.createBroadcastEvent("HomeBanner:Click",(String) getTag()));
+                GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("HomeBanner:Click", (String) getTag()));
             }
         });
-    }
 
-    @Override
-    public void onAttachedToWindow() {
         GeckoAppShell.getEventDispatcher().registerEventListener("HomeBanner:Data", this);
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("HomeBanner:Get", null));
     }
 
     @Override
     public void onDetachedFromWindow() {
-        GeckoAppShell.getEventDispatcher().unregisterEventListener("HomeBanner:Data", this);
-    }
+        super.onDetachedFromWindow();
 
-    public void showBanner() {
-        if (!mDismissed) {
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("HomeBanner:Get", null));
-        }
-    }
+        GeckoAppShell.getEventDispatcher().unregisterEventListener("HomeBanner:Data", this);
+     }
 
-    public void hideBanner() {
-        animateDown();
-    }
-
-    public void setScrollingPages(boolean scrollingPages) {
-        mScrollingPages = scrollingPages;
+    public boolean isDismissed() {
+        return (getVisibility() == View.GONE);
     }
 
     @Override
-    public void handleMessage(final String event, final JSONObject message) {
-        ThreadUtils.postToUiThread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    // Store the current message id to pass back to JS in the view's OnClickListener.
-                    setTag(message.getString("id"));
-                    setText(message.getString("text"));
-                    setIcon(message.optString("iconURI"));
-                    animateUp();
-                } catch (JSONException e) {
-                    Log.e(LOGTAG, "Exception handling " + event + " message", e);
+    public void handleMessage(String event, JSONObject message) {
+        try {
+            // Store the current message id to pass back to JS in the view's OnClickListener.
+            setTag(message.getString("id"));
+
+            // Display styled text from an HTML string.
+            final Spanned text = Html.fromHtml(message.getString("text"));
+            final TextView textView = (TextView) findViewById(R.id.text);
+
+            // Update the banner message on the UI thread.
+            ThreadUtils.postToUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    textView.setText(text);
+                    setVisibility(View.VISIBLE);
                 }
-            }
-        });
-    }
+            });
+        } catch (JSONException e) {
+            Log.e(LOGTAG, "Exception handling " + event + " message", e);
+            return;
+        }
 
-    private void setText(String text) {
-        // Display styled text from an HTML string.
-        final Spanned html = Html.fromHtml(text);
+        final String iconURI = message.optString("iconURI");
+        final ImageView iconView = (ImageView) findViewById(R.id.icon);
 
-        // Update the banner message on the UI thread.
-        mTextView.setText(html);
-    }
-
-    private void setIcon(String iconURI) {
         if (TextUtils.isEmpty(iconURI)) {
             // Hide the image view if we don't have an icon to show.
-            mIconView.setVisibility(View.GONE);
+            iconView.setVisibility(View.GONE);
             return;
         }
 
         BitmapUtils.getDrawable(getContext(), iconURI, new BitmapUtils.BitmapLoader() {
             @Override
             public void onBitmapFound(final Drawable d) {
                 // Bail if getDrawable doesn't find anything.
                 if (d == null) {
-                    mIconView.setVisibility(View.GONE);
+                    iconView.setVisibility(View.GONE);
                     return;
                 }
 
-                // Update the banner icon
-                mIconView.setImageDrawable(d);
-            }
-        });
-    }
-
-    private void animateDown() {
-        // No need to animate if already translated.
-        if (getVisibility() == GONE && ViewHelper.getTranslationY(this) == getHeight()) {
-            return;
-        }
-
-        final PropertyAnimator animator = new PropertyAnimator(100);
-        animator.attach(this, Property.TRANSLATION_Y, getHeight());
-        animator.start();
-        animator.addPropertyAnimationListener(new PropertyAnimationListener() {
-            @Override
-            public void onPropertyAnimationStart() {}
-            public void onPropertyAnimationEnd() {
-                HomeBanner.this.setVisibility(GONE);
+                // Update the banner icon on the UI thread.
+                ThreadUtils.postToUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        iconView.setImageDrawable(d);
+                    }
+                });
             }
         });
     }
-
-    private void animateUp() {
-        // No need to animate if already translated.
-        if (getVisibility() == VISIBLE && ViewHelper.getTranslationY(this) == 0) {
-            return;
-        }
-
-        setVisibility(View.VISIBLE);
-        final PropertyAnimator animator = new PropertyAnimator(100);
-        animator.attach(this, Property.TRANSLATION_Y, 0);
-        animator.start();
-    }
-
-    /**
-     * Touches to the HomePager are forwarded here to handle the hiding / showing of the banner
-     * on scroll.
-     */
-    public void handleHomeTouch(MotionEvent event) {
-        if (mDismissed || mScrollingPages) {
-            return;
-        }
-
-        switch (event.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN: {
-                mTouchY = 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 (mTouchY == -1) {
-                    mTouchY = event.getRawY();
-                    return;
-                }
-
-                final float curY = event.getRawY();
-                final float delta = mTouchY - curY;
-                mSnapBannerToTop = delta <= 0.0f;
-
-                final float height = getHeight();
-                float newTranslationY = ViewHelper.getTranslationY(this) + 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(this, newTranslationY);
-                mTouchY = curY;
-                break;
-            }
-
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL: {
-                mTouchY = -1;
-                final float y = ViewHelper.getTranslationY(this);
-                final float height = getHeight();
-                if (y > 0.0f && y < height) {
-                    if (mSnapBannerToTop) {
-                        animateUp();
-                    } else {
-                        animateDown();
-                    }
-                }
-                break;
-            }
-        }
-    }
 }
--- a/mobile/android/base/home/HomePager.java
+++ b/mobile/android/base/home/HomePager.java
@@ -19,44 +19,39 @@ import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.app.LoaderManager.LoaderCallbacks;
 import android.support.v4.content.Loader;
 import android.support.v4.view.ViewPager;
 import android.view.ViewGroup.LayoutParams;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.view.View;
 
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
 
 public class HomePager extends ViewPager {
-    private static final String LOGTAG = "GeckoHomePager";
 
     private static final int LOADER_ID_CONFIG = 0;
 
     private final Context mContext;
     private volatile boolean mLoaded;
     private Decor mDecor;
     private View mTabStrip;
-    private HomeBanner mHomeBanner;
 
     private final OnAddPanelListener mAddPanelListener;
 
     private final HomeConfig mConfig;
     private ConfigLoaderCallbacks mConfigLoaderCallbacks;
 
     private String mInitialPanelId;
-    private int mDefaultPanelIndex;
 
     // Whether or not we need to restart the loader when we show the HomePager.
     private boolean mRestartLoader;
 
     // 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";
@@ -239,40 +234,27 @@ public class HomePager extends ViewPager
             });
 
             ViewHelper.setAlpha(this, 0.0f);
 
             animator.attach(this,
                             PropertyAnimator.Property.ALPHA,
                             1.0f);
         }
-
-        // Setup banner and decor listeners
-        mHomeBanner = (HomeBanner) ((ViewGroup) getParent()).findViewById(R.id.home_banner);
-        setOnPageChangeListener(new HomePagerOnPageChangeListener());
     }
 
     /**
      * Hides the pager and removes all child fragments.
      */
     public void hide() {
         mLoaded = false;
         setVisibility(GONE);
         setAdapter(null);
     }
 
-    @Override
-    public void setVisibility(int visibility) {
-        // Ensure that no decorations are overlaying the mainlayout
-        if (mHomeBanner != null) {
-            mHomeBanner.setVisibility(visibility);
-        }
-        super.setVisibility(visibility);
-    }
-
     /**
      * Determines whether the pager is visible.
      *
      * Unlike getVisibility(), this method does not need to be called on the UI
      * thread.
      *
      * @return Whether the pager and its fragments are being displayed
      */
@@ -282,45 +264,28 @@ public class HomePager extends ViewPager
 
     @Override
     public void setCurrentItem(int item, boolean smoothScroll) {
         super.setCurrentItem(item, smoothScroll);
 
         if (mDecor != null) {
             mDecor.onPageSelected(item);
         }
-        if (mHomeBanner != null) {
-            if (item == mDefaultPanelIndex) {
-                mHomeBanner.showBanner();
-            } else {
-                mHomeBanner.hideBanner();
-            }
-        }
     }
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
             // Drop the soft keyboard by stealing focus from the URL bar.
             requestFocus();
         }
 
         return super.onInterceptTouchEvent(event);
     }
 
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent event) {
-        // Get touches to pages, pass to banner, and forward to pages.
-        if (mHomeBanner != null) {
-            mHomeBanner.handleHomeTouch(event);
-        }
-
-        return super.dispatchTouchEvent(event);
-    }
-
     private void updateUiFromPanelConfigs(List<PanelConfig> panelConfigs) {
         // We only care about the adapter if HomePager is currently
         // loaded, which means it's visible in the activity.
         if (!mLoaded) {
             return;
         }
 
         if (mDecor != null) {
@@ -334,19 +299,16 @@ public class HomePager extends ViewPager
         setAdapter(null);
 
         // Only keep enabled panels.
         final List<PanelConfig> enabledPanels = new ArrayList<PanelConfig>();
 
         for (PanelConfig panelConfig : panelConfigs) {
             if (!panelConfig.isDisabled()) {
                 enabledPanels.add(panelConfig);
-                if (panelConfig.isDefault()) {
-                    mDefaultPanelIndex = enabledPanels.size() - 1;
-                }
             }
         }
 
         // Update the adapter with the new panel configs
         adapter.update(enabledPanels);
 
         // Hide the tab strip if the new configuration contains no panels.
         final int count = enabledPanels.size();
@@ -382,40 +344,9 @@ public class HomePager extends ViewPager
         public void onLoadFinished(Loader<List<PanelConfig>> loader, List<PanelConfig> panelConfigs) {
             updateUiFromPanelConfigs(panelConfigs);
         }
 
         @Override
         public void onLoaderReset(Loader<List<PanelConfig>> loader) {
         }
     }
-
-    private class HomePagerOnPageChangeListener implements ViewPager.OnPageChangeListener {
-        @Override
-        public void onPageSelected(int position) {
-            if (mDecor != null) {
-                mDecor.onPageSelected(position);
-            }
-
-            if (mHomeBanner != null) {
-                if (position == mDefaultPanelIndex) {
-                    mHomeBanner.showBanner();
-                } else {
-                    mHomeBanner.hideBanner();
-                }
-            }
-        }
-
-        @Override
-        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-            if (mDecor != null) {
-                mDecor.onPageScrolled(position, positionOffset, positionOffsetPixels);
-            }
-
-            if (mHomeBanner != null) {
-                mHomeBanner.setScrollingPages(positionOffsetPixels > 0);
-            }
-        }
-
-        @Override
-        public void onPageScrollStateChanged(int state) { }
-    }
 }
--- a/mobile/android/base/home/TopSitesPanel.java
+++ b/mobile/android/base/home/TopSitesPanel.java
@@ -81,16 +81,25 @@ public class TopSitesPanel extends HomeF
     private TopSitesGridAdapter mGridAdapter;
 
     // List of top sites
     private ListView mList;
 
     // Grid of top sites
     private TopSitesGridView mGrid;
 
+    // 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;
 
     // Callback for thumbnail loader
     private ThumbnailsLoaderCallbacks mThumbnailsLoaderCallbacks;
 
     // Listener for editing pinned sites.
     private EditPinnedSiteListener mEditPinnedSiteListener;
@@ -192,16 +201,25 @@ public class TopSitesPanel extends HomeF
             }
         });
 
         mGrid.setOnUrlOpenListener(mUrlOpenListener);
         mGrid.setOnEditPinnedSiteListener(mEditPinnedSiteListener);
 
         registerForContextMenu(mList);
         registerForContextMenu(mGrid);
+
+        mBanner = (HomeBanner) view.findViewById(R.id.home_banner);
+        mList.setOnTouchListener(new OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                TopSitesPanel.this.handleListTouchEvent(event);
+                return false;
+            }
+        });
     }
 
     @Override
     public void onDestroyView() {
         super.onDestroyView();
 
         // Discard any additional item clicks on the list
         // as the panel is getting destroyed (see bug 930160).
@@ -430,16 +448,70 @@ public class TopSitesPanel extends HomeF
                 @Override
                 public void run() {
                     BrowserDB.pinSite(context.getContentResolver(), url, title, position);
                 }
             });
         }
     }
 
+    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) {
         mList.setHeaderDividersEnabled(c != null && c.getCount() > mMaxGridEntries);
     }
 
     private static class TopSitesLoader extends SimpleCursorLoader {
         // Max number of search results
         private static final int SEARCH_LIMIT = 30;
         private int mMaxGridEntries;
--- a/mobile/android/base/resources/layout-large-v11/home_pager.xml
+++ b/mobile/android/base/resources/layout-large-v11/home_pager.xml
@@ -9,16 +9,15 @@
 <org.mozilla.gecko.home.HomePager xmlns:android="http://schemas.android.com/apk/res/android"
                                   xmlns:gecko="http://schemas.android.com/apk/res-auto"
                                   android:id="@+id/home_pager"
                                   android:layout_width="fill_parent"
                                   android:layout_height="fill_parent"
                                   android:background="@android:color/white"
                                   android:visibility="gone">
 
-    <org.mozilla.gecko.home.TabMenuStrip android:id="@+id/tablet_menu_strip"
-                                         android:layout_width="fill_parent"
+    <org.mozilla.gecko.home.TabMenuStrip android:layout_width="fill_parent"
                                          android:layout_height="32dip"
                                          android:background="@color/background_light"
                                          android:layout_gravity="top"
                                          gecko:strip="@drawable/home_tab_menu_strip"/>
 
 </org.mozilla.gecko.home.HomePager>
--- a/mobile/android/base/resources/layout/gecko_app.xml
+++ b/mobile/android/base/resources/layout/gecko_app.xml
@@ -31,26 +31,16 @@
                          android:layout_width="fill_parent"
                          android:layout_height="fill_parent">
 
                 <ViewStub android:id="@+id/home_pager_stub"
                           android:layout="@layout/home_pager"
                           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>
 
         </RelativeLayout>
 
         <org.mozilla.gecko.FindInPageBar android:id="@+id/find_in_page"
                                          android:layout_width="fill_parent"
                                          android:layout_height="wrap_content"
--- a/mobile/android/base/resources/layout/home_pager.xml
+++ b/mobile/android/base/resources/layout/home_pager.xml
@@ -9,18 +9,17 @@
 <org.mozilla.gecko.home.HomePager xmlns:android="http://schemas.android.com/apk/res/android"
                                   xmlns:gecko="http://schemas.android.com/apk/res-auto"
                                   android:id="@+id/home_pager"
                                   android:layout_width="fill_parent"
                                   android:layout_height="fill_parent"
                                   android:background="@android:color/white"
                                   android:visibility="gone">
 
-    <org.mozilla.gecko.home.HomePagerTabStrip android:id="@+id/phone_menu_strip"
-                                              android:layout_width="fill_parent"
+    <org.mozilla.gecko.home.HomePagerTabStrip android:layout_width="fill_parent"
                                               android:layout_height="32dip"
                                               android:layout_gravity="top"
                                               android:gravity="bottom"
                                               android:background="@color/background_light"
                                               gecko:tabIndicatorColor="@color/text_color_highlight"
                                               android:textAppearance="@style/TextAppearance.Widget.HomePagerTabStrip"/>
 
 </org.mozilla.gecko.home.HomePager>
--- a/mobile/android/base/resources/layout/home_top_sites_panel.xml
+++ b/mobile/android/base/resources/layout/home_top_sites_panel.xml
@@ -1,10 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
-<org.mozilla.gecko.home.HomeListView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/list"
-        style="@style/Widget.TopSitesListView"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent" />
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:layout_width="fill_parent"
+             android:layout_height="fill_parent"
+             android:orientation="vertical">
+
+    <org.mozilla.gecko.home.HomeListView
+            android:id="@+id/list"
+            style="@style/Widget.TopSitesListView"
+            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>