Bug 624847 - 'Undo Close Tab' closes current group when only one blank tab is left [r=ian, a=sdwilsh]
authorTim Taubert <tim.taubert@gmx.de>
Thu, 03 Feb 2011 02:43:32 +0100
changeset 61861 3c87074d5f50d069edf461fe21d86a5b558cfd98
parent 61860 be4f8b47377e4c75398fdf56507469a9c163f967
child 61862 f00b81064d570e372b70ac673ca4b00c40556f2e
push idunknown
push userunknown
push dateunknown
reviewersian, sdwilsh
bugs624847
milestone2.0b12pre
Bug 624847 - 'Undo Close Tab' closes current group when only one blank tab is left [r=ian, a=sdwilsh]
browser/base/content/browser-tabview.js
browser/base/content/browser.js
browser/base/content/tabview/groupitems.js
browser/base/content/tabview/ui.js
browser/base/content/test/tabview/Makefile.in
browser/base/content/test/tabview/browser_tabview_bug624847.js
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -15,16 +15,17 @@
 #
 # The Initial Developer of the Original Code is Mozilla Foundation.
 # Portions created by the Initial Developer are Copyright (C) 2010
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Raymond Lee <raymond@appcoast.com>
 #   Ian Gilman <ian@iangilman.com>
+#   Tim Taubert <tim.taubert@gmx.de>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -241,22 +242,26 @@ let TabView = {
           // Switch to the new tab, and close the old group if it's now empty.
           let oldGroupItem = groupItems.getActiveGroupItem();
           window.gBrowser.selectedTab = tabItem.tab;
           oldGroupItem.closeIfEmpty();
         });
       }
     }, true);
   },
-  
+
   // ----------
   // Prepares the tab view for undo close tab.
-  prepareUndoCloseTab: function() {
-    if (this._window)
+  prepareUndoCloseTab: function(blankTabToRemove) {
+    if (this._window) {
       this._window.UI.restoredClosedTab = true;
+
+      if (blankTabToRemove)
+        blankTabToRemove._tabViewTabIsRemovedAfterRestore = true;
+    }
   },
 
   // ----------
   // Cleans up the tab view after undo close tab.
   afterUndoCloseTab: function () {
     if (this._window)
       this._window.UI.restoredClosedTab = false;
   }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7178,17 +7178,17 @@ function undoCloseTab(aIndex) {
       !gPrefService.getBoolPref("browser.tabs.autoHide") &&
       isTabEmpty(gBrowser.selectedTab))
     blankTabToRemove = gBrowser.selectedTab;
 
   var tab = null;
   var ss = Cc["@mozilla.org/browser/sessionstore;1"].
            getService(Ci.nsISessionStore);
   if (ss.getClosedTabCount(window) > (aIndex || 0)) {
-    TabView.prepareUndoCloseTab();
+    TabView.prepareUndoCloseTab(blankTabToRemove);
     tab = ss.undoCloseTab(window, aIndex || 0);
     TabView.afterUndoCloseTab();
 
     if (blankTabToRemove)
       gBrowser.removeTab(blankTabToRemove);
   }
 
   return tab;
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -981,16 +981,21 @@ GroupItem.prototype = Utils.extend(new I
       item.setRotation(0);
 
       item.droppable(true);
       item.removeSubscriber(this, "close");
 
       if (typeof item.setResizable == 'function')
         item.setResizable(true, options.immediately);
 
+      // if a blank tab is selected while restoring a tab the blank tab gets
+      // removed. we need to keep the group alive for the restored tab.
+      if (item.tab._tabViewTabIsRemovedAfterRestore)
+        options.dontClose = true;
+
       let closed = options.dontClose ? false : this.closeIfEmpty();
       if (closed)
         this._makeClosestTabActive();
       else if (!options.dontArrage)
         this.arrange({animate: !options.immediately});
 
       this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
     } catch(e) {
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -726,24 +726,31 @@ let UI = {
 
           var groupItem = GroupItems.getActiveGroupItem();
 
           // 1) Only go back to the TabView tab when there you close the last
           // tab of a groupItem.
           let closingLastOfGroup = (groupItem && 
               groupItem._children.length == 1 && 
               groupItem._children[0].tab == tab);
-          
+
           // 2) Take care of the case where you've closed the last tab in
           // an un-named groupItem, which means that the groupItem is gone (null) and
           // there are no visible tabs. 
           let closingUnnamedGroup = (groupItem == null &&
               gBrowser.visibleTabs.length <= 1); 
-              
-          if (closingLastOfGroup || closingUnnamedGroup) {
+
+          // 3) When a blank tab is active while restoring a closed tab the
+          // blank tab gets removed. The active group is not closed as this is
+          // where the restored tab goes. So do not show the TabView.
+          let closingBlankTabAfterRestore =
+            (tab && tab._tabViewTabIsRemovedAfterRestore);
+
+          if ((closingLastOfGroup || closingUnnamedGroup) &&
+              !closingBlankTabAfterRestore) {
             // for the tab focus event to pick up.
             self._closedLastVisibleTab = true;
             self.showTabView();
           }
         }
       }
     };
 
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -89,16 +89,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug618816.js \
                  browser_tabview_bug618828.js \
                  browser_tabview_bug619937.js \
                  browser_tabview_bug622835.js \
                  browser_tabview_bug622872.js \
                  browser_tabview_bug624265.js \
                  browser_tabview_bug624931.js \
                  browser_tabview_bug624727.js \
+                 browser_tabview_bug624847.js \
                  browser_tabview_bug624953.js \
                  browser_tabview_bug625269.js \
                  browser_tabview_bug625424.js \
                  browser_tabview_bug626368.js \
                  browser_tabview_bug627288.js \
                  browser_tabview_bug627736.js \
                  browser_tabview_bug628165.js \
                  browser_tabview_bug628270.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug624847.js
@@ -0,0 +1,127 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  let cw;
+  let groupItemId;
+  let prefix = 'start';
+
+  let assertTabViewIsHidden = function () {
+    ok(!TabView.isVisible(), prefix + ': tabview is hidden');
+  }
+
+  let assertNumberOfGroups = function (num) {
+    is(cw.GroupItems.groupItems.length, num, prefix + ': there should be ' + num + ' groups');
+  }
+
+  let assertNumberOfTabs = function (num) {
+    is(gBrowser.visibleTabs.length, num, prefix + ': there should be ' + num + ' tabs');
+  }
+
+  let assertNumberOfPinnedTabs = function (num) {
+    is(gBrowser._numPinnedTabs, num, prefix + ': there should be ' + num + ' pinned tabs');
+  }
+
+  let assertGroupItemPreserved = function () {
+    is(cw.GroupItems.groupItems[0].id, groupItemId, prefix + ': groupItem was preserved');
+  }
+
+  let assertValidPrerequisites = function () {
+    assertNumberOfTabs(1);
+    assertNumberOfGroups(1);
+    assertNumberOfPinnedTabs(0);
+    assertTabViewIsHidden();
+  }
+
+  let createTab = function (url) {
+    return gBrowser.loadOneTab(url || 'http://mochi.test:8888/', {inBackground: true});
+  }
+
+  let createBlankTab = function () {
+    return createTab('about:blank');
+  }
+
+  let restoreTab = function (callback) {
+    let tab = undoCloseTab(0);
+
+    if (tab._tabViewTabItem._reconnected) {
+      afterAllTabsLoaded(callback);
+      return;
+    }
+
+    tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
+      tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
+      afterAllTabsLoaded(callback);
+    });
+  }
+
+  let finishTest = function () {
+    prefix = 'finish';
+    assertValidPrerequisites();
+    finish();
+  }
+
+  let testUndoCloseWithSelectedBlankTab = function () {
+    prefix = 'unpinned';
+    let tab = createTab();
+    assertNumberOfTabs(2);
+
+    afterAllTabsLoaded(function () {
+      gBrowser.removeTab(tab);
+      assertNumberOfTabs(1);
+      assertNumberOfPinnedTabs(0);
+
+      restoreTab(function () {
+        prefix = 'unpinned-restored';
+        assertValidPrerequisites();
+        assertGroupItemPreserved();
+
+        createBlankTab();
+        afterAllTabsLoaded(testUndoCloseWithSelectedBlankPinnedTab);
+      });
+    });
+  }
+
+  let testUndoCloseWithSelectedBlankPinnedTab = function () {
+    prefix = 'pinned';
+    assertNumberOfTabs(2);
+
+    afterAllTabsLoaded(function () {
+      gBrowser.removeTab(gBrowser.tabs[0]);
+      gBrowser.pinTab(gBrowser.tabs[0]);
+
+      registerCleanupFunction(function () {
+        let tab = gBrowser.tabs[0];
+        if (tab.pinned)
+          gBrowser.unpinTab(tab);
+      });
+
+      assertNumberOfTabs(1);
+      assertNumberOfPinnedTabs(1);
+
+      restoreTab(function () {
+        prefix = 'pinned-restored';
+        assertValidPrerequisites();
+        assertGroupItemPreserved();
+
+        createBlankTab();
+        gBrowser.removeTab(gBrowser.tabs[0]);
+
+        afterAllTabsLoaded(finishTest);
+      });
+    });
+  }
+
+  waitForExplicitFinish();
+  registerCleanupFunction(function () TabView.hide());
+
+  showTabView(function () {
+    hideTabView(function () {
+      cw = TabView.getContentWindow();
+      groupItemId = cw.GroupItems.groupItems[0].id;
+
+      assertValidPrerequisites();
+      testUndoCloseWithSelectedBlankTab();
+    });
+  });
+}