Bug 1368744 - Provide a way for users to deny permission prompts by default in about:preferences. r?johannh draft
authorPrathiksha <prathikshaprasadsuman@gmail.com>
Wed, 20 Dec 2017 22:32:20 +0530
changeset 716338 70a4735d08b9f000f89871453c3342bdd28bfaf2
parent 716325 81362f7306fe413b19fdba27cd0e9a5525d902e1
child 744998 11b596c1cd43a27a7339b0b5c5d657d72e7ded52
push id94390
push userbmo:prathikshaprasadsuman@gmail.com
push dateFri, 05 Jan 2018 13:33:15 +0000
reviewersjohannh
bugs1368744
milestone59.0a1
Bug 1368744 - Provide a way for users to deny permission prompts by default in about:preferences. r?johannh MozReview-Commit-ID: 3k3LRi7N8PX
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/tests/browser_permissions_dialog.js
browser/components/preferences/sitePermissions.css
browser/components/preferences/sitePermissions.js
browser/components/preferences/sitePermissions.xul
browser/locales/en-US/chrome/browser/preferences/preferences.properties
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -365,29 +365,37 @@ var gPrivacyPane = {
       bundlePrefs.getString("blockliststext"),
     ]);
     appendSearchKeywords("popupPolicyButton", [
       bundlePrefs.getString("popuppermissionstitle2"),
       bundlePrefs.getString("popuppermissionstext"),
     ]);
     appendSearchKeywords("notificationSettingsButton", [
       bundlePrefs.getString("notificationspermissionstitle2"),
-      bundlePrefs.getString("notificationspermissionstext5"),
+      bundlePrefs.getString("notificationspermissionstext6"),
+      bundlePrefs.getString("notificationspermissionsdisablelabel"),
+      bundlePrefs.getString("notificationspermissionsdisabledescription"),
     ]);
     appendSearchKeywords("locationSettingsButton", [
       bundlePrefs.getString("locationpermissionstitle"),
-      bundlePrefs.getString("locationpermissionstext"),
+      bundlePrefs.getString("locationpermissionstext2"),
+      bundlePrefs.getString("locationpermissionsdisablelabel"),
+      bundlePrefs.getString("locationpermissionsdisabledescription"),
     ]);
     appendSearchKeywords("cameraSettingsButton", [
       bundlePrefs.getString("camerapermissionstitle"),
-      bundlePrefs.getString("camerapermissionstext"),
+      bundlePrefs.getString("camerapermissionstext2"),
+      bundlePrefs.getString("camerapermissionsdisablelabel"),
+      bundlePrefs.getString("camerapermissionsdisabledescription"),
     ]);
     appendSearchKeywords("microphoneSettingsButton", [
       bundlePrefs.getString("microphonepermissionstitle"),
-      bundlePrefs.getString("microphonepermissionstext"),
+      bundlePrefs.getString("microphonepermissionstext2"),
+      bundlePrefs.getString("microphonepermissionsdisablelabel"),
+      bundlePrefs.getString("microphonepermissionsdisabledescription"),
     ]);
     appendSearchKeywords("addonExceptions", [
       bundlePrefs.getString("addons_permissions_title2"),
       bundlePrefs.getString("addonspermissionstext"),
     ]);
     appendSearchKeywords("viewSecurityDevicesButton", [
       pkiBundle.getString("enable_fips"),
     ]);
@@ -889,65 +897,73 @@ var gPrivacyPane = {
   /**
    * Displays the location exceptions dialog where specific site location
    * preferences can be set.
    */
   showLocationExceptions() {
     let bundlePreferences = document.getElementById("bundlePreferences");
     let params = { permissionType: "geo" };
     params.windowTitle = bundlePreferences.getString("locationpermissionstitle");
-    params.introText = bundlePreferences.getString("locationpermissionstext");
+    params.introText = bundlePreferences.getString("locationpermissionstext2");
+    params.disablePermissionsLabel = bundlePreferences.getString("locationpermissionsdisablelabel");
+    params.disablePermissionsDescription = bundlePreferences.getString("locationpermissionsdisabledescription");
 
     gSubDialog.open("chrome://browser/content/preferences/sitePermissions.xul",
       "resizable=yes", params);
   },
 
   // CAMERA
 
   /**
    * Displays the camera exceptions dialog where specific site camera
    * preferences can be set.
    */
   showCameraExceptions() {
     let bundlePreferences = document.getElementById("bundlePreferences");
     let params = { permissionType: "camera" };
     params.windowTitle = bundlePreferences.getString("camerapermissionstitle");
-    params.introText = bundlePreferences.getString("camerapermissionstext");
+    params.introText = bundlePreferences.getString("camerapermissionstext2");
+    params.disablePermissionsLabel = bundlePreferences.getString("camerapermissionsdisablelabel");
+    params.disablePermissionsDescription = bundlePreferences.getString("camerapermissionsdisabledescription");
 
     gSubDialog.open("chrome://browser/content/preferences/sitePermissions.xul",
       "resizable=yes", params);
   },
 
   // MICROPHONE
 
   /**
    * Displays the microphone exceptions dialog where specific site microphone
    * preferences can be set.
    */
   showMicrophoneExceptions() {
     let bundlePreferences = document.getElementById("bundlePreferences");
     let params = { permissionType: "microphone" };
     params.windowTitle = bundlePreferences.getString("microphonepermissionstitle");
-    params.introText = bundlePreferences.getString("microphonepermissionstext");
+    params.introText = bundlePreferences.getString("microphonepermissionstext2");
+    params.disablePermissionsLabel = bundlePreferences.getString("microphonepermissionsdisablelabel");
+    params.disablePermissionsDescription = bundlePreferences.getString("microphonepermissionsdisabledescription");
 
     gSubDialog.open("chrome://browser/content/preferences/sitePermissions.xul",
       "resizable=yes", params);
   },
 
   // NOTIFICATIONS
 
   /**
    * Displays the notifications exceptions dialog where specific site notification
    * preferences can be set.
    */
   showNotificationExceptions() {
     let bundlePreferences = document.getElementById("bundlePreferences");
     let params = { permissionType: "desktop-notification" };
     params.windowTitle = bundlePreferences.getString("notificationspermissionstitle2");
-    params.introText = bundlePreferences.getString("notificationspermissionstext5");
+    params.introText = bundlePreferences.getString("notificationspermissionstext6");
+    params.disablePermissionsLabel = bundlePreferences.getString("notificationspermissionsdisablelabel");
+    params.disablePermissionsDescription = bundlePreferences.getString("notificationspermissionsdisabledescription");
 
     gSubDialog.open("chrome://browser/content/preferences/sitePermissions.xul",
       "resizable=yes", params);
 
     try {
       Services.telemetry
         .getHistogramById("WEB_NOTIFICATION_EXCEPTIONS_OPENED").add();
     } catch (e) { }
--- a/browser/components/preferences/in-content/tests/browser_permissions_dialog.js
+++ b/browser/components/preferences/in-content/tests/browser_permissions_dialog.js
@@ -266,11 +266,76 @@ add_task(async function onPermissionsSor
   Assert.equal(richlistbox.getItemAtIndex(1).getAttribute("origin"), "http://www.example.com");
 
   SitePermissions.remove(URI, "desktop-notification");
   SitePermissions.remove(u, "desktop-notification");
 
   doc.getElementById("cancel").click();
 });
 
+add_task(async function onPermissionDisable() {
+  // Enable desktop-notification permission prompts.
+  Services.prefs.setIntPref("permissions.default.desktop-notification", SitePermissions.UNKNOWN);
+
+  await openPermissionsDialog();
+  let doc = sitePermissionsDialog.document;
+
+  // Check if the enabled state is reflected in the checkbox.
+  let checkbox = doc.getElementById("permissionsDisableCheckbox");
+  Assert.equal(checkbox.checked, false);
+
+  // Disable permission and click on "Cancel".
+  checkbox.checked = true;
+  doc.getElementById("cancel").click();
+
+  // Check that the permission is not disabled yet.
+  let perm = Services.prefs.getIntPref("permissions.default.desktop-notification");
+  Assert.equal(perm, SitePermissions.UNKNOWN);
+
+  // Open the dialog once again.
+  await openPermissionsDialog();
+  doc = sitePermissionsDialog.document;
+
+  // Disable permission and save changes.
+  checkbox = doc.getElementById("permissionsDisableCheckbox");
+  checkbox.checked = true;
+  doc.getElementById("btnApplyChanges").click();
+
+  // Check if the permission is now disabled.
+  perm = Services.prefs.getIntPref("permissions.default.desktop-notification");
+  Assert.equal(perm, SitePermissions.BLOCK);
+
+  // Open the dialog once again and check if the disabled state is still reflected in the checkbox.
+  await openPermissionsDialog();
+  doc = sitePermissionsDialog.document;
+  checkbox = doc.getElementById("permissionsDisableCheckbox");
+  Assert.equal(checkbox.checked, true);
+
+  // Close the dialog.
+  doc.getElementById("cancel").click();
+});
+
+add_task(async function checkDefaultPermissionState() {
+  // Set default permission state to ALLOW.
+  Services.prefs.setIntPref("permissions.default.desktop-notification", SitePermissions.ALLOW);
+
+  await openPermissionsDialog();
+  let doc = sitePermissionsDialog.document;
+
+  // Check if the enabled state is reflected in the checkbox.
+  let checkbox = doc.getElementById("permissionsDisableCheckbox");
+  Assert.equal(checkbox.checked, false);
+
+  // Check the checkbox and then uncheck it.
+  checkbox.checked = true;
+  checkbox.checked = false;
+
+  // Save changes.
+  doc.getElementById("btnApplyChanges").click();
+
+  // Check if the default permission state is retained (and not automatically set to SitePermissions.UNKNOWN).
+  let state = Services.prefs.getIntPref("permissions.default.desktop-notification");
+  Assert.equal(state, SitePermissions.ALLOW);
+});
+
 add_task(async function removeTab() {
   gBrowser.removeCurrentTab();
 });
--- a/browser/components/preferences/sitePermissions.css
+++ b/browser/components/preferences/sitePermissions.css
@@ -16,8 +16,24 @@
 #permissionsBox > richlistitem {
   min-height: 35px;
 }
 
 .website-status {
   margin: 1px;
   margin-inline-end: 5px;
 }
+
+#permissionsDisableLabel {
+  padding-top: 14px;
+  font-weight: bold;
+}
+
+#permissionsDisableDescription {
+  margin-inline-start: 37px;
+  color: #737373;
+  line-height: 110%;
+}
+
+#permissionsDisableCheckbox {
+  margin-inline-start: 4px;
+  padding-top: 10px;
+}
--- a/browser/components/preferences/sitePermissions.js
+++ b/browser/components/preferences/sitePermissions.js
@@ -22,16 +22,19 @@ var gSitePermissionsManager = {
   _permissions: new Map(),
   _permissionsToChange: new Map(),
   _permissionsToDelete: new Map(),
   _list: null,
   _bundle: null,
   _removeButton: null,
   _removeAllButton: null,
   _searchBox: null,
+  _checkbox: null,
+  _currentDefaultPermissionsState: null,
+  _defaultPermissionStatePrefName: null,
 
   onLoad() {
     let params = window.arguments[0];
     this.init(params);
   },
 
   init(params) {
     if (!this._isObserving) {
@@ -40,24 +43,48 @@ var gSitePermissionsManager = {
     }
 
     this._bundle = document.getElementById("bundlePreferences");
     this._type = params.permissionType;
     this._list = document.getElementById("permissionsBox");
     this._removeButton = document.getElementById("removePermission");
     this._removeAllButton = document.getElementById("removeAllPermissions");
     this._searchBox = document.getElementById("searchBox");
+    this._checkbox = document.getElementById("permissionsDisableCheckbox");
 
     let permissionsText = document.getElementById("permissionsText");
     while (permissionsText.hasChildNodes())
       permissionsText.firstChild.remove();
     permissionsText.appendChild(document.createTextNode(params.introText));
 
+    let permissionsDisableLabel = document.getElementById("permissionsDisableLabel");
+    permissionsDisableLabel.value = params.disablePermissionsLabel;
+
+    let permissionsDisableDescription = document.getElementById("permissionsDisableDescription");
+    permissionsDisableDescription.appendChild(document.createTextNode(params.disablePermissionsDescription));
+
     document.title = params.windowTitle;
 
+    // Initialize the checkbox state.
+    this._defaultPermissionStatePrefName = "permissions.default." + this._type;
+    let pref = Services.prefs.getPrefType(this._defaultPermissionStatePrefName);
+    if (pref != Services.prefs.PREF_INVALID) {
+      this._currentDefaultPermissionsState = Services.prefs.getIntPref(this._defaultPermissionStatePrefName);
+    }
+
+    if (this._currentDefaultPermissionsState === null) {
+      this._checkbox.setAttribute("hidden", true);
+      permissionsDisableLabel.setAttribute("hidden", true);
+      permissionsDisableDescription.setAttribute("hidden", true);
+    } else if (this._currentDefaultPermissionsState == SitePermissions.BLOCK) {
+      this._checkbox.checked = true;
+    } else {
+      this._checkbox.checked = false;
+    }
+
     this._loadPermissions();
     this.buildPermissionsList();
 
     this._searchBox.focus();
   },
 
   uninit() {
     if (this._isObserving) {
@@ -259,16 +286,23 @@ var gSitePermissionsManager = {
       let uri = Services.io.newURI(p.origin);
       SitePermissions.set(uri, p.type, p.capability);
     }
 
     for (let p of this._permissionsToDelete.values()) {
       let uri = Services.io.newURI(p.origin);
       SitePermissions.remove(uri, p.type);
     }
+
+    if (this._checkbox.checked) {
+      Services.prefs.setIntPref(this._defaultPermissionStatePrefName, SitePermissions.BLOCK);
+    } else if (this._currentDefaultPermissionsState == SitePermissions.BLOCK) {
+      Services.prefs.setIntPref(this._defaultPermissionStatePrefName, SitePermissions.UNKNOWN);
+    }
+
     window.close();
   },
 
   buildPermissionsList(sortCol) {
     // Clear old entries.
     let oldItems = this._list.querySelectorAll("richlistitem");
     for (let item of oldItems) {
       item.remove();
--- a/browser/components/preferences/sitePermissions.xul
+++ b/browser/components/preferences/sitePermissions.xul
@@ -57,16 +57,24 @@
               icon="remove" label="&removepermission2.label;"
               oncommand="gSitePermissionsManager.onPermissionDelete();"/>
       <button id="removeAllPermissions"
               icon="clear" label="&removeallpermissions2.label;"
               accesskey="&removeallpermissions2.accesskey;"
               oncommand="gSitePermissionsManager.onAllPermissionsDelete();"/>
     </hbox>
     <spacer flex="1"/>
+    <vbox align="start">
+      <hbox align="start">
+        <checkbox id="permissionsDisableCheckbox"/>
+        <label for="permissionsDisableCheckbox" id="permissionsDisableLabel"/>
+      </hbox>
+      <description id="permissionsDisableDescription"/>
+    </vbox>
+    <spacer flex="1"/>
     <hbox class="actionButtons" align="right" flex="1">
       <button oncommand="close();" icon="close" id="cancel"
               label="&button.cancel.label;" accesskey="&button.cancel.accesskey;" />
       <button id="btnApplyChanges" oncommand="gSitePermissionsManager.onApplyChanges();" icon="save"
               label="&button.ok.label;" accesskey="&button.ok.accesskey;"/>
     </hbox>
   </vbox>
 </window>
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -23,24 +23,32 @@ acceptVeryLargeMinimumFont=Keep my chang
 trackingprotectionpermissionstext2=You have disabled Tracking Protection on these websites.
 trackingprotectionpermissionstitle=Exceptions - Tracking Protection
 cookiepermissionstext=You can specify which websites are always or never allowed to use cookies.  Type the exact address of the site you want to manage and then click Block, Allow for Session, or Allow.
 cookiepermissionstitle=Exceptions - Cookies
 addonspermissionstext=You can specify which websites are allowed to install add-ons. Type the exact address of the site you want to allow and then click Allow.
 addons_permissions_title2=Allowed Websites - Add-ons Installation
 popuppermissionstext=You can specify which websites are allowed to open pop-up windows. Type the exact address of the site you want to allow and then click Allow.
 popuppermissionstitle2=Allowed Websites - Pop-ups
-notificationspermissionstext5=The following websites have requested to send you notifications. You can specify which websites are allowed to send you notifications.
+notificationspermissionstext6=The following websites have requested to send you notifications. You can specify which websites are allowed to send you notifications. You can also block new requests asking to allow notifications.
 notificationspermissionstitle2=Settings - Notification Permissions
-locationpermissionstext=The following websites have requested to access your location. You can specify which websites are allowed to access your location.
+notificationspermissionsdisablelabel=Block new requests asking to allow notifications
+notificationspermissionsdisabledescription=This will prevent any websites not listed above from requesting permission to send notifications. Blocking notifications may break some website features.
+locationpermissionstext2=The following websites have requested to access your location. You can specify which websites are allowed to access your location. You can also block new requests asking to access your location.
 locationpermissionstitle=Settings - Location Permissions
-camerapermissionstext=The following websites have requested to access your camera. You can specify which websites are allowed to access your camera.
+locationpermissionsdisablelabel=Block new requests asking to access your location
+locationpermissionsdisabledescription=This will prevent any websites not listed above from requesting permission to access your location. Blocking access to your location may break some website features.
+camerapermissionstext2=The following websites have requested to access your camera. You can specify which websites are allowed to access your camera. You can also block new requests asking to access your camera.
 camerapermissionstitle=Settings - Camera Permissions
-microphonepermissionstext=The following websites have requested to access your microphone. You can specify which websites are allowed to access your microphone.
+camerapermissionsdisablelabel=Block new requests asking to access your camera
+camerapermissionsdisabledescription=This will prevent any websites not listed above from requesting permission to access your camera. Blocking access to your camera may break some website features.
+microphonepermissionstext2=The following websites have requested to access your microphone. You can specify which websites are allowed to access your microphone. You can also block new requests asking to access your microphone.
 microphonepermissionstitle=Settings - Microphone Permissions
+microphonepermissionsdisablelabel=Block new requests asking to access your microphone
+microphonepermissionsdisabledescription=This will prevent any websites not listed above from requesting permission to access your microphone. Blocking access to your microphone may break some website features.
 invalidURI=Please enter a valid hostname
 invalidURITitle=Invalid Hostname Entered
 savedLoginsExceptions_title=Exceptions - Saved Logins
 savedLoginsExceptions_desc3=Logins for the following websites will not be saved
 
 # LOCALIZATION NOTE(pauseNotifications.label): %S is replaced with the
 # brandShortName of the application.
 pauseNotifications.label=Pause notifications until %S restarts