Bug 1458249 - Add autoplay item to about:preferences. r=johannh
MozReview-Commit-ID: AldNoElwH1O
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -71,16 +71,20 @@ Preferences.addAll([
{ id: "network.cookie.lifetimePolicy", type: "int" },
{ id: "network.cookie.blockFutureCookies", type: "bool" },
// Clear Private Data
{ id: "privacy.sanitize.sanitizeOnShutdown", type: "bool" },
{ id: "privacy.sanitize.timeSpan", type: "int" },
// Do not track
{ id: "privacy.donottrackheader.enabled", type: "bool" },
+ // Media
+ { id: "media.autoplay.enabled", type: "bool" },
+ { id: "media.autoplay.enabled.user-gestures-needed", type: "bool" },
+
// Popups
{ id: "dom.disable_open_during_load", type: "bool" },
// Passwords
{ id: "signon.rememberSignons", type: "bool" },
// Buttons
{ id: "pref.privacy.disable_button.view_passwords", type: "bool" },
{ id: "pref.privacy.disable_button.view_passwords_exceptions", type: "bool" },
@@ -249,32 +253,38 @@ var gPrivacyPane = {
init() {
function setEventListener(aId, aEventType, aCallback) {
document.getElementById(aId)
.addEventListener(aEventType, aCallback.bind(gPrivacyPane));
}
this._updateSanitizeSettingsButton();
this.initializeHistoryMode();
+ this.updateAutoplayMediaControls();
+ this.updateAutoplayMediaControlsVisibility();
this.updateHistoryModePane();
this.updatePrivacyMicroControls();
this.initAutoStartPrivateBrowsingReverter();
this._initTrackingProtection();
this._initTrackingProtectionPBM();
this._initTrackingProtectionExtensionControl();
this._initAutocomplete();
Preferences.get("privacy.sanitize.sanitizeOnShutdown").on("change",
gPrivacyPane._updateSanitizeSettingsButton.bind(gPrivacyPane));
Preferences.get("browser.privatebrowsing.autostart").on("change",
gPrivacyPane.updatePrivacyMicroControls.bind(gPrivacyPane));
Preferences.get("privacy.trackingprotection.enabled").on("change",
gPrivacyPane.trackingProtectionReadPrefs.bind(gPrivacyPane));
Preferences.get("privacy.trackingprotection.pbmode.enabled").on("change",
gPrivacyPane.trackingProtectionReadPrefs.bind(gPrivacyPane));
+ Preferences.get("media.autoplay.enabled").on("change",
+ gPrivacyPane.updateAutoplayMediaControls.bind(gPrivacyPane));
+ Preferences.get("media.autoplay.enabled.user-gestures-needed").on("change",
+ gPrivacyPane.updateAutoplayMediaControlsVisibility.bind(gPrivacyPane));
setEventListener("historyMode", "command", function() {
gPrivacyPane.updateHistoryModePane();
gPrivacyPane.updateHistoryModePrefs();
gPrivacyPane.updatePrivacyMicroControls();
gPrivacyPane.updateAutostart();
});
setEventListener("clearHistoryButton", "command", function() {
let historyMode = document.getElementById("historyMode");
@@ -327,16 +337,20 @@ var gPrivacyPane = {
setEventListener("locationSettingsButton", "command",
gPrivacyPane.showLocationExceptions);
setEventListener("cameraSettingsButton", "command",
gPrivacyPane.showCameraExceptions);
setEventListener("microphoneSettingsButton", "command",
gPrivacyPane.showMicrophoneExceptions);
setEventListener("popupPolicyButton", "command",
gPrivacyPane.showPopupExceptions);
+ setEventListener("autoplayMediaPolicy", "command",
+ gPrivacyPane.toggleAutoplayMedia);
+ setEventListener("autoplayMediaPolicyButton", "command",
+ gPrivacyPane.showAutoplayMediaExceptions);
setEventListener("notificationsDoNotDisturb", "command",
gPrivacyPane.toggleDoNotDisturbNotifications);
if (AlertsServiceDND) {
let notificationsDoNotDisturbBox =
document.getElementById("notificationsDoNotDisturbBox");
notificationsDoNotDisturbBox.removeAttribute("hidden");
let checkbox = document.getElementById("notificationsDoNotDisturb");
@@ -966,16 +980,54 @@ var gPrivacyPane = {
try {
Services.telemetry
.getHistogramById("WEB_NOTIFICATION_EXCEPTIONS_OPENED").add();
} catch (e) { }
},
+ // MEDIA
+
+ /**
+ * media.autoplay.enabled works the opposite to most of the other preferences.
+ * The checkbox enabled sets the pref to false
+ */
+ toggleAutoplayMedia(event) {
+ Services.prefs.setBoolPref("media.autoplay.enabled", !event.target.checked);
+ },
+
+ updateAutoplayMediaControls() {
+ let autoPlayEnabled = Preferences.get("media.autoplay.enabled").value;
+ document.getElementById("autoplayMediaPolicy").checked = !autoPlayEnabled;
+ document.getElementById("autoplayMediaPolicyButton").disabled = autoPlayEnabled;
+ },
+
+ /**
+ * Show the controls for the new media autoplay behaviour behind a pref for now
+ */
+ updateAutoplayMediaControlsVisibility() {
+ document.getElementById("autoplayMediaBox").hidden =
+ !Services.prefs.getBoolPref("media.autoplay.enabled.user-gestures-needed");
+ },
+
+ /**
+ * Displays the autoplay exceptions dialog where specific site autoplay preferences
+ * can be set.
+ */
+ showAutoplayMediaExceptions() {
+ var params = {
+ blockVisible: false, sessionVisible: false, allowVisible: true,
+ prefilledHost: "", permissionType: "autoplay-media"
+ };
+
+ gSubDialog.open("chrome://browser/content/preferences/permissions.xul",
+ "resizable=yes", params);
+ },
+
// POP-UPS
/**
* Displays the popup exceptions dialog where specific site popup preferences
* can be set.
*/
showPopupExceptions() {
var params = {
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -491,17 +491,35 @@
</grid>
<vbox id="notificationsDoNotDisturbBox" hidden="true">
<checkbox id="notificationsDoNotDisturb" class="indent"/>
</vbox>
<separator flex="1"/>
- <hbox align="start">
+ <hbox align="start" id="autoplayMediaBox" hidden="true">
+ <checkbox id="autoplayMediaPolicy"
+ data-l10n-id="permissions-block-autoplay-media"
+ flex="1" />
+ <!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
+ <hbox>
+ <button id="autoplayMediaPolicyButton"
+ class="accessory-button"
+ data-l10n-id="permissions-block-autoplay-media-exceptions"
+ search-l10n-ids="permissions-address,
+ permissions-button-cancel.label,
+ permissions-button-ok.label,
+ permissions-exceptions-autoplay-media-window.title,
+ permissions-exceptions-autoplay-media-desc
+ " />
+ </hbox>
+ </hbox>
+
+ <hbox>
<checkbox id="popupPolicy" preference="dom.disable_open_during_load"
data-l10n-id="permissions-block-popups"
onsyncfrompreference="return gPrivacyPane.updateButtons('popupPolicyButton',
'dom.disable_open_during_load');"
flex="1" />
<!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
<hbox>
<button id="popupPolicyButton"
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -75,16 +75,17 @@ run-if = nightly_build
[browser_privacypane_8.js]
[browser_sanitizeOnShutdown_prefLocked.js]
[browser_searchShowSuggestionsFirst.js]
[browser_searchsuggestions.js]
[browser_security-1.js]
[browser_security-2.js]
[browser_spotlight.js]
[browser_site_login_exceptions.js]
+[browser_site_autoplay_media_exceptions.js]
[browser_permissions_dialog.js]
[browser_subdialogs.js]
support-files =
subdialog.xul
subdialog2.xul
[browser_sync_sanitize.js]
[browser_telemetry.js]
# Skip this test on Android as FHR and Telemetry are separate systems there.
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_site_autoplay_media_exceptions.js
@@ -0,0 +1,109 @@
+"use strict";
+
+ChromeUtils.import("resource:///modules/SitePermissions.jsm");
+
+const URL = "http://www.example.com";
+const PRINCIPAL = Services.scriptSecurityManager
+ .createCodebasePrincipal(Services.io.newURI(URL), {});
+
+const PERMISSIONS_URL = "chrome://browser/content/preferences/permissions.xul";
+const AUTOPLAY_ENABLED_KEY = "media.autoplay.enabled";
+const GESTURES_NEEDED_KEY = "media.autoplay.enabled.user-gestures-needed";
+
+var exceptionsDialog;
+
+Services.prefs.setBoolPref(AUTOPLAY_ENABLED_KEY, true);
+Services.prefs.setBoolPref(GESTURES_NEEDED_KEY, false);
+
+async function openExceptionsDialog() {
+ let dialogOpened = promiseLoadSubDialog(PERMISSIONS_URL);
+ await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
+ let exceptionsButton = content.document.getElementById("autoplayMediaPolicyButton");
+ exceptionsButton.click();
+ });
+ exceptionsDialog = await dialogOpened;
+}
+
+add_task(async function ensureCheckboxHidden() {
+
+ registerCleanupFunction(async function() {
+ Services.prefs.clearUserPref(AUTOPLAY_ENABLED_KEY);
+ Services.prefs.clearUserPref(GESTURES_NEEDED_KEY);
+ gBrowser.removeCurrentTab();
+ });
+
+ await openPreferencesViaOpenPreferencesAPI("privacy", {leaveOpen: true});
+ let win = gBrowser.selectedBrowser.contentWindow;
+ is_element_hidden(win.document.getElementById("autoplayMediaPolicy"),
+ "Ensure checkbox is hidden when preffed off");
+});
+
+add_task(async function enableBlockingAutoplay() {
+
+ Services.prefs.setBoolPref(GESTURES_NEEDED_KEY, true);
+
+ await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
+ let doc = content.document;
+ let autoplayCheckBox = doc.getElementById("autoplayMediaPolicy");
+ autoplayCheckBox.click();
+ });
+
+ Assert.equal(Services.prefs.getBoolPref(AUTOPLAY_ENABLED_KEY), false,
+ "Ensure we have set autoplay to false");
+});
+
+add_task(async function addException() {
+ await openExceptionsDialog();
+ let doc = exceptionsDialog.document;
+
+ let tree = doc.getElementById("permissionsTree");
+ Assert.equal(tree.view.rowCount, 0, "Row count should initially be 0");
+
+ let inputBox = doc.getElementById("url");
+ inputBox.focus();
+
+ EventUtils.sendString(URL, exceptionsDialog);
+
+ let btnAllow = doc.getElementById("btnAllow");
+ btnAllow.click();
+
+ await TestUtils.waitForCondition(() => tree.view.rowCount == 1);
+ Assert.equal(tree.view.getCellText(0, tree.treeBoxObject.columns.getColumnAt(0)),
+ URL);
+
+ let permChanged = TestUtils.topicObserved("perm-changed");
+ let btnApplyChanges = doc.getElementById("btnApplyChanges");
+ btnApplyChanges.click();
+ await permChanged;
+
+ is(Services.perms.testPermissionFromPrincipal(PRINCIPAL, "autoplay-media"),
+ Ci.nsIPermissionManager.ALLOW_ACTION, "Correctly added the exception");
+});
+
+add_task(async function deleteException() {
+ await openExceptionsDialog();
+ let doc = exceptionsDialog.document;
+
+ let tree = doc.getElementById("permissionsTree");
+ Assert.equal(tree.view.rowCount, 1, "Row count should initially be 1");
+ tree.focus();
+ tree.view.selection.select(0);
+
+ if (AppConstants.platform == "macosx") {
+ EventUtils.synthesizeKey("KEY_Backspace");
+ } else {
+ EventUtils.synthesizeKey("KEY_Delete");
+ }
+
+ await TestUtils.waitForCondition(() => tree.view.rowCount == 0);
+ is_element_visible(content.gSubDialog._dialogs[0]._box,
+ "Subdialog is visible after deleting an element");
+
+ let permChanged = TestUtils.topicObserved("perm-changed");
+ let btnApplyChanges = doc.getElementById("btnApplyChanges");
+ btnApplyChanges.click();
+ await permChanged;
+
+ is(Services.perms.testPermissionFromPrincipal(PRINCIPAL, "autoplay-media"),
+ Ci.nsIPermissionManager.UNKNOWN_ACTION, "Correctly removed the exception");
+});
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -29,16 +29,20 @@ const permissionExceptionsL10n = {
"login-saving": {
window: "permissions-exceptions-saved-logins-window",
description: "permissions-exceptions-saved-logins-desc",
},
"install": {
window: "permissions-exceptions-addons-window",
description: "permissions-exceptions-addons-desc",
},
+ "autoplay-media": {
+ window: "permissions-exceptions-autoplay-media-window",
+ description: "permissions-exceptions-autoplay-media-desc",
+ },
};
function Permission(principal, type, capability) {
this.principal = principal;
this.origin = principal.origin;
this.type = type;
this.capability = capability;
}
--- a/browser/locales/en-US/browser/preferences/permissions.ftl
+++ b/browser/locales/en-US/browser/preferences/permissions.ftl
@@ -91,16 +91,23 @@ permissions-exceptions-saved-logins-desc
## Exceptions - Add-ons
permissions-exceptions-addons-window =
.title = Allowed Websites - Add-ons Installation
.style = { permissions-window.style }
permissions-exceptions-addons-desc = 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.
+## Exceptions - Autoplay Media
+
+permissions-exceptions-autoplay-media-window =
+ .title = Allowed Websites - Autoplay
+ .style = { permissions-window.style }
+permissions-exceptions-autoplay-media-desc = You can specify which websites are allowed to automatically play media elements. Type the exact address of the site you want to allow and then click Allow.
+
## Site Permissions - Notifications
permissions-site-notification-window =
.title = Settings - Notification Permissions
.style = { permissions-window.style }
permissions-site-notification-desc = 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.
permissions-site-notification-disable-label =
.label = Block new requests asking to allow notifications
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -840,16 +840,24 @@ permissions-notification-settings =
.label = Settings…
.accesskey = t
permissions-notification-link = Learn more
permissions-notification-pause =
.label = Pause notifications until { -brand-short-name } restarts
.accesskey = n
+permissions-block-autoplay-media =
+ .label = Block websites from automatically playing media with sound
+ .accesskey = B
+
+permissions-block-autoplay-media-exceptions =
+ .label = Exceptions…
+ .accesskey = E
+
permissions-block-popups =
.label = Block pop-up windows
.accesskey = B
permissions-block-popups-exceptions =
.label = Exceptions…
.accesskey = E