summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_site_permissions.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_site_permissions.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_site_permissions.js385
1 files changed, 385 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_site_permissions.js b/toolkit/components/extensions/test/xpcshell/test_site_permissions.js
new file mode 100644
index 0000000000..652c9ae3ac
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_site_permissions.js
@@ -0,0 +1,385 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+// TODO(Bug 1789718): adapt to synthetic addon type implemented by the SitePermAddonProvider
+// or remove if redundant, after the deprecated XPIProvider-based implementation is also removed.
+
+const { AddonManager } = ChromeUtils.importESModule(
+ "resource://gre/modules/AddonManager.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+);
+
+const { TelemetryController } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryController.sys.mjs"
+);
+const { TelemetryTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TelemetryTestUtils.sys.mjs"
+);
+
+AddonTestUtils.init(this);
+AddonTestUtils.overrideCertDB();
+AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "42",
+ "42"
+);
+
+const l10n = new Localization([
+ "toolkit/global/extensions.ftl",
+ "toolkit/global/extensionPermissions.ftl",
+ "branding/brand.ftl",
+]);
+// Localization resources need to be first iterated outside a test
+l10n.formatValue("webext-perms-sideload-text");
+
+// Lazily import ExtensionParent to allow AddonTestUtils.createAppInfo to
+// override Services.appinfo.
+ChromeUtils.defineESModuleGetters(this, {
+ ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs",
+});
+
+async function _test_manifest(manifest, expectedError) {
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ let normalized = await ExtensionTestUtils.normalizeManifest(
+ manifest,
+ "manifest.WebExtensionSitePermissionsManifest"
+ );
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+
+ if (expectedError) {
+ ok(
+ normalized.error.includes(expectedError),
+ `The manifest error ${JSON.stringify(
+ normalized.error
+ )} must contain ${JSON.stringify(expectedError)}`
+ );
+ } else {
+ equal(normalized.error, undefined, "Should not have an error");
+ }
+ equal(normalized.errors.length, 0, "Should have no warning");
+}
+
+add_setup(async () => {
+ // Telemetry test setup needed to ensure that the builtin events are defined
+ // and they can be collected and verified.
+ await TelemetryController.testSetup();
+
+ // This is actually only needed on Android, because it does not properly support unified telemetry
+ // and so, if not enabled explicitly here, it would make these tests to fail when running on
+ // release builds.
+ const oldCanRecordBase = Services.telemetry.canRecordBase;
+ Services.telemetry.canRecordBase = true;
+ registerCleanupFunction(() => {
+ Services.telemetry.canRecordBase = oldCanRecordBase;
+ });
+});
+
+add_task(async function test_manifest_site_permissions() {
+ await _test_manifest({
+ site_permissions: ["midi"],
+ install_origins: ["http://example.com"],
+ });
+ await _test_manifest({
+ site_permissions: ["midi-sysex"],
+ install_origins: ["http://example.com"],
+ });
+ await _test_manifest(
+ {
+ site_permissions: ["unknown_site_permission"],
+ install_origins: ["http://example.com"],
+ },
+ `Error processing site_permissions.0: Invalid enumeration value "unknown_site_permission"`
+ );
+ await _test_manifest(
+ {
+ site_permissions: ["unknown_site_permission"],
+ install_origins: [],
+ },
+ `Error processing install_origins: Array requires at least 1 items;`
+ );
+ await _test_manifest(
+ {
+ site_permissions: ["unknown_site_permission"],
+ },
+ `Property "install_origins" is required`
+ );
+ await _test_manifest(
+ {
+ install_origins: ["http://example.com"],
+ },
+ `Property "site_permissions" is required`
+ );
+ // test any extra manifest entries not part of a site permissions addon will cause an error.
+ await _test_manifest(
+ {
+ site_permissions: ["midi"],
+ install_origins: ["http://example.com"],
+ permissions: ["webRequest"],
+ },
+ `Unexpected property`
+ );
+});
+
+add_task(async function test_sitepermission_telemetry() {
+ await AddonTestUtils.promiseStartupManager();
+
+ Services.telemetry.clearEvents();
+
+ const addon_id = "webmidi@test";
+ const origin = "https://example.com";
+ const permName = "midi";
+
+ let site_permission = {
+ "manifest.json": {
+ name: "test Site Permission",
+ version: "1.0",
+ manifest_version: 2,
+ browser_specific_settings: {
+ gecko: { id: addon_id },
+ },
+ install_origins: [origin],
+ site_permissions: [permName],
+ },
+ };
+
+ let [, { addon }] = await Promise.all([
+ TestUtils.topicObserved("webextension-sitepermissions-startup"),
+ AddonTestUtils.promiseInstallXPI(site_permission),
+ ]);
+
+ await addon.uninstall();
+
+ await TelemetryTestUtils.assertEvents(
+ [
+ [
+ "addonsManager",
+ "install",
+ "siteperm_deprecated",
+ /.*/,
+ {
+ step: "started",
+ addon_id,
+ },
+ ],
+ [
+ "addonsManager",
+ "install",
+ "siteperm_deprecated",
+ /.*/,
+ {
+ step: "completed",
+ addon_id,
+ },
+ ],
+ ["addonsManager", "uninstall", "siteperm_deprecated", addon_id],
+ ],
+ {
+ category: "addonsManager",
+ method: /^install|uninstall$/,
+ }
+ );
+
+ await AddonTestUtils.promiseShutdownManager();
+});
+
+async function _test_ext_site_permissions(site_permissions, install_origins) {
+ ExtensionTestUtils.failOnSchemaWarnings(false);
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ install_origins,
+ site_permissions,
+ },
+ });
+ await extension.startup();
+ await extension.unload();
+ ExtensionTestUtils.failOnSchemaWarnings(true);
+}
+
+add_task(async function test_ext_site_permissions() {
+ await _test_ext_site_permissions(["midi"], ["http://example.com"]);
+
+ await _test_ext_site_permissions(
+ ["midi"],
+ ["http://example.com", "http://foo.com"]
+ ).catch(e => {
+ Assert.ok(
+ e.message.includes(
+ "Error processing install_origins: Array requires at most 1 items; you have 2"
+ ),
+ "Site permissions can only contain one install origin: "
+ );
+ });
+});
+
+add_task(async function test_sitepermission_type() {
+ await AddonTestUtils.promiseStartupManager();
+
+ // Test more than one perm to make sure both are added.
+ // While this is allowed, midi-sysex overrides.
+ let perms = ["midi", "midi-sysex"];
+ let id = "@test-permission";
+ let origin = "http://example.com";
+ let uri = Services.io.newURI(origin);
+ let principal = Services.scriptSecurityManager.createContentPrincipal(
+ uri,
+ {}
+ );
+
+ // give the site some other permission (geo)
+ Services.perms.addFromPrincipal(
+ principal,
+ "geo",
+ Services.perms.ALLOW_ACTION,
+ Services.perms.EXPIRE_NEVER
+ );
+
+ let assertGeo = () => {
+ Assert.equal(
+ Services.perms.testExactPermissionFromPrincipal(principal, "geo"),
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ "site still has geo permission"
+ );
+ };
+
+ let checkPerms = (perms, action, msg) => {
+ for (let permName of perms) {
+ let permission = Services.perms.testExactPermissionFromPrincipal(
+ principal,
+ permName
+ );
+ Assert.equal(permission, action, `${permName}: ${msg}`);
+ }
+ };
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.UNKNOWN_ACTION,
+ "no permission for site"
+ );
+
+ let site_permission = {
+ "manifest.json": {
+ name: "test Site Permission",
+ version: "1.0",
+ manifest_version: 2,
+ browser_specific_settings: {
+ gecko: {
+ id,
+ },
+ },
+ install_origins: [origin],
+ site_permissions: perms,
+ },
+ };
+
+ let [, { addon }] = await Promise.all([
+ TestUtils.topicObserved("webextension-sitepermissions-startup"),
+ AddonTestUtils.promiseInstallXPI(site_permission),
+ ]);
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ "extension enabled permission for site"
+ );
+ assertGeo();
+
+ // Test the permission is retained on restart.
+ await AddonTestUtils.promiseRestartManager();
+ addon = await AddonManager.getAddonByID(id);
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ "extension enabled permission for site"
+ );
+ assertGeo();
+
+ // Test that a removed permission is added on restart
+ Services.perms.removeFromPrincipal(principal, perms[0]);
+ await AddonTestUtils.promiseRestartManager();
+ addon = await AddonManager.getAddonByID(id);
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ "extension enabled permission for site"
+ );
+ assertGeo();
+
+ // Test that a changed permission is not changed on restart
+ Services.perms.addFromPrincipal(
+ principal,
+ perms[0],
+ Services.perms.DENY_ACTION,
+ Services.perms.EXPIRE_NEVER
+ );
+
+ await AddonTestUtils.promiseRestartManager();
+ addon = await AddonManager.getAddonByID(id);
+
+ checkPerms(
+ [perms[0]],
+ Ci.nsIPermissionManager.DENY_ACTION,
+ "extension enabled permission for site"
+ );
+ checkPerms(
+ [perms[1]],
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ "extension enabled permission for site"
+ );
+ assertGeo();
+
+ // Test permission removal when addon disabled
+ await addon.disable();
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.UNKNOWN_ACTION,
+ "no permission for site"
+ );
+ assertGeo();
+
+ // Enabling an addon will always force ALLOW_ACTION
+ await addon.enable();
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ "extension enabled permission for site"
+ );
+ assertGeo();
+
+ // Test permission removal when addon uninstalled
+ await addon.uninstall();
+
+ checkPerms(
+ perms,
+ Ci.nsIPermissionManager.UNKNOWN_ACTION,
+ "no permission for site"
+ );
+ assertGeo();
+});
+
+add_task(async function test_site_permissions_have_localization_strings() {
+ await ExtensionParent.apiManager.lazyInit();
+ const SCHEMA_SITE_PERMISSIONS = Schemas.getPermissionNames([
+ "SitePermission",
+ ]);
+ ok(SCHEMA_SITE_PERMISSIONS.length, "we have site permissions");
+
+ for (const perm of SCHEMA_SITE_PERMISSIONS) {
+ const l10nId = `webext-site-perms-${perm}`;
+ try {
+ const str = await l10n.formatValue(l10nId);
+
+ ok(str.length, `Found localization string for '${perm}' site permission`);
+ } catch (e) {
+ ok(false, `Site permission missing '${perm}'`);
+ }
+ }
+});