morgan pushed to branch tor-browser-128.1.0esr-14.0-1 at The Tor Project / Applications / Tor Browser

Commits:

13 changed files:

Changes:

  • browser/components/downloads/DownloadsTorWarning.sys.mjs
    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
    +}

  • browser/components/downloads/content/allDownloadsView.js
    ... ... @@ -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",
    

  • browser/components/downloads/content/contentAreaDownloadsView.js
    ... ... @@ -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") {
    

  • browser/components/downloads/content/contentAreaDownloadsView.xhtml
    ... ... @@ -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"
    

  • browser/components/downloads/content/downloads.css
    ... ... @@ -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,
    

  • browser/components/downloads/content/downloads.js
    ... ... @@ -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
     
    

  • browser/components/downloads/content/downloadsPanel.inc.xhtml
    ... ... @@ -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"
    

  • browser/components/downloads/moz.build
    ... ... @@ -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
     ]
    

  • browser/components/places/content/places.js
    ... ... @@ -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"
    

  • browser/components/places/content/places.xhtml
    ... ... @@ -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"
    

  • browser/themes/shared/downloads/downloads.inc.css
    ... ... @@ -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
     }

  • toolkit/locales/en-US/toolkit/global/tor-browser.ftl
    ... ... @@ -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
     
    

  • tools/torbrowser/l10n/migrations/bug-41820-moz-message-bar-download-warning.py
    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
    +    )