Bug 1445009: Tag errors from extensions with isExtensionError. r=Gijs
authorMichael Kelly <mkelly@mozilla.com>
Mon, 19 Mar 2018 13:40:53 -0700
changeset 409088 e62d73ef396c32ca930897eb95d328e2ac15a901
parent 409087 a7c5889ae81fdf9adbfbf276fb6d9ef22bbbe755
child 409089 a831178ed112be4db3c867876b99e61d22bdbc7a
push id33675
push usertoros@mozilla.com
push dateWed, 21 Mar 2018 09:40:24 +0000
treeherdermozilla-central@f4ddf30ecf57 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1445009
milestone61.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 1445009: Tag errors from extensions with isExtensionError. r=Gijs MozReview-Commit-ID: AQrlvTfJUUS
browser/modules/BrowserErrorReporter.jsm
browser/modules/test/browser/browser_BrowserErrorReporter.js
--- a/browser/modules/BrowserErrorReporter.jsm
+++ b/browser/modules/BrowserErrorReporter.jsm
@@ -167,35 +167,37 @@ class BrowserErrorReporter {
 
     // Sample the amount of errors we send out
     const sampleRate = Number.parseFloat(Services.prefs.getCharPref(PREF_SAMPLE_RATE));
     if (!Number.isFinite(sampleRate) || (Math.random() >= sampleRate)) {
       return;
     }
 
     const exceptionValue = {};
-    const transforms = [
-      addErrorMessage,
-      addStacktrace,
-      addModule,
-      mangleExtensionUrls,
-    ];
-    for (const transform of transforms) {
-      await transform(message, exceptionValue);
-    }
-
     const requestBody = {
       ...this.requestBodyTemplate,
       timestamp: new Date().toISOString().slice(0, -1), // Remove trailing "Z"
       project: Services.prefs.getCharPref(PREF_PROJECT_ID),
       exception: {
         values: [exceptionValue],
       },
+      tags: {},
     };
 
+    const transforms = [
+      addErrorMessage,
+      addStacktrace,
+      addModule,
+      mangleExtensionUrls,
+      tagExtensionErrors,
+    ];
+    for (const transform of transforms) {
+      await transform(message, exceptionValue, requestBody);
+    }
+
     const url = new URL(Services.prefs.getCharPref(PREF_SUBMIT_URL));
     url.searchParams.set("sentry_client", `${SDK_NAME}/${SDK_VERSION}`);
     url.searchParams.set("sentry_version", "7");
     url.searchParams.set("sentry_key", Services.prefs.getCharPref(PREF_PUBLIC_KEY));
 
     try {
       await this.fetch(url, {
         method: "POST",
@@ -311,8 +313,14 @@ function mangleExtensionUrls(message, ex
   }
 
   exceptionValue.value = mangleExtURL(exceptionValue.value, false);
   exceptionValue.module = mangleExtURL(exceptionValue.module);
   for (const frame of exceptionValue.stacktrace.frames) {
     frame.module = mangleExtURL(frame.module);
   }
 }
+
+function tagExtensionErrors(message, exceptionValue, requestBody) {
+  if (exceptionValue.module && exceptionValue.module.startsWith("moz-extension://")) {
+    requestBody.tags.isExtensionError = true;
+  }
+}
--- a/browser/modules/test/browser/browser_BrowserErrorReporter.js
+++ b/browser/modules/test/browser/browser_BrowserErrorReporter.js
@@ -401,8 +401,51 @@ add_task(async function testAddonIDMangl
   ok(
     stackFrame.module.startsWith(`moz-extension://${id}/`),
     "Stack frame filenames use the proper add-on ID instead of internal UUIDs.",
   );
 
   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});
+  await SpecialPowers.pushPrefEnv({set: [
+    [PREF_ENABLED, true],
+    [PREF_SAMPLE_RATE, "1.0"],
+  ]});
+  resetConsole();
+  reporter.init();
+
+  // Create and install test add-on
+  const id = "browsererrorcollection@example.com";
+  const extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      applications: {
+        gecko: { id },
+      },
+    },
+    background() {
+      throw new Error("testExtensionTag error");
+    },
+  });
+  await extension.startup();
+
+  // Just in case the error hasn't been thrown before add-on startup.
+  let call = await TestUtils.waitForCondition(
+    () => fetchCallForMessage(fetchSpy, "testExtensionTag error"),
+    `Wait for error from ${id} to be logged`,
+  );
+  let body = JSON.parse(call.args[1].body);
+  ok(body.tags.isExtensionError, "Errors from extensions have an isExtensionError tag.");
+
+  await extension.unload();
+  reporter.uninit();
+
+  await reporter.observe(createScriptError({message: "testExtensionTag not from extension"}));
+  call = fetchCallForMessage(fetchSpy, "testExtensionTag not from extension");
+  body = JSON.parse(call.args[1].body);
+  is(body.tags.isExtensionError, undefined, "Normal errors do not have an isExtensionError tag.");
+});