Bug 1369456 - Replace nsSessionStartup.js with SessionStartup.jsm. draft
authorDão Gottwald <dao@mozilla.com>
Sat, 04 Aug 2018 13:27:40 +0200
changeset 826557 35d235189a9160362c869da0ac709a81c2a71b3d
parent 826542 4e56a2f51ad739ca52046723448f3129a58f1666
push id118365
push userdgottwald@mozilla.com
push dateSat, 04 Aug 2018 11:28:10 +0000
bugs1369456
milestone63.0a1
Bug 1369456 - Replace nsSessionStartup.js with SessionStartup.jsm. MozReview-Commit-ID: 53Mu4zb9X1C
browser/base/content/browser.js
browser/base/content/test/performance/browser_startup.js
browser/components/nsBrowserContentHandler.js
browser/components/nsBrowserGlue.js
browser/components/sessionstore/SessionFile.jsm
browser/components/sessionstore/SessionStartup.jsm
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/moz.build
browser/components/sessionstore/nsISessionStartup.idl
browser/components/sessionstore/nsSessionStartup.js
browser/components/sessionstore/nsSessionStartup.manifest
browser/components/sessionstore/test/unit/head.js
browser/components/sessionstore/test/unit/test_startup_invalid_session.js
browser/components/sessionstore/test/unit/test_startup_nosession_async.js
browser/components/sessionstore/test/unit/test_startup_session_async.js
browser/installer/package-manifest.in
python/mozbuild/mozbuild/test/codecoverage/test_lcov_rewrite.py
testing/talos/talos/startup_test/sessionrestore/addon/bootstrap.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -48,16 +48,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
   PluralForm: "resource://gre/modules/PluralForm.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
   PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
   ReaderMode: "resource://gre/modules/ReaderMode.jsm",
   ReaderParent: "resource:///modules/ReaderParent.jsm",
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
+  SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   SchedulePressure: "resource:///modules/SchedulePressure.jsm",
   ShortcutUtils: "resource://gre/modules/ShortcutUtils.jsm",
   SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm",
   SiteDataManager: "resource:///modules/SiteDataManager.jsm",
   SitePermissions: "resource:///modules/SitePermissions.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
@@ -136,17 +137,16 @@ if (AppConstants.NIGHTLY_BUILD) {
 // lazy service getters
 
 XPCOMUtils.defineLazyServiceGetters(this, {
   Favicons: ["@mozilla.org/browser/favicon-service;1", "nsIFaviconService"],
   gAboutNewTabService: ["@mozilla.org/browser/aboutnewtab-service;1", "nsIAboutNewTabService"],
   gDNSService: ["@mozilla.org/network/dns-service;1", "nsIDNSService"],
   gSerializationHelper: ["@mozilla.org/network/serialization-helper;1", "nsISerializationHelper"],
   Marionette: ["@mozilla.org/remote/marionette;1", "nsIMarionette"],
-  SessionStartup: ["@mozilla.org/browser/sessionstartup;1", "nsISessionStartup"],
   WindowsUIUtils: ["@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils"],
 });
 
 if (AppConstants.MOZ_CRASHREPORTER) {
   XPCOMUtils.defineLazyServiceGetter(this, "gCrashReporter",
                                      "@mozilla.org/xre/app-info;1",
                                      "nsICrashReporter");
 }
--- a/browser/base/content/test/performance/browser_startup.js
+++ b/browser/base/content/test/performance/browser_startup.js
@@ -26,17 +26,16 @@ const startupPhases = {
   // Consider loading your code after first paint instead,
   // eg. from nsBrowserGlue.js' _onFirstWindowLoaded method).
   "before profile selection": {whitelist: {
     components: new Set([
       "nsBrowserGlue.js",
       "MainProcessSingleton.js",
 
       // Bugs to fix: The following components shouldn't be initialized that early.
-      "nsSessionStartup.js", // bug 1369456
       "PushComponents.js", // bug 1369436
     ]),
     modules: new Set([
       "resource://gre/modules/AppConstants.jsm",
       "resource://gre/modules/XPCOMUtils.jsm",
       "resource://gre/modules/Services.jsm",
     ])
   }},
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -7,16 +7,17 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
   HeadlessShell: "resource:///modules/HeadlessShell.jsm",
   HomePage: "resource:///modules/HomePage.jsm",
   LaterRun: "resource:///modules/LaterRun.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
+  SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   ShellService: "resource:///modules/ShellService.jsm",
   UpdatePing: "resource://gre/modules/UpdatePing.jsm"
 });
 XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils",
   "@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
 
 function shouldLoadURI(aURI) {
   if (aURI && !aURI.schemeIs("chrome"))
@@ -505,19 +506,17 @@ nsBrowserContentHandler.prototype = {
             LaterRun.enabled = true;
             break;
           case OVERRIDE_NEW_MSTONE:
             // Check whether we will restore a session. If we will, we assume
             // that this is an "update" session. This does not take crashes
             // into account because that requires waiting for the session file
             // to be read. If a crash occurs after updating, before restarting,
             // we may open the startPage in addition to restoring the session.
-            var ss = Cc["@mozilla.org/browser/sessionstartup;1"]
-                       .getService(Ci.nsISessionStartup);
-            willRestoreSession = ss.isAutomaticRestoreEnabled();
+            willRestoreSession = SessionStartup.isAutomaticRestoreEnabled();
 
             overridePage = Services.urlFormatter.formatURLPref("startup.homepage_override_url");
             if (prefb.prefHasUserValue("app.update.postupdate")) {
               overridePage = getPostUpdateOverridePage(overridePage);
               // Send the update ping to signal that the update was successful.
               UpdatePing.handleUpdateSuccess(old_mstone, old_buildId);
             }
 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -127,16 +127,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
   ProcessHangMonitor: "resource:///modules/ProcessHangMonitor.jsm",
   ReaderParent: "resource:///modules/ReaderParent.jsm",
   RemotePrompt: "resource:///modules/RemotePrompt.jsm",
   RemoteSettings: "resource://services-settings/remote-settings.js",
   SafeBrowsing: "resource://gre/modules/SafeBrowsing.jsm",
   Sanitizer: "resource:///modules/Sanitizer.jsm",
   SavantShieldStudy: "resource:///modules/SavantShieldStudy.jsm",
+  SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
   ShellService: "resource:///modules/ShellService.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   UIState: "resource://services-sync/UIState.jsm",
   UITour: "resource:///modules/UITour.jsm",
   WebChannel: "resource://gre/modules/WebChannel.jsm",
   WindowsRegistry: "resource://gre/modules/WindowsRegistry.jsm",
 });
@@ -697,16 +698,18 @@ BrowserGlue.prototype = {
     os.removeObserver(this, "xpi-signature-changed");
     os.removeObserver(this, "sync-ui-state:update");
     os.removeObserver(this, "shield-init-complete");
   },
 
   // runs on startup, before the first command line handler is invoked
   // (i.e. before the first window is opened)
   _beforeUIStartup: function BG__beforeUIStartup() {
+    SessionStartup.init();
+
     // check if we're in safe mode
     if (Services.appinfo.inSafeMode) {
       Services.ww.openWindow(null, "chrome://browser/content/safeMode.xul",
                              "_blank", "chrome,centerscreen,modal,resizable=no", null);
     }
 
     // apply distribution customizations
     this._distributionCustomizer.applyCustomizations();
@@ -2155,23 +2158,18 @@ BrowserGlue.prototype = {
     const skipDefaultBrowserCheck =
       Services.prefs.getBoolPref("browser.shell.skipDefaultBrowserCheckOnFirstRun") &&
       !Services.prefs.getBoolPref("browser.shell.didSkipDefaultBrowserCheckOnFirstRun");
 
     const usePromptLimit = !AppConstants.RELEASE_OR_BETA;
     let promptCount =
       usePromptLimit ? Services.prefs.getIntPref("browser.shell.defaultBrowserCheckCount") : 0;
 
-    let willRecoverSession = false;
-    try {
-      let ss = Cc["@mozilla.org/browser/sessionstartup;1"].
-               getService(Ci.nsISessionStartup);
-      willRecoverSession =
-        (ss.sessionType == Ci.nsISessionStartup.RECOVER_SESSION);
-    } catch (ex) { /* never mind; suppose SessionStore is broken */ }
+    let willRecoverSession =
+      (SessionStartup.sessionType == SessionStartup.RECOVER_SESSION);
 
     // startup check, check all assoc
     let isDefault = false;
     let isDefaultError = false;
     try {
       isDefault = ShellService.isDefaultBrowser(true, false);
     } catch (ex) {
       isDefaultError = true;
--- a/browser/components/sessionstore/SessionFile.jsm
+++ b/browser/components/sessionstore/SessionFile.jsm
@@ -25,26 +25,25 @@ var EXPORTED_SYMBOLS = ["SessionFile"];
  * This implementation uses OS.File, which guarantees property 1.
  */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/osfile.jsm");
 ChromeUtils.import("resource://gre/modules/AsyncShutdown.jsm");
 
-ChromeUtils.defineModuleGetter(this, "RunState",
-  "resource:///modules/sessionstore/RunState.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
   "@mozilla.org/base/telemetry;1", "nsITelemetry");
-XPCOMUtils.defineLazyServiceGetter(this, "sessionStartup",
-  "@mozilla.org/browser/sessionstartup;1", "nsISessionStartup");
-ChromeUtils.defineModuleGetter(this, "SessionWorker",
-  "resource:///modules/sessionstore/SessionWorker.jsm");
-ChromeUtils.defineModuleGetter(this, "SessionStore",
-  "resource:///modules/sessionstore/SessionStore.jsm");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  RunState: "resource:///modules/sessionstore/RunState.jsm",
+  SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
+  SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
+  SessionWorker: "resource:///modules/sessionstore/SessionWorker.jsm",
+});
 
 const PREF_UPGRADE_BACKUP = "browser.sessionstore.upgradeBackup.latestBuildID";
 const PREF_MAX_UPGRADE_BACKUPS = "browser.sessionstore.upgradeBackup.maxUpgradeBackups";
 
 const PREF_MAX_SERIALIZE_BACK = "browser.sessionstore.max_serialize_back";
 const PREF_MAX_SERIALIZE_FWD = "browser.sessionstore.max_serialize_forward";
 
 XPCOMUtils.defineLazyPreferenceGetter(this, "kMaxWriteFailures",
@@ -379,17 +378,17 @@ var SessionFileInternal = {
     if (RunState.isClosing) {
       // If shutdown has started, we will want to stop receiving
       // write instructions.
       isFinalWrite = true;
       RunState.setClosed();
     }
 
     let performShutdownCleanup = isFinalWrite &&
-      !sessionStartup.isAutomaticRestoreEnabled();
+      !SessionStartup.isAutomaticRestoreEnabled();
 
     this._attempts++;
     let options = {isFinalWrite, performShutdownCleanup};
     let promise = this._postToWorker("write", [aData, options]);
 
     // Wait until the write is done.
     promise = promise.then(msg => {
       // Record how long the write took.
rename from browser/components/sessionstore/nsSessionStartup.js
rename to browser/components/sessionstore/SessionStartup.jsm
--- a/browser/components/sessionstore/nsSessionStartup.js
+++ b/browser/components/sessionstore/SessionStartup.jsm
@@ -24,39 +24,41 @@
  * installation, set the browser.sessionstore.resume_session_once pref to true,
  * and the session will be restored the next time the browser starts.
  *
  * Always Resume
  * This service will always resume the session if the integer pref
  * browser.startup.page is set to 3.
  */
 
+var EXPORTED_SYMBOLS = ["SessionStartup"];
+
 /* :::::::: Constants and Helpers ::::::::::::::: */
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 ChromeUtils.defineModuleGetter(this, "SessionFile",
   "resource:///modules/sessionstore/SessionFile.jsm");
 ChromeUtils.defineModuleGetter(this, "StartupPerformance",
   "resource:///modules/sessionstore/StartupPerformance.jsm");
 ChromeUtils.defineModuleGetter(this, "CrashMonitor",
   "resource://gre/modules/CrashMonitor.jsm");
 ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 const STATE_RUNNING_STR = "running";
 
+const TYPE_NO_SESSION = 0;
+const TYPE_RECOVER_SESSION = 1;
+const TYPE_RESUME_SESSION = 2;
+const TYPE_DEFER_SESSION = 3;
+
 // 'browser.startup.page' preference value to resume the previous session.
 const BROWSER_STARTUP_RESUME_SESSION = 3;
 
-function debug(aMsg) {
-  aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
-  Services.console.logStringMessage(aMsg);
-}
 function warning(aMsg, aException) {
   let consoleMsg = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);
 consoleMsg.init(aMsg, aException.fileName, null, aException.lineNumber, 0, Ci.nsIScriptError.warningFlag, "component javascript");
   Services.console.logMessage(consoleMsg);
 }
 
 var gOnceInitializedDeferred = (function() {
   let deferred = {};
@@ -66,24 +68,25 @@ var gOnceInitializedDeferred = (function
     deferred.reject = reject;
   });
 
   return deferred;
 })();
 
 /* :::::::: The Service ::::::::::::::: */
 
-function SessionStartup() {
-}
-
-SessionStartup.prototype = {
+var SessionStartup = {
+  NO_SESSION: TYPE_NO_SESSION,
+  RECOVER_SESSION: TYPE_RECOVER_SESSION,
+  RESUME_SESSION: TYPE_RESUME_SESSION,
+  DEFER_SESSION: TYPE_DEFER_SESSION,
 
   // the state to restore at startup
   _initialState: null,
-  _sessionType: Ci.nsISessionStartup.NO_SESSION,
+  _sessionType: TYPE_NO_SESSION,
   _initialized: false,
 
   // Stores whether the previous session crashed.
   _previousSessionCrashed: null,
 
   _resumeSessionEnabled: null,
 
 /* ........ Global Event Handlers .............. */
@@ -156,17 +159,17 @@ SessionStartup.prototype = {
       }
     } else {
       // No need to reparse
       this._initialState = parsed;
     }
 
     if (this._initialState == null) {
       // No valid session found.
-      this._sessionType = Ci.nsISessionStartup.NO_SESSION;
+      this._sessionType = this.NO_SESSION;
       Services.obs.notifyObservers(null, "sessionstore-state-finalized");
       gOnceInitializedDeferred.resolve();
       return;
     }
 
     let initialState = this._initialState;
     Services.tm.idleDispatchToMainThread(() => {
       let pinnedTabCount = initialState.windows.reduce((winAcc, win) => {
@@ -217,66 +220,50 @@ SessionStartup.prototype = {
 
       // Report shutdown success via telemetry. Shortcoming here are
       // being-killed-by-OS-shutdown-logic, shutdown freezing after
       // session restore was written, etc.
       Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!this._previousSessionCrashed);
 
       // set the startup type
       if (this._previousSessionCrashed && resumeFromCrash)
-        this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
+        this._sessionType = this.RECOVER_SESSION;
       else if (!this._previousSessionCrashed && this._resumeSessionEnabled)
-        this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
+        this._sessionType = this.RESUME_SESSION;
       else if (this._initialState)
-        this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
+        this._sessionType = this.DEFER_SESSION;
       else
         this._initialState = null; // reset the state
-
       Services.obs.addObserver(this, "sessionstore-windows-restored", true);
 
-      if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
+      if (this._sessionType != this.NO_SESSION)
         Services.obs.addObserver(this, "browser:purge-session-history", true);
 
       // We're ready. Notify everyone else.
       Services.obs.notifyObservers(null, "sessionstore-state-finalized");
+
       gOnceInitializedDeferred.resolve();
     });
   },
 
   /**
    * Handle notifications
    */
   observe: function sss_observe(aSubject, aTopic, aData) {
     switch (aTopic) {
-    case "app-startup":
-      Services.obs.addObserver(this, "final-ui-startup", true);
-      Services.obs.addObserver(this, "quit-application", true);
-      break;
-    case "final-ui-startup":
-      Services.obs.removeObserver(this, "final-ui-startup");
-      Services.obs.removeObserver(this, "quit-application");
-      this.init();
-      break;
-    case "quit-application":
-      // no reason for initializing at this point (cf. bug 409115)
-      Services.obs.removeObserver(this, "final-ui-startup");
-      Services.obs.removeObserver(this, "quit-application");
-      if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
-        Services.obs.removeObserver(this, "browser:purge-session-history");
-      break;
     case "sessionstore-windows-restored":
       Services.obs.removeObserver(this, "sessionstore-windows-restored");
       // free _initialState after nsSessionStore is done with it
       this._initialState = null;
       this._didRestore = true;
       break;
     case "browser:purge-session-history":
       Services.obs.removeObserver(this, "browser:purge-session-history");
       // reset all state on sanitization
-      this._sessionType = Ci.nsISessionStartup.NO_SESSION;
+      this._sessionType = this.NO_SESSION;
       break;
     }
   },
 
 /* ........ Public API ................*/
 
   get onceInitialized() {
     return gOnceInitializedDeferred.promise;
@@ -314,18 +301,18 @@ SessionStartup.prototype = {
            Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION;
   },
 
   /**
    * Determines whether there is a pending session restore.
    * @returns bool
    */
   _willRestore() {
-    return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
-           this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
+    return this._sessionType == this.RECOVER_SESSION ||
+           this._sessionType == this.RESUME_SESSION;
   },
 
   /**
    * Returns a boolean or a promise that resolves to a boolean, indicating
    * whether we will restore a session that ends up replacing the homepage.
    * True guarantees that we'll restore a session; false means that we
    * /probably/ won't do so.
    * The browser uses this to avoid unnecessarily loading the homepage when
@@ -366,16 +353,12 @@ SessionStartup.prototype = {
 
   /**
    * Get whether the previous session crashed.
    */
   get previousSessionCrashed() {
     return this._previousSessionCrashed;
   },
 
-  /* ........ QueryInterface .............. */
   QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver,
-                                          Ci.nsISupportsWeakReference,
-                                          Ci.nsISessionStartup]),
-  classID: Components.ID("{ec7a6c20-e081-11da-8ad9-0800200c9a66}")
+                                          Ci.nsISupportsWeakReference]),
 };
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SessionStartup]);
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -158,17 +158,16 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/Services.jsm", this);
 ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
 ChromeUtils.import("resource://gre/modules/TelemetryTimestamps.jsm", this);
 ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
 ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
 
 XPCOMUtils.defineLazyServiceGetters(this, {
-  gSessionStartup: ["@mozilla.org/browser/sessionstartup;1", "nsISessionStartup"],
   gScreenManager: ["@mozilla.org/gfx/screenmanager;1", "nsIScreenManager"],
   Telemetry: ["@mozilla.org/base/telemetry;1", "nsITelemetry"],
 });
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   AppConstants: "resource://gre/modules/AppConstants.jsm",
   AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
   BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
@@ -176,16 +175,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
   GlobalState: "resource:///modules/sessionstore/GlobalState.jsm",
   HomePage: "resource:///modules/HomePage.jsm",
   PrivacyFilter: "resource://gre/modules/sessionstore/PrivacyFilter.jsm",
   PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
   RunState: "resource:///modules/sessionstore/RunState.jsm",
   SessionCookies: "resource:///modules/sessionstore/SessionCookies.jsm",
   SessionFile: "resource:///modules/sessionstore/SessionFile.jsm",
   SessionSaver: "resource:///modules/sessionstore/SessionSaver.jsm",
+  SessionStartup: "resource:///modules/sessionstore/SessionStartup.jsm",
   TabAttributes: "resource:///modules/sessionstore/TabAttributes.jsm",
   TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
   TabState: "resource:///modules/sessionstore/TabState.jsm",
   TabStateCache: "resource:///modules/sessionstore/TabStateCache.jsm",
   TabStateFlusher: "resource:///modules/sessionstore/TabStateFlusher.jsm",
   Utils: "resource://gre/modules/sessionstore/Utils.jsm",
   ViewSourceBrowser: "resource://gre/modules/ViewSourceBrowser.jsm",
   setTimeout: "resource://gre/modules/Timer.jsm",
@@ -634,28 +634,28 @@ var SessionStoreInternal = {
   },
 
   /**
    * Initialize the session using the state provided by SessionStartup
    */
   initSession() {
     TelemetryStopwatch.start("FX_SESSION_RESTORE_STARTUP_INIT_SESSION_MS");
     let state;
-    let ss = gSessionStartup;
+    let ss = SessionStartup;
 
     if (ss.doRestore() ||
-        ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
+        ss.sessionType == ss.DEFER_SESSION) {
       state = ss.state;
     }
 
     if (state) {
       try {
         // If we're doing a DEFERRED session, then we want to pull pinned tabs
         // out so they can be restored.
-        if (ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
+        if (ss.sessionType == ss.DEFER_SESSION) {
           let [iniState, remainingState] = this._prepDataForDeferredRestore(state);
           // If we have a iniState with windows, that means that we have windows
           // with app tabs to restore.
           if (iniState.windows.length) {
             // Move cookies over from the remaining state so that they're
             // restored right away, and pinned tabs will load correctly.
             iniState.cookies = remainingState.cookies;
             delete remainingState.cookies;
@@ -1154,17 +1154,17 @@ var SessionStoreInternal = {
         // Don't write to disk right after startup. Set the last time we wrote
         // to disk to NOW() to enforce a full interval before the next write.
         SessionSaver.updateLastSaveTime();
 
         if (isPrivateWindow) {
           // We're starting with a single private window. Save the state we
           // actually wanted to restore so that we can do it later in case
           // the user opens another, non-private window.
-          this._deferredInitialState = gSessionStartup.state;
+          this._deferredInitialState = SessionStartup.state;
 
           // Nothing to restore now, notify observers things are complete.
           Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED);
           Services.obs.notifyObservers(null, "sessionstore-one-or-no-tab-restored");
           this._deferredAllWindowsRestored.resolve();
         } else {
           TelemetryTimestamps.add("sessionRestoreRestoring");
           this._restoreCount = aInitialState.windows ? aInitialState.windows.length : 0;
@@ -1305,17 +1305,17 @@ var SessionStoreInternal = {
             resolve();
           }
         }, "browser-delayed-startup-finished");
       });
 
       // We are ready for initialization as soon as the session file has been
       // read from disk and the initial window's delayed startup has finished.
       this._promiseReadyForInitialization =
-        Promise.all([promise, gSessionStartup.onceInitialized]);
+        Promise.all([promise, SessionStartup.onceInitialized]);
     }
 
     // We can't call this.onLoad since initialization
     // hasn't completed, so we'll wait until it is done.
     // Even if additional windows are opened and wait
     // for initialization as well, the first opened
     // window should execute first, and this.onLoad
     // will be called with the initialState.
@@ -4580,33 +4580,33 @@ var SessionStoreInternal = {
             aTabState.attributes.customizemode == "true") ||
            (aTabState.entries.length &&
             !(aTabState.entries[0].url == "about:printpreview" ||
               aTabState.entries[0].url == "about:privatebrowsing"));
   },
 
   /**
    * This is going to take a state as provided at startup (via
-   * nsISessionStartup.state) and split it into 2 parts. The first part
+   * SessionStartup.state) and split it into 2 parts. The first part
    * (defaultState) will be a state that should still be restored at startup,
    * while the second part (state) is a state that should be saved for later.
    * defaultState will be comprised of windows with only pinned tabs, extracted
    * from state. It will also contain window position information.
    *
    * defaultState will be restored at startup. state will be passed into
    * LastSession and will be kept in case the user explicitly wants
    * to restore the previous session (publicly exposed as restoreLastSession).
    *
    * @param state
-   *        The state, presumably from nsISessionStartup.state
+   *        The state, presumably from SessionStartup.state
    * @returns [defaultState, state]
    */
   _prepDataForDeferredRestore: function ssi_prepDataForDeferredRestore(state) {
     // Make sure that we don't modify the global state as provided by
-    // nsSessionStartup.state.
+    // SessionStartup.state.
     state = Cu.cloneInto(state, {});
 
     let defaultState = { windows: [], selectedWindow: 1 };
 
     state.selectedWindow = state.selectedWindow || 1;
 
     // Look at each window, remove pinned tabs, adjust selectedindex,
     // remove window if necessary.
--- a/browser/components/sessionstore/moz.build
+++ b/browser/components/sessionstore/moz.build
@@ -4,38 +4,28 @@
 # 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
 BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
 
 JAR_MANIFESTS += ['jar.mn']
 
-XPIDL_SOURCES += [
-    'nsISessionStartup.idl',
-]
-
-XPIDL_MODULE = 'sessionstore'
-
-EXTRA_COMPONENTS += [
-    'nsSessionStartup.js',
-    'nsSessionStartup.manifest',
-]
-
 EXTRA_JS_MODULES.sessionstore = [
     'ContentRestore.jsm',
     'ContentSessionStore.jsm',
     'DocShellCapabilities.jsm',
     'GlobalState.jsm',
     'RecentlyClosedTabsAndWindowsMenuUtils.jsm',
     'RunState.jsm',
     'SessionCookies.jsm',
     'SessionFile.jsm',
     'SessionMigration.jsm',
     'SessionSaver.jsm',
+    'SessionStartup.jsm',
     'SessionStorage.jsm',
     'SessionStore.jsm',
     'SessionWorker.js',
     'SessionWorker.jsm',
     'StartupPerformance.jsm',
     'TabAttributes.jsm',
     'TabState.jsm',
     'TabStateCache.jsm',
deleted file mode 100644
--- a/browser/components/sessionstore/nsISessionStartup.idl
+++ /dev/null
@@ -1,64 +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"
-
-/**
- * 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 window.
- */
-
-[scriptable, uuid(934697e4-3807-47f8-b6c9-6caa8d83ccd1)]
-interface nsISessionStartup: nsISupports
-{
-  /**
-   * Return a promise that is resolved once initialization
-   * is complete.
-   */
-  readonly attribute jsval onceInitialized;
-
-  // Get session state
-  readonly attribute jsval state;
-
-  /**
-   * Determines whether there is a pending session restore. Should only be
-   * called after initialization has completed.
-   */
-  boolean doRestore();
-
-  /**
-   * Determines whether automatic session restoration is enabled for this
-   * launch of the browser. This does not include crash restoration, and will
-   * return false if restoration will only be caused by a crash.
-   */
-  boolean isAutomaticRestoreEnabled();
-
-  /**
-   * Returns a boolean or a promise that resolves to a boolean, indicating
-   * whether we will restore a session that ends up replacing the homepage.
-   * True guarantees that we'll restore a session; false means that we
-   * /probably/ won't do so.
-   * The browser uses this to avoid unnecessarily loading the homepage when
-   * restoring a session.
-   */
-  readonly attribute jsval willOverrideHomepage;
-
-  /**
-   * What type of session we're restoring.
-   * NO_SESSION       There is no data available from the previous session
-   * RECOVER_SESSION  The last session crashed. It will either be restored or
-   *                  about:sessionrestore will be shown.
-   * RESUME_SESSION   The previous session should be restored at startup
-   * DEFER_SESSION    The previous session is fine, but it shouldn't be restored
-   *                  without explicit action (with the exception of pinned tabs)
-   */
-  const unsigned long NO_SESSION = 0;
-  const unsigned long RECOVER_SESSION = 1;
-  const unsigned long RESUME_SESSION = 2;
-  const unsigned long DEFER_SESSION = 3;
-
-  readonly attribute unsigned long sessionType;
-  readonly attribute bool previousSessionCrashed;
-};
deleted file mode 100644
--- a/browser/components/sessionstore/nsSessionStartup.manifest
+++ /dev/null
@@ -1,10 +0,0 @@
-# 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 {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}
--- a/browser/components/sessionstore/test/unit/head.js
+++ b/browser/components/sessionstore/test/unit/head.js
@@ -1,36 +1,34 @@
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm", {});
+ChromeUtils.defineModuleGetter(this, "SessionStartup",
+  "resource:///modules/sessionstore/SessionStartup.jsm");
 
 // Call a function once initialization of SessionStartup is complete
 function afterSessionStartupInitialization(cb) {
   info("Waiting for session startup initialization");
   let observer = function() {
     try {
       info("Session startup initialization observed");
       Services.obs.removeObserver(observer, "sessionstore-state-finalized");
       cb();
     } catch (ex) {
       do_throw(ex);
     }
   };
+  Services.obs.addObserver(observer, "sessionstore-state-finalized");
 
   // We need the Crash Monitor initialized for sessionstartup to run
   // successfully.
   ChromeUtils.import("resource://gre/modules/CrashMonitor.jsm");
   CrashMonitor.init();
 
   // Start sessionstartup initialization.
-  let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
-    getService(Ci.nsIObserver);
-  Services.obs.addObserver(startup, "final-ui-startup");
-  Services.obs.addObserver(startup, "quit-application");
-  Services.obs.notifyObservers(null, "final-ui-startup");
-  Services.obs.addObserver(observer, "sessionstore-state-finalized");
+  SessionStartup.init();
 }
 
 // Compress the source file using lz4 and put the result to destination file.
 // After that, source file is deleted.
 async function writeCompressedFile(source, destination) {
   let s = await OS.File.read(source);
   await OS.File.writeAtomic(destination, s, {compression: "lz4"});
   await OS.File.remove(source);
--- a/browser/components/sessionstore/test/unit/test_startup_invalid_session.js
+++ b/browser/components/sessionstore/test/unit/test_startup_invalid_session.js
@@ -10,19 +10,16 @@ function run_test() {
 
   let sourceCheckpoints = do_get_file("data/sessionCheckpoints_all.json");
   sourceCheckpoints.copyTo(profd, "sessionCheckpoints.json");
 
   // Compress sessionstore.js to sessionstore.jsonlz4
   // and remove sessionstore.js
   let oldExtSessionFile = SessionFile.Paths.clean.replace("jsonlz4", "js");
   writeCompressedFile(oldExtSessionFile, SessionFile.Paths.clean).then(() => {
-    let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
-        getService(Ci.nsISessionStartup);
-
     afterSessionStartupInitialization(function cb() {
-      Assert.equal(startup.sessionType, Ci.nsISessionStartup.NO_SESSION);
+      Assert.equal(SessionStartup.sessionType, SessionStartup.NO_SESSION);
       do_test_finished();
     });
   });
 
   do_test_pending();
 }
--- a/browser/components/sessionstore/test/unit/test_startup_nosession_async.js
+++ b/browser/components/sessionstore/test/unit/test_startup_nosession_async.js
@@ -1,22 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 
-// Test nsISessionStartup.sessionType in the following scenario:
+// Test SessionStartup.sessionType in the following scenario:
 // - no sessionstore.js;
 // - the session store has been loaded, so no need to go
 //    through the synchronous fallback
 
 function run_test() {
+  // Initialize the profile (the session startup uses it)
   do_get_profile();
-  // Initialize the profile (the session startup uses it)
 
   do_test_pending();
-  let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
-    getService(Ci.nsISessionStartup);
 
   afterSessionStartupInitialization(function cb() {
-    Assert.equal(startup.sessionType, Ci.nsISessionStartup.NO_SESSION);
+    Assert.equal(SessionStartup.sessionType, SessionStartup.NO_SESSION);
     do_test_finished();
   });
 }
--- a/browser/components/sessionstore/test/unit/test_startup_session_async.js
+++ b/browser/components/sessionstore/test/unit/test_startup_session_async.js
@@ -1,13 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 
-// Test nsISessionStartup.sessionType in the following scenario:
+// Test SessionStartup.sessionType in the following scenario:
 // - valid sessionstore.js;
 // - valid sessionCheckpoints.json with all checkpoints;
 // - the session store has been loaded
 
 function run_test() {
   let profd = do_get_profile();
   var SessionFile = ChromeUtils.import("resource:///modules/sessionstore/SessionFile.jsm", {}).SessionFile;
 
@@ -16,19 +16,16 @@ function run_test() {
 
   let sourceCheckpoints = do_get_file("data/sessionCheckpoints_all.json");
   sourceCheckpoints.copyTo(profd, "sessionCheckpoints.json");
 
   // Compress sessionstore.js to sessionstore.jsonlz4
   // and remove sessionstore.js
   let oldExtSessionFile = SessionFile.Paths.clean.replace("jsonlz4", "js");
   writeCompressedFile(oldExtSessionFile, SessionFile.Paths.clean).then(() => {
-    let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
-        getService(Ci.nsISessionStartup);
-
     afterSessionStartupInitialization(function cb() {
-      Assert.equal(startup.sessionType, Ci.nsISessionStartup.DEFER_SESSION);
+      Assert.equal(SessionStartup.sessionType, SessionStartup.DEFER_SESSION);
       do_test_finished();
     });
   });
 
   do_test_pending();
 }
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -237,18 +237,16 @@
 @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/nsSessionStartup.manifest
-@RESPATH@/browser/components/nsSessionStartup.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/python/mozbuild/mozbuild/test/codecoverage/test_lcov_rewrite.py
+++ b/python/mozbuild/mozbuild/test/codecoverage/test_lcov_rewrite.py
@@ -284,17 +284,17 @@ class TestUrlFinder(unittest.TestCase):
             {
                 'chrome://global/content/netError.xhtml': 'chrome://browser/content/aboutNetError.xhtml',
             },
             {
                 'dist/bin/components/MainProcessSingleton.js': [
                     'path1',
                     None
                 ],
-                'dist/bin/browser/components/nsSessionStartup.js': [
+                'dist/bin/browser/components/nsBrowserGlue.js': [
                     'path2',
                     None
                 ],
                 'dist/bin/browser/features/firefox@getpocket.com/bootstrap.js': [
                     'path4',
                     None
                 ],
                 'dist/bin/modules/osfile/osfile_async_worker.js': [
@@ -329,17 +329,17 @@ class TestUrlFinder(unittest.TestCase):
             shutil.move(self._old_chrome_info_file, self._chrome_map_file)
 
     def test_jar_paths(self):
         app_name = buildconfig.substs.get('MOZ_APP_NAME')
         omnijar_name = buildconfig.substs.get('OMNIJAR_NAME')
 
         paths = [
             ('jar:file:///home/worker/workspace/build/application/' + app_name + '/' + omnijar_name + '!/components/MainProcessSingleton.js', 'path1'),
-            ('jar:file:///home/worker/workspace/build/application/' + app_name + '/browser/' + omnijar_name + '!/components/nsSessionStartup.js', 'path2'),
+            ('jar:file:///home/worker/workspace/build/application/' + app_name + '/browser/' + omnijar_name + '!/components/nsBrowserGlue.js', 'path2'),
             ('jar:file:///home/worker/workspace/build/application/' + app_name + '/browser/features/firefox@getpocket.com.xpi!/bootstrap.js', 'path4'),
         ]
 
         url_finder = lcov_rewriter.UrlFinder(self._chrome_map_file, '', '', [])
         for path, expected in paths:
             self.assertEqual(url_finder.rewrite_url(path)[0], expected)
 
     def test_wrong_scheme_paths(self):
--- a/testing/talos/talos/startup_test/sessionrestore/addon/bootstrap.js
+++ b/testing/talos/talos/startup_test/sessionrestore/addon/bootstrap.js
@@ -1,22 +1,22 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80 filetype=javascript: */
 /* 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";
 
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
 ChromeUtils.defineModuleGetter(this, "Services",
   "resource://gre/modules/Services.jsm");
 ChromeUtils.defineModuleGetter(this, "setTimeout",
   "resource://gre/modules/Timer.jsm");
+ChromeUtils.defineModuleGetter(this, "SessionStartup",
+  "resource:///modules/sessionstore/SessionStartup.jsm");
 ChromeUtils.defineModuleGetter(this, "StartupPerformance",
   "resource:///modules/sessionstore/StartupPerformance.jsm");
 
 // Observer Service topics.
 const WINDOW_READY_TOPIC = "browser-idle-startup-tasks-finished";
 
 // Process Message Manager topics.
 const MSG_REQUEST = "session-restore-test?duration";
@@ -44,21 +44,19 @@ const sessionRestoreTest = {
 
   /**
    * Perform initialization on profile-after-change.
    */
   init() {
     if (StartupPerformance.isRestored) {
       this.onReady(true);
     } else {
-      let sessionStartup = Cc["@mozilla.org/browser/sessionstartup;1"]
-                                 .getService(Ci.nsISessionStartup);
-      sessionStartup.onceInitialized.then(() => {
-        if (sessionStartup.sessionType == Ci.nsISessionStartup.NO_SESSION
-        || sessionStartup.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
+      SessionStartup.onceInitialized.then(() => {
+        if (SessionStartup.sessionType == SessionStartup.NO_SESSION ||
+            SessionStartup.sessionType == SessionStartup.DEFER_SESSION) {
           this.onReady(false);
         } else {
           Services.obs.addObserver(this, StartupPerformance.RESTORED_TOPIC);
         }
       });
     }
   },