tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

builtinBridgeDialog.js (4333B)


      1 "use strict";
      2 
      3 const { TorSettings, TorBridgeSource } = ChromeUtils.importESModule(
      4  "resource://gre/modules/TorSettings.sys.mjs"
      5 );
      6 
      7 const { TorConnect, TorConnectStage, TorConnectTopics } =
      8  ChromeUtils.importESModule("resource://gre/modules/TorConnect.sys.mjs");
      9 
     10 const gBuiltinBridgeDialog = {
     11  init() {
     12    this._result = window.arguments[0];
     13 
     14    this._radioGroup = document.getElementById(
     15      "torPreferences-builtinBridge-typeSelection"
     16    );
     17 
     18    const currentBuiltinType =
     19      TorSettings.bridges.enabled &&
     20      TorSettings.bridges.source == TorBridgeSource.BuiltIn
     21        ? TorSettings.bridges.builtin_type
     22        : null;
     23 
     24    for (const optionEl of this._radioGroup.querySelectorAll(
     25      ".builtin-bridges-option"
     26    )) {
     27      const radio = optionEl.querySelector("radio");
     28      const type = radio.value;
     29      optionEl.hidden = !TorSettings.builtinBridgeTypes.includes(type);
     30 
     31      const descriptionEl = optionEl.querySelector(
     32        ".builtin-bridges-option-description"
     33      );
     34      // Set an id to be used for the aria-describedby.
     35      descriptionEl.id = `builtin-bridges-description-${type}`;
     36      const currentBadge = optionEl.querySelector(".bridge-status-badge");
     37      if (type === currentBuiltinType) {
     38        const currentLabelEl = optionEl.querySelector(
     39          ".torPreferences-current-bridge-label"
     40        );
     41        currentLabelEl.id = `builtin-bridges-current-${type}`;
     42        // Described by both the current badge and the full description.
     43        // These will be concatenated together in the screen reader output.
     44        radio.setAttribute(
     45          "aria-describedby",
     46          `${currentLabelEl.id} ${descriptionEl.id}`
     47        );
     48        // Make visible.
     49        currentBadge.classList.add("bridge-status-current-built-in");
     50      } else {
     51        // No visible badge.
     52        radio.setAttribute("aria-describedby", descriptionEl.id);
     53        currentBadge.classList.remove("bridge-status-current-built-in");
     54      }
     55    }
     56 
     57    if (currentBuiltinType) {
     58      this._radioGroup.value = currentBuiltinType;
     59    } else {
     60      this._radioGroup.selectedItem = null;
     61    }
     62 
     63    this._radioGroup.addEventListener("select", () => this.onSelectChange());
     64 
     65    const dialog = document.getElementById(
     66      "torPreferences-builtinBridge-dialog"
     67    );
     68    dialog.addEventListener("dialogaccept", () => {
     69      this._result.accepted = true;
     70    });
     71 
     72    // Add styling for tor-button to the dialog shadow root.
     73    const styleLink = document.createElement("link");
     74    styleLink.rel = "stylesheet";
     75    styleLink.href =
     76      "chrome://browser/content/torpreferences/torPreferences.css";
     77    dialog.shadowRoot.append(styleLink);
     78 
     79    this._acceptButton = dialog.getButton("accept");
     80 
     81    Services.obs.addObserver(this, TorConnectTopics.StageChange);
     82 
     83    this.onSelectChange();
     84    this.onAcceptStateChange();
     85  },
     86 
     87  uninit() {
     88    Services.obs.removeObserver(this, TorConnectTopics.StageChange);
     89  },
     90 
     91  onSelectChange() {
     92    const value = this._radioGroup.value;
     93    this._acceptButton.disabled = !value;
     94    this._result.type = value;
     95  },
     96 
     97  onAcceptStateChange() {
     98    const connect = TorConnect.stageName !== TorConnectStage.Bootstrapped;
     99    this._result.connect = connect;
    100    this._acceptButton.setAttribute(
    101      "data-l10n-id",
    102      connect ? "bridge-dialog-button-connect2" : "bridge-dialog-button-accept2"
    103    );
    104    this._acceptButton.classList.toggle("tor-button", connect);
    105  },
    106 
    107  observe(subject, topic) {
    108    switch (topic) {
    109      case TorConnectTopics.StageChange:
    110        this.onAcceptStateChange();
    111        break;
    112    }
    113  },
    114 };
    115 
    116 // Initial focus is not visible, even if opened with a keyboard. We avoid the
    117 // default handler and manage the focus ourselves, which will paint the focus
    118 // ring by default.
    119 // NOTE: A side effect is that the focus ring will show even if the user opened
    120 // with a mouse event.
    121 // TODO: Remove this once bugzilla bug 1708261 is resolved.
    122 document.subDialogSetDefaultFocus = () => {
    123  document.getElementById("torPreferences-builtinBridge-typeSelection").focus();
    124 };
    125 
    126 window.addEventListener(
    127  "DOMContentLoaded",
    128  () => {
    129    gBuiltinBridgeDialog.init();
    130    window.addEventListener(
    131      "unload",
    132      () => {
    133        gBuiltinBridgeDialog.uninit();
    134      },
    135      { once: true }
    136    );
    137  },
    138  { once: true }
    139 );