ma1 pushed to branch tor-browser-102.12.0esr-12.5-1 at The Tor Project / Applications / Tor Browser
Commits:
- 
787ac906
by Dan Ballard at 2023-06-06T20:52:51+00:00
11 changed files:
- 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/places/content/places.css
- browser/components/places/content/places.js
- browser/components/places/content/places.xhtml
- browser/themes/shared/customizableui/panelUI-shared.css
- browser/themes/shared/downloads/contentAreaDownloadsView.css
Changes:
| ... | ... | @@ -212,6 +212,7 @@ var DownloadsView = { | 
| 212 | 212 |   */
 | 
| 213 | 213 |  function DownloadsPlacesView(
 | 
| 214 | 214 |    aRichListBox,
 | 
| 215 | +  torWarningMessageBar,
 | |
| 215 | 216 |    aActive = true,
 | 
| 216 | 217 |    aSuppressionFlag = DownloadsCommon.SUPPRESS_ALL_DOWNLOADS_OPEN
 | 
| 217 | 218 |  ) {
 | 
| ... | ... | @@ -241,6 +242,46 @@ function DownloadsPlacesView( | 
| 241 | 242 |      ).attentionSuppressed |= aSuppressionFlag;
 | 
| 242 | 243 |    }
 | 
| 243 | 244 | |
| 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", event => {
 | |
| 282 | +      Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
 | |
| 283 | +    });
 | |
| 284 | + | |
| 244 | 285 |    // Make sure to unregister the view if the window is closed.
 | 
| 245 | 286 |    window.addEventListener(
 | 
| 246 | 287 |      "unload",
 | 
| ... | ... | @@ -10,6 +10,9 @@ const { PrivateBrowsingUtils } = ChromeUtils.import( | 
| 10 | 10 | |
| 11 | 11 |  var ContentAreaDownloadsView = {
 | 
| 12 | 12 |    init() {
 | 
| 13 | +    const torWarningMessage = document.getElementById(
 | |
| 14 | +      "aboutDownloadsTorWarning"
 | |
| 15 | +    );
 | |
| 13 | 16 |      let box = document.getElementById("downloadsListBox");
 | 
| 14 | 17 |      let suppressionFlag = DownloadsCommon.SUPPRESS_CONTENT_AREA_DOWNLOADS_OPEN;
 | 
| 15 | 18 |      box.addEventListener(
 | 
| ... | ... | @@ -17,9 +20,22 @@ var ContentAreaDownloadsView = { | 
| 17 | 20 |        () => {
 | 
| 18 | 21 |          // Set focus to Downloads list once it is created
 | 
| 19 | 22 |          // And prevent it from showing the focus ring around the richlistbox (Bug 1702694)
 | 
| 20 | -        document
 | |
| 21 | -          .getElementById("downloadsListBox")
 | |
| 22 | -          .focus({ preventFocusRing: true });
 | |
| 23 | +        // Prevent focusing the list whilst the tor browser warning is shown.
 | |
| 24 | +        // Some screen readers (tested with Orca and NVDA) will not read out
 | |
| 25 | +        // alerts if they are already present on page load. In that case, a
 | |
| 26 | +        // screen reader user may not be aware of the warning before they
 | |
| 27 | +        // interact with the downloads list, which we do not want.
 | |
| 28 | +        // Some hacky workarounds were tested with Orca to get it to read back
 | |
| 29 | +        // the alert before the focus is read, but this was inconsistent and the
 | |
| 30 | +        // experience was bad.
 | |
| 31 | +        // Without auto-focusing the downloads list, a screen reader should not
 | |
| 32 | +        // skip beyond the alert's content.
 | |
| 33 | +        if (torWarningMessage.hidden) {
 | |
| 34 | +          document
 | |
| 35 | +            .getElementById("downloadsListBox")
 | |
| 36 | +            .focus({ preventFocusRing: true });
 | |
| 37 | +        }
 | |
| 38 | + | |
| 23 | 39 |          // Pause the indicator if the browser is active.
 | 
| 24 | 40 |          if (document.visibilityState === "visible") {
 | 
| 25 | 41 |            DownloadsCommon.getIndicatorData(
 | 
| ... | ... | @@ -29,7 +45,12 @@ var ContentAreaDownloadsView = { | 
| 29 | 45 |        },
 | 
| 30 | 46 |        { once: true }
 | 
| 31 | 47 |      );
 | 
| 32 | -    let view = new DownloadsPlacesView(box, true, suppressionFlag);
 | |
| 48 | +    let view = new DownloadsPlacesView(
 | |
| 49 | +      box,
 | |
| 50 | +      torWarningMessage,
 | |
| 51 | +      true,
 | |
| 52 | +      suppressionFlag
 | |
| 53 | +    );
 | |
| 33 | 54 |      document.addEventListener("visibilitychange", aEvent => {
 | 
| 34 | 55 |        let indicator = DownloadsCommon.getIndicatorData(window);
 | 
| 35 | 56 |        if (document.visibilityState === "visible") {
 | 
| ... | ... | @@ -42,6 +63,53 @@ var ContentAreaDownloadsView = { | 
| 42 | 63 |      if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
 | 
| 43 | 64 |        view.place = "place:transition=7&sort=4";
 | 
| 44 | 65 |      }
 | 
| 66 | + | |
| 67 | +    torWarningMessage.querySelector(
 | |
| 68 | +      ".downloads-tor-warning-title"
 | |
| 69 | +    ).textContent = this._getTorString("torbutton.download.warning.title");
 | |
| 70 | + | |
| 71 | +    const tailsLink = document.createElement("a");
 | |
| 72 | +    tailsLink.href = "https://tails.boum.org/";
 | |
| 73 | +    tailsLink.target = "_blank";
 | |
| 74 | +    tailsLink.textContent = this._getTorString(
 | |
| 75 | +      "torbutton.download.warning.tails_brand_name"
 | |
| 76 | +    );
 | |
| 77 | + | |
| 78 | +    const [beforeLink, afterLink] = this._getTorString(
 | |
| 79 | +      "torbutton.download.warning.description"
 | |
| 80 | +    ).split("%S");
 | |
| 81 | + | |
| 82 | +    torWarningMessage
 | |
| 83 | +      .querySelector(".downloads-tor-warning-description")
 | |
| 84 | +      .append(beforeLink, tailsLink, afterLink);
 | |
| 85 | + | |
| 86 | +    torWarningMessage.querySelector(
 | |
| 87 | +      ".downloads-tor-warning-dismiss-button"
 | |
| 88 | +    ).textContent = this._getTorString("torbutton.download.warning.dismiss");
 | |
| 89 | +  },
 | |
| 90 | + | |
| 91 | +  /**
 | |
| 92 | +   * Get a string from the properties bundle.
 | |
| 93 | +   *
 | |
| 94 | +   * @param {string} name - The string name.
 | |
| 95 | +   *
 | |
| 96 | +   * @return {string} The string.
 | |
| 97 | +   */
 | |
| 98 | +  _getTorString(name) {
 | |
| 99 | +    if (!this._stringBundle) {
 | |
| 100 | +      this._stringBundle = Services.strings.createBundle(
 | |
| 101 | +        "chrome://torbutton/locale/torbutton.properties"
 | |
| 102 | +      );
 | |
| 103 | +    }
 | |
| 104 | +    try {
 | |
| 105 | +      return this._stringBundle.GetStringFromName(name);
 | |
| 106 | +    } catch {}
 | |
| 107 | +    if (!this._fallbackStringBundle) {
 | |
| 108 | +      this._fallbackStringBundle = Services.strings.createBundle(
 | |
| 109 | +        "resource://torbutton/locale/en-US/torbutton.properties"
 | |
| 110 | +      );
 | |
| 111 | +    }
 | |
| 112 | +    return this._fallbackStringBundle.GetStringFromName(name);
 | |
| 45 | 113 |    },
 | 
| 46 | 114 |  };
 | 
| 47 | 115 | 
| ... | ... | @@ -39,6 +39,23 @@ | 
| 39 | 39 |    </keyset>
 | 
| 40 | 40 |  #endif
 | 
| 41 | 41 | |
| 42 | +  <html:message-bar id="aboutDownloadsTorWarning"
 | |
| 43 | +                    class="downloads-tor-warning-message-bar"
 | |
| 44 | +                    role="alert"
 | |
| 45 | +                    aria-labelledby="aboutDownloadsTorWarningTitle"
 | |
| 46 | +                    aria-describedby="aboutDownloadsTorWarningDescription">
 | |
| 47 | +    <html:div class="downloads-tor-warning-grid">
 | |
| 48 | +      <html:p id="aboutDownloadsTorWarningTitle"
 | |
| 49 | +              class="downloads-tor-warning-title">
 | |
| 50 | +      </html:p>
 | |
| 51 | +      <html:p id="aboutDownloadsTorWarningDescription"
 | |
| 52 | +              class="downloads-tor-warning-description">
 | |
| 53 | +      </html:p>
 | |
| 54 | +      <html:button class="downloads-tor-warning-dismiss-button">
 | |
| 55 | +      </html:button>
 | |
| 56 | +    </html:div>
 | |
| 57 | +  </html:message-bar>
 | |
| 58 | + | |
| 42 | 59 |    <richlistbox flex="1"
 | 
| 43 | 60 |                 seltype="multiple"
 | 
| 44 | 61 |                 id="downloadsListBox"
 | 
| ... | ... | @@ -104,18 +104,52 @@ | 
| 104 | 104 |    flex-direction: column;
 | 
| 105 | 105 |  }
 | 
| 106 | 106 | |
| 107 | -#downloadsWarning p {
 | |
| 108 | -  padding-inline: 8px;
 | |
| 109 | -  margin-block-start: 8px;
 | |
| 110 | -  margin-block-end: 0;
 | |
| 107 | +.downloads-tor-warning-grid {
 | |
| 108 | +  display: grid;
 | |
| 109 | +  grid-template:
 | |
| 110 | +    "title button" min-content
 | |
| 111 | +    "description button" auto
 | |
| 112 | +    / 1fr max-content;
 | |
| 113 | +  gap: 8px;
 | |
| 114 | +  margin-block: 8px;
 | |
| 115 | +  /* Some extra space between the text and the icon. */
 | |
| 116 | +  margin-inline-start: 8px;
 | |
| 117 | +}
 | |
| 118 | + | |
| 119 | +.downloads-tor-warning-grid .downloads-tor-warning-title {
 | |
| 120 | +  grid-area: title;
 | |
| 121 | +  margin: 0;
 | |
| 122 | +}
 | |
| 123 | + | |
| 124 | +.downloads-tor-warning-grid .downloads-tor-warning-description {
 | |
| 125 | +  grid-area: description;
 | |
| 126 | +  margin: 0;
 | |
| 127 | +}
 | |
| 128 | + | |
| 129 | +.downloads-tor-warning-grid .downloads-tor-warning-dismiss-button {
 | |
| 130 | +  grid-area: button;
 | |
| 131 | +  align-self: center;
 | |
| 132 | +}
 | |
| 133 | + | |
| 134 | +.downloads-tor-warning-description,
 | |
| 135 | +.downloads-tor-warning-title {
 | |
| 111 | 136 |    line-height: 1.4;
 | 
| 112 | 137 |  }
 | 
| 113 | 138 | |
| 114 | -#downloadsWarningHeaderTitle {
 | |
| 139 | +.downloads-tor-warning-title {
 | |
| 115 | 140 |    font-weight: bold;
 | 
| 116 | 141 |  }
 | 
| 117 | 142 | |
| 118 | -#downloadsWarningDescription {
 | |
| 143 | +#downloadsPanelTorWarning :is(
 | |
| 144 | +  .downloads-tor-warning-description,
 | |
| 145 | +  .downloads-tor-warning-title
 | |
| 146 | +) {
 | |
| 147 | +  padding-inline: 8px;
 | |
| 148 | +  margin-block-start: 8px;
 | |
| 149 | +  margin-block-end: 0;
 | |
| 150 | +}
 | |
| 151 | + | |
| 152 | +#downloadsPanelTorWarningDescription {
 | |
| 119 | 153 |    /* Make sure we wrap the text rather than request the default max-content
 | 
| 120 | 154 |     * width from the parent XUL -moz-box. */
 | 
| 121 | 155 |    width: 0;
 | 
| ... | ... | @@ -33,8 +33,6 @@ | 
| 33 | 33 | |
| 34 | 34 |  const PREF_SHOW_DOWNLOAD_WARNING = "browser.download.showTorWarning";
 | 
| 35 | 35 | |
| 36 | -const TAILS_URI = "https://tails.boum.org/";
 | |
| 37 | - | |
| 38 | 36 |  var { XPCOMUtils } = ChromeUtils.import(
 | 
| 39 | 37 |    "resource://gre/modules/XPCOMUtils.jsm"
 | 
| 40 | 38 |  );
 | 
| ... | ... | @@ -143,13 +141,28 @@ var DownloadsPanel = { | 
| 143 | 141 |        );
 | 
| 144 | 142 |      }
 | 
| 145 | 143 | |
| 146 | -    let showDownloadWarning = Services.prefs.getBoolPref(
 | |
| 147 | -      PREF_SHOW_DOWNLOAD_WARNING
 | |
| 144 | +    const torWarningMessage = document.getElementById(
 | |
| 145 | +      "downloadsPanelTorWarning"
 | |
| 148 | 146 |      );
 | 
| 149 | -    if (!showDownloadWarning) {
 | |
| 150 | -      document.getElementById("downloadsWarning").hidden = true;
 | |
| 151 | -    } else {
 | |
| 152 | -      document.getElementById("downloadsWarning").hidden = false;
 | |
| 147 | +    if (!this._torWarningPrefObserver) {
 | |
| 148 | +      // Observe changes to the tor warning pref.
 | |
| 149 | +      this._torWarningPrefObserver = () => {
 | |
| 150 | +        if (Services.prefs.getBoolPref(PREF_SHOW_DOWNLOAD_WARNING)) {
 | |
| 151 | +          torWarningMessage.hidden = false;
 | |
| 152 | +        } else {
 | |
| 153 | +          // Re-assign focus if it is about to be lost.
 | |
| 154 | +          if (torWarningMessage.contains(document.activeElement)) {
 | |
| 155 | +            this._focusPanel(true);
 | |
| 156 | +          }
 | |
| 157 | +          torWarningMessage.hidden = true;
 | |
| 158 | +        }
 | |
| 159 | +      };
 | |
| 160 | +      Services.prefs.addObserver(
 | |
| 161 | +        PREF_SHOW_DOWNLOAD_WARNING,
 | |
| 162 | +        this._torWarningPrefObserver
 | |
| 163 | +      );
 | |
| 164 | +      // Initialize
 | |
| 165 | +      this._torWarningPrefObserver();
 | |
| 153 | 166 |      }
 | 
| 154 | 167 | |
| 155 | 168 |      if (this._state != this.kStateUninitialized) {
 | 
| ... | ... | @@ -175,42 +188,40 @@ var DownloadsPanel = { | 
| 175 | 188 |        DownloadsSummary
 | 
| 176 | 189 |      );
 | 
| 177 | 190 | |
| 178 | -    if (this._torWarningInitialized == 0) {
 | |
| 179 | -      document.getElementById(
 | |
| 180 | -        "downloadsWarningHeaderTitle"
 | |
| 181 | -      ).textContent = this._getString("torbutton.download.warning.title");
 | |
| 182 | -      let tailsBrandName = this._getString(
 | |
| 183 | -        "torbutton.download.warning.tails_brand_name"
 | |
| 184 | -      );
 | |
| 191 | +    if (!this._torWarningInitialized) {
 | |
| 192 | +      torWarningMessage.querySelector(
 | |
| 193 | +        ".downloads-tor-warning-title"
 | |
| 194 | +      ).textContent = this._getTorString("torbutton.download.warning.title");
 | |
| 185 | 195 | |
| 186 | -      let warningDescriptionText = this._getString(
 | |
| 187 | -        "torbutton.download.warning.description"
 | |
| 188 | -      );
 | |
| 189 | -      let [head, rest] = warningDescriptionText.split("%S");
 | |
| 190 | 196 |        const tailsLink = document.createElement("a");
 | 
| 191 | -      tailsLink.setAttribute("href", TAILS_URI);
 | |
| 192 | -      tailsLink.textContent = tailsBrandName.trim();
 | |
| 197 | +      tailsLink.href = "https://tails.boum.org/";
 | |
| 198 | +      tailsLink.textContent = this._getTorString(
 | |
| 199 | +        "torbutton.download.warning.tails_brand_name"
 | |
| 200 | +      );
 | |
| 193 | 201 |        tailsLink.addEventListener("click", event => {
 | 
| 194 | 202 |          event.preventDefault();
 | 
| 195 | 203 |          this.hidePanel();
 | 
| 196 | -        openWebLinkIn(TAILS_URI, "tab");
 | |
| 204 | +        openWebLinkIn(tailsLink.href, "tab");
 | |
| 197 | 205 |        });
 | 
| 198 | 206 | |
| 199 | -      let downloadsWarningDescription = document.getElementById(
 | |
| 200 | -        "downloadsWarningDescription"
 | |
| 201 | -      );
 | |
| 202 | -      downloadsWarningDescription.append(head, tailsLink, rest);
 | |
| 207 | +      const [beforeLink, afterLink] = this._getTorString(
 | |
| 208 | +        "torbutton.download.warning.description"
 | |
| 209 | +      ).split("%S");
 | |
| 210 | + | |
| 211 | +      torWarningMessage
 | |
| 212 | +        .querySelector(".downloads-tor-warning-description")
 | |
| 213 | +        .append(beforeLink, tailsLink, afterLink);
 | |
| 203 | 214 | |
| 204 | -      let dismissBtn = document.getElementById(
 | |
| 205 | -        "downloadWarningDismiss"
 | |
| 215 | +      let dismissButton = torWarningMessage.querySelector(
 | |
| 216 | +        ".downloads-tor-warning-dismiss-button"
 | |
| 206 | 217 |        );
 | 
| 207 | -      dismissBtn.textContent = this._getString("torbutton.download.warning.dismiss");
 | |
| 208 | -      dismissBtn.addEventListener("click", event => {
 | |
| 218 | +      dismissButton.textContent = this._getTorString(
 | |
| 219 | +        "torbutton.download.warning.dismiss"
 | |
| 220 | +      );
 | |
| 221 | +      dismissButton.addEventListener("click", event => {
 | |
| 209 | 222 |          Services.prefs.setBoolPref(PREF_SHOW_DOWNLOAD_WARNING, false);
 | 
| 210 | -        document.getElementById("downloadsWarning").hidden = true;
 | |
| 211 | -        this._focusPanel(true);
 | |
| 212 | 223 |        });
 | 
| 213 | -      this._torWarningInitialized = 1;
 | |
| 224 | +      this._torWarningInitialized = true;
 | |
| 214 | 225 |      }
 | 
| 215 | 226 | |
| 216 | 227 |      DownloadsCommon.log(
 | 
| ... | ... | @@ -254,6 +265,14 @@ var DownloadsPanel = { | 
| 254 | 265 |        );
 | 
| 255 | 266 |      }
 | 
| 256 | 267 | |
| 268 | +    if (this._torWarningPrefObserver) {
 | |
| 269 | +      Services.prefs.removeObserver(
 | |
| 270 | +        PREF_SHOW_DOWNLOAD_WARNING,
 | |
| 271 | +        this._torWarningPrefObserver
 | |
| 272 | +      );
 | |
| 273 | +      delete this._torWarningPrefObserver;
 | |
| 274 | +    }
 | |
| 275 | + | |
| 257 | 276 |      this._state = this.kStateUninitialized;
 | 
| 258 | 277 | |
| 259 | 278 |      DownloadsSummary.active = false;
 | 
| ... | ... | @@ -591,14 +610,17 @@ var DownloadsPanel = { | 
| 591 | 610 |     *
 | 
| 592 | 611 |     * @param {bool} [forceFocus=false] - Whether to force move the focus.
 | 
| 593 | 612 |     */
 | 
| 594 | -  _focusPanel(forceFocus=false) {
 | |
| 613 | +  _focusPanel(forceFocus = false) {
 | |
| 595 | 614 |      if (!forceFocus) {
 | 
| 596 | 615 |        // We may be invoked while the panel is still waiting to be shown.
 | 
| 597 | 616 |        if (this._state != this.kStateShown) {
 | 
| 598 | 617 |          return;
 | 
| 599 | 618 |        }
 | 
| 600 | 619 | |
| 601 | -      if (document.activeElement && this.panel.contains(document.activeElement)) {
 | |
| 620 | +      if (
 | |
| 621 | +        document.activeElement &&
 | |
| 622 | +        this.panel.contains(document.activeElement)
 | |
| 623 | +      ) {
 | |
| 602 | 624 |          return;
 | 
| 603 | 625 |        }
 | 
| 604 | 626 |      }
 | 
| ... | ... | @@ -729,7 +751,7 @@ var DownloadsPanel = { | 
| 729 | 751 |     *
 | 
| 730 | 752 |     * @return {string} The string.
 | 
| 731 | 753 |     */
 | 
| 732 | -  _getString(name) {
 | |
| 754 | +  _getTorString(name) {
 | |
| 733 | 755 |      if (!this._stringBundle) {
 | 
| 734 | 756 |        this._stringBundle = Services.strings.createBundle(
 | 
| 735 | 757 |          "chrome://torbutton/locale/torbutton.properties"
 | 
| ... | ... | @@ -124,16 +124,19 @@ | 
| 124 | 124 |                    disablekeynav="true">
 | 
| 125 | 125 | |
| 126 | 126 |      <panelview id="downloadsPanel-mainView">
 | 
| 127 | -      <vbox id="downloadsWarning">
 | |
| 127 | +      <vbox id="downloadsPanelTorWarning">
 | |
| 128 | 128 |          <vbox role="alert"
 | 
| 129 | -              aria-labelledby="downloadsWarningHeaderTitle"
 | |
| 130 | -              aria-describedby="downloadsWarningDescription">
 | |
| 131 | -          <html:p id="downloadsWarningHeaderTitle"></html:p>
 | |
| 132 | -          <html:p id="downloadsWarningDescription">
 | |
| 129 | +              aria-labelledby="downloadsPanelTorWarningTitle"
 | |
| 130 | +              aria-describedby="downloadsPanelTorWarningDescription">
 | |
| 131 | +          <html:p id="downloadsPanelTorWarningTitle"
 | |
| 132 | +                  class="downloads-tor-warning-title">
 | |
| 133 | +          </html:p>
 | |
| 134 | +          <html:p id="downloadsPanelTorWarningDescription"
 | |
| 135 | +                  class="downloads-tor-warning-description">
 | |
| 133 | 136 |            </html:p>
 | 
| 134 | 137 | |
| 135 | 138 |            <html:div class="panel-footer">
 | 
| 136 | -            <html:button id="downloadWarningDismiss">
 | |
| 139 | +            <html:button class="downloads-tor-warning-dismiss-button">
 | |
| 137 | 140 |              </html:button>
 | 
| 138 | 141 |            </html:div>
 | 
| 139 | 142 |          </vbox>
 | 
| ... | ... | @@ -126,3 +126,7 @@ tree[is="places-tree"] > treechildren::-moz-tree-cell { | 
| 126 | 126 |    margin: 2px 4px;
 | 
| 127 | 127 |    color: currentColor;
 | 
| 128 | 128 |  }
 | 
| 129 | + | |
| 130 | +#placesDownloadsTorWarning:not(.downloads-visible) {
 | |
| 131 | +  display: none;
 | |
| 132 | +} | 
| ... | ... | @@ -6,6 +6,7 @@ | 
| 6 | 6 |  /* import-globals-from instantEditBookmark.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 */
 | |
| 9 | 10 | |
| 10 | 11 |  /* Shared Places Import - change other consumers if you change this: */
 | 
| 11 | 12 |  var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 | 
| ... | ... | @@ -164,11 +165,15 @@ var PlacesOrganizer = { | 
| 164 | 165 |        "&sort=" +
 | 
| 165 | 166 |        Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING;
 | 
| 166 | 167 | |
| 168 | +    const torWarningMessage = document.getElementById(
 | |
| 169 | +      "placesDownloadsTorWarning"
 | |
| 170 | +    );
 | |
| 167 | 171 |      ContentArea.setContentViewForQueryString(
 | 
| 168 | 172 |        DOWNLOADS_QUERY,
 | 
| 169 | 173 |        () =>
 | 
| 170 | 174 |          new DownloadsPlacesView(
 | 
| 171 | 175 |            document.getElementById("downloadsListBox"),
 | 
| 176 | +          torWarningMessage,
 | |
| 172 | 177 |            false
 | 
| 173 | 178 |          ),
 | 
| 174 | 179 |        {
 | 
| ... | ... | @@ -178,6 +183,33 @@ var PlacesOrganizer = { | 
| 178 | 183 |        }
 | 
| 179 | 184 |      );
 | 
| 180 | 185 | |
| 186 | +    // Initialize tor warning text content.
 | |
| 187 | +    torWarningMessage.querySelector(
 | |
| 188 | +      ".downloads-tor-warning-title"
 | |
| 189 | +    ).textContent = this._getTorString("torbutton.download.warning.title");
 | |
| 190 | + | |
| 191 | +    const tailsLink = document.createElement("a");
 | |
| 192 | +    tailsLink.href = "https://tails.boum.org/";
 | |
| 193 | +    tailsLink.textContent = this._getTorString(
 | |
| 194 | +      "torbutton.download.warning.tails_brand_name"
 | |
| 195 | +    );
 | |
| 196 | +    tailsLink.addEventListener("click", event => {
 | |
| 197 | +      event.preventDefault();
 | |
| 198 | +      openWebLinkIn(tailsLink.href, "tab");
 | |
| 199 | +    });
 | |
| 200 | + | |
| 201 | +    const [beforeLink, afterLink] = this._getTorString(
 | |
| 202 | +      "torbutton.download.warning.description"
 | |
| 203 | +    ).split("%S");
 | |
| 204 | + | |
| 205 | +    torWarningMessage
 | |
| 206 | +      .querySelector(".downloads-tor-warning-description")
 | |
| 207 | +      .append(beforeLink, tailsLink, afterLink);
 | |
| 208 | + | |
| 209 | +    torWarningMessage.querySelector(
 | |
| 210 | +      ".downloads-tor-warning-dismiss-button"
 | |
| 211 | +    ).textContent = this._getTorString("torbutton.download.warning.dismiss");
 | |
| 212 | + | |
| 181 | 213 |      ContentArea.init();
 | 
| 182 | 214 | |
| 183 | 215 |      this._places = document.getElementById("placesList");
 | 
| ... | ... | @@ -246,6 +278,30 @@ var PlacesOrganizer = { | 
| 246 | 278 |      ContentArea.focus();
 | 
| 247 | 279 |    },
 | 
| 248 | 280 | |
| 281 | +  /**
 | |
| 282 | +   * Get a string from the properties bundle.
 | |
| 283 | +   *
 | |
| 284 | +   * @param {string} name - The string name.
 | |
| 285 | +   *
 | |
| 286 | +   * @returns {string} The string.
 | |
| 287 | +   */
 | |
| 288 | +  _getTorString(name) {
 | |
| 289 | +    if (!this._stringBundle) {
 | |
| 290 | +      this._stringBundle = Services.strings.createBundle(
 | |
| 291 | +        "chrome://torbutton/locale/torbutton.properties"
 | |
| 292 | +      );
 | |
| 293 | +    }
 | |
| 294 | +    try {
 | |
| 295 | +      return this._stringBundle.GetStringFromName(name);
 | |
| 296 | +    } catch {}
 | |
| 297 | +    if (!this._fallbackStringBundle) {
 | |
| 298 | +      this._fallbackStringBundle = Services.strings.createBundle(
 | |
| 299 | +        "resource://torbutton/locale/en-US/torbutton.properties"
 | |
| 300 | +      );
 | |
| 301 | +    }
 | |
| 302 | +    return this._fallbackStringBundle.GetStringFromName(name);
 | |
| 303 | +  },
 | |
| 304 | + | |
| 249 | 305 |    QueryInterface: ChromeUtils.generateQI([]),
 | 
| 250 | 306 | |
| 251 | 307 |    handleEvent: function PO_handleEvent(aEvent) {
 | 
| ... | ... | @@ -1386,9 +1442,20 @@ var ContentArea = { | 
| 1386 | 1442 |        oldView.associatedElement.hidden = true;
 | 
| 1387 | 1443 |        aNewView.associatedElement.hidden = false;
 | 
| 1388 | 1444 | |
| 1445 | +      const isDownloads = aNewView.associatedElement.id === "downloadsListBox";
 | |
| 1446 | +      const torWarningMessage = document.getElementById(
 | |
| 1447 | +        "placesDownloadsTorWarning"
 | |
| 1448 | +      );
 | |
| 1449 | +      const torWarningLoosingFocus =
 | |
| 1450 | +        torWarningMessage.contains(document.activeElement) && !isDownloads;
 | |
| 1451 | +      torWarningMessage.classList.toggle("downloads-visible", isDownloads);
 | |
| 1452 | + | |
| 1389 | 1453 |        // If the content area inactivated view was focused, move focus
 | 
| 1390 | 1454 |        // to the new view.
 | 
| 1391 | -      if (document.activeElement == oldView.associatedElement) {
 | |
| 1455 | +      if (
 | |
| 1456 | +        document.activeElement == oldView.associatedElement ||
 | |
| 1457 | +        torWarningLoosingFocus
 | |
| 1458 | +      ) {
 | |
| 1392 | 1459 |          aNewView.associatedElement.focus();
 | 
| 1393 | 1460 |        }
 | 
| 1394 | 1461 |      }
 | 
| ... | ... | @@ -345,6 +345,21 @@ | 
| 345 | 345 |      </tree>
 | 
| 346 | 346 |      <splitter collapse="none" persist="state"></splitter>
 | 
| 347 | 347 |      <vbox id="contentView" flex="4">
 | 
| 348 | +      <html:message-bar id="placesDownloadsTorWarning"
 | |
| 349 | +                        role="alert"
 | |
| 350 | +                        aria-labelledby="placesDownloadsTorWarningTitle"
 | |
| 351 | +                        aria-describedby="placesDownloadsTorWarningDescription">
 | |
| 352 | +        <html:div class="downloads-tor-warning-grid">
 | |
| 353 | +          <html:p id="placesDownloadsTorWarningTitle"
 | |
| 354 | +                  class="downloads-tor-warning-title">
 | |
| 355 | +          </html:p>
 | |
| 356 | +          <html:p id="placesDownloadsTorWarningDescription"
 | |
| 357 | +                  class="downloads-tor-warning-description">
 | |
| 358 | +          </html:p>
 | |
| 359 | +          <html:button class="downloads-tor-warning-dismiss-button">
 | |
| 360 | +          </html:button>
 | |
| 361 | +        </html:div>
 | |
| 362 | +      </html:message-bar>
 | |
| 348 | 363 |        <vbox id="placesViewsBox" flex="1">
 | 
| 349 | 364 |          <tree id="placeContent"
 | 
| 350 | 365 |                class="plain placesTree"
 | 
| ... | ... | @@ -1324,7 +1324,7 @@ panelview .toolbarbutton-1 { | 
| 1324 | 1324 |  #downloadsFooterButtons > toolbarseparator,
 | 
| 1325 | 1325 |  .cui-widget-panelview menuseparator,
 | 
| 1326 | 1326 |  .cui-widget-panel toolbarseparator,
 | 
| 1327 | -#downloadsWarning toolbarseparator,
 | |
| 1327 | +#downloadsPanelTorWarning toolbarseparator,
 | |
| 1328 | 1328 |  #securityLevel-panel toolbarseparator {
 | 
| 1329 | 1329 |    appearance: none;
 | 
| 1330 | 1330 |    min-height: 0;
 | 
| ... | ... | @@ -25,3 +25,7 @@ | 
| 25 | 25 |    text-align: center;
 | 
| 26 | 26 |    color: var(--in-content-deemphasized-text);
 | 
| 27 | 27 |  }
 | 
| 28 | + | |
| 29 | +#aboutDownloadsTorWarning {
 | |
| 30 | +  margin-block-end: 8px;
 | |
| 31 | +} |