Bug 1450559 - Remove nsISessionStore in favor of SessionStore.jsm. r=mikedeboer draft
authorDão Gottwald <dao@mozilla.com>
Thu, 05 Apr 2018 16:30:48 +0200
changeset 777916 fc353af87bd620b7039d3e6241cc60c3788e3da6
parent 777823 1b258f938525fda65ef80ffa0408bc665d5d8948
push id105330
push userdgottwald@mozilla.com
push dateThu, 05 Apr 2018 14:32:10 +0000
reviewersmikedeboer
bugs1450559
milestone61.0a1
Bug 1450559 - Remove nsISessionStore in favor of SessionStore.jsm. r=mikedeboer MozReview-Commit-ID: 8spvIOus9ai
browser/base/content/browser.js
browser/base/content/test/about/browser_aboutCertError.js
browser/base/content/test/about/browser_aboutNetError.js
browser/base/content/test/general/browser_audioTabIcon.js
browser/base/content/test/tabs/browser_bug_1387976_restore_lazy_tab_browser_muted_state.js
browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/content/aboutSessionRestore.js
browser/components/sessionstore/moz.build
browser/components/sessionstore/nsISessionStore.idl
browser/components/sessionstore/nsSessionStartup.manifest
browser/components/sessionstore/nsSessionStore.js
browser/components/sessionstore/nsSessionStore.manifest
browser/components/sessionstore/test/browser_345898.js
browser/components/sessionstore/test/browser_589246.js
browser/components/sessionstore/test/browser_sessionStoreContainer.js
browser/components/sessionstore/test/head.js
browser/installer/package-manifest.in
browser/modules/AboutHome.jsm
devtools/client/responsive.html/test/browser/browser_hide_container.js
devtools/client/scratchpad/test/browser_scratchpad_sessions.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3235,19 +3235,17 @@ function getMeOutOfHere() {
  * Re-direct the browser to the previous page or a known-safe page if no
  * previous page is found in history.  This function is used when the user
  * browses to a secure page with certificate issues and is presented with
  * about:certerror.  The "Go Back" button should take the user to the previous
  * or a default start page so that even when their own homepage is on a server
  * that has certificate errors, we can get them somewhere safe.
  */
 function goBackFromErrorPage() {
-  const ss = Cc["@mozilla.org/browser/sessionstore;1"].
-             getService(Ci.nsISessionStore);
-  let state = JSON.parse(ss.getTabState(gBrowser.selectedTab));
+  let state = JSON.parse(SessionStore.getTabState(gBrowser.selectedTab));
   if (state.index == 1) {
     // If the unsafe page is the first or the only one in history, go to the
     // start page.
     gBrowser.loadURI(getDefaultHomePage());
   } else {
     BrowserBack();
   }
 }
--- a/browser/base/content/test/about/browser_aboutCertError.js
+++ b/browser/base/content/test/about/browser_aboutCertError.js
@@ -7,17 +7,16 @@
 
 const GOOD_PAGE = "https://example.com/";
 const GOOD_PAGE_2 = "https://example.org/";
 const DUMMY_PAGE = getRootDirectory(gTestPath).replace("chrome://mochitests/content", GOOD_PAGE) + "dummy_page.html";
 const BAD_CERT = "https://expired.example.com/";
 const UNKNOWN_ISSUER = "https://self-signed.example.com ";
 const BAD_STS_CERT = "https://badchain.include-subdomains.pinning.example.com:443";
 const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
-const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
 function injectErrorPageFrame(tab, src) {
   return ContentTask.spawn(tab.linkedBrowser, {frameSrc: src}, async function({frameSrc}) {
     let loaded = ContentTaskUtils.waitForEvent(content.wrappedJSObject, "DOMFrameContentLoaded");
     let iframe = content.document.createElement("iframe");
     iframe.src = frameSrc;
     content.document.body.appendChild(iframe);
     await loaded;
@@ -56,17 +55,17 @@ add_task(async function checkReturnToAbo
     let browser = tab.linkedBrowser;
 
     is(browser.webNavigation.canGoBack, false, "!webNavigation.canGoBack");
     is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
 
     // Populate the shistory entries manually, since it happens asynchronously
     // and the following tests will be too soon otherwise.
     await TabStateFlusher.flush(browser);
-    let {entries} = JSON.parse(ss.getTabState(tab));
+    let {entries} = JSON.parse(SessionStore.getTabState(tab));
     is(entries.length, 1, "there is one shistory entry");
 
     info("Clicking the go back button on about:certerror");
     await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
       let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
 
       let returnButton = doc.getElementById("returnButton");
       if (!frame) {
@@ -108,17 +107,17 @@ add_task(async function checkReturnToPre
     }
 
     is(browser.webNavigation.canGoBack, true, "webNavigation.canGoBack");
     is(browser.webNavigation.canGoForward, false, "!webNavigation.canGoForward");
 
     // Populate the shistory entries manually, since it happens asynchronously
     // and the following tests will be too soon otherwise.
     await TabStateFlusher.flush(browser);
-    let {entries} = JSON.parse(ss.getTabState(tab));
+    let {entries} = JSON.parse(SessionStore.getTabState(tab));
     is(entries.length, 2, "there are two shistory entries");
 
     info("Clicking the go back button on about:certerror");
     await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
       let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
       let returnButton = doc.getElementById("returnButton");
       returnButton.click();
 
--- a/browser/base/content/test/about/browser_aboutNetError.js
+++ b/browser/base/content/test/about/browser_aboutNetError.js
@@ -3,18 +3,16 @@
 
 "use strict";
 
 // Set ourselves up for TLS error
 Services.prefs.setIntPref("security.tls.version.max", 3);
 Services.prefs.setIntPref("security.tls.version.min", 3);
 
 const LOW_TLS_VERSION = "https://tls1.example.com/";
-const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
-const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
 add_task(async function checkReturnToPreviousPage() {
   info("Loading a TLS page that isn't supported, ensure we have a fix button and clicking it then loads the page");
   let browser;
   let pageLoaded;
   await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
     gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, LOW_TLS_VERSION);
     browser = gBrowser.selectedBrowser;
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -165,18 +165,17 @@ async function test_mute_tab(tab, icon, 
   if (isAudioPlaying) {
     await wait_for_tab_playing_event(tab, !expectMuted);
   }
 
   return mutedPromise;
 }
 
 function get_tab_state(tab) {
-  const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-  return JSON.parse(ss.getTabState(tab));
+  return JSON.parse(SessionStore.getTabState(tab));
 }
 
 async function test_muting_using_menu(tab, expectMuted) {
   // Show the popup menu
   let contextMenu = document.getElementById("tabContextMenu");
   let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
   EventUtils.synthesizeMouseAtCenter(tab, {type: "contextmenu", button: 2});
   await popupShownPromise;
--- a/browser/base/content/test/tabs/browser_bug_1387976_restore_lazy_tab_browser_muted_state.js
+++ b/browser/base/content/test/tabs/browser_bug_1387976_restore_lazy_tab_browser_muted_state.js
@@ -18,18 +18,17 @@ const restartTab = async function(tab) {
   BrowserTestUtils.removeTab(tab);
 
   let restoredLazyTab = BrowserTestUtils.addTab(gBrowser, "", {createLazyBrowser: true});
   SessionStore.setTabState(restoredLazyTab, JSON.stringify(tabData));
   return restoredLazyTab;
 };
 
 function get_tab_state(tab) {
-  const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-  return JSON.parse(ss.getTabState(tab));
+  return JSON.parse(SessionStore.getTabState(tab));
 }
 
 add_task(async function() {
   const tab = BrowserTestUtils.addTab(gBrowser, "http://mochi.test:8888/");
   const browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   // Let's make sure the tab is not in a muted state at the beginning
--- a/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js
+++ b/browser/components/preferences/in-content/tests/browser_bug1184989_prevent_scrolling_when_preferences_flipped.js
@@ -1,10 +1,8 @@
-const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
-
 const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm", {});
 const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
 
 add_task(async function() {
   waitForExplicitFinish();
 
   const tabURL = getRootDirectory(gTestPath) + "browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul";
 
@@ -63,17 +61,17 @@ add_task(async function() {
   const TAB_URL = "about:sessionrestore";
   const TAB_FORMDATA = {url: TAB_URL, id: {sessionData: CRASH_STATE}};
   const TAB_SHENTRY = {url: TAB_URL, triggeringPrincipal_base64};
   const TAB_STATE = {entries: [TAB_SHENTRY], formdata: TAB_FORMDATA};
 
   let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
 
   // Fake a post-crash tab
-  ss.setTabState(tab, JSON.stringify(TAB_STATE));
+  SessionStore.setTabState(tab, JSON.stringify(TAB_STATE));
 
   await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   let doc = tab.linkedBrowser.contentDocument;
 
   // Make body scrollable
   doc.body.style.height = (doc.body.clientHeight + 100) + "px";
 
   let tabsToggle = doc.getElementById("tabsToggle");
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -2329,16 +2329,19 @@ var SessionStoreInternal = {
 
     this.restoreWindows(aWindow, aState, {overwriteTabs: aOverwrite});
 
     // Notify of changes to closed objects.
     this._notifyOfClosedObjectsChange();
   },
 
   getTabState: function ssi_getTabState(aTab) {
+    if (!aTab || !aTab.ownerGlobal) {
+      throw Components.Exception("Need a valid tab", Cr.NS_ERROR_INVALID_ARG);
+    }
     if (!aTab.ownerGlobal.__SSi) {
       throw Components.Exception("Default view is not tracked", Cr.NS_ERROR_INVALID_ARG);
     }
 
     let tabState = TabState.collect(aTab);
 
     return JSON.stringify(tabState);
   },
@@ -2355,31 +2358,34 @@ var SessionStoreInternal = {
     if (typeof tabState != "object") {
       throw Components.Exception("Not an object", Cr.NS_ERROR_INVALID_ARG);
     }
     if (!("entries" in tabState)) {
       throw Components.Exception("Invalid state object: no entries", Cr.NS_ERROR_INVALID_ARG);
     }
 
     let window = aTab.ownerGlobal;
-    if (!("__SSi" in window)) {
+    if (!window || !("__SSi" in window)) {
       throw Components.Exception("Window is not tracked", Cr.NS_ERROR_INVALID_ARG);
     }
 
     if (aTab.linkedBrowser.__SS_restoreState) {
       this._resetTabRestoringState(aTab);
     }
 
     this.restoreTab(aTab, tabState);
 
     // Notify of changes to closed objects.
     this._notifyOfClosedObjectsChange();
   },
 
   duplicateTab: function ssi_duplicateTab(aWindow, aTab, aDelta = 0, aRestoreImmediately = true) {
+    if (!aTab || !aTab.ownerGlobal) {
+      throw Components.Exception("Need a valid tab", Cr.NS_ERROR_INVALID_ARG);
+    }
     if (!aTab.ownerGlobal.__SSi) {
       throw Components.Exception("Default view is not tracked", Cr.NS_ERROR_INVALID_ARG);
     }
     if (!aWindow.gBrowser) {
       throw Components.Exception("Invalid window object: no gBrowser", Cr.NS_ERROR_INVALID_ARG);
     }
 
     // Create a new tab.
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -3,16 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "AppConstants",
   "resource://gre/modules/AppConstants.jsm");
+ChromeUtils.defineModuleGetter(this, "SessionStore",
+  "resource:///modules/sessionstore/SessionStore.jsm");
 
 var gStateObject;
 var gTreeData;
 
 // Page initialization
 
 window.onload = function() {
   let toggleTabs = document.getElementById("tabsToggle");
@@ -146,35 +148,34 @@ function restoreSession() {
           // this window won't be restored at all
           gStateObject.windows.splice(ix, 1);
         ix--;
       }
     }
   }
   var stateString = JSON.stringify(gStateObject);
 
-  var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
   var top = getBrowserWindow();
 
   // if there's only this page open, reuse the window for restoring the session
   if (top.gBrowser.tabs.length == 1) {
-    ss.setWindowState(top, stateString, true);
+    SessionStore.setWindowState(top, stateString, true);
     return;
   }
 
   // restore the session into a new window and close the current tab
   var newWindow = top.openDialog(top.location, "_blank", "chrome,dialog=no,all");
 
   Services.obs.addObserver(function observe(win, topic) {
     if (win != newWindow) {
       return;
     }
 
     Services.obs.removeObserver(observe, topic);
-    ss.setWindowState(newWindow, stateString, true);
+    SessionStore.setWindowState(newWindow, stateString, true);
 
     var tabbrowser = top.gBrowser;
     var tabIndex = tabbrowser.getBrowserIndexForDocument(document);
     tabbrowser.removeTab(tabbrowser.tabs[tabIndex]);
   }, "browser-delayed-startup-finished");
 }
 
 function startNewSession() {
@@ -263,22 +264,21 @@ function toggleRowChecked(aIx) {
   }
 }
 
 function restoreSingleTab(aIx, aShifted) {
   var tabbrowser = getBrowserWindow().gBrowser;
   var newTab = tabbrowser.addTab();
   var item = gTreeData[aIx];
 
-  var ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
   var tabState = gStateObject.windows[item.parent.ix]
                              .tabs[aIx - gTreeData.indexOf(item.parent) - 1];
   // ensure tab would be visible on the tabstrip.
   tabState.hidden = false;
-  ss.setTabState(newTab, JSON.stringify(tabState));
+  SessionStore.setTabState(newTab, JSON.stringify(tabState));
 
   // respect the preference as to whether to select the tab (the Shift key inverses)
   if (Services.prefs.getBoolPref("browser.tabs.loadInBackground") != !aShifted)
     tabbrowser.selectedTab = newTab;
 }
 
 // Tree controller
 
--- a/browser/components/sessionstore/moz.build
+++ b/browser/components/sessionstore/moz.build
@@ -6,26 +6,24 @@
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 JAR_MANIFESTS += ['jar.mn']
 
 XPIDL_SOURCES += [
     'nsISessionStartup.idl',
-    'nsISessionStore.idl',
     'nsISessionStoreUtils.idl',
 ]
 
 XPIDL_MODULE = 'sessionstore'
 
 EXTRA_COMPONENTS += [
     'nsSessionStartup.js',
-    'nsSessionStore.js',
-    'nsSessionStore.manifest',
+    'nsSessionStartup.manifest',
 ]
 
 EXTRA_JS_MODULES.sessionstore = [
     'ContentRestore.jsm',
     'DocShellCapabilities.jsm',
     'GlobalState.jsm',
     'PrivacyFilter.jsm',
     'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
deleted file mode 100644
--- a/browser/components/sessionstore/nsISessionStore.idl
+++ /dev/null
@@ -1,220 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMWindow;
-interface nsIDOMNode;
-
-/**
- * nsISessionStore keeps track of the current browsing state - i.e.
- * tab history, cookies, scroll state, form data, and window features
- * - and allows to restore everything into one browser window.
- *
- * The nsISessionStore API operates mostly on browser windows and the tabbrowser
- * tabs contained in them:
- *
- * * "Browser windows" are those DOM windows having loaded
- * chrome://browser/content/browser.xul . From overlays you can just pass the
- * global |window| object to the API, though (or |top| from a sidebar).
- * From elsewhere you can get browser windows through the nsIWindowMediator
- * by looking for "navigator:browser" windows.
- *
- * * "Tabbrowser tabs" are all the child nodes of a browser window's
- * |gBrowser.tabContainer| such as e.g. |gBrowser.selectedTab|.
- */
-
-[scriptable, uuid(4580f5eb-693d-423d-b0ce-2cb20a962e4d)]
-interface nsISessionStore : nsISupports
-{
-  /**
-   * Is it possible to restore the previous session. Will always be false when
-   * in Private Browsing mode.
-   */
-  attribute boolean canRestoreLastSession;
-
-  /**
-   * Restore the previous session if possible. This will not overwrite the
-   * current session. Instead the previous session will be merged into the
-   * current session. Current windows will be reused if they were windows that
-   * pinned tabs were previously restored into. New windows will be opened as
-   * needed.
-   *
-   * Note: This will throw if there is no previous state to restore. Check with
-   * canRestoreLastSession first to avoid thrown errors.
-   */
-  void restoreLastSession();
-
-  /**
-   * Get the current browsing state.
-   * @returns a JSON string representing the session state.
-   */
-  AString getBrowserState();
-
-  /**
-   * Set the browsing state.
-   * This will immediately restore the state of the whole application to the state
-   * passed in, *replacing* the current session.
-   *
-   * @param aState is a JSON string representing the session state.
-   */
-  void setBrowserState(in AString aState);
-
-  /**
-   * @param aWindow is the browser window whose state is to be returned.
-   *
-   * @returns a JSON string representing a session state with only one window.
-   */
-  AString getWindowState(in nsIDOMWindow aWindow);
-
-  /**
-   * @param aWindow    is the browser window whose state is to be set.
-   * @param aState     is a JSON string representing a session state.
-   * @param aOverwrite boolean overwrite existing tabs
-   */
-  void setWindowState(in nsIDOMWindow aWindow, in AString aState, in boolean aOverwrite);
-
-  /**
-   * @param aTab is the tabbrowser tab whose state is to be returned.
-   *
-   * @returns a JSON string representing the state of the tab
-   *         (note: doesn't contain cookies - if you need them, use getWindowState instead).
-   */
-  AString getTabState(in nsIDOMNode aTab);
-
-  /**
-   * @param aTab   is the tabbrowser tab whose state is to be set.
-   * @param aState is a JSON string representing a session state.
-   */
-  void setTabState(in nsIDOMNode aTab, in AString aState);
-
-  /**
-   * Duplicates a given tab as thoroughly as possible.
-   *
-   * @param aWindow is the browser window into which the tab will be duplicated.
-   * @param aTab    is the tabbrowser tab to duplicate (can be from a different window).
-   * @param aDelta  is the offset to the history entry to load in the duplicated tab.
-   * @returns a reference to the newly created tab.
-   */
-  nsIDOMNode duplicateTab(in nsIDOMWindow aWindow, in nsIDOMNode aTab,
-                          [optional] in long aDelta);
-
-  /**
-   * Get the number of restore-able tabs for a browser window
-   */
-  unsigned long getClosedTabCount(in nsIDOMWindow aWindow);
-
-  /**
-   * Get closed tab data
-   *
-   * @param aWindow is the browser window for which to get closed tab data
-   * @returns a JSON string representing the list of closed tabs.
-   */
-  AString getClosedTabData(in nsIDOMWindow aWindow);
-
-  /**
-   * @param aWindow is the browser window to reopen a closed tab in.
-   * @param aIndex  is the index of the tab to be restored (FIFO ordered).
-   * @returns a reference to the reopened tab.
-   */
-  nsIDOMNode undoCloseTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
-
-  /**
-   * @param aWindow is the browser window associated with the closed tab.
-   * @param aIndex  is the index of the closed tab to be removed (FIFO ordered).
-   */
-  nsIDOMNode forgetClosedTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
-
-  /**
-   * Get the number of restore-able windows
-   */
-  unsigned long getClosedWindowCount();
-
-  /**
-   * Get closed windows data
-   *
-   * @returns a JSON string representing the list of closed windows.
-   */
-  AString getClosedWindowData();
-
-  /**
-   * @param aIndex is the index of the windows to be restored (FIFO ordered).
-   * @returns the nsIDOMWindow object of the reopened window
-   */
-  nsIDOMWindow undoCloseWindow(in unsigned long aIndex);
-
-  /**
-   * @param aIndex  is the index of the closed window to be removed (FIFO ordered).
-   *
-   * @throws NS_ERROR_INVALID_ARG
-   *   when aIndex does not map to a closed window
-   */
-  nsIDOMNode forgetClosedWindow(in unsigned long aIndex);
-
-  /**
-   * @param aWindow is the window to get the value for.
-   * @param aKey    is the value's name.
-   *
-   * @returns A string value or an empty string if none is set.
-   */
-  AString getWindowValue(in nsIDOMWindow aWindow, in AString aKey);
-
-  /**
-   * @param aWindow      is the browser window to set the value for.
-   * @param aKey         is the value's name.
-   * @param aStringValue is the value itself (use JSON.stringify/parse before setting JS objects).
-   */
-  void setWindowValue(in nsIDOMWindow aWindow, in AString aKey, in jsval aStringValue);
-
-  /**
-   * @param aWindow is the browser window to get the value for.
-   * @param aKey    is the value's name.
-   */
-  void deleteWindowValue(in nsIDOMWindow aWindow, in AString aKey);
-
-  /**
-   * @param aTab is the tabbrowser tab to get the value for.
-   * @param aKey is the value's name.
-   *
-   * @returns A string value or an empty string if none is set.
-   */
-  AString getCustomTabValue(in nsIDOMNode aTab, in AString aKey);
-
-  /**
-   * @param aTab         is the tabbrowser tab to set the value for.
-   * @param aKey         is the value's name.
-   * @param aStringValue is the value itself (use JSON.stringify/parse before setting JS objects).
-   */
-  void setCustomTabValue(in nsIDOMNode aTab, in AString aKey, in jsval aStringValue);
-
-  /**
-   * @param aTab is the tabbrowser tab to get the value for.
-   * @param aKey is the value's name.
-   */
-  void deleteCustomTabValue(in nsIDOMNode aTab, in AString aKey);
-
-   /**
-   * @param aKey is the value's name.
-   *
-   * @returns A string value or an empty string if none is set.
-   */
-  AString getGlobalValue(in AString aKey);
-
-  /**
-   * @param aKey         is the value's name.
-   * @param aStringValue is the value itself (use JSON.stringify/parse before setting JS objects).
-   */
-  void setGlobalValue(in AString aKey, in jsval aStringValue);
-
-  /**
-   * @param aTab is the browser tab to get the value for.
-   * @param aKey is the value's name.
-   */
-  void deleteGlobalValue(in AString aKey);
-
-  /**
-   * @param aName is the name of the attribute to save/restore for all tabbrowser tabs.
-   */
-  void persistTabAttribute(in AString aName);
-};
rename from browser/components/sessionstore/nsSessionStore.manifest
rename to browser/components/sessionstore/nsSessionStartup.manifest
--- a/browser/components/sessionstore/nsSessionStore.manifest
+++ b/browser/components/sessionstore/nsSessionStartup.manifest
@@ -1,12 +1,10 @@
 # This component must restrict its registration for the app-startup category
 # to the specific list of apps that use it so it doesn't get loaded in xpcshell.
 # Thus we restrict it to these apps:
 #
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
 
-component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js
-contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b}
 component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js
 contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66}
 category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110}
deleted file mode 100644
--- a/browser/components/sessionstore/nsSessionStore.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/**
- * Session Storage and Restoration
- *
- * Overview
- * This service keeps track of a user's session, storing the various bits
- * required to return the browser to its current state. The relevant data is
- * stored in memory, and is periodically saved to disk in a file in the
- * profile directory. The service is started at first window load, in
- * delayedStartup, and will restore the session from the data received from
- * the nsSessionStartup service.
- */
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource:///modules/sessionstore/SessionStore.jsm");
-
-function SessionStoreService() {}
-
-// The SessionStore module's object is frozen. We need to modify our prototype
-// and add some properties so let's just copy the SessionStore object.
-Object.keys(SessionStore).forEach(function(aName) {
-  let desc = Object.getOwnPropertyDescriptor(SessionStore, aName);
-  Object.defineProperty(SessionStoreService.prototype, aName, desc);
-});
-
-SessionStoreService.prototype.classID =
-  Components.ID("{5280606b-2510-4fe0-97ef-9b5a22eafe6b}");
-SessionStoreService.prototype.QueryInterface =
-  XPCOMUtils.generateQI([Ci.nsISessionStore]);
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SessionStoreService]);
--- a/browser/components/sessionstore/test/browser_345898.js
+++ b/browser/components/sessionstore/test/browser_345898.js
@@ -8,26 +8,26 @@ function test() {
   // all of the following calls with illegal arguments should throw NS_ERROR_ILLEGAL_VALUE
   Assert.throws(() => ss.getWindowState({}),
     /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid window for getWindowState throws");
   Assert.throws(() => ss.setWindowState({}, "", false),
     /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid window for setWindowState throws");
   Assert.throws(() => ss.getTabState({}),
-    /NS_ERROR_FAILURE/,
+    /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid tab for getTabState throws");
   Assert.throws(() => ss.setTabState({}, "{}"),
-    /NS_ERROR_FAILURE/,
+    /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid tab state for setTabState throws");
   Assert.throws(() => ss.setTabState({}, JSON.stringify({ entries: [] })),
-    /NS_ERROR_FAILURE/,
+    /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid tab for setTabState throws");
   Assert.throws(() => ss.duplicateTab({}, {}),
-    /NS_ERROR_FAILURE/,
+    /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid tab for duplicateTab throws");
   Assert.throws(() => ss.duplicateTab({}, gBrowser.selectedTab),
     /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid window for duplicateTab throws");
   Assert.throws(() => ss.getClosedTabData({}),
     /NS_ERROR_ILLEGAL_VALUE/,
     "Invalid window for getClosedTabData throws");
   Assert.throws(() => ss.undoCloseTab({}, 0),
--- a/browser/components/sessionstore/test/browser_589246.js
+++ b/browser/components/sessionstore/test/browser_589246.js
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-// Mirrors WINDOW_ATTRIBUTES IN nsSessionStore.js
+// Mirrors WINDOW_ATTRIBUTES IN SessionStore.jsm
 const WINDOW_ATTRIBUTES = ["width", "height", "screenX", "screenY", "sizemode"];
 
 var stateBackup = ss.getBrowserState();
 
 var originalWarnOnClose = Services.prefs.getBoolPref("browser.tabs.warnOnClose");
 var originalStartupPage = Services.prefs.getIntPref("browser.startup.page");
 var originalWindowType = document.documentElement.getAttribute("windowtype");
 
@@ -33,17 +33,17 @@ var tests = [];
 
 // the third & fourth test share a condition check, keep it DRY
 function checkOSX34Generator(num) {
   return function(aPreviousState, aCurState) {
     // In here, we should have restored the pinned tab, so only the unpinned tab
     // should be in aCurState. So let's shape our expectations.
     let expectedState = JSON.parse(aPreviousState);
     expectedState[0].tabs.shift();
-    // size attributes are stripped out in _prepDataForDeferredRestore in nsSessionStore.
+    // size attributes are stripped out in _prepDataForDeferredRestore in SessionStore.jsm.
     // This isn't the best approach, but neither is comparing JSON strings
     WINDOW_ATTRIBUTES.forEach(attr => delete expectedState[0][attr]);
 
     is(aCurState, JSON.stringify(expectedState),
        "test #" + num + ": closedWindowState is as expected");
   };
 }
 function checkNoWindowsGenerator(num) {
--- a/browser/components/sessionstore/test/browser_sessionStoreContainer.js
+++ b/browser/components/sessionstore/test/browser_sessionStoreContainer.js
@@ -97,17 +97,16 @@ function waitForNewCookie() {
 
 add_task(async function test() {
   const USER_CONTEXTS = [
     "default",
     "personal",
     "work",
   ];
 
-  const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
   const { TabStateFlusher } = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
 
   // Make sure userContext is enabled.
   await SpecialPowers.pushPrefEnv({
     "set": [ [ "privacy.userContext.enabled", true ] ]
   });
 
   Services.cookies.removeAll();
@@ -128,12 +127,12 @@ add_task(async function test() {
 
     // Ensure the tab's session history is up-to-date.
     await TabStateFlusher.flush(browser);
 
     // Remove the tab.
     gBrowser.removeTab(tab);
   }
 
-  let state = JSON.parse(ss.getBrowserState());
+  let state = JSON.parse(SessionStore.getBrowserState());
   is(state.cookies.length, USER_CONTEXTS.length,
     "session restore should have each container's cookie");
 });
--- a/browser/components/sessionstore/test/head.js
+++ b/browser/components/sessionstore/test/head.js
@@ -20,23 +20,21 @@ for (let script of FRAME_SCRIPTS) {
 }
 
 registerCleanupFunction(() => {
   for (let script of FRAME_SCRIPTS) {
     Services.mm.removeDelayedFrameScript(script, true);
   }
 });
 
-const {SessionStore} = ChromeUtils.import("resource:///modules/sessionstore/SessionStore.jsm", {});
 const {SessionSaver} = ChromeUtils.import("resource:///modules/sessionstore/SessionSaver.jsm", {});
 const {SessionFile} = ChromeUtils.import("resource:///modules/sessionstore/SessionFile.jsm", {});
 const {TabState} = ChromeUtils.import("resource:///modules/sessionstore/TabState.jsm", {});
 const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
-
-const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+const ss = SessionStore;
 
 // Some tests here assume that all restored tabs are loaded without waiting for
 // the user to bring them to the foreground. We ensure this by resetting the
 // related preference (see the "firefox.js" defaults file for details).
 Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", false);
 registerCleanupFunction(function() {
   Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
 });
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -241,19 +241,18 @@
 @RESPATH@/components/nsUpdateTimerManager.manifest
 @RESPATH@/components/nsUpdateTimerManager.js
 @RESPATH@/components/utils.manifest
 @RESPATH@/components/simpleServices.js
 @RESPATH@/components/pluginGlue.manifest
 @RESPATH@/components/ProcessSingleton.manifest
 @RESPATH@/components/MainProcessSingleton.js
 @RESPATH@/components/ContentProcessSingleton.js
-@RESPATH@/browser/components/nsSessionStore.manifest
+@RESPATH@/browser/components/nsSessionStartup.manifest
 @RESPATH@/browser/components/nsSessionStartup.js
-@RESPATH@/browser/components/nsSessionStore.js
 @RESPATH@/components/nsURLFormatter.manifest
 @RESPATH@/components/nsURLFormatter.js
 @RESPATH@/components/txEXSLTRegExFunctions.manifest
 @RESPATH@/components/txEXSLTRegExFunctions.js
 @RESPATH@/components/toolkitplaces.manifest
 @RESPATH@/components/nsLivemarkService.js
 @RESPATH@/components/nsTaggingService.js
 @RESPATH@/components/UnifiedComplete.js
--- a/browser/modules/AboutHome.jsm
+++ b/browser/modules/AboutHome.jsm
@@ -12,16 +12,18 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.defineModuleGetter(this, "AppConstants",
   "resource://gre/modules/AppConstants.jsm");
 ChromeUtils.defineModuleGetter(this, "AutoMigrate",
   "resource:///modules/AutoMigrate.jsm");
 ChromeUtils.defineModuleGetter(this, "fxAccounts",
   "resource://gre/modules/FxAccounts.jsm");
 ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "SessionStore",
+  "resource:///modules/sessionstore/SessionStore.jsm");
 
 // Url to fetch snippets, in the urlFormatter service format.
 const SNIPPETS_URL_PREF = "browser.aboutHomeSnippets.updateUrl";
 
 // Should be bumped up if the snippets content format changes.
 const STARTPAGE_VERSION = 4;
 
 var AboutHomeUtils = {
@@ -103,20 +105,18 @@ var AboutHome = {
   },
 
   // Additional listeners are registered in nsBrowserGlue.js
   receiveMessage(aMessage) {
     let window = aMessage.target.ownerGlobal;
 
     switch (aMessage.name) {
       case "AboutHome:RestorePreviousSession":
-        let ss = Cc["@mozilla.org/browser/sessionstore;1"].
-                 getService(Ci.nsISessionStore);
-        if (ss.canRestoreLastSession) {
-          ss.restoreLastSession();
+        if (SessionStore.canRestoreLastSession) {
+          SessionStore.restoreLastSession();
         }
         break;
 
       case "AboutHome:Downloads":
         window.BrowserDownloadsUI();
         break;
 
       case "AboutHome:Bookmarks":
@@ -151,24 +151,19 @@ var AboutHome = {
         });
         break;
     }
   },
 
   // Send all the chrome-privileged data needed by about:home. This
   // gets re-sent when the search engine changes.
   sendAboutHomeData(target) {
-    let wrapper = {};
-    ChromeUtils.import("resource:///modules/sessionstore/SessionStore.jsm",
-      wrapper);
-    let ss = wrapper.SessionStore;
-
-    ss.promiseInitialized.then(function() {
+    SessionStore.promiseInitialized.then(function() {
       let data = {
-        showRestoreLastSession: ss.canRestoreLastSession,
+        showRestoreLastSession: SessionStore.canRestoreLastSession,
         snippetsURL: AboutHomeUtils.snippetsURL,
         showKnowYourRights: AboutHomeUtils.showKnowYourRights,
         snippetsVersion: AboutHomeUtils.snippetsVersion,
       };
 
       if (AboutHomeUtils.showKnowYourRights) {
         // Set pref to indicate we've shown the notification.
         let currentVersion = Services.prefs.getIntPref("browser.rights.version");
--- a/devtools/client/responsive.html/test/browser/browser_hide_container.js
+++ b/devtools/client/responsive.html/test/browser/browser_hide_container.js
@@ -5,18 +5,16 @@
 
 // Ensure that the RDM container tab URL is not recorded in session history.
 
 const TEST_URL = "http://example.com/";
 const CONTAINER_URL = "chrome://devtools/content/responsive.html/index.xhtml";
 
 const { TabStateFlusher } =
   ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
-const SessionStore =
-  Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 const { OUTER_FRAME_LOADER_SYMBOL } =
   require("devtools/client/responsive.html/browser/tunnel");
 
 function flushContainerTabState(tab) {
   let browser = tab.linkedBrowser;
   let outerBrowser = {
     permanentKey: browser.permanentKey,
     messageManager: browser[OUTER_FRAME_LOADER_SYMBOL].messageManager,
--- a/devtools/client/scratchpad/test/browser_scratchpad_sessions.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_sessions.js
@@ -1,15 +1,14 @@
  /* Any copyright is dedicated to the Public Domain.
     http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm", {});
 const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
-const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
 const testState = {
   windows: [{
     tabs: [
       { entries: [{ url: "about:blank", triggeringPrincipal_base64 }] },
     ]
   }],
   scratchpads: [
@@ -32,17 +31,17 @@ function addState(state) {
   }
 }
 
 function test() {
   waitForExplicitFinish();
 
   Services.ww.registerNotification(windowObserver);
 
-  ss.setBrowserState(JSON.stringify(testState));
+  SessionStore.setBrowserState(JSON.stringify(testState));
 }
 
 function windowObserver(subject, topic, data) {
   if (topic == "domwindowopened") {
     let win = subject.QueryInterface(Ci.nsIDOMWindow);
     win.addEventListener("load", function () {
       if (win.Scratchpad) {
         win.Scratchpad.addObserver({