Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | "use strict"; |
michael@0 | 6 | |
michael@0 | 7 | const Ci = Components.interfaces; |
michael@0 | 8 | const Cu = Components.utils; |
michael@0 | 9 | |
michael@0 | 10 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 11 | Cu.import("resource://gre/modules/AppsUtils.jsm"); |
michael@0 | 12 | Cu.import("resource://gre/modules/PermissionSettings.jsm"); |
michael@0 | 13 | Cu.import("resource://gre/modules/PermissionsTable.jsm"); |
michael@0 | 14 | |
michael@0 | 15 | this.EXPORTED_SYMBOLS = ["PermissionsInstaller"]; |
michael@0 | 16 | const UNKNOWN_ACTION = Ci.nsIPermissionManager.UNKNOWN_ACTION; |
michael@0 | 17 | const ALLOW_ACTION = Ci.nsIPermissionManager.ALLOW_ACTION; |
michael@0 | 18 | const DENY_ACTION = Ci.nsIPermissionManager.DENY_ACTION; |
michael@0 | 19 | const PROMPT_ACTION = Ci.nsIPermissionManager.PROMPT_ACTION; |
michael@0 | 20 | |
michael@0 | 21 | // Permission access flags |
michael@0 | 22 | const READONLY = "readonly"; |
michael@0 | 23 | const CREATEONLY = "createonly"; |
michael@0 | 24 | const READCREATE = "readcreate"; |
michael@0 | 25 | const READWRITE = "readwrite"; |
michael@0 | 26 | |
michael@0 | 27 | const PERM_TO_STRING = ["unknown", "allow", "deny", "prompt"]; |
michael@0 | 28 | |
michael@0 | 29 | function debug(aMsg) { |
michael@0 | 30 | //dump("-*-*- PermissionsInstaller.jsm : " + aMsg + "\n"); |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | // An array carring all the possible (expanded) permission names. |
michael@0 | 34 | let AllPossiblePermissions = []; |
michael@0 | 35 | for (let permName in PermissionsTable) { |
michael@0 | 36 | let expandedPermNames = []; |
michael@0 | 37 | if (PermissionsTable[permName].access) { |
michael@0 | 38 | expandedPermNames = expandPermissions(permName, READWRITE); |
michael@0 | 39 | } else { |
michael@0 | 40 | expandedPermNames = expandPermissions(permName); |
michael@0 | 41 | } |
michael@0 | 42 | AllPossiblePermissions = AllPossiblePermissions.concat(expandedPermNames); |
michael@0 | 43 | AllPossiblePermissions = |
michael@0 | 44 | AllPossiblePermissions.concat(["offline-app", "pin-app"]); |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | this.PermissionsInstaller = { |
michael@0 | 48 | /** |
michael@0 | 49 | * Install permissisions or remove deprecated permissions upon re-install. |
michael@0 | 50 | * @param object aApp |
michael@0 | 51 | * The just-installed app configuration. |
michael@0 | 52 | * The properties used are manifestURL, origin and manifest. |
michael@0 | 53 | * @param boolean aIsReinstall |
michael@0 | 54 | * Indicates the app was just re-installed |
michael@0 | 55 | * @param function aOnError |
michael@0 | 56 | * A function called if an error occurs |
michael@0 | 57 | * @returns void |
michael@0 | 58 | **/ |
michael@0 | 59 | installPermissions: function installPermissions(aApp, aIsReinstall, aOnError) { |
michael@0 | 60 | try { |
michael@0 | 61 | let newManifest = new ManifestHelper(aApp.manifest, aApp.origin); |
michael@0 | 62 | if (!newManifest.permissions && !aIsReinstall) { |
michael@0 | 63 | return; |
michael@0 | 64 | } |
michael@0 | 65 | |
michael@0 | 66 | if (aIsReinstall) { |
michael@0 | 67 | // Compare the original permissions against the new permissions |
michael@0 | 68 | // Remove any deprecated Permissions |
michael@0 | 69 | |
michael@0 | 70 | if (newManifest.permissions) { |
michael@0 | 71 | // Expand permission names. |
michael@0 | 72 | let newPermNames = []; |
michael@0 | 73 | for (let permName in newManifest.permissions) { |
michael@0 | 74 | let expandedPermNames = |
michael@0 | 75 | expandPermissions(permName, |
michael@0 | 76 | newManifest.permissions[permName].access); |
michael@0 | 77 | newPermNames = newPermNames.concat(expandedPermNames); |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | // Add the appcache related permissions. |
michael@0 | 81 | if (newManifest.appcache_path) { |
michael@0 | 82 | newPermNames = newPermNames.concat(["offline-app", "pin-app"]); |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | for (let idx in AllPossiblePermissions) { |
michael@0 | 86 | let permName = AllPossiblePermissions[idx]; |
michael@0 | 87 | let index = newPermNames.indexOf(permName); |
michael@0 | 88 | if (index == -1) { |
michael@0 | 89 | // See if the permission was installed previously. |
michael@0 | 90 | let permValue = |
michael@0 | 91 | PermissionSettingsModule.getPermission(permName, |
michael@0 | 92 | aApp.manifestURL, |
michael@0 | 93 | aApp.origin, |
michael@0 | 94 | false); |
michael@0 | 95 | if (permValue == "unknown" || permValue == "deny") { |
michael@0 | 96 | // All 'deny' permissions should be preserved |
michael@0 | 97 | continue; |
michael@0 | 98 | } |
michael@0 | 99 | // Remove the deprecated permission |
michael@0 | 100 | PermissionSettingsModule.removePermission(permName, |
michael@0 | 101 | aApp.manifestURL, |
michael@0 | 102 | aApp.origin, |
michael@0 | 103 | false); |
michael@0 | 104 | } |
michael@0 | 105 | } |
michael@0 | 106 | } |
michael@0 | 107 | } |
michael@0 | 108 | |
michael@0 | 109 | // Check to see if the 'webapp' is app/privileged/certified. |
michael@0 | 110 | let appStatus; |
michael@0 | 111 | switch (AppsUtils.getAppManifestStatus(aApp.manifest)) { |
michael@0 | 112 | case Ci.nsIPrincipal.APP_STATUS_CERTIFIED: |
michael@0 | 113 | appStatus = "certified"; |
michael@0 | 114 | break; |
michael@0 | 115 | case Ci.nsIPrincipal.APP_STATUS_PRIVILEGED: |
michael@0 | 116 | appStatus = "privileged"; |
michael@0 | 117 | break; |
michael@0 | 118 | case Ci.nsIPrincipal.APP_STATUS_INSTALLED: |
michael@0 | 119 | appStatus = "app"; |
michael@0 | 120 | break; |
michael@0 | 121 | default: |
michael@0 | 122 | // Cannot determine app type, abort install by throwing an error. |
michael@0 | 123 | throw new Error("PermissionsInstaller.jsm: " + |
michael@0 | 124 | "Cannot determine the app's status. Install cancelled."); |
michael@0 | 125 | break; |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | // Add the appcache related permissions. We allow it for all kinds of |
michael@0 | 129 | // apps. |
michael@0 | 130 | if (newManifest.appcache_path) { |
michael@0 | 131 | this._setPermission("offline-app", "allow", aApp); |
michael@0 | 132 | this._setPermission("pin-app", "allow", aApp); |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | for (let permName in newManifest.permissions) { |
michael@0 | 136 | if (!PermissionsTable[permName]) { |
michael@0 | 137 | Cu.reportError("PermissionsInstaller.jsm: '" + permName + "'" + |
michael@0 | 138 | " is not a valid Webapps permission name."); |
michael@0 | 139 | dump("PermissionsInstaller.jsm: '" + permName + "'" + |
michael@0 | 140 | " is not a valid Webapps permission name."); |
michael@0 | 141 | continue; |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | let expandedPermNames = |
michael@0 | 145 | expandPermissions(permName, |
michael@0 | 146 | newManifest.permissions[permName].access); |
michael@0 | 147 | for (let idx in expandedPermNames) { |
michael@0 | 148 | this._setPermission(expandedPermNames[idx], |
michael@0 | 149 | PERM_TO_STRING[PermissionsTable[permName][appStatus]], |
michael@0 | 150 | aApp); |
michael@0 | 151 | } |
michael@0 | 152 | } |
michael@0 | 153 | } |
michael@0 | 154 | catch (ex) { |
michael@0 | 155 | dump("Caught webapps install permissions error for " + aApp.origin); |
michael@0 | 156 | Cu.reportError(ex); |
michael@0 | 157 | if (aOnError) { |
michael@0 | 158 | aOnError(); |
michael@0 | 159 | } |
michael@0 | 160 | } |
michael@0 | 161 | }, |
michael@0 | 162 | |
michael@0 | 163 | /** |
michael@0 | 164 | * Set a permission value. |
michael@0 | 165 | * @param string aPermName |
michael@0 | 166 | * The permission name. |
michael@0 | 167 | * @param string aPermValue |
michael@0 | 168 | * The permission value. |
michael@0 | 169 | * @param object aApp |
michael@0 | 170 | * The just-installed app configuration. |
michael@0 | 171 | * The properties used are manifestURL and origin. |
michael@0 | 172 | * @returns void |
michael@0 | 173 | **/ |
michael@0 | 174 | _setPermission: function setPermission(aPermName, aPermValue, aApp) { |
michael@0 | 175 | PermissionSettingsModule.addPermission({ |
michael@0 | 176 | type: aPermName, |
michael@0 | 177 | origin: aApp.origin, |
michael@0 | 178 | manifestURL: aApp.manifestURL, |
michael@0 | 179 | value: aPermValue, |
michael@0 | 180 | browserFlag: false |
michael@0 | 181 | }); |
michael@0 | 182 | } |
michael@0 | 183 | }; |