Bug 1503685 - Add home_extension_id and newtab_extension_id info to PAGE_TAKEOVER_DATA telemetry ping r=k88hudson a=jcristau
authorRicky Rosario <rickyrosario@gmail.com>
Thu, 22 Nov 2018 18:50:06 +0200
changeset 501337 ce76875904c66eb097b352296c1c72ed03a2d4b3
parent 501336 55364b902bda00060a81dcbaa8a8722a9b637055
child 501338 811d4b940b9b6589840aa30f0000c8885b6c36b0
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersk88hudson, jcristau
bugs1503685
milestone64.0
Bug 1503685 - Add home_extension_id and newtab_extension_id info to PAGE_TAKEOVER_DATA telemetry ping r=k88hudson a=jcristau Summary: MozReview-Commit-ID: C2Fahx4LGHv Reviewers: k88hudson Reviewed By: k88hudson Bug #: 1503685 Differential Revision: https://phabricator.services.mozilla.com/D11919
browser/components/newtab/docs/v2-system-addon/data_events.md
browser/components/newtab/lib/TelemetryFeed.jsm
browser/components/newtab/test/schemas/pings.js
browser/components/newtab/test/unit/lib/TelemetryFeed.test.js
--- a/browser/components/newtab/docs/v2-system-addon/data_events.md
+++ b/browser/components/newtab/docs/v2-system-addon/data_events.md
@@ -28,24 +28,26 @@ where the "value" is encoded as:
   * Value 0: default
   * Value 1: about:blank
   * Value 2: web extension
   * Value 3: other custom URL(s)
 Two encoded integers for about:newtab and about:home are combined in a bitwise fashion. For instance, if both about:home and about:newtab were set to about:blank, then `value = 5 = (1 | (1 << 2))`, i.e `value = (bitfield of about:newtab) | (bitfield of about:newhome << 2)`.
 
 ## Page takeover ping
 
-This ping is submitted once upon Activity Stream initialization if either about:home or about:newtab are set to a custom URL. It sends the category of the custom URL.
+This ping is submitted once upon Activity Stream initialization if either about:home or about:newtab are set to a custom URL. It sends the category of the custom URL. It also includes the web extension id of the extension controlling the home and/or newtab page.
 
 ```js
 {
   "event": "PAGE_TAKEOVER_DATA",
   "value": {
     "home_url_category": ["search-engine" | "search-engine-mozilla-tag" | "search-engine-other-tag" | "news-portal" | "ecommerce" | "social-media" | "known-hijacker" | "other"],
+    "home_extension_id": "26288a14-5cc4-d14f-ae0a-bb01ef45be9c",
     "newtab_url_category": ["search-engine" | "search-engine-mozilla-tag" | "search-engine-other-tag" | "news-portal" | "ecommerce" | "social-media" | "known-hijacker" | "other"],
+    "newtab_extension_id": "26288a14-5cc4-d14f-ae0a-bb01ef45be9c",
   },
 
   // Basic metadata
   "action": "activity_stream_event",
   "client_id": "26288a14-5cc4-d14f-ae0a-bb01ef45be9c",
   "session_id": "005deed0-e3e4-4c02-a041-17405fd703f6",
   "addon_version": "20180710100040",
   "locale": "en-US",
--- a/browser/components/newtab/lib/TelemetryFeed.jsm
+++ b/browser/components/newtab/lib/TelemetryFeed.jsm
@@ -19,16 +19,18 @@ ChromeUtils.defineModuleGetter(this, "pe
 ChromeUtils.defineModuleGetter(this, "PingCentre",
   "resource:///modules/PingCentre.jsm");
 ChromeUtils.defineModuleGetter(this, "UTEventReporting",
   "resource://activity-stream/lib/UTEventReporting.jsm");
 ChromeUtils.defineModuleGetter(this, "UpdateUtils",
   "resource://gre/modules/UpdateUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "HomePage",
   "resource:///modules/HomePage.jsm");
+ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
+  "resource://gre/modules/ExtensionSettingsStore.jsm");
 
 XPCOMUtils.defineLazyServiceGetters(this, {
   gUUIDGenerator: ["@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"],
   aboutNewTabService: ["@mozilla.org/browser/aboutnewtab-service;1", "nsIAboutNewTabService"],
 });
 
 const ACTIVITY_STREAM_ID = "activity-stream";
 const ACTIVITY_STREAM_ENDPOINT_PREF = "browser.newtabpage.activity-stream.telemetry.ping.endpoint";
@@ -487,32 +489,54 @@ this.TelemetryFeed = class TelemetryFeed
 
   handleUndesiredEvent(action) {
     this.sendEvent(this.createUndesiredEvent(action));
   }
 
   async sendPageTakeoverData() {
     if (this.telemetryEnabled) {
       const value = {};
-      let page;
+      let newtabAffected = false;
+      let homeAffected = false;
 
       // Check whether or not about:home and about:newtab are set to a custom URL.
       // If so, classify them.
       if (Services.prefs.getBoolPref("browser.newtabpage.enabled") &&
           aboutNewTabService.overridden &&
           !aboutNewTabService.newTabURL.startsWith("moz-extension://")) {
         value.newtab_url_category = await this._classifySite(aboutNewTabService.newTabURL);
-        page = "about:newtab";
+        newtabAffected = true;
+      }
+      // Check if the newtab page setting is controlled by an extension.
+      await ExtensionSettingsStore.initialize();
+      const newtabExtensionInfo = ExtensionSettingsStore.getSetting("url_overrides", "newTabURL");
+      if (newtabExtensionInfo && newtabExtensionInfo.id) {
+        value.newtab_extension_id = newtabExtensionInfo.id;
+        newtabAffected = true;
       }
 
       const homePageURL = HomePage.get();
       if (!["about:home", "about:blank"].includes(homePageURL) &&
           !homePageURL.startsWith("moz-extension://")) {
         value.home_url_category = await this._classifySite(homePageURL);
-        page = page ? "both" : "about:home";
+        homeAffected = true;
+      }
+      const homeExtensionInfo = ExtensionSettingsStore.getSetting("prefs", "homepage_override");
+      if (homeExtensionInfo && homeExtensionInfo.id) {
+        value.home_extension_id = homeExtensionInfo.id;
+        homeAffected = true;
+      }
+
+      let page;
+      if (newtabAffected && homeAffected) {
+        page = "both";
+      } else if (newtabAffected) {
+        page = "about:newtab";
+      } else if (homeAffected) {
+        page = "about:home";
       }
 
       if (page) {
         const event = Object.assign(
           this.createPing(),
           {
             action: "activity_stream_user_event",
             event: "PAGE_TAKEOVER_DATA",
--- a/browser/components/newtab/test/schemas/pings.js
+++ b/browser/components/newtab/test/schemas/pings.js
@@ -27,17 +27,19 @@ export const UserEventPing = Joi.object(
   source: Joi.string(),
   event: Joi.string().required(),
   action: Joi.valid("activity_stream_user_event").required(),
   metadata_source: Joi.string(),
   highlight_type: Joi.valid(["bookmarks", "recommendation", "history"]),
   recommender_type: Joi.string(),
   value: Joi.object().keys({
     newtab_url_category: Joi.string(),
+    newtab_extension_id: Joi.string(),
     home_url_category: Joi.string(),
+    home_extension_id: Joi.string(),
   }),
 }));
 
 export const UTUserEventPing = Joi.array().items(
   Joi.string().required().valid("activity_stream"),
   Joi.string().required().valid("event"),
   Joi.string().required().valid([
     "CLICK",
--- a/browser/components/newtab/test/unit/lib/TelemetryFeed.test.js
+++ b/browser/components/newtab/test/unit/lib/TelemetryFeed.test.js
@@ -21,16 +21,17 @@ describe("TelemetryFeed", () => {
   let globals;
   let sandbox;
   let expectedUserPrefs;
   let browser = {getAttribute() { return "true"; }};
   let instance;
   let clock;
   let fakeHomePageUrl;
   let fakeHomePage;
+  let fakeExtensionSettingsStore;
   class PingCentre {sendPing() {} uninit() {}}
   class UTEventReporting {sendUserEvent() {} sendSessionEndEvent() {} uninit() {}}
   class PerfService {
     getMostRecentAbsMarkStartByName() { return 1234; }
     mark() {}
     absNow() { return 123; }
     get timeOrigin() { return 123456; }
   }
@@ -51,23 +52,30 @@ describe("TelemetryFeed", () => {
     sandbox = globals.sandbox;
     clock = sinon.useFakeTimers();
     fakeHomePageUrl = "about:home";
     fakeHomePage = {
       get() {
         return fakeHomePageUrl;
       },
     };
+    fakeExtensionSettingsStore = {
+      initialize() {
+        return Promise.resolve();
+      },
+      getSetting() {},
+    };
     sandbox.spy(global.Cu, "reportError");
     globals.set("gUUIDGenerator", {generateUUID: () => FAKE_UUID});
     globals.set("aboutNewTabService", {
       overridden: false,
       newTabURL: "",
     });
     globals.set("HomePage", fakeHomePage);
+    globals.set("ExtensionSettingsStore", fakeExtensionSettingsStore);
     globals.set("PingCentre", PingCentre);
     globals.set("UTEventReporting", UTEventReporting);
     sandbox.stub(ASRouterPreferences, "providers").get(() => FAKE_ROUTER_MESSAGE_PROVIDER);
     instance = new TelemetryFeed();
   });
   afterEach(() => {
     clock.restore();
     globals.restore();
@@ -970,36 +978,64 @@ describe("TelemetryFeed", () => {
   });
   describe("#sendPageTakeoverData", () => {
     let fakePrefs = {"browser.newtabpage.enabled": true};
 
     beforeEach(() => {
       globals.set("Services", Object.assign({}, Services, {prefs: {getBoolPref: key => fakePrefs[key]}}));
       // Services.prefs = {getBoolPref: key => fakePrefs[key]};
     });
-    it("should send correct event data for about:{home,newtab} set to custom URL", async () => {
-      globals.set("aboutNewTabService", {
-        overridden: true,
-        newTabURL: "https://searchprovider.com",
-      });
+    it("should send correct event data for about:home set to custom URL", async () => {
       fakeHomePageUrl = "https://searchprovider.com";
       instance._prefs.set(TELEMETRY_PREF, true);
       instance._classifySite = () => Promise.resolve("other");
       const sendEvent = sandbox.stub(instance, "sendEvent");
 
       await instance.sendPageTakeoverData();
       assert.calledOnce(sendEvent);
       assert.equal(sendEvent.firstCall.args[0].event, "PAGE_TAKEOVER_DATA");
       assert.deepEqual(sendEvent.firstCall.args[0].value, {
         home_url_category: "other",
+      });
+      assert.validate(sendEvent.firstCall.args[0], UserEventPing);
+    });
+    it("should send correct event data for about:newtab set to custom URL", async () => {
+      globals.set("aboutNewTabService", {
+        overridden: true,
+        newTabURL: "https://searchprovider.com",
+      });
+      instance._prefs.set(TELEMETRY_PREF, true);
+      instance._classifySite = () => Promise.resolve("other");
+      const sendEvent = sandbox.stub(instance, "sendEvent");
+
+      await instance.sendPageTakeoverData();
+      assert.calledOnce(sendEvent);
+      assert.equal(sendEvent.firstCall.args[0].event, "PAGE_TAKEOVER_DATA");
+      assert.deepEqual(sendEvent.firstCall.args[0].value, {
         newtab_url_category: "other",
       });
       assert.validate(sendEvent.firstCall.args[0], UserEventPing);
     });
     it("should not send an event if neither about:{home,newtab} are set to custom URL", async () => {
       instance._prefs.set(TELEMETRY_PREF, true);
       const sendEvent = sandbox.stub(instance, "sendEvent");
 
       await instance.sendPageTakeoverData();
       assert.notCalled(sendEvent);
     });
+    it("should send home_extension_id and newtab_extension_id when appropriate", async () => {
+      const ID = "{abc-foo-bar}";
+      fakeExtensionSettingsStore.getSetting = () => ({id: ID});
+      instance._prefs.set(TELEMETRY_PREF, true);
+      instance._classifySite = () => Promise.resolve("other");
+      const sendEvent = sandbox.stub(instance, "sendEvent");
+
+      await instance.sendPageTakeoverData();
+      assert.calledOnce(sendEvent);
+      assert.equal(sendEvent.firstCall.args[0].event, "PAGE_TAKEOVER_DATA");
+      assert.deepEqual(sendEvent.firstCall.args[0].value, {
+        home_extension_id: ID,
+        newtab_extension_id: ID,
+      });
+      assert.validate(sendEvent.firstCall.args[0], UserEventPing);
+    });
   });
 });