summaryrefslogtreecommitdiffstats
path: root/dom/apps/PermissionsInstaller.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'dom/apps/PermissionsInstaller.jsm')
-rw-r--r--dom/apps/PermissionsInstaller.jsm210
1 files changed, 210 insertions, 0 deletions
diff --git a/dom/apps/PermissionsInstaller.jsm b/dom/apps/PermissionsInstaller.jsm
new file mode 100644
index 000000000..e3ed3aca8
--- /dev/null
+++ b/dom/apps/PermissionsInstaller.jsm
@@ -0,0 +1,210 @@
+/* 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,
+ });
+ }
+};