Bug 931891 - [Australis] Backed out bug 887515 and the followups (bug 896291, 909662, 896896). r=ttaubert

This commit is contained in:
Jared Wein 2013-12-13 14:27:56 -05:00
parent ee52a77207
commit d6c33a8631
16 changed files with 27 additions and 323 deletions

View File

@ -6101,33 +6101,16 @@ function undoCloseTab(aIndex) {
if (gBrowser.tabs.length == 1 && isTabEmpty(gBrowser.selectedTab))
blankTabToRemove = gBrowser.selectedTab;
let numberOfTabsToUndoClose = 0;
let index = Number(aIndex);
if (isNaN(index)) {
index = 0;
numberOfTabsToUndoClose = SessionStore.getNumberOfTabsClosedLast(window);
} else {
if (0 > index || index >= SessionStore.getClosedTabCount(window))
return null;
numberOfTabsToUndoClose = 1;
}
let tab = null;
while (numberOfTabsToUndoClose > 0 &&
numberOfTabsToUndoClose--) {
var tab = null;
if (SessionStore.getClosedTabCount(window) > (aIndex || 0)) {
TabView.prepareUndoCloseTab(blankTabToRemove);
tab = SessionStore.undoCloseTab(window, index);
tab = SessionStore.undoCloseTab(window, aIndex || 0);
TabView.afterUndoCloseTab();
if (blankTabToRemove) {
if (blankTabToRemove)
gBrowser.removeTab(blankTabToRemove);
blankTabToRemove = null;
}
}
// Reset the number of tabs closed last time to the default.
SessionStore.setNumberOfTabsClosedLast(window, 1);
return tab;
}
@ -6950,13 +6933,8 @@ var TabContextMenu = {
menuItem.disabled = disabled;
// Session store
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
let closedTabCount = SessionStore.getNumberOfTabsClosedLast(window);
undoCloseTabElement.disabled = closedTabCount == 0;
// Change the label of "Undo Close Tab" to specify if it will undo a batch-close
// or a single close.
let visibleLabel = closedTabCount <= 1 ? "singletablabel" : "multipletablabel";
undoCloseTabElement.setAttribute("label", undoCloseTabElement.getAttribute(visibleLabel));
document.getElementById("context_undoCloseTab").disabled =
SessionStore.getClosedTabCount(window) == 0;
// Only one of pin/unpin should be visible
document.getElementById("context_pinTab").hidden = this.contextTab.pinned;

View File

@ -115,8 +115,7 @@
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
<menuseparator/>
<menuitem id="context_undoCloseTab"
singletablabel="&undoCloseTab.label;"
multipletablabel="&undoCloseTabs.label;"
label="&undoCloseTab.label;"
accesskey="&undoCloseTab.accesskey;"
observes="History:UndoCloseTab"/>
<menuitem id="context_closeTab" label="&closeTab.label;" accesskey="&closeTab.accesskey;"

View File

@ -1679,26 +1679,13 @@
throw new Error("Invalid argument: " + aCloseTabs);
}
let maxUndo =
Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
let warnOnCloseOtherTabs =
Services.prefs.getBoolPref("browser.tabs.warnOnCloseOtherTabs");
let warnOnCloseWindow =
Services.prefs.getBoolPref("browser.tabs.warnOnClose");
let isWindowClosing = aCloseTabs == this.closingTabsEnum.ALL;
if (tabsToClose <= 1)
return true;
let skipWarning =
// 1) If there is only one tab to close, we'll never warn the user.
tabsToClose <= 1 ||
// 2) If the whole window is going to be closed, don't warn the
// user if the user has browser.tabs.warnOnClose set to false.
(isWindowClosing && !warnOnCloseWindow) ||
// 3) If the number of tabs are less than the undo threshold
// or if the user has specifically opted-in to ignoring
// this warning via the warnOnCloseOtherTabs pref.
(!isWindowClosing && (!warnOnCloseOtherTabs ||
tabsToClose <= maxUndo));
if (skipWarning)
const pref = aCloseTabs == this.closingTabsEnum.ALL ?
"browser.tabs.warnOnClose" : "browser.tabs.warnOnCloseOtherTabs";
var shouldPrompt = Services.prefs.getBoolPref(pref);
if (!shouldPrompt)
return true;
var ps = Services.prompt;
@ -1722,16 +1709,14 @@
+ (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1),
bundle.getString("tabs.closeButtonMultiple"),
null, null,
bundle.getString("tabs.closeWarningPromptMe"),
aCloseTabs == this.closingTabsEnum.ALL ?
bundle.getString("tabs.closeWarningPromptMe") : null,
warnOnClose);
var reallyClose = (buttonPressed == 0);
// don't set the pref unless they press OK and it's false
if (reallyClose && !warnOnClose.value) {
let pref = isWindowClosing ? "browser.tabs.warnOnClose" :
"browser.tabs.warnOnCloseOtherTabs";
if (aCloseTabs == this.closingTabsEnum.ALL && reallyClose && !warnOnClose.value)
Services.prefs.setBoolPref(pref, false);
}
return reallyClose;
]]>
@ -1758,11 +1743,9 @@
<![CDATA[
if (this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab)) {
let tabs = this.getTabsToTheEndFrom(aTab);
let numberOfTabsToClose = tabs.length;
for (let i = numberOfTabsToClose - 1; i >= 0; --i) {
for (let i = tabs.length - 1; i >= 0; --i) {
this.removeTab(tabs[i], {animate: true});
}
SessionStore.setNumberOfTabsClosedLast(window, numberOfTabsToClose);
}
]]>
</body>
@ -1779,14 +1762,10 @@
let tabs = this.visibleTabs;
this.selectedTab = aTab;
let closedTabs = 0;
for (let i = tabs.length - 1; i >= 0; --i) {
if (tabs[i] != aTab && !tabs[i].pinned) {
if (tabs[i] != aTab && !tabs[i].pinned)
this.removeTab(tabs[i], {animate: true});
closedTabs++;
}
}
SessionStore.setNumberOfTabsClosedLast(window, closedTabs);
}
]]>
</body>
@ -1815,8 +1794,6 @@
var byMouse = aParams.byMouse;
}
SessionStore.setNumberOfTabsClosedLast(window, 1);
// Handle requests for synchronously removing an already
// asynchronously closing tab.
if (!animate &&

View File

@ -229,8 +229,6 @@ run-if = toolkit == "cocoa"
[browser_bug839103.js]
[browser_bug880101.js]
[browser_bug882977.js]
[browser_bug887515.js]
[browser_bug896291_closeMaxSessionStoreTabs.js]
[browser_bug902156.js]
[browser_bug906190.js]
[browser_canonizeURL.js]

View File

@ -1,75 +0,0 @@
function numClosedTabs()
SessionStore.getNumberOfTabsClosedLast(window);
var originalTab;
var tab1Loaded = false;
var tab2Loaded = false;
function verifyUndoMultipleClose() {
if (!tab1Loaded || !tab2Loaded)
return;
gBrowser.removeAllTabsBut(originalTab);
updateTabContextMenu();
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
ok(!undoCloseTabElement.disabled, "Undo Close Tabs should be enabled.");
is(numClosedTabs(), 2, "There should be 2 closed tabs.");
is(gBrowser.tabs.length, 1, "There should only be 1 open tab");
updateTabContextMenu();
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("multipletablabel"),
"The label should be showing that the command will restore multiple tabs");
undoCloseTab();
is(gBrowser.tabs.length, 3, "There should be 3 open tabs");
updateTabContextMenu();
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("singletablabel"),
"The label should be showing that the command will restore a single tab");
gBrowser.removeTabsToTheEndFrom(originalTab);
updateTabContextMenu();
ok(!undoCloseTabElement.disabled, "Undo Close Tabs should be enabled.");
is(numClosedTabs(), 2, "There should be 2 closed tabs.");
is(gBrowser.tabs.length, 1, "There should only be 1 open tab");
updateTabContextMenu();
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("multipletablabel"),
"The label should be showing that the command will restore multiple tabs");
finish();
}
function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("browser.tabs.animate", false);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.tabs.animate");
originalTab.linkedBrowser.loadURI("about:blank");
originalTab = null;
});
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
updateTabContextMenu();
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("singletablabel"),
"The label should be showing that the command will restore a single tab");
originalTab = gBrowser.selectedTab;
gBrowser.selectedBrowser.loadURI("http://mochi.test:8888/");
var tab1 = gBrowser.addTab("http://mochi.test:8888/");
var tab2 = gBrowser.addTab("http://mochi.test:8888/");
var browser1 = gBrowser.getBrowserForTab(tab1);
browser1.addEventListener("load", function onLoad1() {
browser1.removeEventListener("load", onLoad1, true);
tab1Loaded = true;
tab1 = null;
verifyUndoMultipleClose();
}, true);
var browser2 = gBrowser.getBrowserForTab(tab2);
browser2.addEventListener("load", function onLoad2() {
browser2.removeEventListener("load", onLoad2, true);
tab2Loaded = true;
tab2 = null;
verifyUndoMultipleClose();
}, true);
}

View File

@ -1,108 +0,0 @@
function numClosedTabs()
Cc["@mozilla.org/browser/sessionstore;1"].
getService(Ci.nsISessionStore).
getNumberOfTabsClosedLast(window);
let originalTab;
let maxTabsUndo;
let maxTabsUndoPlusOne;
let acceptRemoveAllTabsDialogListener;
let cancelRemoveAllTabsDialogListener;
function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("browser.tabs.animate", false);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.tabs.animate");
originalTab.linkedBrowser.loadURI("about:blank");
originalTab = null;
});
// Creating and throwing away this tab guarantees that the
// number of tabs closed in the previous tab-close operation is 1.
let throwaway_tab = gBrowser.addTab("http://mochi.test:8888/");
gBrowser.removeTab(throwaway_tab);
let undoCloseTabElement = document.getElementById("context_undoCloseTab");
updateTabContextMenu();
is(undoCloseTabElement.label, undoCloseTabElement.getAttribute("singletablabel"),
"The label should be showing that the command will restore a single tab");
originalTab = gBrowser.selectedTab;
gBrowser.selectedBrowser.loadURI("http://mochi.test:8888/");
maxTabsUndo = Services.prefs.getIntPref("browser.sessionstore.max_tabs_undo");
maxTabsUndoPlusOne = maxTabsUndo + 1;
let numberOfTabsLoaded = 0;
for (let i = 0; i < maxTabsUndoPlusOne; i++) {
let tab = gBrowser.addTab("http://mochi.test:8888/");
let browser = gBrowser.getBrowserForTab(tab);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
if (++numberOfTabsLoaded == maxTabsUndoPlusOne)
verifyUndoMultipleClose();
}, true);
}
}
function verifyUndoMultipleClose() {
info("all tabs opened and loaded");
cancelRemoveAllTabsDialogListener = new WindowListener("chrome://global/content/commonDialog.xul", cancelRemoveAllTabsDialog);
Services.wm.addListener(cancelRemoveAllTabsDialogListener);
gBrowser.removeAllTabsBut(originalTab);
}
function cancelRemoveAllTabsDialog(domWindow) {
ok(true, "dialog appeared in response to multiple tab close action");
domWindow.document.documentElement.cancelDialog();
Services.wm.removeListener(cancelRemoveAllTabsDialogListener);
acceptRemoveAllTabsDialogListener = new WindowListener("chrome://global/content/commonDialog.xul", acceptRemoveAllTabsDialog);
Services.wm.addListener(acceptRemoveAllTabsDialogListener);
waitForCondition(function () gBrowser.tabs.length == 1 + maxTabsUndoPlusOne, function verifyCancel() {
is(gBrowser.tabs.length, 1 + maxTabsUndoPlusOne, /* The '1 +' is for the original tab */
"All tabs should still be open after the 'Cancel' option on the prompt is chosen");
gBrowser.removeAllTabsBut(originalTab);
}, "Waited too long to find that no tabs were closed.");
}
function acceptRemoveAllTabsDialog(domWindow) {
ok(true, "dialog appeared in response to multiple tab close action");
domWindow.document.documentElement.acceptDialog();
Services.wm.removeListener(acceptRemoveAllTabsDialogListener);
waitForCondition(function () gBrowser.tabs.length == 1, function verifyAccept() {
is(gBrowser.tabs.length, 1,
"All other tabs should be closed after the 'OK' option on the prompt is chosen");
finish();
}, "Waited too long for the other tabs to be closed.");
}
function WindowListener(aURL, aCallback) {
this.callback = aCallback;
this.url = aURL;
}
WindowListener.prototype = {
onOpenWindow: function(aXULWindow) {
var domWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var self = this;
domWindow.addEventListener("load", function() {
domWindow.removeEventListener("load", arguments.callee, false);
info("domWindow.document.location.href: " + domWindow.document.location.href);
if (domWindow.document.location.href != self.url)
return;
// Allow other window load listeners to execute before passing to callback
executeSoon(function() {
self.callback(domWindow);
});
}, false);
},
onCloseWindow: function(aXULWindow) {},
onWindowTitleChange: function(aXULWindow, aNewTitle) {}
}

View File

@ -25,7 +25,7 @@ interface nsIDOMNode;
* |gBrowser.tabContainer| such as e.g. |gBrowser.selectedTab|.
*/
[scriptable, uuid(63a4d9f4-373f-11e3-a237-fa91a24410d2)]
[scriptable, uuid(0c99811f-6c5f-4a78-9c31-2d266d714175)]
interface nsISessionStore : nsISupports
{
/**
@ -100,20 +100,6 @@ interface nsISessionStore : nsISupports
nsIDOMNode duplicateTab(in nsIDOMWindow aWindow, in nsIDOMNode aTab,
[optional] in long aDelta);
/**
* Set the number of tabs that was closed during the last close-tabs
* operation. This helps us keep track of batch-close operations so
* we can restore multiple tabs at once.
*/
void setNumberOfTabsClosedLast(in nsIDOMWindow aWindow, in unsigned long aNumber);
/**
* Get the number of tabs that was closed during the last close-tabs
* operation. This helps us keep track of batch-close operations so
* we can restore multiple tabs at once.
*/
unsigned long getNumberOfTabsClosedLast(in nsIDOMWindow aWindow);
/**
* Get the number of restore-able tabs for a browser window
*/

View File

@ -66,7 +66,7 @@ this.RecentlyClosedTabsAndWindowsMenuUtils = {
let restoreAllTabs = fragment.appendChild(doc.createElementNS(kNSXUL, aTagName));
restoreAllTabs.setAttribute("label", navigatorBundle.GetStringFromName("menuRestoreAllTabs.label"));
restoreAllTabs.setAttribute("oncommand",
"for (var i = 0; i < " + closedTabs.length + "; i++) undoCloseTab(0);");
"for (var i = 0; i < " + closedTabs.length + "; i++) undoCloseTab();");
}
return fragment;
},

View File

@ -193,14 +193,6 @@ this.SessionStore = {
return SessionStoreInternal.duplicateTab(aWindow, aTab, aDelta);
},
getNumberOfTabsClosedLast: function ss_getNumberOfTabsClosedLast(aWindow) {
return SessionStoreInternal.getNumberOfTabsClosedLast(aWindow);
},
setNumberOfTabsClosedLast: function ss_setNumberOfTabsClosedLast(aWindow, aNumber) {
return SessionStoreInternal.setNumberOfTabsClosedLast(aWindow, aNumber);
},
getClosedTabCount: function ss_getClosedTabCount(aWindow) {
return SessionStoreInternal.getClosedTabCount(aWindow);
},
@ -1616,35 +1608,6 @@ let SessionStoreInternal = {
return newTab;
},
setNumberOfTabsClosedLast: function ssi_setNumberOfTabsClosedLast(aWindow, aNumber) {
if (this._disabledForMultiProcess) {
return;
}
if (!("__SSi" in aWindow)) {
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
}
return NumberOfTabsClosedLastPerWindow.set(aWindow, aNumber);
},
/* Used to undo batch tab-close operations. Defaults to 1. */
getNumberOfTabsClosedLast: function ssi_getNumberOfTabsClosedLast(aWindow) {
if (this._disabledForMultiProcess) {
return 0;
}
if (!("__SSi" in aWindow)) {
throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
}
// Blank tabs cannot be undo-closed, so the number returned by
// the NumberOfTabsClosedLastPerWindow can be greater than the
// return value of getClosedTabCount. We won't restore blank
// tabs, so we return the minimum of these two values.
return Math.min(NumberOfTabsClosedLastPerWindow.get(aWindow) || 1,
this.getClosedTabCount(aWindow));
},
getClosedTabCount: function ssi_getClosedTabCount(aWindow) {
if ("__SSi" in aWindow) {
return this._windows[aWindow.__SSi]._closedTabs.length;
@ -4029,11 +3992,6 @@ let DirtyWindows = {
}
};
// A map storing the number of tabs last closed per windoow. This only
// stores the most recent tab-close operation, and is used to undo
// batch tab-closing operations.
let NumberOfTabsClosedLastPerWindow = new WeakMap();
// This is used to help meter the number of restoring tabs. This is the control
// point for telling the next tab to restore. It gets attached to each gBrowser
// via gBrowser.addTabsProgressListener

View File

@ -40,8 +40,4 @@ function test() {
"Invalid window for getWindowValue throws");
ok(test(function() ss.setWindowValue({}, "", "")),
"Invalid window for setWindowValue throws");
ok(test(function() ss.getNumberOfTabsClosedLast({})),
"Invalid window for getNumberOfTabsClosedLast throws");
ok(test(function() ss.setNumberOfTabsClosedLast({}, 1)),
"Invalid window for setNumberOfTabsClosedLast throws");
}

View File

@ -38,5 +38,5 @@ function onTabViewWindowLoaded() {
gBrowser.removeTab(tabTwo);
finish();
});
}, 0);
});
}

View File

@ -64,7 +64,7 @@ function test() {
createBlankTab();
afterAllTabsLoaded(testUndoCloseWithSelectedBlankPinnedTab);
}, 0);
});
});
}
@ -94,7 +94,7 @@ function test() {
gBrowser.removeTab(gBrowser.tabs[0]);
afterAllTabsLoaded(finishTest);
}, 0);
});
});
}

View File

@ -81,7 +81,7 @@ function test() {
gBrowser.removeTab(gBrowser.tabs[1]);
gBrowser.removeTab(gBrowser.tabs[1]);
hideTabView(finishTest);
}, 0);
});
}
waitForExplicitFinish();

View File

@ -20,7 +20,7 @@ function test() {
whenTabViewIsHidden(function() {
win.gBrowser.removeTab(win.gBrowser.selectedTab);
executeSoon(function() {
win.undoCloseTab(0);
win.undoCloseTab();
groupItemTwo.addSubscriber("childAdded", function onChildAdded(data) {
groupItemTwo.removeSubscriber("childAdded", onChildAdded);

View File

@ -362,7 +362,7 @@ function newWindowWithState(state, callback) {
function restoreTab(callback, index, win) {
win = win || window;
let tab = win.undoCloseTab(index);
let tab = win.undoCloseTab(index || 0);
let tabItem = tab._tabViewTabItem;
let finalize = function () {

View File

@ -49,11 +49,6 @@ can reach it easily. -->
<!ENTITY bookmarkAllTabs.accesskey "T">
<!ENTITY undoCloseTab.label "Undo Close Tab">
<!ENTITY undoCloseTab.accesskey "U">
<!-- LOCALIZATION NOTE (undoCloseTabs.label) : This label is used
when the previous tab-closing operation closed more than one tab. It
replaces the undoCloseTab.label and will use the same accesskey as the
undoCloseTab.label so users will not need to learn new keyboard controls. -->
<!ENTITY undoCloseTabs.label "Undo Close Tabs">
<!ENTITY closeTab.label "Close Tab">
<!ENTITY closeTab.accesskey "c">