Bug 1261008 - Do not restore tabs pointing to about:home and with no history. r=janh,ahunt a=gchang
authorSebastian Kaspari <s.kaspari@gmail.com>
Wed, 06 Jul 2016 16:04:01 +0200
changeset 339936 ce26d5834678f648f49926fd637e2c90a14df8b4
parent 339935 5849e67a8dbab1086a2b5e2b9a569f446cb15995
child 339937 76f20388d4f8e18634160d3669d26acf9a2e6b68
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanh, ahunt, gchang
bugs1261008
milestone49.0a2
Bug 1261008 - Do not restore tabs pointing to about:home and with no history. r=janh,ahunt a=gchang If the browser is set to always restore the session (default) then we will never start with an empty session. Even if the user closes all tabs we will re-create a new tab pointing to about:home. So we will always at least restore this tab on the next startup. As a consequence we will never open the 'homepage' on app start because we will never have a non-empty session. With this patch we won't restore tabs that point to about:home and do not contain any other history. As a result we might restore an empty session and load the homepage or about:home (depending on configuration) in a new tab. In case we decide to not restore the currently selected tab, we just select the first restored tab if there's any. MozReview-Commit-ID: DuN03M60Gi8
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/SessionParser.java
mobile/android/base/java/org/mozilla/gecko/Tabs.java
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -1687,26 +1687,56 @@ public abstract class GeckoApp
 
             // If we are doing an OOM restore, parse the session data and
             // stub the restored tabs immediately. This allows the UI to be
             // updated before Gecko has restored.
             if (mShouldRestore) {
                 final JSONArray tabs = new JSONArray();
                 final JSONObject windowObject = new JSONObject();
                 SessionParser parser = new SessionParser() {
+                    private boolean selectNextTab;
+
                     @Override
                     public void onTabRead(final SessionTab sessionTab) {
+                        if (sessionTab.isAboutHomeWithoutHistory()) {
+                            // This is a tab pointing to about:home with no history. We won't restore
+                            // this tab. If we end up restoring no tabs then the browser will decide
+                            // whether it needs to open about:home or a different 'homepage'. If we'd
+                            // always restore about:home only tabs then we'd never open the homepage.
+                            // See bug 1261008.
+
+                            if (sessionTab.isSelected()) {
+                                // Unfortunately this tab is the selected tab. Let's just try to select
+                                // the first tab. If we haven't restored any tabs so far then remember
+                                // to select the next tab that gets restored.
+
+                                if (!Tabs.getInstance().selectLastTab()) {
+                                    selectNextTab = true;
+                                }
+                            }
+
+                            // Do not restore this tab.
+                            return;
+                        }
+
                         JSONObject tabObject = sessionTab.getTabObject();
 
                         int flags = Tabs.LOADURL_NEW_TAB;
                         flags |= ((isExternalURL || !sessionTab.isSelected()) ? Tabs.LOADURL_DELAY_LOAD : 0);
                         flags |= (tabObject.optBoolean("desktopMode") ? Tabs.LOADURL_DESKTOP : 0);
                         flags |= (tabObject.optBoolean("isPrivate") ? Tabs.LOADURL_PRIVATE : 0);
 
                         final Tab tab = Tabs.getInstance().loadUrl(sessionTab.getUrl(), flags);
+
+                        if (selectNextTab) {
+                            // We did not restore the selected tab previously. Now let's select this tab.
+                            Tabs.getInstance().selectTab(tab.getId());
+                            selectNextTab = false;
+                        }
+
                         ThreadUtils.postToUiThread(new Runnable() {
                             @Override
                             public void run() {
                                 tab.updateTitle(sessionTab.getTitle());
                             }
                         });
 
                         try {
--- a/mobile/android/base/java/org/mozilla/gecko/SessionParser.java
+++ b/mobile/android/base/java/org/mozilla/gecko/SessionParser.java
@@ -43,16 +43,24 @@ public abstract class SessionParser {
 
         public boolean isSelected() {
             return mIsSelected;
         }
 
         public JSONObject getTabObject() {
             return mTabObject;
         }
+
+        /**
+         * Is this tab pointing to about:home and does not contain any other history?
+         */
+        public boolean isAboutHomeWithoutHistory() {
+            JSONArray entries = mTabObject.optJSONArray("entries");
+            return entries != null && entries.length() == 1 && AboutPages.isAboutHome(mUrl);
+        }
     };
 
     abstract public void onTabRead(SessionTab tab);
 
     /**
      * Placeholder method that must be overloaded to handle closedTabs while parsing session data.
      *
      * @param closedTabs, JSONArray of recently closed tab entries.
--- a/mobile/android/base/java/org/mozilla/gecko/Tabs.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tabs.java
@@ -255,16 +255,25 @@ public class Tabs implements GeckoEventL
             notifyListeners(oldTab, TabEvents.UNSELECTED);
         }
 
         // Pass a message to Gecko to update tab state in BrowserApp.
         GeckoAppShell.notifyObservers("Tab:Selected", String.valueOf(tab.getId()));
         return tab;
     }
 
+    public synchronized boolean selectLastTab() {
+        if (mOrder.isEmpty()) {
+            return false;
+        }
+
+        selectTab(mOrder.get(mOrder.size() - 1).getId());
+        return true;
+    }
+
     private int getIndexOf(Tab tab) {
         return mOrder.lastIndexOf(tab);
     }
 
     private Tab getNextTabFrom(Tab tab, boolean getPrivate) {
         int numTabs = mOrder.size();
         int index = getIndexOf(tab);
         for (int i = index + 1; i < numTabs; i++) {