morgan pushed to branch tor-browser-153.1.0esr-16.0-1 at The Tor Project / Applications / Tor Browser

Commits:

21 changed files:

Changes:

  • browser/components/preferences/config/privacy.mjs
    ... ... @@ -7,6 +7,10 @@
    7 7
     import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs";
    
    8 8
     import { Preferences } from "chrome://global/content/preferences/Preferences.mjs";
    
    9 9
     
    
    10
    +ChromeUtils.importESModule(
    
    11
    +  "chrome://browser/content/securitylevel/config/security-level.mjs",
    
    12
    +  { global: "current" }
    
    13
    +);
    
    10 14
     ChromeUtils.importESModule(
    
    11 15
       "chrome://browser/content/preferences/config/protections-from-apps.mjs",
    
    12 16
       { global: "current" }
    

  • browser/components/preferences/preferences.js
    ... ... @@ -409,6 +409,7 @@ const CONFIG_PANES = Object.freeze({
    409 409
           "ipprotection",
    
    410 410
           "cookiesAndSiteData2",
    
    411 411
           "history2",
    
    412
    +      "securityLevelGroup",
    
    412 413
           "nonTechnicalPrivacy2",
    
    413 414
           "dnsOverHttps",
    
    414 415
           "connectionLink",
    

  • browser/components/preferences/preferences.xhtml
    ... ... @@ -43,7 +43,6 @@
    43 43
         href="chrome://browser/content/preferences/letterboxing.css"
    
    44 44
       />
    
    45 45
     
    
    46
    -  <link rel="stylesheet" href="chrome://browser/content/securitylevel/securityLevelPreferences.css" />
    
    47 46
       <link rel="stylesheet" href="chrome://browser/content/torpreferences/torPreferences.css" />
    
    48 47
       <link rel="stylesheet" href="chrome://browser/content/onionservices/authPreferences.css" />
    
    49 48
     
    
    ... ... @@ -108,6 +107,8 @@
    108 107
       <script type="module" src="chrome://browser/content/preferences/widgets/update-information.mjs"></script>
    
    109 108
       <script type="module" src="chrome://browser/content/preferences/widgets/update-state.mjs"></script>
    
    110 109
       <script type="module" src="chrome://browser/content/ipprotection/bandwidth-usage.mjs"></script>
    
    110
    +  <script type="module" src="chrome://browser/content/securitylevel/widgets/security-level-description.mjs"></script>
    
    111
    +  <script type="module" src="chrome://browser/content/securitylevel/widgets/security-level-display.mjs"></script>
    
    111 112
       <script type="module" src="chrome://browser/content/torpreferences/widgets/tor-bridges-display.mjs"></script>
    
    112 113
       <script type="module" src="chrome://browser/content/torpreferences/widgets/tor-connection-assist-banner.mjs"></script>
    
    113 114
       <script type="module" src="chrome://browser/content/torpreferences/widgets/tor-connection-status.mjs"></script>
    

  • browser/components/preferences/privacy.inc.xhtml
    ... ... @@ -579,7 +579,7 @@
    579 579
       <html:h1 data-l10n-id="security-header"/>
    
    580 580
     </hbox>
    
    581 581
     
    
    582
    -#include ../securitylevel/content/securityLevelPreferences.inc.xhtml
    
    582
    +<html:setting-group groupid="securityLevelGroup" data-category="panePrivacy" hidden="true" data-srd-migrated=""></html:setting-group>
    
    583 583
     
    
    584 584
     <!-- addons, forgery (phishing) UI Security -->
    
    585 585
     <html:setting-group groupid="browsingProtection" data-category="panePrivacy" hidden="true" data-srd-migrated=""></html:setting-group>
    

  • browser/components/preferences/privacy.js
    ... ... @@ -60,13 +60,6 @@ ChromeUtils.defineLazyGetter(lazy, "gParentalControlsService", () =>
    60 60
         : null
    
    61 61
     );
    
    62 62
     
    
    63
    -// TODO: module import via ChromeUtils.defineModuleGetter
    
    64
    -XPCOMUtils.defineLazyScriptGetter(
    
    65
    -  this,
    
    66
    -  ["SecurityLevelPreferences"],
    
    67
    -  "chrome://browser/content/securitylevel/securityLevel.js"
    
    68
    -);
    
    69
    -
    
    70 63
     XPCOMUtils.defineLazyPreferenceGetter(
    
    71 64
       this,
    
    72 65
       "gIsFirstPartyIsolated",
    
    ... ... @@ -150,16 +143,6 @@ function initTCPStandardSection() {
    150 143
     var gPrivacyPane = {
    
    151 144
       _pane: null,
    
    152 145
     
    
    153
    -  /**
    
    154
    -   * Show the Security Level UI
    
    155
    -   */
    
    156
    -  _initSecurityLevel() {
    
    157
    -    SecurityLevelPreferences.init();
    
    158
    -    window.addEventListener("unload", () => SecurityLevelPreferences.uninit(), {
    
    159
    -      once: true,
    
    160
    -    });
    
    161
    -  },
    
    162
    -
    
    163 146
       /**
    
    164 147
        * Whether the prompt to restart Firefox should appear when changing the autostart pref.
    
    165 148
        */
    
    ... ... @@ -654,6 +637,7 @@ var gPrivacyPane = {
    654 637
         initSettingGroup("etpReset");
    
    655 638
         initSettingGroup("etpCustomize");
    
    656 639
         initSettingGroup("networkProxy");
    
    640
    +    initSettingGroup("securityLevelGroup");
    
    657 641
     
    
    658 642
         /* Initialize Content Blocking */
    
    659 643
         this.initContentBlocking();
    
    ... ... @@ -663,7 +647,6 @@ var gPrivacyPane = {
    663 647
         this.networkCookieBehaviorReadPrefs();
    
    664 648
         this._initTrackingProtectionExtensionControl();
    
    665 649
         this._ensureTrackingProtectionExceptionListMigration();
    
    666
    -    this._initSecurityLevel();
    
    667 650
     
    
    668 651
         Preferences.get("privacy.trackingprotection.enabled").on(
    
    669 652
           "change",
    

  • browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs deleted
    1
    -/**
    
    2
    - * Common methods for the desktop security level components.
    
    3
    - */
    
    4
    -export const SecurityLevelUIUtils = {
    
    5
    -  /**
    
    6
    -   * Create an element that gives a description of the security level. To be
    
    7
    -   * used in the settings.
    
    8
    -   *
    
    9
    -   * @param {string} level - The security level to describe.
    
    10
    -   * @param {Document} doc - The document where the element will be inserted.
    
    11
    -   *
    
    12
    -   * @returns {Element} - The newly created element.
    
    13
    -   */
    
    14
    -  createDescriptionElement(level, doc) {
    
    15
    -    const el = doc.createElement("div");
    
    16
    -    el.classList.add("security-level-description");
    
    17
    -
    
    18
    -    let l10nIdSummary;
    
    19
    -    let bullets;
    
    20
    -    switch (level) {
    
    21
    -      case "standard":
    
    22
    -        l10nIdSummary = "security-level-summary-standard";
    
    23
    -        break;
    
    24
    -      case "safer":
    
    25
    -        l10nIdSummary = "security-level-summary-safer";
    
    26
    -        bullets = [
    
    27
    -          "security-level-preferences-bullet-https-only-javascript",
    
    28
    -          "security-level-preferences-bullet-limit-font-and-symbols",
    
    29
    -          "security-level-preferences-bullet-limit-media",
    
    30
    -        ];
    
    31
    -        break;
    
    32
    -      case "safest":
    
    33
    -        l10nIdSummary = "security-level-summary-safest";
    
    34
    -        bullets = [
    
    35
    -          "security-level-preferences-bullet-disabled-javascript",
    
    36
    -          "security-level-preferences-bullet-limit-font-and-symbols-and-images",
    
    37
    -          "security-level-preferences-bullet-limit-media",
    
    38
    -        ];
    
    39
    -        break;
    
    40
    -      case "custom":
    
    41
    -        l10nIdSummary = "security-level-summary-custom";
    
    42
    -        break;
    
    43
    -      default:
    
    44
    -        throw Error(`Unhandled level: ${level}`);
    
    45
    -    }
    
    46
    -
    
    47
    -    const summaryEl = doc.createElement("div");
    
    48
    -    summaryEl.classList.add("security-level-summary");
    
    49
    -    doc.l10n.setAttributes(summaryEl, l10nIdSummary);
    
    50
    -
    
    51
    -    el.append(summaryEl);
    
    52
    -
    
    53
    -    if (!bullets) {
    
    54
    -      return el;
    
    55
    -    }
    
    56
    -
    
    57
    -    const listEl = doc.createElement("ul");
    
    58
    -    listEl.classList.add("security-level-description-extra");
    
    59
    -    // Add a mozilla styling class as well:
    
    60
    -    listEl.classList.add("privacy-extra-information");
    
    61
    -    for (const l10nId of bullets) {
    
    62
    -      const bulletEl = doc.createElement("li");
    
    63
    -      bulletEl.classList.add("security-level-description-bullet");
    
    64
    -
    
    65
    -      doc.l10n.setAttributes(bulletEl, l10nId);
    
    66
    -
    
    67
    -      listEl.append(bulletEl);
    
    68
    -    }
    
    69
    -
    
    70
    -    el.append(listEl);
    
    71
    -    return el;
    
    72
    -  },
    
    73
    -};

  • browser/components/securitylevel/config/security-level.mjs
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +import { SettingGroupManager } from "chrome://browser/content/preferences/config/SettingGroupManager.mjs";
    
    6
    +import { Preferences } from "chrome://global/content/preferences/Preferences.mjs";
    
    7
    +
    
    8
    +const lazy = {};
    
    9
    +
    
    10
    +ChromeUtils.defineESModuleGetters(lazy, {
    
    11
    +  SecurityLevelPrefs:
    
    12
    +    "moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs",
    
    13
    +});
    
    14
    +
    
    15
    +SettingGroupManager.registerGroups({
    
    16
    +  securityLevelGroup: {
    
    17
    +    subcategory: "securitylevel",
    
    18
    +    l10nId: "security-level-settings-group",
    
    19
    +    headingLevel: 2,
    
    20
    +    supportPage: "tor-manual:features__security-levels",
    
    21
    +    items: [
    
    22
    +      {
    
    23
    +        id: "securityLevelBoxGroup",
    
    24
    +        control: "moz-box-group",
    
    25
    +        items: [
    
    26
    +          {
    
    27
    +            id: "securityLevelCurrent",
    
    28
    +            control: "security-level-display",
    
    29
    +          },
    
    30
    +          {
    
    31
    +            id: "securityLevelChangeButton",
    
    32
    +            l10nId: "security-level-settings-change-button",
    
    33
    +            control: "moz-box-button",
    
    34
    +          },
    
    35
    +        ],
    
    36
    +      },
    
    37
    +    ],
    
    38
    +  },
    
    39
    +});
    
    40
    +
    
    41
    +Preferences.addSetting({
    
    42
    +  id: "securityLevelCurrent",
    
    43
    +  setup(emitChange) {
    
    44
    +    Services.prefs.addObserver(
    
    45
    +      "browser.security_level.security_slider",
    
    46
    +      emitChange
    
    47
    +    );
    
    48
    +    Services.prefs.addObserver(
    
    49
    +      "browser.security_level.security_custom",
    
    50
    +      emitChange
    
    51
    +    );
    
    52
    +
    
    53
    +    return () => {
    
    54
    +      Services.prefs.removeObserver(
    
    55
    +        "browser.security_level.security_slider",
    
    56
    +        emitChange
    
    57
    +      );
    
    58
    +      Services.prefs.removeObserver(
    
    59
    +        "browser.security_level.security_custom",
    
    60
    +        emitChange
    
    61
    +      );
    
    62
    +    };
    
    63
    +  },
    
    64
    +  get: () => {
    
    65
    +    return lazy.SecurityLevelPrefs.securityLevelSummary;
    
    66
    +  },
    
    67
    +});
    
    68
    +
    
    69
    +Preferences.addSetting({
    
    70
    +  id: "securityLevelBoxGroup",
    
    71
    +});
    
    72
    +
    
    73
    +Preferences.addSetting({
    
    74
    +  id: "securityLevelChangeButton",
    
    75
    +  onUserClick() {
    
    76
    +    window.gSubDialog.open(
    
    77
    +      "chrome://browser/content/securitylevel/securityLevelDialog.xhtml",
    
    78
    +      { features: "resizable=yes" }
    
    79
    +    );
    
    80
    +  },
    
    81
    +});

  • browser/components/securitylevel/content/securityLevel.js
    ... ... @@ -5,8 +5,6 @@
    5 5
     ChromeUtils.defineESModuleGetters(this, {
    
    6 6
       SecurityLevelPrefs:
    
    7 7
         "moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs",
    
    8
    -  SecurityLevelUIUtils:
    
    9
    -    "moz-src:///browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs",
    
    10 8
     });
    
    11 9
     
    
    12 10
     /*
    
    ... ... @@ -263,103 +261,3 @@ var SecurityLevelPanel = {
    263 261
         }
    
    264 262
       },
    
    265 263
     }; /* SecurityLevelPanel */
    266
    -
    
    267
    -/*
    
    268
    -  Security Level Preferences Code
    
    269
    -
    
    270
    -  Code to handle init and update of security level section in about:preferences#privacy
    
    271
    -*/
    
    272
    -
    
    273
    -var SecurityLevelPreferences = {
    
    274
    -  _securityPrefsBranch: null,
    
    275
    -
    
    276
    -  /**
    
    277
    -   * The element that shows the current security level.
    
    278
    -   *
    
    279
    -   * @type {?Element}
    
    280
    -   */
    
    281
    -  _currentEl: null,
    
    282
    -
    
    283
    -  _populateXUL() {
    
    284
    -    this._currentEl = document.getElementById("security-level-current");
    
    285
    -    const changeButton = document.getElementById("security-level-change");
    
    286
    -    const badgeEl = this._currentEl.querySelector(
    
    287
    -      ".security-level-current-badge"
    
    288
    -    );
    
    289
    -
    
    290
    -    for (const { level, nameId } of [
    
    291
    -      { level: "standard", nameId: "security-level-panel-level-standard" },
    
    292
    -      { level: "safer", nameId: "security-level-panel-level-safer" },
    
    293
    -      { level: "safest", nameId: "security-level-panel-level-safest" },
    
    294
    -      { level: "custom", nameId: "security-level-panel-level-custom" },
    
    295
    -    ]) {
    
    296
    -      // Classes that control visibility:
    
    297
    -      // security-level-current-standard
    
    298
    -      // security-level-current-safer
    
    299
    -      // security-level-current-safest
    
    300
    -      // security-level-current-custom
    
    301
    -      const visibilityClass = `security-level-current-${level}`;
    
    302
    -      const nameEl = document.createElement("div");
    
    303
    -      nameEl.classList.add("security-level-name", visibilityClass);
    
    304
    -      document.l10n.setAttributes(nameEl, nameId);
    
    305
    -
    
    306
    -      const descriptionEl = SecurityLevelUIUtils.createDescriptionElement(
    
    307
    -        level,
    
    308
    -        document
    
    309
    -      );
    
    310
    -      descriptionEl.classList.add(visibilityClass);
    
    311
    -
    
    312
    -      this._currentEl.insertBefore(nameEl, badgeEl);
    
    313
    -      this._currentEl.insertBefore(descriptionEl, changeButton);
    
    314
    -    }
    
    315
    -
    
    316
    -    changeButton.addEventListener("click", () => {
    
    317
    -      this._openDialog();
    
    318
    -    });
    
    319
    -  },
    
    320
    -
    
    321
    -  _openDialog() {
    
    322
    -    gSubDialog.open(
    
    323
    -      "chrome://browser/content/securitylevel/securityLevelDialog.xhtml",
    
    324
    -      { features: "resizable=yes" }
    
    325
    -    );
    
    326
    -  },
    
    327
    -
    
    328
    -  _configUIFromPrefs() {
    
    329
    -    // Set a data-current-level attribute for showing the current security
    
    330
    -    // level, and hiding the rest.
    
    331
    -    this._currentEl.dataset.currentLevel =
    
    332
    -      SecurityLevelPrefs.securityLevelSummary;
    
    333
    -  },
    
    334
    -
    
    335
    -  init() {
    
    336
    -    // populate XUL with localized strings
    
    337
    -    this._populateXUL();
    
    338
    -
    
    339
    -    // read prefs and populate UI
    
    340
    -    this._configUIFromPrefs();
    
    341
    -
    
    342
    -    // register for pref chagnes
    
    343
    -    this._securityPrefsBranch = Services.prefs.getBranch(
    
    344
    -      "browser.security_level."
    
    345
    -    );
    
    346
    -    this._securityPrefsBranch.addObserver("", this);
    
    347
    -  },
    
    348
    -
    
    349
    -  uninit() {
    
    350
    -    // unregister for pref change events
    
    351
    -    this._securityPrefsBranch.removeObserver("", this);
    
    352
    -    this._securityPrefsBranch = null;
    
    353
    -  },
    
    354
    -
    
    355
    -  // callback for when prefs change
    
    356
    -  observe(subject, topic, data) {
    
    357
    -    switch (topic) {
    
    358
    -      case "nsPref:changed":
    
    359
    -        if (data == "security_slider" || data == "security_custom") {
    
    360
    -          this._configUIFromPrefs();
    
    361
    -        }
    
    362
    -        break;
    
    363
    -    }
    
    364
    -  },
    
    365
    -}; /* SecurityLevelPreferences */

  • browser/components/securitylevel/content/securityLevelDialog.css
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +/* Hack to gain the internal styling of <moz-badge>.
    
    6
    + * TODO: Drop this once we can use moz-badge. tor-browser#45229. */
    
    7
    +@import url("chrome://global/content/elements/moz-badge.css");
    
    8
    +
    
    9
    +#security-level-radiogroup {
    
    10
    +  margin-block: var(--space-large) var(--space-xlarge);
    
    11
    +}
    
    12
    +
    
    13
    +.security-level-radio-label {
    
    14
    +  display: inline flex;
    
    15
    +  gap: var(--space-small);
    
    16
    +}
    
    17
    +
    
    18
    +.security-level-radio-label .moz-badge-label > span {
    
    19
    +  /* Still accessible to screen reader, but not visual.
    
    20
    +   * Keep inline, but with no layout width. */
    
    21
    +  display: inline-block;
    
    22
    +  width: 1px;
    
    23
    +  margin-inline-end: -1px;
    
    24
    +  clip-path: inset(50%);
    
    25
    +}
    
    26
    +
    
    27
    +.moz-badge[hidden] {
    
    28
    +  display: none;
    
    29
    +}

  • browser/components/securitylevel/content/securityLevelDialog.js
    ... ... @@ -3,9 +3,6 @@
    3 3
     const { SecurityLevelPrefs } = ChromeUtils.importESModule(
    
    4 4
       "moz-src:///toolkit/components/securitylevel/SecurityLevel.sys.mjs"
    
    5 5
     );
    
    6
    -const { SecurityLevelUIUtils } = ChromeUtils.importESModule(
    
    7
    -  "moz-src:///browser/components/securitylevel/SecurityLevelUIUtils.sys.mjs"
    
    8
    -);
    
    9 6
     
    
    10 7
     const gSecurityLevelDialog = {
    
    11 8
       /**
    
    ... ... @@ -27,9 +24,9 @@ const gSecurityLevelDialog = {
    27 24
        */
    
    28 25
       _radiogroup: null,
    
    29 26
       /**
    
    30
    -   * A list of radio options and their containers.
    
    27
    +   * A list of radio options and their descriptions.
    
    31 28
        *
    
    32
    -   * @type {?Array<{ container: Element, radio: Element }>}
    
    29
    +   * @type {?Array<{ description: Element, radio: Element }>}
    
    33 30
        */
    
    34 31
       _radioOptions: null,
    
    35 32
     
    
    ... ... @@ -56,85 +53,42 @@ const gSecurityLevelDialog = {
    56 53
         this._radiogroup = document.getElementById("security-level-radiogroup");
    
    57 54
     
    
    58 55
         this._radioOptions = Array.from(
    
    59
    -      this._radiogroup.querySelectorAll(".security-level-radio-container"),
    
    60
    -      container => {
    
    61
    -        return {
    
    62
    -          container,
    
    63
    -          radio: container.querySelector(".security-level-radio"),
    
    64
    -        };
    
    56
    +      this._radiogroup.querySelectorAll("moz-radio"),
    
    57
    +      radio => {
    
    58
    +        const description = radio.querySelector("security-level-description");
    
    59
    +        // Hide bullets by default.
    
    60
    +        description.hideBullets = true;
    
    61
    +        return { radio, description };
    
    65 62
           }
    
    66 63
         );
    
    67 64
     
    
    68
    -    for (const { container, radio } of this._radioOptions) {
    
    69
    -      const level = radio.value;
    
    70
    -      radio.id = `security-level-radio-${level}`;
    
    71
    -      const currentEl = container.querySelector(
    
    72
    -        ".security-level-current-badge"
    
    73
    -      );
    
    74
    -      currentEl.id = `security-level-current-badge-${level}`;
    
    75
    -      const descriptionEl = SecurityLevelUIUtils.createDescriptionElement(
    
    76
    -        level,
    
    77
    -        document
    
    78
    -      );
    
    79
    -      descriptionEl.classList.add("indent");
    
    80
    -      descriptionEl.id = `security-level-description-${level}`;
    
    81
    -
    
    82
    -      // Wait for the full translation of the element before adding it to the
    
    83
    -      // DOM. In particular, we want to make sure the elements have text before
    
    84
    -      // we measure the maxHeight below.
    
    85
    -      await document.l10n.translateFragment(descriptionEl);
    
    86
    -      document.l10n.pauseObserving();
    
    87
    -      container.append(descriptionEl);
    
    88
    -      document.l10n.resumeObserving();
    
    89
    -
    
    90
    -      if (level === this._prevLevel) {
    
    91
    -        currentEl.hidden = false;
    
    92
    -        // When the currentEl is visible, include it in the accessible name for
    
    93
    -        // the radio option.
    
    94
    -        // NOTE: The currentEl has an accessible name which includes punctuation
    
    95
    -        // to help separate it's content from the security level name.
    
    96
    -        // E.g. "Standard (Current level)".
    
    97
    -        radio.setAttribute("aria-labelledby", `${radio.id} ${currentEl.id}`);
    
    98
    -      } else {
    
    99
    -        currentEl.hidden = true;
    
    100
    -      }
    
    101
    -      // We point the accessible description to the wrapping
    
    102
    -      // .security-level-description element, rather than its children
    
    103
    -      // that define the actual text content. This means that when the
    
    104
    -      // privacy-extra-information is shown or hidden, its text content is
    
    105
    -      // included or excluded from the accessible description, respectively.
    
    106
    -      radio.setAttribute("aria-describedby", descriptionEl.id);
    
    65
    +    for (const { radio } of this._radioOptions) {
    
    66
    +      radio.querySelector(".moz-badge").hidden =
    
    67
    +        radio.value !== this._prevLevel;
    
    107 68
         }
    
    108 69
     
    
    109
    -    // We want to reserve the maximum height of the radiogroup so that the
    
    70
    +    // We want to reserve the maximum height of the moz-radio-group so that the
    
    110 71
         // dialog has enough height when the user switches options. So we cycle
    
    111 72
         // through the options and measure the height when they are selected to set
    
    112 73
         // a minimum height that fits all of them.
    
    113
    -    // NOTE: At the time of implementation, at this point the dialog may not
    
    114
    -    // yet have the "subdialog" attribute, which means it is missing the
    
    115
    -    // common.css stylesheet from its shadow root, which effects the size of the
    
    116
    -    // .radio-check element and the font. Therefore, we have duplicated the
    
    117
    -    // import of common.css in SecurityLevelDialog.xhtml to ensure it is applied
    
    118
    -    // at this earlier stage.
    
    119 74
         let maxHeight = 0;
    
    120
    -    for (const { container } of this._radioOptions) {
    
    121
    -      container.classList.add("selected");
    
    75
    +    for (const { description } of this._radioOptions) {
    
    76
    +      description.hideBullets = false;
    
    77
    +      await this._settled();
    
    122 78
           maxHeight = Math.max(
    
    123 79
             maxHeight,
    
    124 80
             this._radiogroup.getBoundingClientRect().height
    
    125 81
           );
    
    126
    -      container.classList.remove("selected");
    
    82
    +      description.hideBullets = true;
    
    127 83
         }
    
    128 84
         this._radiogroup.style.minHeight = `${maxHeight}px`;
    
    129 85
     
    
    130 86
         if (this._prevLevel !== "custom") {
    
    131 87
           this._selectedLevel = this._prevLevel;
    
    132 88
           this._radiogroup.value = this._prevLevel;
    
    133
    -    } else {
    
    134
    -      this._radiogroup.selectedItem = null;
    
    135 89
         }
    
    136 90
     
    
    137
    -    this._radiogroup.addEventListener("select", () => {
    
    91
    +    this._radiogroup.addEventListener("change", () => {
    
    138 92
           this._selectedLevel = this._radiogroup.value;
    
    139 93
           this._updateSelected();
    
    140 94
         });
    
    ... ... @@ -142,16 +96,31 @@ const gSecurityLevelDialog = {
    142 96
         this._updateSelected();
    
    143 97
       },
    
    144 98
     
    
    99
    +  /**
    
    100
    +   * Wait for the DOM to be settled after some change.
    
    101
    +   */
    
    102
    +  async _settled() {
    
    103
    +    // Wait for the widgets to react to some change.
    
    104
    +    await Promise.all([
    
    105
    +      this._radiogroup.updateComplete,
    
    106
    +      ...this._radioOptions.map(({ radio }) => radio.updateComplete),
    
    107
    +    ]);
    
    108
    +    // Also wait for any string population.
    
    109
    +    if (document.hasPendingL10nMutations) {
    
    110
    +      await new Promise(r =>
    
    111
    +        document.addEventListener("L10nMutationsFinished", r, { once: true })
    
    112
    +      );
    
    113
    +    }
    
    114
    +  },
    
    115
    +
    
    145 116
       /**
    
    146 117
        * Update the UI in response to a change in selection.
    
    147 118
        */
    
    148 119
       _updateSelected() {
    
    149 120
         this._acceptButton.disabled =
    
    150 121
           !this._selectedLevel || this._selectedLevel === this._prevLevel;
    
    151
    -    // Have the container's `selected` CSS class match the selection state of
    
    152
    -    // the radio elements.
    
    153
    -    for (const { container, radio } of this._radioOptions) {
    
    154
    -      container.classList.toggle("selected", radio.selected);
    
    122
    +    for (const { description, radio } of this._radioOptions) {
    
    123
    +      description.hideBullets = !radio.checked;
    
    155 124
         }
    
    156 125
       },
    
    157 126
     
    

  • browser/components/securitylevel/content/securityLevelDialog.xhtml
    ... ... @@ -10,18 +10,6 @@
    10 10
       <dialog id="security-level-dialog" buttons="accept,cancel">
    
    11 11
         <linkset>
    
    12 12
           <html:link rel="stylesheet" href="chrome://global/skin/global.css" />
    
    13
    -      <!-- NOTE: We include common.css explicitly, rather than relying on
    
    14
    -         - the dialog's shadowroot importing it, which is late loaded in
    
    15
    -         - response to the dialog's "subdialog" attribute, which is set
    
    16
    -         - in response to DOMFrameContentLoaded.
    
    17
    -         - In particular, we need the .radio-check rule and font rules from
    
    18
    -         - common-shared.css to be in place when gSecurityLevelDialog.init is
    
    19
    -         - called, which will help ensure that the radio element has the correct
    
    20
    -         - size when we measure its bounding box. -->
    
    21
    -      <html:link
    
    22
    -        rel="stylesheet"
    
    23
    -        href="chrome://global/skin/in-content/common.css"
    
    24
    -      />
    
    25 13
           <html:link
    
    26 14
             rel="stylesheet"
    
    27 15
             href="chrome://browser/skin/preferences/preferences.css"
    
    ... ... @@ -32,57 +20,77 @@
    32 20
           />
    
    33 21
           <html:link
    
    34 22
             rel="stylesheet"
    
    35
    -        href="chrome://browser/content/securitylevel/securityLevelPreferences.css"
    
    23
    +        href="chrome://browser/content/securitylevel/securityLevelDialog.css"
    
    36 24
           />
    
    37 25
     
    
    38 26
           <html:link rel="localization" href="branding/brand.ftl" />
    
    39 27
           <html:link rel="localization" href="toolkit/global/base-browser.ftl" />
    
    40 28
         </linkset>
    
    41 29
     
    
    30
    +    <html:script
    
    31
    +      type="module"
    
    32
    +      src="chrome://global/content/elements/moz-radio-group.mjs"
    
    33
    +    ></html:script>
    
    34
    +    <html:script
    
    35
    +      type="module"
    
    36
    +      src="chrome://browser/content/securitylevel/widgets/security-level-description.mjs"
    
    37
    +    ></html:script>
    
    42 38
         <script src="chrome://browser/content/securitylevel/securityLevelDialog.js" />
    
    43 39
     
    
    44 40
         <description data-l10n-id="security-level-dialog-restart-description" />
    
    45 41
     
    
    46
    -    <radiogroup id="security-level-radiogroup" class="highlighting-group">
    
    47
    -      <html:div
    
    48
    -        class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
    
    49
    -      >
    
    50
    -        <radio
    
    51
    -          class="security-level-radio security-level-name"
    
    42
    +    <moz-radio-group
    
    43
    +      xmlns="http://www.w3.org/1999/xhtml"
    
    44
    +      id="security-level-radiogroup"
    
    45
    +      data-l10n-id="security-level-dialog-radio-group"
    
    46
    +    >
    
    47
    +      <moz-radio value="standard" use-label-slot="">
    
    48
    +        <span class="security-level-radio-label" slot="label">
    
    49
    +          <span data-l10n-id="security-level-panel-level-standard"></span>
    
    50
    +          <!-- TODO: Use <moz-badge> widget once bugzilla bug 2065204 is
    
    51
    +             - resolved. See tor-browser#45229. -->
    
    52
    +          <span class="moz-badge" hidden="hidden">
    
    53
    +            <span
    
    54
    +              class="moz-badge-label"
    
    55
    +              data-l10n-id="security-level-preferences-current-badge"
    
    56
    +            ></span>
    
    57
    +          </span>
    
    58
    +        </span>
    
    59
    +        <security-level-description
    
    60
    +          slot="description"
    
    52 61
               value="standard"
    
    53
    -          data-l10n-id="security-level-preferences-level-standard"
    
    54
    -        />
    
    55
    -        <html:div
    
    56
    -          class="security-level-current-badge"
    
    57
    -          data-l10n-id="security-level-preferences-current-badge"
    
    58
    -        ></html:div>
    
    59
    -      </html:div>
    
    60
    -      <html:div
    
    61
    -        class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
    
    62
    -      >
    
    63
    -        <radio
    
    64
    -          class="security-level-radio security-level-name"
    
    62
    +        ></security-level-description>
    
    63
    +      </moz-radio>
    
    64
    +      <moz-radio value="safer" use-label-slot="">
    
    65
    +        <span class="security-level-radio-label" slot="label">
    
    66
    +          <span data-l10n-id="security-level-panel-level-safer"></span>
    
    67
    +          <span class="moz-badge" hidden="hidden">
    
    68
    +            <span
    
    69
    +              class="moz-badge-label"
    
    70
    +              data-l10n-id="security-level-preferences-current-badge"
    
    71
    +            ></span>
    
    72
    +          </span>
    
    73
    +        </span>
    
    74
    +        <security-level-description
    
    75
    +          slot="description"
    
    65 76
               value="safer"
    
    66
    -          data-l10n-id="security-level-preferences-level-safer"
    
    67
    -        />
    
    68
    -        <html:div
    
    69
    -          class="security-level-current-badge"
    
    70
    -          data-l10n-id="security-level-preferences-current-badge"
    
    71
    -        ></html:div>
    
    72
    -      </html:div>
    
    73
    -      <html:div
    
    74
    -        class="security-level-radio-container security-level-grid privacy-detailedoption info-box-container"
    
    75
    -      >
    
    76
    -        <radio
    
    77
    -          class="security-level-radio security-level-name"
    
    77
    +        ></security-level-description>
    
    78
    +      </moz-radio>
    
    79
    +      <moz-radio value="safest" use-label-slot="">
    
    80
    +        <span class="security-level-radio-label" slot="label">
    
    81
    +          <span data-l10n-id="security-level-panel-level-safest"></span>
    
    82
    +          <span class="moz-badge" hidden="hidden">
    
    83
    +            <span
    
    84
    +              class="moz-badge-label"
    
    85
    +              data-l10n-id="security-level-preferences-current-badge"
    
    86
    +            ></span>
    
    87
    +          </span>
    
    88
    +        </span>
    
    89
    +        <security-level-description
    
    90
    +          slot="description"
    
    78 91
               value="safest"
    
    79
    -          data-l10n-id="security-level-preferences-level-safest"
    
    80
    -        />
    
    81
    -        <html:div
    
    82
    -          class="security-level-current-badge"
    
    83
    -          data-l10n-id="security-level-preferences-current-badge"
    
    84
    -        ></html:div>
    
    85
    -      </html:div>
    
    86
    -    </radiogroup>
    
    92
    +        ></security-level-description>
    
    93
    +      </moz-radio>
    
    94
    +    </moz-radio-group>
    
    87 95
       </dialog>
    
    88 96
     </window>

  • browser/components/securitylevel/content/securityLevelPreferences.css deleted
    1
    -.security-level-grid {
    
    2
    -  display: grid;
    
    3
    -  grid-template:
    
    4
    -    "icon name badge button" min-content
    
    5
    -    "icon summary summary button" auto
    
    6
    -    "icon extra extra ." auto
    
    7
    -    / max-content max-content 1fr max-content;
    
    8
    -}
    
    9
    -
    
    10
    -.security-level-icon {
    
    11
    -  grid-area: icon;
    
    12
    -  align-self: start;
    
    13
    -  width: var(--icon-size-large);
    
    14
    -  height: var(--icon-size-large);
    
    15
    -  -moz-context-properties: fill, stroke;
    
    16
    -  fill: var(--icon-color);
    
    17
    -  stroke: var(--icon-color-warning);
    
    18
    -  margin-block-start: var(--space-xsmall);
    
    19
    -  margin-inline-end: var(--space-large);
    
    20
    -}
    
    21
    -
    
    22
    -:-moz-locale-dir(rtl) .security-level-icon {
    
    23
    -  transform: scaleX(-1);
    
    24
    -}
    
    25
    -
    
    26
    -.security-level-current-badge {
    
    27
    -  grid-area: badge;
    
    28
    -  align-self: center;
    
    29
    -  justify-self: start;
    
    30
    -  white-space: nowrap;
    
    31
    -  background: var(--background-color-information);
    
    32
    -  color: inherit;
    
    33
    -  font-size: var(--font-size-small);
    
    34
    -  border-radius: var(--border-radius-circle);
    
    35
    -  margin-inline-start: var(--space-small);
    
    36
    -  padding-block: var(--space-xsmall);
    
    37
    -  padding-inline: var(--space-small);
    
    38
    -}
    
    39
    -
    
    40
    -.security-level-current-badge span {
    
    41
    -  /* Still accessible to screen reader, but not visual.
    
    42
    -   * Keep inline, but with no layout width. */
    
    43
    -  display: inline-block;
    
    44
    -  width: 1px;
    
    45
    -  margin-inline-end: -1px;
    
    46
    -  clip-path: inset(50%);
    
    47
    -}
    
    48
    -
    
    49
    -@media (prefers-contrast) and (not (forced-colors)) {
    
    50
    -  .security-level-current-badge {
    
    51
    -    /* Match the checkbox/radio colors. */
    
    52
    -    background: var(--color-accent-primary);
    
    53
    -    color: var(--button-text-color-primary);
    
    54
    -  }
    
    55
    -}
    
    56
    -
    
    57
    -@media (forced-colors) {
    
    58
    -  .security-level-current-badge {
    
    59
    -    /* Match the checkbox/radio/selected colors. */
    
    60
    -    background: SelectedItem;
    
    61
    -    color: SelectedItemText;
    
    62
    -  }
    
    63
    -}
    
    64
    -
    
    65
    -.security-level-name {
    
    66
    -  grid-area: name;
    
    67
    -  font-weight: var(--font-weight-bold);
    
    68
    -  align-self: center;
    
    69
    -  white-space: nowrap;
    
    70
    -}
    
    71
    -
    
    72
    -.security-level-description {
    
    73
    -  display: grid;
    
    74
    -  grid-column: summary-start / extra-end;
    
    75
    -  grid-row: summary-start / extra-end;
    
    76
    -  grid-template-rows: subgrid;
    
    77
    -  grid-template-columns: subgrid;
    
    78
    -  margin-block-start: var(--space-small);
    
    79
    -}
    
    80
    -
    
    81
    -.security-level-summary {
    
    82
    -  grid-area: summary;
    
    83
    -}
    
    84
    -
    
    85
    -.security-level-description-extra {
    
    86
    -  grid-area: extra;
    
    87
    -  margin-block: var(--space-medium) 0;
    
    88
    -  margin-inline: var(--space-large) 0;
    
    89
    -  padding: 0;
    
    90
    -}
    
    91
    -
    
    92
    -.security-level-description-bullet:not(:last-child) {
    
    93
    -  margin-block-end: var(--space-medium);
    
    94
    -}
    
    95
    -
    
    96
    -/* Tweak current security level display. */
    
    97
    -
    
    98
    -#security-level-current {
    
    99
    -  margin-block-start: var(--space-large);
    
    100
    -  background: var(--background-color-box);
    
    101
    -  border: var(--border-width) solid var(--border-color);
    
    102
    -  border-radius: var(--border-radius-small);
    
    103
    -  padding: var(--space-medium);
    
    104
    -}
    
    105
    -
    
    106
    -#security-level-change {
    
    107
    -  grid-area: button;
    
    108
    -  align-self: center;
    
    109
    -  margin: 0;
    
    110
    -  margin-inline-start: var(--space-large);
    
    111
    -}
    
    112
    -
    
    113
    -/* Adjust which content is visible depending on the current security level. */
    
    114
    -
    
    115
    -#security-level-current:not([data-current-level="standard"]) .security-level-current-standard {
    
    116
    -  display: none;
    
    117
    -}
    
    118
    -
    
    119
    -#security-level-current:not([data-current-level="safer"]) .security-level-current-safer {
    
    120
    -  display: none;
    
    121
    -}
    
    122
    -
    
    123
    -#security-level-current:not([data-current-level="safest"]) .security-level-current-safest {
    
    124
    -  display: none;
    
    125
    -}
    
    126
    -
    
    127
    -#security-level-current:not([data-current-level="custom"]) .security-level-current-custom {
    
    128
    -  display: none;
    
    129
    -}
    
    130
    -
    
    131
    -#security-level-current[data-current-level="standard"] .security-level-icon {
    
    132
    -  content: url("chrome://browser/content/securitylevel/security-level-standard.svg");
    
    133
    -}
    
    134
    -
    
    135
    -#security-level-current[data-current-level="safer"] .security-level-icon {
    
    136
    -  content: url("chrome://browser/content/securitylevel/security-level-safer.svg");
    
    137
    -}
    
    138
    -
    
    139
    -#security-level-current[data-current-level="safest"] .security-level-icon {
    
    140
    -  content: url("chrome://browser/content/securitylevel/security-level-safest.svg");
    
    141
    -}
    
    142
    -
    
    143
    -#security-level-current[data-current-level="custom"] .security-level-icon {
    
    144
    -  content: url("chrome://browser/content/securitylevel/security-level-custom.svg");
    
    145
    -}
    
    146
    -
    
    147
    -/* Tweak security level dialog. */
    
    148
    -
    
    149
    -#security-level-radiogroup {
    
    150
    -  margin-block: var(--space-large) var(--space-xlarge);
    
    151
    -}
    
    152
    -
    
    153
    -.security-level-radio-container {
    
    154
    -  padding-block: var(--space-large);
    
    155
    -}
    
    156
    -
    
    157
    -#security-level-radiogroup .security-level-radio {
    
    158
    -  margin: 0;
    
    159
    -}
    
    160
    -
    
    161
    -#security-level-radiogroup .radio-label-box {
    
    162
    -  /* .security-level-current-badge already has a margin. */
    
    163
    -  margin: 0;
    
    164
    -}
    
    165
    -
    
    166
    -#security-level-radiogroup .privacy-detailedoption.security-level-radio-container:not(.selected) .security-level-description-extra {
    
    167
    -  /* .privacy-detailedoption uses visibility: hidden, which does not work with
    
    168
    -   * our grid display (the margin is still reserved) so we use display: none
    
    169
    -   * instead. */
    
    170
    -  display: none;
    
    171
    -}

  • browser/components/securitylevel/content/securityLevelPreferences.inc.xhtml deleted
    1
    -<groupbox id="securityLevel-groupbox"
    
    2
    -          data-category="panePrivacy"
    
    3
    -          data-subcategory="securitylevel"
    
    4
    -          hidden="true">
    
    5
    -  <label>
    
    6
    -    <html:h2 data-l10n-id="security-level-preferences-heading"></html:h2>
    
    7
    -  </label>
    
    8
    -  <vbox flex="1">
    
    9
    -    <description class="description-deemphasized" flex="1">
    
    10
    -      <html:span
    
    11
    -        id="securityLevel-overview"
    
    12
    -        data-l10n-id="security-level-preferences-overview"
    
    13
    -      ></html:span>
    
    14
    -      <html:a
    
    15
    -        is="moz-support-link"
    
    16
    -        support-page="tor-manual:features__security-levels"
    
    17
    -        data-l10n-id="security-level-preferences-learn-more-link"
    
    18
    -      ></html:a>
    
    19
    -    </description>
    
    20
    -    <html:div id="security-level-current" class="security-level-grid">
    
    21
    -      <html:img
    
    22
    -        class="security-level-icon"
    
    23
    -        alt=""
    
    24
    -      />
    
    25
    -      <html:div
    
    26
    -        class="security-level-current-badge"
    
    27
    -        data-l10n-id="security-level-preferences-current-badge"
    
    28
    -      ></html:div>
    
    29
    -      <html:button
    
    30
    -        id="security-level-change"
    
    31
    -        data-l10n-id="security-level-preferences-change-button"
    
    32
    -      ></html:button>
    
    33
    -    </html:div>
    
    34
    -  </vbox>
    
    35
    -</groupbox>

  • browser/components/securitylevel/jar.mn
    1 1
     browser.jar:
    
    2
    +    content/browser/securitylevel/config/security-level.mjs              (config/security-level.mjs)
    
    3
    +    content/browser/securitylevel/widgets/security-level-description.mjs (widgets/security-level-description.mjs)
    
    4
    +    content/browser/securitylevel/widgets/security-level-description.css (widgets/security-level-description.css)
    
    5
    +    content/browser/securitylevel/widgets/security-level-display.mjs     (widgets/security-level-display.mjs)
    
    6
    +    content/browser/securitylevel/widgets/security-level-display.css     (widgets/security-level-display.css)
    
    2 7
         content/browser/securitylevel/securityLevel.js             (content/securityLevel.js)
    
    3 8
         content/browser/securitylevel/securityLevelPanel.css       (content/securityLevelPanel.css)
    
    4 9
         content/browser/securitylevel/securityLevelButton.css      (content/securityLevelButton.css)
    
    5
    -    content/browser/securitylevel/securityLevelPreferences.css (content/securityLevelPreferences.css)
    
    6 10
         content/browser/securitylevel/security-level-custom.svg    (content/security-level-custom.svg)
    
    7 11
         content/browser/securitylevel/security-level-safer.svg     (content/security-level-safer.svg)
    
    8 12
         content/browser/securitylevel/security-level-safest.svg    (content/security-level-safest.svg)
    
    9 13
         content/browser/securitylevel/security-level-standard.svg  (content/security-level-standard.svg)
    
    10 14
         content/browser/securitylevel/securityLevelDialog.xhtml    (content/securityLevelDialog.xhtml)
    
    11 15
         content/browser/securitylevel/securityLevelDialog.js       (content/securityLevelDialog.js)
    
    16
    +    content/browser/securitylevel/securityLevelDialog.css      (content/securityLevelDialog.css)

  • browser/components/securitylevel/moz.build
    1 1
     JAR_MANIFESTS += ["jar.mn"]
    2
    -
    
    3
    -MOZ_SRC_FILES += [
    
    4
    -    "SecurityLevelUIUtils.sys.mjs",
    
    5
    -]

  • browser/components/securitylevel/widgets/security-level-description.css
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +p {
    
    6
    +  margin: 0;
    
    7
    +}
    
    8
    +
    
    9
    +:host([hide-bullets]) ul {
    
    10
    +  display: none;
    
    11
    +}
    
    12
    +
    
    13
    +ul {
    
    14
    +  margin: 0;
    
    15
    +  padding-inline: var(--space-large) 0;
    
    16
    +}
    
    17
    +
    
    18
    +li {
    
    19
    +  margin-block-start: var(--space-xsmall);
    
    20
    +}

  • browser/components/securitylevel/widgets/security-level-description.mjs
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
    
    6
    +import { html, repeat } from "chrome://global/content/vendor/lit.all.mjs";
    
    7
    +
    
    8
    +/**
    
    9
    + * Widget that displays the description for a given security level.
    
    10
    + *
    
    11
    + * @tagname security-level-description
    
    12
    + * @property {string} value - The security level to show the description for.
    
    13
    + * @property {boolean} hideBullets - Whether to hide the bullet points for the
    
    14
    + *   description.
    
    15
    + */
    
    16
    +class SecurityLevelDescription extends MozLitElement {
    
    17
    +  static properties = {
    
    18
    +    value: { type: String },
    
    19
    +    hideBullets: { type: Boolean, reflect: true, attribute: "hide-bullets" },
    
    20
    +  };
    
    21
    +
    
    22
    +  static #config = {
    
    23
    +    standard: {
    
    24
    +      summaryL10nId: "security-level-summary-standard",
    
    25
    +    },
    
    26
    +    safer: {
    
    27
    +      summaryL10nId: "security-level-summary-safer",
    
    28
    +      bullets: [
    
    29
    +        "security-level-preferences-bullet-https-only-javascript",
    
    30
    +        "security-level-preferences-bullet-limit-font-and-symbols",
    
    31
    +        "security-level-preferences-bullet-limit-media",
    
    32
    +      ],
    
    33
    +    },
    
    34
    +    safest: {
    
    35
    +      summaryL10nId: "security-level-summary-safest",
    
    36
    +      bullets: [
    
    37
    +        "security-level-preferences-bullet-disabled-javascript",
    
    38
    +        "security-level-preferences-bullet-limit-font-and-symbols-and-images",
    
    39
    +        "security-level-preferences-bullet-limit-media",
    
    40
    +      ],
    
    41
    +    },
    
    42
    +    custom: {
    
    43
    +      summaryL10nId: "security-level-summary-custom",
    
    44
    +    },
    
    45
    +  };
    
    46
    +
    
    47
    +  listTemplate() {
    
    48
    +    const bullets = SecurityLevelDescription.#config[this.value]?.bullets;
    
    49
    +    if (!bullets) {
    
    50
    +      return "";
    
    51
    +    }
    
    52
    +    return html`
    
    53
    +      <ul>
    
    54
    +        ${repeat(
    
    55
    +          bullets,
    
    56
    +          l10nId => l10nId,
    
    57
    +          l10nId => html`<li data-l10n-id=${l10nId}></li>`
    
    58
    +        )}
    
    59
    +      </ul>
    
    60
    +    `;
    
    61
    +  }
    
    62
    +
    
    63
    +  render() {
    
    64
    +    let l10nId = SecurityLevelDescription.#config[this.value]?.summaryL10nId;
    
    65
    +    if (!l10nId) {
    
    66
    +      return "";
    
    67
    +    }
    
    68
    +
    
    69
    +    return html`
    
    70
    +      <link
    
    71
    +        rel="stylesheet"
    
    72
    +        href="chrome://browser/content/securitylevel/widgets/security-level-description.css"
    
    73
    +      />
    
    74
    +      <p data-l10n-id=${l10nId}></p>
    
    75
    +      ${this.listTemplate()}
    
    76
    +    `;
    
    77
    +  }
    
    78
    +}
    
    79
    +customElements.define("security-level-description", SecurityLevelDescription);

  • browser/components/securitylevel/widgets/security-level-display.css
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +:host {
    
    6
    +  --box-icon-stroke: var(--icon-color-warning);
    
    7
    +}
    
    8
    +
    
    9
    +p {
    
    10
    +  margin: 0;
    
    11
    +}
    
    12
    +
    
    13
    +.text-content {
    
    14
    +  padding: var(--box-padding);
    
    15
    +}
    
    16
    +
    
    17
    +.icon:dir(rtl) {
    
    18
    +  transform: scaleX(-1);
    
    19
    +}
    
    20
    +
    
    21
    +security-level-description {
    
    22
    +  grid-area: description;
    
    23
    +}

  • browser/components/securitylevel/widgets/security-level-display.mjs
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +import { MozBoxBase } from "chrome://global/content/lit-utils.mjs";
    
    6
    +import { html } from "chrome://global/content/vendor/lit.all.mjs";
    
    7
    +
    
    8
    +/**
    
    9
    + * Widget for displaying the current security level.
    
    10
    + *
    
    11
    + * @tagname security-level-display
    
    12
    + * @property {string} value - The current security level.
    
    13
    + */
    
    14
    +class SecurityLevelDisplay extends MozBoxBase {
    
    15
    +  static properties = {
    
    16
    +    value: { type: String },
    
    17
    +    _nameL10nId: { type: String },
    
    18
    +  };
    
    19
    +
    
    20
    +  static #config = {
    
    21
    +    standard: {
    
    22
    +      nameL10nId: "security-level-panel-level-standard",
    
    23
    +      iconSrc:
    
    24
    +        "chrome://browser/content/securitylevel/security-level-standard.svg",
    
    25
    +    },
    
    26
    +    safer: {
    
    27
    +      nameL10nId: "security-level-panel-level-safer",
    
    28
    +      iconSrc:
    
    29
    +        "chrome://browser/content/securitylevel/security-level-safer.svg",
    
    30
    +    },
    
    31
    +    safest: {
    
    32
    +      nameL10nId: "security-level-panel-level-safest",
    
    33
    +      iconSrc:
    
    34
    +        "chrome://browser/content/securitylevel/security-level-safest.svg",
    
    35
    +    },
    
    36
    +    custom: {
    
    37
    +      nameL10nId: "security-level-panel-level-custom",
    
    38
    +      iconSrc:
    
    39
    +        "chrome://browser/content/securitylevel/security-level-custom.svg",
    
    40
    +    },
    
    41
    +  };
    
    42
    +
    
    43
    +  willUpdate() {
    
    44
    +    const levelConfig = SecurityLevelDisplay.#config[this.value];
    
    45
    +    this._nameL10nId = levelConfig?.nameL10nId ?? null;
    
    46
    +    this.iconSrc = levelConfig?.iconSrc ?? null;
    
    47
    +  }
    
    48
    +
    
    49
    +  render() {
    
    50
    +    if (!this._nameL10nId) {
    
    51
    +      return "";
    
    52
    +    }
    
    53
    +    // NOTE: styleTemplate and iconTemplate come from MozBoxBase.
    
    54
    +    return html`
    
    55
    +      ${this.stylesTemplate()}
    
    56
    +      <link
    
    57
    +        rel="stylesheet"
    
    58
    +        href="chrome://browser/content/securitylevel/widgets/security-level-display.css"
    
    59
    +      />
    
    60
    +      <div class="text-content has-icon has-description">
    
    61
    +        ${this.iconTemplate()}
    
    62
    +        <p class="label" data-l10n-id=${this._nameL10nId}></p>
    
    63
    +        <security-level-description
    
    64
    +          .value=${this.value}
    
    65
    +          class="text-deemphasized"
    
    66
    +        ></security-level-description>
    
    67
    +      </div>
    
    68
    +    `;
    
    69
    +  }
    
    70
    +}
    
    71
    +customElements.define("security-level-display", SecurityLevelDisplay);

  • toolkit/content/widgets/lit-utils.mjs
    ... ... @@ -266,6 +266,9 @@ export class MozBaseInputElement extends MozLitElement {
    266 266
         // label-align-before is a customisation for the moz-toggle in about:tor.
    
    267 267
         // See tor-browser#43727.
    
    268 268
         labelAlignBefore: { type: Boolean, attribute: "label-align-before" },
    
    269
    +    // Allow us to set more complex content in a label (e.g. a moz-badge).
    
    270
    +    // See tor-browser#45201.
    
    271
    +    useLabelSlot: { type: Boolean, attribute: "use-label-slot" },
    
    269 272
       };
    
    270 273
       /** @type {"inline" | "block" | "inline-end"} */
    
    271 274
       static inputLayout = "inline";
    
    ... ... @@ -465,7 +468,7 @@ export class MozBaseInputElement extends MozLitElement {
    465 468
       }
    
    466 469
     
    
    467 470
       labelTemplate() {
    
    468
    -    if (!this.label) {
    
    471
    +    if (!this.label && !this.useLabelSlot) {
    
    469 472
           return "";
    
    470 473
         }
    
    471 474
         let labelEl;
    
    ... ... @@ -478,6 +481,12 @@ export class MozBaseInputElement extends MozLitElement {
    478 481
             class="text text-box-trim-start"
    
    479 482
             .textContent=${this.label}
    
    480 483
           ></h3>`;
    
    484
    +    } else if (this.useLabelSlot) {
    
    485
    +      labelEl = html`<slot
    
    486
    +        class="text"
    
    487
    +        name="label"
    
    488
    +        @slotchange=${this.onSlotchange}
    
    489
    +      ></slot>`;
    
    481 490
         } else {
    
    482 491
           labelEl = html`<span class="text" .textContent=${this.label}></span>`;
    
    483 492
         }
    

  • toolkit/locales/en-US/toolkit/global/base-browser.ftl
    ... ... @@ -185,13 +185,11 @@ security-level-panel-open-settings-button = Settings…
    185 185
     
    
    186 186
     ## Security level settings.
    
    187 187
     
    
    188
    -security-level-preferences-heading = Security Level
    
    189
    -security-level-preferences-overview = Disable certain web features that can be used to attack your security and anonymity.
    
    190
    -security-level-preferences-learn-more-link = Learn more
    
    191
    -# Text for a badge that labels the currently active security level.
    
    192
    -# The text in between '<span>' and '</span>' should contain some kind of bracket, like '(' and ')', or other punctuation used in your language to separate out text from its surrounding context. This will not be visible, but will be use for screen readers to make it clear that the text is not part of the same sentence. For example, in US English this would be read as "(Current level)", and the full line of text would be read as "Safest (Current level)".
    
    193
    -security-level-preferences-current-badge = <span>(</span>Current level<span>)</span>
    
    194
    -security-level-preferences-change-button = Change…
    
    188
    +security-level-settings-group =
    
    189
    +    .label = Security level
    
    190
    +    .description = Disable certain web features that can be used to attack your security and anonymity.
    
    191
    +security-level-settings-change-button =
    
    192
    +    .label = Change security level
    
    195 193
     
    
    196 194
     ## Security level settings dialog.
    
    197 195
     
    
    ... ... @@ -201,13 +199,12 @@ security-level-dialog-window =
    201 199
     # '-brand-short-name' is the localized browser name, like "Tor Browser".
    
    202 200
     security-level-dialog-restart-description = You will need to restart { -brand-short-name } to apply any changes. This will close all windows and tabs.
    
    203 201
     
    
    204
    -security-level-preferences-level-standard =
    
    205
    -    .label = Standard
    
    206
    -security-level-preferences-level-safer =
    
    207
    -    .label = Safer
    
    208
    -security-level-preferences-level-safest =
    
    209
    -    .label = Safest
    
    210
    -
    
    202
    +# Text for a badge that labels the currently active security level.
    
    203
    +# The text in between '<span>' and '</span>' should contain some kind of bracket, like '(' and ')', or other punctuation used in your language to separate out text from its surrounding context. This will not be visible, but will be use for screen readers to make it clear that the text is not part of the same sentence. For example, in US English this would be read as "(Current level)", and the full line of text would be read as "Safest (Current level)".
    
    204
    +security-level-preferences-current-badge = <span>(</span>Current level<span>)</span>
    
    205
    +# The "aria-label" provides a name for the group of radio options. This is not visibly shown, but it is useful for screen reader users.
    
    206
    +security-level-dialog-radio-group =
    
    207
    +    .aria-label = Security level
    
    211 208
     security-level-dialog-save-restart =
    
    212 209
         .label = Save and restart
    
    213 210