[tbb-commits] [Git][tpo/applications/tor-browser][tor-browser-102.6.0esr-12.5-1] fixup! Bug 40925: Implemented the Security Level component

Richard Pospesel (@richard) git at gitlab.torproject.org
Mon Jan 9 20:42:23 UTC 2023



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/90395b296772e91b9d9c4015393377a497d15778

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/commit/90395b296772e91b9d9c4015393377a497d15778
You're receiving this email because of your account on gitlab.torproject.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20230109/63f68ab7/attachment-0001.htm>


More information about the tbb-commits mailing list