1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/permission/PermissionSettings.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,184 @@ 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 +function debug(s) { 1.11 + //dump("-*- PermissionSettings Module: " + s + "\n"); 1.12 +} 1.13 + 1.14 +const Cu = Components.utils; 1.15 +const Cc = Components.classes; 1.16 +const Ci = Components.interfaces; 1.17 + 1.18 +this.EXPORTED_SYMBOLS = ["PermissionSettingsModule"]; 1.19 + 1.20 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.21 +Cu.import("resource://gre/modules/Services.jsm"); 1.22 +Cu.import("resource://gre/modules/PermissionsTable.jsm"); 1.23 + 1.24 +XPCOMUtils.defineLazyServiceGetter(this, "ppmm", 1.25 + "@mozilla.org/parentprocessmessagemanager;1", 1.26 + "nsIMessageListenerManager"); 1.27 + 1.28 +XPCOMUtils.defineLazyServiceGetter(this, 1.29 + "permissionManager", 1.30 + "@mozilla.org/permissionmanager;1", 1.31 + "nsIPermissionManager"); 1.32 + 1.33 +XPCOMUtils.defineLazyServiceGetter(this, 1.34 + "secMan", 1.35 + "@mozilla.org/scriptsecuritymanager;1", 1.36 + "nsIScriptSecurityManager"); 1.37 + 1.38 +XPCOMUtils.defineLazyServiceGetter(this, 1.39 + "appsService", 1.40 + "@mozilla.org/AppsService;1", 1.41 + "nsIAppsService"); 1.42 + 1.43 +this.PermissionSettingsModule = { 1.44 + init: function init() { 1.45 + debug("Init"); 1.46 + ppmm.addMessageListener("PermissionSettings:AddPermission", this); 1.47 + Services.obs.addObserver(this, "profile-before-change", false); 1.48 + }, 1.49 + 1.50 + 1.51 + _isChangeAllowed: function(aPrincipal, aPermName, aAction) { 1.52 + // Bug 812289: 1.53 + // Change is allowed from a child process when all of the following 1.54 + // conditions stand true: 1.55 + // * the action isn't "unknown" (so the change isn't a delete) if the app 1.56 + // is installed 1.57 + // * the permission already exists on the database 1.58 + // * the permission is marked as explicit on the permissions table 1.59 + // Note that we *have* to check the first two conditions here because 1.60 + // permissionManager doesn't know if it's being called as a result of 1.61 + // a parent process or child process request. We could check 1.62 + // if the permission is actually explicit (and thus modifiable) or not 1.63 + // on permissionManager also but we currently don't. 1.64 + let perm = 1.65 + permissionManager.testExactPermissionFromPrincipal(aPrincipal,aPermName); 1.66 + let isExplicit = isExplicitInPermissionsTable(aPermName, aPrincipal.appStatus); 1.67 + 1.68 + return (aAction === "unknown" && 1.69 + aPrincipal.appStatus === Ci.nsIPrincipal.APP_STATUS_NOT_INSTALLED) || 1.70 + (aAction !== "unknown" && 1.71 + (perm !== Ci.nsIPermissionManager.UNKNOWN_ACTION) && 1.72 + isExplicit); 1.73 + }, 1.74 + 1.75 + addPermission: function addPermission(aData, aCallbacks) { 1.76 + 1.77 + this._internalAddPermission(aData, true, aCallbacks); 1.78 + 1.79 + }, 1.80 + 1.81 + 1.82 + _internalAddPermission: function _internalAddPermission(aData, aAllowAllChanges, aCallbacks) { 1.83 + let uri = Services.io.newURI(aData.origin, null, null); 1.84 + let appID = appsService.getAppLocalIdByManifestURL(aData.manifestURL); 1.85 + let principal = secMan.getAppCodebasePrincipal(uri, appID, aData.browserFlag); 1.86 + 1.87 + let action; 1.88 + switch (aData.value) 1.89 + { 1.90 + case "unknown": 1.91 + action = Ci.nsIPermissionManager.UNKNOWN_ACTION; 1.92 + break; 1.93 + case "allow": 1.94 + action = Ci.nsIPermissionManager.ALLOW_ACTION; 1.95 + break; 1.96 + case "deny": 1.97 + action = Ci.nsIPermissionManager.DENY_ACTION; 1.98 + break; 1.99 + case "prompt": 1.100 + action = Ci.nsIPermissionManager.PROMPT_ACTION; 1.101 + break; 1.102 + default: 1.103 + dump("Unsupported PermisionSettings Action: " + aData.value +"\n"); 1.104 + action = Ci.nsIPermissionManager.UNKNOWN_ACTION; 1.105 + } 1.106 + 1.107 + if (aAllowAllChanges || 1.108 + this._isChangeAllowed(principal, aData.type, aData.value)) { 1.109 + debug("add: " + aData.origin + " " + appID + " " + action); 1.110 + permissionManager.addFromPrincipal(principal, aData.type, action); 1.111 + return true; 1.112 + } else { 1.113 + debug("add Failure: " + aData.origin + " " + appID + " " + action); 1.114 + return false; // This isn't currently used, see comment on setPermission 1.115 + } 1.116 + }, 1.117 + 1.118 + getPermission: function getPermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) { 1.119 + debug("getPermission: " + aPermName + ", " + aManifestURL + ", " + aOrigin); 1.120 + let uri = Services.io.newURI(aOrigin, null, null); 1.121 + let appID = appsService.getAppLocalIdByManifestURL(aManifestURL); 1.122 + let principal = secMan.getAppCodebasePrincipal(uri, appID, aBrowserFlag); 1.123 + let result = permissionManager.testExactPermissionFromPrincipal(principal, aPermName); 1.124 + 1.125 + switch (result) 1.126 + { 1.127 + case Ci.nsIPermissionManager.UNKNOWN_ACTION: 1.128 + return "unknown"; 1.129 + case Ci.nsIPermissionManager.ALLOW_ACTION: 1.130 + return "allow"; 1.131 + case Ci.nsIPermissionManager.DENY_ACTION: 1.132 + return "deny"; 1.133 + case Ci.nsIPermissionManager.PROMPT_ACTION: 1.134 + return "prompt"; 1.135 + default: 1.136 + dump("Unsupported PermissionSettings Action!\n"); 1.137 + return "unknown"; 1.138 + } 1.139 + }, 1.140 + 1.141 + removePermission: function removePermission(aPermName, aManifestURL, aOrigin, aBrowserFlag) { 1.142 + let data = { 1.143 + type: aPermName, 1.144 + origin: aOrigin, 1.145 + manifestURL: aManifestURL, 1.146 + value: "unknown", 1.147 + browserFlag: aBrowserFlag 1.148 + }; 1.149 + this._internalAddPermission(data, true); 1.150 + }, 1.151 + 1.152 + observe: function observe(aSubject, aTopic, aData) { 1.153 + ppmm.removeMessageListener("PermissionSettings:AddPermission", this); 1.154 + Services.obs.removeObserver(this, "profile-before-change"); 1.155 + ppmm = null; 1.156 + }, 1.157 + 1.158 + receiveMessage: function receiveMessage(aMessage) { 1.159 + debug("PermissionSettings::receiveMessage " + aMessage.name); 1.160 + let mm = aMessage.target; 1.161 + let msg = aMessage.data; 1.162 + 1.163 + let result; 1.164 + switch (aMessage.name) { 1.165 + case "PermissionSettings:AddPermission": 1.166 + let success = false; 1.167 + let errorMsg = 1.168 + " from a content process with no 'permissions' privileges."; 1.169 + if (mm.assertPermission("permissions")) { 1.170 + success = this._internalAddPermission(msg, false); 1.171 + if (!success) { 1.172 + // Just kill the calling process 1.173 + mm.assertPermission("permissions-modify-implicit"); 1.174 + errorMsg = " had an implicit permission change. Child process killed."; 1.175 + } 1.176 + } 1.177 + 1.178 + if (!success) { 1.179 + Cu.reportError("PermissionSettings message " + msg.type + errorMsg); 1.180 + return null; 1.181 + } 1.182 + break; 1.183 + } 1.184 + } 1.185 +} 1.186 + 1.187 +PermissionSettingsModule.init();