Bug 1452666 - Simplify SessionHistory serialization code and test expanded principals are serialized and can restore tabs. r=bz,mikedeboer
authorJonathan Kingston <jkt@mozilla.com>
Sat, 19 May 2018 14:42:52 +0100
changeset 419621 4269e02632264e158ac9d7cfc12cb33ab0dc8bf5
parent 419620 8a9d325e3285cb0fd3ded6e329c9d585896ae77f
child 419622 240237473d9e7c87000a10f8985f673fa409a615
push id34040
push userebalazs@mozilla.com
push dateThu, 24 May 2018 09:37:05 +0000
treeherdermozilla-central@c411ccb6bb4a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, mikedeboer
bugs1452666
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1452666 - Simplify SessionHistory serialization code and test expanded principals are serialized and can restore tabs. r=bz,mikedeboer MozReview-Commit-ID: EV39wz2TFlj
browser/components/extensions/test/browser/browser-common.ini
browser/components/extensions/test/browser/browser_ext_sessions_restoreTab.js
toolkit/modules/sessionstore/SessionHistory.jsm
--- 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)