bug 1287125 Lock down mozAddonManager.install() r=rhelmer

MozReview-Commit-ID: 7wLqVme2Yzi

--HG--
extra : rebase_source : 870ddfc2a92599b3ce6f8ab1b850f8bde944575e
This commit is contained in:
Andrew Swan 2016-07-15 11:40:45 -07:00
parent 5d733ce029
commit e8c3e2138f
3 changed files with 69 additions and 9 deletions

View File

@ -46,6 +46,7 @@ const PREF_SELECTED_LOCALE = "general.useragent.locale";
const UNKNOWN_XPCOM_ABI = "unknownABI";
const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion";
const PREF_WEBAPI_TESTING = "extensions.webapi.testing";
const UPDATE_REQUEST_VERSION = 2;
const CATEGORY_UPDATE_PARAMS = "extension-update-params";
@ -66,6 +67,13 @@ const TOOLKIT_ID = "toolkit@mozilla.org";
const VALID_TYPES_REGEXP = /^[\w\-]+$/;
const WEBAPI_INSTALL_HOSTS = ["addons.mozilla.org", "addons.cdn.mozilla.net"];
const WEBAPI_TEST_INSTALL_HOSTS = [
"addons.allizom.org", "addons-stage-cdn.allizom.org",
"addons-dev.allizom.org", "addons-dev-cdn-allizom.org",
"example.com",
];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
@ -2896,7 +2904,29 @@ var AddonManagerInternal = {
},
createInstall(target, options) {
return new Promise((resolve) => {
// Throw an appropriate error if the given URL is not valid
// as an installation source. Return silently if it is okay.
function checkInstallUrl(url) {
let host = Services.io.newURI(options.url, null, null).host;
if (WEBAPI_INSTALL_HOSTS.includes(host)) {
return;
}
if (Services.prefs.getBoolPref(PREF_WEBAPI_TESTING)
&& WEBAPI_TEST_INSTALL_HOSTS.includes(host)) {
return;
}
throw new Error(`Install from ${host} not permitted`);
}
return new Promise((resolve, reject) => {
try {
checkInstallUrl(options.url);
} catch (err) {
reject({message: err.message});
return;
}
let newInstall = install => {
let id = this.nextInstall++;
let listener = this.makeListener(id, target);

View File

@ -248,7 +248,9 @@ amManager.prototype = {
}
AddonManager.addAddonListener(this.addonListener);
} else {
AddonManager.removeAddonListener(this.addonListener);
if (this.addonListener) {
AddonManager.removeAddonListener(this.addonListener);
}
}
}
}

View File

@ -5,13 +5,6 @@ const ID = "webapi_install@tests.mozilla.org";
// eh, would be good to just stat the real file instead of this...
const XPI_LEN = 4782;
Services.prefs.setBoolPref("extensions.webapi.testing", true);
Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("extensions.webapi.testing");
Services.prefs.clearUserPref("extensions.install.requireBuiltInCerts");
});
function waitForClear() {
const MSG = "WebAPICleanup";
return new Promise(resolve => {
@ -28,6 +21,14 @@ function waitForClear() {
});
}
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["extensions.webapi.testing", true],
["extensions.install.requireBuiltInCerts", false]],
});
info("added preferences");
});
// Wrapper around a common task to run in the content process to test
// the mozAddonManager API. Takes a URL for the XPI to install and an
// array of steps, each of which can either be an action to take
@ -240,3 +241,30 @@ add_task(makeInstallTest(function* (browser) {
ok(AddonManager.webAPI.installs.size > 0, "webAPI is tracking the AddonInstall");
}));
add_task(function* test_permissions() {
function testBadUrl(url, pattern, successMessage) {
return BrowserTestUtils.withNewTab(TESTPAGE, function* (browser) {
let result = yield ContentTask.spawn(browser, {url, pattern}, function (opts) {
return new Promise(resolve => {
content.navigator.mozAddonManager.createInstall({url: opts.url})
.then(() => {
resolve({success: false, message: "createInstall should not have succeeded"});
}, err => {
if (err.message.match(new RegExp(opts.pattern))) {
resolve({success: true});
}
resolve({success: false, message: `Wrong error message: ${err.message}`});
});
});
});
is(result.success, true, result.message || successMessage);
});
}
yield testBadUrl("i am not a url", "NS_ERROR_MALFORMED_URI",
"Installing from an unparseable URL fails");
yield testBadUrl("https://addons.not-really-mozilla.org/impostor.xpi",
"not permitted",
"Installing from non-approved URL fails");
});