Bug 1402850 Don't include runtime permissions in prompts for webextension updates r=zombie
MozReview-Commit-ID: 1cnNsWLVGmg
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
},
|
||||
{
|
||||
"namespace": "devtools",
|
||||
"permissions": ["devtools"],
|
||||
"permissions": ["manifest:devtools_page"],
|
||||
"allowedContexts": ["devtools", "devtools_only"],
|
||||
"defaultContexts": ["devtools", "devtools_only"]
|
||||
}
|
||||
|
||||
@@ -423,12 +423,51 @@ class ExtensionData {
|
||||
});
|
||||
}
|
||||
|
||||
// This method should return a structured representation of any
|
||||
// capabilities this extension has access to, as derived from the
|
||||
// manifest. The current implementation just returns the contents
|
||||
// of the permissions attribute, if we add things like url_overrides,
|
||||
// they should also be added here.
|
||||
get userPermissions() {
|
||||
/**
|
||||
* Returns an object representing any capabilities that the extension
|
||||
* has access to based on fixed properties in the manifest. The result
|
||||
* 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).
|
||||
*/
|
||||
get manifestPermissions() {
|
||||
if (this.type !== "extension") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let permissions = new Set();
|
||||
let origins = new Set();
|
||||
for (let perm of this.manifest.permissions || []) {
|
||||
let type = classifyPermission(perm);
|
||||
if (type.origin) {
|
||||
origins.add(perm);
|
||||
} else if (!type.api) {
|
||||
permissions.add(perm);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.manifest.devtools_page) {
|
||||
permissions.add("devtools");
|
||||
}
|
||||
|
||||
for (let entry of this.manifest.content_scripts || []) {
|
||||
for (let origin of entry.matches) {
|
||||
origins.add(origin);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
permissions: Array.from(permissions),
|
||||
origins: Array.from(origins),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object representing all capabilities this extension has
|
||||
* access to, including fixed ones from the manifest as well as dynamically
|
||||
* granted permissions.
|
||||
*/
|
||||
get activePermissions() {
|
||||
if (this.type !== "extension") {
|
||||
return null;
|
||||
}
|
||||
@@ -438,11 +477,6 @@ class ExtensionData {
|
||||
apis: [...this.apiNames],
|
||||
};
|
||||
|
||||
if (Array.isArray(this.manifest.content_scripts)) {
|
||||
for (let entry of this.manifest.content_scripts) {
|
||||
result.origins.push(...entry.matches);
|
||||
}
|
||||
}
|
||||
const EXP_PATTERN = /^experiments\.\w+/;
|
||||
result.permissions = [...this.permissions]
|
||||
.filter(p => !result.origins.includes(p) && !EXP_PATTERN.test(p));
|
||||
@@ -542,10 +576,6 @@ class ExtensionData {
|
||||
};
|
||||
|
||||
if (this.type === "extension") {
|
||||
if (this.manifest.devtools_page) {
|
||||
permissions.add("devtools");
|
||||
}
|
||||
|
||||
for (let perm of manifest.permissions) {
|
||||
if (perm === "geckoProfiler" && !this.isPrivileged) {
|
||||
const acceptedExtensions = Services.prefs.getStringPref("extensions.geckoProfiler.acceptedExtensionIds", "");
|
||||
|
||||
@@ -64,7 +64,7 @@ this.permissions = class extends ExtensionAPI {
|
||||
},
|
||||
|
||||
async getAll() {
|
||||
let perms = context.extension.userPermissions;
|
||||
let perms = context.extension.activePermissions;
|
||||
delete perms.apis;
|
||||
return perms;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/ExtensionPermissions.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/MessageChannel.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||
|
||||
const BROWSER_PROPERTIES = "chrome://browser/locale/browser.properties";
|
||||
|
||||
@@ -435,3 +437,88 @@ add_task(function test_permissions_have_localization_strings() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Check that optional permissions are not included in update prompts
|
||||
add_task(async function test_permissions_prompt() {
|
||||
function background() {
|
||||
browser.test.onMessage.addListener(async (msg, arg) => {
|
||||
if (msg == "request") {
|
||||
let result = await browser.permissions.request(arg);
|
||||
browser.test.sendMessage("result", result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background,
|
||||
manifest: {
|
||||
name: "permissions test",
|
||||
description: "permissions test",
|
||||
manifest_version: 2,
|
||||
version: "1.0",
|
||||
|
||||
permissions: ["tabs", "https://test1.example.com/*"],
|
||||
optional_permissions: ["clipboardWrite", "<all_urls>"],
|
||||
|
||||
content_scripts: [
|
||||
{
|
||||
matches: ["https://test2.example.com/*"],
|
||||
js: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
useAddonManager: "permanent",
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
await withHandlingUserInput(extension, async () => {
|
||||
extension.sendMessage("request", {
|
||||
permissions: ["clipboardWrite"],
|
||||
origins: ["https://test2.example.com/*"],
|
||||
});
|
||||
let result = await extension.awaitMessage("result");
|
||||
equal(result, true, "request() for optional permissions succeeded");
|
||||
});
|
||||
|
||||
const PERMS = ["history", "tabs"];
|
||||
const ORIGINS = ["https://test1.example.com/*", "https://test3.example.com/"];
|
||||
let xpi = Extension.generateXPI({
|
||||
background,
|
||||
manifest: {
|
||||
name: "permissions test",
|
||||
description: "permissions test",
|
||||
manifest_version: 2,
|
||||
version: "2.0",
|
||||
|
||||
applications: {gecko: {id: extension.id}},
|
||||
|
||||
permissions: [...PERMS, ...ORIGINS],
|
||||
optional_permissions: ["clipboardWrite", "<all_urls>"],
|
||||
},
|
||||
});
|
||||
|
||||
let install = await AddonManager.getInstallForFile(xpi);
|
||||
|
||||
Services.prefs.setBoolPref("extensions.webextPermissionPrompts", true);
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("extensions.webextPermissionPrompts");
|
||||
});
|
||||
|
||||
let perminfo;
|
||||
install.promptHandler = info => {
|
||||
perminfo = info;
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
await AddonTestUtils.promiseCompleteInstall(install);
|
||||
await extension.awaitStartup();
|
||||
|
||||
notEqual(perminfo, undefined, "Permission handler was invoked");
|
||||
let perms = perminfo.addon.userPermissions;
|
||||
deepEqual(perms.permissions, PERMS, "Update details includes only manifest api permissions");
|
||||
deepEqual(perms.origins, ORIGINS, "Update details includes only manifest origin permissions");
|
||||
|
||||
await extension.unload();
|
||||
await OS.File.remove(xpi.path);
|
||||
});
|
||||
|
||||
@@ -375,7 +375,7 @@ async function loadManifestFromWebManifest(aUri) {
|
||||
addon.iconURL = null;
|
||||
addon.icon64URL = null;
|
||||
addon.icons = manifest.icons || {};
|
||||
addon.userPermissions = extension.userPermissions;
|
||||
addon.userPermissions = extension.manifestPermissions;
|
||||
|
||||
addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
|
||||
|
||||
|
||||
@@ -498,7 +498,7 @@ add_task(async function test_permissions_prompt() {
|
||||
manifest_version: 2,
|
||||
version: "1.0",
|
||||
|
||||
permissions: ["tabs", "storage", "https://*.example.com/*", "<all_urls>", "experiments.test"],
|
||||
permissions: ["tabs", "storage", "https://*.example.com/*", "<all_urls>"],
|
||||
};
|
||||
|
||||
let xpi = ExtensionTestCommon.generateXPI({manifest});
|
||||
@@ -519,7 +519,6 @@ add_task(async function test_permissions_prompt() {
|
||||
let perms = perminfo.addon.userPermissions;
|
||||
deepEqual(perms.permissions, ["tabs", "storage"], "API permissions are correct");
|
||||
deepEqual(perms.origins, ["https://*.example.com/*", "<all_urls>"], "Host permissions are correct");
|
||||
deepEqual(perms.apis, ["test"], "Experiments permissions are correct");
|
||||
|
||||
let addon = await promiseAddonByID(perminfo.addon.id);
|
||||
notEqual(addon, null, "Extension was installed");
|
||||
|
||||
Reference in New Issue
Block a user