"use strict"; const { ExtensionAPI } = ExtensionCommon; AddonTestUtils.init(this); AddonTestUtils.overrideCertDB(); AddonTestUtils.usePrivilegedSignatures = false; AddonTestUtils.createAppInfo( "xpcshell@tests.mozilla.org", "XPCShell", "1", "42" ); add_setup(async () => { const schema = [ { namespace: "privileged", permissions: ["mozillaAddons"], properties: { test: { type: "any", }, }, }, ]; class API extends ExtensionAPI { getAPI(context) { return { privileged: { test: "hello", }, }; } } const modules = { privileged: { url: URL.createObjectURL(new Blob([API.toString()])), schema: `data:,${JSON.stringify(schema)}`, scopes: ["addon_parent"], paths: [["privileged"]], }, }; Services.catMan.addCategoryEntry( "webextension-modules", "test-privileged", `data:,${JSON.stringify(modules)}`, false, false ); await AddonTestUtils.promiseStartupManager(); registerCleanupFunction(async () => { await AddonTestUtils.promiseShutdownManager(); Services.catMan.deleteCategoryEntry( "webextension-modules", "test-privileged", false ); }); }); add_task( { // Some builds (e.g. thunderbird) have experiments enabled by default. pref_set: [["extensions.experiments.enabled", false]], }, async function test_privileged_namespace_disallowed() { // Try accessing the privileged namespace. async function testOnce({ isPrivileged = false, temporarilyInstalled = false, } = {}) { let extension = ExtensionTestUtils.loadExtension({ manifest: { permissions: ["mozillaAddons", "tabs"], }, background() { browser.test.sendMessage( "result", browser.privileged instanceof Object ); }, isPrivileged, temporarilyInstalled, }); if (temporarilyInstalled && !isPrivileged) { ExtensionTestUtils.failOnSchemaWarnings(false); let { messages } = await promiseConsoleOutput(async () => { await Assert.rejects( extension.startup(), /Using the privileged permission/, "Startup failed with privileged permission" ); }); ExtensionTestUtils.failOnSchemaWarnings(true); AddonTestUtils.checkMessages( messages, { expected: [ { message: /Using the privileged permission 'mozillaAddons' requires a privileged add-on/, }, ], }, true ); return null; } await extension.startup(); let result = await extension.awaitMessage("result"); await extension.unload(); return result; } // Prevents startup let result = await testOnce({ temporarilyInstalled: true }); equal( result, null, "Privileged namespace should not be accessible to a regular webextension" ); result = await testOnce({ isPrivileged: true }); equal( result, true, "Privileged namespace should be accessible to a webextension signed with Mozilla Extensions" ); // Allows startup, no access result = await testOnce(); equal( result, false, "Privileged namespace should not be accessible to a regular webextension" ); } ); // Test that Extension.jsm and schema correctly match. add_task(function test_privileged_permissions_match() { const { PRIVILEGED_PERMS } = ChromeUtils.importESModule( "resource://gre/modules/Extension.sys.mjs" ); let perms = Schemas.getPermissionNames(["PermissionPrivileged"]); if (AppConstants.platform == "android") { perms.push("nativeMessaging"); } Assert.deepEqual( Array.from(PRIVILEGED_PERMS).sort(), perms.sort(), "List of privileged permissions is correct." ); });