зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1889402 - Grant origin permissions during install for mv3 r=robwu
Differential Revision: https://phabricator.services.mozilla.com/D208426
This commit is contained in:
Родитель
60383a2ec2
Коммит
9fd11ac2ef
|
@ -16,11 +16,14 @@ const kSideloaded = true;
|
|||
async function createWebExtension(details) {
|
||||
let options = {
|
||||
manifest: {
|
||||
manifest_version: details.manifest_version ?? 2,
|
||||
|
||||
browser_specific_settings: { gecko: { id: details.id } },
|
||||
|
||||
name: details.name,
|
||||
|
||||
permissions: details.permissions,
|
||||
host_permissions: details.host_permissions,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -86,9 +89,10 @@ add_task(async function test_sideloading() {
|
|||
|
||||
const ID2 = "addon2@tests.mozilla.org";
|
||||
await createWebExtension({
|
||||
manifest_version: 3,
|
||||
id: ID2,
|
||||
name: "Test 2",
|
||||
permissions: ["<all_urls>"],
|
||||
host_permissions: ["<all_urls>"],
|
||||
});
|
||||
|
||||
const ID3 = "addon3@tests.mozilla.org";
|
||||
|
|
|
@ -20,6 +20,12 @@ const l10n = new Localization(
|
|||
true
|
||||
);
|
||||
|
||||
add_setup(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.originControls.grantByDefault", false]],
|
||||
});
|
||||
});
|
||||
|
||||
async function makeExtension({
|
||||
useAddonManager = "temporary",
|
||||
manifest_version = 3,
|
||||
|
|
|
@ -44,6 +44,9 @@ add_setup(async function () {
|
|||
// panel, which could happen when a previous test file resizes the current
|
||||
// window.
|
||||
await ensureMaximizedWindow(window);
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.originControls.grantByDefault", false]],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_button_enabled_by_pref() {
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
loadTestSubscript("head_unified_extensions.js");
|
||||
|
||||
add_setup(async () => {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.originControls.grantByDefault", false]],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_keyboard_navigation_activeScript() {
|
||||
const extension1 = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
|
|
|
@ -134,7 +134,7 @@ export var ExtensionsUI = {
|
|||
|
||||
let strings = this._buildStrings({
|
||||
addon,
|
||||
permissions: addon.userPermissions,
|
||||
permissions: addon.installPermissions,
|
||||
type: "sideload",
|
||||
});
|
||||
|
||||
|
|
|
@ -3147,6 +3147,9 @@ pref("extensions.webextensions.restrictedDomains", "accounts-static.cdn.mozilla.
|
|||
pref("extensions.quarantinedDomains.enabled", true);
|
||||
pref("extensions.quarantinedDomains.list", "");
|
||||
|
||||
// Include origin permissions in the install prompt for MV3 extensions.
|
||||
pref("extensions.originControls.grantByDefault", true);
|
||||
|
||||
// Whether or not the moz-extension resource loads are remoted. For debugging
|
||||
// purposes only. Setting this to false will break moz-extension URI loading
|
||||
// unless other process sandboxing and extension remoting prefs are changed.
|
||||
|
|
|
@ -161,6 +161,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
|||
30 * 1000
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"installIncludesOrigins",
|
||||
"extensions.originControls.grantByDefault",
|
||||
false
|
||||
);
|
||||
|
||||
var {
|
||||
GlobalManager,
|
||||
IconDetails,
|
||||
|
@ -1196,8 +1203,10 @@ export class ExtensionData {
|
|||
* includes the contents of the "permissions" property as well as other
|
||||
* capabilities that are derived from manifest fields that users should
|
||||
* be informed of (e.g., origins where content scripts are injected).
|
||||
*
|
||||
* For MV3 extensions with origin controls, this does not include origins.
|
||||
*/
|
||||
get manifestPermissions() {
|
||||
getRequiredPermissions() {
|
||||
if (this.type !== "extension") {
|
||||
return null;
|
||||
}
|
||||
|
@ -1240,6 +1249,20 @@ export class ExtensionData {
|
|||
return Array.from(origins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns additional permissions that extensions is requesting based on its
|
||||
* manifest. For now, this is host_permissions (and content scripts) in mv3.
|
||||
*/
|
||||
getRequestedPermissions() {
|
||||
if (this.type !== "extension") {
|
||||
return null;
|
||||
}
|
||||
if (this.originControls && lazy.installIncludesOrigins) {
|
||||
return { permissions: [], origins: this.getManifestOrigins() };
|
||||
}
|
||||
return { permissions: [], origins: [] };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns optional permissions from the manifest, including host permissions
|
||||
* if originControls is true.
|
||||
|
@ -3729,8 +3752,8 @@ export class Extension extends ExtensionData {
|
|||
|
||||
if (
|
||||
this.originControls &&
|
||||
this.manifest.granted_host_permissions &&
|
||||
this.startupReason === "ADDON_INSTALL"
|
||||
this.startupReason === "ADDON_INSTALL" &&
|
||||
(this.manifest.granted_host_permissions || lazy.installIncludesOrigins)
|
||||
) {
|
||||
let origins = this.getManifestOrigins();
|
||||
lazy.ExtensionPermissions.add(this.id, { permissions: [], origins });
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.manifestV3.enabled", true]],
|
||||
set: [
|
||||
["extensions.manifestV3.enabled", true],
|
||||
["extensions.originControls.grantByDefault", false],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -27,7 +27,10 @@ const makeExtension = ({ manifest: manifestProps, ...otherProps }) => {
|
|||
|
||||
add_task(async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.manifestV3.enabled", true]],
|
||||
set: [
|
||||
["extensions.manifestV3.enabled", true],
|
||||
["extensions.originControls.grantByDefault", false],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
Services.prefs.setBoolPref("extensions.originControls.grantByDefault", false);
|
||||
|
||||
const server = createHttpServer({ hosts: ["example.com", "example.net"] });
|
||||
server.registerDirectory("/data/", do_get_file("data"));
|
||||
|
|
|
@ -41,7 +41,7 @@ async function getManifestPermissions(extensionData) {
|
|||
ExtensionTestUtils.failOnSchemaWarnings(false);
|
||||
await extension.loadManifest();
|
||||
ExtensionTestUtils.failOnSchemaWarnings(true);
|
||||
let result = extension.manifestPermissions;
|
||||
let result = extension.getRequiredPermissions();
|
||||
|
||||
if (extension.manifest.manifest_version >= 3) {
|
||||
// In MV3, host permissions are optional by default.
|
||||
|
|
|
@ -10,6 +10,11 @@ const { ExtensionPermissions } = ChromeUtils.importESModule(
|
|||
"resource://gre/modules/ExtensionPermissions.sys.mjs"
|
||||
);
|
||||
|
||||
const WITH_INSTALL_PROMPT = [
|
||||
["extensions.originControls.grantByDefault", true],
|
||||
];
|
||||
const NO_INSTALL_PROMPT = [["extensions.originControls.grantByDefault", false]];
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
|
||||
// ExtensionParent.sys.mjs is being imported lazily because when it is imported Services.appinfo will be
|
||||
|
@ -427,12 +432,24 @@ add_task(function test_normal_mv2() {
|
|||
});
|
||||
});
|
||||
|
||||
add_task(function test_normal_mv3_noInstallPrompt() {
|
||||
return runWithPrefs(NO_INSTALL_PROMPT, () =>
|
||||
test_permissions({
|
||||
manifest_version: 3,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
add_task(function test_normal_mv3() {
|
||||
return test_permissions({
|
||||
manifest_version: 3,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: false,
|
||||
});
|
||||
return runWithPrefs(WITH_INSTALL_PROMPT, () =>
|
||||
test_permissions({
|
||||
manifest_version: 3,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
add_task(function test_granted_for_temporary_mv3() {
|
||||
|
@ -444,28 +461,30 @@ add_task(function test_granted_for_temporary_mv3() {
|
|||
});
|
||||
});
|
||||
|
||||
add_task(async function test_granted_only_for_privileged_mv3() {
|
||||
try {
|
||||
// For permanent non-privileged, granted_host_permissions does nothing.
|
||||
await test_permissions({
|
||||
manifest_version: 3,
|
||||
granted_host_permissions: true,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: false,
|
||||
});
|
||||
add_task(function test_granted_only_for_privileged_mv3() {
|
||||
return runWithPrefs(NO_INSTALL_PROMPT, async () => {
|
||||
try {
|
||||
// For permanent non-privileged, granted_host_permissions does nothing.
|
||||
await test_permissions({
|
||||
manifest_version: 3,
|
||||
granted_host_permissions: true,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: false,
|
||||
});
|
||||
|
||||
// Make extensions loaded with addon manager privileged.
|
||||
AddonTestUtils.usePrivilegedSignatures = true;
|
||||
// Make extensions loaded with addon manager privileged.
|
||||
AddonTestUtils.usePrivilegedSignatures = true;
|
||||
|
||||
await test_permissions({
|
||||
manifest_version: 3,
|
||||
granted_host_permissions: true,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: true,
|
||||
});
|
||||
} finally {
|
||||
AddonTestUtils.usePrivilegedSignatures = false;
|
||||
}
|
||||
await test_permissions({
|
||||
manifest_version: 3,
|
||||
granted_host_permissions: true,
|
||||
useAddonManager: "permanent",
|
||||
expectAllGranted: true,
|
||||
});
|
||||
} finally {
|
||||
AddonTestUtils.usePrivilegedSignatures = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_startup() {
|
||||
|
@ -540,7 +559,7 @@ add_task(async function test_startup() {
|
|||
});
|
||||
|
||||
// Test that we don't prompt for permissions an extension already has.
|
||||
async function test_alreadyGranted(manifest_version) {
|
||||
async function test_alreadyGranted({ manifest_version }) {
|
||||
const REQUIRED_PERMISSIONS = ["geolocation"];
|
||||
const REQUIRED_ORIGINS = [
|
||||
"*://required-host.com/",
|
||||
|
@ -671,10 +690,17 @@ async function test_alreadyGranted(manifest_version) {
|
|||
await extension.unload();
|
||||
}
|
||||
add_task(async function test_alreadyGranted_mv2() {
|
||||
return test_alreadyGranted(2);
|
||||
return test_alreadyGranted({ manifest_version: 2 });
|
||||
});
|
||||
add_task(async function test_alreadyGranted_mv3() {
|
||||
return test_alreadyGranted(3);
|
||||
add_task(function test_alreadyGranted_mv3_noInstallPrompt() {
|
||||
return runWithPrefs(NO_INSTALL_PROMPT, () =>
|
||||
test_alreadyGranted({ manifest_version: 3 })
|
||||
);
|
||||
});
|
||||
add_task(function test_alreadyGranted_mv3() {
|
||||
return runWithPrefs(WITH_INSTALL_PROMPT, () =>
|
||||
test_alreadyGranted({ manifest_version: 3 })
|
||||
);
|
||||
});
|
||||
|
||||
// IMPORTANT: Do not change this list without review from a Web Extensions peer!
|
||||
|
@ -779,7 +805,10 @@ add_task(async function test_optional_all_urls() {
|
|||
});
|
||||
|
||||
// Check when content_script match patterns are treated as optional origins.
|
||||
async function test_content_script_is_optional(manifest_version) {
|
||||
async function test_content_script_is_optional({
|
||||
manifest_version,
|
||||
expectGranted,
|
||||
}) {
|
||||
function background() {
|
||||
browser.test.onMessage.addListener(async (msg, arg) => {
|
||||
if (msg == "request") {
|
||||
|
@ -816,7 +845,11 @@ async function test_content_script_is_optional(manifest_version) {
|
|||
|
||||
extension.sendMessage("getAll");
|
||||
let initial = await extension.awaitMessage("granted");
|
||||
deepEqual(initial.origins, [], "Nothing granted on install.");
|
||||
if (manifest_version < 3 || !expectGranted) {
|
||||
deepEqual(initial.origins, [], "Nothing granted on install.");
|
||||
} else {
|
||||
deepEqual(initial.origins, [CS_ORIGIN], "CS origin granted on install.");
|
||||
}
|
||||
|
||||
await withHandlingUserInput(extension, async () => {
|
||||
extension.sendMessage("request", {
|
||||
|
@ -845,11 +878,32 @@ async function test_content_script_is_optional(manifest_version) {
|
|||
|
||||
await extension.unload();
|
||||
}
|
||||
add_task(() => test_content_script_is_optional(2));
|
||||
add_task(() => test_content_script_is_optional(3));
|
||||
|
||||
add_task(async function test_content_script_is_optional_mv2() {
|
||||
await test_content_script_is_optional({ manifest_version: 2 });
|
||||
});
|
||||
add_task(function test_content_script_is_optional_mv3_noInstallPrompt() {
|
||||
return runWithPrefs(NO_INSTALL_PROMPT, () =>
|
||||
test_content_script_is_optional({
|
||||
manifest_version: 3,
|
||||
expectGranted: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
add_task(function test_content_script_is_optional_mv3() {
|
||||
return runWithPrefs(WITH_INSTALL_PROMPT, () =>
|
||||
test_content_script_is_optional({
|
||||
manifest_version: 3,
|
||||
expectGranted: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Check that optional permissions are not included in update prompts
|
||||
async function test_permissions_prompt(manifest_version) {
|
||||
async function test_permissions_prompt({
|
||||
manifest_version,
|
||||
expectInitialGranted,
|
||||
}) {
|
||||
function background() {
|
||||
browser.test.onMessage.addListener(async (msg, arg) => {
|
||||
if (msg == "request") {
|
||||
|
@ -896,7 +950,7 @@ async function test_permissions_prompt(manifest_version) {
|
|||
equal(result, true, "request() for optional permissions succeeded");
|
||||
});
|
||||
|
||||
if (manifest_version >= 3) {
|
||||
if (!expectInitialGranted) {
|
||||
await withHandlingUserInput(extension, async () => {
|
||||
extension.sendMessage("request", {
|
||||
origins: ["https://test1.example.com/*"],
|
||||
|
@ -964,10 +1018,26 @@ async function test_permissions_prompt(manifest_version) {
|
|||
await extension.unload();
|
||||
}
|
||||
add_task(async function test_permissions_prompt_mv2() {
|
||||
return test_permissions_prompt(2);
|
||||
return test_permissions_prompt({
|
||||
manifest_version: 2,
|
||||
expectInitialGranted: true,
|
||||
});
|
||||
});
|
||||
add_task(function test_permissions_prompt_mv3_noInstallPrompt() {
|
||||
return runWithPrefs(NO_INSTALL_PROMPT, () =>
|
||||
test_permissions_prompt({
|
||||
manifest_version: 3,
|
||||
expectInitialGranted: false,
|
||||
})
|
||||
);
|
||||
});
|
||||
add_task(async function test_permissions_prompt_mv3() {
|
||||
return test_permissions_prompt(3);
|
||||
return runWithPrefs(WITH_INSTALL_PROMPT, () =>
|
||||
test_permissions_prompt({
|
||||
manifest_version: 3,
|
||||
expectInitialGranted: true,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Check that internal permissions can not be set and are not returned by the API.
|
||||
|
|
|
@ -3278,7 +3278,7 @@ var AddonManagerInternal = {
|
|||
// the customConfirmationUI preference and responding to the
|
||||
// "addon-install-confirmation" notification. If the application
|
||||
// does not implement its own prompt, use the built-in xul dialog.
|
||||
if (info.addon.userPermissions) {
|
||||
if (info.addon.installPermissions) {
|
||||
let subject = {
|
||||
wrappedJSObject: {
|
||||
target: browser,
|
||||
|
@ -3286,7 +3286,7 @@ var AddonManagerInternal = {
|
|||
},
|
||||
};
|
||||
subject.wrappedJSObject.info.permissions =
|
||||
info.addon.userPermissions;
|
||||
info.addon.installPermissions;
|
||||
Services.obs.notifyObservers(
|
||||
subject,
|
||||
"webextension-permission-prompt"
|
||||
|
|
|
@ -150,13 +150,13 @@ function shouldShowPermissionsPrompt(addon) {
|
|||
return false;
|
||||
}
|
||||
|
||||
let perms = addon.userPermissions;
|
||||
let perms = addon.installPermissions;
|
||||
return perms?.origins.length || perms?.permissions.length;
|
||||
}
|
||||
|
||||
function showPermissionsPrompt(addon) {
|
||||
return new Promise(resolve => {
|
||||
const permissions = addon.userPermissions;
|
||||
const permissions = addon.installPermissions;
|
||||
const target = getBrowserElement();
|
||||
|
||||
const onAddonEnabled = () => {
|
||||
|
|
|
@ -200,6 +200,7 @@ const PROP_JSON_FIELDS = [
|
|||
"incognito",
|
||||
"userPermissions",
|
||||
"optionalPermissions",
|
||||
"requestedPermissions",
|
||||
"sitePermissions",
|
||||
"siteOrigin",
|
||||
"icons",
|
||||
|
@ -1426,6 +1427,10 @@ AddonWrapper = class {
|
|||
return addon.location.name == KEY_APP_PROFILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required permissions that extension has access to based on its manifest.
|
||||
* In mv3 this doesn't include host_permissions.
|
||||
*/
|
||||
get userPermissions() {
|
||||
return addonFor(this).userPermissions;
|
||||
}
|
||||
|
@ -1434,6 +1439,32 @@ AddonWrapper = class {
|
|||
return addonFor(this).optionalPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional permissions that extension is requesting in its manifest.
|
||||
* Currently this is host_permissions in MV3.
|
||||
*/
|
||||
get requestedPermissions() {
|
||||
return addonFor(this).requestedPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper that returns all permissions for the install prompt.
|
||||
*/
|
||||
get installPermissions() {
|
||||
let required = this.userPermissions;
|
||||
if (!required) {
|
||||
return null;
|
||||
}
|
||||
let requested = this.requestedPermissions;
|
||||
// Currently this can't result in duplicates, but if logic of what goes
|
||||
// into these lists changes, make sure to check for dupes.
|
||||
let perms = {
|
||||
origins: required.origins.concat(requested?.origins ?? []),
|
||||
permissions: required.permissions.concat(requested?.permissions ?? []),
|
||||
};
|
||||
return perms;
|
||||
}
|
||||
|
||||
isCompatibleWith(aAppVersion, aPlatformVersion) {
|
||||
return addonFor(this).isCompatibleWith(aAppVersion, aPlatformVersion);
|
||||
}
|
||||
|
|
|
@ -542,8 +542,9 @@ async function loadManifestFromWebManifest(aPackage, aLocation) {
|
|||
// WebExtensions don't use iconURLs
|
||||
addon.iconURL = null;
|
||||
addon.icons = manifest.icons || {};
|
||||
addon.userPermissions = extension.manifestPermissions;
|
||||
addon.userPermissions = extension.getRequiredPermissions();
|
||||
addon.optionalPermissions = extension.manifestOptionalPermissions;
|
||||
addon.requestedPermissions = extension.getRequestedPermissions();
|
||||
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
|
||||
|
||||
function getLocale(aLocale) {
|
||||
|
|
|
@ -419,7 +419,11 @@ async function runTest(options) {
|
|||
}
|
||||
}
|
||||
|
||||
async function testPermissionsView({ manifestV3enabled, manifest_version }) {
|
||||
async function testPermissionsView({
|
||||
manifestV3enabled,
|
||||
manifest_version,
|
||||
expectGranted,
|
||||
}) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.manifestV3.enabled", manifestV3enabled]],
|
||||
});
|
||||
|
@ -438,7 +442,16 @@ async function testPermissionsView({ manifestV3enabled, manifest_version }) {
|
|||
extension: extensions["addon1@mochi.test"],
|
||||
permissions: ["<all_urls>", "tabs", "webNavigation"],
|
||||
});
|
||||
} else {
|
||||
}
|
||||
if (manifest_version >= 3 && expectGranted) {
|
||||
await runTest({
|
||||
extension: extensions["addon1@mochi.test"],
|
||||
permissions: ["tabs", "webNavigation"],
|
||||
optional_permissions: ["<all_urls>"],
|
||||
optional_enabled: ["<all_urls>"],
|
||||
});
|
||||
}
|
||||
if (manifest_version >= 3 && !expectGranted) {
|
||||
await runTest({
|
||||
extension: extensions["addon1@mochi.test"],
|
||||
permissions: ["tabs", "webNavigation"],
|
||||
|
@ -544,8 +557,28 @@ add_task(async function testPermissionsView_MV2_manifestV3enabled() {
|
|||
await testPermissionsView({ manifestV3enabled: true, manifest_version: 2 });
|
||||
});
|
||||
|
||||
add_task(async function testPermissionsView_MV3_noInstallPrompt() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.originControls.grantByDefault", false]],
|
||||
});
|
||||
await testPermissionsView({
|
||||
manifestV3enabled: true,
|
||||
manifest_version: 3,
|
||||
expectGranted: false,
|
||||
});
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function testPermissionsView_MV3() {
|
||||
await testPermissionsView({ manifestV3enabled: true, manifest_version: 3 });
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.originControls.grantByDefault", true]],
|
||||
});
|
||||
await testPermissionsView({
|
||||
manifestV3enabled: true,
|
||||
manifest_version: 3,
|
||||
expectGranted: true,
|
||||
});
|
||||
await SpecialPowers.popPrefEnv();
|
||||
});
|
||||
|
||||
add_task(async function testPermissionsViewStates() {
|
||||
|
@ -623,7 +656,10 @@ add_task(async function testPermissionsViewStates() {
|
|||
|
||||
add_task(async function testAllUrlsNotGrantedUnconditionally_MV3() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["extensions.manifestV3.enabled", true]],
|
||||
set: [
|
||||
["extensions.manifestV3.enabled", true],
|
||||
["extensions.originControls.grantByDefault", false],
|
||||
],
|
||||
});
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
|
|
Загрузка…
Ссылка в новой задаче