Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test runs only with pattern: os != 'android'
- Manifest: browser/components/enterprisepolicies/tests/xpcshell/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
"use strict";
const { AddonManager } = ChromeUtils.importESModule(
"resource://gre/modules/AddonManager.sys.mjs"
);
const { AddonTestUtils } = ChromeUtils.importESModule(
);
AddonTestUtils.init(this);
AddonTestUtils.overrideCertDB();
AddonTestUtils.appInfo = getAppInfo();
AddonTestUtils.usePrivilegedSignatures = false;
ExtensionTestUtils.init(this);
add_setup(async function setup() {
await AddonTestUtils.promiseStartupManager();
});
add_task(async function test_blocked_permissions_prevent_manual_install() {
// 1. Apply enterprise policy (do not include install_url)
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": {
blocked_permissions: ["history"],
},
},
},
});
// 2. Create a local XPI file with a blocked permission
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id: "blocked@tests.mozilla.org" } },
name: "Blocked Permission Extension",
version: "1.0",
permissions: ["history"], // this is blocked by policy
},
});
// 3. Try to install it manually
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
notEqual(install.addon, null, "Addon should not be null");
equal(install.addon.appDisabled, true, "Addon should be disabled");
await install.addon.uninstall();
});
add_task(
{
pref_set: [
["extensions.webextOptionalPermissionPrompts", false],
// Required for browser.test.withHandlingUserInput in xpcshell.
[
"security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
true,
],
],
},
async function test_blocked_permissions_request_rejects_entire_call() {
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": {
blocked_permissions: ["cookies"],
},
},
},
});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
browser_specific_settings: {
gecko: { id: "blockedreq@tests.mozilla.org" },
},
optional_permissions: ["cookies", "notifications"],
},
useAddonManager: "temporary",
async background() {
let result;
browser.test.withHandlingUserInput(() => {
result = browser.permissions.request({
permissions: ["cookies", "notifications"],
});
});
await browser.test.assertRejects(
result,
/Permissions are blocked by enterprise policy/,
"permissions.request throws when any requested perm is blocked"
);
let granted = await browser.permissions.getAll();
browser.test.assertFalse(
granted.permissions.includes("notifications"),
"non-blocked perm was not granted when another was blocked"
);
browser.test.assertFalse(
granted.permissions.includes("cookies"),
"blocked perm was not granted"
);
browser.test.sendMessage("done");
},
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
}
);
add_task(
{
pref_set: [
["extensions.webextOptionalPermissionPrompts", false],
[
"security.turn_off_all_security_so_that_viruses_can_take_over_this_computer",
true,
],
],
},
async function test_per_id_blocked_permissions_request_rejects() {
let id = "peridreq@tests.mozilla.org";
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
[id]: { blocked_permissions: ["cookies"] },
},
},
});
let extension = ExtensionTestUtils.loadExtension({
manifest: {
browser_specific_settings: { gecko: { id } },
optional_permissions: ["cookies"],
},
useAddonManager: "temporary",
async background() {
let result;
browser.test.withHandlingUserInput(() => {
result = browser.permissions.request({ permissions: ["cookies"] });
});
await browser.test.assertRejects(
result,
/Permissions are blocked by enterprise policy/,
"Per-id blocked_permissions rejects permissions.request"
);
browser.test.sendMessage("done");
},
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
}
);
add_task(
async function test_per_id_entry_bypasses_global_blocked_permissions() {
let id = "peridoverride@tests.mozilla.org";
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": { blocked_permissions: ["history"] },
[id]: {},
},
},
});
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id } },
name: "Per-id override",
version: "1.0",
permissions: ["history"],
},
});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
equal(
install.addon.appDisabled,
false,
"Per-id entry should override global blocked_permissions"
);
await install.addon.uninstall();
}
);
add_task(async function test_per_id_blocked_permissions_applies() {
let id = "peridblocked@tests.mozilla.org";
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
[id]: { blocked_permissions: ["history"] },
},
},
});
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id } },
name: "Per-id blocked",
version: "1.0",
permissions: ["history"],
},
});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
equal(
install.addon.appDisabled,
true,
"Per-id blocked_permissions should disable this addon"
);
await install.addon.uninstall();
});
add_task(async function test_per_id_blocked_permissions_overrides_global() {
let id = "peridoverridesglobal@tests.mozilla.org";
// Per-id has its own blocked_permissions; per Chrome, per-id shadows "*"
// entirely, so the global blocked entry for "tabs" should not apply here.
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": { blocked_permissions: ["tabs"] },
[id]: { blocked_permissions: ["history"] },
},
},
});
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id } },
name: "Per-id overrides global",
version: "1.0",
permissions: ["tabs"],
},
});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
equal(
install.addon.appDisabled,
false,
"Per-id blocked_permissions fully shadows global; tabs is not blocked here"
);
await install.addon.uninstall();
});
add_task(async function test_per_id_entry_shadows_global_allowed_types() {
// Verifies the Chrome per-id-shadows-* semantic in mayInstallAddon: an
// empty per-id entry exempts the addon from the global allowed_types
// restriction.
let id = "peridshadowstypes@tests.mozilla.org";
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": { allowed_types: ["theme"] },
[id]: {},
},
},
});
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id } },
name: "Per-id shadows allowed_types",
version: "1.0",
},
});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
equal(
install.addon.appDisabled,
false,
"Per-id entry shadows global allowed_types restriction"
);
await install.addon.uninstall();
});
add_task(async function test_per_id_entry_bypasses_block_all_extensions() {
let blockedId = "willBeRemoved@tests.mozilla.org";
let bypassId = "bypassGlobal@tests.mozilla.org";
await setupPolicyEngineWithJson({
policies: { ExtensionSettings: { "*": { blocked_permissions: [] } } },
});
let blockedXpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id: blockedId } },
name: "Will be removed",
version: "1.0",
},
});
let bypassXpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id: bypassId } },
name: "Bypass global",
version: "1.0",
},
});
await (await AddonManager.getInstallForFile(blockedXpi)).install();
await (await AddonManager.getInstallForFile(bypassXpi)).install();
// blockAll with a per-id override entry for bypassId only.
await Promise.all([
AddonTestUtils.promiseAddonEvent("onUninstalled"),
setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": { installation_mode: "blocked" },
[bypassId]: {},
},
},
}),
]);
let blocked = await AddonManager.getAddonByID(blockedId);
equal(blocked, null, "Addon without per-id entry was uninstalled");
let bypass = await AddonManager.getAddonByID(bypassId);
notEqual(bypass, null, "Addon with per-id entry survived blockAllExtensions");
equal(
bypass.appDisabled,
false,
"Per-id override addon stays enabled under blockAllExtensions"
);
await bypass.uninstall();
// Reset so subsequent tests do not inherit installation_mode:blocked.
await setupPolicyEngineWithJson({
policies: { ExtensionSettings: { "*": { blocked_permissions: [] } } },
});
});
add_task(async function test_blocked_permissions_filters_invalid_entries() {
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": {
blocked_permissions: [
"internal:privateBrowsingAllowed",
"<all_urls>",
"history",
],
},
},
},
});
let settings = Services.policies.getExtensionSettings("*");
Assert.deepEqual(
settings.blocked_permissions,
["history"],
"Only valid permission names are preserved; internal:/host patterns/<all_urls> stripped"
);
});
add_task(async function test_post_install_block_disables_addon() {
let id = "postinstallblock@tests.mozilla.org";
// Install with no policy restricting the permission.
await setupPolicyEngineWithJson({
policies: { ExtensionSettings: { "*": { blocked_permissions: [] } } },
});
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id } },
name: "Post-install block",
version: "1.0",
permissions: ["history"],
},
});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
equal(
install.addon.appDisabled,
false,
"Addon is enabled before policy is applied"
);
// Apply policy that blocks the addon's required permission.
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": { blocked_permissions: ["history"] },
},
},
});
let addon = await AddonManager.getAddonByID(id);
notEqual(addon, null, "Addon should still be installed (not uninstalled)");
equal(
addon.appDisabled,
true,
"Addon should be appDisabled after blocking policy"
);
// User tries to re-enable. isUsableAddon re-evaluates via mayInstallAddon,
// which still returns false, so appDisabled stays true.
await addon.enable();
equal(
addon.appDisabled,
true,
"appDisabled remains true after user attempts to re-enable"
);
await addon.uninstall();
});
add_task(async function test_post_install_block_revokes_granted_optional() {
const { ExtensionPermissions } = ChromeUtils.importESModule(
"resource://gre/modules/ExtensionPermissions.sys.mjs"
);
let id = "optionalrevoke@tests.mozilla.org";
await setupPolicyEngineWithJson({
policies: { ExtensionSettings: { "*": { blocked_permissions: [] } } },
});
let xpi = AddonTestUtils.createTempWebExtensionFile({
manifest: {
applications: { gecko: { id } },
name: "Optional revoke",
version: "1.0",
optional_permissions: ["cookies", "notifications"],
},
});
let install = await AddonManager.getInstallForFile(xpi);
await install.install();
// Grant the optional permissions directly.
await ExtensionPermissions.add(id, {
permissions: ["cookies", "notifications"],
origins: [],
data_collection: [],
});
let granted = await ExtensionPermissions.get(id);
ok(
granted.permissions.includes("cookies"),
"cookies was granted before policy"
);
// Apply a policy that blocks "cookies".
await setupPolicyEngineWithJson({
policies: {
ExtensionSettings: {
"*": { blocked_permissions: ["cookies"] },
},
},
});
granted = await ExtensionPermissions.get(id);
ok(
!granted.permissions.includes("cookies"),
"blocked optional permission was revoked"
);
ok(
granted.permissions.includes("notifications"),
"non-blocked optional permission was preserved"
);
let addon = await AddonManager.getAddonByID(id);
equal(
addon.appDisabled,
false,
"Addon stays enabled when only an optional perm was blocked"
);
await addon.uninstall();
});