Bug 1516704 incognito support in session api, r=rpl,mikedeboer

Differential Revision: https://phabricator.services.mozilla.com/D16921

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Shane Caraveo 2019-01-29 20:18:36 +00:00
Родитель 375d1a074a
Коммит 2deab03293
7 изменённых файлов: 251 добавлений и 56 удалений

Просмотреть файл

@ -18,6 +18,8 @@ const getRecentlyClosed = (maxResults, extension) => {
let recentlyClosed = []; let recentlyClosed = [];
// Get closed windows // Get closed windows
// Closed private windows are not stored in sessionstore, we do
// not need to check access for that.
let closedWindowData = SessionStore.getClosedWindowData(false); let closedWindowData = SessionStore.getClosedWindowData(false);
for (let window of closedWindowData) { for (let window of closedWindowData) {
recentlyClosed.push({ recentlyClosed.push({
@ -26,7 +28,11 @@ const getRecentlyClosed = (maxResults, extension) => {
} }
// Get closed tabs // Get closed tabs
// Private closed tabs are in sessionstore if the owning window is still open .
for (let window of windowTracker.browserWindows()) { for (let window of windowTracker.browserWindows()) {
if (!extension.canAccessWindow(window)) {
continue;
}
let closedTabData = SessionStore.getClosedTabData(window, false); let closedTabData = SessionStore.getClosedTabData(window, false);
for (let tab of closedTabData) { for (let tab of closedTabData) {
recentlyClosed.push({ recentlyClosed.push({
@ -66,23 +72,25 @@ const getEncodedKey = function getEncodedKey(extensionId, key) {
return `extension:${extensionId}:${key}`; return `extension:${extensionId}:${key}`;
}; };
const getTabParams = function getTabParams(extensionId, key, id) {
let encodedKey = getEncodedKey(extensionId, key);
let tab = tabTracker.getTab(id);
return {encodedKey, tab};
};
const getWindowParams = function getWindowParams(extensionId, key, id, context) {
let encodedKey = getEncodedKey(extensionId, key);
let win = windowTracker.getWindow(id, context);
return {encodedKey, win};
};
this.sessions = class extends ExtensionAPI { this.sessions = class extends ExtensionAPI {
getAPI(context) { getAPI(context) {
let {extension} = context; let {extension} = context;
function getTabParams(key, id) {
let encodedKey = getEncodedKey(extension.id, key);
let tab = tabTracker.getTab(id);
if (!context.canAccessWindow(tab.ownerGlobal)) {
throw new ExtensionError(`Invalid tab ID: ${id}`);
}
return {encodedKey, tab};
}
function getWindowParams(key, id) {
let encodedKey = getEncodedKey(extension.id, key);
let win = windowTracker.getWindow(id, context);
return {encodedKey, win};
}
return { return {
sessions: { sessions: {
async getRecentlyClosed(filter) { async getRecentlyClosed(filter) {
@ -93,7 +101,7 @@ this.sessions = class extends ExtensionAPI {
async forgetClosedTab(windowId, sessionId) { async forgetClosedTab(windowId, sessionId) {
await SessionStore.promiseInitialized; await SessionStore.promiseInitialized;
let window = context.extension.windowManager.get(windowId).window; let window = windowTracker.getWindow(windowId, context);
let closedTabData = SessionStore.getClosedTabData(window, false); let closedTabData = SessionStore.getClosedTabData(window, false);
let closedTabIndex = closedTabData.findIndex((closedTab) => { let closedTabIndex = closedTabData.findIndex((closedTab) => {
@ -127,7 +135,7 @@ this.sessions = class extends ExtensionAPI {
let session, closedId; let session, closedId;
if (sessionId) { if (sessionId) {
closedId = sessionId; closedId = sessionId;
session = SessionStore.undoCloseById(closedId); session = SessionStore.undoCloseById(closedId, extension.privateBrowsingAllowed);
} else if (SessionStore.lastClosedObjectType == "window") { } else if (SessionStore.lastClosedObjectType == "window") {
// If the most recently closed object is a window, just undo closing the most recent window. // If the most recently closed object is a window, just undo closing the most recent window.
session = SessionStore.undoCloseWindow(0); session = SessionStore.undoCloseWindow(0);
@ -142,26 +150,28 @@ this.sessions = class extends ExtensionAPI {
} }
} }
// Sort the tabs. if (recentlyClosedTabs.length > 0) {
recentlyClosedTabs.sort((a, b) => b.closedAt - a.closedAt); // Sort the tabs.
recentlyClosedTabs.sort((a, b) => b.closedAt - a.closedAt);
// Use the closedId of the most recently closed tab to restore it. // Use the closedId of the most recently closed tab to restore it.
closedId = recentlyClosedTabs[0].closedId; closedId = recentlyClosedTabs[0].closedId;
session = SessionStore.undoCloseById(closedId); session = SessionStore.undoCloseById(closedId, extension.privateBrowsingAllowed);
}
} }
return createSession(session, extension, closedId); return createSession(session, extension, closedId);
}, },
setTabValue(tabId, key, value) { setTabValue(tabId, key, value) {
let {tab, encodedKey} = let {tab, encodedKey} =
getTabParams(extension.id, key, tabId); getTabParams(key, tabId);
SessionStore.setCustomTabValue(tab, encodedKey, JSON.stringify(value)); SessionStore.setCustomTabValue(tab, encodedKey, JSON.stringify(value));
}, },
async getTabValue(tabId, key) { async getTabValue(tabId, key) {
let {tab, encodedKey} = let {tab, encodedKey} =
getTabParams(extension.id, key, tabId); getTabParams(key, tabId);
let value = SessionStore.getCustomTabValue(tab, encodedKey); let value = SessionStore.getCustomTabValue(tab, encodedKey);
if (value) { if (value) {
@ -173,21 +183,21 @@ this.sessions = class extends ExtensionAPI {
removeTabValue(tabId, key) { removeTabValue(tabId, key) {
let {tab, encodedKey} = let {tab, encodedKey} =
getTabParams(extension.id, key, tabId); getTabParams(key, tabId);
SessionStore.deleteCustomTabValue(tab, encodedKey); SessionStore.deleteCustomTabValue(tab, encodedKey);
}, },
setWindowValue(windowId, key, value) { setWindowValue(windowId, key, value) {
let {win, encodedKey} = let {win, encodedKey} =
getWindowParams(extension.id, key, windowId, context); getWindowParams(key, windowId);
SessionStore.setCustomWindowValue(win, encodedKey, JSON.stringify(value)); SessionStore.setCustomWindowValue(win, encodedKey, JSON.stringify(value));
}, },
async getWindowValue(windowId, key) { async getWindowValue(windowId, key) {
let {win, encodedKey} = let {win, encodedKey} =
getWindowParams(extension.id, key, windowId, context); getWindowParams(key, windowId);
let value = SessionStore.getCustomWindowValue(win, encodedKey); let value = SessionStore.getCustomWindowValue(win, encodedKey);
if (value) { if (value) {
@ -199,7 +209,7 @@ this.sessions = class extends ExtensionAPI {
removeWindowValue(windowId, key) { removeWindowValue(windowId, key) {
let {win, encodedKey} = let {win, encodedKey} =
getWindowParams(extension.id, key, windowId, context); getWindowParams(key, windowId);
SessionStore.deleteCustomWindowValue(win, encodedKey); SessionStore.deleteCustomWindowValue(win, encodedKey);
}, },

Просмотреть файл

@ -161,6 +161,7 @@ skip-if = !e10s || !crashreporter # the tab's process is killed during the test.
[browser_ext_runtime_setUninstallURL.js] [browser_ext_runtime_setUninstallURL.js]
[browser_ext_sessions_forgetClosedTab.js] [browser_ext_sessions_forgetClosedTab.js]
[browser_ext_sessions_forgetClosedWindow.js] [browser_ext_sessions_forgetClosedWindow.js]
[browser_ext_sessions_incognito.js]
[browser_ext_sessions_getRecentlyClosed.js] [browser_ext_sessions_getRecentlyClosed.js]
[browser_ext_sessions_getRecentlyClosed_private.js] [browser_ext_sessions_getRecentlyClosed_private.js]
[browser_ext_sessions_getRecentlyClosed_tabs.js] [browser_ext_sessions_getRecentlyClosed_tabs.js]

Просмотреть файл

@ -2,7 +2,7 @@
/* vim: set sts=2 sw=2 et tw=80: */ /* vim: set sts=2 sw=2 et tw=80: */
"use strict"; "use strict";
add_task(async function test_sessions_forget_closed_tab() { function getExtension(incognitoOverride) {
function background() { function background() {
browser.test.onMessage.addListener((msg, windowId, sessionId) => { browser.test.onMessage.addListener((msg, windowId, sessionId) => {
if (msg === "check-sessions") { if (msg === "check-sessions") {
@ -15,22 +15,24 @@ add_task(async function test_sessions_forget_closed_tab() {
browser.test.sendMessage("forgot-tab"); browser.test.sendMessage("forgot-tab");
}, },
error => { error => {
browser.test.assertEq(error.message, browser.test.sendMessage("forget-reject", error.message);
`Could not find closed tab using sessionId ${sessionId}.`);
browser.test.sendMessage("forget-reject");
} }
); );
} }
}); });
} }
let extension = ExtensionTestUtils.loadExtension({ return ExtensionTestUtils.loadExtension({
manifest: { manifest: {
permissions: ["sessions", "tabs"], permissions: ["sessions", "tabs"],
}, },
background, background,
incognitoOverride,
}); });
}
add_task(async function test_sessions_forget_closed_tab() {
let extension = getExtension();
await extension.startup(); await extension.startup();
let tabUrl = "http://example.com"; let tabUrl = "http://example.com";
@ -62,7 +64,9 @@ add_task(async function test_sessions_forget_closed_tab() {
extension.sendMessage("forget-tab", extension.sendMessage("forget-tab",
recentlyClosedTab.windowId, recentlyClosedTab.windowId,
recentlyClosedTab.sessionId); recentlyClosedTab.sessionId);
await extension.awaitMessage("forget-reject"); let errormsg = await extension.awaitMessage("forget-reject");
is(errormsg, `Could not find closed tab using sessionId ${recentlyClosedTab.sessionId}.`);
extension.sendMessage("check-sessions"); extension.sendMessage("check-sessions");
remainingClosed = await extension.awaitMessage("recentlyClosed"); remainingClosed = await extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1, is(remainingClosed.length, recentlyClosedLength - 1,
@ -72,3 +76,40 @@ add_task(async function test_sessions_forget_closed_tab() {
await extension.unload(); await extension.unload();
}); });
add_task(async function test_sessions_forget_closed_tab_private() {
SpecialPowers.pushPrefEnv({set: [
["extensions.allowPrivateBrowsingByDefault", false],
]});
let pb_extension = getExtension("spanning");
await pb_extension.startup();
let extension = getExtension();
await extension.startup();
// Open a private browsing window.
let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
let tabUrl = "http://example.com";
let tab = await BrowserTestUtils.openNewForegroundTab(privateWin.gBrowser, tabUrl);
BrowserTestUtils.removeTab(tab);
tab = await BrowserTestUtils.openNewForegroundTab(privateWin.gBrowser, tabUrl);
let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab);
BrowserTestUtils.removeTab(tab);
await sessionUpdatePromise;
pb_extension.sendMessage("check-sessions");
let recentlyClosed = await pb_extension.awaitMessage("recentlyClosed");
let recentlyClosedTab = recentlyClosed[0].tab;
// Check that forgetting a tab works properly
extension.sendMessage("forget-tab",
recentlyClosedTab.windowId,
recentlyClosedTab.sessionId);
let errormsg = await extension.awaitMessage("forget-reject");
ok(/Invalid window ID/.test(errormsg), "could not access window");
await BrowserTestUtils.closeWindow(privateWin);
await extension.unload();
await pb_extension.unload();
});

Просмотреть файл

@ -2,14 +2,7 @@
/* vim: set sts=2 sw=2 et tw=80: */ /* vim: set sts=2 sw=2 et tw=80: */
"use strict"; "use strict";
add_task(async function test_sessions_forget_closed_window() { function getExtension(incognitoOverride) {
async function openAndCloseWindow(url = "http://example.com") {
let win = await BrowserTestUtils.openNewBrowserWindow();
await BrowserTestUtils.loadURI(win.gBrowser.selectedBrowser, url);
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
await BrowserTestUtils.closeWindow(win);
}
function background() { function background() {
browser.test.onMessage.addListener((msg, sessionId) => { browser.test.onMessage.addListener((msg, sessionId) => {
if (msg === "check-sessions") { if (msg === "check-sessions") {
@ -22,23 +15,32 @@ add_task(async function test_sessions_forget_closed_window() {
browser.test.sendMessage("forgot-window"); browser.test.sendMessage("forgot-window");
}, },
error => { error => {
browser.test.assertEq( browser.test.sendMessage("forget-reject", error.message);
error.message,
`Could not find closed window using sessionId ${sessionId}.`);
browser.test.sendMessage("forget-reject");
} }
); );
} }
}); });
} }
let extension = ExtensionTestUtils.loadExtension({ return ExtensionTestUtils.loadExtension({
manifest: { manifest: {
permissions: ["sessions", "tabs"], permissions: ["sessions", "tabs"],
}, },
background, background,
incognitoOverride,
}); });
}
async function openAndCloseWindow(url = "http://example.com", privateWin) {
let win = await BrowserTestUtils.openNewBrowserWindow({private: privateWin});
let tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, url);
let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab);
await BrowserTestUtils.closeWindow(win);
await sessionUpdatePromise;
}
add_task(async function test_sessions_forget_closed_window() {
let extension = getExtension();
await extension.startup(); await extension.startup();
await openAndCloseWindow("about:config"); await openAndCloseWindow("about:config");
@ -46,7 +48,6 @@ add_task(async function test_sessions_forget_closed_window() {
extension.sendMessage("check-sessions"); extension.sendMessage("check-sessions");
let recentlyClosed = await extension.awaitMessage("recentlyClosed"); let recentlyClosed = await extension.awaitMessage("recentlyClosed");
let recentlyClosedLength = recentlyClosed.length;
let recentlyClosedWindow = recentlyClosed[0].window; let recentlyClosedWindow = recentlyClosed[0].window;
// Check that forgetting a window works properly // Check that forgetting a window works properly
@ -54,20 +55,51 @@ add_task(async function test_sessions_forget_closed_window() {
await extension.awaitMessage("forgot-window"); await extension.awaitMessage("forgot-window");
extension.sendMessage("check-sessions"); extension.sendMessage("check-sessions");
let remainingClosed = await extension.awaitMessage("recentlyClosed"); let remainingClosed = await extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1, is(remainingClosed.length, recentlyClosed.length - 1,
"One window was forgotten."); "One window was forgotten.");
is(remainingClosed[0].window.sessionId, recentlyClosed[1].window.sessionId, is(remainingClosed[0].window.sessionId, recentlyClosed[1].window.sessionId,
"The correct window was forgotten."); "The correct window was forgotten.");
// Check that re-forgetting the same window fails properly // Check that re-forgetting the same window fails properly
extension.sendMessage("forget-window", recentlyClosedWindow.sessionId); extension.sendMessage("forget-window", recentlyClosedWindow.sessionId);
await extension.awaitMessage("forget-reject"); let errMsg = await extension.awaitMessage("forget-reject");
is(errMsg, `Could not find closed window using sessionId ${recentlyClosedWindow.sessionId}.`);
extension.sendMessage("check-sessions"); extension.sendMessage("check-sessions");
remainingClosed = await extension.awaitMessage("recentlyClosed"); remainingClosed = await extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosedLength - 1, is(remainingClosed.length, recentlyClosed.length - 1,
"No extra window was forgotten."); "No extra window was forgotten.");
is(remainingClosed[0].window.sessionId, recentlyClosed[1].window.sessionId, is(remainingClosed[0].window.sessionId, recentlyClosed[1].window.sessionId,
"The correct window remains."); "The correct window remains.");
await extension.unload(); await extension.unload();
}); });
add_task(async function test_sessions_forget_closed_window_private() {
SpecialPowers.pushPrefEnv({set: [
["extensions.allowPrivateBrowsingByDefault", false],
]});
let pb_extension = getExtension("spanning");
await pb_extension.startup();
let extension = getExtension("not_allowed");
await extension.startup();
await openAndCloseWindow("about:config", true);
await openAndCloseWindow("about:robots", true);
pb_extension.sendMessage("check-sessions");
let recentlyClosed = await pb_extension.awaitMessage("recentlyClosed");
let recentlyClosedWindow = recentlyClosed[0].window;
extension.sendMessage("forget-window", recentlyClosedWindow.sessionId);
await extension.awaitMessage("forgot-window");
extension.sendMessage("check-sessions");
let remainingClosed = await extension.awaitMessage("recentlyClosed");
is(remainingClosed.length, recentlyClosed.length - 1,
"One window was forgotten.");
ok(!recentlyClosedWindow.incognito, "not an incognito window");
await extension.unload();
await pb_extension.unload();
});

Просмотреть файл

@ -7,7 +7,7 @@ SimpleTest.requestCompleteLog();
Services.scriptloader.loadSubScript(new URL("head_sessions.js", gTestPath).href, Services.scriptloader.loadSubScript(new URL("head_sessions.js", gTestPath).href,
this); this);
add_task(async function test_sessions_get_recently_closed_private() { async function run_test_extension(incognitoOverride) {
function background() { function background() {
browser.test.onMessage.addListener((msg, filter) => { browser.test.onMessage.addListener((msg, filter) => {
if (msg == "check-sessions") { if (msg == "check-sessions") {
@ -23,6 +23,7 @@ add_task(async function test_sessions_get_recently_closed_private() {
permissions: ["sessions", "tabs"], permissions: ["sessions", "tabs"],
}, },
background, background,
incognitoOverride,
}); });
// Open a private browsing window. // Open a private browsing window.
@ -48,7 +49,8 @@ add_task(async function test_sessions_get_recently_closed_private() {
extension.sendMessage("check-sessions"); extension.sendMessage("check-sessions");
recentlyClosed = await extension.awaitMessage("recentlyClosed"); recentlyClosed = await extension.awaitMessage("recentlyClosed");
checkRecentlyClosed(recentlyClosed.filter(onlyNewItemsFilter), 2, privateWinId, true); let expectedCount = incognitoOverride == "not_allowed" ? 0 : 2;
checkRecentlyClosed(recentlyClosed.filter(onlyNewItemsFilter), expectedCount, privateWinId, true);
// Close the private window. // Close the private window.
await BrowserTestUtils.closeWindow(privateWin); await BrowserTestUtils.closeWindow(privateWin);
@ -58,4 +60,21 @@ add_task(async function test_sessions_get_recently_closed_private() {
is(recentlyClosed.filter(onlyNewItemsFilter).length, 0, "the closed private window info was not found in recently closed data"); is(recentlyClosed.filter(onlyNewItemsFilter).length, 0, "the closed private window info was not found in recently closed data");
await extension.unload(); await extension.unload();
}
add_task(async function test_sessions_get_recently_closed_default() {
SpecialPowers.pushPrefEnv({set: [
["extensions.allowPrivateBrowsingByDefault", true],
]});
await run_test_extension();
});
add_task(async function test_sessions_get_recently_closed_private_incognito() {
SpecialPowers.pushPrefEnv({set: [
["extensions.allowPrivateBrowsingByDefault", false],
]});
await run_test_extension("spanning");
await run_test_extension("not_allowed");
}); });

Просмотреть файл

@ -0,0 +1,88 @@
"use strict";
add_task(async function test_sessions_tab_value_private() {
Services.obs.notifyObservers(null, "browser:purge-session-history");
is(SessionStore.getClosedWindowCount(), 0,
"No closed window sessions at start of test");
SpecialPowers.pushPrefEnv({set: [
["extensions.allowPrivateBrowsingByDefault", false],
]});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
applications: {
gecko: {
id: "exampleextension@mozilla.org",
},
},
permissions: ["sessions"],
},
background() {
browser.test.onMessage.addListener(async (msg, pbw) => {
if (msg == "value") {
await browser.test.assertRejects(browser.sessions.setWindowValue(pbw.windowId, "foo", "bar"),
/Invalid window ID/,
"should not be able to set incognito window session data");
await browser.test.assertRejects(browser.sessions.getWindowValue(pbw.windowId, "foo"),
/Invalid window ID/,
"should not be able to get incognito window session data");
await browser.test.assertRejects(browser.sessions.removeWindowValue(pbw.windowId, "foo"),
/Invalid window ID/,
"should not be able to remove incognito window session data");
await browser.test.assertRejects(browser.sessions.setTabValue(pbw.tabId, "foo", "bar"),
/Invalid tab ID/,
"should not be able to set incognito tab session data");
await browser.test.assertRejects(browser.sessions.getTabValue(pbw.tabId, "foo"),
/Invalid tab ID/,
"should not be able to get incognito tab session data");
await browser.test.assertRejects(browser.sessions.removeTabValue(pbw.tabId, "foo"),
/Invalid tab ID/,
"should not be able to remove incognito tab session data");
}
if (msg == "restore") {
await browser.test.assertRejects(browser.sessions.restore(),
/Could not restore object/,
"should not be able to restore incognito last window session data");
if (pbw) {
await browser.test.assertRejects(browser.sessions.restore(pbw.sessionId),
/Could not restore object/,
`should not be able to restore incognito session ID ${pbw.sessionId} session data`);
}
}
browser.test.sendMessage("done");
});
},
});
let winData = await getIncognitoWindow("http://mochi.test:8888/");
await extension.startup();
// Test value set/get APIs on a private window and tab.
extension.sendMessage("value", winData.details);
await extension.awaitMessage("done");
// Test restoring a private tab.
let tab = await BrowserTestUtils.openNewForegroundTab(winData.win.gBrowser, "http://example.com");
let sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(tab);
await BrowserTestUtils.removeTab(tab);
await sessionUpdatePromise;
let closedTabData = SessionStore.getClosedTabData(winData.win, false);
extension.sendMessage("restore", {sesionId: closedTabData[0].closedId});
await extension.awaitMessage("done");
// Test restoring a private window.
sessionUpdatePromise = BrowserTestUtils.waitForSessionStoreUpdate(winData.win.gBrowser.selectedTab);
await BrowserTestUtils.closeWindow(winData.win);
await sessionUpdatePromise;
is(SessionStore.getClosedWindowCount(), 0,
"The closed window was added to Recently Closed Windows");
// If the window gets restored, test will fail with an unclosed window.
extension.sendMessage("restore");
await extension.awaitMessage("done");
await extension.unload();
});

Просмотреть файл

@ -375,8 +375,8 @@ var SessionStore = {
return SessionStoreInternal.getSessionHistory(tab, updatedCallback); return SessionStoreInternal.getSessionHistory(tab, updatedCallback);
}, },
undoCloseById(aClosedId) { undoCloseById(aClosedId, aIncludePrivate) {
return SessionStoreInternal.undoCloseById(aClosedId); return SessionStoreInternal.undoCloseById(aClosedId, aIncludePrivate);
}, },
resetBrowserToLazyState(tab) { resetBrowserToLazyState(tab) {
@ -2689,7 +2689,6 @@ var SessionStoreInternal = {
if (!(aIndex in this._closedWindows)) { if (!(aIndex in this._closedWindows)) {
throw Components.Exception("Invalid index: not in the closed windows", Cr.NS_ERROR_INVALID_ARG); throw Components.Exception("Invalid index: not in the closed windows", Cr.NS_ERROR_INVALID_ARG);
} }
// reopen the window // reopen the window
let state = { windows: this._removeClosedWindow(aIndex) }; let state = { windows: this._removeClosedWindow(aIndex) };
delete state.windows[0].closedAt; // Window is now open. delete state.windows[0].closedAt; // Window is now open.
@ -2828,10 +2827,12 @@ var SessionStoreInternal = {
* *
* @param aClosedId * @param aClosedId
* The closedId of the tab or window * The closedId of the tab or window
* @param aIncludePrivate
* Whether to restore private tabs or windows
* *
* @returns a tab or window object * @returns a tab or window object
*/ */
undoCloseById(aClosedId) { undoCloseById(aClosedId, aIncludePrivate = true) {
// Check for a window first. // Check for a window first.
for (let i = 0, l = this._closedWindows.length; i < l; i++) { for (let i = 0, l = this._closedWindows.length; i < l; i++) {
if (this._closedWindows[i].closedId == aClosedId) { if (this._closedWindows[i].closedId == aClosedId) {
@ -2841,6 +2842,9 @@ var SessionStoreInternal = {
// Check for a tab. // Check for a tab.
for (let window of Services.wm.getEnumerator("navigator:browser")) { for (let window of Services.wm.getEnumerator("navigator:browser")) {
if (!aIncludePrivate && PrivateBrowsingUtils.isWindowPrivate(window)) {
continue;
}
let windowState = this._windows[window.__SSi]; let windowState = this._windows[window.__SSi];
if (windowState) { if (windowState) {
for (let j = 0, l = windowState._closedTabs.length; j < l; j++) { for (let j = 0, l = windowState._closedTabs.length; j < l; j++) {