--- a/mobile/android/extensions/moz.build
+++ b/mobile/android/extensions/moz.build
@@ -2,13 +2,17 @@
# vim: set filetype=python:
# 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/.
with Files('**'):
BUG_COMPONENT = ('Firefox for Android', 'General')
+DIRS += [
+ 'webcompat',
+]
+
# Only include the following system add-ons if building Nightly
if CONFIG['NIGHTLY_BUILD']:
DIRS += [
'gws-and-facebook-chrome-spoof',
]
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/bootstrap.js
@@ -0,0 +1,117 @@
+/* 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/XPCOMUtils.jsm");
+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/mobile/android/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/mobile/android/extensions/webcompat/content/lib/ua_overrider.jsm
@@ -0,0 +1,127 @@
+/* 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/XPCOMUtils.jsm");
+
+ChromeUtils.defineModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
+ChromeUtils.defineModuleGetter(this, "UserAgentOverrides", "resource://gre/modules/UserAgentOverrides.jsm");
+XPCOMUtils.defineLazyServiceGetter(this, "eTLDService", "@mozilla.org/network/effective-tld-service;1", "nsIEffectiveTLDService");
+
+class UAOverrider {
+ constructor(overrides) {
+ this._overrides = {};
+ this._shouldOverride = true;
+
+ this.initOverrides(overrides);
+ }
+
+ initOverrides(overrides) {
+ // on xpcshell tests, there is no impleentation 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 (_) {}
+
+ 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 eTLDService.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/mobile/android/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/mobile/android/extensions/webcompat/jar.mn
@@ -0,0 +1,3 @@
+[features/webcompat@mozilla.org] chrome.jar:
+% content webcompat %content/
+ content/ (content/*)
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/moz.build
@@ -0,0 +1,39 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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'] += [
+ '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']['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'
+]
+
+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/mobile/android/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/mobile/android/extensions/webcompat/test/browser.ini
@@ -0,0 +1,4 @@
+[DEFAULT]
+
+[browser_check_installed.js]
+[browser_overrider.js]
new file mode 100644
--- /dev/null
+++ b/mobile/android/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/mobile/android/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");
+});
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/background.js
@@ -0,0 +1,88 @@
+/**
+ * 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 contentScripts = {
+ universal: [
+ {
+ matches: ["*://webcompat-addon-testcases.schub.io/*"],
+ css: [{file: "injections/css/bug0000000-dummy-css-injection.css"}],
+ js: [{file: "injections/js/bug0000000-dummy-js-injection.js"}],
+ runAt: "document_start"
+ }
+ ],
+ desktop: [
+ {
+ matches: ["https://ib.absa.co.za/*"],
+ js: [{file: "injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js"}],
+ runAt: "document_start"
+ },
+ {
+ matches: ["http://histography.io/*"],
+ js: [{file: "injections/js/bug1457335-histography.io-ua-change.js"}],
+ runAt: "document_start"
+ },
+ {
+ matches: ["*://*.bankofamerica.com/*"],
+ js: [{file: "injections/js/bug1472075-bankofamerica.com-ua-change.js"}],
+ runAt: "document_start"
+ },
+ {
+ matches: ["http://202.166.205.141/bbvrs/*"],
+ js: [{file: "injections/js/bug1472081-election.gov.np-window.sidebar-shim.js"}],
+ runAt: "document_start",
+ allFrames: true
+ }
+ ],
+ fennec: []
+};
+
+/* globals browser */
+
+let port = browser.runtime.connect();
+let registeredContentScripts = [];
+
+async function registerContentScripts() {
+ let platform = "desktop";
+ let platformInfo = await browser.runtime.getPlatformInfo();
+ if (platformInfo.os == "android") {
+ platform = "fennec";
+ }
+
+ let targetContentScripts = contentScripts.universal.concat(contentScripts[platform]);
+ targetContentScripts.forEach(async (contentScript) => {
+ try {
+ let handle = await browser.contentScripts.register(contentScript);
+ registeredContentScripts.push(handle);
+ } catch (ex) {
+ console.error("Registering WebCompat GoFaster content scripts failed: ", ex);
+ }
+ });
+}
+
+function unregisterContentScripts() {
+ registeredContentScripts.forEach((contentScript) => {
+ contentScript.unregister();
+ });
+}
+
+port.onMessage.addListener((message) => {
+ switch (message.type) {
+ case "injection-pref-changed":
+ if (message.prefState) {
+ registerContentScripts();
+ } else {
+ unregisterContentScripts();
+ }
+ break;
+ }
+});
+
+/**
+ * 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();
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/injections/css/bug0000000-dummy-css-injection.css
@@ -0,0 +1,3 @@
+#css-injection.red {
+ background-color: #0f0;
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/injections/js/bug0000000-dummy-js-injection.js
@@ -0,0 +1,11 @@
+"use strict";
+
+/* globals exportFunction */
+
+Object.defineProperty(window.wrappedJSObject, "isTestFeatureSupported", {
+ get: exportFunction(function() {
+ return true;
+ }, window),
+
+ set: exportFunction(function() {}, window)
+});
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js
@@ -0,0 +1,25 @@
+"use strict";
+
+/**
+ * Bug 1452707 - Build site patch for ib.absa.co.za
+ * WebCompat issue #16401 - https://webcompat.com/issues/16401
+ *
+ * The online banking at ib.absa.co.za detect if window.controllers is a
+ * non-falsy value to detect if the current browser is Firefox or something
+ * else. In bug 1448045, this shim has been disabled for Firefox Nightly 61+,
+ * which breaks the UA detection on this site and results in a "Browser
+ * unsuppored" error message.
+ *
+ * This site patch simply sets window.controllers to a string, resulting in
+ * their check to work again.
+ */
+
+/* globals exportFunction */
+
+Object.defineProperty(window.wrappedJSObject, "controllers", {
+ get: exportFunction(function() {
+ return "window.controllers has been shimmed with a string to get this site's browser detection to work in Firefox 61+.";
+ }, window),
+
+ set: exportFunction(function() {}, window)
+});
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/injections/js/bug1457335-histography.io-ua-change.js
@@ -0,0 +1,30 @@
+"use strict";
+
+/**
+ * Bug 1457335 - histography.io - Override UA & navigator.vendor
+ * WebCompat issue #1804 - https://webcompat.com/issues/1804
+ *
+ * This site is using a strict matching of navigator.userAgent and
+ * navigator.vendor to allow access for Safari or Chrome. Here, we set the
+ * values appropriately so we get recognized as Chrome.
+ */
+
+/* globals exportFunction */
+
+const CHROME_UA = navigator.userAgent + " Chrome for WebCompat";
+
+Object.defineProperty(window.wrappedJSObject.navigator, "userAgent", {
+ get: exportFunction(function() {
+ return CHROME_UA;
+ }, window),
+
+ set: exportFunction(function() {}, window)
+});
+
+Object.defineProperty(window.wrappedJSObject.navigator, "vendor", {
+ get: exportFunction(function() {
+ return "Google Inc.";
+ }, window),
+
+ set: exportFunction(function() {}, window)
+});
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/injections/js/bug1472075-bankofamerica.com-ua-change.js
@@ -0,0 +1,41 @@
+"use strict";
+
+/**
+ * Bug 1472075 - Build UA override for Bank of America for OSX & Linux
+ * WebCompat issue #2787 - https://webcompat.com/issues/2787
+ *
+ * BoA is showing a red warning to Linux and macOS users, while accepting
+ * Windows users without warning. From our side, there is no difference here
+ * and we receive a lot of user complains about the warnings, so we spoof
+ * as Firefox on Windows in those cases.
+ */
+
+/* globals exportFunction */
+
+if (!navigator.platform.includes("Win") && !navigator.userAgent.includes("Android")) {
+ const WINDOWS_UA = navigator.userAgent.replace(/\(.*; rv:/i, "(Windows NT 10.0; Win64; x64; rv:");
+
+ Object.defineProperty(window.wrappedJSObject.navigator, "userAgent", {
+ get: exportFunction(function() {
+ return WINDOWS_UA;
+ }, window),
+
+ set: exportFunction(function() {}, window)
+ });
+
+ Object.defineProperty(window.wrappedJSObject.navigator, "appVersion", {
+ get: exportFunction(function() {
+ return "appVersion";
+ }, window),
+
+ set: exportFunction(function() {}, window)
+ });
+
+ Object.defineProperty(window.wrappedJSObject.navigator, "platform", {
+ get: exportFunction(function() {
+ return "Win64";
+ }, window),
+
+ set: exportFunction(function() {}, window)
+ });
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/extensions/webcompat/webextension/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js
@@ -0,0 +1,21 @@
+"use strict";
+
+/**
+ * Bug 1472081 - election.gov.np - Override window.sidebar with something falsey
+ * WebCompat issue #11622 - https://webcompat.com/issues/11622
+ *
+ * This site is blocking onmousedown and onclick if window.sidebar is something
+ * that evaluates to true, rendering the form fields unusable. This patch
+ * overrides window.sidebar with false, so the blockign event handlers won't
+ * get registered.
+ */
+
+/* globals exportFunction */
+
+Object.defineProperty(window.wrappedJSObject, "sidebar", {
+ get: exportFunction(function() {
+ return false;
+ }, window),
+
+ set: exportFunction(function() {}, window)
+});
new file mode 100644
--- /dev/null
+++ b/mobile/android/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"
+ ]
+ }
+}