[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-115.10.0esr-13.5-1] fixup! Bug 31286: Implementation of bridge, proxy, and firewall settings in...



Title: GitLab

richard pushed to branch tor-browser-115.10.0esr-13.5-1 at The Tor Project / Applications / Tor Browser

Commits:

  • 00e009df
    by Henry Wilkes at 2024-04-18T13:57:12+01:00
    fixup! Bug 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection
    
    Bug 42457: Add a loading icon for Lox invites.
    
    Also reduce the amount of focus-jumping by keeping the focus on the
    disabled button.
    
    Also change the focus of the last provideBridgeDialog page to be the
    table of bridges. NVDA did not announce the focus when it was set to the
    dialog itself.
    

6 changed files:

Changes:

  • browser/components/torpreferences/content/connectionPane.xhtml
    ... ... @@ -48,7 +48,7 @@
    48 48
               class="network-status-label"
    
    49 49
               data-l10n-id="tor-connection-internet-status-label"
    
    50 50
             ></html:span>
    
    51
    -        <img alt="" class="network-status-loading-icon" />
    
    51
    +        <img alt="" class="network-status-loading-icon tor-loading-icon" />
    
    52 52
             <html:span class="network-status-result"></html:span>
    
    53 53
           </html:div>
    
    54 54
           <html:button
    

  • browser/components/torpreferences/content/loxInviteDialog.js
    ... ... @@ -62,12 +62,12 @@ const gLoxInvites = {
    62 62
         this._remainingInvitesEl = document.getElementById(
    
    63 63
           "lox-invite-dialog-remaining"
    
    64 64
         );
    
    65
    +    this._generateArea = document.getElementById(
    
    66
    +      "lox-invite-dialog-generate-area"
    
    67
    +    );
    
    65 68
         this._generateButton = document.getElementById(
    
    66 69
           "lox-invite-dialog-generate-button"
    
    67 70
         );
    
    68
    -    this._connectingEl = document.getElementById(
    
    69
    -      "lox-invite-dialog-connecting"
    
    70
    -    );
    
    71 71
         this._errorEl = document.getElementById("lox-invite-dialog-error-message");
    
    72 72
         this._inviteListEl = document.getElementById("lox-invite-dialog-list");
    
    73 73
     
    
    ... ... @@ -237,20 +237,46 @@ const gLoxInvites = {
    237 237
       _setGenerating(isGenerating) {
    
    238 238
         this._generating = isGenerating;
    
    239 239
         this._updateGenerateButtonState();
    
    240
    -    this._connectingEl.classList.toggle("show-connecting", isGenerating);
    
    240
    +    this._generateArea.classList.toggle("show-connecting", isGenerating);
    
    241 241
       },
    
    242 242
     
    
    243
    +  /**
    
    244
    +   * Whether the generate button is disabled.
    
    245
    +   *
    
    246
    +   * @type {boolean}
    
    247
    +   */
    
    248
    +  _generateDisabled: false,
    
    243 249
       /**
    
    244 250
        * Update the state of the generate button.
    
    245 251
        */
    
    246 252
       _updateGenerateButtonState() {
    
    247
    -    this._generateButton.disabled = this._generating || !this._remainingInvites;
    
    253
    +    const disabled = this._generating || !this._remainingInvites;
    
    254
    +    this._generateDisabled = disabled;
    
    255
    +    // When generating we use "aria-disabled" rather than the "disabled"
    
    256
    +    // attribute so that the button can remain focusable whilst we generate
    
    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) {
    
    267
    +      this._generateButton.setAttribute("aria-disabled", "true");
    
    268
    +    } else {
    
    269
    +      this._generateButton.removeAttribute("aria-disabled");
    
    270
    +    }
    
    248 271
       },
    
    249 272
     
    
    250 273
       /**
    
    251 274
        * Start generating a new invite.
    
    252 275
        */
    
    253 276
       _generateNewInvite() {
    
    277
    +    if (this._generateDisabled) {
    
    278
    +      return;
    
    279
    +    }
    
    254 280
         if (this._generating) {
    
    255 281
           console.error("Already generating an invite");
    
    256 282
           return;
    
    ... ... @@ -258,15 +284,13 @@ const gLoxInvites = {
    258 284
         this._setGenerating(true);
    
    259 285
         // Clear the previous error.
    
    260 286
         this._updateGenerateError(null);
    
    261
    -    // Move focus from the button to the connecting element, since button is
    
    262
    -    // now disabled.
    
    263
    -    this._connectingEl.focus();
    
    264 287
     
    
    265
    -    let lostFocus = false;
    
    288
    +    let moveFocus = false;
    
    266 289
         Lox.generateInvite(this._loxId)
    
    267 290
           .finally(() => {
    
    268
    -        // Fetch whether the connecting label still has focus before we hide it.
    
    269
    -        lostFocus = this._connectingEl.contains(document.activeElement);
    
    291
    +        // Fetch whether the generate button has focus before we potentially
    
    292
    +        // disable it.
    
    293
    +        moveFocus = this._generateButton.contains(document.activeElement);
    
    270 294
             this._setGenerating(false);
    
    271 295
           })
    
    272 296
           .then(
    
    ... ... @@ -279,7 +303,7 @@ const gLoxInvites = {
    279 303
                 this._inviteListEl.selectedIndex = 0;
    
    280 304
               }
    
    281 305
     
    
    282
    -          if (lostFocus) {
    
    306
    +          if (moveFocus) {
    
    283 307
                 // Move focus to the new invite before we hide the "Connecting"
    
    284 308
                 // message.
    
    285 309
                 this._inviteListEl.focus();
    
    ... ... @@ -295,12 +319,6 @@ const gLoxInvites = {
    295 319
                   this._updateGenerateError("generic");
    
    296 320
                   break;
    
    297 321
               }
    
    298
    -
    
    299
    -          if (lostFocus) {
    
    300
    -            // Move focus back to the button before we hide the "Connecting"
    
    301
    -            // message.
    
    302
    -            this._generateButton.focus();
    
    303
    -          }
    
    304 322
             }
    
    305 323
           );
    
    306 324
       },
    
    ... ... @@ -315,7 +333,7 @@ const gLoxInvites = {
    315 333
         // First clear the existing error.
    
    316 334
         this._errorEl.removeAttribute("data-l10n-id");
    
    317 335
         this._errorEl.textContent = "";
    
    318
    -    this._errorEl.classList.toggle("show-error", !!type);
    
    336
    +    this._generateArea.classList.toggle("show-error", !!type);
    
    319 337
     
    
    320 338
         if (!type) {
    
    321 339
           return;
    

  • browser/components/torpreferences/content/loxInviteDialog.xhtml
    ... ... @@ -40,10 +40,14 @@
    40 40
               id="lox-invite-dialog-error-message"
    
    41 41
               role="alert"
    
    42 42
             ></html:span>
    
    43
    +        <img
    
    44
    +          id="lox-invite-dialog-loading-icon"
    
    45
    +          class="tor-loading-icon"
    
    46
    +          alt=""
    
    47
    +        />
    
    43 48
             <html:span
    
    44 49
               id="lox-invite-dialog-connecting"
    
    45 50
               role="alert"
    
    46
    -          tabindex="0"
    
    47 51
               data-l10n-id="lox-invite-dialog-connecting"
    
    48 52
             ></html:span>
    
    49 53
           </html:div>
    

  • browser/components/torpreferences/content/provideBridgeDialog.js
    ... ... @@ -84,13 +84,19 @@ const gProvideBridgeDialog = {
    84 84
     
    
    85 85
         this._dialog = document.getElementById("user-provide-bridge-dialog");
    
    86 86
         this._acceptButton = this._dialog.getButton("accept");
    
    87
    +
    
    88
    +    // Inject our stylesheet into the shadow root so that the accept button can
    
    89
    +    // take the spoof-button-disabled styling.
    
    90
    +    const styleLink = document.createElement("link");
    
    91
    +    styleLink.rel = "stylesheet";
    
    92
    +    styleLink.href =
    
    93
    +      "chrome://browser/content/torpreferences/torPreferences.css";
    
    94
    +    this._dialog.shadowRoot.append(styleLink);
    
    95
    +
    
    87 96
         this._textarea = document.getElementById("user-provide-bridge-textarea");
    
    88 97
         this._errorEl = document.getElementById(
    
    89 98
           "user-provide-bridge-error-message"
    
    90 99
         );
    
    91
    -    this._connectingEl = document.getElementById(
    
    92
    -      "user-provide-bridge-connecting"
    
    93
    -    );
    
    94 100
         this._resultDescription = document.getElementById(
    
    95 101
           "user-provide-result-description"
    
    96 102
         );
    
    ... ... @@ -152,13 +158,16 @@ const gProvideBridgeDialog = {
    152 158
        * Reset focus position in the dialog.
    
    153 159
        */
    
    154 160
       takeFocus() {
    
    155
    -    if (this._page === "entry") {
    
    156
    -      this._textarea.focus();
    
    157
    -    } else {
    
    158
    -      // Move focus to the <xul:window> element.
    
    159
    -      // In particular, we do not want to keep the focus on the (same) accept
    
    160
    -      // button (with now different text).
    
    161
    -      document.documentElement.focus();
    
    161
    +    switch (this._page) {
    
    162
    +      case "entry":
    
    163
    +        this._textarea.focus();
    
    164
    +        break;
    
    165
    +      case "result":
    
    166
    +        // Move focus to the table.
    
    167
    +        // In particular, we do not want to keep the focus on the (same) accept
    
    168
    +        // button (with now different text).
    
    169
    +        this._bridgeGrid.focus();
    
    170
    +        break;
    
    162 171
         }
    
    163 172
       },
    
    164 173
     
    
    ... ... @@ -193,12 +202,27 @@ const gProvideBridgeDialog = {
    193 202
         }
    
    194 203
       },
    
    195 204
     
    
    205
    +  /**
    
    206
    +   * Whether the dialog accept button is disabled.
    
    207
    +   *
    
    208
    +   * @type {boolean}
    
    209
    +   */
    
    210
    +  _acceptDisabled: false,
    
    196 211
       /**
    
    197 212
        * Callback for whenever the accept button's might need to be disabled.
    
    198 213
        */
    
    199 214
       updateAcceptDisabled() {
    
    200
    -    this._acceptButton.disabled =
    
    215
    +    const disabled =
    
    201 216
           this._page === "entry" && (this.isEmpty() || this._loxLoading);
    
    217
    +    this._acceptDisabled = disabled;
    
    218
    +    // Spoof the button to look and act as if it is disabled, but still allow
    
    219
    +    // keyboard focus so the user can sit on this button whilst we are loading.
    
    220
    +    this._acceptButton.classList.toggle("spoof-button-disabled", disabled);
    
    221
    +    if (disabled) {
    
    222
    +      this._acceptButton.setAttribute("aria-disabled", "true");
    
    223
    +    } else {
    
    224
    +      this._acceptButton.removeAttribute("aria-disabled");
    
    225
    +    }
    
    202 226
       },
    
    203 227
     
    
    204 228
       /**
    
    ... ... @@ -217,16 +241,7 @@ const gProvideBridgeDialog = {
    217 241
       setLoxLoading(isLoading) {
    
    218 242
         this._loxLoading = isLoading;
    
    219 243
         this._textarea.readOnly = isLoading;
    
    220
    -    this._connectingEl.classList.toggle("show-connecting", isLoading);
    
    221
    -    if (
    
    222
    -      isLoading &&
    
    223
    -      this._acceptButton.contains(
    
    224
    -        this._acceptButton.getRootNode().activeElement
    
    225
    -      )
    
    226
    -    ) {
    
    227
    -      // Move focus to the alert before we disable the button.
    
    228
    -      this._connectingEl.focus();
    
    229
    -    }
    
    244
    +    this._dialog.classList.toggle("show-connecting", isLoading);
    
    230 245
         this.updateAcceptDisabled();
    
    231 246
       },
    
    232 247
     
    
    ... ... @@ -236,6 +251,12 @@ const gProvideBridgeDialog = {
    236 251
        * @param {Event} event - The dialogaccept event.
    
    237 252
        */
    
    238 253
       onDialogAccept(event) {
    
    254
    +    if (this._acceptDisabled) {
    
    255
    +      // Prevent closing.
    
    256
    +      event.preventDefault();
    
    257
    +      return;
    
    258
    +    }
    
    259
    +
    
    239 260
         if (this._page === "result") {
    
    240 261
           this._result.accepted = true;
    
    241 262
           // Continue to close the dialog.
    
    ... ... @@ -313,14 +334,11 @@ const gProvideBridgeDialog = {
    313 334
         this._errorEl.textContent = "";
    
    314 335
         if (error) {
    
    315 336
           this._textarea.setAttribute("aria-invalid", "true");
    
    316
    -      // Move focus back to the text area, likely away from the Next button or
    
    317
    -      // the "Connecting..." alert.
    
    318
    -      this._textarea.focus();
    
    319 337
         } else {
    
    320 338
           this._textarea.removeAttribute("aria-invalid");
    
    321 339
         }
    
    322 340
         this._textarea.classList.toggle("invalid-input", !!error);
    
    323
    -    this._errorEl.classList.toggle("show-error", !!error);
    
    341
    +    this._dialog.classList.toggle("show-error", !!error);
    
    324 342
     
    
    325 343
         if (!error) {
    
    326 344
           return;
    

  • browser/components/torpreferences/content/provideBridgeDialog.xhtml
    ... ... @@ -51,10 +51,14 @@
    51 51
               role="alert"
    
    52 52
               aria-live="assertive"
    
    53 53
             ></html:span>
    
    54
    +        <img
    
    55
    +          id="user-provide-bridge-loading-icon"
    
    56
    +          class="tor-loading-icon"
    
    57
    +          alt=""
    
    58
    +        />
    
    54 59
             <html:span
    
    55 60
               id="user-provide-bridge-connecting"
    
    56 61
               role="alert"
    
    57
    -          tabindex="0"
    
    58 62
               data-l10n-id="user-provide-bridge-dialog-connecting"
    
    59 63
             ></html:span>
    
    60 64
           </html:div>
    
    ... ... @@ -70,6 +74,8 @@
    70 74
             id="user-provide-bridge-grid-display"
    
    71 75
             class="tor-bridges-grid"
    
    72 76
             role="table"
    
    77
    +        tabindex="0"
    
    78
    +        aria-labelledby="user-provide-result-description"
    
    73 79
           ></html:div>
    
    74 80
           <html:template id="user-provide-bridge-row-template">
    
    75 81
             <html:div class="tor-bridges-grid-row" role="row">
    

  • browser/components/torpreferences/content/torPreferences.css
    ... ... @@ -14,6 +14,24 @@ button.spoof-button-disabled {
    14 14
       pointer-events: none;
    
    15 15
     }
    
    16 16
     
    
    17
    +.tor-loading-icon {
    
    18
    +  width: 16px;
    
    19
    +  height: 16px;
    
    20
    +  content: image-set(
    
    21
    +    url("chrome://global/skin/icons/tor-light-loading.png"),
    
    22
    +    url("chrome://global/skin/icons/tor-light-loading@xxxxxx") 2x
    
    23
    +  );
    
    24
    +}
    
    25
    +
    
    26
    +@media (prefers-color-scheme: dark) {
    
    27
    +  .tor-loading-icon {
    
    28
    +    content: image-set(
    
    29
    +      url("chrome://global/skin/icons/tor-dark-loading.png"),
    
    30
    +      url("chrome://global/skin/icons/tor-dark-loading@xxxxxx") 2x
    
    31
    +    );
    
    32
    +  }
    
    33
    +}
    
    34
    +
    
    17 35
     /* Status */
    
    18 36
     
    
    19 37
     #network-status-internet-area {
    
    ... ... @@ -81,21 +99,6 @@ button.spoof-button-disabled {
    81 99
     
    
    82 100
     .network-status-loading-icon {
    
    83 101
       margin-inline-end: 0.5em;
    
    84
    -  width: 16px;
    
    85
    -  height: 16px;
    
    86
    -  content: image-set(
    
    87
    -    url("chrome://global/skin/icons/tor-light-loading.png"),
    
    88
    -    url("chrome://global/skin/icons/tor-light-loading@xxxxxx") 2x
    
    89
    -  );
    
    90
    -}
    
    91
    -
    
    92
    -@media (prefers-color-scheme: dark) {
    
    93
    -  .network-status-loading-icon {
    
    94
    -    content: image-set(
    
    95
    -      url("chrome://global/skin/icons/tor-dark-loading.png"),
    
    96
    -      url("chrome://global/skin/icons/tor-dark-loading@xxxxxx") 2x
    
    97
    -    );
    
    98
    -  }
    
    99 102
     }
    
    100 103
     
    
    101 104
     #network-status-internet-area:not(.status-loading) .network-status-loading-icon {
    
    ... ... @@ -900,6 +903,8 @@ dialog#torPreferences-requestBridge-dialog > hbox {
    900 903
     #lox-invite-dialog-message-area {
    
    901 904
       grid-area: message;
    
    902 905
       justify-self: end;
    
    906
    +  display: flex;
    
    907
    +  align-items: center;
    
    903 908
     }
    
    904 909
     
    
    905 910
     #lox-invite-dialog-message-area::after {
    
    ... ... @@ -911,19 +916,29 @@ dialog#torPreferences-requestBridge-dialog > hbox {
    911 916
       color: var(--in-content-error-text-color);
    
    912 917
     }
    
    913 918
     
    
    914
    -#lox-invite-dialog-error-message:not(.show-error) {
    
    919
    +#lox-invite-dialog-generate-area:not(.show-error) #lox-invite-dialog-error-message {
    
    915 920
       display: none;
    
    916 921
     }
    
    917 922
     
    
    918 923
     #lox-invite-dialog-connecting {
    
    919 924
       color: var(--text-color-deemphasized);
    
    920
    -  /* TODO: Add spinner ::before */
    
    925
    +  /* Gap with #user-provide-bridge-loading-icon. */
    
    926
    +  margin-inline-start: 0.5em;
    
    921 927
     }
    
    922 928
     
    
    923
    -#lox-invite-dialog-connecting:not(.show-connecting) {
    
    929
    +#lox-invite-dialog-generate-area:not(.show-connecting) #lox-invite-dialog-connecting {
    
    924 930
       display: none;
    
    925 931
     }
    
    926 932
     
    
    933
    +#lox-invite-dialog-loading-icon {
    
    934
    +  flex: 0 0 auto;
    
    935
    +}
    
    936
    +
    
    937
    +#lox-invite-dialog-generate-area:not(.show-connecting) #lox-invite-dialog-loading-icon {
    
    938
    +  /* Use width:0 to effectively hide, but still occupy vertical space. */
    
    939
    +  width: 0;
    
    940
    +}
    
    941
    +
    
    927 942
     #lox-invite-dialog-list-label {
    
    928 943
       font-weight: 700;
    
    929 944
     }
    
    ... ... @@ -1019,6 +1034,8 @@ groupbox#torPreferences-bridges-group textarea {
    1019 1034
       flex: 0 0 auto;
    
    1020 1035
       margin-block: 8px 12px;
    
    1021 1036
       align-self: end;
    
    1037
    +  display: flex;
    
    1038
    +  align-items: center;
    
    1022 1039
     }
    
    1023 1040
     
    
    1024 1041
     #user-provide-bridge-message-area::after {
    
    ... ... @@ -1035,19 +1052,29 @@ groupbox#torPreferences-bridges-group textarea {
    1035 1052
       color: var(--in-content-error-text-color);
    
    1036 1053
     }
    
    1037 1054
     
    
    1038
    -#user-provide-bridge-error-message.not(.show-error) {
    
    1055
    +#user-provide-bridge-dialog:not(.show-error) #user-provide-bridge-error-message {
    
    1039 1056
       display: none;
    
    1040 1057
     }
    
    1041 1058
     
    
    1042 1059
     #user-provide-bridge-connecting {
    
    1043 1060
       color: var(--text-color-deemphasized);
    
    1044
    -  /* TODO: Add spinner ::before */
    
    1061
    +  /* Gap with #user-provide-bridge-loading-icon. */
    
    1062
    +  margin-inline-start: 0.5em;
    
    1045 1063
     }
    
    1046 1064
     
    
    1047
    -#user-provide-bridge-connecting:not(.show-connecting) {
    
    1065
    +#user-provide-bridge-dialog:not(.show-connecting) #user-provide-bridge-connecting {
    
    1048 1066
       display: none;
    
    1049 1067
     }
    
    1050 1068
     
    
    1069
    +#user-provide-bridge-loading-icon {
    
    1070
    +  flex: 0 0 auto;
    
    1071
    +}
    
    1072
    +
    
    1073
    +#user-provide-bridge-dialog:not(.show-connecting) #user-provide-bridge-loading-icon {
    
    1074
    +  /* Use width:0 to effectively hide, but still occupy vertical space. */
    
    1075
    +  width: 0;
    
    1076
    +}
    
    1077
    +
    
    1051 1078
     #user-provide-bridge-result-page {
    
    1052 1079
       flex: 1 1 0;
    
    1053 1080
       min-height: 0;
    
    ... ... @@ -1065,6 +1092,11 @@ groupbox#torPreferences-bridges-group textarea {
    1065 1092
       margin-block: 8px;
    
    1066 1093
     }
    
    1067 1094
     
    
    1095
    +#user-provide-bridge-grid-display:focus-visible {
    
    1096
    +  outline: var(--in-content-focus-outline);
    
    1097
    +  outline-offset: var(--in-content-focus-outline-offset);
    
    1098
    +}
    
    1099
    +
    
    1068 1100
     /* Connection settings dialog */
    
    1069 1101
     #torPreferences-connection-dialog label {
    
    1070 1102
       /* Do not wrap the labels. */
    

  • _______________________________________________
    tor-commits mailing list
    tor-commits@xxxxxxxxxxxxxxxxxxxx
    https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits