Richard Pospesel pushed to branch tor-browser-102.6.0esr-12.5-1 at The Tor Project / Applications / Tor Browser
Commits: 90395b29 by Henry Wilkes at 2023-01-09T20:41:54+00:00 fixup! Bug 40925: Implemented the Security Level component
Bug 32274: Make the security level settings more accessible:
+ We remove the "Restore Defaults" link that was between each radio option and place it separately as a button, with some notification text. + We set the `aria-describedby` attribute on the radio options to point to the description. + We change the security level popup's button text from "Change" to "Change Setting" to give users more of a hint that clicking the button will land them in the middle of about:preferences.
We also tidied up the javascript, CSS and xhtml.
- - - - -
5 changed files:
- browser/components/preferences/privacy.js - browser/components/securitylevel/content/securityLevel.js - browser/components/securitylevel/content/securityLevelPreferences.css - browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml - browser/components/securitylevel/locale/en-US/securityLevel.properties
Changes:
===================================== browser/components/preferences/privacy.js ===================================== @@ -341,11 +341,9 @@ var gPrivacyPane = { */ _initSecurityLevel() { SecurityLevelPreferences.init(); - let unload = () => { - window.removeEventListener("unload", unload); - SecurityLevelPreferences.uninit(); - }; - window.addEventListener("unload", unload); + window.addEventListener("unload", () => SecurityLevelPreferences.uninit(), { + once: true, + }); },
/**
===================================== browser/components/securitylevel/content/securityLevel.js ===================================== @@ -17,13 +17,14 @@ XPCOMUtils.defineLazyGetter(this, "SecurityLevelStrings", () => { security_level_restore: "Restore Defaults", security_level_learn_more: "Learn more", // Panel - security_level_change: "Change…", + security_level_change_setting: "Change Setting…", security_level_standard_summary: "All browser and website features are enabled.", security_level_safer_summary: "Disables website features that are often dangerous, causing some sites to lose functionality.", security_level_safest_summary: "Only allows website features required for static sites and basic services. These changes affect images, media, and scripts.", + security_level_custom_heading: "Warning!", security_level_custom_summary: "Your custom browser preferences have resulted in unusual security settings. For security and privacy reasons, we recommend you choose one of the default security levels.", // Security level section in about:preferences#privacy @@ -259,7 +260,7 @@ var SecurityLevelPanel = { this._elements.restoreDefaultsButton.textContent = SecurityLevelStrings.security_level_restore; this._elements.settingsButton.textContent = - SecurityLevelStrings.security_level_change; + SecurityLevelStrings.security_level_change_setting;
this._elements.restoreDefaultsButton.addEventListener("command", () => { this.restoreDefaults(); @@ -367,120 +368,112 @@ var SecurityLevelPanel = {
var SecurityLevelPreferences = { _securityPrefsBranch: null, + /** + * The notification box shown when the user has a custom security setting. + * + * @type {Element} + */ + _customNotification: null, + /** + * The radiogroup for this preference. + * + * @type {Element} + */ + _radiogroup: null, + /** + * A list of radio options and their containers. + * + * @type {Array<Object>} + */ + _radioOptions: null,
_populateXUL() { - const groupbox = document.querySelector("#securityLevel-groupbox"); - const radiogroup = groupbox.querySelector("#securityLevel-radiogroup"); - radiogroup.addEventListener( - "command", - SecurityLevelPreferences.selectSecurityLevel + this._customNotification = document.getElementById( + "securityLevel-customNotification" ); + this._radiogroup = document.getElementById("securityLevel-radiogroup");
- groupbox.querySelector("h2").textContent = + document.querySelector("#securityLevel-groupbox h2").textContent = SecurityLevelStrings.security_level; - groupbox.querySelector("#securityLevel-overview").textContent = + document.getElementById("securityLevel-overview").textContent = SecurityLevelStrings.security_level_overview; - groupbox - .querySelector("#securityLevel-learnMore") + document + .getElementById("securityLevel-learnMore") .setAttribute("value", SecurityLevelStrings.security_level_learn_more);
- const populateRadioElements = (level, descr) => { - const vbox = groupbox.querySelector(`#securityLevel-vbox-${level}`); - vbox - .querySelector("radio") - .setAttribute("label", SecurityLevelStrings[`security_level_${level}`]); - vbox - .querySelector(".securityLevel-customWarning") - .setAttribute("value", SecurityLevelStrings.security_level_custom); - vbox.querySelector(".summary").textContent = - SecurityLevelStrings[`security_level_${level}_summary`]; - const labelRestoreDefaults = vbox.querySelector( - ".securityLevel-restoreDefaults" - ); - labelRestoreDefaults.setAttribute( - "value", - SecurityLevelStrings.security_level_restore + document.getElementById("securityLevel-customHeading").textContent = + SecurityLevelStrings.security_level_custom_heading; + document.getElementById("securityLevel-customDescription").textContent = + SecurityLevelStrings.security_level_custom_summary; + const restoreDefaultsButton = document.getElementById( + "securityLevel-restoreDefaults" + ); + restoreDefaultsButton.textContent = + SecurityLevelStrings.security_level_restore; + + this._radioOptions = Array.from( + this._radiogroup.querySelectorAll(".securityLevel-radio-option"), + container => { + return { container, radio: container.querySelector("radio") }; + } + ); + const descListItemsMap = { + safer: [ + SecurityLevelStrings.security_level_js_https_only, + SecurityLevelStrings.security_level_limit_typography, + SecurityLevelStrings.security_level_limit_media, + ], + safest: [ + SecurityLevelStrings.security_level_js_disabled, + SecurityLevelStrings.security_level_limit_typography_svg, + SecurityLevelStrings.security_level_limit_media, + ], + }; + for (const { container, radio } of this._radioOptions) { + const level = radio.value; + radio.setAttribute( + "label", + SecurityLevelStrings[`security_level_${level}`] ); - labelRestoreDefaults.addEventListener( - "click", - SecurityLevelStrings.restoreDefaults + container.querySelector(".summary").textContent = + SecurityLevelStrings[`security_level_${level}_summary`]; + const descListItems = descListItemsMap[level]; + if (!descListItems) { + continue; + } + const descrList = container.querySelector( + ".securityLevel-descriptionList" ); - if (descr) { - const descrList = vbox.querySelector(".securityLevel-descriptionList"); - // TODO: Add the elements in securityLevelPreferences.inc.xhtml again - // when we switch to Fluent - for (const text of descr) { - let elem = document.createXULElement("description"); - elem.textContent = text; - elem.className = "indent"; - descrList.append(elem); - } + // TODO: Add the elements in securityLevelPreferences.inc.xhtml again + // when we switch to Fluent + for (const text of descListItems) { + let elem = document.createXULElement("description"); + elem.textContent = text; + elem.className = "indent"; + descrList.append(elem); } - }; - populateRadioElements("standard"); - populateRadioElements("safer", [ - SecurityLevelStrings.security_level_js_https_only, - SecurityLevelStrings.security_level_limit_typography, - SecurityLevelStrings.security_level_limit_media, - ]); - populateRadioElements("safest", [ - SecurityLevelStrings.security_level_js_disabled, - SecurityLevelStrings.security_level_limit_typography_svg, - SecurityLevelStrings.security_level_limit_media, - ]); + } + + restoreDefaultsButton.addEventListener("command", () => { + SecurityLevelPrefs.securityCustom = false; + }); + this._radiogroup.addEventListener("select", () => { + SecurityLevelPrefs.securityLevel = this._radiogroup.value; + }); },
_configUIFromPrefs() { - // read our prefs - const securityLevel = SecurityLevelPrefs.securityLevel; - const securityCustom = SecurityLevelPrefs.securityCustom; - - // get our elements - const groupbox = document.querySelector("#securityLevel-groupbox"); - let radiogroup = groupbox.querySelector("#securityLevel-radiogroup"); - let labelStandardCustom = groupbox.querySelector( - "#securityLevel-vbox-standard label.securityLevel-customWarning" - ); - let labelSaferCustom = groupbox.querySelector( - "#securityLevel-vbox-safer label.securityLevel-customWarning" - ); - let labelSafestCustom = groupbox.querySelector( - "#securityLevel-vbox-safest label.securityLevel-customWarning" - ); - let labelStandardRestoreDefaults = groupbox.querySelector( - "#securityLevel-vbox-standard label.securityLevel-restoreDefaults" - ); - let labelSaferRestoreDefaults = groupbox.querySelector( - "#securityLevel-vbox-safer label.securityLevel-restoreDefaults" - ); - let labelSafestRestoreDefaults = groupbox.querySelector( - "#securityLevel-vbox-safest label.securityLevel-restoreDefaults" - ); - - // hide custom label by default until we know which level we're at - labelStandardCustom.hidden = true; - labelSaferCustom.hidden = true; - labelSafestCustom.hidden = true; - - labelStandardRestoreDefaults.hidden = true; - labelSaferRestoreDefaults.hidden = true; - labelSafestRestoreDefaults.hidden = true; - - radiogroup.value = securityLevel; - - switch (securityLevel) { - case "standard": - labelStandardCustom.hidden = !securityCustom; - labelStandardRestoreDefaults.hidden = !securityCustom; - break; - case "safer": - labelSaferCustom.hidden = !securityCustom; - labelSaferRestoreDefaults.hidden = !securityCustom; - break; - case "safest": - labelSafestCustom.hidden = !securityCustom; - labelSafestRestoreDefaults.hidden = !securityCustom; - break; + this._radiogroup.value = SecurityLevelPrefs.securityLevel; + const isCustom = SecurityLevelPrefs.securityCustom; + this._radiogroup.disabled = isCustom; + this._customNotification.hidden = !isCustom; + // Have the container's selection CSS class match the selection state of the + // radio elements. + for (const { container, radio } of this._radioOptions) { + container.classList.toggle( + "securityLevel-radio-option-selected", + radio.selected + ); } },
@@ -514,17 +507,4 @@ var SecurityLevelPreferences = { break; } }, - - selectSecurityLevel() { - // radio group elements - let radiogroup = document.getElementById("securityLevel-radiogroup"); - - // update pref based on selected radio option - SecurityLevelPrefs.securityLevel = radiogroup.value; - SecurityLevelPreferences.restoreDefaults(); - }, - - restoreDefaults() { - SecurityLevelPrefs.securityCustom = false; - }, }; /* SecurityLevelPreferences */
===================================== browser/components/securitylevel/content/securityLevelPreferences.css ===================================== @@ -1,51 +1,58 @@ -label.securityLevel-customWarning { - border-radius: 4px; - background-color: var(--yellow-50); - color: black; - font-size: 1em; - height: 1.6em; - padding: 0.4em 0.5em; +#securityLevel-groupbox { + --section-highlight-background-color: color-mix(in srgb, var(--in-content-accent-color) 20%, transparent); +} + +#securityLevel-customNotification { + /* Spacing similar to #fpiIncompatibilityWarning. */ + margin-block: 16px; +} + +.info-icon.securityLevel-custom-warning-icon { + list-style-image: url("chrome://global/skin/icons/warning.svg"); +} + +#securityLevel-customHeading { + font-weight: bold; }
-radiogroup#securityLevel-radiogroup description { - color: var(--in-content-page-color)!important; +/* Overwrite indent rule from preferences.css */ +#securityLevel-radiogroup description.indent { + color: var(--in-content-page-color); }
-radiogroup#securityLevel-radiogroup radio { +#securityLevel-radiogroup radio { font-weight: bold; }
-radiogroup#securityLevel-radiogroup > vbox { +#securityLevel-radiogroup[disabled] { + opacity: 0.5; +} + +/* Overwrite the rule in common-shared.css so we don't get 0.25 opacity overall + * on the radio text. */ +#securityLevel-radiogroup[disabled] radio[disabled] { + opacity: 1.0; +} + +.securityLevel-radio-option { border: 1px solid var(--in-content-box-border-color); border-radius: 4px; margin: 3px 0; padding: 9px; }
-radiogroup#securityLevel-radiogroup[value=standard] > vbox#securityLevel-vbox-standard, -radiogroup#securityLevel-radiogroup[value=safer] > vbox#securityLevel-vbox-safer, -radiogroup#securityLevel-radiogroup[value=safest] > vbox#securityLevel-vbox-safest { - --section-highlight-background-color: color-mix(in srgb, var(--in-content-accent-color) 20%, transparent); +.securityLevel-radio-option.securityLevel-radio-option-selected { background-color: var(--section-highlight-background-color); border: 1px solid var(--in-content-accent-color);
}
-vbox.securityLevel-descriptionList { +.securityLevel-radio-option:not( + .securityLevel-radio-option-selected +) .securityLevel-descriptionList { display: none; }
-radiogroup#securityLevel-radiogroup[value=safer] vbox#securityLevel-vbox-safer vbox.securityLevel-descriptionList, -radiogroup#securityLevel-radiogroup[value=safest] vbox#securityLevel-vbox-safest vbox.securityLevel-descriptionList { - display: inherit; -} - -vbox.securityLevel-descriptionList description { +.securityLevel-descriptionList description { display: list-item; } - -vbox#securityLevel-vbox-standard, -vbox#securityLevel-vbox-safer, -vbox#securityLevel-vbox-safest { - margin-top: 0.4em; -}
===================================== browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml ===================================== @@ -2,62 +2,58 @@ data-category="panePrivacy" data-subcategory="securitylevel" hidden="true"> - <label>html:h2/</label> + <label>html:h2</html:h2></label> <vbox flex="1"> <description flex="1"> - <html:span id="securityLevel-overview" class="tail-with-learn-more"/> + <html:span id="securityLevel-overview" class="tail-with-learn-more"> + </html:span> <label id="securityLevel-learnMore" class="learnMore text-link" is="text-link" href="about:manual#security-settings" useoriginprincipal="true"/> </description> + <hbox id="securityLevel-customNotification" + class="info-box-container" + flex="1"> + <hbox class="info-icon-container"> + <image class="info-icon securityLevel-custom-warning-icon"/> + </hbox> + <vbox flex="1"> + <label id="securityLevel-customHeading"/> + <description id="securityLevel-customDescription" flex="1"/> + </vbox> + <hbox align="center"> + <button id="securityLevel-restoreDefaults"/> + </hbox> + </hbox> <radiogroup id="securityLevel-radiogroup"> - <vbox id="securityLevel-vbox-standard"> - <hbox> - <radio value="standard"/> - <vbox> - <spacer flex="1"/> - <label class="securityLevel-customWarning"/> - <spacer flex="1"/> - </vbox> - <spacer flex="1"/> - </hbox> - <description flex="1" class="indent"> - <html:span class="summary tail-with-learn-more"/> - <label class="securityLevel-restoreDefaults learnMore text-link"/> - </description> + <vbox class="securityLevel-radio-option"> + <radio value="standard" + aria-describedby="securityLevelSummary-standard"/> + <vbox id="securityLevelSummary-standard"> + <description class="summary indent" flex="1"/> + </vbox> </vbox> - <vbox id="securityLevel-vbox-safer"> - <hbox> - <radio value="safer"/> - <vbox> - <spacer flex="1"/> - <label class="securityLevel-customWarning"/> - <spacer flex="1"/> - </vbox> - </hbox> - <description flex="1" class="indent"> - <html:span class="summary tail-with-learn-more"/> - <label class="securityLevel-restoreDefaults learnMore text-link"/> - </description> - <vbox class="securityLevel-descriptionList indent"> + <vbox class="securityLevel-radio-option"> + <!-- NOTE: We point the accessible description to the wrapping vbox + - rather than its first description element. This means that when the + - securityLevel-descriptionList is shown or hidden, its text content + - is included or excluded from the accessible description, + - respectively. --> + <radio value="safer" + aria-describedby="securityLevelSummary-safer"/> + <vbox id="securityLevelSummary-safer"> + <description class="summary indent" flex="1"/> + <vbox class="securityLevel-descriptionList indent"/> </vbox> </vbox> - <vbox id="securityLevel-vbox-safest"> - <hbox> - <radio value="safest"/> - <vbox> - <spacer flex="1"/> - <label class="securityLevel-customWarning"/> - <spacer flex="1"/> - </vbox> - </hbox> - <description flex="1" class="indent"> - <html:span class="summary tail-with-learn-more"/> - <label class="securityLevel-restoreDefaults learnMore text-link"/> - </description> - <vbox class="securityLevel-descriptionList indent"> + <vbox class="securityLevel-radio-option"> + <radio value="safest" + aria-describedby="securityLevelSummary-safest"/> + <vbox id="securityLevelSummary-safest"> + <description class="summary indent" flex="1"/> + <vbox class="securityLevel-descriptionList indent"/> </vbox> </vbox> </radiogroup>
===================================== browser/components/securitylevel/locale/en-US/securityLevel.properties ===================================== @@ -13,9 +13,11 @@ security_level_learn_more = Learn more
# Panel security_level_change = Change… +security_level_change_setting = Change Setting… security_level_standard_summary = All browser and website features are enabled. security_level_safer_summary = Disables website features that are often dangerous, causing some sites to lose functionality. security_level_safest_summary = Only allows website features required for static sites and basic services. These changes affect images, media, and scripts. +security_level_custom_heading = Warning! security_level_custom_summary = Your custom browser preferences have resulted in unusual security settings. For security and privacy reasons, we recommend you choose one of the default security levels.
## Security level section in about:preferences#privacy
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/90395b29...
tbb-commits@lists.torproject.org