365 lines
11 KiB
JavaScript
365 lines
11 KiB
JavaScript
"use strict";
|
|
|
|
/**
|
|
* This file contains test for 'theme' type WebExtension addons. Tests focus mostly
|
|
* on interoperability between the different theme formats (XUL and LWT) and
|
|
* Addon Manager integration.
|
|
*
|
|
* Coverage may overlap with other tests in this folder.
|
|
*/
|
|
|
|
const THEME_IDS = [
|
|
"theme3@tests.mozilla.org",
|
|
"theme2@personas.mozilla.org", // Unused. Legacy. Evil.
|
|
"default-theme@mozilla.org",
|
|
];
|
|
const REAL_THEME_IDS = [THEME_IDS[0], THEME_IDS[2]];
|
|
const DEFAULT_THEME = THEME_IDS[2];
|
|
|
|
const profileDir = gProfD.clone();
|
|
profileDir.append("extensions");
|
|
|
|
Services.prefs.setIntPref(
|
|
"extensions.enabledScopes",
|
|
AddonManager.SCOPE_PROFILE | AddonManager.SCOPE_APPLICATION
|
|
);
|
|
|
|
// We remember the last/ currently active theme for tracking events.
|
|
var gActiveTheme = null;
|
|
|
|
add_task(async function setup_to_default_browserish_state() {
|
|
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
|
|
|
|
await promiseWriteWebManifestForExtension(
|
|
{
|
|
author: "Some author",
|
|
manifest_version: 2,
|
|
name: "Web Extension Name",
|
|
version: "1.0",
|
|
theme: { images: { theme_frame: "example.png" } },
|
|
browser_specific_settings: {
|
|
gecko: {
|
|
id: THEME_IDS[0],
|
|
},
|
|
},
|
|
},
|
|
profileDir
|
|
);
|
|
|
|
await promiseStartupManager();
|
|
|
|
if (AppConstants.MOZ_DEV_EDITION) {
|
|
// Developer Edition selects the wrong theme by default.
|
|
let defaultTheme = await AddonManager.getAddonByID(DEFAULT_THEME);
|
|
await defaultTheme.enable();
|
|
}
|
|
|
|
let [t1, t2, d] = await promiseAddonsByIDs(THEME_IDS);
|
|
Assert.ok(t1, "Theme addon should exist");
|
|
Assert.equal(t2, null, "Theme addon is not a thing anymore");
|
|
Assert.ok(d, "Theme addon should exist");
|
|
|
|
await t1.disable();
|
|
await new Promise(executeSoon);
|
|
Assert.ok(!t1.isActive, "Theme should be disabled");
|
|
Assert.ok(d.isActive, "Default theme should be active");
|
|
|
|
await promiseRestartManager();
|
|
|
|
[t1, t2, d] = await promiseAddonsByIDs(THEME_IDS);
|
|
Assert.ok(!t1.isActive, "Theme should still be disabled");
|
|
Assert.ok(d.isActive, "Default theme should still be active");
|
|
|
|
gActiveTheme = d.id;
|
|
});
|
|
|
|
/**
|
|
* Set the `userDisabled` property of one specific theme and check if the theme
|
|
* switching works as expected by checking the state of all installed themes.
|
|
*
|
|
* @param {String} which ID of the addon to set the `userDisabled` property on
|
|
* @param {Boolean} disabled Flag value to switch to
|
|
*/
|
|
async function setDisabledStateAndCheck(which, disabled = false) {
|
|
if (disabled) {
|
|
Assert.equal(which, gActiveTheme, "Only the active theme can be disabled");
|
|
}
|
|
|
|
let themeToDisable = disabled ? which : gActiveTheme;
|
|
let themeToEnable = disabled ? DEFAULT_THEME : which;
|
|
|
|
let expectedStates = {
|
|
[themeToDisable]: true,
|
|
[themeToEnable]: false,
|
|
};
|
|
let addonEvents = {
|
|
[themeToDisable]: [{ event: "onDisabling" }, { event: "onDisabled" }],
|
|
[themeToEnable]: [{ event: "onEnabling" }, { event: "onEnabled" }],
|
|
};
|
|
|
|
// Set the state of the theme to change.
|
|
let theme = await promiseAddonByID(which);
|
|
await expectEvents({ addonEvents }, () => {
|
|
if (disabled) {
|
|
theme.disable();
|
|
} else {
|
|
theme.enable();
|
|
}
|
|
});
|
|
|
|
let isDisabled;
|
|
for (theme of await promiseAddonsByIDs(REAL_THEME_IDS)) {
|
|
isDisabled = theme.id in expectedStates ? expectedStates[theme.id] : true;
|
|
Assert.equal(
|
|
theme.userDisabled,
|
|
isDisabled,
|
|
`Theme '${theme.id}' should be ${isDisabled ? "dis" : "en"}abled`
|
|
);
|
|
Assert.equal(
|
|
theme.pendingOperations,
|
|
AddonManager.PENDING_NONE,
|
|
"There should be no pending operations when no restart is expected"
|
|
);
|
|
Assert.equal(
|
|
theme.isActive,
|
|
!isDisabled,
|
|
`Theme '${theme.id} should be ${isDisabled ? "in" : ""}active`
|
|
);
|
|
}
|
|
|
|
await promiseRestartManager();
|
|
|
|
// All should still be good after a restart of the Addon Manager.
|
|
for (theme of await promiseAddonsByIDs(REAL_THEME_IDS)) {
|
|
isDisabled = theme.id in expectedStates ? expectedStates[theme.id] : true;
|
|
Assert.equal(
|
|
theme.userDisabled,
|
|
isDisabled,
|
|
`Theme '${theme.id}' should be ${isDisabled ? "dis" : "en"}abled`
|
|
);
|
|
Assert.equal(
|
|
theme.isActive,
|
|
!isDisabled,
|
|
`Theme '${theme.id}' should be ${isDisabled ? "in" : ""}active`
|
|
);
|
|
Assert.equal(
|
|
theme.pendingOperations,
|
|
AddonManager.PENDING_NONE,
|
|
"There should be no pending operations left"
|
|
);
|
|
if (!isDisabled) {
|
|
gActiveTheme = theme.id;
|
|
}
|
|
}
|
|
}
|
|
|
|
add_task(async function test_WebExtension_themes() {
|
|
// Enable the WebExtension theme.
|
|
await setDisabledStateAndCheck(THEME_IDS[0]);
|
|
|
|
// Disabling WebExtension should revert to the default theme.
|
|
await setDisabledStateAndCheck(THEME_IDS[0], true);
|
|
|
|
// Enable it again.
|
|
await setDisabledStateAndCheck(THEME_IDS[0]);
|
|
});
|
|
|
|
add_task(async function test_default_theme() {
|
|
// Explicitly enable the default theme.
|
|
await setDisabledStateAndCheck(DEFAULT_THEME);
|
|
|
|
// Swith to the WebExtension theme.
|
|
await setDisabledStateAndCheck(THEME_IDS[0]);
|
|
|
|
// Enable it again.
|
|
await setDisabledStateAndCheck(DEFAULT_THEME);
|
|
});
|
|
|
|
add_task(async function uninstall_offers_undo() {
|
|
let defaultTheme = await AddonManager.getAddonByID(DEFAULT_THEME);
|
|
const ID = THEME_IDS[0];
|
|
let theme = await promiseAddonByID(ID);
|
|
|
|
Assert.ok(theme, "Webextension theme is present");
|
|
|
|
async function promiseAddonEvent(event, id) {
|
|
let [addon] = await AddonTestUtils.promiseAddonEvent(event);
|
|
if (id) {
|
|
Assert.equal(addon.id, id, `Got event for expected addon (${event})`);
|
|
}
|
|
}
|
|
|
|
async function uninstallTheme() {
|
|
let uninstallingPromise = promiseAddonEvent("onUninstalling", ID);
|
|
await theme.uninstall(true);
|
|
await uninstallingPromise;
|
|
|
|
Assert.ok(
|
|
hasFlag(theme.pendingOperations, AddonManager.PENDING_UNINSTALL),
|
|
"Theme being uninstalled has PENDING_UNINSTALL flag"
|
|
);
|
|
}
|
|
|
|
async function cancelUninstallTheme() {
|
|
let cancelPromise = promiseAddonEvent("onOperationCancelled", ID);
|
|
theme.cancelUninstall();
|
|
await cancelPromise;
|
|
|
|
Assert.equal(
|
|
theme.pendingOperations,
|
|
AddonManager.PENDING_NONE,
|
|
"PENDING_UNINSTALL flag is cleared when uninstall is canceled"
|
|
);
|
|
}
|
|
|
|
// A theme should still be disabled if the uninstallation of a disabled theme
|
|
// is undone.
|
|
Assert.ok(!theme.isActive, "Webextension theme is not active");
|
|
Assert.ok(defaultTheme.isActive, "Default theme is active");
|
|
await uninstallTheme();
|
|
await cancelUninstallTheme();
|
|
Assert.ok(!theme.isActive, "Webextension theme is still not active");
|
|
Assert.ok(defaultTheme.isActive, "Default theme is still active");
|
|
|
|
// Enable theme, the previously active theme should be disabled.
|
|
await Promise.all([
|
|
promiseAddonEvent("onDisabled", DEFAULT_THEME),
|
|
promiseAddonEvent("onEnabled", ID),
|
|
theme.enable(),
|
|
]);
|
|
Assert.ok(theme.isActive, "Webextension theme is active after enabling");
|
|
Assert.ok(!defaultTheme.isActive, "Default theme is not active any more");
|
|
|
|
// Uninstall active theme, default theme should become active.
|
|
await Promise.all([
|
|
// Note: no listener for onDisabled & ID because the uninstall is pending.
|
|
promiseAddonEvent("onEnabled", DEFAULT_THEME),
|
|
uninstallTheme(),
|
|
]);
|
|
Assert.ok(!theme.isActive, "Webextension theme is not active upon uninstall");
|
|
Assert.ok(defaultTheme.isActive, "Default theme is active again");
|
|
|
|
// Undo uninstall, default theme should be deactivated.
|
|
await Promise.all([
|
|
// Note: no listener for onEnabled & ID because the uninstall was pending.
|
|
promiseAddonEvent("onDisabled", DEFAULT_THEME),
|
|
cancelUninstallTheme(),
|
|
]);
|
|
Assert.ok(theme.isActive, "Webextension theme is active upon undo uninstall");
|
|
Assert.ok(!defaultTheme.isActive, "Default theme is not active again");
|
|
|
|
// Immediately remove the theme. Default theme should be activated.
|
|
await Promise.all([
|
|
promiseAddonEvent("onEnabled", DEFAULT_THEME),
|
|
theme.uninstall(),
|
|
]);
|
|
|
|
await promiseRestartManager();
|
|
});
|
|
|
|
// Test that default_locale works with WE themes
|
|
add_task(async function default_locale_themes() {
|
|
let addon = await promiseInstallWebExtension({
|
|
manifest: {
|
|
default_locale: "en",
|
|
name: "__MSG_name__",
|
|
description: "__MSG_description__",
|
|
theme: {
|
|
colors: {
|
|
frame: "black",
|
|
tab_background_text: "white",
|
|
},
|
|
},
|
|
},
|
|
files: {
|
|
"_locales/en/messages.json": `{
|
|
"name": {
|
|
"message": "the name"
|
|
},
|
|
"description": {
|
|
"message": "the description"
|
|
}
|
|
}`,
|
|
},
|
|
});
|
|
|
|
addon = await promiseAddonByID(addon.id);
|
|
equal(addon.name, "the name");
|
|
equal(addon.description, "the description");
|
|
equal(addon.type, "theme");
|
|
await addon.uninstall();
|
|
});
|
|
|
|
add_task(async function test_theme_update() {
|
|
let addon = await AddonManager.getAddonByID(DEFAULT_THEME);
|
|
ok(!addon.userDisabled, "default theme is enabled");
|
|
|
|
await AddonTestUtils.promiseRestartManager("2");
|
|
|
|
addon = await AddonManager.getAddonByID(DEFAULT_THEME);
|
|
ok(!addon.userDisabled, "default theme is enabled after upgrade");
|
|
});
|
|
|
|
add_task(async function test_builtin_theme_permissions() {
|
|
const ADDON_ID = "mytheme@mozilla.org";
|
|
|
|
let themeDef = {
|
|
manifest: {
|
|
browser_specific_settings: { gecko: { id: ADDON_ID } },
|
|
version: "1.0",
|
|
theme: {},
|
|
},
|
|
};
|
|
|
|
function checkPerms(addon) {
|
|
// builtin themes enable or disable based on disabled state
|
|
Assert.equal(
|
|
addon.userDisabled,
|
|
hasFlag(addon.permissions, AddonManager.PERM_CAN_ENABLE),
|
|
"enable permission is correct"
|
|
);
|
|
Assert.equal(
|
|
!addon.userDisabled,
|
|
hasFlag(addon.permissions, AddonManager.PERM_CAN_DISABLE),
|
|
"disable permission is correct"
|
|
);
|
|
// builtin themes do not get any other permission
|
|
Assert.ok(
|
|
!hasFlag(addon.permissions, AddonManager.PERM_CAN_INSTALL),
|
|
"cannot install by user"
|
|
);
|
|
Assert.ok(
|
|
!hasFlag(addon.permissions, AddonManager.PERM_CAN_UPGRADE),
|
|
"cannot upgrade"
|
|
);
|
|
Assert.ok(
|
|
!hasFlag(addon.permissions, AddonManager.PERM_CAN_UNINSTALL),
|
|
"cannot uninstall"
|
|
);
|
|
Assert.ok(
|
|
!hasFlag(
|
|
addon.permissions,
|
|
AddonManager.PERM_CAN_CHANGE_PRIVATEBROWSING_ACCESS
|
|
),
|
|
"can change private browsing access"
|
|
);
|
|
Assert.ok(
|
|
hasFlag(addon.permissions, AddonManager.PERM_API_CAN_UNINSTALL),
|
|
"can uninstall via API"
|
|
);
|
|
}
|
|
|
|
await setupBuiltinExtension(themeDef, "first-loc", false);
|
|
await AddonManager.maybeInstallBuiltinAddon(
|
|
ADDON_ID,
|
|
"1.0",
|
|
"resource://first-loc/"
|
|
);
|
|
|
|
let addon = await AddonManager.getAddonByID(ADDON_ID);
|
|
checkPerms(addon);
|
|
await addon.enable();
|
|
checkPerms(addon);
|
|
|
|
await addon.uninstall();
|
|
});
|