1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/apps/src/PermissionsInstaller.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,183 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +"use strict"; 1.9 + 1.10 +const Ci = Components.interfaces; 1.11 +const Cu = Components.utils; 1.12 + 1.13 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.14 +Cu.import("resource://gre/modules/AppsUtils.jsm"); 1.15 +Cu.import("resource://gre/modules/PermissionSettings.jsm"); 1.16 +Cu.import("resource://gre/modules/PermissionsTable.jsm"); 1.17 + 1.18 +this.EXPORTED_SYMBOLS = ["PermissionsInstaller"]; 1.19 +const UNKNOWN_ACTION = Ci.nsIPermissionManager.UNKNOWN_ACTION; 1.20 +const ALLOW_ACTION = Ci.nsIPermissionManager.ALLOW_ACTION; 1.21 +const DENY_ACTION = Ci.nsIPermissionManager.DENY_ACTION; 1.22 +const PROMPT_ACTION = Ci.nsIPermissionManager.PROMPT_ACTION; 1.23 + 1.24 +// Permission access flags 1.25 +const READONLY = "readonly"; 1.26 +const CREATEONLY = "createonly"; 1.27 +const READCREATE = "readcreate"; 1.28 +const READWRITE = "readwrite"; 1.29 + 1.30 +const PERM_TO_STRING = ["unknown", "allow", "deny", "prompt"]; 1.31 + 1.32 +function debug(aMsg) { 1.33 + //dump("-*-*- PermissionsInstaller.jsm : " + aMsg + "\n"); 1.34 +} 1.35 + 1.36 +// An array carring all the possible (expanded) permission names. 1.37 +let AllPossiblePermissions = []; 1.38 +for (let permName in PermissionsTable) { 1.39 + let expandedPermNames = []; 1.40 + if (PermissionsTable[permName].access) { 1.41 + expandedPermNames = expandPermissions(permName, READWRITE); 1.42 + } else { 1.43 + expandedPermNames = expandPermissions(permName); 1.44 + } 1.45 + AllPossiblePermissions = AllPossiblePermissions.concat(expandedPermNames); 1.46 + AllPossiblePermissions = 1.47 + AllPossiblePermissions.concat(["offline-app", "pin-app"]); 1.48 +} 1.49 + 1.50 +this.PermissionsInstaller = { 1.51 + /** 1.52 + * Install permissisions or remove deprecated permissions upon re-install. 1.53 + * @param object aApp 1.54 + * The just-installed app configuration. 1.55 + * The properties used are manifestURL, origin and manifest. 1.56 + * @param boolean aIsReinstall 1.57 + * Indicates the app was just re-installed 1.58 + * @param function aOnError 1.59 + * A function called if an error occurs 1.60 + * @returns void 1.61 + **/ 1.62 + installPermissions: function installPermissions(aApp, aIsReinstall, aOnError) { 1.63 + try { 1.64 + let newManifest = new ManifestHelper(aApp.manifest, aApp.origin); 1.65 + if (!newManifest.permissions && !aIsReinstall) { 1.66 + return; 1.67 + } 1.68 + 1.69 + if (aIsReinstall) { 1.70 + // Compare the original permissions against the new permissions 1.71 + // Remove any deprecated Permissions 1.72 + 1.73 + if (newManifest.permissions) { 1.74 + // Expand permission names. 1.75 + let newPermNames = []; 1.76 + for (let permName in newManifest.permissions) { 1.77 + let expandedPermNames = 1.78 + expandPermissions(permName, 1.79 + newManifest.permissions[permName].access); 1.80 + newPermNames = newPermNames.concat(expandedPermNames); 1.81 + } 1.82 + 1.83 + // Add the appcache related permissions. 1.84 + if (newManifest.appcache_path) { 1.85 + newPermNames = newPermNames.concat(["offline-app", "pin-app"]); 1.86 + } 1.87 + 1.88 + for (let idx in AllPossiblePermissions) { 1.89 + let permName = AllPossiblePermissions[idx]; 1.90 + let index = newPermNames.indexOf(permName); 1.91 + if (index == -1) { 1.92 + // See if the permission was installed previously. 1.93 + let permValue = 1.94 + PermissionSettingsModule.getPermission(permName, 1.95 + aApp.manifestURL, 1.96 + aApp.origin, 1.97 + false); 1.98 + if (permValue == "unknown" || permValue == "deny") { 1.99 + // All 'deny' permissions should be preserved 1.100 + continue; 1.101 + } 1.102 + // Remove the deprecated permission 1.103 + PermissionSettingsModule.removePermission(permName, 1.104 + aApp.manifestURL, 1.105 + aApp.origin, 1.106 + false); 1.107 + } 1.108 + } 1.109 + } 1.110 + } 1.111 + 1.112 + // Check to see if the 'webapp' is app/privileged/certified. 1.113 + let appStatus; 1.114 + switch (AppsUtils.getAppManifestStatus(aApp.manifest)) { 1.115 + case Ci.nsIPrincipal.APP_STATUS_CERTIFIED: 1.116 + appStatus = "certified"; 1.117 + break; 1.118 + case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED: 1.119 + appStatus = "privileged"; 1.120 + break; 1.121 + case Ci.nsIPrincipal.APP_STATUS_INSTALLED: 1.122 + appStatus = "app"; 1.123 + break; 1.124 + default: 1.125 + // Cannot determine app type, abort install by throwing an error. 1.126 + throw new Error("PermissionsInstaller.jsm: " + 1.127 + "Cannot determine the app's status. Install cancelled."); 1.128 + break; 1.129 + } 1.130 + 1.131 + // Add the appcache related permissions. We allow it for all kinds of 1.132 + // apps. 1.133 + if (newManifest.appcache_path) { 1.134 + this._setPermission("offline-app", "allow", aApp); 1.135 + this._setPermission("pin-app", "allow", aApp); 1.136 + } 1.137 + 1.138 + for (let permName in newManifest.permissions) { 1.139 + if (!PermissionsTable[permName]) { 1.140 + Cu.reportError("PermissionsInstaller.jsm: '" + permName + "'" + 1.141 + " is not a valid Webapps permission name."); 1.142 + dump("PermissionsInstaller.jsm: '" + permName + "'" + 1.143 + " is not a valid Webapps permission name."); 1.144 + continue; 1.145 + } 1.146 + 1.147 + let expandedPermNames = 1.148 + expandPermissions(permName, 1.149 + newManifest.permissions[permName].access); 1.150 + for (let idx in expandedPermNames) { 1.151 + this._setPermission(expandedPermNames[idx], 1.152 + PERM_TO_STRING[PermissionsTable[permName][appStatus]], 1.153 + aApp); 1.154 + } 1.155 + } 1.156 + } 1.157 + catch (ex) { 1.158 + dump("Caught webapps install permissions error for " + aApp.origin); 1.159 + Cu.reportError(ex); 1.160 + if (aOnError) { 1.161 + aOnError(); 1.162 + } 1.163 + } 1.164 + }, 1.165 + 1.166 + /** 1.167 + * Set a permission value. 1.168 + * @param string aPermName 1.169 + * The permission name. 1.170 + * @param string aPermValue 1.171 + * The permission value. 1.172 + * @param object aApp 1.173 + * The just-installed app configuration. 1.174 + * The properties used are manifestURL and origin. 1.175 + * @returns void 1.176 + **/ 1.177 + _setPermission: function setPermission(aPermName, aPermValue, aApp) { 1.178 + PermissionSettingsModule.addPermission({ 1.179 + type: aPermName, 1.180 + origin: aApp.origin, 1.181 + manifestURL: aApp.manifestURL, 1.182 + value: aPermValue, 1.183 + browserFlag: false 1.184 + }); 1.185 + } 1.186 +};