morgan pushed to branch tor-browser-128.1.0esr-14.0-1 at The Tor Project / Applications / Tor Browser
Commits:
-
8a68fba1
by Henry Wilkes at 2024-08-21T19:22:49+00:00
-
49c2f08e
by Henry Wilkes at 2024-08-21T19:22:49+00:00
-
04d6d341
by Henry Wilkes at 2024-08-21T19:22:49+00:00
13 changed files:
- + browser/components/downloads/DownloadsTorWarning.sys.mjs
- browser/components/downloads/content/allDownloadsView.js
- browser/components/downloads/content/contentAreaDownloadsView.js
- browser/components/downloads/content/contentAreaDownloadsView.xhtml
- browser/components/downloads/content/downloads.css
- browser/components/downloads/content/downloads.js
- browser/components/downloads/content/downloadsPanel.inc.xhtml
- browser/components/downloads/moz.build
- browser/components/places/content/places.js
- browser/components/places/content/places.xhtml
- browser/themes/shared/downloads/downloads.inc.css
- toolkit/locales/en-US/toolkit/global/tor-browser.ftl
- + tools/torbrowser/l10n/migrations/bug-41820-moz-message-bar-download-warning.py
Changes:
| 1 | +/* import-globals-from /browser/base/content/utilityOverlay.js */
|
|
| 2 | + |
|
| 3 | +const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
|
|
| 4 | + |
|
| 5 | +/**
|
|
| 6 | + * Manages an instance of a tor warning.
|
|
| 7 | + */
|
|
| 8 | +export class DownloadsTorWarning {
|
|
| 9 | + /**
|
|
| 10 | + * Observer for showing or hiding the warning.
|
|
| 11 | + *
|
|
| 12 | + * @type {function}
|
|
| 13 | + */
|
|
| 14 | + #torWarningPrefObserver;
|
|
| 15 | + |
|
| 16 | + /**
|
|
| 17 | + * Whether the warning is active.
|
|
| 18 | + *
|
|
| 19 | + * @type {boolean}
|
|
| 20 | + */
|
|
| 21 | + #active = false;
|
|
| 22 | + |
|
| 23 | + /**
|
|
| 24 | + * The moz-message-bar element that should show the warning.
|
|
| 25 | + *
|
|
| 26 | + * @type {MozMessageBar}
|
|
| 27 | + */
|
|
| 28 | + #warningElement;
|
|
| 29 | + |
|
| 30 | + /**
|
|
| 31 | + * The dismiss button for the warning.
|
|
| 32 | + *
|
|
| 33 | + * @type {HTMLButton}
|
|
| 34 | + */
|
|
| 35 | + #dismissButton;
|
|
| 36 | + |
|
| 37 | + /**
|
|
| 38 | + * Attach to an instance of the tor warning.
|
|
| 39 | + *
|
|
| 40 | + * @param {MozMessageBar} warningElement - The warning element to initialize
|
|
| 41 | + * and attach to.
|
|
| 42 | + * @param {boolean} isChrome - Whether the element belongs to the chrome.
|
|
| 43 | + * Otherwise it belongs to content.
|
|
| 44 | + * @param {function} moveFocus - Callback to move the focus out of the warning
|
|
| 45 | + * when it is hidden.
|
|
| 46 | + * @param {function} [onLinkClick] - Callback that is called when a link is
|
|
| 47 | + * about to open.
|
|
| 48 | + */
|
|
| 49 | + constructor(warningElement, isChrome, moveFocus, onLinkClick) {
|
|
| 50 | + const doc = warningElement.ownerDocument;
|
|
| 51 | + this.#warningElement = warningElement;
|
|
| 52 | + warningElement.setAttribute(
|
|
| 53 | + "data-l10n-id",
|
|
| 54 | + "downloads-tor-warning-message-bar"
|
|
| 55 | + );
|
|
| 56 | + warningElement.setAttribute("data-l10n-attrs", "heading, message");
|
|
| 57 | + |
|
| 58 | + // Observe changes to the tor warning pref.
|
|
| 59 | + this.#torWarningPrefObserver = () => {
|
|
| 60 | + if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
|
|
| 61 | + warningElement.hidden = false;
|
|
| 62 | + } else {
|
|
| 63 | + const hadFocus = warningElement.contains(doc.activeElement);
|
|
| 64 | + warningElement.hidden = true;
|
|
| 65 | + if (hadFocus) {
|
|
| 66 | + moveFocus();
|
|
| 67 | + }
|
|
| 68 | + }
|
|
| 69 | + };
|
|
| 70 | + |
|
| 71 | + const tailsLink = doc.createElement("a");
|
|
| 72 | + tailsLink.setAttribute("slot", "support-link");
|
|
| 73 | + tailsLink.href = "https://tails.net/";
|
|
| 74 | + tailsLink.target = "_blank";
|
|
| 75 | + tailsLink.setAttribute("data-l10n-id", "downloads-tor-warning-tails-link");
|
|
| 76 | + if (isChrome) {
|
|
| 77 | + // Intercept clicks on the tails link.
|
|
| 78 | + tailsLink.addEventListener("click", event => {
|
|
| 79 | + event.preventDefault();
|
|
| 80 | + onLinkClick?.();
|
|
| 81 | + doc.defaultView.openWebLinkIn(tailsLink.href, "tab");
|
|
| 82 | + });
|
|
| 83 | + }
|
|
| 84 | + |
|
| 85 | + const dismissButton = doc.createElement("button");
|
|
| 86 | + dismissButton.setAttribute("slot", "actions");
|
|
| 87 | + dismissButton.setAttribute(
|
|
| 88 | + "data-l10n-id",
|
|
| 89 | + "downloads-tor-warning-dismiss-button"
|
|
| 90 | + );
|
|
| 91 | + if (isChrome) {
|
|
| 92 | + dismissButton.classList.add("footer-button");
|
|
| 93 | + }
|
|
| 94 | + |
|
| 95 | + dismissButton.addEventListener("click", () => {
|
|
| 96 | + Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
|
|
| 97 | + });
|
|
| 98 | + |
|
| 99 | + warningElement.append(tailsLink);
|
|
| 100 | + warningElement.append(dismissButton);
|
|
| 101 | + |
|
| 102 | + this.#dismissButton = dismissButton;
|
|
| 103 | + }
|
|
| 104 | + |
|
| 105 | + /**
|
|
| 106 | + * Whether the warning is hidden by the preference.
|
|
| 107 | + *
|
|
| 108 | + * @type {boolean}
|
|
| 109 | + */
|
|
| 110 | + get hidden() {
|
|
| 111 | + return this.#warningElement.hidden;
|
|
| 112 | + }
|
|
| 113 | + |
|
| 114 | + /**
|
|
| 115 | + * The dismiss button for the warning.
|
|
| 116 | + *
|
|
| 117 | + * @type {HTMLButton}
|
|
| 118 | + */
|
|
| 119 | + get dismissButton() {
|
|
| 120 | + return this.#dismissButton;
|
|
| 121 | + }
|
|
| 122 | + |
|
| 123 | + /**
|
|
| 124 | + * Activate the instance.
|
|
| 125 | + */
|
|
| 126 | + activate() {
|
|
| 127 | + if (this.#active) {
|
|
| 128 | + return;
|
|
| 129 | + }
|
|
| 130 | + this.#active = true;
|
|
| 131 | + Services.prefs.addObserver(
|
|
| 132 | + PREF_SHOW_DOWNLOAD_WARNING,
|
|
| 133 | + this.#torWarningPrefObserver
|
|
| 134 | + );
|
|
| 135 | + // Initialize.
|
|
| 136 | + this.#torWarningPrefObserver();
|
|
| 137 | + }
|
|
| 138 | + |
|
| 139 | + /**
|
|
| 140 | + * Deactivate the instance.
|
|
| 141 | + */
|
|
| 142 | + deactivate() {
|
|
| 143 | + if (!this.#active) {
|
|
| 144 | + return;
|
|
| 145 | + }
|
|
| 146 | + this.#active = false;
|
|
| 147 | + Services.prefs.removeObserver(
|
|
| 148 | + PREF_SHOW_DOWNLOAD_WARNING,
|
|
| 149 | + this.#torWarningPrefObserver
|
|
| 150 | + );
|
|
| 151 | + }
|
|
| 152 | +} |
| ... | ... | @@ -213,7 +213,6 @@ var DownloadsView = { |
| 213 | 213 | */
|
| 214 | 214 | function DownloadsPlacesView(
|
| 215 | 215 | aRichListBox,
|
| 216 | - torWarningMessageBar,
|
|
| 217 | 216 | aActive = true,
|
| 218 | 217 | aSuppressionFlag = DownloadsCommon.SUPPRESS_ALL_DOWNLOADS_OPEN
|
| 219 | 218 | ) {
|
| ... | ... | @@ -242,46 +241,6 @@ function DownloadsPlacesView( |
| 242 | 241 | aSuppressionFlag;
|
| 243 | 242 | }
|
| 244 | 243 | |
| 245 | - // Tor browser warning message/alert shown above the list.
|
|
| 246 | - |
|
| 247 | - const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
|
|
| 248 | - // Observe changes to the tor warning pref.
|
|
| 249 | - const torWarningPrefObserver = () => {
|
|
| 250 | - if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
|
|
| 251 | - torWarningMessageBar.hidden = false;
|
|
| 252 | - } else {
|
|
| 253 | - // Re-assign focus if it is about to be lost.
|
|
| 254 | - if (torWarningMessageBar.contains(document.activeElement)) {
|
|
| 255 | - // Try and focus the downloads list.
|
|
| 256 | - // NOTE: If #downloadsListBox is still hidden, this will do nothing.
|
|
| 257 | - // But in this case there are no other focusable targets within the
|
|
| 258 | - // view, so we just leave it up to the focus handler.
|
|
| 259 | - this._richlistbox.focus({ preventFocusRing: true });
|
|
| 260 | - }
|
|
| 261 | - torWarningMessageBar.hidden = true;
|
|
| 262 | - }
|
|
| 263 | - };
|
|
| 264 | - |
|
| 265 | - Services.prefs.addObserver(
|
|
| 266 | - PREF_SHOW_DOWNLOAD_WARNING,
|
|
| 267 | - torWarningPrefObserver
|
|
| 268 | - );
|
|
| 269 | - // Initialize.
|
|
| 270 | - torWarningPrefObserver();
|
|
| 271 | - |
|
| 272 | - window.addEventListener("unload", () => {
|
|
| 273 | - Services.prefs.removeObserver(
|
|
| 274 | - PREF_SHOW_DOWNLOAD_WARNING,
|
|
| 275 | - torWarningPrefObserver
|
|
| 276 | - );
|
|
| 277 | - });
|
|
| 278 | - |
|
| 279 | - torWarningMessageBar
|
|
| 280 | - .querySelector(".downloads-tor-warning-dismiss-button")
|
|
| 281 | - .addEventListener("click", () => {
|
|
| 282 | - Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
|
|
| 283 | - });
|
|
| 284 | - |
|
| 285 | 244 | // Make sure to unregister the view if the window is closed.
|
| 286 | 245 | window.addEventListener(
|
| 287 | 246 | "unload",
|
| ... | ... | @@ -8,12 +8,30 @@ const { PrivateBrowsingUtils } = ChromeUtils.importESModule( |
| 8 | 8 | "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
|
| 9 | 9 | );
|
| 10 | 10 | |
| 11 | +const { DownloadsTorWarning } = ChromeUtils.importESModule(
|
|
| 12 | + "resource:///modules/DownloadsTorWarning.sys.mjs"
|
|
| 13 | +);
|
|
| 14 | + |
|
| 11 | 15 | var ContentAreaDownloadsView = {
|
| 12 | 16 | init() {
|
| 13 | - const torWarningMessage = document.getElementById(
|
|
| 14 | - "aboutDownloadsTorWarning"
|
|
| 15 | - );
|
|
| 16 | 17 | let box = document.getElementById("downloadsListBox");
|
| 18 | + |
|
| 19 | + const torWarning = new DownloadsTorWarning(
|
|
| 20 | + document.getElementById("aboutDownloadsTorWarning"),
|
|
| 21 | + false,
|
|
| 22 | + () => {
|
|
| 23 | + // Try and focus the downloads list.
|
|
| 24 | + // NOTE: If #downloadsListBox is still hidden, this will do nothing.
|
|
| 25 | + // But in this case there are no other focusable targets within the
|
|
| 26 | + // view, so we just leave it up to the focus handler.
|
|
| 27 | + box.focus({ preventFocusRing: true });
|
|
| 28 | + }
|
|
| 29 | + );
|
|
| 30 | + torWarning.activate();
|
|
| 31 | + window.addEventListener("unload", () => {
|
|
| 32 | + torWarning.deactivate();
|
|
| 33 | + });
|
|
| 34 | + |
|
| 17 | 35 | let suppressionFlag = DownloadsCommon.SUPPRESS_CONTENT_AREA_DOWNLOADS_OPEN;
|
| 18 | 36 | box.addEventListener(
|
| 19 | 37 | "InitialDownloadsLoaded",
|
| ... | ... | @@ -30,7 +48,7 @@ var ContentAreaDownloadsView = { |
| 30 | 48 | // experience was bad.
|
| 31 | 49 | // Without auto-focusing the downloads list, a screen reader should not
|
| 32 | 50 | // skip beyond the alert's content.
|
| 33 | - if (torWarningMessage.hidden) {
|
|
| 51 | + if (torWarning.hidden) {
|
|
| 34 | 52 | document
|
| 35 | 53 | .getElementById("downloadsListBox")
|
| 36 | 54 | .focus({ focusVisible: false });
|
| ... | ... | @@ -44,12 +62,7 @@ var ContentAreaDownloadsView = { |
| 44 | 62 | },
|
| 45 | 63 | { once: true }
|
| 46 | 64 | );
|
| 47 | - let view = new DownloadsPlacesView(
|
|
| 48 | - box,
|
|
| 49 | - torWarningMessage,
|
|
| 50 | - true,
|
|
| 51 | - suppressionFlag
|
|
| 52 | - );
|
|
| 65 | + let view = new DownloadsPlacesView(box, true, suppressionFlag);
|
|
| 53 | 66 | document.addEventListener("visibilitychange", () => {
|
| 54 | 67 | let indicator = DownloadsCommon.getIndicatorData(window);
|
| 55 | 68 | if (document.visibilityState === "visible") {
|
| ... | ... | @@ -49,36 +49,7 @@ |
| 49 | 49 | </keyset>
|
| 50 | 50 | #endif
|
| 51 | 51 | |
| 52 | - <html:message-bar
|
|
| 53 | - id="aboutDownloadsTorWarning"
|
|
| 54 | - class="downloads-tor-warning-message-bar"
|
|
| 55 | - role="alert"
|
|
| 56 | - aria-labelledby="aboutDownloadsTorWarningTitle"
|
|
| 57 | - aria-describedby="aboutDownloadsTorWarningDescription"
|
|
| 58 | - >
|
|
| 59 | - <html:div class="downloads-tor-warning-grid">
|
|
| 60 | - <html:p
|
|
| 61 | - id="aboutDownloadsTorWarningTitle"
|
|
| 62 | - class="downloads-tor-warning-title"
|
|
| 63 | - data-l10n-id="downloads-tor-warning-title"
|
|
| 64 | - ></html:p>
|
|
| 65 | - <html:p
|
|
| 66 | - id="aboutDownloadsTorWarningDescription"
|
|
| 67 | - class="downloads-tor-warning-description"
|
|
| 68 | - data-l10n-id="downloads-tor-warning-description"
|
|
| 69 | - >
|
|
| 70 | - <html:a
|
|
| 71 | - href="https://tails.net/"
|
|
| 72 | - target="_blank"
|
|
| 73 | - data-l10n-name="tails-link"
|
|
| 74 | - ></html:a>
|
|
| 75 | - </html:p>
|
|
| 76 | - <html:button
|
|
| 77 | - class="downloads-tor-warning-dismiss-button"
|
|
| 78 | - data-l10n-id="downloads-tor-warning-dismiss-button"
|
|
| 79 | - ></html:button>
|
|
| 80 | - </html:div>
|
|
| 81 | - </html:message-bar>
|
|
| 52 | + <html:moz-message-bar id="aboutDownloadsTorWarning"></html:moz-message-bar>
|
|
| 82 | 53 | |
| 83 | 54 | <richlistbox flex="1"
|
| 84 | 55 | seltype="multiple"
|
| ... | ... | @@ -92,63 +92,13 @@ |
| 92 | 92 | #downloadsPanel-mainView {
|
| 93 | 93 | min-width: 37em;
|
| 94 | 94 | padding: 0.62em;
|
| 95 | - /* If we don't set a width, #downloadsPanelTorWarningDescription will request
|
|
| 95 | + /* If we don't set a width, #downloadsPanelTorWarning will request
|
|
| 96 | 96 | * its max-content width. */
|
| 97 | 97 | width: 37em;
|
| 98 | 98 | }
|
| 99 | 99 | |
| 100 | -#downloadsPanel-mainView {
|
|
| 101 | - /* Fix the layout to ensure the #downloadsWarningDescription is given enough
|
|
| 102 | - * vertical space. For tor-browser#40701.
|
|
| 103 | - * TODO: May no longer be necessary after esr 115 due to bugzilla bug 1816455.
|
|
| 104 | - */
|
|
| 105 | - display: flex;
|
|
| 106 | - flex-direction: column;
|
|
| 107 | -}
|
|
| 108 | - |
|
| 109 | -.downloads-tor-warning-grid {
|
|
| 110 | - display: grid;
|
|
| 111 | - grid-template:
|
|
| 112 | - "title button" min-content
|
|
| 113 | - "description button" auto
|
|
| 114 | - / 1fr max-content;
|
|
| 115 | - gap: 8px;
|
|
| 116 | - margin-block: 8px;
|
|
| 117 | - /* Some extra space between the text and the icon. */
|
|
| 118 | - margin-inline-start: 8px;
|
|
| 119 | -}
|
|
| 120 | - |
|
| 121 | -.downloads-tor-warning-grid .downloads-tor-warning-title {
|
|
| 122 | - grid-area: title;
|
|
| 123 | - margin: 0;
|
|
| 124 | -}
|
|
| 125 | - |
|
| 126 | -.downloads-tor-warning-grid .downloads-tor-warning-description {
|
|
| 127 | - grid-area: description;
|
|
| 128 | - margin: 0;
|
|
| 129 | -}
|
|
| 130 | - |
|
| 131 | -.downloads-tor-warning-grid .downloads-tor-warning-dismiss-button {
|
|
| 132 | - grid-area: button;
|
|
| 133 | - align-self: center;
|
|
| 134 | -}
|
|
| 135 | - |
|
| 136 | -.downloads-tor-warning-description,
|
|
| 137 | -.downloads-tor-warning-title {
|
|
| 138 | - line-height: 1.4;
|
|
| 139 | -}
|
|
| 140 | - |
|
| 141 | -.downloads-tor-warning-title {
|
|
| 142 | - font-weight: bold;
|
|
| 143 | -}
|
|
| 144 | - |
|
| 145 | -#downloadsPanelTorWarning :is(
|
|
| 146 | - .downloads-tor-warning-description,
|
|
| 147 | - .downloads-tor-warning-title
|
|
| 148 | -) {
|
|
| 149 | - padding-inline: 8px;
|
|
| 150 | - margin-block-start: 8px;
|
|
| 151 | - margin-block-end: 0;
|
|
| 100 | +#downloadsPanelTorWarning {
|
|
| 101 | + margin-block-end: var(--arrowpanel-menuitem-padding-block);
|
|
| 152 | 102 | }
|
| 153 | 103 | |
| 154 | 104 | #downloadsHistory,
|
| ... | ... | @@ -31,8 +31,6 @@ |
| 31 | 31 | |
| 32 | 32 | "use strict";
|
| 33 | 33 | |
| 34 | -const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
|
|
| 35 | - |
|
| 36 | 34 | var { XPCOMUtils } = ChromeUtils.importESModule(
|
| 37 | 35 | "resource://gre/modules/XPCOMUtils.sys.mjs"
|
| 38 | 36 | );
|
| ... | ... | @@ -42,6 +40,7 @@ ChromeUtils.defineESModuleGetters(this, { |
| 42 | 40 | FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
|
| 43 | 41 | NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
|
| 44 | 42 | PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
|
| 43 | + DownloadsTorWarning: "resource:///modules/DownloadsTorWarning.sys.mjs",
|
|
| 45 | 44 | });
|
| 46 | 45 | |
| 47 | 46 | const { Integration } = ChromeUtils.importESModule(
|
| ... | ... | @@ -76,11 +75,11 @@ var DownloadsPanel = { |
| 76 | 75 | _waitingDataForOpen: false,
|
| 77 | 76 | |
| 78 | 77 | /**
|
| 79 | - * State of tor's download warning. It should only be initialized once (text assigned,
|
|
| 80 | - * button commands assigned). This tracks if that has been performed and prevents
|
|
| 81 | - * repeats.
|
|
| 78 | + * Tracks whether to show the tor warning or not.
|
|
| 79 | + *
|
|
| 80 | + * @type {?DownloadsTorWarning}
|
|
| 82 | 81 | */
|
| 83 | - _torWarningInitialized: false,
|
|
| 82 | + _torWarning: null,
|
|
| 84 | 83 | |
| 85 | 84 | /**
|
| 86 | 85 | * Starts loading the download data in background, without opening the panel.
|
| ... | ... | @@ -98,30 +97,20 @@ var DownloadsPanel = { |
| 98 | 97 | );
|
| 99 | 98 | }
|
| 100 | 99 | |
| 101 | - const torWarningMessage = document.getElementById(
|
|
| 102 | - "downloadsPanelTorWarning"
|
|
| 103 | - );
|
|
| 104 | - if (!this._torWarningPrefObserver) {
|
|
| 105 | - // Observe changes to the tor warning pref.
|
|
| 106 | - this._torWarningPrefObserver = () => {
|
|
| 107 | - if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
|
|
| 108 | - torWarningMessage.hidden = false;
|
|
| 109 | - } else {
|
|
| 110 | - const hadFocus = torWarningMessage.contains(document.activeElement);
|
|
| 111 | - torWarningMessage.hidden = true;
|
|
| 100 | + if (!this._torWarning) {
|
|
| 101 | + this._torWarning = new DownloadsTorWarning(
|
|
| 102 | + document.getElementById("downloadsPanelTorWarning"),
|
|
| 103 | + true,
|
|
| 104 | + () => {
|
|
| 112 | 105 | // Re-assign focus that was lost.
|
| 113 | - if (hadFocus) {
|
|
| 114 | - this._focusPanel(true);
|
|
| 115 | - }
|
|
| 106 | + this._focusPanel(true);
|
|
| 107 | + },
|
|
| 108 | + () => {
|
|
| 109 | + this.hidePanel();
|
|
| 116 | 110 | }
|
| 117 | - };
|
|
| 118 | - Services.prefs.addObserver(
|
|
| 119 | - PREF_SHOW_DOWNLOAD_WARNING,
|
|
| 120 | - this._torWarningPrefObserver
|
|
| 121 | 111 | );
|
| 122 | - // Initialize
|
|
| 123 | - this._torWarningPrefObserver();
|
|
| 124 | 112 | }
|
| 113 | + this._torWarning.activate();
|
|
| 125 | 114 | |
| 126 | 115 | if (this._initialized) {
|
| 127 | 116 | DownloadsCommon.log("DownloadsPanel is already initialized.");
|
| ... | ... | @@ -149,33 +138,6 @@ var DownloadsPanel = { |
| 149 | 138 | DownloadsSummary
|
| 150 | 139 | );
|
| 151 | 140 | |
| 152 | - if (!this._torWarningInitialized) {
|
|
| 153 | - // Intercept clicks on the tails link.
|
|
| 154 | - // NOTE: We listen for clicks on the parent instead of the
|
|
| 155 | - // <a data-l10n-name="tails-link"> element because the latter may be
|
|
| 156 | - // swapped for a new instance by Fluent when refreshing the parent.
|
|
| 157 | - torWarningMessage
|
|
| 158 | - .querySelector(".downloads-tor-warning-description")
|
|
| 159 | - .addEventListener("click", event => {
|
|
| 160 | - const tailsLink = event.target.closest(
|
|
| 161 | - ".downloads-tor-warning-tails-link"
|
|
| 162 | - );
|
|
| 163 | - if (!tailsLink) {
|
|
| 164 | - return;
|
|
| 165 | - }
|
|
| 166 | - event.preventDefault();
|
|
| 167 | - this.hidePanel();
|
|
| 168 | - openWebLinkIn(tailsLink.href, "tab");
|
|
| 169 | - });
|
|
| 170 | - |
|
| 171 | - torWarningMessage
|
|
| 172 | - .querySelector(".downloads-tor-warning-dismiss-button")
|
|
| 173 | - .addEventListener("click", () => {
|
|
| 174 | - Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
|
|
| 175 | - });
|
|
| 176 | - this._torWarningInitialized = true;
|
|
| 177 | - }
|
|
| 178 | - |
|
| 179 | 141 | DownloadsCommon.log(
|
| 180 | 142 | "DownloadsView attached - the panel for this window",
|
| 181 | 143 | "should now see download items come in."
|
| ... | ... | @@ -218,13 +180,7 @@ var DownloadsPanel = { |
| 218 | 180 | DownloadIntegration.downloadSpamProtection.unregister(window);
|
| 219 | 181 | }
|
| 220 | 182 | |
| 221 | - if (this._torWarningPrefObserver) {
|
|
| 222 | - Services.prefs.removeObserver(
|
|
| 223 | - PREF_SHOW_DOWNLOAD_WARNING,
|
|
| 224 | - this._torWarningPrefObserver
|
|
| 225 | - );
|
|
| 226 | - delete this._torWarningPrefObserver;
|
|
| 227 | - }
|
|
| 183 | + this._torWarning?.deactivate();
|
|
| 228 | 184 | |
| 229 | 185 | this._initialized = false;
|
| 230 | 186 | |
| ... | ... | @@ -582,13 +538,8 @@ var DownloadsPanel = { |
| 582 | 538 | // Focus the "Got it" button if it is visible.
|
| 583 | 539 | // This should ensure that the alert is read aloud by Orca when the
|
| 584 | 540 | // downloads panel is opened. See tor-browser#42642.
|
| 585 | - const torWarningMessage = document.getElementById(
|
|
| 586 | - "downloadsPanelTorWarning"
|
|
| 587 | - );
|
|
| 588 | - if (!torWarningMessage.hidden) {
|
|
| 589 | - torWarningMessage
|
|
| 590 | - .querySelector(".downloads-tor-warning-dismiss-button")
|
|
| 591 | - .focus(focusOptions);
|
|
| 541 | + if (!this._torWarning?.hidden) {
|
|
| 542 | + this._torWarning.dismissButton.focus(focusOptions);
|
|
| 592 | 543 | return;
|
| 593 | 544 | }
|
| 594 | 545 |
| ... | ... | @@ -104,37 +104,8 @@ |
| 104 | 104 | disablekeynav="true">
|
| 105 | 105 | |
| 106 | 106 | <panelview id="downloadsPanel-mainView">
|
| 107 | - <vbox id="downloadsPanelTorWarning">
|
|
| 108 | - <vbox
|
|
| 109 | - role="alert"
|
|
| 110 | - aria-labelledby="downloadsPanelTorWarningTitle"
|
|
| 111 | - aria-describedby="downloadsPanelTorWarningDescription"
|
|
| 112 | - >
|
|
| 113 | - <html:p
|
|
| 114 | - id="downloadsPanelTorWarningTitle"
|
|
| 115 | - class="downloads-tor-warning-title"
|
|
| 116 | - data-l10n-id="downloads-tor-warning-title"
|
|
| 117 | - ></html:p>
|
|
| 118 | - <html:p
|
|
| 119 | - id="downloadsPanelTorWarningDescription"
|
|
| 120 | - class="downloads-tor-warning-description"
|
|
| 121 | - data-l10n-id="downloads-tor-warning-description"
|
|
| 122 | - >
|
|
| 123 | - <html:a
|
|
| 124 | - href="https://tails.net/"
|
|
| 125 | - data-l10n-name="tails-link"
|
|
| 126 | - class="downloads-tor-warning-tails-link"
|
|
| 127 | - ></html:a>
|
|
| 128 | - </html:p>
|
|
| 129 | - <html:moz-button-group class="panel-footer">
|
|
| 130 | - <html:button
|
|
| 131 | - class="footer-button downloads-tor-warning-dismiss-button"
|
|
| 132 | - data-l10n-id="downloads-tor-warning-dismiss-button"
|
|
| 133 | - ></html:button>
|
|
| 134 | - </html:moz-button-group>
|
|
| 135 | - </vbox>
|
|
| 136 | - <toolbarseparator />
|
|
| 137 | - </vbox>
|
|
| 107 | + <html:moz-message-bar id="downloadsPanelTorWarning">
|
|
| 108 | + </html:moz-message-bar>
|
|
| 138 | 109 | <vbox class="panel-view-body-unscrollable">
|
| 139 | 110 | <richlistbox id="downloadsListBox"
|
| 140 | 111 | data-l10n-id="downloads-panel-items"
|
| ... | ... | @@ -15,6 +15,7 @@ EXTRA_JS_MODULES += [ |
| 15 | 15 | "DownloadsCommon.sys.mjs",
|
| 16 | 16 | "DownloadSpamProtection.sys.mjs",
|
| 17 | 17 | "DownloadsTaskbar.sys.mjs",
|
| 18 | + "DownloadsTorWarning.sys.mjs",
|
|
| 18 | 19 | "DownloadsViewableInternally.sys.mjs",
|
| 19 | 20 | "DownloadsViewUI.sys.mjs",
|
| 20 | 21 | ]
|
| ... | ... | @@ -6,7 +6,6 @@ |
| 6 | 6 | /* import-globals-from editBookmark.js */
|
| 7 | 7 | /* import-globals-from /toolkit/content/contentAreaUtils.js */
|
| 8 | 8 | /* import-globals-from /browser/components/downloads/content/allDownloadsView.js */
|
| 9 | -/* import-globals-from /browser/base/content/utilityOverlay.js */
|
|
| 10 | 9 | |
| 11 | 10 | /* Shared Places Import - change other consumers if you change this: */
|
| 12 | 11 | var { XPCOMUtils } = ChromeUtils.importESModule(
|
| ... | ... | @@ -18,6 +17,7 @@ ChromeUtils.defineESModuleGetters(this, { |
| 18 | 17 | PlacesBackups: "resource://gre/modules/PlacesBackups.sys.mjs",
|
| 19 | 18 | PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
|
| 20 | 19 | DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
|
| 20 | + DownloadsTorWarning: "resource:///modules/DownloadsTorWarning.sys.mjs",
|
|
| 21 | 21 | });
|
| 22 | 22 | XPCOMUtils.defineLazyScriptGetter(
|
| 23 | 23 | this,
|
| ... | ... | @@ -158,15 +158,25 @@ var PlacesOrganizer = { |
| 158 | 158 | "&sort=" +
|
| 159 | 159 | Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
|
| 160 | 160 | |
| 161 | - const torWarningMessage = document.getElementById(
|
|
| 162 | - "placesDownloadsTorWarning"
|
|
| 161 | + const torWarning = new DownloadsTorWarning(
|
|
| 162 | + document.getElementById("placesDownloadsTorWarning"),
|
|
| 163 | + true,
|
|
| 164 | + () => {
|
|
| 165 | + document
|
|
| 166 | + .getElementById("downloadsListBox")
|
|
| 167 | + .focus({ preventFocusRing: true });
|
|
| 168 | + }
|
|
| 163 | 169 | );
|
| 170 | + torWarning.activate();
|
|
| 171 | + window.addEventListener("unload", () => {
|
|
| 172 | + torWarning.deactivate();
|
|
| 173 | + });
|
|
| 174 | + |
|
| 164 | 175 | ContentArea.setContentViewForQueryString(
|
| 165 | 176 | DOWNLOADS_QUERY,
|
| 166 | 177 | () =>
|
| 167 | 178 | new DownloadsPlacesView(
|
| 168 | 179 | document.getElementById("downloadsListBox"),
|
| 169 | - torWarningMessage,
|
|
| 170 | 180 | false
|
| 171 | 181 | ),
|
| 172 | 182 | {
|
| ... | ... | @@ -176,23 +186,6 @@ var PlacesOrganizer = { |
| 176 | 186 | }
|
| 177 | 187 | );
|
| 178 | 188 | |
| 179 | - // Intercept clicks on the tor warning tails link.
|
|
| 180 | - // NOTE: We listen for clicks on the parent instead of the
|
|
| 181 | - // <a data-l10n-name="tails-link"> element because the latter may be
|
|
| 182 | - // swapped for a new instance by Fluent when refreshing the parent.
|
|
| 183 | - document
|
|
| 184 | - .querySelector(".downloads-tor-warning-description")
|
|
| 185 | - .addEventListener("click", event => {
|
|
| 186 | - const tailsLink = event.target.closest(
|
|
| 187 | - ".downloads-tor-warning-tails-link"
|
|
| 188 | - );
|
|
| 189 | - if (!tailsLink) {
|
|
| 190 | - return;
|
|
| 191 | - }
|
|
| 192 | - event.preventDefault();
|
|
| 193 | - openWebLinkIn(tailsLink.href, "tab");
|
|
| 194 | - });
|
|
| 195 | - |
|
| 196 | 189 | ContentArea.init();
|
| 197 | 190 | |
| 198 | 191 | this._places = document.getElementById("placesList");
|
| ... | ... | @@ -1432,6 +1425,7 @@ var ContentArea = { |
| 1432 | 1425 | oldView.associatedElement.hidden = true;
|
| 1433 | 1426 | aNewView.associatedElement.hidden = false;
|
| 1434 | 1427 | |
| 1428 | + // Hide the Tor warning when not in the downloads view.
|
|
| 1435 | 1429 | const isDownloads = aNewView.associatedElement.id === "downloadsListBox";
|
| 1436 | 1430 | const torWarningMessage = document.getElementById(
|
| 1437 | 1431 | "placesDownloadsTorWarning"
|
| ... | ... | @@ -363,35 +363,8 @@ |
| 363 | 363 | </tree>
|
| 364 | 364 | <splitter collapse="none" persist="state"></splitter>
|
| 365 | 365 | <vbox id="contentView">
|
| 366 | - <html:message-bar
|
|
| 367 | - id="placesDownloadsTorWarning"
|
|
| 368 | - role="alert"
|
|
| 369 | - aria-labelledby="placesDownloadsTorWarningTitle"
|
|
| 370 | - aria-describedby="placesDownloadsTorWarningDescription"
|
|
| 371 | - >
|
|
| 372 | - <html:div class="downloads-tor-warning-grid">
|
|
| 373 | - <html:p
|
|
| 374 | - id="placesDownloadsTorWarningTitle"
|
|
| 375 | - class="downloads-tor-warning-title"
|
|
| 376 | - data-l10n-id="downloads-tor-warning-title"
|
|
| 377 | - ></html:p>
|
|
| 378 | - <html:p
|
|
| 379 | - id="placesDownloadsTorWarningDescription"
|
|
| 380 | - class="downloads-tor-warning-description"
|
|
| 381 | - data-l10n-id="downloads-tor-warning-description"
|
|
| 382 | - >
|
|
| 383 | - <html:a
|
|
| 384 | - href="https://tails.net/"
|
|
| 385 | - class="downloads-tor-warning-tails-link"
|
|
| 386 | - data-l10n-name="tails-link"
|
|
| 387 | - ></html:a>
|
|
| 388 | - </html:p>
|
|
| 389 | - <html:button
|
|
| 390 | - class="downloads-tor-warning-dismiss-button"
|
|
| 391 | - data-l10n-id="downloads-tor-warning-dismiss-button"
|
|
| 392 | - ></html:button>
|
|
| 393 | - </html:div>
|
|
| 394 | - </html:message-bar>
|
|
| 366 | + <html:moz-message-bar id="placesDownloadsTorWarning">
|
|
| 367 | + </html:moz-message-bar>
|
|
| 395 | 368 | <vbox id="placesViewsBox" flex="1">
|
| 396 | 369 | <tree id="placeContent"
|
| 397 | 370 | class="placesTree"
|
| ... | ... | @@ -252,7 +252,6 @@ |
| 252 | 252 | }
|
| 253 | 253 | |
| 254 | 254 | /*** Toolbarseparator ***/
|
| 255 | -#downloadsPanelTorWarning toolbarseparator,
|
|
| 256 | 255 | #downloadsFooterButtons > toolbarseparator {
|
| 257 | 256 | margin-inline: 0;
|
| 258 | 257 | } |
| ... | ... | @@ -559,9 +559,13 @@ crypto-safety-prompt-dismiss-button = Dismiss Warning |
| 559 | 559 | ## Downloads warning.
|
| 560 | 560 | ## Shown in downloads panel, about:downloads and Library window.
|
| 561 | 561 | |
| 562 | -downloads-tor-warning-title = Be careful opening downloads
|
|
| 563 | -# "Tails" is the brand name for the Tails operating system and should be localized appropriately, and will be a link to its website. The name should be wrapped in '<a data-l10n-name="tails-link">' and '</a>'.
|
|
| 564 | -downloads-tor-warning-description = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like <a data-l10n-name="tails-link">Tails</a>.
|
|
| 562 | +# "Tails" is the brand name for the Tails operating system and should be localized appropriately.
|
|
| 563 | +downloads-tor-warning-message-bar =
|
|
| 564 | + .heading = Be careful opening downloads
|
|
| 565 | + .message = Some files may connect to the internet when opened without using Tor. To be safe, open the files while offline or use a portable operating system like Tails.
|
|
| 566 | +# This will be a link to the Tails operating system website.
|
|
| 567 | +# "Tails" is the brand name for the Tails operating system and should be localized appropriately.
|
|
| 568 | +downloads-tor-warning-tails-link= Learn more about Tails
|
|
| 565 | 569 | # Button to dismiss the warning forever.
|
| 566 | 570 | downloads-tor-warning-dismiss-button = Got it
|
| 567 | 571 |
| 1 | +import re
|
|
| 2 | + |
|
| 3 | +import fluent.syntax.ast as FTL
|
|
| 4 | +from fluent.migrate.transforms import COPY_PATTERN, FluentSource
|
|
| 5 | +from fluent.syntax.visitor import Visitor
|
|
| 6 | + |
|
| 7 | + |
|
| 8 | +class RemoveAnchorVisitor(Visitor):
|
|
| 9 | + """Class to remove <a> and </a> wrappers from a Fluent TextElement."""
|
|
| 10 | + |
|
| 11 | + def __init__(self):
|
|
| 12 | + # Good enough regex for our needs that will match starting and ending
|
|
| 13 | + # tags.
|
|
| 14 | + self._anchor_regex = re.compile(r"<\/?[aA](| [^>]*)>")
|
|
| 15 | + super().__init__()
|
|
| 16 | + |
|
| 17 | + def visit_TextElement(self, node):
|
|
| 18 | + node.value = self._anchor_regex.sub("", node.value)
|
|
| 19 | + |
|
| 20 | + |
|
| 21 | +class RemoveAnchorTransform(FluentSource):
|
|
| 22 | + """Class to remove <a> and </a> wrappers from a Fluent source."""
|
|
| 23 | + |
|
| 24 | + def __call__(self, ctx):
|
|
| 25 | + pattern = ctx.get_fluent_source_pattern(self.path, self.key).clone()
|
|
| 26 | + # Visit every node in the pattern, replacing each TextElement's content.
|
|
| 27 | + RemoveAnchorVisitor().visit(pattern)
|
|
| 28 | + return pattern
|
|
| 29 | + |
|
| 30 | + |
|
| 31 | +def migrate(ctx):
|
|
| 32 | + # Convert
|
|
| 33 | + #
|
|
| 34 | + # downloads-tor-warning-title = A
|
|
| 35 | + # downloads-tor-warning-description = B<a data-l10n-name="tails-link">C</a>D
|
|
| 36 | + #
|
|
| 37 | + # to
|
|
| 38 | + #
|
|
| 39 | + # downloads-tor-warning-message-bar =
|
|
| 40 | + # .heading = A
|
|
| 41 | + # .message = BCD
|
|
| 42 | + ctx.add_transforms(
|
|
| 43 | + "tor-browser.ftl",
|
|
| 44 | + "tor-browser.ftl",
|
|
| 45 | + [
|
|
| 46 | + FTL.Message(
|
|
| 47 | + id=FTL.Identifier("downloads-tor-warning-message-bar"),
|
|
| 48 | + value=None,
|
|
| 49 | + attributes=[
|
|
| 50 | + FTL.Attribute(
|
|
| 51 | + id=FTL.Identifier("heading"),
|
|
| 52 | + value=COPY_PATTERN(
|
|
| 53 | + "tor-browser.ftl",
|
|
| 54 | + "downloads-tor-warning-title",
|
|
| 55 | + ),
|
|
| 56 | + ),
|
|
| 57 | + FTL.Attribute(
|
|
| 58 | + id=FTL.Identifier("message"),
|
|
| 59 | + value=RemoveAnchorTransform(
|
|
| 60 | + "tor-browser.ftl",
|
|
| 61 | + "downloads-tor-warning-description",
|
|
| 62 | + ),
|
|
| 63 | + ),
|
|
| 64 | + ],
|
|
| 65 | + ),
|
|
| 66 | + ],
|
|
| 67 | + ) |