summaryrefslogtreecommitdiffstats
path: root/browser/modules/PermissionUI.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'browser/modules/PermissionUI.jsm')
-rw-r--r--browser/modules/PermissionUI.jsm595
1 files changed, 0 insertions, 595 deletions
diff --git a/browser/modules/PermissionUI.jsm b/browser/modules/PermissionUI.jsm
deleted file mode 100644
index 5fa0f9f06..000000000
--- a/browser/modules/PermissionUI.jsm
+++ /dev/null
@@ -1,595 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
- "PermissionUI",
-];
-
-/**
- * PermissionUI is responsible for exposing both a prototype
- * PermissionPrompt that can be used by arbitrary browser
- * components and add-ons, but also hosts the implementations of
- * built-in permission prompts.
- *
- * If you're developing a feature that requires web content to ask
- * for special permissions from the user, this module is for you.
- *
- * Suppose a system add-on wants to add a new prompt for a new request
- * for getting more low-level access to the user's sound card, and the
- * permission request is coming up from content by way of the
- * nsContentPermissionHelper. The system add-on could then do the following:
- *
- * Cu.import("resource://gre/modules/Integration.jsm");
- * Cu.import("resource:///modules/PermissionUI.jsm");
- *
- * const SoundCardIntegration = (base) => ({
- * __proto__: base,
- * createPermissionPrompt(type, request) {
- * if (type != "sound-api") {
- * return super.createPermissionPrompt(...arguments);
- * }
- *
- * return {
- * __proto__: PermissionUI.PermissionPromptForRequestPrototype,
- * get permissionKey() {
- * return "sound-permission";
- * }
- * // etc - see the documentation for PermissionPrompt for
- * // a better idea of what things one can and should override.
- * }
- * },
- * });
- *
- * // Add-on startup:
- * Integration.contentPermission.register(SoundCardIntegration);
- * // ...
- * // Add-on shutdown:
- * Integration.contentPermission.unregister(SoundCardIntegration);
- *
- * Note that PermissionPromptForRequestPrototype must be used as the
- * prototype, since the prompt is wrapping an nsIContentPermissionRequest,
- * and going through nsIContentPermissionPrompt.
- *
- * It is, however, possible to take advantage of PermissionPrompt without
- * having to go through nsIContentPermissionPrompt or with a
- * nsIContentPermissionRequest. The PermissionPromptPrototype can be
- * imported, subclassed, and have prompt() called directly, without
- * the caller having called into createPermissionPrompt.
- */
-const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
- "resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
- "resource://gre/modules/PrivateBrowsingUtils.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
- return Services.strings
- .createBundle('chrome://branding/locale/brand.properties');
-});
-
-XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
- return Services.strings
- .createBundle('chrome://browser/locale/browser.properties');
-});
-
-this.PermissionUI = {};
-
-/**
- * PermissionPromptPrototype should be subclassed by callers that
- * want to display prompts to the user. See each method and property
- * below for guidance on what to override.
- *
- * Note that if you're creating a prompt for an
- * nsIContentPermissionRequest, you'll want to subclass
- * PermissionPromptForRequestPrototype instead.
- */
-this.PermissionPromptPrototype = {
- /**
- * Returns the associated <xul:browser> for the request. This should
- * work for the e10s and non-e10s case.
- *
- * Subclasses must override this.
- *
- * @return {<xul:browser>}
- */
- get browser() {
- throw new Error("Not implemented.");
- },
-
- /**
- * Returns the nsIPrincipal associated with the request.
- *
- * Subclasses must override this.
- *
- * @return {nsIPrincipal}
- */
- get principal() {
- throw new Error("Not implemented.");
- },
-
- /**
- * If the nsIPermissionManager is being queried and written
- * to for this permission request, set this to the key to be
- * used. If this is undefined, user permissions will not be
- * read from or written to.
- *
- * Note that if a permission is set, in any follow-up
- * prompting within the expiry window of that permission,
- * the prompt will be skipped and the allow or deny choice
- * will be selected automatically.
- */
- get permissionKey() {
- return undefined;
- },
-
- /**
- * These are the options that will be passed to the
- * PopupNotification when it is shown. See the documentation
- * for PopupNotification for more details.
- *
- * Note that prompt() will automatically set displayURI to
- * be the URI of the requesting pricipal, unless the displayURI is exactly
- * set to false.
- */
- get popupOptions() {
- return {};
- },
-
- /**
- * PopupNotification requires a unique ID to open the notification.
- * You must return a unique ID string here, for which PopupNotification
- * will then create a <xul:popupnotification> node with the ID
- * "<notificationID>-notification".
- *
- * If there's a custom <xul:popupnotification> you're hoping to show,
- * then you need to make sure its ID has the "-notification" suffix,
- * and then return the prefix here.
- *
- * See PopupNotification.jsm for more details.
- *
- * @return {string}
- * The unique ID that will be used to as the
- * "<unique ID>-notification" ID for the <xul:popupnotification>
- * to use or create.
- */
- get notificationID() {
- throw new Error("Not implemented.");
- },
-
- /**
- * The ID of the element to anchor the PopupNotification to.
- *
- * @return {string}
- */
- get anchorID() {
- return "default-notification-icon";
- },
-
- /**
- * The message to show the user in the PopupNotification. This
- * is usually a string describing the permission that is being
- * requested.
- *
- * Subclasses must override this.
- *
- * @return {string}
- */
- get message() {
- throw new Error("Not implemented.");
- },
-
- /**
- * This will be called if the request is to be cancelled.
- *
- * Subclasses only need to override this if they provide a
- * permissionKey.
- */
- cancel() {
- throw new Error("Not implemented.")
- },
-
- /**
- * This will be called if the request is to be allowed.
- *
- * Subclasses only need to override this if they provide a
- * permissionKey.
- */
- allow() {
- throw new Error("Not implemented.");
- },
-
- /**
- * The actions that will be displayed in the PopupNotification
- * via a dropdown menu. The first item in this array will be
- * the default selection. Each action is an Object with the
- * following properties:
- *
- * label (string):
- * The label that will be displayed for this choice.
- * accessKey (string):
- * The access key character that will be used for this choice.
- * action (Ci.nsIPermissionManager action, optional)
- * The nsIPermissionManager action that will be associated with
- * this choice. For example, Ci.nsIPermissionManager.DENY_ACTION.
- *
- * If omitted, the nsIPermissionManager will not be written to
- * when this choice is chosen.
- * expireType (Ci.nsIPermissionManager expiration policy, optional)
- * The nsIPermissionManager expiration policy that will be associated
- * with this choice. For example, Ci.nsIPermissionManager.EXPIRE_SESSION.
- *
- * If action is not set, expireType will be ignored.
- * callback (function, optional)
- * A callback function that will fire if the user makes this choice.
- */
- get promptActions() {
- return [];
- },
-
- /**
- * If the prompt will be shown to the user, this callback will
- * be called just before. Subclasses may want to override this
- * in order to, for example, bump a counter Telemetry probe for
- * how often a particular permission request is seen.
- */
- onBeforeShow() {},
-
- /**
- * Will determine if a prompt should be shown to the user, and if so,
- * will show it.
- *
- * If a permissionKey is defined prompt() might automatically
- * allow or cancel itself based on the user's current
- * permission settings without displaying the prompt.
- *
- * If the <xul:browser> that the request is associated with
- * does not belong to a browser window with the PopupNotifications
- * global set, the prompt request is ignored.
- */
- prompt() {
- let chromeWin = this.browser.ownerGlobal;
- if (!chromeWin.PopupNotifications) {
- return;
- }
-
- // We ignore requests from non-nsIStandardURLs
- let requestingURI = this.principal.URI;
- if (!(requestingURI instanceof Ci.nsIStandardURL)) {
- return;
- }
-
- if (this.permissionKey) {
- // If we're reading and setting permissions, then we need
- // to check to see if we already have a permission setting
- // for this particular principal.
- let result =
- Services.perms.testExactPermissionFromPrincipal(this.principal,
- this.permissionKey);
-
- if (result == Ci.nsIPermissionManager.DENY_ACTION) {
- this.cancel();
- return;
- }
-
- if (result == Ci.nsIPermissionManager.ALLOW_ACTION) {
- this.allow();
- return;
- }
- }
-
- // Transform the PermissionPrompt actions into PopupNotification actions.
- let popupNotificationActions = [];
- for (let promptAction of this.promptActions) {
- // Don't offer action in PB mode if the action remembers permission
- // for more than a session.
- if (PrivateBrowsingUtils.isWindowPrivate(chromeWin) &&
- promptAction.expireType != Ci.nsIPermissionManager.EXPIRE_SESSION &&
- promptAction.action) {
- continue;
- }
-
- let action = {
- label: promptAction.label,
- accessKey: promptAction.accessKey,
- callback: () => {
- if (promptAction.callback) {
- promptAction.callback();
- }
-
- if (this.permissionKey) {
- // Remember permissions.
- if (promptAction.action) {
- Services.perms.addFromPrincipal(this.principal,
- this.permissionKey,
- promptAction.action,
- promptAction.expireType);
- }
-
- // Grant permission if action is null or ALLOW_ACTION.
- if (!promptAction.action ||
- promptAction.action == Ci.nsIPermissionManager.ALLOW_ACTION) {
- this.allow();
- } else {
- this.cancel();
- }
- }
- },
- };
- if (promptAction.dismiss) {
- action.dismiss = promptAction.dismiss
- }
-
- popupNotificationActions.push(action);
- }
-
- let mainAction = popupNotificationActions.length ?
- popupNotificationActions[0] : null;
- let secondaryActions = popupNotificationActions.splice(1);
-
- let options = this.popupOptions;
-
- if (!options.hasOwnProperty('displayURI') || options.displayURI) {
- options.displayURI = this.principal.URI;
- }
-
- this.onBeforeShow();
- chromeWin.PopupNotifications.show(this.browser,
- this.notificationID,
- this.message,
- this.anchorID,
- mainAction,
- secondaryActions,
- options);
- },
-};
-
-PermissionUI.PermissionPromptPrototype = PermissionPromptPrototype;
-
-/**
- * A subclass of PermissionPromptPrototype that assumes
- * that this.request is an nsIContentPermissionRequest
- * and fills in some of the required properties on the
- * PermissionPrompt. For callers that are wrapping an
- * nsIContentPermissionRequest, this should be subclassed
- * rather than PermissionPromptPrototype.
- */
-this.PermissionPromptForRequestPrototype = {
- __proto__: PermissionPromptPrototype,
-
- get browser() {
- // In the e10s-case, the <xul:browser> will be at request.element.
- // In the single-process case, we have to use some XPCOM incantations
- // to resolve to the <xul:browser>.
- if (this.request.element) {
- return this.request.element;
- }
- return this.request
- .window
- .QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIWebNavigation)
- .QueryInterface(Ci.nsIDocShell)
- .chromeEventHandler;
- },
-
- get principal() {
- return this.request.principal;
- },
-
- cancel() {
- this.request.cancel();
- },
-
- allow() {
- this.request.allow();
- },
-};
-
-PermissionUI.PermissionPromptForRequestPrototype =
- PermissionPromptForRequestPrototype;
-
-/**
- * Creates a PermissionPrompt for a nsIContentPermissionRequest for
- * the GeoLocation API.
- *
- * @param request (nsIContentPermissionRequest)
- * The request for a permission from content.
- */
-function GeolocationPermissionPrompt(request) {
- this.request = request;
-}
-
-GeolocationPermissionPrompt.prototype = {
- __proto__: PermissionPromptForRequestPrototype,
-
- get permissionKey() {
- return "geo";
- },
-
- get popupOptions() {
- let pref = "browser.geolocation.warning.infoURL";
- return {
- learnMoreURL: Services.urlFormatter.formatURLPref(pref),
- };
- },
-
- get notificationID() {
- return "geolocation";
- },
-
- get anchorID() {
- return "geo-notification-icon";
- },
-
- get message() {
- let message;
- if (this.principal.URI.schemeIs("file")) {
- message = gBrowserBundle.GetStringFromName("geolocation.shareWithFile2");
- } else {
- message = gBrowserBundle.GetStringFromName("geolocation.shareWithSite2");
- }
- return message;
- },
-
- get promptActions() {
- // We collect Telemetry data on Geolocation prompts and how users
- // respond to them. The probe keys are a bit verbose, so let's alias them.
- const SHARE_LOCATION =
- Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_SHARE_LOCATION;
- const ALWAYS_SHARE =
- Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_ALWAYS_SHARE;
- const NEVER_SHARE =
- Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST_NEVER_SHARE;
-
- let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
-
- let actions = [{
- label: gBrowserBundle.GetStringFromName("geolocation.shareLocation"),
- accessKey:
- gBrowserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
- action: null,
- expireType: null,
- callback: function() {
- secHistogram.add(SHARE_LOCATION);
- },
- }];
-
- if (!this.principal.URI.schemeIs("file")) {
- // Always share location action.
- actions.push({
- label: gBrowserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
- accessKey:
- gBrowserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: null,
- callback: function() {
- secHistogram.add(ALWAYS_SHARE);
- },
- });
-
- // Never share location action.
- actions.push({
- label: gBrowserBundle.GetStringFromName("geolocation.neverShareLocation"),
- accessKey:
- gBrowserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
- action: Ci.nsIPermissionManager.DENY_ACTION,
- expireType: null,
- callback: function() {
- secHistogram.add(NEVER_SHARE);
- },
- });
- }
-
- return actions;
- },
-
- onBeforeShow() {
- let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
- const SHOW_REQUEST = Ci.nsISecurityUITelemetry.WARNING_GEOLOCATION_REQUEST;
- secHistogram.add(SHOW_REQUEST);
- },
-};
-
-PermissionUI.GeolocationPermissionPrompt = GeolocationPermissionPrompt;
-
-/**
- * Creates a PermissionPrompt for a nsIContentPermissionRequest for
- * the Desktop Notification API.
- *
- * @param request (nsIContentPermissionRequest)
- * The request for a permission from content.
- * @return {PermissionPrompt} (see documentation in header)
- */
-function DesktopNotificationPermissionPrompt(request) {
- this.request = request;
-}
-
-DesktopNotificationPermissionPrompt.prototype = {
- __proto__: PermissionPromptForRequestPrototype,
-
- get permissionKey() {
- return "desktop-notification";
- },
-
- get popupOptions() {
- let learnMoreURL =
- Services.urlFormatter.formatURLPref("app.support.baseURL") + "push";
-
- // The eventCallback is bound to the Notification that's being
- // shown. We'll stash a reference to this in the closure so that
- // the request can be cancelled.
- let prompt = this;
-
- let eventCallback = function(type) {
- if (type == "dismissed") {
- // Bug 1259148: Hide the doorhanger icon. Unlike other permission
- // doorhangers, the user can't restore the doorhanger using the icon
- // in the location bar. Instead, the site will be notified that the
- // doorhanger was dismissed.
- this.remove();
- prompt.request.cancel();
- }
- };
-
- return {
- learnMoreURL,
- eventCallback,
- };
- },
-
- get notificationID() {
- return "web-notifications";
- },
-
- get anchorID() {
- return "web-notifications-notification-icon";
- },
-
- get message() {
- return gBrowserBundle.GetStringFromName("webNotifications.receiveFromSite");
- },
-
- get promptActions() {
- let promptActions;
- // Only show "allow for session" in PB mode, we don't
- // support "allow for session" in non-PB mode.
- if (PrivateBrowsingUtils.isBrowserPrivate(this.browser)) {
- promptActions = [
- {
- label: gBrowserBundle.GetStringFromName("webNotifications.receiveForSession"),
- accessKey:
- gBrowserBundle.GetStringFromName("webNotifications.receiveForSession.accesskey"),
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
- }
- ];
- } else {
- promptActions = [
- {
- label: gBrowserBundle.GetStringFromName("webNotifications.alwaysReceive"),
- accessKey:
- gBrowserBundle.GetStringFromName("webNotifications.alwaysReceive.accesskey"),
- action: Ci.nsIPermissionManager.ALLOW_ACTION,
- expireType: null,
- },
- {
- label: gBrowserBundle.GetStringFromName("webNotifications.neverShow"),
- accessKey:
- gBrowserBundle.GetStringFromName("webNotifications.neverShow.accesskey"),
- action: Ci.nsIPermissionManager.DENY_ACTION,
- expireType: null,
- },
- ];
- }
-
- return promptActions;
- },
-};
-
-PermissionUI.DesktopNotificationPermissionPrompt =
- DesktopNotificationPermissionPrompt;