Bug 835381 - Update libnestegg to 38c83d9d4c0c5c84373aa285bd30094a12d6b6f6. r=kinetik
[gecko.git] / dom / permission / PermissionSettings.jsm
blob2a953319de1ae62519d4fd4fb2d4ca8217e9d410
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/. */
5 "use strict";
7 function debug(s) {
8   //dump("-*- PermissionSettings Module: " + s + "\n");
11 const Cu = Components.utils;
12 const Cc = Components.classes;
13 const Ci = Components.interfaces;
15 this.EXPORTED_SYMBOLS = ["PermissionSettingsModule"];
17 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
18 Cu.import("resource://gre/modules/Services.jsm");
19 Cu.import("resource://gre/modules/PermissionsTable.jsm");
21 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
22                                    "@mozilla.org/parentprocessmessagemanager;1",
23                                    "nsIMessageListenerManager");
25 XPCOMUtils.defineLazyServiceGetter(this,
26                                    "permissionManager",
27                                    "@mozilla.org/permissionmanager;1",
28                                    "nsIPermissionManager");
30 XPCOMUtils.defineLazyServiceGetter(this,
31                                    "secMan",
32                                    "@mozilla.org/scriptsecuritymanager;1",
33                                    "nsIScriptSecurityManager");
35 XPCOMUtils.defineLazyServiceGetter(this,
36                                    "appsService",
37                                    "@mozilla.org/AppsService;1",
38                                    "nsIAppsService");
40 this.PermissionSettingsModule = {
41   init: function init() {
42     debug("Init");
43     ppmm.addMessageListener("PermissionSettings:AddPermission", this);
44     Services.obs.addObserver(this, "profile-before-change", false);
45   },
48   _isChangeAllowed: function(aPrincipal, aPermName, aAction) {
49     // Bug 812289:
50     // Change is allowed from a child process when all of the following
51     // conditions stand true:
52     //   * the action isn't "unknown" (so the change isn't a delete) if the app
53     //     is installed
54     //   * the permission already exists on the database
55     //   * the permission is marked as explicit on the permissions table
56     // Note that we *have* to check the first two conditions here because
57     // permissionManager doesn't know if it's being called as a result of
58     // a parent process or child process request. We could check
59     // if the permission is actually explicit (and thus modifiable) or not
60     // on permissionManager also but we currently don't.
61     let perm =
62       permissionManager.testExactPermissionFromPrincipal(aPrincipal,aPermName);
63     let isExplicit = isExplicitInPermissionsTable(aPermName, aPrincipal.appStatus);
65     return (aAction === "unknown" &&
66             aPrincipal.appStatus === Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED) ||
67            (aAction !== "unknown" &&
68             (perm !== Ci.nsIPermissionManager.UNKNOWN_ACTION) &&
69             isExplicit);
70   },
72   addPermission: function addPermission(aData, aCallbacks) {
74     this._internalAddPermission(aData, true, aCallbacks);
76   },
79   _internalAddPermission: function _internalAddPermission(aData, aAllowAllChanges, aCallbacks) {
80     let uri = Services.io.newURI(aData.origin, null, null);
81     let appID = appsService.getAppLocalIdByManifestURL(aData.manifestURL);
82     let principal = secMan.getAppCodebasePrincipal(uri, appID, aData.browserFlag);
84     let action;
85     switch (aData.value)
86     {
87       case "unknown":
88         action = Ci.nsIPermissionManager.UNKNOWN_ACTION;
89         break;
90       case "allow":
91         action = Ci.nsIPermissionManager.ALLOW_ACTION;
92         break;
93       case "deny":
94         action = Ci.nsIPermissionManager.DENY_ACTION;
95         break;
96       case "prompt":
97         action = Ci.nsIPermissionManager.PROMPT_ACTION;
98         break;
99       default:
100         dump("Unsupported PermisionSettings Action: " + aData.value +"\n");
101         action = Ci.nsIPermissionManager.UNKNOWN_ACTION;
102     }
104     if (aAllowAllChanges ||
105         this._isChangeAllowed(principal, aData.type, aData.value)) {
106       debug("add: " + aData.origin + " " + appID + " " + action);
107       permissionManager.addFromPrincipal(principal, aData.type, action);
108       return true;
109     } else {
110       debug("add Failure: " + aData.origin + " " + appID + " " + action);
111       return false; // This isn't currently used, see comment on setPermission
112     }
113   },
115   getPermission: function getPermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
116     debug("getPermission: " + aPermName + ", " + aManifestURL + ", " + aOrigin);
117     let uri = Services.io.newURI(aOrigin, null, null);
118     let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
119     let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
120     let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermName);
122     switch (result)
123     {
124       case Ci.nsIPermissionManager.UNKNOWN_ACTION:
125         return "unknown";
126       case Ci.nsIPermissionManager.ALLOW_ACTION:
127         return "allow";
128       case Ci.nsIPermissionManager.DENY_ACTION:
129         return "deny";
130       case Ci.nsIPermissionManager.PROMPT_ACTION:
131         return "prompt";
132       default:
133         dump("Unsupported PermissionSettings Action!\n");
134         return "unknown";
135     }
136   },
138   removePermission: function removePermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
139     let data = {
140       type: aPermName,
141       origin: aOrigin,
142       manifestURL: aManifestURL,
143       value: "unknown",
144       browserFlag: aBrowserFlag
145     };
146     this._internalAddPermission(data, true);
147   },
149   observe: function observe(aSubject, aTopic, aData) {
150     ppmm.removeMessageListener("PermissionSettings:AddPermission", this);
151     Services.obs.removeObserver(this, "profile-before-change");
152     ppmm = null;
153   },
155   receiveMessage: function receiveMessage(aMessage) {
156     debug("PermissionSettings::receiveMessage " + aMessage.name);
157     let mm = aMessage.target;
158     let msg = aMessage.data;
160     let result;
161     switch (aMessage.name) {
162       case "PermissionSettings:AddPermission":
163         let success = false;
164         let errorMsg =
165               " from a content process with no 'permissions' privileges.";
166         if (mm.assertPermission("permissions")) {
167           success = this._internalAddPermission(msg, false);
168           if (!success) {
169             // Just kill the calling process
170             mm.assertPermission("permissions-modify-implicit");
171             errorMsg = " had an implicit permission change. Child process killed.";
172           }
173         }
175         if (!success) {
176           Cu.reportError("PermissionSettings message " + msg.type + errorMsg);
177           return null;
178         }
179         break;
180     }
181   }
184 PermissionSettingsModule.init();