mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1833522 - Add closed tabs from closed windows to the history:recently-closed tab menus. r=dao,extension-reviewers,sessionstore-reviewers,sclements,robwu,Standard8,fxview-reviewers
* Change the signature for SessionStore.getClosedTabCount to accept either a window or options object * Extend tests for the recently-closed-tabs menu(s) * Add a test manifest to run the session/recently-closed tabs related extension tests with the legacy (false) values for the all-windows and closed tabs from closed windows prefs Differential Revision: https://phabricator.services.mozilla.com/D186400
This commit is contained in:
parent
7878082e5c
commit
0db730dada
@ -593,15 +593,6 @@ class HistoryMenu extends PlacesMenu {
|
||||
}
|
||||
}
|
||||
|
||||
_getClosedTabCount() {
|
||||
try {
|
||||
return SessionStore.getClosedTabCount();
|
||||
} catch (ex) {
|
||||
// SessionStore doesn't track the hidden window, so just return zero then.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
toggleHiddenTabs() {
|
||||
const isShown =
|
||||
window.gBrowser && gBrowser.visibleTabs.length < gBrowser.tabs.length;
|
||||
@ -611,7 +602,7 @@ class HistoryMenu extends PlacesMenu {
|
||||
toggleRecentlyClosedTabs() {
|
||||
// enable/disable the Recently Closed Tabs sub menu
|
||||
// no restorable tabs, so disable menu
|
||||
if (this._getClosedTabCount() == 0) {
|
||||
if (SessionStore.getClosedTabCount() == 0) {
|
||||
this.undoTabMenu.setAttribute("disabled", true);
|
||||
} else {
|
||||
this.undoTabMenu.removeAttribute("disabled");
|
||||
@ -630,7 +621,7 @@ class HistoryMenu extends PlacesMenu {
|
||||
}
|
||||
|
||||
// no restorable tabs, so make sure menu is disabled, and return
|
||||
if (this._getClosedTabCount() == 0) {
|
||||
if (SessionStore.getClosedTabCount() == 0) {
|
||||
this.undoTabMenu.setAttribute("disabled", true);
|
||||
return;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
prefs =
|
||||
browser.sessionstore.closedTabsFromAllWindows=true
|
||||
browser.sessionstore.closedTabsFromClosedWindows=true
|
||||
|
||||
[browser_file_close_tabs.js]
|
||||
[browser_file_menu_import_wizard.js]
|
||||
|
@ -338,3 +338,60 @@ add_task(async function test_recently_closed_tabs_mixed_private_pref_off() {
|
||||
info("finished tab cleanup");
|
||||
SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function test_recently_closed_tabs_closed_windows() {
|
||||
// prepare window state with closed tabs from closed windows
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["sessionstore.closedTabsFromClosedWindows", true]],
|
||||
});
|
||||
const closedTabUrls = ["about:robots"];
|
||||
const closedWindowState = {
|
||||
tabs: [
|
||||
{
|
||||
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
|
||||
},
|
||||
],
|
||||
_closedTabs: closedTabUrls.map(url => {
|
||||
return {
|
||||
state: {
|
||||
entries: [
|
||||
{
|
||||
url,
|
||||
triggeringPrincipal_base64,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
await SessionStoreTestUtils.promiseBrowserState({
|
||||
windows: [
|
||||
{
|
||||
tabs: [
|
||||
{
|
||||
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
_closedWindows: [closedWindowState],
|
||||
});
|
||||
|
||||
// verify the recently-closed-tabs menu item is enabled
|
||||
await checkMenu(window, {
|
||||
menuItemDisabled: false,
|
||||
});
|
||||
|
||||
// flip the pref
|
||||
await SpecialPowers.popPrefEnv();
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.sessionstore.closedTabsFromClosedWindows", false]],
|
||||
});
|
||||
|
||||
// verify the recently-closed-tabs menu item is disabled
|
||||
await checkMenu(window, {
|
||||
menuItemDisabled: true,
|
||||
});
|
||||
|
||||
SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
@ -9,6 +9,7 @@ support-files =
|
||||
file_about_srcdoc.html
|
||||
prefs =
|
||||
browser.sessionstore.closedTabsFromAllWindows=true
|
||||
browser.sessionstore.closedTabsFromClosedWindows=true
|
||||
|
||||
[browser_addAdjacentNewTab.js]
|
||||
[browser_addTab_index.js]
|
||||
|
@ -4,6 +4,7 @@ support-files =
|
||||
support/test_967000_charEncoding_page.html
|
||||
prefs =
|
||||
browser.sessionstore.closedTabsFromAllWindows=true
|
||||
browser.sessionstore.closedTabsFromClosedWindows=true
|
||||
|
||||
[browser_1003588_no_specials_in_panel.js]
|
||||
[browser_1008559_anchor_undo_restore.js]
|
||||
|
@ -33,6 +33,10 @@ async function openRecentlyClosedTabsMenu() {
|
||||
await openHistoryPanel();
|
||||
|
||||
let recentlyClosedTabs = document.getElementById("appMenuRecentlyClosedTabs");
|
||||
Assert.ok(
|
||||
!recentlyClosedTabs.getAttribute("disabled"),
|
||||
"Recently closed tabs button enabled"
|
||||
);
|
||||
let closeTabsPanel = document.getElementById(
|
||||
"appMenu-library-recentlyClosedTabs"
|
||||
);
|
||||
@ -52,23 +56,21 @@ async function openRecentlyClosedTabsMenu() {
|
||||
return closeTabsPanel;
|
||||
}
|
||||
|
||||
async function resetClosedTabs(win) {
|
||||
// Clear the lists of closed tabs.
|
||||
let sessionStoreChanged;
|
||||
let windows = win ? [win] : BrowserWindowTracker.orderedWindows;
|
||||
for (win of windows) {
|
||||
while (SessionStore.getClosedTabCountForWindow(win)) {
|
||||
sessionStoreChanged = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
SessionStore.forgetClosedTab(win, 0);
|
||||
await sessionStoreChanged;
|
||||
}
|
||||
function resetClosedTabsAndWindows() {
|
||||
// Clear the lists of closed windows and tabs.
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
is(SessionStore.getClosedWindowCount(), 0, "Expect 0 closed windows");
|
||||
for (const win of BrowserWindowTracker.orderedWindows) {
|
||||
is(
|
||||
SessionStore.getClosedTabCountForWindow(win),
|
||||
0,
|
||||
"Expect 0 closed tabs for this window"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
registerCleanupFunction(async () => {
|
||||
await resetClosedTabs();
|
||||
await resetClosedTabsAndWindows();
|
||||
});
|
||||
|
||||
add_task(async function testRecentlyClosedDisabled() {
|
||||
@ -203,7 +205,7 @@ add_task(async function testRecentlyClosedTabsDisabledPersists() {
|
||||
add_task(async function testRecentlyClosedRestoreAllTabs() {
|
||||
// We need to make sure the history is cleared before starting the test
|
||||
await Sanitizer.sanitize(["history"]);
|
||||
await resetClosedTabs();
|
||||
await resetClosedTabsAndWindows();
|
||||
const initialTabCount = gBrowser.visibleTabs.length;
|
||||
|
||||
const closedTabUrls = [
|
||||
@ -292,7 +294,7 @@ add_task(async function testRecentlyClosedRestoreAllTabs() {
|
||||
add_task(async function testRecentlyClosedWindows() {
|
||||
// We need to make sure the history is cleared before starting the test
|
||||
await Sanitizer.sanitize(["history"]);
|
||||
await resetClosedTabs();
|
||||
await resetClosedTabsAndWindows();
|
||||
|
||||
// Open and close a new window.
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
@ -339,3 +341,90 @@ add_task(async function testRecentlyClosedWindows() {
|
||||
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
||||
|
||||
add_task(async function testRecentlyClosedTabsFromClosedWindows() {
|
||||
await resetClosedTabsAndWindows();
|
||||
const closedTabUrls = [
|
||||
"about:robots",
|
||||
"https://example.com/",
|
||||
"https://example.org/",
|
||||
];
|
||||
const closedWindowState = {
|
||||
tabs: [
|
||||
{
|
||||
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
|
||||
},
|
||||
],
|
||||
_closedTabs: closedTabUrls.map(url => {
|
||||
return {
|
||||
title: url,
|
||||
state: {
|
||||
entries: [
|
||||
{
|
||||
url,
|
||||
triggeringPrincipal_base64,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
await SessionStoreTestUtils.promiseBrowserState({
|
||||
windows: [
|
||||
{
|
||||
tabs: [
|
||||
{
|
||||
entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
_closedWindows: [closedWindowState],
|
||||
});
|
||||
Assert.equal(
|
||||
SessionStore.getClosedTabCountFromClosedWindows(),
|
||||
closedTabUrls.length,
|
||||
"Sanity check number of closed tabs from closed windows"
|
||||
);
|
||||
|
||||
prepareHistoryPanel();
|
||||
let closeTabsPanel = await openRecentlyClosedTabsMenu();
|
||||
// make sure we can actually restore one of these closed tabs
|
||||
const closedTabItems = closeTabsPanel.querySelectorAll(
|
||||
"toolbarbutton[targetURI]"
|
||||
);
|
||||
Assert.equal(
|
||||
closedTabItems.length,
|
||||
closedTabUrls.length,
|
||||
"We have expected number of closed tab items"
|
||||
);
|
||||
|
||||
const newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
|
||||
const closedObjectsChangePromise = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
EventUtils.sendMouseEvent({ type: "click" }, closedTabItems[0], window);
|
||||
await newTabPromise;
|
||||
await closedObjectsChangePromise;
|
||||
|
||||
// flip the pref so none of the closed tabs from closed window are included
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.sessionstore.closedTabsFromClosedWindows", false]],
|
||||
});
|
||||
await openHistoryPanel();
|
||||
|
||||
// verify the recently-closed-tabs menu item is disabled
|
||||
let recentlyClosedTabsItem = document.getElementById(
|
||||
"appMenuRecentlyClosedTabs"
|
||||
);
|
||||
Assert.ok(
|
||||
recentlyClosedTabsItem.hasAttribute("disabled"),
|
||||
"Recently closed tabs button is now disabled"
|
||||
);
|
||||
SpecialPowers.popPrefEnv();
|
||||
while (gBrowser.tabs.length > 1) {
|
||||
await SessionStoreTestUtils.closeTab(
|
||||
gBrowser.tabs[gBrowser.tabs.length - 1]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -28,6 +28,7 @@ DIRS += ["schemas"]
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
"test/browser/browser-private.ini",
|
||||
"test/browser/browser.ini",
|
||||
"test/browser/browser_legacy_recent_tabs.ini",
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += ["test/mochitest/mochitest.ini"]
|
||||
|
@ -2,6 +2,7 @@
|
||||
tags = webextensions
|
||||
prefs =
|
||||
browser.sessionstore.closedTabsFromAllWindows=true
|
||||
browser.sessionstore.closedTabsFromClosedWindows=true
|
||||
# We don't want to reset this at the end of the test, so that we don't have
|
||||
# to spawn a new extension child process for each test unit.
|
||||
dom.ipc.keepProcessesAlive.extension=1
|
||||
|
@ -0,0 +1,23 @@
|
||||
[DEFAULT]
|
||||
#
|
||||
# This manifest lists tests that use cover the session API and recently-closed tabs behavior with the legacy pref values
|
||||
#
|
||||
tags = webextensions
|
||||
dupe-manifest =
|
||||
prefs =
|
||||
browser.sessionstore.closedTabsFromAllWindows=false
|
||||
browser.sessionstore.closedTabsFromClosedWindows=false
|
||||
support-files =
|
||||
head.js
|
||||
empty.xpi
|
||||
|
||||
[browser_ext_sessions_forgetClosedTab.js]
|
||||
[browser_ext_sessions_forgetClosedWindow.js]
|
||||
[browser_ext_sessions_getRecentlyClosed.js]
|
||||
[browser_ext_sessions_getRecentlyClosed_private.js]
|
||||
[browser_ext_sessions_getRecentlyClosed_tabs.js]
|
||||
[browser_ext_sessions_incognito.js]
|
||||
[browser_ext_sessions_restore.js]
|
||||
[browser_ext_sessions_restoreTab.js]
|
||||
[browser_ext_sessions_restore_private.js]
|
||||
[browser_ext_sessions_window_tab_value.js]
|
@ -467,14 +467,6 @@ class RecentlyClosedTabsContainer extends HTMLDetailsElement {
|
||||
toggleContainerStyleForEmptyMsg(visible) {
|
||||
this.collapsibleContainer.classList.toggle("empty-container", visible);
|
||||
}
|
||||
|
||||
getClosedTabCount = () => {
|
||||
try {
|
||||
return lazy.SessionStore.getClosedTabCountForWindow(getWindow());
|
||||
} catch (ex) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
customElements.define(
|
||||
"recently-closed-tabs-container",
|
||||
|
@ -181,17 +181,17 @@ async function prepareClosedTabs() {
|
||||
"Expected 1 closed tab from a closed window"
|
||||
);
|
||||
|
||||
const closedTabsFromOpenWindowsCount = SessionStore.getClosedTabCount(window);
|
||||
const closedTabsFromOpenWindowsCount = SessionStore.getClosedTabCount({
|
||||
sourceWindow: window,
|
||||
closedTabsFromClosedWindows: false,
|
||||
});
|
||||
const actualClosedTabCount = SessionStore.getClosedTabCount();
|
||||
is(
|
||||
closedTabsFromOpenWindowsCount,
|
||||
3,
|
||||
"Expected 3 closed tabs currently-open windows"
|
||||
);
|
||||
|
||||
// For illustrative purposes.
|
||||
// Currently "recently-closed" tab count is the sum of these 2 return values:
|
||||
let actualClosedTabCount =
|
||||
closedTabsFromOpenWindowsCount + closedTabsFromClosedWindowsCount;
|
||||
is(
|
||||
actualClosedTabCount,
|
||||
preparedClosedTabCount,
|
||||
@ -547,6 +547,7 @@ add_task(async function test_dismiss_tab() {
|
||||
});
|
||||
|
||||
add_task(async function test_empty_states() {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
is(
|
||||
SessionStore.getClosedTabCount(window),
|
||||
0,
|
||||
|
@ -8,6 +8,7 @@ const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
PlacesUIUtils: "resource:///modules/PlacesUIUtils.sys.mjs",
|
||||
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
||||
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
|
||||
});
|
||||
|
||||
@ -18,8 +19,13 @@ ChromeUtils.defineLazyGetter(lazy, "l10n", () => {
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"closedTabsFromAllWindowsEnabled",
|
||||
"browser.sessionstore.closedTabsFromAllWindows",
|
||||
true
|
||||
"browser.sessionstore.closedTabsFromAllWindows"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"closedTabsFromClosedWindowsEnabled",
|
||||
"browser.sessionstore.closedTabsFromClosedWindows"
|
||||
);
|
||||
|
||||
export var RecentlyClosedTabsAndWindowsMenuUtils = {
|
||||
@ -36,13 +42,21 @@ export var RecentlyClosedTabsAndWindowsMenuUtils = {
|
||||
*/
|
||||
getTabsFragment(aWindow, aTagName, aPrefixRestoreAll = false) {
|
||||
let doc = aWindow.document;
|
||||
const isPrivate = lazy.PrivateBrowsingUtils.isWindowPrivate(aWindow);
|
||||
const fragment = doc.createDocumentFragment();
|
||||
const browserWindows = lazy.closedTabsFromAllWindowsEnabled
|
||||
? lazy.SessionStore.getWindows(aWindow)
|
||||
: [aWindow];
|
||||
const tabCount = lazy.SessionStore.getClosedTabCount(aWindow);
|
||||
let isEmpty = true;
|
||||
|
||||
if (
|
||||
lazy.SessionStore.getClosedTabCount({
|
||||
sourceWindow: aWindow,
|
||||
closedTabsFromClosedWindows: false,
|
||||
})
|
||||
) {
|
||||
isEmpty = false;
|
||||
const browserWindows = lazy.closedTabsFromAllWindowsEnabled
|
||||
? lazy.SessionStore.getWindows(aWindow)
|
||||
: [aWindow];
|
||||
|
||||
if (tabCount > 0) {
|
||||
for (const win of browserWindows) {
|
||||
const closedTabs = lazy.SessionStore.getClosedTabDataForWindow(win);
|
||||
for (let i = 0; i < closedTabs.length; i++) {
|
||||
@ -57,7 +71,29 @@ export var RecentlyClosedTabsAndWindowsMenuUtils = {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!isPrivate &&
|
||||
lazy.closedTabsFromClosedWindowsEnabled &&
|
||||
lazy.SessionStore.getClosedTabCountFromClosedWindows()
|
||||
) {
|
||||
isEmpty = false;
|
||||
const closedTabs = lazy.SessionStore.getClosedTabDataFromClosedWindows();
|
||||
for (let i = 0; i < closedTabs.length; i++) {
|
||||
createEntry(
|
||||
aTagName,
|
||||
false,
|
||||
i,
|
||||
closedTabs[i],
|
||||
doc,
|
||||
closedTabs[i].title,
|
||||
fragment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEmpty) {
|
||||
createRestoreAllEntry(
|
||||
doc,
|
||||
fragment,
|
||||
@ -130,6 +166,15 @@ export var RecentlyClosedTabsAndWindowsMenuUtils = {
|
||||
lazy.SessionStore.undoCloseTab(sourceWindow, 0, currentWindow);
|
||||
}
|
||||
}
|
||||
if (lazy.closedTabsFromClosedWindowsEnabled) {
|
||||
for (let tabData of lazy.SessionStore.getClosedTabDataFromClosedWindows()) {
|
||||
lazy.SessionStore.undoClosedTabFromClosedWindow(
|
||||
{ sourceClosedId: tabData.sourceClosedId },
|
||||
tabData.closedId,
|
||||
currentWindow
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -154,11 +199,20 @@ export var RecentlyClosedTabsAndWindowsMenuUtils = {
|
||||
if (aEvent.button != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
aEvent.view.undoCloseTab(
|
||||
aEvent.originalTarget.getAttribute("value"),
|
||||
aEvent.originalTarget.getAttribute("source-window-id")
|
||||
);
|
||||
if (aEvent.originalTarget.hasAttribute("source-closed-id")) {
|
||||
lazy.SessionStore.undoClosedTabFromClosedWindow(
|
||||
{
|
||||
sourceClosedId:
|
||||
aEvent.originalTarget.getAttribute("source-closed-id"),
|
||||
},
|
||||
aEvent.originalTarget.getAttribute("value")
|
||||
);
|
||||
} else {
|
||||
aEvent.view.undoCloseTab(
|
||||
aEvent.originalTarget.getAttribute("value"),
|
||||
aEvent.originalTarget.getAttribute("source-window-id")
|
||||
);
|
||||
}
|
||||
aEvent.view.gBrowser.moveTabToEnd();
|
||||
let ancestorPanel = aEvent.target.closest("panel");
|
||||
if (ancestorPanel) {
|
||||
@ -203,6 +257,22 @@ function createEntry(
|
||||
|
||||
if (aIsWindowsFragment) {
|
||||
element.setAttribute("oncommand", `undoCloseWindow("${aIndex}");`);
|
||||
} else if (typeof aClosedTab.sourceClosedId == "number") {
|
||||
// sourceClosedId is used to look up the closed window to remove it when the tab is restored
|
||||
let sourceClosedId = aClosedTab.sourceClosedId;
|
||||
element.setAttribute("source-closed-id", sourceClosedId);
|
||||
element.setAttribute("value", aClosedTab.closedId);
|
||||
element.removeAttribute("oncommand");
|
||||
element.addEventListener(
|
||||
"command",
|
||||
event => {
|
||||
lazy.SessionStore.undoClosedTabFromClosedWindow(
|
||||
{ sourceClosedId },
|
||||
aClosedTab.closedId
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
} else {
|
||||
// sourceWindowId is used to look up the closed tab entry to remove it when it is restored
|
||||
let sourceWindowId = aClosedTab.sourceWindowId;
|
||||
|
@ -407,15 +407,21 @@ export var SessionStore = {
|
||||
|
||||
/**
|
||||
* Get the number of closed tabs associated with all matching windows
|
||||
* @param {Window} [aWindow] Optional window argument used to determine if we're counting for private or non-private windows
|
||||
* @param {Window|Object} [aOptions]
|
||||
* Either a DOMWindow (see aOptions.sourceWindow) or an object with properties
|
||||
to identify which closed tabs to include in the count.
|
||||
* @param {Window} aOptions.sourceWindow
|
||||
A browser window used to identity privateness.
|
||||
When closedTabsFromAllWindows is false, we only count closed tabs assocated with this window.
|
||||
* @param {boolean} [aOptions.private = false]
|
||||
Explicit indicator to constrain tab count to only private or non-private windows,
|
||||
* @param {boolean} [aOptions.closedTabsFromAllWindows]
|
||||
Override the value of the closedTabsFromAllWindows preference.
|
||||
* @param {boolean} [aOptions.closedTabsFromClosedWindows]
|
||||
Override the value of the closedTabsFromClosedWindows preference.
|
||||
*/
|
||||
getClosedTabCount: function ss_getClosedTabCount(aWindow) {
|
||||
if (!SessionStoreInternal._closedTabsFromAllWindowsEnabled) {
|
||||
return this.getClosedTabCountForWindow(
|
||||
aWindow ?? SessionStoreInternal._getTopWindow()
|
||||
);
|
||||
}
|
||||
return SessionStoreInternal.getClosedTabCount(aWindow);
|
||||
getClosedTabCount: function ss_getClosedTabCount(aOptions) {
|
||||
return SessionStoreInternal.getClosedTabCount(aOptions);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -439,18 +445,21 @@ export var SessionStore = {
|
||||
|
||||
/**
|
||||
* Get the closed tab data associated with all matching windows
|
||||
* @param {Window} [aWindow] Optional window argument used to determine if we're collecting data for private or non-private windows, will
|
||||
* default to non-private only due to SessionStoreInternal._getTopWindow(false).
|
||||
* @param {Window|Object} [aOptions]
|
||||
* Either a DOMWindow (see aOptions.sourceWindow) or an object with properties
|
||||
to identify which closed tabs to get data from
|
||||
* @param {Window} aOptions.sourceWindow
|
||||
A browser window used to identity privateness.
|
||||
When closedTabsFromAllWindows is false, we only include closed tabs assocated with this window.
|
||||
* @param {boolean} [aOptions.private = false]
|
||||
Explicit indicator to constrain tab data to only private or non-private windows,
|
||||
* @param {boolean} [aOptions.closedTabsFromAllWindows]
|
||||
Override the value of the closedTabsFromAllWindows preference.
|
||||
* @param {boolean} [aOptions.closedTabsFromClosedWindows]
|
||||
Override the value of the closedTabsFromClosedWindows preference.
|
||||
*/
|
||||
getClosedTabData: function ss_getClosedTabData(aWindow) {
|
||||
if (!SessionStoreInternal._closedTabsFromAllWindowsEnabled) {
|
||||
return this.getClosedTabDataForWindow(
|
||||
aWindow ?? SessionStoreInternal._getTopWindow(false)
|
||||
);
|
||||
}
|
||||
return SessionStoreInternal.getClosedTabData(
|
||||
aWindow ?? SessionStoreInternal._getTopWindow(false)
|
||||
);
|
||||
getClosedTabData: function ss_getClosedTabData(aOptions) {
|
||||
return SessionStoreInternal.getClosedTabData(aOptions);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1321,8 +1330,7 @@ var SessionStoreInternal = {
|
||||
this._prefBranch.addObserver("sessionstore.max_tabs_undo", this, true);
|
||||
|
||||
this._closedTabsFromAllWindowsEnabled = this._prefBranch.getBoolPref(
|
||||
"sessionstore.closedTabsFromAllWindows",
|
||||
true
|
||||
"sessionstore.closedTabsFromAllWindows"
|
||||
);
|
||||
this._prefBranch.addObserver(
|
||||
"sessionstore.closedTabsFromAllWindows",
|
||||
@ -1331,8 +1339,7 @@ var SessionStoreInternal = {
|
||||
);
|
||||
|
||||
this._closedTabsFromClosedWindowsEnabled = this._prefBranch.getBoolPref(
|
||||
"sessionstore.closedTabsFromClosedWindows",
|
||||
true
|
||||
"sessionstore.closedTabsFromClosedWindows"
|
||||
);
|
||||
this._prefBranch.addObserver(
|
||||
"sessionstore.closedTabsFromClosedWindows",
|
||||
@ -2853,9 +2860,15 @@ var SessionStoreInternal = {
|
||||
break;
|
||||
case "sessionstore.closedTabsFromAllWindows":
|
||||
this._closedTabsFromAllWindowsEnabled = this._prefBranch.getBoolPref(
|
||||
"sessionstore.closedTabsFromAllWindows",
|
||||
true
|
||||
"sessionstore.closedTabsFromAllWindows"
|
||||
);
|
||||
this._closedObjectsChanged = true;
|
||||
break;
|
||||
case "sessionstore.closedTabsFromClosedWindows":
|
||||
this._closedTabsFromClosedWindowsEnabled = this._prefBranch.getBoolPref(
|
||||
"sessionstore.closedTabsFromClosedWindows"
|
||||
);
|
||||
this._closedObjectsChanged = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -3738,11 +3751,43 @@ var SessionStoreInternal = {
|
||||
return DyingWindowCache.get(aWindow)._closedTabs.length;
|
||||
},
|
||||
|
||||
getClosedTabCount(aLikeWindow) {
|
||||
const openBrowserWindows = this.getWindows(aLikeWindow);
|
||||
const tabCount = openBrowserWindows
|
||||
.map(win => this.getClosedTabCountForWindow(win))
|
||||
.reduce((total, count) => total + count, 0);
|
||||
_prepareClosedTabOptions(aOptions = {}) {
|
||||
const sourceOptions = Object.assign(
|
||||
{
|
||||
closedTabsFromAllWindows: this._closedTabsFromAllWindowsEnabled,
|
||||
closedTabsFromClosedWindows: this._closedTabsFromClosedWindowsEnabled,
|
||||
sourceWindow: null,
|
||||
},
|
||||
aOptions instanceof Ci.nsIDOMWindow
|
||||
? { sourceWindow: aOptions }
|
||||
: aOptions
|
||||
);
|
||||
if (!sourceOptions.sourceWindow) {
|
||||
sourceOptions.sourceWindow = this._getTopWindow(sourceOptions.private);
|
||||
}
|
||||
if (!sourceOptions.hasOwnProperty("private")) {
|
||||
sourceOptions.private = PrivateBrowsingUtils.isWindowPrivate(
|
||||
sourceOptions.sourceWindow
|
||||
);
|
||||
}
|
||||
return sourceOptions;
|
||||
},
|
||||
|
||||
getClosedTabCount(aOptions) {
|
||||
const sourceOptions = this._prepareClosedTabOptions(aOptions);
|
||||
let tabCount = 0;
|
||||
|
||||
if (sourceOptions.closedTabsFromAllWindows) {
|
||||
tabCount += this.getWindows({ private: sourceOptions.private })
|
||||
.map(win => this.getClosedTabCountForWindow(win))
|
||||
.reduce((total, count) => total + count, 0);
|
||||
} else {
|
||||
tabCount += this.getClosedTabCountForWindow(sourceOptions.sourceWindow);
|
||||
}
|
||||
|
||||
if (!sourceOptions.private && sourceOptions.closedTabsFromClosedWindows) {
|
||||
tabCount += this.getClosedTabCountFromClosedWindows();
|
||||
}
|
||||
return tabCount;
|
||||
},
|
||||
|
||||
@ -3778,11 +3823,17 @@ var SessionStoreInternal = {
|
||||
return Cu.cloneInto(data._closedTabs, {}, options);
|
||||
},
|
||||
|
||||
getClosedTabData: function ssi_getClosedTabData(aLikeWindow) {
|
||||
const windows = this.getWindows(aLikeWindow);
|
||||
getClosedTabData: function ssi_getClosedTabData(aOptions) {
|
||||
const sourceOptions = this._prepareClosedTabOptions(aOptions);
|
||||
const closedTabData = [];
|
||||
for (let win of windows) {
|
||||
closedTabData.push(...this.getClosedTabDataForWindow(win));
|
||||
if (sourceOptions.closedTabsFromAllWindows) {
|
||||
for (let win of this.getWindows({ private: sourceOptions.private })) {
|
||||
closedTabData.push(...this.getClosedTabDataForWindow(win));
|
||||
}
|
||||
} else {
|
||||
closedTabData.push(
|
||||
...this.getClosedTabDataForWindow(sourceOptions.sourceWindow)
|
||||
);
|
||||
}
|
||||
return closedTabData;
|
||||
},
|
||||
|
@ -63,6 +63,7 @@ prefs =
|
||||
network.cookie.cookieBehavior=5
|
||||
gfx.font_rendering.fallback.async=false
|
||||
browser.sessionstore.closedTabsFromAllWindows=true
|
||||
browser.sessionstore.closedTabsFromClosedWindows=true
|
||||
|
||||
#NB: the following are disabled
|
||||
# browser_464620_a.html
|
||||
|
@ -19,6 +19,7 @@ add_setup(async function testSetup() {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history");
|
||||
});
|
||||
preparedClosedIds = await prepareClosedData();
|
||||
SimpleTest.promiseFocus(window);
|
||||
});
|
||||
|
||||
async function prepareClosedData() {
|
||||
@ -92,9 +93,14 @@ async function prepareClosedData() {
|
||||
|
||||
add_task(async function get_closed_tabs_from_closed_windows() {
|
||||
Assert.equal(
|
||||
SessionStore.getClosedTabCount(),
|
||||
SessionStore.getClosedTabCount({ closedTabsFromClosedWindows: false }),
|
||||
1,
|
||||
"Expected closed tab count (in currently-open windows)"
|
||||
"Expected closed tab count (in currently-open windows only)"
|
||||
);
|
||||
Assert.equal(
|
||||
SessionStore.getClosedTabCount(),
|
||||
5,
|
||||
"Expected closed tab count (in currently-open and closed windows)"
|
||||
);
|
||||
// We dont keep the closed tab from the private window
|
||||
Assert.equal(
|
||||
|
@ -62,6 +62,22 @@ const multiWindowState = {
|
||||
selected: 1,
|
||||
},
|
||||
],
|
||||
_closedWindows: [
|
||||
{
|
||||
_closedTabs: [
|
||||
{
|
||||
state: {
|
||||
entries: [
|
||||
{
|
||||
url: "https://example.org#closedWindowClosedTab0",
|
||||
triggeringPrincipal_base64,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
add_setup(async function testSetup() {
|
||||
@ -96,11 +112,12 @@ add_task(async function test_ClosedTabMethods() {
|
||||
Assert.equal(1, closedCount, "1 closed tab for this window");
|
||||
|
||||
closedCount = SessionStore.getClosedTabCount();
|
||||
Assert.equal(3, closedCount, "3 closed tab for all windows");
|
||||
// 3 closed tabs from open windows, 1 closed tab from the closed window
|
||||
Assert.equal(4, closedCount, "4 closed tab for all windows");
|
||||
|
||||
let allWindowsClosedTabs = SessionStore.getClosedTabData();
|
||||
Assert.equal(
|
||||
closedCount,
|
||||
SessionStore.getClosedTabCount({ closedTabsFromClosedWindows: false }),
|
||||
allWindowsClosedTabs.length,
|
||||
"getClosedTabData returned the correct number of entries"
|
||||
);
|
||||
@ -108,6 +125,25 @@ add_task(async function test_ClosedTabMethods() {
|
||||
Assert.ok(tabData.sourceWindowId, "each tab has a sourceWindowId property");
|
||||
}
|
||||
|
||||
closedCount = SessionStore.getClosedTabCountFromClosedWindows();
|
||||
Assert.equal(1, closedCount, "1 closed tabs from closed windows");
|
||||
|
||||
sessionStoreUpdated = TestUtils.topicObserved(
|
||||
"sessionstore-closed-objects-changed"
|
||||
);
|
||||
SessionStore.forgetClosedTab(
|
||||
{ sourceClosedId: SessionStore.getClosedWindowData()[0].closedId },
|
||||
0
|
||||
);
|
||||
await sessionStoreUpdated;
|
||||
|
||||
closedCount = SessionStore.getClosedTabCountFromClosedWindows();
|
||||
Assert.equal(
|
||||
0,
|
||||
closedCount,
|
||||
"0 closed tabs from closed windows after forgetting them"
|
||||
);
|
||||
|
||||
// ***********************************
|
||||
// check with the pref off
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
@ -198,8 +234,14 @@ add_task(async function test_ClosedTabMethods() {
|
||||
|
||||
Assert.equal(
|
||||
0,
|
||||
SessionStore.getClosedTabCount(),
|
||||
"Theres now 0 closed tabs after closing the other browser window which had the last one"
|
||||
SessionStore.getClosedTabCount({ closedTabsFromClosedWindows: false }),
|
||||
"Theres now 0 closed tabs from open windows after closing the other browser window which had the last one"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
1,
|
||||
SessionStore.getClosedTabCount({ closedTabsFromClosedWindows: true }),
|
||||
"Theres now 1 closed tabs including closed windows after closing the other browser window which had the last one"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
@ -208,6 +250,12 @@ add_task(async function test_ClosedTabMethods() {
|
||||
"We get the right number of tab entries from getClosedTabData()"
|
||||
);
|
||||
|
||||
Assert.equal(
|
||||
1,
|
||||
SessionStore.getClosedTabCountFromClosedWindows(),
|
||||
"There's 1 closed tabs from closed windows"
|
||||
);
|
||||
|
||||
// Cleanup.
|
||||
await promiseBrowserState(ORIG_STATE);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user