Bug 1281884 - strict_min_version and strict_max_version aren't respected in "Load Temporary Add-on". r=aswan

Replace test_disabled_addon_can_be_enabled_after_reload in test_reload.js with test_reload_to_invalid_version_fails.

MozReview-Commit-ID: 9OEBnbwNplC

--HG--
extra : transplant_source : %F8T%13%BAZ%9C%9D%A2%23%E7n%FC%2CL%81%90%05g%0D%C3
This commit is contained in:
Bob Silverberg 2016-08-22 13:28:17 -04:00
Родитель 816f3e9990
Коммит d487ac88f9
8 изменённых файлов: 251 добавлений и 44 удалений

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

@ -989,9 +989,8 @@ var loadManifestFromWebManifest = Task.async(function*(aUri) {
addon.targetApplications = [{ addon.targetApplications = [{
id: TOOLKIT_ID, id: TOOLKIT_ID,
minVersion: (bss.strict_min_version || minVersion: bss.strict_min_version,
AddonManagerPrivate.webExtensionsMinPlatformVersion), maxVersion: bss.strict_max_version,
maxVersion: bss.strict_max_version || "*",
}]; }];
addon.targetPlatforms = []; addon.targetPlatforms = [];
@ -3994,6 +3993,13 @@ this.XPIProvider = {
} }
let addon = yield loadManifestFromFile(aFile, TemporaryInstallLocation); let addon = yield loadManifestFromFile(aFile, TemporaryInstallLocation);
if (!addon.isCompatible) {
let app = addon.matchingTargetApplication;
throw new Error(`Add-on ${addon.id} is not compatible with application version. ` +
`add-on minVersion: ${app.minVersion}, ` +
`add-on maxVersion: ${app.maxVersion}`);
}
if (!addon.bootstrap) { if (!addon.bootstrap) {
throw new Error("Only restartless (bootstrap) add-ons" throw new Error("Only restartless (bootstrap) add-ons"
+ " can be temporarily installed:", addon.id); + " can be temporarily installed:", addon.id);
@ -7014,6 +7020,10 @@ AddonInternal.prototype = {
if (!app) if (!app)
return false; return false;
// set reasonable defaults for minVersion and maxVersion
let minVersion = app.minVersion || "0";
let maxVersion = app.maxVersion || "*";
if (!aAppVersion) if (!aAppVersion)
aAppVersion = Services.appinfo.version; aAppVersion = Services.appinfo.version;
if (!aPlatformVersion) if (!aPlatformVersion)
@ -7050,14 +7060,14 @@ AddonInternal.prototype = {
minCompatVersion = XPIProvider.minCompatiblePlatformVersion; minCompatVersion = XPIProvider.minCompatiblePlatformVersion;
if (minCompatVersion && if (minCompatVersion &&
Services.vc.compare(minCompatVersion, app.maxVersion) > 0) Services.vc.compare(minCompatVersion, maxVersion) > 0)
return false; return false;
return Services.vc.compare(version, app.minVersion) >= 0; return Services.vc.compare(version, minVersion) >= 0;
} }
return (Services.vc.compare(version, app.minVersion) >= 0) && return (Services.vc.compare(version, minVersion) >= 0) &&
(Services.vc.compare(version, app.maxVersion) <= 0) (Services.vc.compare(version, maxVersion) <= 0)
}, },
get matchingTargetApplication() { get matchingTargetApplication() {

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

@ -717,13 +717,11 @@ function writeInstallRDFForExtension(aData, aDir, aId, aExtraFile) {
* An optional string to override the default installation aId * An optional string to override the default installation aId
* @return A file pointing to where the extension was installed * @return A file pointing to where the extension was installed
*/ */
function writeWebManifestForExtension(aData, aDir, aId = aData.applications.gecko.id) { function promiseWriteWebManifestForExtension(aData, aDir, aId = aData.applications.gecko.id) {
let files = { let files = {
"manifest.json": JSON.stringify(aData), "manifest.json": JSON.stringify(aData),
} }
let promise = AddonTestUtils.promiseWriteFilesToExtension(aDir.path, aId, files); return AddonTestUtils.promiseWriteFilesToExtension(aDir.path, aId, files);
return awaitPromise(promise);
} }
var {writeFilesToZip} = AddonTestUtils; var {writeFilesToZip} = AddonTestUtils;

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

@ -20,6 +20,19 @@ const manifestSample = {
}], }],
}; };
const { Management } = Components.utils.import("resource://gre/modules/Extension.jsm", {});
function promiseAddonStartup() {
return new Promise(resolve => {
let listener = (extension) => {
Management.off("startup", listener);
resolve(extension);
};
Management.on("startup", listener);
});
}
function* installAddon(fixtureName, addonID) { function* installAddon(fixtureName, addonID) {
yield promiseInstallAllFiles([do_get_addon(fixtureName)]); yield promiseInstallAllFiles([do_get_addon(fixtureName)]);
return promiseAddonByID(addonID); return promiseAddonByID(addonID);
@ -110,38 +123,58 @@ add_task(function* test_can_reload_permanent_addon() {
yield tearDownAddon(addon); yield tearDownAddon(addon);
}); });
add_task(function* test_disabled_addon_can_be_enabled_after_reload() { add_task(function* test_reload_to_invalid_version_fails() {
yield promiseRestartManager(); yield promiseRestartManager();
let tempdir = gTmpD.clone(); let tempdir = gTmpD.clone();
// Create an add-on with strictCompatibility which should cause it // The initial version of the add-on will be compatible, and will therefore load
// to be appDisabled. const addonId = "invalid_version_cannot_be_reloaded@tests.mozilla.org";
const unpackedAddon = writeInstallRDFToDir( let manifest = {
Object.assign({}, manifestSample, { name: "invalid_version_cannot_be_reloaded",
strictCompatibility: true, description: "test invalid_version_cannot_be_reloaded",
targetApplications: [{ manifest_version: 2,
id: "xpcshell@tests.mozilla.org", version: "1.0",
minVersion: "0.1", applications: {
maxVersion: "0.1" gecko: {
}], id: addonId,
}), tempdir, manifestSample.id, "bootstrap.js"); }
},
};
yield AddonManager.installTemporaryAddon(unpackedAddon); let addonDir = yield promiseWriteWebManifestForExtension(manifest, tempdir, "invalid_version");
const addon = yield promiseAddonByID(manifestSample.id); yield AddonManager.installTemporaryAddon(addonDir);
yield promiseAddonStartup();
let addon = yield promiseAddonByID(addonId);
notEqual(addon, null); notEqual(addon, null);
equal(addon.appDisabled, true); equal(addon.id, addonId);
equal(addon.version, "1.0");
equal(addon.appDisabled, false);
equal(addon.userDisabled, false);
addonDir.remove(true);
// Remove strictCompatibility from the manifest. // update the manifest to make the add-on version incompatible, so the reload will reject
writeInstallRDFToDir(manifestSample, tempdir, manifestSample.id); manifest.applications.gecko.strict_min_version = "1";
manifest.applications.gecko.strict_max_version = "1";
manifest.version = "2.0";
yield addon.reload(); addonDir = yield promiseWriteWebManifestForExtension(manifest, tempdir, "invalid_version", false);
let expectedMsg = new RegExp("Add-on invalid_version_cannot_be_reloaded@tests.mozilla.org is not compatible with application version. " +
"add-on minVersion: 1, add-on maxVersion: 1");
const reloadedAddon = yield promiseAddonByID(manifestSample.id); yield Assert.rejects(addon.reload(),
expectedMsg,
"Reload rejects when application version does not fall between minVersion and maxVersion");
let reloadedAddon = yield promiseAddonByID(addonId);
notEqual(reloadedAddon, null); notEqual(reloadedAddon, null);
equal(reloadedAddon.id, addonId);
equal(reloadedAddon.version, "1.0");
equal(reloadedAddon.appDisabled, false); equal(reloadedAddon.appDisabled, false);
equal(reloadedAddon.userDisabled, false);
yield tearDownAddon(reloadedAddon); yield tearDownAddon(reloadedAddon);
unpackedAddon.remove(true); addonDir.remove(true);
}); });
add_task(function* test_manifest_changes_are_refreshed() { add_task(function* test_manifest_changes_are_refreshed() {

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

@ -124,7 +124,7 @@ add_task(function*() {
// Writing the manifest direct to the profile should work // Writing the manifest direct to the profile should work
add_task(function*() { add_task(function*() {
writeWebManifestForExtension({ yield promiseWriteWebManifestForExtension({
name: "Web Extension Name", name: "Web Extension Name",
version: "1.0", version: "1.0",
manifest_version: 2, manifest_version: 2,
@ -190,7 +190,7 @@ add_task(function* test_manifest_localization() {
// Missing version should cause a failure // Missing version should cause a failure
add_task(function*() { add_task(function*() {
writeWebManifestForExtension({ yield promiseWriteWebManifestForExtension({
name: "Web Extension Name", name: "Web Extension Name",
manifest_version: 2, manifest_version: 2,
applications: { applications: {
@ -213,7 +213,7 @@ add_task(function*() {
// Incorrect manifest version should cause a failure // Incorrect manifest version should cause a failure
add_task(function*() { add_task(function*() {
writeWebManifestForExtension({ yield promiseWriteWebManifestForExtension({
name: "Web Extension Name", name: "Web Extension Name",
version: "1.0", version: "1.0",
manifest_version: 1, manifest_version: 1,

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

@ -26,7 +26,7 @@ function promiseAddonStartup() {
// Test simple icon set parsing // Test simple icon set parsing
add_task(function*() { add_task(function*() {
writeWebManifestForExtension({ yield promiseWriteWebManifestForExtension({
name: "Web Extension Name", name: "Web Extension Name",
version: "1.0", version: "1.0",
manifest_version: 2, manifest_version: 2,
@ -90,7 +90,7 @@ add_task(function*() {
// Test AddonManager.getPreferredIconURL for retina screen sizes // Test AddonManager.getPreferredIconURL for retina screen sizes
add_task(function*() { add_task(function*() {
writeWebManifestForExtension({ yield promiseWriteWebManifestForExtension({
name: "Web Extension Name", name: "Web Extension Name",
version: "1.0", version: "1.0",
manifest_version: 2, manifest_version: 2,
@ -136,7 +136,7 @@ add_task(function*() {
// Handles no icons gracefully // Handles no icons gracefully
add_task(function*() { add_task(function*() {
writeWebManifestForExtension({ yield promiseWriteWebManifestForExtension({
name: "Web Extension Name", name: "Web Extension Name",
version: "1.0", version: "1.0",
manifest_version: 2, manifest_version: 2,

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

@ -79,7 +79,7 @@ add_task(function* test_unsigned_no_id_temp_install() {
version: "1.0" version: "1.0"
}; };
const addonDir = writeWebManifestForExtension(manifest, gTmpD, const addonDir = yield promiseWriteWebManifestForExtension(manifest, gTmpD,
"the-addon-sub-dir"); "the-addon-sub-dir");
const addon = yield AddonManager.installTemporaryAddon(addonDir); const addon = yield AddonManager.installTemporaryAddon(addonDir);
ok(addon.id, "ID should have been auto-generated"); ok(addon.id, "ID should have been auto-generated");
@ -112,9 +112,9 @@ add_task(function* test_multiple_no_id_extensions() {
version: "1.0" version: "1.0"
}; };
const firstAddonDir = writeWebManifestForExtension(manifest, gTmpD, const firstAddonDir = yield promiseWriteWebManifestForExtension(manifest, gTmpD,
"addon-sub-dir-one"); "addon-sub-dir-one");
const secondAddonDir = writeWebManifestForExtension(manifest, gTmpD, const secondAddonDir = yield promiseWriteWebManifestForExtension(manifest, gTmpD,
"addon-sub-dir-two"); "addon-sub-dir-two");
const [firstAddon, secondAddon] = yield Promise.all([ const [firstAddon, secondAddon] = yield Promise.all([
AddonManager.installTemporaryAddon(firstAddonDir), AddonManager.installTemporaryAddon(firstAddonDir),
@ -155,7 +155,7 @@ add_task(function* test_bss_id() {
let addon = yield promiseAddonByID(ID); let addon = yield promiseAddonByID(ID);
do_check_eq(addon, null); do_check_eq(addon, null);
writeWebManifestForExtension(manifest, profileDir, ID); yield promiseWriteWebManifestForExtension(manifest, profileDir, ID);
yield promiseRestartManager(); yield promiseRestartManager();
addon = yield promiseAddonByID(ID); addon = yield promiseAddonByID(ID);
@ -189,7 +189,7 @@ add_task(function* test_two_ids() {
} }
} }
writeWebManifestForExtension(manifest, profileDir, GOOD_ID); yield promiseWriteWebManifestForExtension(manifest, profileDir, GOOD_ID);
yield promiseRestartManager(); yield promiseRestartManager();
let addon = yield promiseAddonByID(BAD_ID); let addon = yield promiseAddonByID(BAD_ID);
@ -199,3 +199,168 @@ add_task(function* test_two_ids() {
addon.uninstall(); addon.uninstall();
}); });
// Test that strict_min_version and strict_max_version are enforced for
// loading temporary extension.
add_task(function* test_strict_min_max() {
// the app version being compared to is 1.9.2
const addonId = "strict_min_max@tests.mozilla.org";
const MANIFEST = {
name: "strict min max test",
description: "test strict min and max with temporary loading",
manifest_version: 2,
version: "1.0",
};
function flushAndRemove(file) {
// flush JAR cache and remove the file
Services.obs.notifyObservers(file, "flush-cache-entry", null);
file.remove(true);
}
// bad max good min
let apps = {
applications: {
gecko: {
id: addonId,
strict_min_version: "1",
strict_max_version: "1"
},
},
}
let testManifest = Object.assign(apps, MANIFEST);
let addonDir = yield promiseWriteWebManifestForExtension(testManifest, gTmpD,
"the-addon-sub-dir");
let expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version. " +
"add-on minVersion: 1, add-on maxVersion: 1");
yield Assert.rejects(AddonManager.installTemporaryAddon(addonDir),
expectedMsg,
"Install rejects when specified maxVersion is not valid");
let addon = yield promiseAddonByID(addonId);
do_check_eq(addon, null);
flushAndRemove(addonDir);
// bad min good max
apps = {
applications: {
gecko: {
id: addonId,
strict_min_version: "2",
strict_max_version: "2"
},
},
}
testManifest = Object.assign(apps, MANIFEST);
addonDir = yield promiseWriteWebManifestForExtension(testManifest, gTmpD,
"the-addon-sub-dir");
expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version. " +
"add-on minVersion: 2, add-on maxVersion: 2");
yield Assert.rejects(AddonManager.installTemporaryAddon(addonDir),
expectedMsg,
"Install rejects when specified minVersion is not valid");
addon = yield promiseAddonByID(addonId);
do_check_eq(addon, null);
flushAndRemove(addonDir);
// bad both
apps = {
applications: {
gecko: {
id: addonId,
strict_min_version: "2",
strict_max_version: "1"
},
},
}
testManifest = Object.assign(apps, MANIFEST);
addonDir = yield promiseWriteWebManifestForExtension(testManifest, gTmpD,
"the-addon-sub-dir");
expectedMsg = new RegExp("Add-on strict_min_max@tests.mozilla.org is not compatible with application version. " +
"add-on minVersion: 2, add-on maxVersion: 1");
yield Assert.rejects(AddonManager.installTemporaryAddon(addonDir),
expectedMsg,
"Install rejects when specified minVersion and maxVersion are not valid");
addon = yield promiseAddonByID(addonId);
do_check_eq(addon, null);
flushAndRemove(addonDir);
// good both
apps = {
applications: {
gecko: {
id: addonId,
strict_min_version: "1",
strict_max_version: "2"
},
},
}
testManifest = Object.assign(apps, MANIFEST);
addonDir = yield promiseWriteWebManifestForExtension(testManifest, gTmpD,
"strict_min_max");
yield AddonManager.installTemporaryAddon(addonDir);
addon = yield promiseAddonByID(addonId);
do_check_neq(addon, null);
do_check_eq(addon.id, addonId);
addon.uninstall();
flushAndRemove(addonDir);
// good only min
let newId = "strict_min_only@tests.mozilla.org";
apps = {
applications: {
gecko: {
id: newId,
strict_min_version: "1",
},
},
}
testManifest = Object.assign(apps, MANIFEST);
addonDir = yield promiseWriteWebManifestForExtension(testManifest, gTmpD,
"strict_min_only");
yield AddonManager.installTemporaryAddon(addonDir);
addon = yield promiseAddonByID(newId);
do_check_neq(addon, null);
do_check_eq(addon.id, newId);
addon.uninstall();
flushAndRemove(addonDir);
// good only max
newId = "strict_max_only@tests.mozilla.org";
apps = {
applications: {
gecko: {
id: newId,
strict_max_version: "2",
},
},
}
testManifest = Object.assign(apps, MANIFEST);
addonDir = yield promiseWriteWebManifestForExtension(testManifest, gTmpD,
"strict_max_only");
yield AddonManager.installTemporaryAddon(addonDir);
addon = yield promiseAddonByID(newId);
do_check_neq(addon, null);
do_check_eq(addon.id, newId);
addon.uninstall();
flushAndRemove(addonDir);
});

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

@ -37,7 +37,7 @@ add_task(function* test_bad_unpacked_path() {
for (let dir of directories) { for (let dir of directories) {
try { try {
writeWebManifestForExtension(manifest, profileDir, dir); yield promiseWriteWebManifestForExtension(manifest, profileDir, dir);
} catch (ex) { } catch (ex) {
// This can fail if the underlying filesystem (looking at you windows) // This can fail if the underlying filesystem (looking at you windows)
// doesn't handle some of the characters in the ID. In that case, // doesn't handle some of the characters in the ID. In that case,

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

@ -6,7 +6,8 @@ tags = addons
[test_AddonRepository.js] [test_AddonRepository.js]
[test_reload.js] [test_reload.js]
# Bug 676992: test consistently hangs on Android # Bug 676992: test consistently hangs on Android
skip-if = os == "android" # There's a problem removing a temp file without manually clearing the cache on Windows
skip-if = os == "android" || os == "win"
tags = webextensions tags = webextensions
[test_AddonRepository_cache.js] [test_AddonRepository_cache.js]
# Bug 676992: test consistently hangs on Android # Bug 676992: test consistently hangs on Android