morgan pushed to branch tor-browser-128.4.0esr-14.5-1 at The Tor Project / Applications / Tor Browser
Commits:
-
a83dddb9
by Henry Wilkes at 2024-11-13T19:54:08+00:00
-
2073c1fa
by Henry Wilkes at 2024-11-13T19:54:08+00:00
10 changed files:
- browser/components/onionservices/content/authPopup.inc.xhtml
- browser/components/onionservices/content/authPreferences.css
- browser/components/onionservices/content/authPrompt.js
- browser/components/onionservices/content/savedKeysDialog.js
- browser/components/onionservices/content/savedKeysDialog.xhtml
- browser/components/torpreferences/content/connectionPane.js
- browser/components/torpreferences/content/loxInviteDialog.js
- browser/components/torpreferences/content/provideBridgeDialog.js
- browser/components/torpreferences/content/provideBridgeDialog.xhtml
- browser/components/torpreferences/content/torPreferences.css
Changes:
... | ... | @@ -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"
|
... | ... | @@ -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 | +} |
... | ... | @@ -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 | );
|
... | ... | @@ -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 |
... | ... | @@ -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
|
... | ... | @@ -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 | },
|
... | ... | @@ -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");
|
... | ... | @@ -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 {
|
... | ... | @@ -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"
|
... | ... | @@ -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;
|