Bug 1197420 Part 4 Apply dynamic permission changes r=kmag
MozReview-Commit-ID: 6TdcUv1fHPh
This commit is contained in:
@@ -36,6 +36,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
|
||||
"resource://gre/modules/AppConstants.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionAPIs",
|
||||
"resource://gre/modules/ExtensionAPI.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionPermissions",
|
||||
"resource://gre/modules/ExtensionPermissions.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionStorage",
|
||||
"resource://gre/modules/ExtensionStorage.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionTestCommon",
|
||||
@@ -632,7 +634,7 @@ this.ExtensionData = class {
|
||||
|
||||
let _browserUpdated = false;
|
||||
|
||||
const PROXIED_EVENTS = new Set(["test-harness-message"]);
|
||||
const PROXIED_EVENTS = new Set(["test-harness-message", "add-permissions", "remove-permissions"]);
|
||||
|
||||
// We create one instance of this class per extension. |addonData|
|
||||
// comes directly from bootstrap.js when initializing.
|
||||
@@ -684,6 +686,28 @@ this.Extension = class extends ExtensionData {
|
||||
this.webAccessibleResources = null;
|
||||
|
||||
this.emitter = new EventEmitter();
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
this.on("add-permissions", (ignoreEvent, permissions) => {
|
||||
for (let perm of permissions.permissions) {
|
||||
this.permissions.add(perm);
|
||||
}
|
||||
|
||||
if (permissions.origins.length > 0) {
|
||||
this.whiteListedHosts = new MatchPattern(this.whiteListedHosts.pat.concat(...permissions.origins));
|
||||
}
|
||||
});
|
||||
|
||||
this.on("remove-permissions", (ignoreEvent, permissions) => {
|
||||
for (let perm of permissions.permissions) {
|
||||
this.permissions.delete(perm);
|
||||
}
|
||||
|
||||
for (let origin of permissions.origins) {
|
||||
this.whiteListedHosts.removeOne(origin);
|
||||
}
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
}
|
||||
|
||||
static set browserUpdated(updated) {
|
||||
@@ -797,6 +821,7 @@ this.Extension = class extends ExtensionData {
|
||||
localeData: this.localeData.serialize(),
|
||||
permissions: this.permissions,
|
||||
principal: this.principal,
|
||||
optionalPermissions: this.manifest.optional_permissions,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -894,16 +919,19 @@ this.Extension = class extends ExtensionData {
|
||||
return super.initLocale(locale);
|
||||
}
|
||||
|
||||
startup() {
|
||||
async startup() {
|
||||
let started = false;
|
||||
return this.loadManifest().then(() => {
|
||||
|
||||
try {
|
||||
let [, perms] = await Promise.all([this.loadManifest(), ExtensionPermissions.get(this)]);
|
||||
|
||||
ExtensionManagement.startupExtension(this.uuid, this.addonData.resourceURI, this);
|
||||
started = true;
|
||||
|
||||
if (!this.hasShutdown) {
|
||||
return this.initLocale();
|
||||
await this.initLocale();
|
||||
}
|
||||
}).then(() => {
|
||||
|
||||
if (this.errors.length) {
|
||||
return Promise.reject({errors: this.errors});
|
||||
}
|
||||
@@ -914,6 +942,14 @@ this.Extension = class extends ExtensionData {
|
||||
|
||||
GlobalManager.init(this);
|
||||
|
||||
// Apply optional permissions
|
||||
for (let perm of perms.permissions) {
|
||||
this.permissions.add(perm);
|
||||
}
|
||||
if (perms.origins.length > 0) {
|
||||
this.whiteListedHosts = new MatchPattern(this.whiteListedHosts.pat.concat(...perms.origins));
|
||||
}
|
||||
|
||||
// The "startup" Management event sent on the extension instance itself
|
||||
// is emitted just before the Management "startup" event,
|
||||
// and it is used to run code that needs to be executed before
|
||||
@@ -921,10 +957,10 @@ this.Extension = class extends ExtensionData {
|
||||
this.emit("startup", this);
|
||||
Management.emit("startup", this);
|
||||
|
||||
return this.runManifest(this.manifest);
|
||||
}).then(() => {
|
||||
await this.runManifest(this.manifest);
|
||||
|
||||
Management.emit("ready", this);
|
||||
}).catch(e => {
|
||||
} catch (e) {
|
||||
dump(`Extension error: ${e.message} ${e.filename || e.fileName}:${e.lineNumber} :: ${e.stack || new Error().stack}\n`);
|
||||
Cu.reportError(e);
|
||||
|
||||
@@ -935,7 +971,7 @@ this.Extension = class extends ExtensionData {
|
||||
this.cleanupGeneratedFile();
|
||||
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cleanupGeneratedFile() {
|
||||
@@ -1007,13 +1043,21 @@ this.Extension = class extends ExtensionData {
|
||||
}
|
||||
}
|
||||
|
||||
hasPermission(perm) {
|
||||
hasPermission(perm, includeOptional = false) {
|
||||
let match = /^manifest:(.*)/.exec(perm);
|
||||
if (match) {
|
||||
return this.manifest[match[1]] != null;
|
||||
}
|
||||
|
||||
return this.permissions.has(perm);
|
||||
if (this.permissions.has(perm)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (includeOptional && this.manifest.optional_permissions.includes(perm)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get name() {
|
||||
|
||||
@@ -627,6 +627,22 @@ class ChildAPIManager {
|
||||
Object.assign(params, contextData);
|
||||
|
||||
this.messageManager.sendAsyncMessage("API:CreateProxyContext", params);
|
||||
|
||||
this.permissionsChangedCallbacks = new Set();
|
||||
this.updatePermissions = null;
|
||||
if (this.context.extension.optionalPermissions.length > 0) {
|
||||
this.updatePermissions = () => {
|
||||
for (let callback of this.permissionsChangedCallbacks) {
|
||||
try {
|
||||
callback();
|
||||
} catch (err) {
|
||||
Cu.reportError(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.context.extension.on("add-permissions", this.updatePermissions);
|
||||
this.context.extension.on("remove-permissions", this.updatePermissions);
|
||||
}
|
||||
}
|
||||
|
||||
receiveMessage({name, messageName, data}) {
|
||||
@@ -726,6 +742,10 @@ class ChildAPIManager {
|
||||
|
||||
close() {
|
||||
this.messageManager.sendAsyncMessage("API:CloseProxyContext", {childId: this.id});
|
||||
if (this.updatePermissions) {
|
||||
this.context.extension.off("add-permissions", this.updatePermissions);
|
||||
this.context.extension.off("remove-permissions", this.updatePermissions);
|
||||
}
|
||||
}
|
||||
|
||||
get cloneScope() {
|
||||
@@ -781,6 +801,14 @@ class ChildAPIManager {
|
||||
hasPermission(permission) {
|
||||
return this.context.extension.hasPermission(permission);
|
||||
}
|
||||
|
||||
isPermissionRevokable(permission) {
|
||||
return this.context.extension.optionalPermissions.includes(permission);
|
||||
}
|
||||
|
||||
setPermissionsChangedCallback(callback) {
|
||||
this.permissionsChangedCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
class ExtensionBaseContextChild extends BaseContext {
|
||||
|
||||
@@ -689,8 +689,11 @@ class SchemaAPIManager extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function hasPermission(perm) {
|
||||
return context.extension.hasPermission(perm, true);
|
||||
}
|
||||
for (let api of apis) {
|
||||
if (Schemas.checkPermissions(api.namespace, context.extension)) {
|
||||
if (Schemas.checkPermissions(api.namespace, {hasPermission})) {
|
||||
api = api.getAPI(context);
|
||||
copy(obj, api);
|
||||
}
|
||||
|
||||
@@ -991,6 +991,7 @@ class BrowserExtensionContent extends EventEmitter {
|
||||
this.webAccessibleResources = new MatchGlobs(data.webAccessibleResources);
|
||||
this.whiteListedHosts = new MatchPattern(data.whiteListedHosts);
|
||||
this.permissions = data.permissions;
|
||||
this.optionalPermissions = data.optionalPermissions;
|
||||
this.principal = data.principal;
|
||||
|
||||
this.localeData = new LocaleData(data.localeData);
|
||||
@@ -1010,6 +1011,34 @@ class BrowserExtensionContent extends EventEmitter {
|
||||
// Extension.jsm takes care of this in the parent.
|
||||
ExtensionManagement.startupExtension(this.uuid, uri, this);
|
||||
}
|
||||
|
||||
/* eslint-disable mozilla/balanced-listeners */
|
||||
this.on("add-permissions", (ignoreEvent, permissions) => {
|
||||
if (permissions.permissions.length > 0) {
|
||||
for (let perm of permissions.permissions) {
|
||||
this.permissions.add(perm);
|
||||
}
|
||||
}
|
||||
|
||||
if (permissions.origins.length > 0) {
|
||||
this.whiteListedHosts = new MatchPattern(this.whiteListedHosts.pat.concat(...permissions.origins));
|
||||
}
|
||||
});
|
||||
|
||||
this.on("remove-permissions", (ignoreEvent, permissions) => {
|
||||
if (permissions.permissions.length > 0) {
|
||||
for (let perm of permissions.permissions) {
|
||||
this.permissions.delete(perm);
|
||||
}
|
||||
}
|
||||
|
||||
if (permissions.origins.length > 0) {
|
||||
for (let origin of permissions.origins) {
|
||||
this.whiteListedHosts.removeOne(origin);
|
||||
}
|
||||
}
|
||||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
|
||||
@@ -66,7 +66,7 @@ this.ExtensionPermissions = {
|
||||
|
||||
if (added.permissions.length > 0 || added.origins.length > 0) {
|
||||
prefs.saveSoon();
|
||||
// TODO apply the changes
|
||||
extension.emit("add-permissions", added);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -99,7 +99,7 @@ this.ExtensionPermissions = {
|
||||
|
||||
if (removed.permissions.length > 0 || removed.origins.length > 0) {
|
||||
prefs.saveSoon();
|
||||
// TODO apply the changes
|
||||
extension.emit("remove-permissions", removed);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -182,7 +182,8 @@
|
||||
"optional_permissions": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "OptionalPermission" },
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"default": []
|
||||
},
|
||||
|
||||
"web_accessible_resources": {
|
||||
|
||||
@@ -199,6 +199,21 @@ MatchPattern.prototype = {
|
||||
serialize() {
|
||||
return this.pat;
|
||||
},
|
||||
|
||||
removeOne(pattern) {
|
||||
if (!Array.isArray(this.pat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this.pat.indexOf(pattern);
|
||||
if (index >= 0) {
|
||||
if (this.matchers[index].pat != pattern) {
|
||||
throw new Error("pat/matcher mismatch in removeOne()");
|
||||
}
|
||||
this.pat.splice(index, 1);
|
||||
this.matchers.splice(index, 1);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Globs can match everything. Be careful, this DOES NOT filter by allowed schemes!
|
||||
|
||||
Reference in New Issue
Block a user