michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: this.EXPORTED_SYMBOLS = [ "SitePermissions" ]; michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: let gStringBundle = michael@0: Services.strings.createBundle("chrome://browser/locale/sitePermissions.properties"); michael@0: michael@0: this.SitePermissions = { michael@0: michael@0: UNKNOWN: Services.perms.UNKNOWN_ACTION, michael@0: ALLOW: Services.perms.ALLOW_ACTION, michael@0: BLOCK: Services.perms.DENY_ACTION, michael@0: SESSION: Components.interfaces.nsICookiePermission.ACCESS_SESSION, michael@0: michael@0: /* Checks whether a UI for managing permissions should be exposed for a given michael@0: * URI. This excludes file URIs, for instance, as they don't have a host, michael@0: * even though nsIPermissionManager can still handle them. michael@0: */ michael@0: isSupportedURI: function (aURI) { michael@0: return aURI.schemeIs("http") || aURI.schemeIs("https"); michael@0: }, michael@0: michael@0: /* Returns an array of all permission IDs. michael@0: */ michael@0: listPermissions: function () { michael@0: let array = Object.keys(gPermissionObject); michael@0: array.sort((a, b) => { michael@0: return this.getPermissionLabel(a).localeCompare(this.getPermissionLabel(b)); michael@0: }); michael@0: return array; michael@0: }, michael@0: michael@0: /* Returns an array of permission states to be exposed to the user for a michael@0: * permission with the given ID. michael@0: */ michael@0: getAvailableStates: function (aPermissionID) { michael@0: if (aPermissionID in gPermissionObject && michael@0: gPermissionObject[aPermissionID].states) michael@0: return gPermissionObject[aPermissionID].states; michael@0: michael@0: if (this.getDefault(aPermissionID) == this.UNKNOWN) michael@0: return [ SitePermissions.UNKNOWN, SitePermissions.ALLOW, SitePermissions.BLOCK ]; michael@0: michael@0: return [ SitePermissions.ALLOW, SitePermissions.BLOCK ]; michael@0: }, michael@0: michael@0: /* Returns the default state of a particular permission. michael@0: */ michael@0: getDefault: function (aPermissionID) { michael@0: if (aPermissionID in gPermissionObject && michael@0: gPermissionObject[aPermissionID].getDefault) michael@0: return gPermissionObject[aPermissionID].getDefault(); michael@0: michael@0: return this.UNKNOWN; michael@0: }, michael@0: michael@0: /* Returns the state of a particular permission for a given URI. michael@0: */ michael@0: get: function (aURI, aPermissionID) { michael@0: if (!this.isSupportedURI(aURI)) michael@0: return this.UNKNOWN; michael@0: michael@0: let state; michael@0: if (aPermissionID in gPermissionObject && michael@0: gPermissionObject[aPermissionID].exactHostMatch) michael@0: state = Services.perms.testExactPermission(aURI, aPermissionID); michael@0: else michael@0: state = Services.perms.testPermission(aURI, aPermissionID); michael@0: return state; michael@0: }, michael@0: michael@0: /* Sets the state of a particular permission for a given URI. michael@0: */ michael@0: set: function (aURI, aPermissionID, aState) { michael@0: if (!this.isSupportedURI(aURI)) michael@0: return; michael@0: michael@0: if (aState == this.UNKNOWN) { michael@0: this.remove(aURI, aPermissionID); michael@0: return; michael@0: } michael@0: michael@0: Services.perms.add(aURI, aPermissionID, aState); michael@0: michael@0: if (aPermissionID in gPermissionObject && michael@0: gPermissionObject[aPermissionID].onChange) michael@0: gPermissionObject[aPermissionID].onChange(aURI, aState); michael@0: }, michael@0: michael@0: /* Removes the saved state of a particular permission for a given URI. michael@0: */ michael@0: remove: function (aURI, aPermissionID) { michael@0: if (!this.isSupportedURI(aURI)) michael@0: return; michael@0: michael@0: Services.perms.remove(aURI.host, aPermissionID); michael@0: michael@0: if (aPermissionID in gPermissionObject && michael@0: gPermissionObject[aPermissionID].onChange) michael@0: gPermissionObject[aPermissionID].onChange(aURI, this.UNKNOWN); michael@0: }, michael@0: michael@0: /* Returns the localized label for the permission with the given ID, to be michael@0: * used in a UI for managing permissions. michael@0: */ michael@0: getPermissionLabel: function (aPermissionID) { michael@0: return gStringBundle.GetStringFromName("permission." + aPermissionID + ".label"); michael@0: }, michael@0: michael@0: /* Returns the localized label for the given permission state, to be used in michael@0: * a UI for managing permissions. michael@0: */ michael@0: getStateLabel: function (aPermissionID, aState) { michael@0: if (aPermissionID in gPermissionObject && michael@0: gPermissionObject[aPermissionID].getStateLabel) { michael@0: let label = gPermissionObject[aPermissionID].getStateLabel(aState); michael@0: if (label) michael@0: return label; michael@0: } michael@0: michael@0: switch (aState) { michael@0: case this.UNKNOWN: michael@0: return gStringBundle.GetStringFromName("alwaysAsk"); michael@0: case this.ALLOW: michael@0: return gStringBundle.GetStringFromName("allow"); michael@0: case this.SESSION: michael@0: return gStringBundle.GetStringFromName("allowForSession"); michael@0: case this.BLOCK: michael@0: return gStringBundle.GetStringFromName("block"); michael@0: default: michael@0: throw new Error("unknown permission state"); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: let gPermissionObject = { michael@0: /* Holds permission ID => options pairs. michael@0: * michael@0: * Supported options: michael@0: * michael@0: * - exactHostMatch michael@0: * Allows sub domains to have their own permissions. michael@0: * Defaults to false. michael@0: * michael@0: * - getDefault michael@0: * Called to get the permission's default state. michael@0: * Defaults to UNKNOWN, indicating that the user will be asked each time michael@0: * a page asks for that permissions. michael@0: * michael@0: * - getStateLabel michael@0: * Called to get the localized label for the given permission state, to be michael@0: * used in a UI for managing permissions. May return null for states that michael@0: * should use their default label. michael@0: * michael@0: * - onChange michael@0: * Called when a permission state changes. michael@0: * michael@0: * - states michael@0: * Array of permission states to be exposed to the user. michael@0: * Defaults to ALLOW, BLOCK and the default state (see getDefault). michael@0: */ michael@0: michael@0: "image": { michael@0: getDefault: function () { michael@0: return Services.prefs.getIntPref("permissions.default.image") == 2 ? michael@0: SitePermissions.BLOCK : SitePermissions.ALLOW; michael@0: } michael@0: }, michael@0: michael@0: "cookie": { michael@0: states: [ SitePermissions.ALLOW, SitePermissions.SESSION, SitePermissions.BLOCK ], michael@0: getDefault: function () { michael@0: if (Services.prefs.getIntPref("network.cookie.cookieBehavior") == 2) michael@0: return SitePermissions.BLOCK; michael@0: michael@0: if (Services.prefs.getIntPref("network.cookie.lifetimePolicy") == 2) michael@0: return SitePermissions.SESSION; michael@0: michael@0: return SitePermissions.ALLOW; michael@0: } michael@0: }, michael@0: michael@0: "desktop-notification": {}, michael@0: michael@0: "camera": {}, michael@0: "microphone": {}, michael@0: michael@0: "popup": { michael@0: getDefault: function () { michael@0: return Services.prefs.getBoolPref("dom.disable_open_during_load") ? michael@0: SitePermissions.BLOCK : SitePermissions.ALLOW; michael@0: } michael@0: }, michael@0: michael@0: "install": { michael@0: getDefault: function () { michael@0: return Services.prefs.getBoolPref("xpinstall.whitelist.required") ? michael@0: SitePermissions.BLOCK : SitePermissions.ALLOW; michael@0: } michael@0: }, michael@0: michael@0: "geo": { michael@0: exactHostMatch: true michael@0: }, michael@0: michael@0: "indexedDB": { michael@0: states: [ SitePermissions.ALLOW, SitePermissions.UNKNOWN, SitePermissions.BLOCK ], michael@0: getStateLabel: function (aState) { michael@0: // indexedDB redefines nsIPermissionManager.UNKNOWN_ACTION (the default) michael@0: // as "allow" and nsIPermissionManager.ALLOW_ACTION as "ask the user." michael@0: switch (aState) { michael@0: case SitePermissions.UNKNOWN: michael@0: return gStringBundle.GetStringFromName("allow"); michael@0: case SitePermissions.ALLOW: michael@0: return gStringBundle.GetStringFromName("alwaysAsk"); michael@0: default: michael@0: return null; michael@0: } michael@0: }, michael@0: onChange: function (aURI, aState) { michael@0: if (aState == SitePermissions.ALLOW || aState == SitePermissions.BLOCK) michael@0: Services.perms.remove(aURI.host, "indexedDB-unlimited"); michael@0: } michael@0: }, michael@0: michael@0: "fullscreen": {}, michael@0: michael@0: "pointerLock": { michael@0: exactHostMatch: true michael@0: } michael@0: };