Bumping manifests a=b2g-bump
[gecko.git] / dom / permission / PermissionSettings.jsm
blob6c948ffc2fcab258a91e5015d1cae3a1acef845d
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                                    "appsService",
27                                    "@mozilla.org/AppsService;1",
28                                    "nsIAppsService");
30 this.PermissionSettingsModule = {
31   init: function init() {
32     debug("Init");
33     ppmm.addMessageListener("PermissionSettings:AddPermission", this);
34     Services.obs.addObserver(this, "profile-before-change", false);
35   },
38   _isChangeAllowed: function(aPrincipal, aPermName, aAction, aAppKind) {
39     // Bug 812289:
40     // Change is allowed from a child process when all of the following
41     // conditions stand true:
42     //   * the action isn't "unknown" (so the change isn't a delete) if the app
43     //     is installed
44     //   * the permission already exists on the database
45     //   * the permission is marked as explicit on the permissions table
46     // Note that we *have* to check the first two conditions here because
47     // permissionManager doesn't know if it's being called as a result of
48     // a parent process or child process request. We could check
49     // if the permission is actually explicit (and thus modifiable) or not
50     // on permissionManager also but we currently don't.
51     let perm =
52       Services.perms.testExactPermissionFromPrincipal(aPrincipal,aPermName);
53     let isExplicit = isExplicitInPermissionsTable(aPermName, aPrincipal.appStatus, aAppKind);
55     return (aAction === "unknown" &&
56             aPrincipal.appStatus === Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED) ||
57            (aAction !== "unknown" &&
58             (perm !== Ci.nsIPermissionManager.UNKNOWN_ACTION) &&
59             isExplicit);
60   },
62   addPermission: function addPermission(aData, aCallbacks) {
64     this._internalAddPermission(aData, true, aCallbacks);
66   },
69   _internalAddPermission: function _internalAddPermission(aData, aAllowAllChanges, aCallbacks) {
70     let uri = Services.io.newURI(aData.origin, null, null);
71     let app = appsService.getAppByManifestURL(aData.manifestURL);
72     let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(uri, app.localId, aData.browserFlag);
74     let action;
75     switch (aData.value)
76     {
77       case "unknown":
78         action = Ci.nsIPermissionManager.UNKNOWN_ACTION;
79         break;
80       case "allow":
81         action = Ci.nsIPermissionManager.ALLOW_ACTION;
82         break;
83       case "deny":
84         action = Ci.nsIPermissionManager.DENY_ACTION;
85         break;
86       case "prompt":
87         action = Ci.nsIPermissionManager.PROMPT_ACTION;
88         break;
89       default:
90         dump("Unsupported PermisionSettings Action: " + aData.value +"\n");
91         action = Ci.nsIPermissionManager.UNKNOWN_ACTION;
92     }
94     if (aAllowAllChanges ||
95         this._isChangeAllowed(principal, aData.type, aData.value, app.kind)) {
96       debug("add: " + aData.origin + " " + app.localId + " " + action);
97       Services.perms.addFromPrincipal(principal, aData.type, action);
98       return true;
99     } else {
100       debug("add Failure: " + aData.origin + " " + app.localId + " " + action);
101       return false; // This isn't currently used, see comment on setPermission
102     }
103   },
105   getPermission: function getPermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
106     debug("getPermission: " + aPermName + ", " + aManifestURL + ", " + aOrigin);
107     let uri = Services.io.newURI(aOrigin, null, null);
108     let appID = appsService.getAppLocalIdByManifestURL(aManifestURL);
109     let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(uri, appID, aBrowserFlag);
110     let result = Services.perms.testExactPermissionFromPrincipal(principal, aPermName);
112     switch (result)
113     {
114       case Ci.nsIPermissionManager.UNKNOWN_ACTION:
115         return "unknown";
116       case Ci.nsIPermissionManager.ALLOW_ACTION:
117         return "allow";
118       case Ci.nsIPermissionManager.DENY_ACTION:
119         return "deny";
120       case Ci.nsIPermissionManager.PROMPT_ACTION:
121         return "prompt";
122       default:
123         dump("Unsupported PermissionSettings Action!\n");
124         return "unknown";
125     }
126   },
128   removePermission: function removePermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) {
129     let data = {
130       type: aPermName,
131       origin: aOrigin,
132       manifestURL: aManifestURL,
133       value: "unknown",
134       browserFlag: aBrowserFlag
135     };
136     this._internalAddPermission(data, true);
137   },
139   observe: function observe(aSubject, aTopic, aData) {
140     ppmm.removeMessageListener("PermissionSettings:AddPermission", this);
141     Services.obs.removeObserver(this, "profile-before-change");
142     ppmm = null;
143   },
145   receiveMessage: function receiveMessage(aMessage) {
146     debug("PermissionSettings::receiveMessage " + aMessage.name);
147     let mm = aMessage.target;
148     let msg = aMessage.data;
150     let result;
151     switch (aMessage.name) {
152       case "PermissionSettings:AddPermission":
153         let success = false;
154         let errorMsg =
155               " from a content process with no 'permissions' privileges.";
156         if (mm.assertPermission("permissions")) {
157           success = this._internalAddPermission(msg, false);
158           if (!success) {
159             // Just kill the calling process
160             mm.assertPermission("permissions-modify-implicit");
161             errorMsg = " had an implicit permission change. Child process killed.";
162           }
163         }
165         if (!success) {
166           Cu.reportError("PermissionSettings message " + msg.type + errorMsg);
167           return null;
168         }
169         break;
170     }
171   }
174 PermissionSettingsModule.init();