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 | + ) |