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

Commits:

10 changed files:

Changes:

  • browser/components/onionservices/content/authPopup.inc.xhtml
    ... ... @@ -11,12 +11,27 @@
    11 11
           data-l10n-id="onion-site-authentication-prompt-learn-more"
    
    12 12
         />
    
    13 13
         <html:div>
    
    14
    +      <!-- NOTE: Orca 46.2 will not say "invalid" for "type=password". See
    
    15
    +         - https://gitlab.gnome.org/GNOME/orca/-/issues/550
    
    16
    +         - Moreover, it will ignore the aria-errormessage relation when we are
    
    17
    +         - not in a document context. See related bugzilla bug 1820765. -->
    
    14 18
           <html:input
    
    15 19
             id="tor-clientauth-notification-key"
    
    16 20
             type="password"
    
    17 21
             data-l10n-id="onion-site-authentication-prompt-key-input"
    
    22
    +        aria-errormessage="tor-clientauth-warning"
    
    18 23
           />
    
    19
    -      <html:div id="tor-clientauth-warning"></html:div>
    
    24
    +      <html:div
    
    25
    +        id="tor-clientauth-warning"
    
    26
    +        role="alert"
    
    27
    +        aria-labelledby="tor-clientauth-warning-text"
    
    28
    +      >
    
    29
    +        <!-- NOTE: Orca 46.2 treats this notification as non-document context.
    
    30
    +           - As such it seems to only read out the alert content if it contains
    
    31
    +           - a <xul:label>, <html:label> or if it has an accessible name.
    
    32
    +           - We use aria-labelledby here. -->
    
    33
    +        <html:span id="tor-clientauth-warning-text"></html:span>
    
    34
    +      </html:div>
    
    20 35
           <checkbox
    
    21 36
             id="tor-clientauth-persistkey-checkbox"
    
    22 37
             data-l10n-id="onion-site-authentication-prompt-remember-checkbox"
    

  • browser/components/onionservices/content/authPreferences.css
    ... ... @@ -23,3 +23,15 @@
    23 23
       -moz-context-properties: fill;
    
    24 24
       fill: var(--in-content-warning-icon-color);
    
    25 25
     }
    
    26
    +
    
    27
    +/* Make a button appear disabled, whilst still allowing it to keep keyboard
    
    28
    + * focus.
    
    29
    + * Duplicate of rule in torPreferences.css.
    
    30
    + * TODO: Replace with moz-button when it handles this for us. See
    
    31
    + * tor-browser#43275. */
    
    32
    +button.spoof-button-disabled {
    
    33
    +  /* Borrow the :disabled rule from common-shared.css */
    
    34
    +  opacity: 0.4;
    
    35
    +  /* Also ensure it does not get hover or active styling. */
    
    36
    +  pointer-events: none;
    
    37
    +}

  • browser/components/onionservices/content/authPrompt.js
    ... ... @@ -32,6 +32,8 @@ var OnionAuthPrompt = {
    32 32
     
    
    33 33
       /**
    
    34 34
        * The currently shown details in the prompt.
    
    35
    +   *
    
    36
    +   * @type {?PromptDetails}
    
    35 37
        */
    
    36 38
       _shownDetails: null,
    
    37 39
     
    
    ... ... @@ -264,16 +266,18 @@ var OnionAuthPrompt = {
    264 266
        */
    
    265 267
       _showWarning(warningMessageId) {
    
    266 268
         this._logger.debug(`Showing warning: ${warningMessageId}`);
    
    269
    +
    
    267 270
         if (warningMessageId) {
    
    268
    -      document.l10n.setAttributes(this._warningEl, warningMessageId);
    
    271
    +      document.l10n.setAttributes(this._warningTextEl, warningMessageId);
    
    269 272
           this._warningEl.removeAttribute("hidden");
    
    270 273
           this._keyInput.classList.add("invalid");
    
    274
    +      this._keyInput.setAttribute("aria-invalid", "true");
    
    271 275
         } else {
    
    272
    -      // Clean up.
    
    273
    -      this._warningEl.removeAttribute("data-l10n-id");
    
    274
    -      this._warningEl.textContent = "";
    
    276
    +      this._warningTextEl.removeAttribute("data-l10n-id");
    
    277
    +      this._warningTextEl.textContent = "";
    
    275 278
           this._warningEl.setAttribute("hidden", "true");
    
    276 279
           this._keyInput.classList.remove("invalid");
    
    280
    +      this._keyInput.removeAttribute("aria-invalid");
    
    277 281
         }
    
    278 282
       },
    
    279 283
     
    
    ... ... @@ -344,6 +348,9 @@ var OnionAuthPrompt = {
    344 348
           "tor-clientauth-persistkey-checkbox"
    
    345 349
         );
    
    346 350
         this._warningEl = document.getElementById("tor-clientauth-warning");
    
    351
    +    this._warningTextEl = document.getElementById(
    
    352
    +      "tor-clientauth-warning-text"
    
    353
    +    );
    
    347 354
         this._descriptionEl = document.getElementById(
    
    348 355
           "tor-clientauth-notification-desc"
    
    349 356
         );
    

  • browser/components/onionservices/content/savedKeysDialog.js
    ... ... @@ -14,6 +14,20 @@ var gOnionServicesSavedKeysDialog = {
    14 14
         return this._busyCount > 0;
    
    15 15
       },
    
    16 16
     
    
    17
    +  /**
    
    18
    +   * Whether the "remove selected" button is disabled.
    
    19
    +   *
    
    20
    +   * @type {boolean}
    
    21
    +   */
    
    22
    +  _removeSelectedDisabled: true,
    
    23
    +
    
    24
    +  /**
    
    25
    +   * Whether the "remove all" button is disabled.
    
    26
    +   *
    
    27
    +   * @type {boolean}
    
    28
    +   */
    
    29
    +  _removeAllDisabled: true,
    
    30
    +
    
    17 31
       async _deleteSelectedKeys() {
    
    18 32
         this._showError(null);
    
    19 33
         this._withBusy(async () => {
    
    ... ... @@ -36,6 +50,15 @@ var gOnionServicesSavedKeysDialog = {
    36 50
               for (let i = indexesToDelete.length - 1; i >= 0; --i) {
    
    37 51
                 await this._deleteOneKey(provider, indexesToDelete[i]);
    
    38 52
               }
    
    53
    +          // If successful and the user focus is still on the buttons move focus
    
    54
    +          // to the table with the updated state. We do this before calling
    
    55
    +          // _updateButtonState and potentially making the buttons disabled.
    
    56
    +          if (
    
    57
    +            this._removeButton.contains(document.activeElement) ||
    
    58
    +            this._removeAllButton.contains(document.activeElement)
    
    59
    +          ) {
    
    60
    +            this._tree.focus();
    
    61
    +          }
    
    39 62
             } catch (e) {
    
    40 63
               console.error("Removing a saved key failed", e);
    
    41 64
               this._showError(
    
    ... ... @@ -51,10 +74,37 @@ var gOnionServicesSavedKeysDialog = {
    51 74
         await this._deleteSelectedKeys();
    
    52 75
       },
    
    53 76
     
    
    77
    +  /**
    
    78
    +   * Show the given button as being disabled or enabled.
    
    79
    +   *
    
    80
    +   * @param {Button} button - The button to change.
    
    81
    +   * @param {boolean} disable - Whether to show the button as disabled or
    
    82
    +   *   enabled.
    
    83
    +   */
    
    84
    +  _disableButton(button, disable) {
    
    85
    +    // If we are disabled we show the button as disabled, and we also remove it
    
    86
    +    // from the tab focus cycle using `tabIndex = -1`.
    
    87
    +    // This is similar to using the `disabled` attribute, except that
    
    88
    +    // `tabIndex = -1` still allows the button to be focusable. I.e. not part of
    
    89
    +    // the focus cycle but can *keep* existing focus when the button becomes
    
    90
    +    // disabled to avoid loosing focus to the top of the dialog.
    
    91
    +    // TODO: Replace with moz-button when it handles this for us. See
    
    92
    +    // tor-browser#43275.
    
    93
    +    button.classList.toggle("spoof-button-disabled", disable);
    
    94
    +    button.tabIndex = disable ? -1 : 0;
    
    95
    +    if (disable) {
    
    96
    +      this._removeButton.setAttribute("aria-disabled", "true");
    
    97
    +    } else {
    
    98
    +      this._removeButton.removeAttribute("aria-disabled");
    
    99
    +    }
    
    100
    +  },
    
    101
    +
    
    54 102
       _updateButtonsState() {
    
    55 103
         const haveSelection = this._tree.view.selection.getRangeCount() > 0;
    
    56
    -    this._removeButton.disabled = this._isBusy || !haveSelection;
    
    57
    -    this._removeAllButton.disabled = this._isBusy || this.rowCount === 0;
    
    104
    +    this._removeSelectedDisabled = this._isBusy || !haveSelection;
    
    105
    +    this._removeAllDisabled = this._isBusy || this.rowCount === 0;
    
    106
    +    this._disableButton(this._removeButton, this._removeSelectedDisabled);
    
    107
    +    this._disableButton(this._removeAllButton, this._removeAllDisabled);
    
    58 108
       },
    
    59 109
     
    
    60 110
       // Private functions.
    
    ... ... @@ -79,12 +129,18 @@ var gOnionServicesSavedKeysDialog = {
    79 129
           "onionservices-savedkeys-remove"
    
    80 130
         );
    
    81 131
         this._removeButton.addEventListener("click", () => {
    
    132
    +      if (this._removeSelectedDisabled) {
    
    133
    +        return;
    
    134
    +      }
    
    82 135
           this._deleteSelectedKeys();
    
    83 136
         });
    
    84 137
         this._removeAllButton = document.getElementById(
    
    85 138
           "onionservices-savedkeys-removeall"
    
    86 139
         );
    
    87 140
         this._removeAllButton.addEventListener("click", () => {
    
    141
    +      if (this._removeAllDisabled) {
    
    142
    +        return;
    
    143
    +      }
    
    88 144
           this._deleteAllKeys();
    
    89 145
         });
    
    90 146
     
    

  • browser/components/onionservices/content/savedKeysDialog.xhtml
    ... ... @@ -49,7 +49,11 @@
    49 49
           </treecols>
    
    50 50
           <treechildren />
    
    51 51
         </tree>
    
    52
    -    <hbox id="onionservices-savedkeys-errorContainer" align="center">
    
    52
    +    <hbox
    
    53
    +      id="onionservices-savedkeys-errorContainer"
    
    54
    +      align="center"
    
    55
    +      role="alert"
    
    56
    +    >
    
    53 57
           <image id="onionservices-savedkeys-errorIcon" />
    
    54 58
           <description id="onionservices-savedkeys-errorMessage" flex="1" />
    
    55 59
         </hbox>
    
    ... ... @@ -57,7 +61,6 @@
    57 61
         <hbox id="onionservices-savedkeys-buttons">
    
    58 62
           <html:button
    
    59 63
             id="onionservices-savedkeys-remove"
    
    60
    -        disabled="true"
    
    61 64
             data-l10n-id="onion-site-saved-keys-dialog-remove-button"
    
    62 65
           ></html:button>
    
    63 66
           <html:button
    

  • browser/components/torpreferences/content/connectionPane.js
    ... ... @@ -2354,8 +2354,11 @@ const gNetworkStatus = {
    2354 2354
         this._internetTestDisabled = true;
    
    2355 2355
         // We use "aria-disabled" rather than the "disabled" attribute so that the
    
    2356 2356
         // button can remain focusable during the test.
    
    2357
    +    // TODO: Replace with moz-button when it handles this for us. See
    
    2358
    +    // tor-browser#43275.
    
    2357 2359
         this._internetTestButton.setAttribute("aria-disabled", "true");
    
    2358 2360
         this._internetTestButton.classList.add("spoof-button-disabled");
    
    2361
    +    this._internetTestButton.tabIndex = -1;
    
    2359 2362
         try {
    
    2360 2363
           this._updateInternetStatus("testing");
    
    2361 2364
           const mrpc = new MoatRPC();
    
    ... ... @@ -2376,6 +2379,7 @@ const gNetworkStatus = {
    2376 2379
         } finally {
    
    2377 2380
           this._internetTestButton.removeAttribute("aria-disabled");
    
    2378 2381
           this._internetTestButton.classList.remove("spoof-button-disabled");
    
    2382
    +      this._internetTestButton.tabIndex = 0;
    
    2379 2383
           this._internetTestDisabled = false;
    
    2380 2384
         }
    
    2381 2385
       },
    

  • browser/components/torpreferences/content/loxInviteDialog.js
    ... ... @@ -255,15 +255,11 @@ const gLoxInvites = {
    255 255
         // When generating we use "aria-disabled" rather than the "disabled"
    
    256 256
         // attribute so that the button can remain focusable whilst we generate
    
    257 257
         // invites.
    
    258
    -    // NOTE: When we generate the invite the focus will move to the invite list,
    
    259
    -    // so it should be safe to make the button non-focusable in this case.
    
    260
    -    const spoofDisabled = this._generating;
    
    261
    -    this._generateButton.disabled = disabled && !spoofDisabled;
    
    262
    -    this._generateButton.classList.toggle(
    
    263
    -      "spoof-button-disabled",
    
    264
    -      spoofDisabled
    
    265
    -    );
    
    266
    -    if (spoofDisabled) {
    
    258
    +    // TODO: Replace with moz-button when it handles this for us. See
    
    259
    +    // tor-browser#43275.
    
    260
    +    this._generateButton.classList.toggle("spoof-button-disabled", disabled);
    
    261
    +    this._generateButton.tabIndex = disabled ? -1 : 0;
    
    262
    +    if (disabled) {
    
    267 263
           this._generateButton.setAttribute("aria-disabled", "true");
    
    268 264
         } else {
    
    269 265
           this._generateButton.removeAttribute("aria-disabled");
    

  • browser/components/torpreferences/content/provideBridgeDialog.js
    ... ... @@ -215,7 +215,10 @@ const gProvideBridgeDialog = {
    215 215
         this._acceptDisabled = disabled;
    
    216 216
         // Spoof the button to look and act as if it is disabled, but still allow
    
    217 217
         // keyboard focus so the user can sit on this button whilst we are loading.
    
    218
    +    // TODO: Replace with moz-button when it handles this for us. See
    
    219
    +    // tor-browser#43275.
    
    218 220
         this._acceptButton.classList.toggle("spoof-button-disabled", disabled);
    
    221
    +    this._acceptButton.tabIndex = disabled ? -1 : 0;
    
    219 222
         if (disabled) {
    
    220 223
           this._acceptButton.setAttribute("aria-disabled", "true");
    
    221 224
         } else {
    

  • browser/components/torpreferences/content/provideBridgeDialog.xhtml
    ... ... @@ -55,7 +55,6 @@
    55 55
             <html:span
    
    56 56
               id="user-provide-bridge-error-message"
    
    57 57
               role="alert"
    
    58
    -          aria-live="assertive"
    
    59 58
             ></html:span>
    
    60 59
             <img
    
    61 60
               id="user-provide-bridge-loading-icon"
    

  • browser/components/torpreferences/content/torPreferences.css
    ... ... @@ -6,7 +6,9 @@
    6 6
     }
    
    7 7
     
    
    8 8
     /* Make a button appear disabled, whilst still allowing it to keep keyboard
    
    9
    - * focus. */
    
    9
    + * focus.
    
    10
    + * TODO: Replace with moz-button when it handles this for us. See
    
    11
    + * tor-browser#43275. */
    
    10 12
     button.spoof-button-disabled {
    
    11 13
       /* Borrow the :disabled rule from common-shared.css */
    
    12 14
       opacity: 0.4;