Bug 872206 - Part 2 -Use CrashMonitor to identify crashes in Metro for sending a SHUTDOWN_OK telemetry probe. r=mbrubeck
authorMarina Samuel <msamuel@mozilla.com>
Wed, 12 Feb 2014 12:59:16 -0500
changeset 168360 77e7f75b502d7f0dc21377d7d358d8002096e5e0
parent 168359 c0ea0b4d69f7750002c5bed54219f7296f2536ac
child 168361 ce6caf543408184d1ccdeac576ab3278a3d3648a
push id5034
push usermsamuel@mozilla.com
push dateWed, 12 Feb 2014 18:00:36 +0000
treeherderfx-team@77e7f75b502d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs872206
milestone30.0a1
Bug 872206 - Part 2 -Use CrashMonitor to identify crashes in Metro for sending a SHUTDOWN_OK telemetry probe. r=mbrubeck
browser/metro/components/SessionStore.js
--- a/browser/metro/components/SessionStore.js
+++ b/browser/metro/components/SessionStore.js
@@ -11,16 +11,19 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/WindowsPrefSync.jsm");
 
 #ifdef MOZ_CRASHREPORTER
 XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
   "@mozilla.org/xre/app-info;1", "nsICrashReporter");
 #endif
 
+XPCOMUtils.defineLazyModuleGetter(this, "CrashMonitor",
+  "resource://gre/modules/CrashMonitor.jsm");
+
 XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
   "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
@@ -71,16 +74,35 @@ SessionStore.prototype = {
 
     try {
       UITelemetry.addSimpleMeasureFunction("metro-tabs",
                                           this._getTabStats.bind(this));
     } catch (ex) {
       // swallow exception that occurs if metro-tabs measure is already set up
     }
 
+    CrashMonitor.previousCheckpoints.then(checkpoints => {
+      let previousSessionCrashed = false;
+
+      if (checkpoints) {
+        // If the previous session finished writing the final state, we'll
+        // assume there was no crash.
+        previousSessionCrashed = !checkpoints["sessionstore-final-state-write-complete"];
+      } else {
+        // If no checkpoints are saved, this is the first run with CrashMonitor or the
+        // metroSessionCheckpoints file was corrupted/deleted, so fallback to defining
+        // a crash as init-ing with an unexpected previousExecutionState
+        // 1 == RUNNING, 2 == SUSPENDED
+        previousSessionCrashed = Services.metro.previousExecutionState == 1 ||
+          Services.metro.previousExecutionState == 2;
+      }
+
+      Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!previousSessionCrashed);
+    });
+
     try {
       let shutdownWasUnclean = false;
 
       if (this._sessionFileBackup.exists()) {
         this._sessionFileBackup.remove(false);
         shutdownWasUnclean = true;
       }
 
@@ -286,18 +308,18 @@ SessionStore.prototype = {
         observerService.removeObserver(this, "quit-application-granted");
         observerService.removeObserver(this, "quit-application");
         observerService.removeObserver(this, "reset-telemetry-vars");
 
         // If a save has been queued, kill the timer and save state now
         if (this._saveTimer) {
           this._saveTimer.cancel();
           this._saveTimer = null;
-          this.saveState();
         }
+        this.saveState();
         break;
       case "browser:purge-session-history": // catch sanitization
         this._clearDisk();
 
         // If the browser is shutting down, simply return after clearing the
         // session data on disk as this notification fires after the
         // quit-application notification so the browser is about to exit.
         if (this._loadState == STATE_QUITTING)
@@ -639,16 +661,19 @@ SessionStore.prototype = {
     // Obtain a converter to convert our data to a UTF-8 encoded input stream.
     let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     // Asynchronously copy the data to the file.
     let istream = converter.convertToInputStream(aData);
     NetUtil.asyncCopy(istream, ostream, function(rc) {
       if (Components.isSuccessCode(rc)) {
+        if (Services.startup.shuttingDown) {
+          Services.obs.notifyObservers(null, "sessionstore-final-state-write-complete", "");
+        }
         Services.obs.notifyObservers(null, "sessionstore-state-write-complete", "");
       }
     });
   },
 
   _updateCrashReportURL: function ss_updateCrashReportURL(aWindow) {
 #ifdef MOZ_CRASHREPORTER
     try {