Bug 1470505: Disable browser error collection for webextension errors. r=Gijs
authorMichael Kelly <mkelly@mozilla.com>
Mon, 09 Jul 2018 18:27:22 +0000
changeset 425528 acb50efde2ede296d49fc60e3f413e9efa5acc00
parent 425527 f4f6234d143cf9fa2263da79238f073f06daf67a
child 425529 1d40377d3c2558da69e641df37ab1948d91050ea
push id34258
push usertoros@mozilla.com
push dateTue, 10 Jul 2018 09:43:53 +0000
treeherdermozilla-central@0c55071115c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1470505
milestone63.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 1470505: Disable browser error collection for webextension errors. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D1792
browser/modules/BrowserErrorReporter.jsm
browser/modules/test/browser/browser_BrowserErrorReporter.js
browser/modules/test/browser/browser_BrowserErrorReporter_nightly.js
--- a/browser/modules/BrowserErrorReporter.jsm
+++ b/browser/modules/BrowserErrorReporter.jsm
@@ -60,16 +60,17 @@ const TELEMETRY_REPORTED_PATTERNS = new 
   /^chrome:\/\/(?:global|browser|devtools)/,
 ]);
 
 // Mapping of regexes to sample rates; if the regex matches the module an error
 // is thrown from, the matching sample rate is used instead of the default.
 // In case of a conflict, the first matching rate by insertion order is used.
 const MODULE_SAMPLE_RATES = new Map([
   [/^(?:chrome|resource):\/\/devtools/, 1],
+  [/^moz-extension:\/\//, 0],
 ]);
 
 /**
  * Collects nsIScriptError messages logged to the browser console and reports
  * them to a remotely-hosted error collection service.
  *
  * This is a PROTOTYPE; it will be removed in the future and potentially
  * replaced with a more robust implementation. It is meant to only collect
@@ -93,25 +94,27 @@ class BrowserErrorReporter {
     // Date constructor uses 0-indexed months
     const buildMonth = Number.parseInt(appBuildId.slice(4, 6)) - 1;
     const buildDay = Number.parseInt(appBuildId.slice(6, 8));
     return new Date(buildYear, buildMonth, buildDay);
   }
 
   constructor(options = {}) {
     // Test arguments for mocks and changing behavior
-    this.fetch = options.fetch || defaultFetch;
-    this.now = options.now || null;
-    this.chromeOnly = options.chromeOnly !== undefined ? options.chromeOnly : true;
-    this.registerListener = (
-      options.registerListener || (() => Services.console.registerListener(this))
-    );
-    this.unregisterListener = (
-      options.unregisterListener || (() => Services.console.unregisterListener(this))
-    );
+    const defaultOptions = {
+      fetch: defaultFetch,
+      now: null,
+      chromeOnly: true,
+      sampleRates: MODULE_SAMPLE_RATES,
+      registerListener: () => Services.console.registerListener(this),
+      unregisterListener: () => Services.console.unregisterListener(this),
+    };
+    for (const [key, defaultValue] of Object.entries(defaultOptions)) {
+      this[key] = key in options ? options[key] : defaultValue;
+    }
 
     XPCOMUtils.defineLazyGetter(this, "appBuildIdDate", BrowserErrorReporter.getAppBuildIdDate);
 
     // Values that don't change between error reports.
     this.requestBodyTemplate = {
       logger: "javascript",
       platform: "javascript",
       release: Services.appinfo.appBuildID,
@@ -265,17 +268,17 @@ class BrowserErrorReporter {
     // We do not collect errors on non-Nightly channels, just telemetry.
     // Also, old builds should not send errors to Sentry
     if (!AppConstants.NIGHTLY_BUILD || !this.isRecentBuild()) {
       return;
     }
 
     // Sample the amount of errors we send out
     let sampleRate = Number.parseFloat(this.sampleRatePref);
-    for (const [regex, rate] of MODULE_SAMPLE_RATES) {
+    for (const [regex, rate] of this.sampleRates) {
       if (message.sourceName.match(regex)) {
         sampleRate = rate;
         break;
       }
     }
     if (!Number.isFinite(sampleRate) || (Math.random() >= sampleRate)) {
       return;
     }
--- a/browser/modules/test/browser/browser_BrowserErrorReporter.js
+++ b/browser/modules/test/browser/browser_BrowserErrorReporter.js
@@ -79,16 +79,17 @@ add_task(async function testScalars() {
   // Do not bother testing telemetry scalars if they're already expired.
   if (SCALARS_EXPIRED) {
     return;
   }
 
   const fetchStub = sinon.stub();
   const reporter = new BrowserErrorReporter({
     fetch: fetchStub,
+    sampleRates: new Map(),
     now: BrowserErrorReporter.getAppBuildIdDate(),
   });
   await SpecialPowers.pushPrefEnv({set: [
     [PREF_ENABLED, true],
     [PREF_SAMPLE_RATE, "1.0"],
   ]});
 
   Services.telemetry.clearScalars();
--- a/browser/modules/test/browser/browser_BrowserErrorReporter_nightly.js
+++ b/browser/modules/test/browser/browser_BrowserErrorReporter_nightly.js
@@ -101,16 +101,25 @@ add_task(async function testSampling() {
   );
 
   await reporter.handleMessage(createScriptError({message: "undefined", sourceName: undefined}));
   ok(
     fetchPassedError(fetchSpy, "undefined"),
     "A missing sourceName doesn't break reporting.",
   );
 
+  await reporter.handleMessage(createScriptError({
+    message: "mozextension",
+    sourceName: "moz-extension://Bar/Foo.jsm",
+  }));
+  ok(
+    !fetchPassedError(fetchSpy, "mozextension"),
+    "moz-extension:// paths are sampled at 0% even if the default rate is 1.0.",
+  );
+
   await SpecialPowers.pushPrefEnv({set: [
     [PREF_SAMPLE_RATE, "0.0"],
   ]});
   await reporter.handleMessage(createScriptError({message: "Shouldn't log"}));
   ok(
     !fetchPassedError(fetchSpy, "Shouldn't log"),
     "A 0.0 sample rate will cause the reporter to never collect errors.",
   );
@@ -315,21 +324,20 @@ add_task(async function testFetchArgumen
     );
   });
 
   reporter.uninit();
 });
 
 add_task(async function testAddonIDMangle() {
   const fetchSpy = sinon.spy();
-  // Passing false here disables category checks on errors, which would
-  // otherwise block errors directly from extensions.
   const reporter = new BrowserErrorReporter({
     fetch: fetchSpy,
     chromeOnly: false,
+    sampleRates: new Map(),
     now: BrowserErrorReporter.getAppBuildIdDate(),
   });
   await SpecialPowers.pushPrefEnv({set: [
     [PREF_ENABLED, true],
     [PREF_SAMPLE_RATE, "1.0"],
   ]});
   resetConsole();
   reporter.init();
@@ -361,21 +369,20 @@ add_task(async function testAddonIDMangl
   );
 
   await extension.unload();
   reporter.uninit();
 });
 
 add_task(async function testExtensionTag() {
   const fetchSpy = sinon.spy();
-  // Passing false here disables category checks on errors, which would
-  // otherwise block errors directly from extensions.
   const reporter = new BrowserErrorReporter({
     fetch: fetchSpy,
     chromeOnly: false,
+    sampleRates: new Map(),
     now: BrowserErrorReporter.getAppBuildIdDate(),
   });
   await SpecialPowers.pushPrefEnv({set: [
     [PREF_ENABLED, true],
     [PREF_SAMPLE_RATE, "1.0"],
   ]});
   resetConsole();
   reporter.init();