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