Bug 909618 - Part 3: Remember about:home tab selection. r=lucasr, a=lsblakk
authorSola Ogunsakin <oogunsakin@mozilla.com>
Fri, 17 Jan 2014 10:41:15 -0800
changeset 192960 6290c8194ab984a25a1ec9fa7af41cc16466a491
parent 192959 b2be07b69a742155672ef781a76f5b921a350ec9
child 192961 73afe69f15d32f3f518ba3e09406423377621850
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslucasr, lsblakk
bugs909618
milestone30.0a2
Bug 909618 - Part 3: Remember about:home tab selection. r=lucasr, a=lsblakk
mobile/android/base/AboutPages.java
mobile/android/base/BrowserApp.java
mobile/android/base/Tab.java
mobile/android/base/home/HomePager.java
mobile/android/chrome/content/aboutReader.js
--- a/mobile/android/base/AboutPages.java
+++ b/mobile/android/base/AboutPages.java
@@ -17,16 +17,18 @@ public class AboutPages {
     public static final String HEALTHREPORT    = "about:healthreport";
     public static final String HOME            = "about:home";
     public static final String PRIVATEBROWSING = "about:privatebrowsing";
     public static final String READER          = "about:reader";
     public static final String UPDATER         = "about:";
 
     public static final String URL_FILTER = "about:%";
 
+    public static final String PANEL_PARAM = "panel";
+
     public static final boolean isAboutPage(final String url) {
         return url.startsWith("about:");
     }
 
     public static final boolean isTitlelessAboutPage(final String url) {
         return isAboutHome(url) ||
                PRIVATEBROWSING.equals(url);
     }
@@ -36,18 +38,18 @@ public class AboutPages {
             return false;
         }
         // We sometimes append a parameter to "about:home" to specify which page to
         // show when we open the home pager. Discard this parameter when checking
         // whether or not this URL is "about:home".
         return HOME.equals(url.split("\\?")[0]);
     }
 
-    public static final String getPageIdFromAboutHomeUrl(final String aboutHomeUrl) {
-        return StringUtils.getQueryParameter(aboutHomeUrl, "page");
+    public static final String getPanelIdFromAboutHomeUrl(String aboutHomeUrl) {
+        return StringUtils.getQueryParameter(aboutHomeUrl, PANEL_PARAM);
     }
 
     public static final boolean isAboutReader(final String url) {
         if (url == null) {
             return false;
         }
         return url.startsWith(READER);
     }
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -1537,17 +1537,19 @@ abstract public class BrowserApp extends
 
         final Tab selectedTab = Tabs.getInstance().getSelectedTab();
         mTargetTabForEditingMode = (selectedTab != null ? selectedTab.getId() : null);
 
         final PropertyAnimator animator = new PropertyAnimator(250);
         animator.setUseHardwareLayer(false);
 
         mBrowserToolbar.startEditing(url, animator);
-        showHomePagerWithAnimator(animator);
+
+        final String panelId = selectedTab.getMostRecentHomePanel();
+        showHomePagerWithAnimator(panelId, animator);
 
         animator.start();
     }
 
     private void commitEditingMode() {
         if (!mBrowserToolbar.isEditing()) {
             return;
         }
@@ -1667,18 +1669,23 @@ abstract public class BrowserApp extends
      */
     private void updateHomePagerForTab(Tab tab) {
         // Don't change the visibility of the home pager if we're in editing mode.
         if (mBrowserToolbar.isEditing()) {
             return;
         }
 
         if (isAboutHome(tab)) {
-            final String pageId = AboutPages.getPageIdFromAboutHomeUrl(tab.getURL());
-            showHomePager(pageId);
+            String panelId = AboutPages.getPanelIdFromAboutHomeUrl(tab.getURL());
+            if (panelId == null) {
+                // No panel was specified in the URL. Try loading the most recent
+                // home panel for this tab.
+                panelId = tab.getMostRecentHomePanel();
+            }
+            showHomePager(panelId);
 
             if (mDynamicToolbar.isEnabled()) {
                 mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
             }
         } else {
             hideHomePager();
         }
     }
@@ -1690,44 +1697,50 @@ abstract public class BrowserApp extends
         HomeConfigInvalidator.getInstance().onLocaleReady(locale);
 
         if (mMenu != null) {
             mMenu.clear();
             onCreateOptionsMenu(mMenu);
         }
     }
 
-    private void showHomePager(String pageId) {
-        showHomePagerWithAnimator(pageId, null);
+    private void showHomePager(String panelId) {
+        showHomePagerWithAnimator(panelId, null);
     }
 
-    private void showHomePagerWithAnimator(PropertyAnimator animator) {
-        // Passing null here means the default page will be defined
-        // by the HomePager's configuration.
-        showHomePagerWithAnimator(null, animator);
-    }
-
-    private void showHomePagerWithAnimator(String pageId, PropertyAnimator animator) {
+    private void showHomePagerWithAnimator(String panelId, PropertyAnimator animator) {
         if (isHomePagerVisible()) {
+            // Home pager already visible, make sure it shows the correct panel.
+            mHomePager.showPanel(panelId);
             return;
         }
 
         // Refresh toolbar height to possibly restore the toolbar padding
         refreshToolbarHeight();
 
         // Show the toolbar before hiding about:home so the
         // onMetricsChanged callback still works.
         if (mDynamicToolbar.isEnabled()) {
             mDynamicToolbar.setVisible(true, VisibilityTransition.IMMEDIATE);
         }
 
         if (mHomePager == null) {
             final ViewStub homePagerStub = (ViewStub) findViewById(R.id.home_pager_stub);
             mHomePager = (HomePager) homePagerStub.inflate();
 
+            mHomePager.setOnPanelChangeListener(new HomePager.OnPanelChangeListener() {
+                @Override
+                public void onPanelSelected(String panelId) {
+                    final Tab currentTab = Tabs.getInstance().getSelectedTab();
+                    if (currentTab != null) {
+                        currentTab.setMostRecentHomePanel(panelId);
+                    }
+                }
+            });
+
             // Don't show the banner in guest mode.
             if (!getProfile().inGuestMode()) {
                 final ViewStub homeBannerStub = (ViewStub) findViewById(R.id.home_banner_stub);
                 final HomeBanner homeBanner = (HomeBanner) homeBannerStub.inflate();
                 mHomePager.setBanner(homeBanner);
 
                 // Remove the banner from the view hierarchy if it is dismissed.
                 homeBanner.setOnDismissListener(new HomeBanner.OnDismissListener() {
@@ -1738,17 +1751,17 @@ abstract public class BrowserApp extends
                     }
                 });
             }
         }
 
         mHomePagerContainer.setVisibility(View.VISIBLE);
         mHomePager.load(getSupportLoaderManager(),
                         getSupportFragmentManager(),
-                        pageId, animator);
+                        panelId, animator);
 
         // Hide the web content so it cannot be focused by screen readers.
         hideWebContentOnPropertyAnimationEnd(animator);
     }
 
     private void hideWebContentOnPropertyAnimationEnd(final PropertyAnimator animator) {
         if (animator == null) {
             hideWebContent();
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -63,16 +63,17 @@ public class Tab {
     private int mState;
     private Bitmap mThumbnailBitmap;
     private boolean mDesktopMode;
     private boolean mEnteringReaderMode;
     private Context mAppContext;
     private ErrorType mErrorType = ErrorType.NONE;
     private static final int MAX_HISTORY_LIST_SIZE = 50;
     private volatile int mLoadProgress;
+    private String mMostRecentHomePanel;
 
     public static final int STATE_DELAYED = 0;
     public static final int STATE_LOADING = 1;
     public static final int STATE_SUCCESS = 2;
     public static final int STATE_ERROR = 3;
 
     public static final int LOAD_PROGRESS_INIT = 10;
     public static final int LOAD_PROGRESS_START = 20;
@@ -182,16 +183,24 @@ public class Tab {
     public Bitmap getFavicon() {
         return mFavicon;
     }
 
     public BitmapDrawable getThumbnail() {
         return mThumbnail;
     }
 
+    public String getMostRecentHomePanel() {
+        return mMostRecentHomePanel;
+    }
+
+    public void setMostRecentHomePanel(String panelId) {
+        mMostRecentHomePanel = panelId;
+    }
+
     public Bitmap getThumbnailBitmap(int width, int height) {
         if (mThumbnailBitmap != null) {
             // Bug 787318 - Honeycomb has a bug with bitmap caching, we can't
             // reuse the bitmap there.
             boolean honeycomb = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB
                               && Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
             boolean sizeChange = mThumbnailBitmap.getWidth() != width
                               || mThumbnailBitmap.getHeight() != height;
--- a/mobile/android/base/home/HomePager.java
+++ b/mobile/android/base/home/HomePager.java
@@ -48,16 +48,19 @@ public class HomePager extends ViewPager
     private String mInitialPanelId;
 
     // Cached original ViewPager background.
     private final Drawable mOriginalBackground;
 
     // Current load state of HomePager.
     private LoadState mLoadState;
 
+    // Listens for when the current panel changes.
+    private OnPanelChangeListener mPanelChangedListener;
+
     // 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";
     static final String LIST_TAG_READING_LIST = "reading_list";
     static final String LIST_TAG_TOP_SITES = "top_sites";
     static final String LIST_TAG_MOST_RECENT = "most_recent";
     static final String LIST_TAG_LAST_TABS = "last_tabs";
@@ -71,16 +74,28 @@ public class HomePager extends ViewPager
 
         public void onUrlOpen(String url, EnumSet<Flags> flags);
     }
 
     public interface OnNewTabsListener {
         public void onNewTabs(String[] urls);
     }
 
+    /**
+     * Interface for listening into ViewPager panel changes
+     */
+    public interface OnPanelChangeListener {
+        /**
+         * Called when a new panel is selected.
+         *
+         * @param panelId of the newly selected panel
+         */
+        public void onPanelSelected(String panelId);
+    }
+
     interface OnTitleClickListener {
         public void onTitleClicked(int index);
     }
 
     /**
      * Special type of child views that could be added as pager decorations by default.
      */
     interface Decor {
@@ -242,16 +257,50 @@ public class HomePager extends ViewPager
             mDecor.onPageSelected(item);
         }
 
         if (mHomeBanner != null) {
             mHomeBanner.setActive(item == mDefaultPageIndex);
         }
     }
 
+    /**
+     * Shows a home panel. If the given panelId is null,
+     * the default panel will be shown. No action will be taken if:
+     *  * HomePager has not loaded yet
+     *  * Panel with the given panelId cannot be found
+     *
+     * @param panelId of the home panel to be shown.
+     */
+    public void showPanel(String panelId) {
+        if (!mVisible) {
+            return;
+        }
+
+        switch (mLoadState) {
+            case LOADING:
+                mInitialPanelId = panelId;
+                break;
+
+            case LOADED:
+                int position = mDefaultPageIndex;
+                if (panelId != null) {
+                    position = ((HomeAdapter) getAdapter()).getItemPosition(panelId);
+                }
+
+                if (position > -1) {
+                    setCurrentItem(position);
+                }
+                break;
+
+            default:
+                // Do nothing.
+        }
+    }
+
     @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);
@@ -347,16 +396,36 @@ public class HomePager extends ViewPager
                 setCurrentItem(itemPosition, false);
                 mInitialPanelId = null;
             } else {
                 setCurrentItem(mDefaultPageIndex, false);
             }
         }
     }
 
+    public void setOnPanelChangeListener(OnPanelChangeListener listener) {
+       mPanelChangedListener = listener;
+    }
+
+    /**
+     * Notify listeners of newly selected panel.
+     *
+     * @param position of the newly selected panel
+     */
+    private void notifyPanelSelected(int position) {
+        if (mDecor != null) {
+            mDecor.onPageSelected(position);
+        }
+
+        if (mPanelChangedListener != null) {
+            final String panelId = ((HomeAdapter) getAdapter()).getPanelIdAtPosition(position);
+            mPanelChangedListener.onPanelSelected(panelId);
+        }
+    }
+
     private class ConfigLoaderCallbacks implements LoaderCallbacks<HomeConfig.State> {
         @Override
         public Loader<HomeConfig.State> onCreateLoader(int id, Bundle args) {
             return new HomeConfigLoader(mContext, mConfig);
         }
 
         @Override
         public void onLoadFinished(Loader<HomeConfig.State> loader, HomeConfig.State configState) {
@@ -368,19 +437,17 @@ public class HomePager extends ViewPager
         public void onLoaderReset(Loader<HomeConfig.State> loader) {
             mLoadState = LoadState.UNLOADED;
         }
     }
 
     private class PageChangeListener implements ViewPager.OnPageChangeListener {
         @Override
         public void onPageSelected(int position) {
-            if (mDecor != null) {
-                mDecor.onPageSelected(position);
-            }
+            notifyPanelSelected(position);
 
             if (mHomeBanner != null) {
                 mHomeBanner.setActive(position == mDefaultPageIndex);
             }
         }
 
         @Override
         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -360,17 +360,17 @@ AboutReader.prototype = {
       Services.obs.notifyObservers(null, "Reader:Remove", this._article.url);
     }
   },
 
   _onList: function Reader_onList() {
     if (!this._article || this._readingListCount < 1)
       return;
 
-    gChromeWin.BrowserApp.loadURI("about:home?page=" + READING_LIST_PANEL_ID);
+    gChromeWin.BrowserApp.loadURI("about:home?panel=" + READING_LIST_PANEL_ID);
   },
 
   _onShare: function Reader_onShare() {
     if (!this._article)
       return;
 
     gChromeWin.sendMessageToJava({
       type: "Reader:Share",