Backed out changeset 7c1aecbca3dd (bug 1498278) for causing leaks at at mozilla::extensions::ChannelWrapper::Get
authorCoroiu Cristina <ccoroiu@mozilla.com>
Fri, 12 Oct 2018 23:12:07 +0300
changeset 499381 a0d97137f1d6686476466a57e0fcba6451663a09
parent 499380 620be2ce2c8c8f346f4fa30a167e7c6afd995fd1
child 499382 3df978f11b6d4017d88295335458283c38d697cd
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)
bugs1498278
milestone64.0a1
backs out7c1aecbca3ddeb55c60b943a123eb65a052f8594
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
Backed out changeset 7c1aecbca3dd (bug 1498278) for causing leaks at at mozilla::extensions::ChannelWrapper::Get
browser/extensions/webcompat/aboutConfigPrefs.js
browser/extensions/webcompat/aboutConfigPrefs.json
browser/extensions/webcompat/bootstrap.js
browser/extensions/webcompat/content/data/ua_overrides.jsm
browser/extensions/webcompat/content/lib/ua_overrider.jsm
browser/extensions/webcompat/injections.js
browser/extensions/webcompat/injections/css/bug0000000-dummy-css-injection.css
browser/extensions/webcompat/injections/js/bug0000000-dummy-js-injection.js
browser/extensions/webcompat/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js
browser/extensions/webcompat/injections/js/bug1457335-histography.io-ua-change.js
browser/extensions/webcompat/injections/js/bug1472075-bankofamerica.com-ua-change.js
browser/extensions/webcompat/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js
browser/extensions/webcompat/injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js
browser/extensions/webcompat/install.rdf.in
browser/extensions/webcompat/jar.mn
browser/extensions/webcompat/manifest.json
browser/extensions/webcompat/moz.build
browser/extensions/webcompat/test/.eslintrc.js
browser/extensions/webcompat/test/browser.ini
browser/extensions/webcompat/test/browser_check_installed.js
browser/extensions/webcompat/test/browser_overrider.js
browser/extensions/webcompat/ua_overrides.js
browser/extensions/webcompat/webextension/background.js
browser/extensions/webcompat/webextension/injections/css/bug0000000-dummy-css-injection.css
browser/extensions/webcompat/webextension/injections/js/bug0000000-dummy-js-injection.js
browser/extensions/webcompat/webextension/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js
browser/extensions/webcompat/webextension/injections/js/bug1457335-histography.io-ua-change.js
browser/extensions/webcompat/webextension/injections/js/bug1472075-bankofamerica.com-ua-change.js
browser/extensions/webcompat/webextension/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js
browser/extensions/webcompat/webextension/injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js
browser/extensions/webcompat/webextension/manifest.json
dom/serviceworkers/test/test_cross_origin_url_after_redirect.html
dom/serviceworkers/test/test_gzip_redirect.html
dom/serviceworkers/test/test_https_origin_after_redirect.html
dom/serviceworkers/test/test_https_origin_after_redirect_cached.html
dom/serviceworkers/test/test_openWindow.html
dom/serviceworkers/test/test_origin_after_redirect.html
dom/serviceworkers/test/test_origin_after_redirect_cached.html
dom/serviceworkers/test/test_origin_after_redirect_to_https.html
dom/serviceworkers/test/test_origin_after_redirect_to_https_cached.html
deleted file mode 100644
--- a/browser/extensions/webcompat/aboutConfigPrefs.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/* global ExtensionAPI, ExtensionCommon */
-
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-this.aboutConfigPrefs = class extends ExtensionAPI {
-  getAPI(context) {
-    const EventManager = ExtensionCommon.EventManager;
-    const extensionIDBase = context.extension.id.split("@")[0];
-    const extensionPrefNameBase = `extensions.${extensionIDBase}.`;
-
-    return {
-      aboutConfigPrefs: {
-        onPrefChange: new EventManager({
-          context,
-          name: "aboutConfigPrefs.onUAOverridesPrefChange",
-          register: (fire, name) => {
-            const prefName = `${extensionPrefNameBase}${name}`;
-            const callback = () => {
-              fire.async(name).catch(() => {}); // ignore Message Manager disconnects
-            };
-            Services.prefs.addObserver(prefName, callback);
-            return () => {
-              Services.prefs.removeObserver(prefName, callback);
-            };
-          },
-        }).api(),
-        async getPref(name) {
-          try {
-            return Services.prefs.getBoolPref(`${extensionPrefNameBase}${name}`);
-          } catch (_) {
-            return undefined;
-          }
-        },
-        async setPref(name, value) {
-          Services.prefs.setBoolPref(`${extensionPrefNameBase}${name}`, value);
-        },
-      },
-    };
-  }
-};
deleted file mode 100644
--- a/browser/extensions/webcompat/aboutConfigPrefs.json
+++ /dev/null
@@ -1,53 +0,0 @@
-[
-  {
-    "namespace": "aboutConfigPrefs",
-    "description": "experimental API extension to allow access to about:config preferences",
-    "events": [
-      {
-        "name": "onPrefChange",
-        "type": "function",
-        "parameters": [{
-          "name": "name",
-          "type": "string",
-          "description": "The preference which changed"
-        }],
-        "extraParameters": [{
-          "name": "name",
-          "type": "string",
-          "description": "The preference to monitor"
-        }]
-      }
-    ],
-    "functions": [
-      {
-        "name": "getPref",
-        "type": "function",
-        "description": "Get a preference's value",
-        "parameters": [{
-          "name": "name",
-          "type": "string",
-          "description": "The preference name"
-        }],
-        "async": true
-      },
-      {
-        "name": "setPref",
-        "type": "function",
-        "description": "Set a preference's value",
-        "parameters": [
-          {
-            "name": "name",
-            "type": "string",
-            "description": "The preference name"
-          },
-          {
-            "name": "value",
-            "type": "boolean",
-            "description": "The new value"
-          }
-        ],
-        "async": true
-      }
-    ]
-  }
-]
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/bootstrap.js
@@ -0,0 +1,116 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+const PREF_BRANCH = "extensions.webcompat.";
+const PREF_DEFAULTS = {
+  perform_injections: true,
+  perform_ua_overrides: true,
+};
+
+const INJECTIONS_ENABLE_PREF_NAME = "extensions.webcompat.perform_injections";
+
+const BROWSER_STARTUP_FINISHED_TOPIC = "browser-delayed-startup-finished";
+
+const UA_OVERRIDES_INIT_TOPIC = "useragentoverrides-initialized";
+const UA_ENABLE_PREF_NAME = "extensions.webcompat.perform_ua_overrides";
+
+ChromeUtils.defineModuleGetter(this, "UAOverrider", "chrome://webcompat/content/lib/ua_overrider.jsm");
+ChromeUtils.defineModuleGetter(this, "UAOverrides", "chrome://webcompat/content/data/ua_overrides.jsm");
+
+let overrider;
+let webextensionPort;
+
+function InjectionsEnablePrefObserver() {
+  let isEnabled = Services.prefs.getBoolPref(INJECTIONS_ENABLE_PREF_NAME);
+  webextensionPort.postMessage({
+    type: "injection-pref-changed",
+    prefState: isEnabled,
+  });
+}
+
+function UAEnablePrefObserver() {
+  let isEnabled = Services.prefs.getBoolPref(UA_ENABLE_PREF_NAME);
+  overrider.setShouldOverride(isEnabled);
+}
+
+function setDefaultPrefs() {
+  const branch = Services.prefs.getDefaultBranch(PREF_BRANCH);
+  for (const [key, val] of Object.entries(PREF_DEFAULTS)) {
+    // If someone beat us to setting a default, don't overwrite it.
+    if (branch.getPrefType(key) !== branch.PREF_INVALID) {
+      continue;
+    }
+
+    switch (typeof val) {
+      case "boolean":
+        branch.setBoolPref(key, val);
+        break;
+      case "number":
+        branch.setIntPref(key, val);
+        break;
+      case "string":
+        branch.setCharPref(key, val);
+        break;
+    }
+  }
+}
+
+this.install = function() {};
+this.uninstall = function() {};
+
+this.startup = function({webExtension}) {
+  setDefaultPrefs();
+
+  // Intentionally reset the preference on every browser restart to avoid site
+  // breakage by accidentally toggled preferences or by leaving it off after
+  // debugging a site.
+  Services.prefs.clearUserPref(INJECTIONS_ENABLE_PREF_NAME);
+  Services.prefs.addObserver(INJECTIONS_ENABLE_PREF_NAME, InjectionsEnablePrefObserver);
+
+  Services.prefs.clearUserPref(UA_ENABLE_PREF_NAME);
+  Services.prefs.addObserver(UA_ENABLE_PREF_NAME, UAEnablePrefObserver);
+
+  // Listen to the useragentoverrides-initialized notification we get and
+  // initialize our overrider there. This is done to avoid slowing down the
+  // apparent startup process, since we avoid loading anything before the first
+  // window is visible to the user. See bug 1371442 for details.
+  let uaStartupObserver = {
+    observe(aSubject, aTopic, aData) {
+      if (aTopic !== UA_OVERRIDES_INIT_TOPIC) {
+        return;
+      }
+
+      Services.obs.removeObserver(this, UA_OVERRIDES_INIT_TOPIC);
+      overrider = new UAOverrider(UAOverrides);
+      overrider.init();
+    },
+  };
+  Services.obs.addObserver(uaStartupObserver, UA_OVERRIDES_INIT_TOPIC);
+
+  // Observe browser-delayed-startup-finished and only initialize our embedded
+  // WebExtension after that. Otherwise, we'd try to initialize as soon as the
+  // browser starts up, which adds a heavy startup penalty.
+  let appStartupObserver = {
+    observe(aSubject, aTopic, aData) {
+      webExtension.startup().then((api) => {
+        api.browser.runtime.onConnect.addListener((port) => {
+          webextensionPort = port;
+        });
+
+        return Promise.resolve();
+      }).catch((ex) => {
+        console.error(ex);
+      });
+      Services.obs.removeObserver(this, BROWSER_STARTUP_FINISHED_TOPIC);
+    },
+  };
+  Services.obs.addObserver(appStartupObserver, BROWSER_STARTUP_FINISHED_TOPIC);
+};
+
+this.shutdown = function() {
+  Services.prefs.removeObserver(INJECTIONS_ENABLE_PREF_NAME, InjectionsEnablePrefObserver);
+  Services.prefs.removeObserver(UA_ENABLE_PREF_NAME, UAEnablePrefObserver);
+};
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/content/data/ua_overrides.jsm
@@ -0,0 +1,65 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * For detailed information on our policies, and a documention on this format
+ * and its possibilites, please check the Mozilla-Wiki at
+ *
+ * https://wiki.mozilla.org/Compatibility/Go_Faster_Addon/Override_Policies_and_Workflows#User_Agent_overrides
+ */
+const UAOverrides = [
+
+  /*
+   * This is a dummy override that applies a Chrome UA to a dummy site that
+   * blocks all browsers but Chrome.
+   *
+   * This was only put in place to allow QA to test this system addon on an
+   * actual site, since we were not able to find a proper override in time.
+   */
+  {
+    baseDomain: "schub.io",
+    applications: ["firefox", "fennec"],
+    uriMatcher: (uri) => uri.includes("webcompat-addon-testcases.schub.io"),
+    uaTransformer: (originalUA) => {
+      let prefix = originalUA.substr(0, originalUA.indexOf(")") + 1);
+      return `${prefix} AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36`;
+    },
+  },
+
+  /*
+   * Bug 1480710 - m.imgur.com - Build UA override
+   * WebCompat issue #13154 - https://webcompat.com/issues/13154
+   *
+   * imgur returns a 404 for requests to CSS and JS file if requested with a Fennec
+   * User Agent. By removing the Fennec identifies and adding Chrome Mobile's, we
+   * receive the correct CSS and JS files.
+   */
+  {
+    baseDomain: "imgur.com",
+    applications: ["fennec"],
+    uriMatcher: (uri) => uri.includes("m.imgur.com"),
+    uaTransformer: (originalUA) => {
+      let prefix = originalUA.substr(0, originalUA.indexOf(")") + 1);
+      return prefix + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.85 Mobile Safari/537.36";
+    },
+  },
+
+  /*
+   * Bug 755590 - sites.google.com - top bar doesn't show up in Firefox for Android
+   *
+   * Google Sites does show a different top bar template based on the User Agent.
+   * For Fennec, this results in a broken top bar. Appending Chrome and Mobile Safari
+   * identifiers to the UA results in a correct rendering.
+   */
+  {
+    baseDomain: "google.com",
+    applications: ["fennec"],
+    uriMatcher: (uri) => uri.includes("sites.google.com"),
+    uaTransformer: (originalUA) => {
+      return originalUA + " Chrome/68.0.3440.85 Mobile Safari/537.366";
+    },
+  },
+];
+
+var EXPORTED_SYMBOLS = ["UAOverrides"]; /* exported UAOverrides */
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/content/lib/ua_overrider.jsm
@@ -0,0 +1,126 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ChromeUtils.defineModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
+ChromeUtils.defineModuleGetter(this, "UserAgentOverrides", "resource://gre/modules/UserAgentOverrides.jsm");
+
+class UAOverrider {
+  constructor(overrides) {
+    this._overrides = {};
+    this._shouldOverride = true;
+
+    this.initOverrides(overrides);
+  }
+
+  initOverrides(overrides) {
+    // on xpcshell tests, there is no implementation for nsIXULAppInfo, so this
+    // might fail there. To have all of our test cases running at all times,
+    // assume they are on Desktop for now.
+    let currentApplication = "firefox";
+    try {
+      currentApplication = Services.appinfo.name.toLowerCase();
+    } catch (ex) {
+      console.warn("Getting appinfo.name failed, assuming we run on Desktop.", ex);
+    }
+
+    for (let override of overrides) {
+      // Firefox for Desktop is the default application for all overrides.
+      if (!override.applications) {
+        override.applications = ["firefox"];
+      }
+
+      // If the current application is not targeted by the override in question,
+      // we can skip adding the override to our checks entirely.
+      if (!override.applications.includes(currentApplication)) {
+        continue;
+      }
+
+      if (!this._overrides[override.baseDomain]) {
+        this._overrides[override.baseDomain] = [];
+      }
+
+      if (!override.uriMatcher) {
+        override.uriMatcher = () => true;
+      }
+
+      this._overrides[override.baseDomain].push(override);
+    }
+  }
+
+  /**
+   * Used for disabling overrides when the pref has been flipped to false.
+   *
+   * Since we no longer use our own event handlers, we check this bool in our
+   * override callback and simply return early if we are not supposed to do
+   * anything.
+   */
+  setShouldOverride(newState) {
+    this._shouldOverride = newState;
+  }
+
+  init() {
+    UserAgentOverrides.addComplexOverride(this.overrideCallback.bind(this));
+  }
+
+  overrideCallback(channel, defaultUA) {
+    if (!this._shouldOverride) {
+      return false;
+    }
+
+    let uaOverride = this.lookupUAOverride(channel.URI, defaultUA);
+    if (uaOverride) {
+      console.log("The user agent has been overridden for compatibility reasons.");
+      return uaOverride;
+    }
+
+    return false;
+  }
+
+  /**
+   * Try to use the eTLDService to get the base domain (will return example.com
+   * for http://foo.bar.example.com/foo/bar).
+   *
+   * However, the eTLDService is a bit picky and throws whenever we pass a
+   * blank host name or an IP into it, see bug 1337785. Since we do not plan on
+   * override UAs for such cases, we simply catch everything and return false.
+   */
+  getBaseDomainFromURI(uri) {
+    try {
+      return Services.eTLD.getBaseDomain(uri);
+    } catch (_) {
+      return false;
+    }
+  }
+
+  /**
+   * This function returns a User Agent based on the URI passed into. All
+   * override rules are defined in data/ua_overrides.jsm and the required format
+   * is explained there.
+   *
+   * Since it is expected and designed to have more than one override per base
+   * domain, we have to loop over this._overrides[baseDomain], which contains
+   * all available overrides.
+   *
+   * If the uriMatcher function returns true, the uaTransformer function gets
+   * called and its result will be used as the Use Agent for the current
+   * request.
+   *
+   * If there are more than one possible overrides, that is if two or more
+   * uriMatchers would return true, the first one gets applied.
+   */
+  lookupUAOverride(uri, defaultUA) {
+    let baseDomain = this.getBaseDomainFromURI(uri);
+    if (baseDomain && this._overrides[baseDomain]) {
+      for (let uaOverride of this._overrides[baseDomain]) {
+        if (uaOverride.uriMatcher(uri.specIgnoringRef)) {
+          return uaOverride.uaTransformer(defaultUA);
+        }
+      }
+    }
+
+    return false;
+  }
+}
+
+var EXPORTED_SYMBOLS = ["UAOverrider"]; /* exported UAOverrider */
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/install.rdf.in
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+#filter substitution
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:install-manifest">
+    <em:id>webcompat@mozilla.org</em:id>
+    <em:version>2.0.1</em:version>
+    <em:type>2</em:type>
+    <em:bootstrap>true</em:bootstrap>
+    <em:multiprocessCompatible>true</em:multiprocessCompatible>
+    <em:hasEmbeddedWebExtension>true</em:hasEmbeddedWebExtension>
+
+    <!-- Firefox Desktop -->
+    <em:targetApplication>
+      <Description>
+        <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
+        <em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
+        <em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Firefox for Android -->
+    <em:targetApplication>
+      <Description>
+        <em:id>{aa3c5121-dab2-40e2-81ca-7ea25febc110}</em:id>
+        <em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
+        <em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
+      </Description>
+    </em:targetApplication>
+
+    <!-- Front End MetaData -->
+    <em:name>Web Compat</em:name>
+    <em:description>Urgent post-release fixes for web compatibility.</em:description>
+  </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/jar.mn
@@ -0,0 +1,3 @@
+[features/webcompat@mozilla.org] chrome.jar:
+% content webcompat %content/
+  content/ (content/*)
deleted file mode 100644
--- a/browser/extensions/webcompat/manifest.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "manifest_version": 2,
-  "name": "Web Compat",
-  "description": "Urgent post-release fixes for web compatibility.",
-  "version": "3.0.0",
-
-  "applications": {
-    "gecko": {
-      "id": "webcompat@mozilla.org",
-      "strict_min_version": "59.0b5"
-    }
-  },
-
-  "experiment_apis": {
-    "aboutConfigPrefs": {
-      "schema": "aboutConfigPrefs.json",
-      "parent": {
-        "scopes": ["addon_parent"],
-        "script": "aboutConfigPrefs.js",
-        "paths": [["aboutConfigPrefs"]]
-      }
-    }
-  },
-
-  "permissions": [
-    "webRequest",
-    "webRequestBlocking",
-    "<all_urls>"
-  ],
-
-  "background": {
-    "scripts": [
-      "injections.js",
-      "ua_overrides.js"
-    ]
-  }
-}
--- a/browser/extensions/webcompat/moz.build
+++ b/browser/extensions/webcompat/moz.build
@@ -3,30 +3,38 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
 DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
 
 FINAL_TARGET_FILES.features['webcompat@mozilla.org'] += [
-  'aboutConfigPrefs.js',
-  'aboutConfigPrefs.json',
-  'injections.js',
-  'manifest.json',
-  'ua_overrides.js'
+  'bootstrap.js'
+]
+
+FINAL_TARGET_FILES.features['webcompat@mozilla.org']['webextension'] += [
+  'webextension/background.js',
+  'webextension/manifest.json'
+]
+
+FINAL_TARGET_FILES.features['webcompat@mozilla.org']['webextension']['injections']['css'] += [
+  'webextension/injections/css/bug0000000-dummy-css-injection.css'
 ]
 
-FINAL_TARGET_FILES.features['webcompat@mozilla.org']['injections']['css'] += [
-  'injections/css/bug0000000-dummy-css-injection.css'
+FINAL_TARGET_FILES.features['webcompat@mozilla.org']['webextension']['injections']['js'] += [
+  'webextension/injections/js/bug0000000-dummy-js-injection.js',
+  'webextension/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js',
+  'webextension/injections/js/bug1457335-histography.io-ua-change.js',
+  'webextension/injections/js/bug1472075-bankofamerica.com-ua-change.js',
+  'webextension/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js',
+  'webextension/injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js'
 ]
 
-FINAL_TARGET_FILES.features['webcompat@mozilla.org']['injections']['js'] += [
-  'injections/js/bug0000000-dummy-js-injection.js',
-  'injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js',
-  'injections/js/bug1457335-histography.io-ua-change.js',
-  'injections/js/bug1472075-bankofamerica.com-ua-change.js',
-  'injections/js/bug1472081-election.gov.np-window.sidebar-shim.js',
-  'injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js'
+FINAL_TARGET_PP_FILES.features['webcompat@mozilla.org'] += [
+  'install.rdf.in'
 ]
 
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
+JAR_MANIFESTS += ['jar.mn']
+
 with Files('**'):
   BUG_COMPONENT = ('Web Compatibility Tools', 'Go Faster')
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/test/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test"
+  ]
+};
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/test/browser.ini
@@ -0,0 +1,4 @@
+[DEFAULT]
+
+[browser_check_installed.js]
+[browser_overrider.js]
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/test/browser_check_installed.js
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+add_task(async function installed() {
+  let addon = await AddonManager.getAddonByID("webcompat@mozilla.org");
+  isnot(addon, null, "Webcompat addon should exist");
+  is(addon.name, "Web Compat");
+  ok(addon.isCompatible, "Webcompat addon is compatible with Firefox");
+  ok(!addon.appDisabled, "Webcompat addon is not app disabled");
+  ok(addon.isActive, "Webcompat addon is active");
+  is(addon.type, "extension", "Webcompat addon is type extension");
+});
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/test/browser_overrider.js
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "UAOverrider", "chrome://webcompat/content/lib/ua_overrider.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "IOService", "@mozilla.org/network/io-service;1", "nsIIOService");
+
+function getnsIURI(uri) {
+  return IOService.newURI(uri, "utf-8");
+}
+
+add_task(function test() {
+  let overrider = new UAOverrider([
+    {
+      baseDomain: "example.org",
+      uaTransformer: () => "Test UA",
+    },
+  ]);
+
+  let finalUA = overrider.lookupUAOverride(getnsIURI("http://www.example.org/foobar/"));
+  is(finalUA, "Test UA", "Overrides the UA without a matcher function");
+});
+
+add_task(function test() {
+  let overrider = new UAOverrider([
+    {
+      baseDomain: "example.org",
+      uriMatcher: () => false,
+      uaTransformer: () => "Test UA",
+    },
+  ]);
+
+  let finalUA = overrider.lookupUAOverride(getnsIURI("http://www.example.org/foobar/"));
+  isnot(finalUA, "Test UA", "Does not override the UA with the matcher returning false");
+});
deleted file mode 100644
--- a/browser/extensions/webcompat/ua_overrides.js
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- * For detailed information on our policies, and a documention on this format
- * and its possibilites, please check the Mozilla-Wiki at
- *
- * https://wiki.mozilla.org/Compatibility/Go_Faster_Addon/Override_Policies_and_Workflows#User_Agent_overrides
- */
-const UAOverrides = {
-  universal: [
-    /*
-     * This is a dummy override that applies a Chrome UA to a dummy site that
-     * blocks all browsers but Chrome.
-     *
-     * This was only put in place to allow QA to test this system addon on an
-     * actual site, since we were not able to find a proper override in time.
-     */
-    {
-      matches: ["*://webcompat-addon-testcases.schub.io/*"],
-      uaTransformer: (originalUA) => {
-        let prefix = originalUA.substr(0, originalUA.indexOf(")") + 1);
-        return `${prefix} AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36`;
-      },
-    },
-  ],
-  desktop: [],
-  android: [
-    /*
-     * Bug 1480710 - m.imgur.com - Build UA override
-     * WebCompat issue #13154 - https://webcompat.com/issues/13154
-     *
-     * imgur returns a 404 for requests to CSS and JS file if requested with a Fennec
-     * User Agent. By removing the Fennec identifies and adding Chrome Mobile's, we
-     * receive the correct CSS and JS files.
-     */
-    {
-      matches: ["*://m.imgur.com/*"],
-      uaTransformer: (originalUA) => {
-        let prefix = originalUA.substr(0, originalUA.indexOf(")") + 1);
-        return prefix + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.85 Mobile Safari/537.36";
-      },
-    },
-
-    /*
-     * Bug 755590 - sites.google.com - top bar doesn't show up in Firefox for Android
-     *
-     * Google Sites does show a different top bar template based on the User Agent.
-     * For Fennec, this results in a broken top bar. Appending Chrome and Mobile Safari
-     * identifiers to the UA results in a correct rendering.
-     */
-    {
-      matches: ["*://sites.google.com/*"],
-      uaTransformer: (originalUA) => {
-        return originalUA + " Chrome/68.0.3440.85 Mobile Safari/537.366";
-      },
-    },
-
-    /*
-     * Bug 945963 - tieba.baidu.com serves simplified mobile content to Firefox Android
-     * WebCompat issue #18455 - https://webcompat.com/issues/18455
-     *
-     * tieba.baidu.com and tiebac.baidu.com serve a heavily simplified and less functional
-     * mobile experience to Firefox for Android users. Adding the AppleWebKit indicator
-     * to the User Agent gets us the same experience.
-     */
-    {
-      matches: ["*://tieba.baidu.com/*", "*://tiebac.baidu.com/*"],
-      uaTransformer: (originalUA) => {
-        return originalUA + " AppleWebKit/537.36 (KHTML, like Gecko)";
-      },
-    },
-  ],
-};
-
-/* globals browser */
-
-let activeListeners = [];
-function buildAndRegisterListener(matches, transformer) {
-  let listener = (details) => {
-    for (var header of details.requestHeaders) {
-      if (header.name.toLowerCase() === "user-agent") {
-        header.value = transformer(header.value);
-      }
-    }
-    return {requestHeaders: details.requestHeaders};
-  };
-
-  browser.webRequest.onBeforeSendHeaders.addListener(
-    listener,
-    {urls: matches},
-    ["blocking", "requestHeaders"]
-  );
-
-  activeListeners.push(listener);
-}
-
-async function registerUAOverrides() {
-  let platform = "desktop";
-  let platformInfo = await browser.runtime.getPlatformInfo();
-  if (platformInfo.os == "android") {
-    platform = "android";
-  }
-
-  let targetOverrides = UAOverrides.universal.concat(UAOverrides[platform]);
-  targetOverrides.forEach((override) => {
-    buildAndRegisterListener(override.matches, override.uaTransformer);
-  });
-}
-
-function unregisterUAOverrides() {
-  activeListeners.forEach((listener) => {
-    browser.webRequest.onBeforeSendHeaders.removeListener(listener);
-  });
-
-  activeListeners = [];
-}
-
-const OVERRIDE_PREF = "perform_ua_overrides";
-function checkOverridePref() {
-  browser.aboutConfigPrefs.getPref(OVERRIDE_PREF).then(value => {
-    if (value === undefined) {
-      browser.aboutConfigPrefs.setPref(OVERRIDE_PREF, true);
-    } else if (value === false) {
-      unregisterUAOverrides();
-    } else {
-      registerUAOverrides();
-    }
-  });
-}
-browser.aboutConfigPrefs.onPrefChange.addListener(checkOverridePref, OVERRIDE_PREF);
-checkOverridePref();
rename from browser/extensions/webcompat/injections.js
rename to browser/extensions/webcompat/webextension/background.js
--- a/browser/extensions/webcompat/injections.js
+++ b/browser/extensions/webcompat/webextension/background.js
@@ -81,22 +81,14 @@ port.onMessage.addListener((message) => 
         registerContentScripts();
       } else {
         unregisterContentScripts();
       }
       break;
   }
 });
 
-const INJECTION_PREF = "perform_injections";
-function checkInjectionPref() {
-  browser.aboutConfigPrefs.getPref(INJECTION_PREF).then(value => {
-    if (value === undefined) {
-      browser.aboutConfigPrefs.setPref(INJECTION_PREF, true);
-    } else if (value === false) {
-      unregisterContentScripts();
-    } else {
-      registerContentScripts();
-    }
-  });
-}
-browser.aboutConfigPrefs.onPrefChange.addListener(checkInjectionPref, INJECTION_PREF);
-checkInjectionPref();
+/**
+ * Note that we reset all preferences on extension startup, so the injections will
+ * never be disabled when this loads up. Because of that, we can simply register
+ * right away.
+ */
+registerContentScripts();
rename from browser/extensions/webcompat/injections/css/bug0000000-dummy-css-injection.css
rename to browser/extensions/webcompat/webextension/injections/css/bug0000000-dummy-css-injection.css
rename from browser/extensions/webcompat/injections/js/bug0000000-dummy-js-injection.js
rename to browser/extensions/webcompat/webextension/injections/js/bug0000000-dummy-js-injection.js
rename from browser/extensions/webcompat/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js
rename to browser/extensions/webcompat/webextension/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js
rename from browser/extensions/webcompat/injections/js/bug1457335-histography.io-ua-change.js
rename to browser/extensions/webcompat/webextension/injections/js/bug1457335-histography.io-ua-change.js
rename from browser/extensions/webcompat/injections/js/bug1472075-bankofamerica.com-ua-change.js
rename to browser/extensions/webcompat/webextension/injections/js/bug1472075-bankofamerica.com-ua-change.js
rename from browser/extensions/webcompat/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js
rename to browser/extensions/webcompat/webextension/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js
rename from browser/extensions/webcompat/injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js
rename to browser/extensions/webcompat/webextension/injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js
new file mode 100644
--- /dev/null
+++ b/browser/extensions/webcompat/webextension/manifest.json
@@ -0,0 +1,23 @@
+{
+  "manifest_version": 2,
+  "name": "Web Compat",
+  "description": "Urgent post-release fixes for web compatibility.",
+  "version": "2.0",
+
+  "applications": {
+    "gecko": {
+      "id": "webcompat@mozilla.org",
+      "strict_min_version": "59.0b5"
+    }
+  },
+
+  "permissions": [
+    "<all_urls>"
+  ],
+
+  "background": {
+    "scripts": [
+      "background.js"
+    ]
+  }
+}
--- a/dom/serviceworkers/test/test_cross_origin_url_after_redirect.html
+++ b/dom/serviceworkers/test/test_cross_origin_url_after_redirect.html
@@ -37,15 +37,14 @@
   }
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_gzip_redirect.html
+++ b/dom/serviceworkers/test/test_gzip_redirect.html
@@ -76,14 +76,13 @@
       }).then(SimpleTest.finish);
   }
 
   SimpleTest.waitForExplicitFinish();
   SpecialPowers.pushPrefEnv({"set": [
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
-    ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
   ]}, runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_https_origin_after_redirect.html
+++ b/dom/serviceworkers/test/test_https_origin_after_redirect.html
@@ -44,15 +44,14 @@
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_https_origin_after_redirect_cached.html
+++ b/dom/serviceworkers/test/test_https_origin_after_redirect_cached.html
@@ -44,15 +44,14 @@
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_openWindow.html
+++ b/dom/serviceworkers/test/test_openWindow.html
@@ -97,14 +97,13 @@ https://bugzilla.mozilla.org/show_bug.cg
     ["dom.serviceWorkers.exemptFromPerDomainMax", true],
     ["dom.serviceWorkers.enabled", true],
     ["dom.serviceWorkers.testing.enabled", true],
     ["dom.webnotifications.workers.enabled", true],
     ["dom.webnotifications.serviceworker.enabled", true],
     ["notification.prompt.testing", true],
     ["dom.serviceWorkers.disable_open_click_delay", 1000],
     ["dom.serviceWorkers.idle_timeout", 299999],
-    ["dom.serviceWorkers.idle_extended_timeout", 299999],
-    ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
+    ["dom.serviceWorkers.idle_extended_timeout", 299999]
   ]}, runTest);
 </script>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_origin_after_redirect.html
+++ b/dom/serviceworkers/test/test_origin_after_redirect.html
@@ -44,15 +44,14 @@
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_origin_after_redirect_cached.html
+++ b/dom/serviceworkers/test/test_origin_after_redirect_cached.html
@@ -44,15 +44,14 @@
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_origin_after_redirect_to_https.html
+++ b/dom/serviceworkers/test/test_origin_after_redirect_to_https.html
@@ -44,15 +44,14 @@
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>
--- a/dom/serviceworkers/test/test_origin_after_redirect_to_https_cached.html
+++ b/dom/serviceworkers/test/test_origin_after_redirect_to_https_cached.html
@@ -44,15 +44,14 @@
 
   SimpleTest.waitForExplicitFinish();
   onload = function() {
     SpecialPowers.pushPrefEnv({"set": [
       ["dom.serviceWorkers.exemptFromPerDomainMax", true],
       ["dom.serviceWorkers.enabled", true],
       ["dom.serviceWorkers.testing.enabled", true],
       ["dom.caches.enabled", true],
-      ["extensions.webcompat.perform_ua_overrides", false], // bug 1495748
     ]}, runTest);
   };
 </script>
 </pre>
 </body>
 </html>