1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/modules/SitePermissions.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,235 @@ 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 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +this.EXPORTED_SYMBOLS = [ "SitePermissions" ]; 1.9 + 1.10 +Components.utils.import("resource://gre/modules/Services.jsm"); 1.11 + 1.12 +let gStringBundle = 1.13 + Services.strings.createBundle("chrome://browser/locale/sitePermissions.properties"); 1.14 + 1.15 +this.SitePermissions = { 1.16 + 1.17 + UNKNOWN: Services.perms.UNKNOWN_ACTION, 1.18 + ALLOW: Services.perms.ALLOW_ACTION, 1.19 + BLOCK: Services.perms.DENY_ACTION, 1.20 + SESSION: Components.interfaces.nsICookiePermission.ACCESS_SESSION, 1.21 + 1.22 + /* Checks whether a UI for managing permissions should be exposed for a given 1.23 + * URI. This excludes file URIs, for instance, as they don't have a host, 1.24 + * even though nsIPermissionManager can still handle them. 1.25 + */ 1.26 + isSupportedURI: function (aURI) { 1.27 + return aURI.schemeIs("http") || aURI.schemeIs("https"); 1.28 + }, 1.29 + 1.30 + /* Returns an array of all permission IDs. 1.31 + */ 1.32 + listPermissions: function () { 1.33 + let array = Object.keys(gPermissionObject); 1.34 + array.sort((a, b) => { 1.35 + return this.getPermissionLabel(a).localeCompare(this.getPermissionLabel(b)); 1.36 + }); 1.37 + return array; 1.38 + }, 1.39 + 1.40 + /* Returns an array of permission states to be exposed to the user for a 1.41 + * permission with the given ID. 1.42 + */ 1.43 + getAvailableStates: function (aPermissionID) { 1.44 + if (aPermissionID in gPermissionObject && 1.45 + gPermissionObject[aPermissionID].states) 1.46 + return gPermissionObject[aPermissionID].states; 1.47 + 1.48 + if (this.getDefault(aPermissionID) == this.UNKNOWN) 1.49 + return [ SitePermissions.UNKNOWN, SitePermissions.ALLOW, SitePermissions.BLOCK ]; 1.50 + 1.51 + return [ SitePermissions.ALLOW, SitePermissions.BLOCK ]; 1.52 + }, 1.53 + 1.54 + /* Returns the default state of a particular permission. 1.55 + */ 1.56 + getDefault: function (aPermissionID) { 1.57 + if (aPermissionID in gPermissionObject && 1.58 + gPermissionObject[aPermissionID].getDefault) 1.59 + return gPermissionObject[aPermissionID].getDefault(); 1.60 + 1.61 + return this.UNKNOWN; 1.62 + }, 1.63 + 1.64 + /* Returns the state of a particular permission for a given URI. 1.65 + */ 1.66 + get: function (aURI, aPermissionID) { 1.67 + if (!this.isSupportedURI(aURI)) 1.68 + return this.UNKNOWN; 1.69 + 1.70 + let state; 1.71 + if (aPermissionID in gPermissionObject && 1.72 + gPermissionObject[aPermissionID].exactHostMatch) 1.73 + state = Services.perms.testExactPermission(aURI, aPermissionID); 1.74 + else 1.75 + state = Services.perms.testPermission(aURI, aPermissionID); 1.76 + return state; 1.77 + }, 1.78 + 1.79 + /* Sets the state of a particular permission for a given URI. 1.80 + */ 1.81 + set: function (aURI, aPermissionID, aState) { 1.82 + if (!this.isSupportedURI(aURI)) 1.83 + return; 1.84 + 1.85 + if (aState == this.UNKNOWN) { 1.86 + this.remove(aURI, aPermissionID); 1.87 + return; 1.88 + } 1.89 + 1.90 + Services.perms.add(aURI, aPermissionID, aState); 1.91 + 1.92 + if (aPermissionID in gPermissionObject && 1.93 + gPermissionObject[aPermissionID].onChange) 1.94 + gPermissionObject[aPermissionID].onChange(aURI, aState); 1.95 + }, 1.96 + 1.97 + /* Removes the saved state of a particular permission for a given URI. 1.98 + */ 1.99 + remove: function (aURI, aPermissionID) { 1.100 + if (!this.isSupportedURI(aURI)) 1.101 + return; 1.102 + 1.103 + Services.perms.remove(aURI.host, aPermissionID); 1.104 + 1.105 + if (aPermissionID in gPermissionObject && 1.106 + gPermissionObject[aPermissionID].onChange) 1.107 + gPermissionObject[aPermissionID].onChange(aURI, this.UNKNOWN); 1.108 + }, 1.109 + 1.110 + /* Returns the localized label for the permission with the given ID, to be 1.111 + * used in a UI for managing permissions. 1.112 + */ 1.113 + getPermissionLabel: function (aPermissionID) { 1.114 + return gStringBundle.GetStringFromName("permission." + aPermissionID + ".label"); 1.115 + }, 1.116 + 1.117 + /* Returns the localized label for the given permission state, to be used in 1.118 + * a UI for managing permissions. 1.119 + */ 1.120 + getStateLabel: function (aPermissionID, aState) { 1.121 + if (aPermissionID in gPermissionObject && 1.122 + gPermissionObject[aPermissionID].getStateLabel) { 1.123 + let label = gPermissionObject[aPermissionID].getStateLabel(aState); 1.124 + if (label) 1.125 + return label; 1.126 + } 1.127 + 1.128 + switch (aState) { 1.129 + case this.UNKNOWN: 1.130 + return gStringBundle.GetStringFromName("alwaysAsk"); 1.131 + case this.ALLOW: 1.132 + return gStringBundle.GetStringFromName("allow"); 1.133 + case this.SESSION: 1.134 + return gStringBundle.GetStringFromName("allowForSession"); 1.135 + case this.BLOCK: 1.136 + return gStringBundle.GetStringFromName("block"); 1.137 + default: 1.138 + throw new Error("unknown permission state"); 1.139 + } 1.140 + } 1.141 +}; 1.142 + 1.143 +let gPermissionObject = { 1.144 + /* Holds permission ID => options pairs. 1.145 + * 1.146 + * Supported options: 1.147 + * 1.148 + * - exactHostMatch 1.149 + * Allows sub domains to have their own permissions. 1.150 + * Defaults to false. 1.151 + * 1.152 + * - getDefault 1.153 + * Called to get the permission's default state. 1.154 + * Defaults to UNKNOWN, indicating that the user will be asked each time 1.155 + * a page asks for that permissions. 1.156 + * 1.157 + * - getStateLabel 1.158 + * Called to get the localized label for the given permission state, to be 1.159 + * used in a UI for managing permissions. May return null for states that 1.160 + * should use their default label. 1.161 + * 1.162 + * - onChange 1.163 + * Called when a permission state changes. 1.164 + * 1.165 + * - states 1.166 + * Array of permission states to be exposed to the user. 1.167 + * Defaults to ALLOW, BLOCK and the default state (see getDefault). 1.168 + */ 1.169 + 1.170 + "image": { 1.171 + getDefault: function () { 1.172 + return Services.prefs.getIntPref("permissions.default.image") == 2 ? 1.173 + SitePermissions.BLOCK : SitePermissions.ALLOW; 1.174 + } 1.175 + }, 1.176 + 1.177 + "cookie": { 1.178 + states: [ SitePermissions.ALLOW, SitePermissions.SESSION, SitePermissions.BLOCK ], 1.179 + getDefault: function () { 1.180 + if (Services.prefs.getIntPref("network.cookie.cookieBehavior") == 2) 1.181 + return SitePermissions.BLOCK; 1.182 + 1.183 + if (Services.prefs.getIntPref("network.cookie.lifetimePolicy") == 2) 1.184 + return SitePermissions.SESSION; 1.185 + 1.186 + return SitePermissions.ALLOW; 1.187 + } 1.188 + }, 1.189 + 1.190 + "desktop-notification": {}, 1.191 + 1.192 + "camera": {}, 1.193 + "microphone": {}, 1.194 + 1.195 + "popup": { 1.196 + getDefault: function () { 1.197 + return Services.prefs.getBoolPref("dom.disable_open_during_load") ? 1.198 + SitePermissions.BLOCK : SitePermissions.ALLOW; 1.199 + } 1.200 + }, 1.201 + 1.202 + "install": { 1.203 + getDefault: function () { 1.204 + return Services.prefs.getBoolPref("xpinstall.whitelist.required") ? 1.205 + SitePermissions.BLOCK : SitePermissions.ALLOW; 1.206 + } 1.207 + }, 1.208 + 1.209 + "geo": { 1.210 + exactHostMatch: true 1.211 + }, 1.212 + 1.213 + "indexedDB": { 1.214 + states: [ SitePermissions.ALLOW, SitePermissions.UNKNOWN, SitePermissions.BLOCK ], 1.215 + getStateLabel: function (aState) { 1.216 + // indexedDB redefines nsIPermissionManager.UNKNOWN_ACTION (the default) 1.217 + // as "allow" and nsIPermissionManager.ALLOW_ACTION as "ask the user." 1.218 + switch (aState) { 1.219 + case SitePermissions.UNKNOWN: 1.220 + return gStringBundle.GetStringFromName("allow"); 1.221 + case SitePermissions.ALLOW: 1.222 + return gStringBundle.GetStringFromName("alwaysAsk"); 1.223 + default: 1.224 + return null; 1.225 + } 1.226 + }, 1.227 + onChange: function (aURI, aState) { 1.228 + if (aState == SitePermissions.ALLOW || aState == SitePermissions.BLOCK) 1.229 + Services.perms.remove(aURI.host, "indexedDB-unlimited"); 1.230 + } 1.231 + }, 1.232 + 1.233 + "fullscreen": {}, 1.234 + 1.235 + "pointerLock": { 1.236 + exactHostMatch: true 1.237 + } 1.238 +};