Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/* Any copyright is dedicated to the Public Domain.
"use strict";
const { AMBrowserExtensionsImport } = ChromeUtils.importESModule(
"resource://gre/modules/AddonManager.sys.mjs"
);
const { AddonTestUtils } = ChromeUtils.importESModule(
);
// This test verifies the global notification in `about:addons` when there are
// pending imported add-ons. The appmenu UI is covered by tests in:
// `browser/components/extensions/test/browser/browser_AMBrowserExtensionsImport.js`.
AddonTestUtils.initMochitest(this);
const TEST_SERVER = AddonTestUtils.createHttpServer();
const ADDONS = {
ext1: {
manifest: {
name: "Ext 1",
version: "1.0",
browser_specific_settings: { gecko: { id: "ff@ext-1" } },
permissions: ["history"],
},
},
ext2: {
manifest: {
name: "Ext 2",
version: "1.0",
browser_specific_settings: { gecko: { id: "ff@ext-2" } },
permissions: ["history"],
},
},
};
// Populated in `setup()`.
const XPIS = {};
// Populated in `setup()`.
const ADDON_SEARCH_RESULTS = {};
const mockAddonRepository = ({ addons = [] }) => {
return {
async getMappedAddons() {
return Promise.resolve({
addons,
matchedIDs: [],
unmatchedIDs: [],
});
},
};
};
const assertWarningShown = async (
win,
stack,
expectedWarningType = "imported-addons",
expectAction = true
) => {
Assert.equal(stack.childElementCount, 1, "expected a global warning");
const messageBar = stack.firstElementChild;
Assert.equal(
messageBar.getAttribute("warning-type"),
expectedWarningType,
`expected a warning for ${expectedWarningType}`
);
Assert.equal(
messageBar.getAttribute("data-l10n-id"),
`extensions-warning-${expectedWarningType}2`,
"expected correct l10n ID"
);
await win.document.l10n.translateElements([messageBar]);
if (expectAction) {
const button = messageBar.querySelector("button");
Assert.equal(
button.getAttribute("action"),
expectedWarningType,
`expected a button for ${expectedWarningType}`
);
Assert.equal(
button.getAttribute("data-l10n-id"),
`extensions-warning-${expectedWarningType}-button`,
"expected correct l10n ID on the button"
);
await win.document.l10n.translateElements([button]);
}
};
add_setup(async function setup() {
for (const [name, data] of Object.entries(ADDONS)) {
XPIS[name] = AddonTestUtils.createTempWebExtensionFile(data);
TEST_SERVER.registerFile(`/addons/${name}.xpi`, XPIS[name]);
ADDON_SEARCH_RESULTS[name] = {
id: data.manifest.browser_specific_settings.gecko.id,
name: data.name,
version: data.version,
sourceURI: Services.io.newURI(
),
icons: {},
};
}
registerCleanupFunction(() => {
// Clear the add-on repository override.
AMBrowserExtensionsImport._addonRepository = null;
});
});
add_task(async function test_aboutaddons_global_message() {
const browserID = "some-browser-id";
const extensionIDs = ["ext-1", "ext-2"];
AMBrowserExtensionsImport._addonRepository = mockAddonRepository({
addons: Object.values(ADDON_SEARCH_RESULTS),
});
// Global warnings should be displayed in all the `about:addons` views but
// the migration wizard links to the default view. That's why we load this
// view here, too (as opposed to, e.g., `"extensions"`).
const win = await loadInitialView();
const stack = win.document.querySelector("global-warnings");
Assert.equal(stack.childElementCount, 0, "expected no global warning");
let promiseTopic = TestUtils.topicObserved(
"webextension-imported-addons-pending"
);
// Start a first import...
await AMBrowserExtensionsImport.stageInstalls(browserID, extensionIDs);
await promiseTopic;
// We expect a warning about the imported add-ons to be shown.
await assertWarningShown(win, stack);
// ...then cancel it.
promiseTopic = TestUtils.topicObserved(
"webextension-imported-addons-cancelled"
);
await AMBrowserExtensionsImport.cancelInstalls();
await promiseTopic;
// At this point, the warning about the imported add-ons should be hidden.
Assert.equal(stack.childElementCount, 0, "expected no global warning");
// We start a second import here, then we make sure an imported-addons
// messagebar doesn't prevent the other global warning types to be shown.
promiseTopic = TestUtils.topicObserved(
"webextension-imported-addons-pending"
);
const result = await AMBrowserExtensionsImport.stageInstalls(
browserID,
extensionIDs
);
await promiseTopic;
await assertWarningShown(win, stack);
info("Verify safe-mode is not hidden by an imported-addons messagebar");
stack.inSafeMode = true;
stack.refresh();
await assertWarningShown(
win,
stack,
"safe-mode",
false /* no button expected */
);
stack.inSafeMode = false;
info(
"Verify check-compatibility is not hidden by an imported-addons messagebar"
);
AddonManager.checkCompatibility = false;
stack.refresh();
await assertWarningShown(win, stack, "check-compatibility");
AddonManager.checkCompatibility = true;
info("Verify update-security is not hidden by an imported-addons messagebar");
await SpecialPowers.pushPrefEnv({
set: [["extensions.checkUpdateSecurity", false]],
});
stack.refresh();
await assertWarningShown(win, stack, "update-security");
await SpecialPowers.popPrefEnv();
// After making sure the imported-addons messagebar is visible again, we
// finally complete the pending import with the UI from the global warning.
info(
"Verify pending imported addons can be completed from the messagebar action"
);
stack.refresh();
await assertWarningShown(win, stack, "imported-addons");
// Complete the installation of the add-ons by clicking on the button in the
// global warning.
promiseTopic = TestUtils.topicObserved(
"webextension-imported-addons-complete"
);
const endedPromises = result.importedAddonIDs.map(id =>
AddonTestUtils.promiseInstallEvent(
"onInstallEnded",
install => install.addon.id === id
)
);
stack.firstElementChild.querySelector("button").click();
await Promise.all([...endedPromises, promiseTopic]);
// At this point, the warning about the imported add-ons should be hidden
// because the add-ons are installed.
Assert.equal(stack.childElementCount, 0, "expected no global warning");
for (const id of result.importedAddonIDs) {
const addon = await AddonManager.getAddonByID(id);
Assert.ok(addon.isActive, `expected add-on "${id}" to be enabled`);
await addon.uninstall();
}
await closeView(win);
});