Bug 805655 - System messages are received by applications that should not be allowed to (part 4). r=fabrice,mounir

This commit is contained in:
Gene Lian 2012-11-28 18:57:16 +08:00
parent 3376879096
commit 6b0730d50b
4 changed files with 134 additions and 122 deletions

View File

@ -144,7 +144,7 @@ this.PermissionsTable = { geolocation: {
certified: ALLOW_ACTION
},
fmradio: {
app: ALLOW_ACTION, // Matrix indicates '?'
app: ALLOW_ACTION,
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
@ -256,11 +256,12 @@ this.appendAccessToPermName = function appendAccessToPermName(aPermName, aAccess
/**
* Expand an access string into multiple permission names,
* e.g: perm 'contacts' with 'readwrite' =
* ['contacts-read', 'contacts-create', contacts-write']
* e.g: permission name 'contacts' with 'readwrite' =
* ['contacts-read', 'contacts-create', 'contacts-write']
* @param string aPermName
* @param string aAccess
* @returns Array
* @param string array aChannels
* @returns array containing expanded permission names.
**/
this.expandPermissions = function expandPermissions(aPermName, aAccess, aChannels) {
if (!PermissionsTable[aPermName]) {
@ -287,45 +288,45 @@ this.expandPermissions = function expandPermissions(aPermName, aAccess, aChannel
aPermName + " " + aAccess + "\n");
}
let expandedPerms = [];
let expandedPermNames = [];
if (tableEntry.access && aAccess) {
let requestedSuffixes = [];
let requestedSuffixes = [];
switch (aAccess) {
case READONLY:
requestedSuffixes.push("read");
break;
case CREATEONLY:
requestedSuffixes.push("create");
break;
case READCREATE:
requestedSuffixes.push("read", "create");
break;
case READWRITE:
requestedSuffixes.push("read", "create", "write");
break;
default:
return [];
}
let permArr = appendAccessToPermName(aPermName, requestedSuffixes);
// Add the same suffix to each of the additions.
if (tableEntry.additional) {
for each (let additional in tableEntry.additional) {
permArr = permArr.concat(appendAccessToPermName(additional, requestedSuffixes));
case READONLY:
requestedSuffixes.push("read");
break;
case CREATEONLY:
requestedSuffixes.push("create");
break;
case READCREATE:
requestedSuffixes.push("read", "create");
break;
case READWRITE:
requestedSuffixes.push("read", "create", "write");
break;
default:
return [];
}
}
// Only add the suffixed version if the suffix exisits in the table.
for (let idx in permArr) {
let permArr = appendAccessToPermName(aPermName, requestedSuffixes);
// Add the same suffix to each of the additions.
if (tableEntry.additional) {
for each (let additional in tableEntry.additional) {
permArr = permArr.concat(appendAccessToPermName(additional, requestedSuffixes));
}
}
// Only add the suffixed version if the suffix exisits in the table.
for (let idx in permArr) {
let suffix = requestedSuffixes[idx % requestedSuffixes.length];
if (tableEntry.access.indexOf(suffix) != -1) {
expandedPerms.push(permArr[idx]);
expandedPermNames.push(permArr[idx]);
}
}
}
} else if (tableEntry.substitute) {
expandedPerms = expandedPerms.concat(tableEntry.substitute);
expandedPermNames = expandedPermNames.concat(tableEntry.substitute);
} else if (tableEntry.channels) {
if ("audio" == aPermName && aChannels) {
let allowChannels = tableEntry.channels;
@ -333,24 +334,24 @@ this.expandPermissions = function expandPermissions(aPermName, aAccess, aChannel
for (let idx in aChannels) {
let candidate = aChannels[idx];
if (allowChannels.indexOf(candidate) == -1) {
continue;
continue;
}
let permAttr = aPermName + "-channel-" + candidate;
expandedPerms.push(permAttr);
expandedPermNames.push(permAttr);
}
}
} else {
expandedPerms.push(aPermName);
expandedPermNames.push(aPermName);
// Include each of the additions exactly as they appear in the table.
if (tableEntry.additional) {
expandedPerms = expandedPerms.concat(tableEntry.additional);
expandedPermNames = expandedPermNames.concat(tableEntry.additional);
}
}
return expandedPerms;
return expandedPermNames;
};
// Sometimes all permissions (fully expanded) need to be iterated through
// An array carring all the possible (expanded) permission names.
let AllPossiblePermissions = [];
for (let permName in PermissionsTable) {
if (PermissionsTable[permName].access) {
@ -365,11 +366,11 @@ for (let permName in PermissionsTable) {
}
this.PermissionsInstaller = {
/**
* Install permissisions or remove deprecated permissions upon re-install
/**
* Install permissisions or remove deprecated permissions upon re-install.
* @param object aApp
* The just-installed app configuration.
The properties used are manifestURL, origin and manifest.
* The properties used are manifestURL, origin and manifest.
* @param boolean aIsReinstall
* Indicates the app was just re-installed
* @param function aOnError
@ -388,67 +389,74 @@ this.PermissionsInstaller = {
// Remove any deprecated Permissions
if (newManifest.permissions) {
// Expand perms
let newPerms = [];
for (let perm in newManifest.permissions) {
let _perms = expandPermissions(perm,
newManifest.permissions[perm].access,
newManifest.permissions[perm].channels);
newPerms = newPerms.concat(_perms);
// Expand permission names.
let newPermNames = [];
for (let permName in newManifest.permissions) {
let expandedPermNames =
expandPermissions(permName,
newManifest.permissions[permName].access,
newManifest.permissions[permName].channels);
newPermNames = newPermNames.concat(expandedPermNames);
}
for (let idx in AllPossiblePermissions) {
let index = newPerms.indexOf(AllPossiblePermissions[idx]);
let permName = AllPossiblePermissions[idx];
let index = newPermNames.indexOf(permName);
if (index == -1) {
// See if the permission was installed previously
let _perm = PermissionSettingsModule.getPermission(AllPossiblePermissions[idx],
aApp.manifestURL,
aApp.origin,
false);
if (_perm == "unknown" || _perm == "deny") {
// See if the permission was installed previously.
let permValue =
PermissionSettingsModule.getPermission(permName,
aApp.manifestURL,
aApp.origin,
false);
if (permValue == "unknown" || permValue == "deny") {
// All 'deny' permissions should be preserved
continue;
}
// Remove the deprecated permission
// TODO: use PermSettings.remove, see bug 793204
this._setPermission(AllPossiblePermissions[idx], "unknown", aApp);
this._setPermission(permName, "unknown", aApp);
}
}
}
}
let installPermType;
// Check to see if the 'webapp' is app/priv/certified
// Check to see if the 'webapp' is app/privileged/certified.
let appStatus;
switch (AppsUtils.getAppManifestStatus(aApp.manifest)) {
case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
installPermType = "certified";
appStatus = "certified";
break;
case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
installPermType = "privileged";
appStatus = "privileged";
break;
case Ci.nsIPrincipal.APP_STATUS_INSTALLED:
installPermType = "app";
appStatus = "app";
break;
default:
// Cannot determine app type, abort install by throwing an error
throw new Error("PermissionsInstaller.jsm: Cannot determine app type, install cancelled");
// Cannot determine app type, abort install by throwing an error.
throw new Error("PermissionsInstaller.jsm: " +
"Cannot determine the app's status. Install cancelled.");
break;
}
for (let permName in newManifest.permissions) {
if (!PermissionsTable[permName]) {
Cu.reportError("PermissionsInstaller.jsm: '" + permName + "'" +
" is not a valid Webapps permission type.");
" is not a valid Webapps permission name.");
dump("PermissionsInstaller.jsm: '" + permName + "'" +
" is not a valid Webapps permission type.");
" is not a valid Webapps permission name.");
continue;
}
let perms = expandPermissions(permName,
newManifest.permissions[permName].access,
newManifest.permissions[permName].channels);
for (let idx in perms) {
let perm = PermissionsTable[permName][installPermType];
let permValue = PERM_TO_STRING[perm];
this._setPermission(perms[idx], permValue, aApp);
let expandedPermNames =
expandPermissions(permName,
newManifest.permissions[permName].access,
newManifest.permissions[permName].channels);
for (let idx in expandedPermNames) {
this._setPermission(expandedPermNames[idx],
PERM_TO_STRING[PermissionsTable[permName][appStatus]],
aApp);
}
}
}
@ -462,23 +470,23 @@ this.PermissionsInstaller = {
},
/**
* Set a permission value
* @param string aPerm
* Set a permission value.
* @param string aPermName
* The permission name.
* @param string aValue
* @param string aPermValue
* The permission value.
* @param object aApp
* The just-installed app configuration.
The properties used are manifestURL, origin and manifest.
* The properties used are manifestURL and origin.
* @returns void
**/
_setPermission: function setPermission(aPerm, aValue, aApp) {
PermissionSettingsModule.addPermission({
type: aPerm,
origin: aApp.origin,
manifestURL: aApp.manifestURL,
value: aValue,
browserFlag: false
});
}
_setPermission: function setPermission(aPermName, aPermValue, aApp) {
PermissionSettingsModule.addPermission({
type: aPermName,
origin: aApp.origin,
manifestURL: aApp.manifestURL,
value: aPermValue,
browserFlag: false
});
}
};

View File

@ -49,47 +49,47 @@ var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptS
var appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
this.PermissionPromptHelper = {
init: function() {
init: function init() {
debug("Init");
ppmm.addMessageListener("PermissionPromptHelper:AskPermission", this);
Services.obs.addObserver(this, "profile-before-change", false);
},
askPermission: function(aMessage, aCallbacks) {
askPermission: function askPermission(aMessage, aCallbacks) {
let msg = aMessage.json;
let access;
if (PermissionsTable[msg.type].access) {
access = "readwrite"; // XXXddahl: Not sure if this should be set to READWRITE
}
// expand Permissions:
var expandedPerms = expandPermissions(msg.type, access);
let installedPerms = [];
// Expand permission names.
var expandedPermNames = expandPermissions(msg.type, access);
let installedPermValues = [];
let principal;
for (let idx in expandedPerms) {
for (let idx in expandedPermNames) {
let uri = Services.io.newURI(msg.origin, null, null);
principal =
secMan.getAppCodebasePrincipal(uri, msg.appID, msg.browserFlag);
let access = msg.access ? msg.type + "-" + msg.access : msg.type;
let perm =
let permValue =
permissionManager.testExactPermissionFromPrincipal(principal, access);
installedPerms.push(perm);
installedPermValues.push(permValue);
}
// TODO: see bug 804623, We are preventing "read" operations
// even if just "write" has been set to DENY_ACTION
for (let idx in installedPerms) {
// if any of the installedPerms are deny, run aCallbacks.cancel
if (installedPerms[idx] == Ci.nsIPermissionManager.DENY_ACTION ||
installedPerms[idx] == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
for (let idx in installedPermValues) {
// if any of the installedPermValues are deny, run aCallbacks.cancel
if (installedPermValues[idx] == Ci.nsIPermissionManager.DENY_ACTION ||
installedPermValues[idx] == Ci.nsIPermissionManager.UNKNOWN_ACTION) {
aCallbacks.cancel();
return;
}
}
for (let idx in installedPerms) {
if (installedPerms[idx] == Ci.nsIPermissionManager.PROMPT_ACTION) {
for (let idx in installedPermValues) {
if (installedPermValues[idx] == Ci.nsIPermissionManager.PROMPT_ACTION) {
// create a nsIContentPermissionRequest
let request = {
type: msg.type,
@ -105,21 +105,21 @@ this.PermissionPromptHelper = {
}
}
for (let idx in installedPerms) {
if (installedPerms[idx] == Ci.nsIPermissionManager.ALLOW_ACTION) {
for (let idx in installedPermValues) {
if (installedPermValues[idx] == Ci.nsIPermissionManager.ALLOW_ACTION) {
aCallbacks.allow();
return;
}
}
},
observe: function(aSubject, aTopic, aData) {
observe: function observe(aSubject, aTopic, aData) {
ppmm.removeMessageListener("PermissionPromptHelper:AskPermission", this);
Services.obs.removeObserver(this, "profile-before-change");
ppmm = null;
},
receiveMessage: function(aMessage) {
receiveMessage: function receiveMessage(aMessage) {
debug("PermissionPromptHelper::receiveMessage " + aMessage.name);
let mm = aMessage.target;
let msg = aMessage.data;
@ -128,10 +128,14 @@ this.PermissionPromptHelper = {
if (aMessage.name == "PermissionPromptHelper:AskPermission") {
this.askPermission(aMessage, {
cancel: function() {
mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK", {result: Ci.nsIPermissionManager.DENY_ACTION, requestID: msg.requestID});
mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK",
{ result: Ci.nsIPermissionManager.DENY_ACTION,
requestID: msg.requestID });
},
allow: function() {
mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK", {result: Ci.nsIPermissionManager.ALLOW_ACTION, requestID: msg.requestID});
mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK",
{ result: Ci.nsIPermissionManager.ALLOW_ACTION,
requestID: msg.requestID });
}
});
}

View File

@ -44,12 +44,12 @@ XPCOMUtils.defineLazyServiceGetter(this,
"nsIAppsService");
PermissionSettings.prototype = {
get: function get(aPermission, aManifestURL, aOrigin, aBrowserFlag) {
debug("Get called with: " + aPermission + ", " + aManifestURL + ", " + aOrigin + ", " + aBrowserFlag);
get: function get(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
debug("Get called with: " + aPermName + ", " + aManifestURL + ", " + aOrigin + ", " + aBrowserFlag);
let uri = Services.io.newURI(aOrigin, null, null);
let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermName);
switch (result)
{
@ -67,19 +67,19 @@ PermissionSettings.prototype = {
}
},
set: function set(aPermission, aValue, aManifestURL, aOrigin, aBrowserFlag) {
debug("Set called with: " + aPermission + ", " + aManifestURL + ", " + aOrigin + ", " + aValue + ", " + aBrowserFlag);
set: function set(aPermName, aPermValue, aManifestURL, aOrigin, aBrowserFlag) {
debug("Set called with: " + aPermName + ", " + aManifestURL + ", " + aOrigin + ", " + aPermValue + ", " + aBrowserFlag);
let action;
cpm.sendSyncMessage("PermissionSettings:AddPermission", {
type: aPermission,
type: aPermName,
origin: aOrigin,
manifestURL: aManifestURL,
value: aValue,
value: aPermValue,
browserFlag: aBrowserFlag
});
},
init: function(aWindow) {
init: function init(aWindow) {
debug("init");
// Set navigator.mozPermissionSettings to null.

View File

@ -37,13 +37,13 @@ XPCOMUtils.defineLazyServiceGetter(this,
"nsIAppsService");
this.PermissionSettingsModule = {
init: function() {
init: function init() {
debug("Init");
ppmm.addMessageListener("PermissionSettings:AddPermission", this);
Services.obs.addObserver(this, "profile-before-change", false);
},
addPermission: function(aData, aCallbacks) {
addPermission: function addPermission(aData, aCallbacks) {
let uri = Services.io.newURI(aData.origin, null, null);
let appID = appsService.getAppLocalIdByManifestURL(aData.manifestURL);
let principal = secMan.getAppCodebasePrincipal(uri, appID, aData.browserFlag);
@ -71,12 +71,12 @@ this.PermissionSettingsModule = {
permissionManager.addFromPrincipal(principal, aData.type, action);
},
getPermission: function getPermission(aPermission, aManifestURL, aOrigin, aBrowserFlag) {
debug("getPermission: " + aPermission + ", " + aManifestURL + ", " + aOrigin);
getPermission: function getPermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
debug("getPermission: " + aPermName + ", " + aManifestURL + ", " + aOrigin);
let uri = Services.io.newURI(aOrigin, null, null);
let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermName);
switch (result)
{
@ -94,13 +94,13 @@ this.PermissionSettingsModule = {
}
},
observe: function(aSubject, aTopic, aData) {
observe: function observe(aSubject, aTopic, aData) {
ppmm.removeMessageListener("PermissionSettings:AddPermission", this);
Services.obs.removeObserver(this, "profile-before-change");
ppmm = null;
},
receiveMessage: function(aMessage) {
receiveMessage: function receiveMessage(aMessage) {
debug("PermissionSettings::receiveMessage " + aMessage.name);
let mm = aMessage.target;
let msg = aMessage.data;