Bug 1465694 - Add tab event telemetry for Savant Shield study; r=dao
authorBianca Danforth <bdanforth@mozilla.com>
Wed, 06 Jun 2018 03:44:48 -0700
changeset 422010 8a278eebbe5df459eab42bc7f1f515cbc8e38a01
parent 422009 437d495c93b657420be63d179b420f956050d4c9
child 422011 5edda305eaf0239be020b2e8bc8f90be4bca62d9
push id65071
push userdwillcoxon@mozilla.com
push dateFri, 08 Jun 2018 22:20:43 +0000
treeherderautoland@8a278eebbe5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao
bugs1465694
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1465694 - Add tab event telemetry for Savant Shield study; r=dao These probes will register and record (for the duration of the study only): * When a tab opens. * When a tab closes. * When a tab is selected. MozReview-Commit-ID: BvknEH0ofS0
browser/base/content/tabbrowser.js
browser/modules/SavantShieldStudy.jsm
toolkit/components/telemetry/Events.yaml
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1035,16 +1035,17 @@ window._gBrowser = {
       let event = new CustomEvent("TabSelect", {
         bubbles: true,
         cancelable: false,
         detail: {
           previousTab: oldTab
         }
       });
       newTab.dispatchEvent(event);
+      Services.telemetry.recordEvent("savant", "tab", "select", null, { subcategory: "frame" });
 
       this._tabAttrModified(oldTab, ["selected"]);
       this._tabAttrModified(newTab, ["selected"]);
 
       if (oldBrowser != newBrowser &&
           oldBrowser.getInPermitUnload) {
         oldBrowser.getInPermitUnload(inPermitUnload => {
           if (!inPermitUnload) {
@@ -2455,16 +2456,17 @@ window._gBrowser = {
     }
 
     // Dispatch a new tab notification.  We do this once we're
     // entirely done, so that things are in a consistent state
     // even if the event listener opens or closes tabs.
     var detail = aEventDetail || {};
     var evt = new CustomEvent("TabOpen", { bubbles: true, detail });
     t.dispatchEvent(evt);
+    Services.telemetry.recordEvent("savant", "tab", "open", null, { subcategory: "frame" });
 
     if (!usingPreloadedContent && aOriginPrincipal && aURI) {
       let { URI_INHERITS_SECURITY_CONTEXT } = Ci.nsIProtocolHandler;
       // Unless we know for sure we're not inheriting principals,
       // force the about:blank viewer to have the right principal:
       if (!aURIObject ||
         (doGetProtocolFlags(aURIObject) & URI_INHERITS_SECURITY_CONTEXT)) {
         b.createAboutBlankContentViewer(aOriginPrincipal);
@@ -2842,16 +2844,17 @@ window._gBrowser = {
       TabBarVisibility.update();
 
     // We're committed to closing the tab now.
     // Dispatch a notification.
     // We dispatch it before any teardown so that event listeners can
     // inspect the tab that's about to close.
     var evt = new CustomEvent("TabClose", { bubbles: true, detail: { adoptedBy: aAdoptedByTab } });
     aTab.dispatchEvent(evt);
+    Services.telemetry.recordEvent("savant", "tab", "close", null, { subcategory: "frame" });
 
     if (aTab.linkedPanel) {
       if (!aAdoptedByTab && !gMultiProcessBrowser) {
         // Prevent this tab from showing further dialogs, since we're closing it
         var windowUtils = browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                                                .getInterface(Ci.nsIDOMWindowUtils);
         windowUtils.disableDialogs();
       }
--- a/browser/modules/SavantShieldStudy.jsm
+++ b/browser/modules/SavantShieldStudy.jsm
@@ -34,16 +34,19 @@ class SavantShieldStudyClass {
     this.STUDY_PREF = "shield.savant.enabled";
     this.STUDY_TELEMETRY_CATEGORY = "savant";
     this.ALWAYS_PRIVATE_BROWSING_PREF = "browser.privatebrowsing.autostart";
     this.STUDY_DURATION_OVERRIDE_PREF = "shield.savant.duration_override";
     this.STUDY_EXPIRATION_DATE_PREF = "shield.savant.expiration_date";
     // ms = 'x' weeks * 7 days/week * 24 hours/day * 60 minutes/hour
     // * 60 seconds/minute * 1000 milliseconds/second
     this.DEFAULT_STUDY_DURATION_MS = 4 * 7 * 24 * 60 * 60 * 1000;
+    // If on startupStudy(), user is ineligible or study has expired,
+    // no probe listeners from this module have been added yet
+    this.shouldRemoveListeners = true;
   }
 
   init() {
     this.telemetryEvents = new TelemetryEvents(this.STUDY_TELEMETRY_CATEGORY);
     this.addonListener = new AddonListener(this.STUDY_TELEMETRY_CATEGORY);
     this.bookmarkObserver = new BookmarkObserver(this.STUDY_TELEMETRY_CATEGORY);
     this.menuListener = new MenuListener(this.STUDY_TELEMETRY_CATEGORY);
 
@@ -68,24 +71,26 @@ class SavantShieldStudyClass {
     }
   }
 
   startupStudy() {
     // enable before any possible calls to endStudy, since it sends an 'end_study' event
     this.telemetryEvents.enableCollection();
 
     if (!this.isEligible()) {
+      this.shouldRemoveListeners = false;
       this.endStudy("ineligible");
       return;
     }
 
     this.initStudyDuration();
 
     if (this.isStudyExpired()) {
       log.debug("Study expired in between this and the previous session.");
+      this.shouldRemoveListeners = false;
       this.endStudy("expired");
     }
 
     this.addonListener.init();
     this.bookmarkObserver.init();
     this.menuListener.init();
   }
 
@@ -249,17 +254,19 @@ class AddonListener {
                                   { subcategory: this.EXTRA_SUBCATEGORY });
   }
 
   removeListeners() {
     AddonManager.removeAddonListener(this.listener);
   }
 
   uninit() {
-    this.removeListeners();
+    if (SavantShieldStudy.shouldRemoveListeners) {
+      this.removeListeners();
+    }
   }
 }
 
 class BookmarkObserver {
   constructor(studyCategory) {
     this.STUDY_TELEMETRY_CATEGORY = studyCategory;
     // there are two probes: bookmark and follow_bookmark
     this.METHOD_1 = "bookmark";
@@ -275,21 +282,21 @@ class BookmarkObserver {
     this.addObservers();
   }
 
   addObservers() {
     PlacesUtils.bookmarks.addObserver(this);
   }
 
   onItemAdded(itemID, parentID, index, itemType, uri, title, dateAdded, guid, parentGUID, source) {
-    this.handleBookmarkSaveRemove(itemType, uri, source, "save");
+    this.handleItemAddRemove(itemType, uri, source, "save");
   }
 
   onItemRemoved(itemID, parentID, index, itemType, uri, guid, parentGUID, source) {
-    this.handleBookmarkSaveRemove(itemType, uri, source, "remove");
+    this.handleItemAddRemove(itemType, uri, source, "remove");
   }
 
   handleItemAddRemove(itemType, uri, source, event) {
     /*
     * "place:query" uris are used to create containers like Most Visited or
     * Recently Bookmarked. These are added as default bookmarks.
     */
     if (itemType === this.TYPE_BOOKMARK && !uri.schemeIs("place")
@@ -314,17 +321,19 @@ class BookmarkObserver {
                                   });
   }
 
   removeObservers() {
     PlacesUtils.bookmarks.removeObserver(this);
   }
 
   uninit() {
-    this.removeObservers();
+    if (SavantShieldStudy.shouldRemoveListeners) {
+      this.removeObservers();
+    }
   }
 }
 
 class MenuListener {
   constructor(studyCategory) {
     this.STUDY_TELEMETRY_CATEGORY = studyCategory;
     this.NAVIGATOR_TOOLBOX_ID = "navigator-toolbox";
     this.OVERFLOW_PANEL_ID = "widget-overflow";
@@ -413,17 +422,19 @@ class MenuListener {
       hamburgerPanel.removeEventListener("popupshown", this);
       dotdotdotPanel.removeEventListener("popupshown", this);
     } catch (err) {
       // Firefox is shutting down; elements have already been removed.
     }
   }
 
   uninit() {
-    this.windowWatcher.uninit();
+    if (SavantShieldStudy.shouldRemoveListeners) {
+      this.windowWatcher.uninit();
+    }
   }
 }
 
 /*
 * The WindowWatcher is used to add/remove listeners from MenuListener
 * to/from all windows.
 */
 class WindowWatcher {
--- a/toolkit/components/telemetry/Events.yaml
+++ b/toolkit/components/telemetry/Events.yaml
@@ -266,16 +266,29 @@ savant:
     notification_emails:
       - "bdanforth@mozilla.com"
       - "shong@mozilla.com"
     expiry_version: "65"
     extra_keys:
       subcategory: The broad event category for this probe. E.g. navigation
       flow_id: A tab identifier to associate events occuring in the same tab
       canRecordSubmit: True if a login form loads in a non-private window with Password Manager enabled.
+  tab:
+    objects: ["open", "close", "select"]
+    release_channel_collection: opt-out
+    record_in_processes: ["main"]
+    description: >
+      This is recorded any time a tab is opened, closed or selected.
+    bug_numbers: [1457226, 1465694]
+    notification_emails:
+      - "bdanforth@mozilla.com"
+      - "shong@mozilla.com"
+    expiry_version: "65"
+    extra_keys:
+      subcategory: The broad event category for this probe. E.g. navigation
 
 # This category contains event entries used for Telemetry tests.
 # They will not be sent out with any pings.
 telemetry.test:
   test:
     methods: ["test1", "test2"]
     objects: ["object1", "object2"]
     bug_numbers: [1286606]