Bug 1452666 - Simplify SessionHistory serialization code and test expanded principals are serialized and can restore tabs. r?bz r?mikedeboer
MozReview-Commit-ID: EV39wz2TFlj
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -130,16 +130,17 @@ skip-if = !e10s || !crashreporter # the
[browser_ext_runtime_openOptionsPage_uninstall.js]
[browser_ext_runtime_setUninstallURL.js]
[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_restore.js]
+[browser_ext_sessions_restoreTab.js]
[browser_ext_sessions_window_tab_value.js]
[browser_ext_settings_overrides_default_search.js]
[browser_ext_sidebarAction.js]
[browser_ext_sidebarAction_browser_style.js]
[browser_ext_sidebarAction_context.js]
[browser_ext_sidebarAction_contextMenu.js]
[browser_ext_sidebarAction_runtime.js]
[browser_ext_sidebarAction_tabs.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_sessions_restoreTab.js
@@ -0,0 +1,63 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+ChromeUtils.defineModuleGetter(this, "SessionStore",
+ "resource:///modules/sessionstore/SessionStore.jsm");
+
+
+/**
+ This test checks that after closing an extension made tab it restores correctly.
+ The tab is given an expanded triggering principal and we didn't use to serialize
+ these correctly into session history.
+ */
+
+// Check that we can restore a tab modified by an extension.
+add_task(async function test_restoringModifiedTab() {
+ function background() {
+ browser.tabs.create({url: "http://example.com/"});
+ browser.test.onMessage.addListener((msg, filter) => {
+ if (msg == "change-tab") {
+ browser.tabs.executeScript({code: 'location.href += "?changedTab";'});
+ }
+ });
+ }
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ permissions: ["tabs", "<all_urls>"],
+ },
+ "browser_action": {
+ "default_title": "Navigate current tab via content script",
+ },
+ background,
+ });
+
+ const contentScriptTabURL = "http://example.com/?changedTab";
+
+ let win = await BrowserTestUtils.openNewBrowserWindow({});
+
+ // Open and close a tabs.
+ let tabPromise = BrowserTestUtils.waitForNewTab(win.gBrowser, "http://example.com/");
+ await extension.startup();
+ let firstTab = await tabPromise;
+ let locationChange = BrowserTestUtils.waitForLocationChange(win.gBrowser, contentScriptTabURL);
+ extension.sendMessage("change-tab");
+ await locationChange;
+ is(firstTab.linkedBrowser.currentURI.spec, contentScriptTabURL, "Got expected URL");
+
+ let sessionPromise = BrowserTestUtils.waitForSessionStoreUpdate(firstTab);
+ BrowserTestUtils.removeTab(firstTab);
+ await sessionPromise;
+
+ tabPromise = BrowserTestUtils.waitForNewTab(win.gBrowser, contentScriptTabURL, true);
+ SessionStore.undoCloseTab(win, 0);
+ let restoredTab = await tabPromise;
+ ok(restoredTab, "We returned a tab here");
+ is(restoredTab.linkedBrowser.currentURI.spec, contentScriptTabURL, "Got expected URL");
+
+ await extension.unload();
+ BrowserTestUtils.removeTab(restoredTab);
+
+ // Close the window.
+ await BrowserTestUtils.closeWindow(win);
+});
--- a/toolkit/modules/sessionstore/SessionHistory.jsm
+++ b/toolkit/modules/sessionstore/SessionHistory.jsm
@@ -209,35 +209,21 @@ var SessionHistoryInternal = {
if (presStates.length > 0) {
entry.presState = presStates;
}
}
}
// Collect triggeringPrincipal data for the current history entry.
if (shEntry.principalToInherit) {
- try {
- let principalToInherit = Utils.serializePrincipal(shEntry.principalToInherit);
- if (principalToInherit) {
- entry.principalToInherit_base64 = principalToInherit;
- }
- } catch (e) {
- debug(e);
- }
+ entry.principalToInherit_base64 = Utils.serializePrincipal(shEntry.principalToInherit);
}
if (shEntry.triggeringPrincipal) {
- try {
- let triggeringPrincipal = Utils.serializePrincipal(shEntry.triggeringPrincipal);
- if (triggeringPrincipal) {
- entry.triggeringPrincipal_base64 = triggeringPrincipal;
- }
- } catch (e) {
- debug(e);
- }
+ entry.triggeringPrincipal_base64 = Utils.serializePrincipal(shEntry.triggeringPrincipal);
}
entry.docIdentifier = shEntry.BFCacheEntry.ID;
if (shEntry.stateData != null) {
entry.structuredCloneState = shEntry.stateData.getDataAsBase64();
entry.structuredCloneVersion = shEntry.stateData.formatVersion;
}
@@ -456,16 +442,22 @@ var SessionHistoryInternal = {
shEntry.adoptBFCacheEntry(matchingEntry.shEntry);
childDocIdents = matchingEntry.childDocIdents;
}
}
if (entry.triggeringPrincipal_base64) {
shEntry.triggeringPrincipal = Utils.deserializePrincipal(entry.triggeringPrincipal_base64);
}
+ // Ensure that we have a null principal if we couldn't deserialize it.
+ // This won't always work however is safe to use.
+ if (!shEntry.triggeringPrincipal) {
+ debug("Couldn't deserialize the triggeringPrincipal, falling back to NullPrincipal");
+ shEntry.triggeringPrincipal = Services.scriptSecurityManager.createNullPrincipal({});
+ }
if (entry.principalToInherit_base64) {
shEntry.principalToInherit = Utils.deserializePrincipal(entry.principalToInherit_base64);
}
if (entry.children && shEntry instanceof Ci.nsISHContainer) {
for (var i = 0; i < entry.children.length; i++) {
// XXXzpao Wallpaper patch for bug 514751
if (!entry.children[i].url)