Mypal/dom/apps/PermissionsInstaller.jsm

211 lines
7.7 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/PermissionSettings.jsm");
Cu.import("resource://gre/modules/PermissionsTable.jsm");
this.EXPORTED_SYMBOLS = ["PermissionsInstaller"];
const UNKNOWN_ACTION = Ci.nsIPermissionManager.UNKNOWN_ACTION;
const ALLOW_ACTION = Ci.nsIPermissionManager.ALLOW_ACTION;
const DENY_ACTION = Ci.nsIPermissionManager.DENY_ACTION;
const PROMPT_ACTION = Ci.nsIPermissionManager.PROMPT_ACTION;
// Permission access flags
const READONLY = "readonly";
const CREATEONLY = "createonly";
const READCREATE = "readcreate";
const READWRITE = "readwrite";
const PERM_TO_STRING = ["unknown", "allow", "deny", "prompt"];
function debug(aMsg) {
//dump("-*-*- PermissionsInstaller.jsm : " + aMsg + "\n");
}
this.PermissionsInstaller = {
/**
* 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.
* @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) {
try {
let newManifest =
new ManifestHelper(aApp.manifest, aApp.origin, aApp.manifestURL);
if (!newManifest.permissions && !aIsReinstall) {
return;
}
if (aIsReinstall) {
// Compare the original permissions against the new permissions
// Remove any deprecated Permissions
if (newManifest.permissions) {
// Expand permission names.
let newPermNames = [];
for (let permName in newManifest.permissions) {
let expandedPermNames =
expandPermissions(permName,
newManifest.permissions[permName].access);
newPermNames = newPermNames.concat(expandedPermNames);
}
newPermNames.push("indexedDB");
// Add the appcache related permissions.
if (newManifest.appcache_path) {
newPermNames = newPermNames.concat(["offline-app", "pin-app"]);
}
for (let idx in AllPossiblePermissions) {
let permName = AllPossiblePermissions[idx];
let index = newPermNames.indexOf(permName);
if (index == -1) {
// 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
PermissionSettingsModule.removePermission(permName,
aApp.manifestURL,
aApp.origin,
false);
}
}
}
}
// Check to see if the 'webapp' is app/privileged/certified.
let appStatus;
switch (AppsUtils.getAppManifestStatus(aApp.manifest)) {
case Ci.nsIPrincipal.APP_STATUS_CERTIFIED:
appStatus = "certified";
break;
case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED:
appStatus = "privileged";
break;
case Ci.nsIPrincipal.APP_STATUS_INSTALLED:
appStatus = "app";
break;
default:
// Cannot determine app type, abort install by throwing an error.
throw new Error("PermissionsInstaller.jsm: " +
"Cannot determine the app's status. Install cancelled.");
break;
}
this._setPermission("indexedDB", "allow", aApp);
// Add the appcache related permissions. We allow it for all kinds of
// apps.
if (newManifest.appcache_path) {
this._setPermission("offline-app", "allow", aApp);
this._setPermission("pin-app", "allow", aApp);
}
for (let permName in newManifest.permissions) {
if (!PermissionsTable[permName]) {
Cu.reportError("PermissionsInstaller.jsm: '" + permName + "'" +
" is not a valid Webapps permission name.");
dump("PermissionsInstaller.jsm: '" + permName + "'" +
" is not a valid Webapps permission name.");
continue;
}
let expandedPermNames =
expandPermissions(permName,
newManifest.permissions[permName].access);
for (let idx in expandedPermNames) {
let isPromptPermission =
PermissionsTable[permName][appStatus] === PROMPT_ACTION;
// We silently upgrade the permission to whatever the permission
// is for certified apps (ALLOW or PROMPT) only if the
// following holds true:
// * The app is preinstalled
// * The permission that would be granted is PROMPT
// * The app is privileged
let permission =
aApp.isPreinstalled && isPromptPermission &&
appStatus === "privileged"
? PermissionsTable[permName]["certified"]
: PermissionsTable[permName][appStatus];
let permValue = PERM_TO_STRING[permission];
if (isPromptPermission) {
// If the permission is prompt, keep the current value. This will
// work even on a system update, with the caveat that if a
// ALLOW/DENY permission is changed to PROMPT then the system should
// inform the user that he can now change a permission that he could
// not change before.
permValue =
PermissionSettingsModule.getPermission(expandedPermNames[idx],
aApp.manifestURL,
aApp.origin,
false,
aApp.isCachedPackage);
if (permValue === "unknown") {
permValue = PERM_TO_STRING[permission];
}
}
this._setPermission(expandedPermNames[idx], permValue, aApp);
}
}
}
catch (ex) {
dump("Caught webapps install permissions error for " + aApp.origin +
" : " + ex + "\n");
Cu.reportError(ex);
if (aOnError) {
aOnError();
}
}
},
/**
* Set a permission value.
* @param string aPermName
* The permission name.
* @param string aPermValue
* The permission value.
* @param object aApp
* The just-installed app configuration.
* The properties used are manifestURL, origin, appId, isCachedPackage.
* @returns void
**/
_setPermission: function setPermission(aPermName, aPermValue, aApp) {
PermissionSettingsModule.addPermission({
type: aPermName,
origin: aApp.origin,
manifestURL: aApp.manifestURL,
value: aPermValue,
browserFlag: false,
localId: aApp.localId,
isCachedPackage: aApp.isCachedPackage,
});
}
};