Bug 1330467 - part 2. Add SitePermissions APIs functions to accept principal; r=johannh

Differential Revision: https://phabricator.services.mozilla.com/D19923

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Liang-Heng Chen 2019-05-07 22:15:43 +00:00
parent bcff5a6630
commit 8e1e5c0a50

View File

@ -259,6 +259,7 @@ var SitePermissions = {
_defaultPrefBranch: Services.prefs.getBranch("permissions.default."),
/**
* Deprecated! Please use getAllByPrincipal(principal) instead.
* Gets all custom permissions for a given URI.
* Install addon permission is excluded, check bug 1303108.
*
@ -271,12 +272,28 @@ var SitePermissions = {
getAllByURI(uri) {
if (!(uri instanceof Ci.nsIURI))
throw new Error("uri parameter should be an nsIURI");
let principal = uri ? Services.scriptSecurityManager.createCodebasePrincipal(uri, {}) : null;
return this.getAllByPrincipal(principal);
},
/**
* Gets all custom permissions for a given principal.
* Install addon permission is excluded, check bug 1303108.
*
* @return {Array} a list of objects with the keys:
* - id: the permissionId of the permission
* - scope: the scope of the permission (e.g. SitePermissions.SCOPE_TEMPORARY)
* - state: a constant representing the current permission state
* (e.g. SitePermissions.ALLOW)
*/
getAllByPrincipal(principal) {
let result = [];
if (!this.isSupportedURI(uri)) {
if (!this.isSupportedPrincipal(principal)) {
return result;
}
let permissions = Services.perms.getAllForURI(uri);
let permissions = Services.perms.getAllForPrincipal(principal);
while (permissions.hasMoreElements()) {
let permission = permissions.getNext();
@ -338,7 +355,7 @@ var SitePermissions = {
permissions[permission.id] = permission;
}
for (let permission of this.getAllByURI(browser.currentURI)) {
for (let permission of this.getAllByPrincipal(browser.contentPrincipal)) {
permissions[permission.id] = permission;
}
@ -366,6 +383,7 @@ var SitePermissions = {
},
/**
* Deprecated! Please use isSupportedPrincipal(principal) instead.
* Checks whether a UI for managing permissions should be exposed for a given
* URI. This excludes file URIs, for instance, as they don't have a host,
* even though nsIPermissionManager can still handle them.
@ -380,6 +398,21 @@ var SitePermissions = {
},
/**
* Checks whether a UI for managing permissions should be exposed for a given
* principal. This excludes file URIs, for instance, as they don't have a host,
* even though nsIPermissionManager can still handle them.
*
* @param {nsIPrincipal} principal
* The principal to check.
*
* @return {boolean} if the principal is supported.
*/
isSupportedPrincipal(principal) {
return principal && principal.URI &&
["http", "https", "moz-extension"].includes(principal.URI.scheme);
},
/**
* Gets an array of all permission IDs.
*
* @return {Array<String>} an array of all permission IDs.
@ -478,15 +511,40 @@ var SitePermissions = {
get(uri, permissionID, browser) {
if ((!uri && !browser) || (uri && !(uri instanceof Ci.nsIURI)))
throw new Error("uri parameter should be an nsIURI or a browser parameter is needed");
let principal = uri ? Services.scriptSecurityManager.createCodebasePrincipal(uri, {}) : null;
return this.getForPrincipal(principal, permissionID, browser);
},
/**
* Returns the state and scope of a particular permission for a given principal.
*
* This method will NOT dispatch a "PermissionStateChange" event on the specified
* browser if a temporary permission was removed because it has expired.
*
* @param {nsIPrincipal} principal
* The principal to check.
* @param {String} permissionID
* The id of the permission.
* @param {Browser} browser (optional)
* The browser object to check for temporary permissions.
*
* @return {Object} an object with the keys:
* - state: The current state of the permission
* (e.g. SitePermissions.ALLOW)
* - scope: The scope of the permission
* (e.g. SitePermissions.SCOPE_PERSISTENT)
*/
getForPrincipal(principal, permissionID, browser) {
let defaultState = this.getDefault(permissionID);
let result = { state: defaultState, scope: this.SCOPE_PERSISTENT };
if (this.isSupportedURI(uri)) {
if (this.isSupportedPrincipal(principal)) {
let permission = null;
if (permissionID in gPermissionObject &&
gPermissionObject[permissionID].exactHostMatch) {
permission = Services.perms.getPermissionObjectForURI(uri, permissionID, true);
permission = Services.perms.getPermissionObject(principal, permissionID, true);
} else {
permission = Services.perms.getPermissionObjectForURI(uri, permissionID, false);
permission = Services.perms.getPermissionObject(principal, permissionID, false);
}
if (permission) {
@ -514,6 +572,7 @@ var SitePermissions = {
},
/**
* Deprecated! Use setForPrincipal(...) instead.
* Sets the state of a particular permission for a given URI or browser.
* This method will dispatch a "PermissionStateChange" event on the specified
* browser if a temporary permission was set
@ -534,6 +593,30 @@ var SitePermissions = {
set(uri, permissionID, state, scope = this.SCOPE_PERSISTENT, browser = null) {
if ((!uri && !browser) || (uri && !(uri instanceof Ci.nsIURI)))
throw new Error("uri parameter should be an nsIURI or a browser parameter is needed");
let principal = uri ? Services.scriptSecurityManager.createCodebasePrincipal(uri, {}) : null;
return this.setForPrincipal(principal, permissionID, state, scope, browser);
},
/**
* Sets the state of a particular permission for a given principal or browser.
* This method will dispatch a "PermissionStateChange" event on the specified
* browser if a temporary permission was set
*
* @param {nsIPrincipal} principal
* The principal to set the permission for.
* Note that this will be ignored if the scope is set to SCOPE_TEMPORARY
* @param {String} permissionID
* The id of the permission.
* @param {SitePermissions state} state
* The state of the permission.
* @param {SitePermissions scope} scope (optional)
* The scope of the permission. Defaults to SCOPE_PERSISTENT.
* @param {Browser} browser (optional)
* The browser object to set temporary permissions on.
* This needs to be provided if the scope is SCOPE_TEMPORARY!
*/
setForPrincipal(principal, permissionID, state, scope = this.SCOPE_PERSISTENT, browser = null) {
if (scope == this.SCOPE_GLOBAL && state == this.BLOCK) {
GloballyBlockedPermissions.set(browser, permissionID);
browser.dispatchEvent(new browser.ownerGlobal.CustomEvent("PermissionStateChange"));
@ -545,7 +628,7 @@ var SitePermissions = {
// correspond to the classical ALLOW/DENY/PROMPT model, we want to always
// allow the user to add exceptions to their cookie rules without removing them.
if (permissionID != "cookie") {
this.remove(uri, permissionID, browser);
this.removeFromPrincipal(principal, permissionID, browser);
return;
}
}
@ -559,7 +642,7 @@ var SitePermissions = {
// We do not support setting temp ALLOW for security reasons.
// In its current state, this permission could be exploited by subframes
// on the same page. This is because for BLOCK we ignore the request
// URI and only consider the current browser URI, to avoid notification spamming.
// principal and only consider the current browser principal, to avoid notification spamming.
//
// If you ever consider removing this line, you likely want to implement
// a more fine-grained TemporaryPermissions that temporarily blocks for the
@ -576,7 +659,7 @@ var SitePermissions = {
browser.dispatchEvent(new browser.ownerGlobal
.CustomEvent("PermissionStateChange"));
} else if (this.isSupportedURI(uri)) {
} else if (this.isSupportedPrincipal(principal)) {
let perms_scope = Services.perms.EXPIRE_NEVER;
if (scope == this.SCOPE_SESSION) {
perms_scope = Services.perms.EXPIRE_SESSION;
@ -584,11 +667,12 @@ var SitePermissions = {
perms_scope = Services.perms.EXPIRE_POLICY;
}
Services.perms.add(uri, permissionID, state, perms_scope);
Services.perms.addFromPrincipal(principal, permissionID, state, perms_scope);
}
},
/**
* Deprecated! Please use removeFromPrincipal(principal, permissionID, browser).
* Removes the saved state of a particular permission for a given URI and/or browser.
* This method will dispatch a "PermissionStateChange" event on the specified
* browser if a temporary permission was removed.
@ -603,8 +687,26 @@ var SitePermissions = {
remove(uri, permissionID, browser) {
if ((!uri && !browser) || (uri && !(uri instanceof Ci.nsIURI)))
throw new Error("uri parameter should be an nsIURI or a browser parameter is needed");
if (this.isSupportedURI(uri))
Services.perms.remove(uri, permissionID);
let principal = uri ? Services.scriptSecurityManager.createCodebasePrincipal(uri, {}) : null;
return this.removeFromPrincipal(principal, permissionID, browser);
},
/**
* Removes the saved state of a particular permission for a given principal and/or browser.
* This method will dispatch a "PermissionStateChange" event on the specified
* browser if a temporary permission was removed.
*
* @param {nsIPrincipal} principal
* The principal to remove the permission for.
* @param {String} permissionID
* The id of the permission.
* @param {Browser} browser (optional)
* The browser object to remove temporary permissions on.
*/
removeFromPrincipal(principal, permissionID, browser) {
if (this.isSupportedPrincipal(principal))
Services.perms.removeFromPrincipal(principal, permissionID);
// TemporaryPermissions.get() deletes expired permissions automatically,
if (TemporaryPermissions.get(browser, permissionID)) {