282 lines
8.6 KiB
JavaScript
282 lines
8.6 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const { AddonTestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/AddonTestUtils.sys.mjs"
|
|
);
|
|
|
|
AddonTestUtils.initMochitest(this);
|
|
|
|
const XPI_INCOMPATIBLE_ID = "incompatible-xpi@tests.mozilla.org";
|
|
// NOTE: we are using an HTTP url on purpose here, the test case fails
|
|
// otherwise... We disable `AddonManager.checkUpdateSecurity` to allow
|
|
// retrieving updates from HTTP (which is restored in a
|
|
// `registerCleanupFunction()` or at the end of the task).
|
|
//
|
|
// eslint-disable-next-line @microsoft/sdl/no-insecure-url
|
|
const BASE_URL = "http://fake-updates.example.com";
|
|
|
|
const server = AddonTestUtils.createHttpServer({
|
|
hosts: ["fake-updates.example.com"],
|
|
});
|
|
|
|
const UPDATE_ENTRY_COMPATIBLE = {
|
|
// NOTE: this version must be the exact same one associated than the
|
|
// initially incompatible XPI, otherwise it won't override the initial
|
|
// compatibility range.
|
|
// See the check in `AddonUpdateChecker.getCompatibilityUpdate` here:
|
|
// https://searchfox.org/mozilla-central/rev/4044c340/toolkit/mozapps/extensions/internal/AddonUpdateChecker.sys.mjs#489
|
|
version: "4.0",
|
|
// An empty compatibility range will make this update to be overriding the
|
|
// incompatible range in the xpi and makes the xpi version to be considered
|
|
// compatible.
|
|
applications: { gecko: {} },
|
|
};
|
|
|
|
const UPDATE_ENTRY_INCOMPATIBLE = {
|
|
...UPDATE_ENTRY_COMPATIBLE,
|
|
// This update entry instead is including a compatibility range that would
|
|
// makes the xpi version being installed to be considered still incompatible.
|
|
applications: {
|
|
gecko: {
|
|
strict_min_version: "41",
|
|
strict_max_version: "41.*",
|
|
},
|
|
},
|
|
};
|
|
|
|
AddonTestUtils.registerJSON(server, "/updates-still-incompatible.json", {
|
|
addons: {
|
|
[XPI_INCOMPATIBLE_ID]: {
|
|
updates: [UPDATE_ENTRY_INCOMPATIBLE],
|
|
},
|
|
},
|
|
});
|
|
|
|
AddonTestUtils.registerJSON(server, "/updates-now-compatible.json", {
|
|
addons: {
|
|
[XPI_INCOMPATIBLE_ID]: {
|
|
updates: [UPDATE_ENTRY_COMPATIBLE],
|
|
},
|
|
},
|
|
});
|
|
|
|
async function test_local_install_blocked({ id, stash, expectedError }) {
|
|
await AddonTestUtils.loadBlocklistRawData({
|
|
extensionsMLBF: [
|
|
{
|
|
stash,
|
|
stash_time: 0,
|
|
},
|
|
],
|
|
});
|
|
let needsCleanupBlocklist = true;
|
|
const cleanupBlocklist = async () => {
|
|
if (!needsCleanupBlocklist) {
|
|
return;
|
|
}
|
|
await AddonTestUtils.loadBlocklistRawData({
|
|
extensionsMLBF: [
|
|
{
|
|
stash: { blocked: [], unblocked: [] },
|
|
stash_time: 0,
|
|
},
|
|
],
|
|
});
|
|
needsCleanupBlocklist = false;
|
|
};
|
|
registerCleanupFunction(cleanupBlocklist);
|
|
|
|
const xpiFilePath = getTestFilePath("../xpinstall/amosigned.xpi");
|
|
const xpiFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
xpiFile.initWithPath(xpiFilePath);
|
|
ok(xpiFile.exists(), "Expect the xpi file to exist");
|
|
const xpiFileURI = Services.io.newFileURI(xpiFile);
|
|
|
|
const promiseInstallCancelled = AddonTestUtils.promiseInstallEvent(
|
|
"onDownloadCancelled",
|
|
install => install.addon.id === id
|
|
);
|
|
|
|
let install = await AddonManager.getInstallForURL(xpiFileURI.spec, {
|
|
telemetryInfo: { source: "file-url" },
|
|
});
|
|
const promiseInstallFailed = BrowserUtils.promiseObserved(
|
|
"addon-install-failed",
|
|
subject => {
|
|
return subject.wrappedJSObject.installs[0] == install;
|
|
}
|
|
);
|
|
|
|
AddonManager.installAddonFromWebpage(
|
|
"application/x-xpinstall",
|
|
gBrowser.selectedBrowser,
|
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
|
install
|
|
);
|
|
|
|
info("Wait for addon-install-failed to be notified");
|
|
await promiseInstallFailed;
|
|
Assert.equal(
|
|
install.error,
|
|
expectedError,
|
|
"LocalInstall cancelled with the expected error"
|
|
);
|
|
|
|
info("Wait for onDownloadCancelled to be notified");
|
|
await promiseInstallCancelled;
|
|
Assert.equal(
|
|
install.state,
|
|
AddonManager.STATE_CANCELLED,
|
|
"Expect the install.state to be STATE_CANCELLED"
|
|
);
|
|
|
|
await cleanupBlocklist();
|
|
}
|
|
|
|
add_task(async function test_local_install_hard_blocked() {
|
|
let id = "amosigned-xpi@tests.mozilla.org";
|
|
let version = "2.2";
|
|
|
|
await test_local_install_blocked({
|
|
id,
|
|
stash: { blocked: [`${id}:${version}`], unblocked: [] },
|
|
expectedError: AddonManager.ERROR_BLOCKLISTED,
|
|
});
|
|
});
|
|
|
|
add_task(async function test_local_install_soft_blocked() {
|
|
let id = "amosigned-xpi@tests.mozilla.org";
|
|
let version = "2.2";
|
|
|
|
await SpecialPowers.pushPrefEnv({
|
|
set: [["extensions.blocklist.softblock.enabled", true]],
|
|
});
|
|
|
|
await test_local_install_blocked({
|
|
id,
|
|
stash: { softblocked: [`${id}:${version}`], blocked: [], unblocked: [] },
|
|
expectedError: AddonManager.ERROR_SOFT_BLOCKED,
|
|
});
|
|
|
|
await SpecialPowers.popPrefEnv();
|
|
});
|
|
|
|
add_task(async function test_local_install_incompatible() {
|
|
const xpiFilePath = getTestFilePath("../xpinstall/incompatible.xpi");
|
|
const xpiFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
|
xpiFile.initWithPath(xpiFilePath);
|
|
ok(xpiFile.exists(), "Expect the xpi file to exist");
|
|
const xpiFileURI = Services.io.newFileURI(xpiFile);
|
|
|
|
const installTestExtension = async ({ expectIncompatible }) => {
|
|
let install = await AddonManager.getInstallForURL(xpiFileURI.spec, {
|
|
telemetryInfo: { source: "file-url" },
|
|
});
|
|
const promiseInstallDone = expectIncompatible
|
|
? BrowserUtils.promiseObserved(
|
|
"addon-install-failed",
|
|
subject => subject.wrappedJSObject.installs[0] == install
|
|
)
|
|
: BrowserUtils.promiseObserved(
|
|
"webextension-permission-prompt",
|
|
subject => subject.wrappedJSObject.info.addon == install.addon
|
|
);
|
|
|
|
AddonManager.installAddonFromWebpage(
|
|
"application/x-xpinstall",
|
|
gBrowser.selectedBrowser,
|
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
|
install
|
|
);
|
|
|
|
if (expectIncompatible) {
|
|
info("Wait for addon-install-failed to be notified");
|
|
await promiseInstallDone;
|
|
Assert.equal(
|
|
install.error,
|
|
AddonManager.ERROR_INCOMPATIBLE,
|
|
"LocalInstall cancelled with the expected error"
|
|
);
|
|
} else {
|
|
info("Wait for webextension-permission-prompt to be notified");
|
|
await promiseInstallDone;
|
|
Assert.equal(
|
|
install.error,
|
|
0,
|
|
"no error expected on the LocalInstall instance"
|
|
);
|
|
Assert.equal(
|
|
install.state,
|
|
AddonManager.STATE_DOWNLOADED,
|
|
"Got the expected LocalInstall state"
|
|
);
|
|
Assert.ok(
|
|
install.addon.isCompatible,
|
|
"updated Addon XPI is expected to be compatible"
|
|
);
|
|
Assert.equal(
|
|
install.addon.version,
|
|
"4.0",
|
|
"Addon version expected to match the updated xpi file"
|
|
);
|
|
// Cancel the installation, before exiting the test.
|
|
await install.cancel();
|
|
}
|
|
};
|
|
|
|
info("Test incompatible xpi without a compatibility override");
|
|
// Use a new tab to make sure the doorhanger will be gone when
|
|
// the test tab is being removed (same when repeating the
|
|
// test with expectIncompatible set to false).
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
await installTestExtension({ expectIncompatible: true });
|
|
});
|
|
|
|
// Add the prefs to ignore signature checks for this test (allowed on all
|
|
// channels while running in automation).
|
|
SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["extensions.update.url", `${BASE_URL}/updates.json`],
|
|
["xpinstall.signatures.required", false],
|
|
],
|
|
});
|
|
AddonManager.checkUpdateSecurity = false;
|
|
registerCleanupFunction(() => {
|
|
AddonManager.checkUpdateSecurity = true;
|
|
});
|
|
|
|
info(
|
|
"Test incompatible xpi with a compatibility override that is still incompatible"
|
|
);
|
|
// Add the prefs to provide a compatibility range override which is still
|
|
// incompatible.
|
|
SpecialPowers.pushPrefEnv({
|
|
set: [
|
|
["extensions.update.url", `${BASE_URL}/updates-still-incompatible.json`],
|
|
],
|
|
});
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
await installTestExtension({ expectIncompatible: true });
|
|
});
|
|
SpecialPowers.popPrefEnv();
|
|
|
|
info(
|
|
"Test incompatible xpi with a compatibility override that makes it compatible"
|
|
);
|
|
// Add the prefs to provide a compatibility range override which is
|
|
// compatible.
|
|
SpecialPowers.pushPrefEnv({
|
|
set: [["extensions.update.url", `${BASE_URL}/updates-now-compatible.json`]],
|
|
});
|
|
await BrowserTestUtils.withNewTab("about:blank", async () => {
|
|
await installTestExtension({ expectIncompatible: false });
|
|
});
|
|
SpecialPowers.popPrefEnv();
|
|
|
|
SpecialPowers.popPrefEnv();
|
|
AddonManager.checkUpdateSecurity = true;
|
|
});
|