Bug 1271483 - p10. Front-end handling of prefs&telemetry - r=gijs draft
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 26 May 2016 23:46:52 +1000
changeset 380483 59ae50f8545c8bc4e0c61a0d818651185c1b078c
parent 380482 373703ee7f332306a1f5d7a8647189d21aa24646
child 380484 af745ceacd4b194698b719ebe3f7b4ee07786565
push id21230
push usergsquelart@mozilla.com
push dateWed, 22 Jun 2016 01:46:41 +0000
reviewersgijs
bugs1271483
milestone50.0a1
Bug 1271483 - p10. Front-end handling of prefs&telemetry - r=gijs When an issue is reported, save the unplayable formats/key-systesm in a pref, keyed by the detailed issue string id, and report the infobar-shown telemetry. More telemetry when the "Show me how" button is clicked. And final telemetry (and clearing the prefs) when the issue is solved. MozReview-Commit-ID: 4PgaPMVfjsQ
browser/base/content/browser-media.js
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -190,16 +190,22 @@ var gEMEHandler = {
   },
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener])
 };
 
 XPCOMUtils.defineLazyGetter(gEMEHandler, "_brandShortName", function() {
   return document.getElementById("bundle_brand").getString("brandShortName");
 });
 
+const TELEMETRY_DDSTAT_SHOWN = 0;
+const TELEMETRY_DDSTAT_SHOWN_FIRST = 1;
+const TELEMETRY_DDSTAT_CLICKED = 2;
+const TELEMETRY_DDSTAT_CLICKED_FIRST = 3;
+const TELEMETRY_DDSTAT_SOLVED = 4;
+
 let gDecoderDoctorHandler = {
   shouldShowLearnMoreButton() {
     return AppConstants.platform == "win";
   },
 
   getLabelForNotificationBox(type) {
     if (type == "adobe-cdm-not-found" &&
         AppConstants.platform == "win") {
@@ -236,42 +242,103 @@ let gDecoderDoctorHandler = {
 
     let parsedData;
     try {
       parsedData = JSON.parse(data);
     } catch (ex) {
       Cu.reportError("Malformed Decoder Doctor message with data: " + data);
       return;
     }
-    let {type} = parsedData;
+    // parsedData (the result of parsing the incoming 'data' json string)
+    // contains analysis information from Decoder Doctor:
+    // - 'type' is the type of issue, it determines which text to show in the
+    //   infobar.
+    // - 'decoderDoctorReportId' is the Decoder Doctor issue identifier, to be
+    //   used here as key for the telemetry (counting infobar displays,
+    //   "Learn how" buttons clicks, and resolutions) and for the prefs used
+    //   to store at-issue formats.
+    // - 'formats' contains a comma-separated list of formats (or key systems)
+    //   that suffer the issue. These are kept in a pref, which the backend
+    //   uses to later find when an issue is resolved.
+    // - 'isSolved' is true when the notification actually indicates the
+    //   resolution of that issue, to be reported as telemetry.
+    let {type, isSolved, decoderDoctorReportId, formats} = parsedData;
     type = type.toLowerCase();
     let title = gDecoderDoctorHandler.getLabelForNotificationBox(type);
     if (!title) {
       return;
     }
 
-    let buttons = [];
-    if (gDecoderDoctorHandler.shouldShowLearnMoreButton()) {
-      buttons.push({
-        label: gNavigatorBundle.getString("decoder.noCodecs.button"),
-        accessKey: gNavigatorBundle.getString("decoder.noCodecs.accesskey"),
-        callback() {
-          let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
-          openUILinkIn(baseURL + "fix-video-audio-problems-firefox-windows", "tab");
+    // We keep the list of formats in prefs for the sake of the decoder itself,
+    // which reads it to determine when issues get solved for these formats.
+    // (Writing prefs from e10s content is now allowed.)
+    let formatsPref = "media.decoder-doctor." + decoderDoctorReportId + ".formats";
+    let buttonClickedPref = "media.decoder-doctor." + decoderDoctorReportId + ".button-clicked";
+    let histogram =
+      Services.telemetry.getKeyedHistogramById("DECODER_DOCTOR_INFOBAR_STATS");
+
+    let formatsInPref = Services.prefs.getPrefType(formatsPref) &&
+                        Services.prefs.getCharPref(formatsPref);
+
+    if (!isSolved) {
+      if (!formats) {
+        Cu.reportError("Malformed Decoder Doctor unsolved message with no formats");
+        return;
+      }
+      if (!formatsInPref) {
+        Services.prefs.setCharPref(formatsPref, formats);
+        histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_SHOWN_FIRST);
+      } else {
+        // Split existing formats into an array of strings.
+        let existing = formatsInPref.split(",").map(String.trim);
+        // Keep given formats that were not already recorded.
+        let newbies = formats.split(",").map(String.trim)
+                      .filter(x => existing.includes(x));
+        // And rewrite pref with the added new formats (if any).
+        if (newbies.length) {
+          Services.prefs.setCharPref(formatsPref,
+                                     existing.concat(newbies).join(", "));
         }
-      });
-    }
+      }
+      histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_SHOWN);
+
+      let buttons = [];
+      if (gDecoderDoctorHandler.shouldShowLearnMoreButton()) {
+        buttons.push({
+          label: gNavigatorBundle.getString("decoder.noCodecs.button"),
+          accessKey: gNavigatorBundle.getString("decoder.noCodecs.accesskey"),
+          callback() {
+            let clickedInPref = Services.prefs.getPrefType(buttonClickedPref) &&
+                                Services.prefs.getBoolPref(buttonClickedPref);
+            if (!clickedInPref) {
+              Services.prefs.setBoolPref(buttonClickedPref, true);
+              histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED_FIRST);
+            }
+            histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_CLICKED);
 
-    box.appendNotification(
-      title,
-      notificationId,
-      "", // This uses the info icon as specified below.
-      box.PRIORITY_INFO_LOW,
-      buttons
-    );
+            let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
+            openUILinkIn(baseURL + "fix-video-audio-problems-firefox-windows", "tab");
+          }
+        });
+      }
+
+      box.appendNotification(
+          title,
+          notificationId,
+          "", // This uses the info icon as specified below.
+          box.PRIORITY_INFO_LOW,
+          buttons
+      );
+    } else if (formatsInPref) {
+      // Issue is solved, and prefs haven't been cleared yet, meaning it's the
+      // first time we get this resolution -> Clear prefs and report telemetry.
+      Services.prefs.clearUserPref(formatsPref);
+      Services.prefs.clearUserPref(buttonClickedPref);
+      histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_SOLVED);
+    }
   },
 }
 
 window.messageManager.addMessageListener("DecoderDoctor:Notification", gDecoderDoctorHandler);
 window.messageManager.addMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
 window.addEventListener("unload", function() {
   window.messageManager.removeMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
   window.messageManager.removeMessageListener("DecoderDoctor:Notification", gDecoderDoctorHandler);