diff --git a/browser/components/sessionstore/StartupPerformance.jsm b/browser/components/sessionstore/StartupPerformance.jsm index 9a90e8d486f7..bdce5852f836 100644 --- a/browser/components/sessionstore/StartupPerformance.jsm +++ b/browser/components/sessionstore/StartupPerformance.jsm @@ -23,9 +23,14 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise", const COLLECT_RESULTS_AFTER_MS = 10000; -const TOPICS = ["sessionstore-restoring-on-startup", "sessionstore-initiating-manual-restore"]; +const OBSERVED_TOPICS = ["sessionstore-restoring-on-startup", "sessionstore-initiating-manual-restore"]; this.StartupPerformance = { + /** + * Once we have finished restoring initial tabs, we broadcast on this topic. + */ + RESTORED_TOPIC: "sessionstore-finished-restoring-initial-tabs", + // Instant at which we have started restoration (notification "sessionstore-restoring-on-startup") _startTimeStamp: null, @@ -44,22 +49,42 @@ this.StartupPerformance = { // `true` once the timer has fired _hasFired: false, + // `true` once we are restored + _isRestored: false, + // Statistics on the session we need to restore. _totalNumberOfEagerTabs: 0, _totalNumberOfTabs: 0, _totalNumberOfWindows: 0, init: function() { - for (let topic of TOPICS) { + for (let topic of OBSERVED_TOPICS) { Services.obs.addObserver(this, topic, false); } }, + /** + * Return the timestamp at which we finished restoring the latest tab. + * + * This information is not really interesting until we have finished restoring + * tabs. + */ + get latestRestoredTimeStamp() { + return this._latestRestoredTimeStamp; + }, + + /** + * `true` once we have finished restoring startup tabs. + */ + get isRestored() { + return this._isRestored; + }, + // Called when restoration starts. // Record the start timestamp, setup the timer and `this._promiseFinished`. // Behavior is unspecified if there was already an ongoing measure. _onRestorationStarts: function(isAutoRestore) { - this._startTimeStamp = Date.now(); + this._latestRestoredTimeStamp = this._startTimeStamp = Date.now(); this._totalNumberOfEagerTabs = 0; this._totalNumberOfTabs = 0; this._totalNumberOfWindows = 0; @@ -68,7 +93,7 @@ this.StartupPerformance = { // that's a very unusual case, and not really worth measuring, so let's // stop listening for further restorations. - for (let topic of TOPICS) { + for (let topic of OBSERVED_TOPICS) { Services.obs.removeObserver(this, topic); } @@ -78,7 +103,10 @@ this.StartupPerformance = { }); this._promiseFinished.then(() => { try { - if (!this._latestRestoredTimeStamp) { + this._isRestored = true; + Services.obs.notifyObservers(null, this.RESTORED_TOPIC, ""); + + if (this._latestRestoredTimeStamp == this._startTimeStamp) { // Apparently, we haven't restored any tab. return; } @@ -95,7 +123,6 @@ this.StartupPerformance = { Services.telemetry.getHistogramById("FX_SESSION_RESTORE_NUMBER_OF_TABS_RESTORED").add(this._totalNumberOfTabs); Services.telemetry.getHistogramById("FX_SESSION_RESTORE_NUMBER_OF_WINDOWS_RESTORED").add(this._totalNumberOfWindows); - // Reset this._startTimeStamp = null; } catch (ex) { diff --git a/testing/talos/talos/startup_test/sessionrestore/addon/SessionRestoreTalosTest.js b/testing/talos/talos/startup_test/sessionrestore/addon/SessionRestoreTalosTest.js index a7979f8c4925..a838de18211f 100644 --- a/testing/talos/talos/startup_test/sessionrestore/addon/SessionRestoreTalosTest.js +++ b/testing/talos/talos/startup_test/sessionrestore/addon/SessionRestoreTalosTest.js @@ -16,16 +16,17 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "setTimeout", "resource://gre/modules/Timer.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "StartupPerformance", + "resource:///modules/sessionstore/StartupPerformance.jsm"); // Observer Service topics. const STARTUP_TOPIC = "profile-after-change"; -const RESTORED_TOPIC = "sessionstore-windows-restored"; // Process Message Manager topics. const MSG_REQUEST = "session-restore-test?duration"; const MSG_PROVIDE = "session-restore-test:duration"; -function nsSessionRestoreTalosTest() {} +function nsSessionRestoreTalosTest() { } nsSessionRestoreTalosTest.prototype = { classID: Components.ID("{716346e5-0c45-4aa2-b601-da36f3c74bd8}"), @@ -45,8 +46,8 @@ nsSessionRestoreTalosTest.prototype = { case STARTUP_TOPIC: this.init(); break; - case RESTORED_TOPIC: - this.onRestored(); + case StartupPerformance.RESTORED_TOPIC: + this.onReady(true); break; default: throw new Error(`Unknown topic ${aTopic}`); @@ -57,29 +58,54 @@ nsSessionRestoreTalosTest.prototype = { * Perform initialization on profile-after-change. */ init: function() { - Services.obs.addObserver(this, RESTORED_TOPIC, false); + 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) { + this.onReady(false); + } else { + Services.obs.addObserver(this, StartupPerformance.RESTORED_TOPIC, false); + } + }); + } }, /** * Session Restore is complete, hurray. */ - onRestored: function() { - setTimeout(function() { - // `sessionRestored` actually becomes available only on the next tick. - let startup_info = Services.startup.getStartupInfo(); - let duration = startup_info.sessionRestored - startup_info.sessionRestoreInit; + onReady: function(hasRestoredTabs) { + if (hasRestoredTabs) { + Services.obs.removeObserver(this, StartupPerformance.RESTORED_TOPIC); + } + try { + setTimeout(function() { + // `StartupPerformance.latestRestoredTimeStamp` actually becomes available only on the next tick. + let startup_info = Services.startup.getStartupInfo(); + let duration = + hasRestoredTabs + ? StartupPerformance.latestRestoredTimeStamp - startup_info.sessionRestoreInit + : startup_info.sessionRestored - startup_info.sessionRestoreInit; - // Broadcast startup duration information immediately, in case the talos - // page is already loaded. - Services.ppmm.broadcastAsyncMessage(MSG_PROVIDE, {duration}); - - // Now, in case the talos page isn't loaded yet, prepare to respond if it - // requestions the duration information. - Services.ppmm.addMessageListener(MSG_REQUEST, function listener() { - Services.ppmm.removeMessageListener(MSG_REQUEST, listener); + // Broadcast startup duration information immediately, in case the talos + // page is already loaded. Services.ppmm.broadcastAsyncMessage(MSG_PROVIDE, {duration}); - }); - }, 0); + + // Now, in case the talos page isn't loaded yet, prepare to respond if it + // requestions the duration information. + Services.ppmm.addMessageListener(MSG_REQUEST, function listener() { + Services.ppmm.removeMessageListener(MSG_REQUEST, listener); + Services.ppmm.broadcastAsyncMessage(MSG_PROVIDE, {duration}); + }); + }, 0); + } catch (ex) { + dump(`SessionRestoreTalosTest: error ${ex}\n`); + dump(ex.stack); + dump("\n"); + } }, }; diff --git a/testing/talos/talos/startup_test/sessionrestore/addon/install.rdf b/testing/talos/talos/startup_test/sessionrestore/addon/install.rdf index a45f5da73c78..95b055a532ee 100644 --- a/testing/talos/talos/startup_test/sessionrestore/addon/install.rdf +++ b/testing/talos/talos/startup_test/sessionrestore/addon/install.rdf @@ -1,9 +1,9 @@ -session-restore-test@mozilla.org +session-restore-test-2@mozilla.org Session Restore Startup Performance Test -1.2.0 +2.0.9 diff --git a/testing/talos/talos/startup_test/sessionrestore/addon/sessionrestore-signed.xpi b/testing/talos/talos/startup_test/sessionrestore/addon/sessionrestore-signed.xpi index 3dcd0124a5b0..a4bc441bff09 100644 Binary files a/testing/talos/talos/startup_test/sessionrestore/addon/sessionrestore-signed.xpi and b/testing/talos/talos/startup_test/sessionrestore/addon/sessionrestore-signed.xpi differ