[tbb-commits] [Git][tpo/applications/tor-browser][tor-browser-128.1.0esr-14.0-1] 3 commits: fixup! Bug 40701: Add security warning when downloading a file

morgan (@morgan) git at gitlab.torproject.org
Wed Aug 21 19:23:27 UTC 2024



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
fixup! Bug 40701: Add security warning when downloading a file

Bug 41820: Convert downloads warning to moz-message-bar.

Move the logic to DownloadsTorWarning.sys.mjs so it remains in one
place.

- - - - -
49c2f08e by Henry Wilkes at 2024-08-21T19:22:49+00:00
fixup! Tor Browser strings

Bug 41820: Use moz-message-bar for the downloads warning.

- - - - -
04d6d341 by Henry Wilkes at 2024-08-21T19:22:49+00:00
fixup! Tor Browser localization migration scripts.

Bug 41820: Use moz-message-bar for the downloads warning.

We add a migration to convert the old string values into the new value.

- - - - -


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:

=====================================
browser/components/downloads/DownloadsTorWarning.sys.mjs
=====================================
@@ -0,0 +1,152 @@
+/* import-globals-from /browser/base/content/utilityOverlay.js */
+
+const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
+
+/**
+ * Manages an instance of a tor warning.
+ */
+export class DownloadsTorWarning {
+  /**
+   * Observer for showing or hiding the warning.
+   *
+   * @type {function}
+   */
+  #torWarningPrefObserver;
+
+  /**
+   * Whether the warning is active.
+   *
+   * @type {boolean}
+   */
+  #active = false;
+
+  /**
+   * The moz-message-bar element that should show the warning.
+   *
+   * @type {MozMessageBar}
+   */
+  #warningElement;
+
+  /**
+   * The dismiss button for the warning.
+   *
+   * @type {HTMLButton}
+   */
+  #dismissButton;
+
+  /**
+   * Attach to an instance of the tor warning.
+   *
+   * @param {MozMessageBar} warningElement - The warning element to initialize
+   *   and attach to.
+   * @param {boolean} isChrome - Whether the element belongs to the chrome.
+   *   Otherwise it belongs to content.
+   * @param {function} moveFocus - Callback to move the focus out of the warning
+   *   when it is hidden.
+   * @param {function} [onLinkClick] - Callback that is called when a link is
+   *   about to open.
+   */
+  constructor(warningElement, isChrome, moveFocus, onLinkClick) {
+    const doc = warningElement.ownerDocument;
+    this.#warningElement = warningElement;
+    warningElement.setAttribute(
+      "data-l10n-id",
+      "downloads-tor-warning-message-bar"
+    );
+    warningElement.setAttribute("data-l10n-attrs", "heading, message");
+
+    // Observe changes to the tor warning pref.
+    this.#torWarningPrefObserver = () => {
+      if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
+        warningElement.hidden = false;
+      } else {
+        const hadFocus = warningElement.contains(doc.activeElement);
+        warningElement.hidden = true;
+        if (hadFocus) {
+          moveFocus();
+        }
+      }
+    };
+
+    const tailsLink = doc.createElement("a");
+    tailsLink.setAttribute("slot", "support-link");
+    tailsLink.href = "https://tails.net/";
+    tailsLink.target = "_blank";
+    tailsLink.setAttribute("data-l10n-id", "downloads-tor-warning-tails-link");
+    if (isChrome) {
+      // Intercept clicks on the tails link.
+      tailsLink.addEventListener("click", event => {
+        event.preventDefault();
+        onLinkClick?.();
+        doc.defaultView.openWebLinkIn(tailsLink.href, "tab");
+      });
+    }
+
+    const dismissButton = doc.createElement("button");
+    dismissButton.setAttribute("slot", "actions");
+    dismissButton.setAttribute(
+      "data-l10n-id",
+      "downloads-tor-warning-dismiss-button"
+    );
+    if (isChrome) {
+      dismissButton.classList.add("footer-button");
+    }
+
+    dismissButton.addEventListener("click", () => {
+      Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
+    });
+
+    warningElement.append(tailsLink);
+    warningElement.append(dismissButton);
+
+    this.#dismissButton = dismissButton;
+  }
+
+  /**
+   * Whether the warning is hidden by the preference.
+   *
+   * @type {boolean}
+   */
+  get hidden() {
+    return this.#warningElement.hidden;
+  }
+
+  /**
+   * The dismiss button for the warning.
+   *
+   * @type {HTMLButton}
+   */
+  get dismissButton() {
+    return this.#dismissButton;
+  }
+
+  /**
+   * Activate the instance.
+   */
+  activate() {
+    if (this.#active) {
+      return;
+    }
+    this.#active = true;
+    Services.prefs.addObserver(
+      PREF_SHOW_DOWNLOAD_WARNING,
+      this.#torWarningPrefObserver
+    );
+    // Initialize.
+    this.#torWarningPrefObserver();
+  }
+
+  /**
+   * Deactivate the instance.
+   */
+  deactivate() {
+    if (!this.#active) {
+      return;
+    }
+    this.#active = false;
+    Services.prefs.removeObserver(
+      PREF_SHOW_DOWNLOAD_WARNING,
+      this.#torWarningPrefObserver
+    );
+  }
+}


=====================================
browser/components/downloads/content/allDownloadsView.js
=====================================
@@ -213,7 +213,6 @@ var DownloadsView = {
  */
 function DownloadsPlacesView(
   aRichListBox,
-  torWarningMessageBar,
   aActive = true,
   aSuppressionFlag = DownloadsCommon.SUPPRESS_ALL_DOWNLOADS_OPEN
 ) {
@@ -242,46 +241,6 @@ function DownloadsPlacesView(
       aSuppressionFlag;
   }
 
-  // Tor browser warning message/alert shown above the list.
-
-  const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
-  // Observe changes to the tor warning pref.
-  const torWarningPrefObserver = () => {
-    if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
-      torWarningMessageBar.hidden = false;
-    } else {
-      // Re-assign focus if it is about to be lost.
-      if (torWarningMessageBar.contains(document.activeElement)) {
-        // Try and focus the downloads list.
-        // NOTE: If #downloadsListBox is still hidden, this will do nothing.
-        // But in this case there are no other focusable targets within the
-        // view, so we just leave it up to the focus handler.
-        this._richlistbox.focus({ preventFocusRing: true });
-      }
-      torWarningMessageBar.hidden = true;
-    }
-  };
-
-  Services.prefs.addObserver(
-    PREF_SHOW_DOWNLOAD_WARNING,
-    torWarningPrefObserver
-  );
-  // Initialize.
-  torWarningPrefObserver();
-
-  window.addEventListener("unload", () => {
-    Services.prefs.removeObserver(
-      PREF_SHOW_DOWNLOAD_WARNING,
-      torWarningPrefObserver
-    );
-  });
-
-  torWarningMessageBar
-    .querySelector(".downloads-tor-warning-dismiss-button")
-    .addEventListener("click", () => {
-      Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
-    });
-
   // Make sure to unregister the view if the window is closed.
   window.addEventListener(
     "unload",


=====================================
browser/components/downloads/content/contentAreaDownloadsView.js
=====================================
@@ -8,12 +8,30 @@ const { PrivateBrowsingUtils } = ChromeUtils.importESModule(
   "resource://gre/modules/PrivateBrowsingUtils.sys.mjs"
 );
 
+const { DownloadsTorWarning } = ChromeUtils.importESModule(
+  "resource:///modules/DownloadsTorWarning.sys.mjs"
+);
+
 var ContentAreaDownloadsView = {
   init() {
-    const torWarningMessage = document.getElementById(
-      "aboutDownloadsTorWarning"
-    );
     let box = document.getElementById("downloadsListBox");
+
+    const torWarning = new DownloadsTorWarning(
+      document.getElementById("aboutDownloadsTorWarning"),
+      false,
+      () => {
+        // Try and focus the downloads list.
+        // NOTE: If #downloadsListBox is still hidden, this will do nothing.
+        // But in this case there are no other focusable targets within the
+        // view, so we just leave it up to the focus handler.
+        box.focus({ preventFocusRing: true });
+      }
+    );
+    torWarning.activate();
+    window.addEventListener("unload", () => {
+      torWarning.deactivate();
+    });
+
     let suppressionFlag = DownloadsCommon.SUPPRESS_CONTENT_AREA_DOWNLOADS_OPEN;
     box.addEventListener(
       "InitialDownloadsLoaded",
@@ -30,7 +48,7 @@ var ContentAreaDownloadsView = {
         // experience was bad.
         // Without auto-focusing the downloads list, a screen reader should not
         // skip beyond the alert's content.
-        if (torWarningMessage.hidden) {
+        if (torWarning.hidden) {
           document
             .getElementById("downloadsListBox")
             .focus({ focusVisible: false });
@@ -44,12 +62,7 @@ var ContentAreaDownloadsView = {
       },
       { once: true }
     );
-    let view = new DownloadsPlacesView(
-      box,
-      torWarningMessage,
-      true,
-      suppressionFlag
-    );
+    let view = new DownloadsPlacesView(box, true, suppressionFlag);
     document.addEventListener("visibilitychange", () => {
       let indicator = DownloadsCommon.getIndicatorData(window);
       if (document.visibilityState === "visible") {


=====================================
browser/components/downloads/content/contentAreaDownloadsView.xhtml
=====================================
@@ -49,36 +49,7 @@
   </keyset>
 #endif
 
-  <html:message-bar
-    id="aboutDownloadsTorWarning"
-    class="downloads-tor-warning-message-bar"
-    role="alert"
-    aria-labelledby="aboutDownloadsTorWarningTitle"
-    aria-describedby="aboutDownloadsTorWarningDescription"
-  >
-    <html:div class="downloads-tor-warning-grid">
-      <html:p
-        id="aboutDownloadsTorWarningTitle"
-        class="downloads-tor-warning-title"
-        data-l10n-id="downloads-tor-warning-title"
-      ></html:p>
-      <html:p
-        id="aboutDownloadsTorWarningDescription"
-        class="downloads-tor-warning-description"
-        data-l10n-id="downloads-tor-warning-description"
-      >
-        <html:a
-          href="https://tails.net/"
-          target="_blank"
-          data-l10n-name="tails-link"
-        ></html:a>
-      </html:p>
-      <html:button
-        class="downloads-tor-warning-dismiss-button"
-        data-l10n-id="downloads-tor-warning-dismiss-button"
-      ></html:button>
-    </html:div>
-  </html:message-bar>
+  <html:moz-message-bar id="aboutDownloadsTorWarning"></html:moz-message-bar>
 
   <richlistbox flex="1"
                seltype="multiple"


=====================================
browser/components/downloads/content/downloads.css
=====================================
@@ -92,63 +92,13 @@
 #downloadsPanel-mainView {
   min-width: 37em;
   padding: 0.62em;
-  /* If we don't set a width, #downloadsPanelTorWarningDescription will request
+  /* If we don't set a width, #downloadsPanelTorWarning will request
    * its max-content width. */
   width: 37em;
 }
 
-#downloadsPanel-mainView {
-  /* Fix the layout to ensure the #downloadsWarningDescription is given enough
-   * vertical space. For tor-browser#40701.
-   * TODO: May no longer be necessary after esr 115 due to bugzilla bug 1816455.
-   */
-  display: flex;
-  flex-direction: column;
-}
-
-.downloads-tor-warning-grid {
-  display: grid;
-  grid-template:
-    "title button" min-content
-    "description button" auto
-    / 1fr max-content;
-  gap: 8px;
-  margin-block: 8px;
-  /* Some extra space between the text and the icon. */
-  margin-inline-start: 8px;
-}
-
-.downloads-tor-warning-grid .downloads-tor-warning-title {
-  grid-area: title;
-  margin: 0;
-}
-
-.downloads-tor-warning-grid .downloads-tor-warning-description {
-  grid-area: description;
-  margin: 0;
-}
-
-.downloads-tor-warning-grid .downloads-tor-warning-dismiss-button {
-  grid-area: button;
-  align-self: center;
-}
-
-.downloads-tor-warning-description,
-.downloads-tor-warning-title {
-  line-height: 1.4;
-}
-
-.downloads-tor-warning-title {
-  font-weight: bold;
-}
-
-#downloadsPanelTorWarning :is(
-  .downloads-tor-warning-description,
-  .downloads-tor-warning-title
-) {
-  padding-inline: 8px;
-  margin-block-start: 8px;
-  margin-block-end: 0;
+#downloadsPanelTorWarning {
+  margin-block-end: var(--arrowpanel-menuitem-padding-block);
 }
 
 #downloadsHistory,


=====================================
browser/components/downloads/content/downloads.js
=====================================
@@ -31,8 +31,6 @@
 
 "use strict";
 
-const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
-
 var { XPCOMUtils } = ChromeUtils.importESModule(
   "resource://gre/modules/XPCOMUtils.sys.mjs"
 );
@@ -42,6 +40,7 @@ ChromeUtils.defineESModuleGetters(this, {
   FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
   NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
   PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs",
+  DownloadsTorWarning: "resource:///modules/DownloadsTorWarning.sys.mjs",
 });
 
 const { Integration } = ChromeUtils.importESModule(
@@ -76,11 +75,11 @@ var DownloadsPanel = {
   _waitingDataForOpen: false,
 
   /**
-   * State of tor's download warning. It should only be initialized once (text assigned,
-   * button commands assigned). This tracks if that has been performed and prevents
-   * repeats.
+   * Tracks whether to show the tor warning or not.
+   *
+   * @type {?DownloadsTorWarning}
    */
-  _torWarningInitialized: false,
+  _torWarning: null,
 
   /**
    * Starts loading the download data in background, without opening the panel.
@@ -98,30 +97,20 @@ var DownloadsPanel = {
       );
     }
 
-    const torWarningMessage = document.getElementById(
-      "downloadsPanelTorWarning"
-    );
-    if (!this._torWarningPrefObserver) {
-      // Observe changes to the tor warning pref.
-      this._torWarningPrefObserver = () => {
-        if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
-          torWarningMessage.hidden = false;
-        } else {
-          const hadFocus = torWarningMessage.contains(document.activeElement);
-          torWarningMessage.hidden = true;
+    if (!this._torWarning) {
+      this._torWarning = new DownloadsTorWarning(
+        document.getElementById("downloadsPanelTorWarning"),
+        true,
+        () => {
           // Re-assign focus that was lost.
-          if (hadFocus) {
-            this._focusPanel(true);
-          }
+          this._focusPanel(true);
+        },
+        () => {
+          this.hidePanel();
         }
-      };
-      Services.prefs.addObserver(
-        PREF_SHOW_DOWNLOAD_WARNING,
-        this._torWarningPrefObserver
       );
-      // Initialize
-      this._torWarningPrefObserver();
     }
+    this._torWarning.activate();
 
     if (this._initialized) {
       DownloadsCommon.log("DownloadsPanel is already initialized.");
@@ -149,33 +138,6 @@ var DownloadsPanel = {
       DownloadsSummary
     );
 
-    if (!this._torWarningInitialized) {
-      // Intercept clicks on the tails link.
-      // NOTE: We listen for clicks on the parent instead of the
-      // <a data-l10n-name="tails-link"> element because the latter may be
-      // swapped for a new instance by Fluent when refreshing the parent.
-      torWarningMessage
-        .querySelector(".downloads-tor-warning-description")
-        .addEventListener("click", event => {
-          const tailsLink = event.target.closest(
-            ".downloads-tor-warning-tails-link"
-          );
-          if (!tailsLink) {
-            return;
-          }
-          event.preventDefault();
-          this.hidePanel();
-          openWebLinkIn(tailsLink.href, "tab");
-        });
-
-      torWarningMessage
-        .querySelector(".downloads-tor-warning-dismiss-button")
-        .addEventListener("click", () => {
-          Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
-        });
-      this._torWarningInitialized = true;
-    }
-
     DownloadsCommon.log(
       "DownloadsView attached - the panel for this window",
       "should now see download items come in."
@@ -218,13 +180,7 @@ var DownloadsPanel = {
       DownloadIntegration.downloadSpamProtection.unregister(window);
     }
 
-    if (this._torWarningPrefObserver) {
-      Services.prefs.removeObserver(
-        PREF_SHOW_DOWNLOAD_WARNING,
-        this._torWarningPrefObserver
-      );
-      delete this._torWarningPrefObserver;
-    }
+    this._torWarning?.deactivate();
 
     this._initialized = false;
 
@@ -582,13 +538,8 @@ var DownloadsPanel = {
     // Focus the "Got it" button if it is visible.
     // This should ensure that the alert is read aloud by Orca when the
     // downloads panel is opened. See tor-browser#42642.
-    const torWarningMessage = document.getElementById(
-      "downloadsPanelTorWarning"
-    );
-    if (!torWarningMessage.hidden) {
-      torWarningMessage
-        .querySelector(".downloads-tor-warning-dismiss-button")
-        .focus(focusOptions);
+    if (!this._torWarning?.hidden) {
+      this._torWarning.dismissButton.focus(focusOptions);
       return;
     }
 


=====================================
browser/components/downloads/content/downloadsPanel.inc.xhtml
=====================================
@@ -104,37 +104,8 @@
                   disablekeynav="true">
 
     <panelview id="downloadsPanel-mainView">
-      <vbox id="downloadsPanelTorWarning">
-        <vbox
-          role="alert"
-          aria-labelledby="downloadsPanelTorWarningTitle"
-          aria-describedby="downloadsPanelTorWarningDescription"
-        >
-          <html:p
-            id="downloadsPanelTorWarningTitle"
-            class="downloads-tor-warning-title"
-            data-l10n-id="downloads-tor-warning-title"
-          ></html:p>
-          <html:p
-            id="downloadsPanelTorWarningDescription"
-            class="downloads-tor-warning-description"
-            data-l10n-id="downloads-tor-warning-description"
-          >
-            <html:a
-              href="https://tails.net/"
-              data-l10n-name="tails-link"
-              class="downloads-tor-warning-tails-link"
-            ></html:a>
-          </html:p>
-          <html:moz-button-group class="panel-footer">
-            <html:button
-              class="footer-button downloads-tor-warning-dismiss-button"
-              data-l10n-id="downloads-tor-warning-dismiss-button"
-            ></html:button>
-          </html:moz-button-group>
-        </vbox>
-        <toolbarseparator />
-      </vbox>
+      <html:moz-message-bar id="downloadsPanelTorWarning">
+      </html:moz-message-bar>
       <vbox class="panel-view-body-unscrollable">
         <richlistbox id="downloadsListBox"
                      data-l10n-id="downloads-panel-items"


=====================================
browser/components/downloads/moz.build
=====================================
@@ -15,6 +15,7 @@ EXTRA_JS_MODULES += [
     "DownloadsCommon.sys.mjs",
     "DownloadSpamProtection.sys.mjs",
     "DownloadsTaskbar.sys.mjs",
+    "DownloadsTorWarning.sys.mjs",
     "DownloadsViewableInternally.sys.mjs",
     "DownloadsViewUI.sys.mjs",
 ]


=====================================
browser/components/places/content/places.js
=====================================
@@ -6,7 +6,6 @@
 /* import-globals-from editBookmark.js */
 /* import-globals-from /toolkit/content/contentAreaUtils.js */
 /* import-globals-from /browser/components/downloads/content/allDownloadsView.js */
-/* import-globals-from /browser/base/content/utilityOverlay.js */
 
 /* Shared Places Import - change other consumers if you change this: */
 var { XPCOMUtils } = ChromeUtils.importESModule(
@@ -18,6 +17,7 @@ ChromeUtils.defineESModuleGetters(this, {
   PlacesBackups: "resource://gre/modules/PlacesBackups.sys.mjs",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
   DownloadUtils: "resource://gre/modules/DownloadUtils.sys.mjs",
+  DownloadsTorWarning: "resource:///modules/DownloadsTorWarning.sys.mjs",
 });
 XPCOMUtils.defineLazyScriptGetter(
   this,
@@ -158,15 +158,25 @@ var PlacesOrganizer = {
       "&sort=" +
       Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
 
-    const torWarningMessage = document.getElementById(
-      "placesDownloadsTorWarning"
+    const torWarning = new DownloadsTorWarning(
+      document.getElementById("placesDownloadsTorWarning"),
+      true,
+      () => {
+        document
+          .getElementById("downloadsListBox")
+          .focus({ preventFocusRing: true });
+      }
     );
+    torWarning.activate();
+    window.addEventListener("unload", () => {
+      torWarning.deactivate();
+    });
+
     ContentArea.setContentViewForQueryString(
       DOWNLOADS_QUERY,
       () =>
         new DownloadsPlacesView(
           document.getElementById("downloadsListBox"),
-          torWarningMessage,
           false
         ),
       {
@@ -176,23 +186,6 @@ var PlacesOrganizer = {
       }
     );
 
-    // Intercept clicks on the tor warning tails link.
-    // NOTE: We listen for clicks on the parent instead of the
-    // <a data-l10n-name="tails-link"> element because the latter may be
-    // swapped for a new instance by Fluent when refreshing the parent.
-    document
-      .querySelector(".downloads-tor-warning-description")
-      .addEventListener("click", event => {
-        const tailsLink = event.target.closest(
-          ".downloads-tor-warning-tails-link"
-        );
-        if (!tailsLink) {
-          return;
-        }
-        event.preventDefault();
-        openWebLinkIn(tailsLink.href, "tab");
-      });
-
     ContentArea.init();
 
     this._places = document.getElementById("placesList");
@@ -1432,6 +1425,7 @@ var ContentArea = {
       oldView.associatedElement.hidden = true;
       aNewView.associatedElement.hidden = false;
 
+      // Hide the Tor warning when not in the downloads view.
       const isDownloads = aNewView.associatedElement.id === "downloadsListBox";
       const torWarningMessage = document.getElementById(
         "placesDownloadsTorWarning"


=====================================
browser/components/places/content/places.xhtml
=====================================
@@ -363,35 +363,8 @@
     </tree>
     <splitter collapse="none" persist="state"></splitter>
     <vbox id="contentView">
-      <html:message-bar
-        id="placesDownloadsTorWarning"
-        role="alert"
-        aria-labelledby="placesDownloadsTorWarningTitle"
-        aria-describedby="placesDownloadsTorWarningDescription"
-      >
-        <html:div class="downloads-tor-warning-grid">
-          <html:p
-            id="placesDownloadsTorWarningTitle"
-            class="downloads-tor-warning-title"
-            data-l10n-id="downloads-tor-warning-title"
-          ></html:p>
-          <html:p
-            id="placesDownloadsTorWarningDescription"
-            class="downloads-tor-warning-description"
-            data-l10n-id="downloads-tor-warning-description"
-          >
-            <html:a
-              href="https://tails.net/"
-              class="downloads-tor-warning-tails-link"
-              data-l10n-name="tails-link"
-            ></html:a>
-          </html:p>
-          <html:button
-            class="downloads-tor-warning-dismiss-button"
-            data-l10n-id="downloads-tor-warning-dismiss-button"
-          ></html:button>
-        </html:div>
-      </html:message-bar>
+      <html:moz-message-bar id="placesDownloadsTorWarning">
+      </html:moz-message-bar>
       <vbox id="placesViewsBox" flex="1">
         <tree id="placeContent"
               class="placesTree"


=====================================
browser/themes/shared/downloads/downloads.inc.css
=====================================
@@ -252,7 +252,6 @@
 }
 
 /*** Toolbarseparator ***/
-#downloadsPanelTorWarning toolbarseparator,
 #downloadsFooterButtons > toolbarseparator {
   margin-inline: 0;
 }


=====================================
toolkit/locales/en-US/toolkit/global/tor-browser.ftl
=====================================
@@ -559,9 +559,13 @@ crypto-safety-prompt-dismiss-button = Dismiss Warning
 ## Downloads warning.
 ## Shown in downloads panel, about:downloads and Library window.
 
-downloads-tor-warning-title = Be careful opening downloads
-# "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>'.
-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>.
+# "Tails" is the brand name for the Tails operating system and should be localized appropriately.
+downloads-tor-warning-message-bar =
+    .heading = Be careful opening downloads
+    .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.
+# This will be a link to the Tails operating system website.
+# "Tails" is the brand name for the Tails operating system and should be localized appropriately.
+downloads-tor-warning-tails-link= Learn more about Tails
 # Button to dismiss the warning forever.
 downloads-tor-warning-dismiss-button = Got it
 


=====================================
tools/torbrowser/l10n/migrations/bug-41820-moz-message-bar-download-warning.py
=====================================
@@ -0,0 +1,67 @@
+import re
+
+import fluent.syntax.ast as FTL
+from fluent.migrate.transforms import COPY_PATTERN, FluentSource
+from fluent.syntax.visitor import Visitor
+
+
+class RemoveAnchorVisitor(Visitor):
+    """Class to remove <a> and </a> wrappers from a Fluent TextElement."""
+
+    def __init__(self):
+        # Good enough regex for our needs that will match starting and ending
+        # tags.
+        self._anchor_regex = re.compile(r"<\/?[aA](| [^>]*)>")
+        super().__init__()
+
+    def visit_TextElement(self, node):
+        node.value = self._anchor_regex.sub("", node.value)
+
+
+class RemoveAnchorTransform(FluentSource):
+    """Class to remove <a> and </a> wrappers from a Fluent source."""
+
+    def __call__(self, ctx):
+        pattern = ctx.get_fluent_source_pattern(self.path, self.key).clone()
+        # Visit every node in the pattern, replacing each TextElement's content.
+        RemoveAnchorVisitor().visit(pattern)
+        return pattern
+
+
+def migrate(ctx):
+    # Convert
+    #
+    # downloads-tor-warning-title = A
+    # downloads-tor-warning-description = B<a data-l10n-name="tails-link">C</a>D
+    #
+    # to
+    #
+    # downloads-tor-warning-message-bar =
+    #   .heading = A
+    #   .message = BCD
+    ctx.add_transforms(
+        "tor-browser.ftl",
+        "tor-browser.ftl",
+        [
+            FTL.Message(
+                id=FTL.Identifier("downloads-tor-warning-message-bar"),
+                value=None,
+                attributes=[
+                    FTL.Attribute(
+                        id=FTL.Identifier("heading"),
+                        value=COPY_PATTERN(
+                            "tor-browser.ftl",
+                            "downloads-tor-warning-title",
+                        ),
+                    ),
+                    FTL.Attribute(
+                        id=FTL.Identifier("message"),
+                        value=RemoveAnchorTransform(
+                            "tor-browser.ftl",
+                            "downloads-tor-warning-description",
+                        ),
+                    ),
+                ],
+            ),
+        ],
+    )



View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/f650dacf7e155005678ca80bf0aaa3517e07ca7a...04d6d34179014417113362799167a22eff905e19

-- 
View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/f650dacf7e155005678ca80bf0aaa3517e07ca7a...04d6d34179014417113362799167a22eff905e19
You're receiving this email because of your account on gitlab.torproject.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20240821/3646ad46/attachment-0001.htm>


More information about the tbb-commits mailing list