tor-browser

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

AboutTorParent.sys.mjs (4405B)


      1 import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
      2 
      3 const lazy = {};
      4 
      5 ChromeUtils.defineESModuleGetters(lazy, {
      6  AboutTorMessage: "resource:///modules/AboutTorMessage.sys.mjs",
      7  TorConnect: "resource://gre/modules/TorConnect.sys.mjs",
      8 });
      9 
     10 const initializedActors = new Set();
     11 const onionizePref = "torbrowser.homepage.search.onionize";
     12 const surveyDismissVersionPref = "torbrowser.homepage.survey.dismiss_version";
     13 
     14 /**
     15 * Actor parent class for the about:tor page.
     16 */
     17 export class AboutTorParent extends JSWindowActorParent {
     18  /**
     19   * Whether the user has dismissed the Year End Campaign (YEC) banner this
     20   * session.
     21   *
     22   * @type {boolean}
     23   */
     24  static #dismissYEC = false;
     25 
     26  /**
     27   * Whether this instance has a preloaded browser.
     28   *
     29   * @type {boolean}
     30   */
     31  #preloaded = false;
     32 
     33  /**
     34   * Method to be called when the browser corresponding to this actor has its
     35   * preloadedState attribute removed.
     36   */
     37  preloadedRemoved() {
     38    if (!this.#preloaded) {
     39      return;
     40    }
     41    this.#preloaded = false;
     42    // Send in the initial data now that the page is actually going to be
     43    // visible.
     44    this.sendAsyncMessage(
     45      "AboutTor:DelayedInitialData",
     46      this.#getInitialData()
     47    );
     48  }
     49 
     50  /**
     51   * Get the initial data for the page when it is about to be shown.
     52   *
     53   * @returns {object} - The initial data.
     54   */
     55  #getInitialData() {
     56    let appLocale = Services.locale.appLocaleAsBCP47;
     57    if (appLocale === "ja-JP-macos") {
     58      appLocale = "ja";
     59    }
     60 
     61    return {
     62      torConnectEnabled: lazy.TorConnect.enabled,
     63      messageData: lazy.AboutTorMessage.getNext(),
     64      isStable: AppConstants.MOZ_UPDATE_CHANNEL === "release",
     65      searchOnionize: Services.prefs.getBoolPref(onionizePref, false),
     66      surveyDismissVersion: Services.prefs.getIntPref(
     67        surveyDismissVersionPref,
     68        0
     69      ),
     70      appLocale,
     71      dismissYEC: AboutTorParent.#dismissYEC,
     72    };
     73  }
     74 
     75  didDestroy() {
     76    initializedActors.delete(this);
     77  }
     78 
     79  receiveMessage(message) {
     80    switch (message.name) {
     81      case "AboutTor:GetInitialData": {
     82        // Track this actor to send future updates.
     83        initializedActors.add(this);
     84 
     85        const browser = this.browsingContext.top.embedderElement;
     86        if (browser?.getAttribute("preloadedState") === "preloaded") {
     87          // Wait until the page is actually about to be shown before sending
     88          // the initial data.
     89          // Otherwise the preloaded page might receive data that has expired by
     90          // the time the page is shown. And it will iterate
     91          // AboutTorMessage.getNext too early. See tor-browser#44314.
     92          this.#preloaded = true;
     93          return Promise.resolve(null);
     94        }
     95        return Promise.resolve(this.#getInitialData());
     96      }
     97      case "AboutTor:SetSearchOnionize":
     98        Services.prefs.setBoolPref(onionizePref, message.data);
     99        break;
    100      case "AboutTor:SurveyDismissed":
    101        // The message.data contains the version of the current survey.
    102        // Rather than introduce a new preference for each survey campaign we
    103        // reuse the same integer preference and increase its value every time
    104        // a new version of the survey is shown and dismissed by the user.
    105        // I.e. if the preference value is 2, we will not show survey version 2
    106        // but will show survey version 3 or higher when they are introduced.
    107        // It should be safe to overwrite the value since we do not expect more
    108        // than one active survey campaign at any given time, nor do we expect
    109        // the version value to decrease.
    110        Services.prefs.setIntPref(surveyDismissVersionPref, message.data);
    111        break;
    112      case "AboutTor:UserDismissedYEC":
    113        AboutTorParent.#dismissYEC = true;
    114        for (const actor of initializedActors) {
    115          if (actor === this) {
    116            // Don't send to ourselves.
    117            continue;
    118          }
    119          // Tell all existing instances to also close the banner, if they still
    120          // exist.
    121          // NOTE: If the user's new tab page is `about:tor`, this may include
    122          // some preloaded pages that have not been made visible yet (see
    123          // NewTabPagePreloading).
    124          try {
    125            actor.sendAsyncMessage("AboutTor:DismissYEC");
    126          } catch {}
    127        }
    128        break;
    129    }
    130    return undefined;
    131  }
    132 }