Bug 787439 - Ensure applications permissions are updated when doing a system update [r=marshall,ddahl]

This commit is contained in:
Fabrice Desré 2012-10-10 09:16:49 -07:00
parent 0dd7c92a0b
commit c2667e7437
9 changed files with 183 additions and 68 deletions

View File

@ -197,7 +197,31 @@ let AppsUtils = {
default:
throw new Error("Webapps.jsm: Undetermined app manifest type");
}
}
},
/**
* Determines if an update or a factory reset occured.
*/
isFirstRun: function isFirstRun(aPrefBranch) {
let savedmstone = null;
try {
savedmstone = aPrefBranch.getCharPref("gecko.mstone");
} catch (e) {}
let mstone = Services.appinfo.platformVersion;
let savedBuildID = null;
try {
savedBuildID = aPrefBranch.getCharPref("gecko.buildID");
} catch (e) {}
let buildID = Services.appinfo.platformBuildID;
aPrefBranch.setCharPref("gecko.mstone", mstone);
aPrefBranch.setCharPref("gecko.buildID", buildID);
return ((mstone != savedmstone) || (buildID != savedBuildID));
},
}
/**

View File

@ -53,8 +53,8 @@ function mapSuffixes(aPermName, aSuffixes)
// Permissions Matrix: https://docs.google.com/spreadsheet/ccc?key=0Akyz_Bqjgf5pdENVekxYRjBTX0dCXzItMnRyUU1RQ0E#gid=0
// Permissions that are implicit:
// battery-status, idle, network-information, vibration,
// device-capabilities, webapps-manage, web-activities
// battery-status, network-information, vibration,
// device-capabilities
const PermissionsTable = { "resource-lock": {
app: ALLOW_ACTION,
@ -71,12 +71,12 @@ const PermissionsTable = { "resource-lock": {
privileged: PROMPT_ACTION,
certified: ALLOW_ACTION
},
alarm: {
alarms: {
app: ALLOW_ACTION,
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
"network-tcp": {
"tcp-socket": {
app: DENY_ACTION,
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
@ -89,11 +89,7 @@ const PermissionsTable = { "resource-lock": {
contacts: {
app: DENY_ACTION,
privileged: PROMPT_ACTION,
certified: ALLOW_ACTION,
access: ["read",
"write",
"create"
]
certified: ALLOW_ACTION
},
"device-storage:apps": {
app: DENY_ACTION,
@ -163,10 +159,7 @@ const PermissionsTable = { "resource-lock": {
settings: {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION,
access: ["read",
"write"
],
certified: ALLOW_ACTION
},
permissions: {
app: DENY_ACTION,
@ -183,6 +176,71 @@ const PermissionsTable = { "resource-lock": {
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"webapps-manage": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"backgroundservice": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"desktop-notification": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"networkstats-manage": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"mozBluetooth": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"wifi-manage": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"systemXHR": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"voicemail": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"deprecated-hwvideo": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"idle": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"time": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"embed-apps": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"storage": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
};
// Sometimes all permissions (fully expanded) need to be iterated through
@ -213,7 +271,8 @@ function expandPermissions(aPermName, aAccess) {
}
if (!aAccess && PermissionsTable[aPermName].access ||
aAccess && !PermissionsTable[aPermName].access) {
Cu.reportError("PermissionsTable.jsm: expandPermissions: Invalid Manifest");
Cu.reportError("PermissionsTable.jsm: expandPermissions: Invalid Manifest : " +
aPermName + " " + aAccess + "\n");
throw new Error("PermissionsTable.jsm: expandPermissions: Invalid Manifest");
}
if (!PermissionsTable[aPermName].access) {
@ -252,10 +311,13 @@ function expandPermissions(aPermName, aAccess) {
let PermissionsInstaller = {
/**
* Install permissisions or remove deprecated permissions upon re-install
* @param object aData
* The just-installed app configuration
* @param object aApp
* The just-installed app configuration.
The properties used are manifestURL, origin and manifest.
* @param boolean aIsReinstall
* Indicates the app was just re-installed
* @param function aOnError
* A function called if an error occurs
* @returns void
**/
installPermissions: function installPermissions(aApp, aIsReinstall, aOnError) {
@ -292,11 +354,7 @@ let PermissionsInstaller = {
}
// Remove the deprecated permission
// TODO: use PermSettings.remove, see bug 793204
PermSettings.set(AllPossiblePermissions[idx],
"unknown",
aApp.manifestURL,
aApp.origin,
false);
this._setPermission(AllPossiblePermissions[idx], "unknown", aApp);
}
}
}
@ -304,7 +362,7 @@ let PermissionsInstaller = {
let installPermType;
// Check to see if the 'webapp' is app/priv/certified
switch (AppsUtils.getAppManifestStatus(newManifest)) {
switch (AppsUtils.getAppManifestStatus(aApp.manifest)) {
case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
installPermType = "certified";
break;
@ -316,12 +374,12 @@ let PermissionsInstaller = {
break;
default:
// Cannot determine app type, abort install by throwing an error
throw new Error("Webapps.jsm: Cannot determine app type, install cancelled");
throw new Error("PermissionsInstaller.jsm: Cannot determine app type, install cancelled");
}
for (let permName in newManifest.permissions) {
if (!PermissionsTable[permName]) {
throw new Error("Webapps.jsm: '" + permName + "'" +
throw new Error("PermissionsInstaller.jsm: '" + permName + "'" +
" is not a valid Webapps permission type. Aborting Webapp installation");
return;
}
@ -331,11 +389,7 @@ let PermissionsInstaller = {
for (let idx in perms) {
let perm = PermissionsTable[permName][installPermType];
let permValue = PERM_TO_STRING[perm];
PermSettings.set(perms[idx],
permValue,
aApp.manifestURL,
aApp.origin,
false);
this._setPermission(perms[idx], permValue, aApp);
}
}
}
@ -346,5 +400,30 @@ let PermissionsInstaller = {
aOnError();
}
}
},
/**
* Set a permission value, replacing "storage" if needed.
* @param string aPerm
* The permission name.
* @param string aValue
* The permission value.
* @param object aApp
* The just-installed app configuration.
The properties used are manifestURL, origin and manifest.
* @returns void
**/
_setPermission: function setPermission(aPerm, aValue, aApp) {
dump("XxXxX setting " + aPerm + " to " + aValue + "\n");
if (aPerm != "storage") {
PermSettings.set(aPerm, aValue, aApp.manifestURL, aApp.origin, false);
return;
}
["indexedDB-unlimited", "offline-app", "pin-app"].forEach(
function(aName) {
PermSettings.set(aName, aValue, aApp.manifestURL, aApp.origin, false);
}
);
}
}
}

View File

@ -145,6 +145,21 @@ let DOMApplicationRegistry = {
#endif
},
updatePermissionsForApp: function updatePermissionsForApp(aId) {
// Install the permissions for this app, as if we were updating
// to cleanup the old ones if needed.
this._readManifests([{ id: aId }], (function(aResult) {
let data = aResult[0];
PermissionsInstaller.installPermissions({
manifest: data.manifest,
manifestURL: this.webapps[aId].manifestURL,
origin: this.webapps[aId].origin
}, true, function() {
debug("Error installing permissions for " + aId);
});
}).bind(this));
},
// Implements the core of bug 787439
// 1. load the apps from the current registry.
// 2. if at first run, go through these steps:
@ -154,8 +169,7 @@ let DOMApplicationRegistry = {
// c. for all apps in the new core registry, install them if they are not
// yet in the current registry, and run installPermissions()
loadAndUpdateApps: function loadAndUpdateApps() {
let runUpdate = Services.prefs.getBoolPref("dom.mozApps.runUpdate");
Services.prefs.setBoolPref("dom.mozApps.runUpdate", false);
let runUpdate = AppsUtils.isFirstRun(Services.prefs);
// 1.
this.loadCurrentRegistry((function() {
@ -179,10 +193,14 @@ let DOMApplicationRegistry = {
for (let id in this.webapps) {
if (id in aData || this.webapps[id].removable)
continue;
let localId = this.webapps[id].localId;
delete this.webapps[id];
// XXXX once bug 758269 is ready, revoke perms for this app
// removePermissions(localId);
// Remove the permissions, cookies and private data for this app.
let localId = this.webapps[id].localId;
let permMgr = Cc["@mozilla.org/permissionmanager;1"]
.getService(Ci.nsIPermissionManager);
permMgr.RemovePermissionsForApp(localId);
Services.cookies.removeCookiesForApp(localId, false);
this._clearPrivateData(localId, false);
}
let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
@ -202,19 +220,28 @@ let DOMApplicationRegistry = {
this.webapps[id].removable = false;
}
}
// XXXX once bug 758269 is ready, revoke perms for this app
// let localId = this.webapps[id].localId;
// installPermissions(localId);
this.updatePermissionsForApp(id);
}
this.registerAppsHandlers();
}).bind(this));
} else {
// At first run, set up the permissions for eng builds.
for (let id in this.webapps) {
this.updatePermissionsForApp(id);
}
this.registerAppsHandlers();
}
} else {
this.registerAppsHandlers();
}
#else
if (runUpdate) {
// At first run, set up the permissions for desktop builds.
for (let id in this.webapps) {
this.updatePermissionsForApp(id);
}
}
this.registerAppsHandlers();
#endif
}).bind(this));

View File

@ -26,19 +26,15 @@ const TEST_ORIGIN_URL = "http://mochi.test:8888";
const installedPermsToTest = {
"geolocation": "prompt",
"alarm": "allow",
"contacts-read": "deny",
"contacts-create": "deny",
"contacts-write": "deny",
"device-storage:apps": "deny",
"alarms": "allow",
"contacts": "prompt",
"device-storage:apps": "allow",
};
const uninstalledPermsToTest = {
"geolocation": "unknown",
"alarm": "unknown",
"contacts-read": "unknown",
"contacts-create": "unknown",
"contacts-write": "unknown",
"alarms": "unknown",
"contacts": "unknown",
"device-storage:apps": "unknown",
};

View File

@ -14,19 +14,15 @@ const TEST_ORIGIN_URL = "http://mochi.test:8888";
const installedPermsToTest = {
"geolocation": "prompt",
"alarm": "allow",
"contacts-read": "deny",
"contacts-create": "deny",
"contacts-write": "deny",
"alarms": "allow",
"contacts": "deny",
"device-storage:apps": "deny",
};
const reinstalledPermsToTest = {
"geolocation": "prompt",
"alarm": "unknown",
"contacts-read": "deny",
"contacts-create": "deny",
"contacts-write": "deny",
"alarms": "unknown",
"contacts": "deny",
"device-storage:apps": "deny",
};

View File

@ -6,12 +6,11 @@
"geolocation": {
"description": "geolocate"
},
"alarm" : {
"alarms" : {
"description": "alarm"
},
"contacts": {
"description": "contacts",
"access": "readwrite"
"description": "contacts"
},
"device-storage:apps": {
"description": "storage"

View File

@ -7,8 +7,7 @@
"description": "geolocate"
},
"contacts": {
"description": "contacts",
"access": "read"
"description": "contacts"
},
"device-storage:apps": {
"description": "storage"

View File

@ -6,12 +6,11 @@
"geolocation": {
"description": "geolocate"
},
"alarm" : {
"alarms" : {
"description": "alarm"
},
"contacts": {
"description": "contacts",
"access": "readwrite"
"description": "contacts"
},
"device-storage:apps": {
"description": "storage"

View File

@ -3791,10 +3791,6 @@ pref("dom.mozApps.dev_mode", false);
// Lowest localId for apps.
pref("dom.mozApps.maxLocalId", 1000);
// Let us know wether we should run the permissions update algorithm.
// See Bug 787439
pref("dom.mozApps.runUpdate", true);
// Minimum delay in milliseconds between network activity notifications (0 means
// no notifications). The delay is the same for both download and upload, though
// they are handled separately. This pref is only read once at startup: