Bug 1308271 - Import sources of the WebCompat Go Faster add-on V1. r=Felipe

MozReview-Commit-ID: 58iV4MqTeKA

--HG--
rename : browser/extensions/webcompat/test/browser/browser.ini => browser/extensions/webcompat/test/browser.ini
rename : browser/extensions/webcompat/test/browser/browser_check_installed.js => browser/extensions/webcompat/test/browser_check_installed.js
extra : rebase_source : e82dd055860f8d4d40e4af90a68dfd0896b8d6f1
This commit is contained in:
Dennis Schubert 2017-01-25 20:15:11 +01:00
Родитель 5b02eb2870
Коммит 3a74451338
10 изменённых файлов: 316 добавлений и 26 удалений

74
browser/extensions/webcompat/bootstrap.js поставляемый
Просмотреть файл

@ -2,8 +2,72 @@
* 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";
function startup() {}
function shutdown() {}
function install() {}
function uninstall() {}
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
const PREF_BRANCH = "extensions.webcompat.";
const PREF_DEFAULTS = {perform_ua_overrides: true};
const UA_ENABLE_PREF_NAME = "extensions.webcompat.perform_ua_overrides";
XPCOMUtils.defineLazyModuleGetter(this, "UAOverrider", "chrome://webcompat/content/lib/ua_overrider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "UAOverrides", "chrome://webcompat/content/data/ua_overrides.jsm");
let overrider;
function UAEnablePrefObserver() {
let isEnabled = Services.prefs.getBoolPref(UA_ENABLE_PREF_NAME);
if (isEnabled && !overrider) {
overrider = new UAOverrider(UAOverrides);
overrider.init();
} else if (!isEnabled && overrider) {
overrider.uninit();
overrider = null;
}
}
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(UA_ENABLE_PREF_NAME);
Services.prefs.addObserver(UA_ENABLE_PREF_NAME, UAEnablePrefObserver, false);
overrider = new UAOverrider(UAOverrides);
overrider.init();
};
this.shutdown = function() {
Services.prefs.removeObserver(UA_ENABLE_PREF_NAME, UAEnablePrefObserver);
if (overrider) {
overrider.uninit();
}
};

Просмотреть файл

@ -0,0 +1,60 @@
/* 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/. */
/**
* This is an array of objects that specify user agent overrides. Each object
* can have three attributes:
*
* * `baseDomain`, required: The base domain that further checks and user
* agents override are applied to. This does not include subdomains.
* * `uriMatcher`: Function that gets the requested URI passed in the first
* argument and needs to return boolean whether or not the override should
* be applied. If not provided, the user agent override will be applied
* every time.
* * `uaTransformer`, required: Function that gets the original Firefox user
* agent passed as its first argument and needs to return a string that
* will be used as the the user agent for this URI.
*
* Examples:
*
* Gets applied for all requests to mozilla.org and subdomains:
*
* ```
* {
* baseDomain: "mozilla.org",
* uaTransformer: (originalUA) => `Ohai Mozilla, it's me, ${originalUA}`
* }
* ```
*
* Applies to *.example.com/app/*:
*
* ```
* {
* baseDomain: "example.com",
* uriMatcher: (uri) => uri.includes("/app/"),
* uaTransformer: (originalUA) => originalUA.replace("Firefox", "Otherfox")
* }
* ```
*/
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",
uriMatcher: (uri) => uri.includes("webcompat-ua-dummy.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`;
}
}
];
this.EXPORTED_SYMBOLS = ["UAOverrides"]; /* exported UAOverrides */

Просмотреть файл

@ -0,0 +1,122 @@
/* 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/. */
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Console.jsm");
const DefaultUA = Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).userAgent;
const NS_HTTP_ON_USERAGENT_REQUEST_TOPIC = "http-on-useragent-request";
XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "eTLDService", "@mozilla.org/network/effective-tld-service;1", "nsIEffectiveTLDService");
class UAOverrider {
constructor(overrides) {
this._overrides = {};
this._overrideForURICache = new Map();
this.initOverrides(overrides);
}
initOverrides(overrides) {
for (let override of overrides) {
if (!this._overrides[override.baseDomain]) {
this._overrides[override.baseDomain] = [];
}
if (!override.uriMatcher) {
override.uriMatcher = () => true;
}
this._overrides[override.baseDomain].push(override);
}
}
init() {
Services.obs.addObserver(this, NS_HTTP_ON_USERAGENT_REQUEST_TOPIC, false);
}
uninit() {
Services.obs.removeObserver(this, NS_HTTP_ON_USERAGENT_REQUEST_TOPIC);
}
observe(subject, topic) {
if (topic !== NS_HTTP_ON_USERAGENT_REQUEST_TOPIC) {
return;
}
let channel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
let uaOverride = this.getUAForURI(channel.URI);
if (uaOverride) {
console.log("The user agent has been overridden for compatibility reasons.");
channel.setRequestHeader("User-Agent", uaOverride, false);
}
}
getUAForURI(uri) {
let bareUri = uri.specIgnoringRef;
if (this._overrideForURICache.has(bareUri)) {
// Although the cache could have an entry to a bareUri, `false` is also
// a value that could be cached. A `false` cache entry means that there
// is no override for this URI.
// We cache these to avoid having to walk through all overrides to see
// if a domain matches.
return this._overrideForURICache.get(bareUri);
}
let finalUA = this.lookupUAOverride(uri);
this._overrideForURICache.set(bareUri, finalUA);
return finalUA;
}
/**
* This function gets called from within the embedded webextension to check
* if the current site has been overriden or not. We only check the cached
* URI list here, but that's safe in our case since the tabUpdateHandler will
* always run after our message observer.
*/
hasUAForURIInCache(uri) {
let bareUri = uri.specIgnoringRef;
if (this._overrideForURICache.has(bareUri)) {
return !!this._overrideForURICache.get(bareUri);
}
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) {
let baseDomain = eTLDService.getBaseDomain(uri);
if (this._overrides[baseDomain]) {
for (let uaOverride of this._overrides[baseDomain]) {
if (uaOverride.uriMatcher(uri.specIgnoringRef)) {
return uaOverride.uaTransformer(DefaultUA);
}
}
}
return false;
}
}
this.EXPORTED_SYMBOLS = ["UAOverrider"]; /* exported UAOverrider */

Просмотреть файл

@ -0,0 +1,3 @@
[features/webcompat@mozilla.org] chrome.jar:
% content webcompat %content/
content/ (content/*)

Просмотреть файл

@ -15,4 +15,5 @@ FINAL_TARGET_PP_FILES.features['webcompat@mozilla.org'] += [
'install.rdf.in'
]
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
JAR_MANIFESTS += ['jar.mn']

Просмотреть файл

@ -1,3 +1,4 @@
[DEFAULT]
[browser_check_installed.js]
[browser_overrider.js]

Просмотреть файл

@ -1,7 +0,0 @@
"use strict";
module.exports = {
"extends": [
"../../../../../testing/mochitest/browser.eslintrc.js"
]
};

Просмотреть файл

@ -1,13 +0,0 @@
"use strict";
add_task(function* test_enabled() {
let addon = yield new Promise(
resolve => AddonManager.getAddonByID("webcompat@mozilla.org", resolve)
);
isnot(addon, null, "Check addon exists");
is(addon.version, "1.0", "Check version");
is(addon.name, "Web Compat", "Check name");
ok(addon.isCompatible, "Check application compatibility");
ok(!addon.appDisabled, "Check not app disabled");
ok(addon.isActive, "Check addon is active");
});

Просмотреть файл

@ -0,0 +1,19 @@
/* 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/. */
/* global AddonManager */
"use strict";
add_task(function* installed() {
let addon = yield new Promise(
(resolve) => AddonManager.getAddonByID("webcompat@mozilla.org", resolve)
);
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");
});

Просмотреть файл

@ -0,0 +1,40 @@
/* 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/. */
/* globals XPCOMUtils, UAOverrider, IOService */
"use strict";
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(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.getUAForURI(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.getUAForURI(getnsIURI("http://www.example.org/foobar/"));
isnot(finalUA, "Test UA", "Does not override the UA with the matcher returning false");
});