Bug 1345460 - Implement FX_SANITIZE telemetry on Android. r?liuche draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Wed, 08 Mar 2017 20:17:06 +0100
changeset 502330 c573a48b3c6e3a18fc49c8d8ab360644d245584f
parent 501700 4239adc9a9429028303f99471aff2102083e84c0
child 550138 16b2cc0288d548c9df159c6831150fafaf79d4ca
push id50259
push usermozilla@buttercookie.de
push dateTue, 21 Mar 2017 17:57:36 +0000
reviewersliuche
bugs1345460, 1343995
milestone55.0a1
Bug 1345460 - Implement FX_SANITIZE telemetry on Android. r?liuche To gauge the impact of bug 1343995 on perceived shutdown times, we want to measure how long sanitising actually takes in practice on Android. MozReview-Commit-ID: 3gSfT8IoO70
mobile/android/chrome/content/browser.js
mobile/android/modules/Sanitizer.jsm
toolkit/components/telemetry/Histograms.json
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -113,16 +113,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode", "resource://gre/modules/ReaderMode.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "RuntimePermissions", "resource://gre/modules/RuntimePermissions.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "WebsiteMetadata", "resource://gre/modules/WebsiteMetadata.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm");
+
 XPCOMUtils.defineLazyServiceGetter(this, "FontEnumerator",
   "@mozilla.org/gfx/fontenumerator;1",
   "nsIFontEnumerator");
 
 var GlobalEventDispatcher = EventDispatcher.instance;
 var WindowEventDispatcher = EventDispatcher.for(window);
 
 var lazilyLoadedBrowserScripts = [
@@ -1503,16 +1505,19 @@ var BrowserApp = {
       return this.PREF_TRACKING_PROTECTION_ENABLED_PB;
     }
     return this.PREF_TRACKING_PROTECTION_DISABLED;
   },
 
   sanitize: function (aItems, callback, aShutdown) {
     let success = true;
     var promises = [];
+    let refObj = {};
+
+    TelemetryStopwatch.start("FX_SANITIZE_TOTAL", refObj);
 
     for (let key in aItems) {
       if (!aItems[key])
         continue;
 
       key = key.replace("private.data.", "");
 
       switch (key) {
@@ -1527,26 +1532,28 @@ var BrowserApp = {
           }
           // fall-through if aShutdown is false
         default:
           promises.push(Sanitizer.clearItem(key));
       }
     }
 
     Promise.all(promises).then(function() {
+      TelemetryStopwatch.finish("FX_SANITIZE_TOTAL", refObj);
       GlobalEventDispatcher.sendRequest({
         type: "Sanitize:Finished",
         success: true,
         shutdown: aShutdown === true
       });
 
       if (callback) {
         callback();
       }
     }).catch(function(err) {
+      TelemetryStopwatch.finish("FX_SANITIZE_TOTAL", refObj);
       GlobalEventDispatcher.sendRequest({
         type: "Sanitize:Finished",
         error: err,
         success: false,
         shutdown: aShutdown === true
       });
 
       if (callback) {
--- a/mobile/android/modules/Sanitizer.jsm
+++ b/mobile/android/modules/Sanitizer.jsm
@@ -17,16 +17,18 @@ Cu.import("resource://gre/modules/Task.j
 Cu.import("resource://gre/modules/Downloads.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/Accounts.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadIntegration",
                                   "resource://gre/modules/DownloadIntegration.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
                                   "resource://gre/modules/Messaging.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
+                                  "resource://gre/modules/TelemetryStopwatch.jsm");
 
 function dump(a) {
   Services.console.logStringMessage(a);
 }
 
 this.EXPORTED_SYMBOLS = ["Sanitizer"];
 
 function Sanitizer() {}
@@ -45,54 +47,66 @@ Sanitizer.prototype = {
     }
   },
 
   items: {
     cache: {
       clear: function ()
       {
         return new Promise(function(resolve, reject) {
+          let refObj = {};
+          TelemetryStopwatch.start("FX_SANITIZE_CACHE", refObj);
+
           var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
           try {
             cache.clear();
           } catch(er) {}
 
           let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
                                                            .getImgCacheForDocument(null);
           try {
             imageCache.clearCache(false); // true=chrome, false=content
           } catch(er) {}
 
+          TelemetryStopwatch.finish("FX_SANITIZE_CACHE", refObj);
           resolve();
         });
       },
 
       get canClear()
       {
         return true;
       }
     },
 
     cookies: {
       clear: function ()
       {
         return new Promise(function(resolve, reject) {
+          let refObj = {};
+          TelemetryStopwatch.start("FX_SANITIZE_COOKIES_2", refObj);
+
           Services.cookies.removeAll();
+
+          TelemetryStopwatch.finish("FX_SANITIZE_COOKIES_2", refObj);
           resolve();
         });
       },
 
       get canClear()
       {
         return true;
       }
     },
 
     siteSettings: {
       clear: Task.async(function* () {
+        let refObj = {};
+        TelemetryStopwatch.start("FX_SANITIZE_SITESETTINGS", refObj);
+
         // Clear site-specific permissions like "Allow this site to open popups"
         Services.perms.removeAll();
 
         // Clear site-specific settings like page-zoom level
         Cc["@mozilla.org/content-pref/service;1"]
           .getService(Ci.nsIContentPrefService2)
           .removeAllDomains(null);
 
@@ -109,16 +123,17 @@ Sanitizer.prototype = {
             if (Components.isSuccessCode(status)) {
               resolve();
             } else {
               reject(new Error("Error clearing push subscriptions: " +
                                status));
             }
           });
         });
+        TelemetryStopwatch.finish("FX_SANITIZE_SITESETTINGS", refObj);
       }),
 
       get canClear()
       {
         return true;
       }
     },
 
@@ -140,19 +155,23 @@ Sanitizer.prototype = {
       {
           return true;
       }
     },
 
     history: {
       clear: function ()
       {
+        let refObj = {};
+        TelemetryStopwatch.start("FX_SANITIZE_HISTORY", refObj);
+
         return EventDispatcher.instance.sendRequestForResult({ type: "Sanitize:ClearHistory" })
           .catch(e => Cu.reportError("Java-side history clearing failed: " + e))
           .then(function() {
+            TelemetryStopwatch.finish("FX_SANITIZE_HISTORY", refObj);
             try {
               Services.obs.notifyObservers(null, "browser:purge-session-history", "");
             }
             catch (e) { }
 
             try {
               var predictor = Cc["@mozilla.org/network/predictor;1"].getService(Ci.nsINetworkPredictor);
               predictor.reset();
@@ -166,24 +185,28 @@ Sanitizer.prototype = {
         // the browser:purge-session-history notification. (like error console)
         return true;
       }
     },
 
     openTabs: {
       clear: function ()
       {
+        let refObj = {};
+        TelemetryStopwatch.start("FX_SANITIZE_OPENWINDOWS", refObj);
+
         return EventDispatcher.instance.sendRequestForResult({ type: "Sanitize:OpenTabs" })
           .catch(e => Cu.reportError("Java-side tab clearing failed: " + e))
           .then(function() {
             try {
               // clear "Recently Closed" tabs in Android App
               Services.obs.notifyObservers(null, "browser:purge-session-tabs", "");
             }
             catch (e) { }
+            TelemetryStopwatch.finish("FX_SANITIZE_OPENWINDOWS", refObj);
           });
       },
 
       get canClear()
       {
         return true;
       }
     },
@@ -200,17 +223,22 @@ Sanitizer.prototype = {
         return true;
       }
     },
 
     formdata: {
       clear: function ()
       {
         return new Promise(function(resolve, reject) {
+          let refObj = {};
+          TelemetryStopwatch.start("FX_SANITIZE_FORMDATA", refObj);
+
           FormHistory.update({ op: "remove" });
+
+          TelemetryStopwatch.finish("FX_SANITIZE_FORMDATA", refObj);
           resolve();
         });
       },
 
       canClear: function (aCallback)
       {
         let count = 0;
         let countDone = {
@@ -219,16 +247,19 @@ Sanitizer.prototype = {
           handleCompletion: function(aReason) { aCallback(aReason == 0 && count > 0); }
         };
         FormHistory.count({}, countDone);
       }
     },
 
     downloadFiles: {
       clear: Task.async(function* () {
+        let refObj = {};
+        TelemetryStopwatch.start("FX_SANITIZE_DOWNLOADS", refObj);
+
         let list = yield Downloads.getList(Downloads.ALL);
         let downloads = yield list.getAll();
         var finalizePromises = [];
 
         // Logic copied from DownloadList.removeFinished. Ideally, we would
         // just use that method directly, but we want to be able to remove the
         // downloaded files as well.
         for (let download of downloads) {
@@ -251,16 +282,17 @@ Sanitizer.prototype = {
                 Cu.reportError(ex);
               }
             });
           }
         }
 
         yield Promise.all(finalizePromises);
         yield DownloadIntegration.forceSave();
+        TelemetryStopwatch.finish("FX_SANITIZE_DOWNLOADS", refObj);
       }),
 
       get canClear()
       {
         return true;
       }
     },
 
@@ -279,23 +311,27 @@ Sanitizer.prototype = {
         return (count > 0);
       }
     },
 
     sessions: {
       clear: function ()
       {
         return new Promise(function(resolve, reject) {
+          let refObj = {};
+          TelemetryStopwatch.start("FX_SANITIZE_SESSIONS", refObj);
+
           // clear all auth tokens
           var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
           sdr.logoutAndTeardown();
 
           // clear FTP and plain HTTP auth sessions
           Services.obs.notifyObservers(null, "net:clear-active-logins", null);
 
+          TelemetryStopwatch.finish("FX_SANITIZE_SESSIONS", refObj);
           resolve();
         });
       },
 
       get canClear()
       {
         return true;
       }
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9668,17 +9668,17 @@
     "description": "Sanitize: Time it takes to sanitize site-specific settings (ms)"
   },
   "FX_SANITIZE_OPENWINDOWS": {
     "alert_emails": ["firefox-dev@mozilla.org"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 30000,
     "n_buckets": 20,
-    "description": "Sanitize: Time it takes to sanitize the open windows list (ms)"
+    "description": "Sanitize: Time it takes to sanitize the open windows list (ms). On Android, this is the time it takes to close all open tabs (ms)."
   },
   "PWMGR_BLOCKLIST_NUM_SITES": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 100,
     "n_buckets" : 10,
     "description": "The number of sites for which the user has explicitly rejected saving logins"
   },