tor-browser

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

OnionLocationParent.sys.mjs (5258B)


      1 // Copyright (c) 2020, The Tor Project, Inc.
      2 
      3 import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs";
      4 
      5 // Prefs
      6 
      7 // We keep the "prioritizeonions" name, even if obsolete, in order to
      8 // prevent the notification from being shown again to upgrading users.
      9 const NOTIFICATION_PREF = "privacy.prioritizeonions.showNotification";
     10 
     11 // Element IDs
     12 const ONIONLOCATION_BOX_ID = "onion-location-box";
     13 const ONIONLOCATION_LABEL_ID = "onion-label";
     14 
     15 // Notification IDs
     16 const NOTIFICATION_ID = "onion-location";
     17 const NOTIFICATION_ANCHOR_ID = "onion-location-box";
     18 
     19 // Strings
     20 const STRING_ONION_AVAILABLE = TorStrings.onionLocation.onionAvailable;
     21 const NOTIFICATION_CANCEL_LABEL = TorStrings.onionLocation.notNow;
     22 const NOTIFICATION_CANCEL_ACCESSKEY = TorStrings.onionLocation.notNowAccessKey;
     23 const NOTIFICATION_OK_LABEL = TorStrings.onionLocation.loadOnion;
     24 const NOTIFICATION_OK_ACCESSKEY = TorStrings.onionLocation.loadOnionAccessKey;
     25 const NOTIFICATION_TITLE = TorStrings.onionLocation.tryThis;
     26 const NOTIFICATION_DESCRIPTION = TorStrings.onionLocation.description;
     27 const NOTIFICATION_LEARN_MORE_URL =
     28  TorStrings.onionLocation.learnMoreURLNotification;
     29 
     30 /**
     31 * This class contains the parent part of Onion Location.
     32 */
     33 export class OnionLocationParent extends JSWindowActorParent {
     34  // Listeners are added in BrowserGlue.jsm
     35  receiveMessage(aMsg) {
     36    switch (aMsg.name) {
     37      case "OnionLocation:Set": {
     38        let browser = this.browsingContext.embedderElement;
     39        OnionLocationParent.setOnionLocation(browser);
     40        break;
     41      }
     42    }
     43  }
     44 
     45  static init(document) {
     46    document
     47      .getElementById(ONIONLOCATION_BOX_ID)
     48      .addEventListener("click", event => this.buttonClick(event));
     49  }
     50 
     51  static buttonClick(event) {
     52    if (event.button !== 0) {
     53      return;
     54    }
     55    const win = event.target.ownerGlobal;
     56    if (win.gBrowser) {
     57      const browser = win.gBrowser.selectedBrowser;
     58      OnionLocationParent.redirect(browser);
     59    }
     60  }
     61 
     62  static redirect(browser) {
     63    let windowGlobal = browser.browsingContext.currentWindowGlobal;
     64    let actor = windowGlobal.getActor("OnionLocation");
     65    if (actor) {
     66      actor.sendAsyncMessage("OnionLocation:Refresh", {});
     67      OnionLocationParent.setDisabled(browser);
     68    }
     69  }
     70 
     71  static onStateChange(browser) {
     72    delete browser._onionLocation;
     73    OnionLocationParent.hideNotification(browser);
     74  }
     75 
     76  static setOnionLocation(browser) {
     77    browser._onionLocation = true;
     78    let tabBrowser = browser.getTabBrowser();
     79    if (tabBrowser && browser === tabBrowser.selectedBrowser) {
     80      OnionLocationParent.updateOnionLocationBadge(browser);
     81    }
     82  }
     83 
     84  static hideNotification(browser) {
     85    const win = browser.ownerGlobal;
     86    if (browser._onionLocationPrompt) {
     87      win.PopupNotifications.remove(browser._onionLocationPrompt);
     88    }
     89  }
     90 
     91  static showNotification(browser) {
     92    const mustShow = Services.prefs.getBoolPref(NOTIFICATION_PREF, true);
     93    if (!mustShow) {
     94      return;
     95    }
     96 
     97    const win = browser.ownerGlobal;
     98    Services.prefs.setBoolPref(NOTIFICATION_PREF, false);
     99 
    100    const mainAction = {
    101      label: NOTIFICATION_OK_LABEL,
    102      accessKey: NOTIFICATION_OK_ACCESSKEY,
    103      callback() {
    104        OnionLocationParent.redirect(browser);
    105      },
    106    };
    107 
    108    const cancelAction = {
    109      label: NOTIFICATION_CANCEL_LABEL,
    110      accessKey: NOTIFICATION_CANCEL_ACCESSKEY,
    111      callback: () => {},
    112    };
    113 
    114    win.document.getElementById("onion-location-body-text").textContent =
    115      NOTIFICATION_DESCRIPTION;
    116 
    117    const options = {
    118      autofocus: true,
    119      persistent: true,
    120      removeOnDismissal: false,
    121      eventCallback(aTopic) {
    122        if (aTopic === "removed") {
    123          delete browser._onionLocationPrompt;
    124        }
    125      },
    126      learnMoreURL: NOTIFICATION_LEARN_MORE_URL,
    127      hideClose: true,
    128      popupOptions: {
    129        position: "bottomright topright",
    130      },
    131    };
    132 
    133    // A hacky way of setting the popup anchor outside the usual url bar icon
    134    // box, similar to CRF and addons.
    135    // See: https://searchfox.org/mozilla-esr115/rev/7962d6b7b17ee105ad64ab7906af2b9179f6e3d2/toolkit/modules/PopupNotifications.sys.mjs#46
    136    browser[NOTIFICATION_ANCHOR_ID + "popupnotificationanchor"] =
    137      win.document.getElementById(NOTIFICATION_ANCHOR_ID);
    138 
    139    browser._onionLocationPrompt = win.PopupNotifications.show(
    140      browser,
    141      NOTIFICATION_ID,
    142      NOTIFICATION_TITLE,
    143      NOTIFICATION_ANCHOR_ID,
    144      mainAction,
    145      [cancelAction],
    146      options
    147    );
    148  }
    149 
    150  static setEnabled(browser) {
    151    const win = browser.ownerGlobal;
    152    const label = win.document.getElementById(ONIONLOCATION_LABEL_ID);
    153    label.textContent = STRING_ONION_AVAILABLE;
    154    const elem = win.document.getElementById(ONIONLOCATION_BOX_ID);
    155    elem.removeAttribute("hidden");
    156  }
    157 
    158  static setDisabled(browser) {
    159    const win = browser.ownerGlobal;
    160    const elem = win.document.getElementById(ONIONLOCATION_BOX_ID);
    161    elem.setAttribute("hidden", true);
    162  }
    163 
    164  static updateOnionLocationBadge(browser) {
    165    if (browser._onionLocation) {
    166      OnionLocationParent.setEnabled(browser);
    167      OnionLocationParent.showNotification(browser);
    168    } else {
    169      OnionLocationParent.setDisabled(browser);
    170    }
    171  }
    172 }