Verified Commit e2537bc3 authored by Pier Angelo Vendrame's avatar Pier Angelo Vendrame 🎃
Browse files

fixup! Bug 40933: Add tor-launcher functionality

Store the SOCKS settings as a member, so that we can customize them if
needed before applying them.

Also, cleanup the public interface of TorProcess.
E.g., removed TorProcess.connectionWorked, since we do not use this
information anymore.

Finally, added a TorLauncherUtil.isAndroid.
parent b1c0325e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -325,6 +325,10 @@ class TorFile {
}

export const TorLauncherUtil = Object.freeze({
  get isAndroid() {
    return Services.appinfo.OS === "Android";
  },

  get isMac() {
    return Services.appinfo.OS === "Darwin";
  },
+0 −28
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@ export class TorProcess {
  #args = [];
  #subprocess = null;
  #status = TorProcessStatus.Unknown;
  // Have we ever made a connection on the control port?
  #didConnectToTorControlPort = false;

  onExit = exitCode => {};

@@ -69,10 +67,6 @@ export class TorProcess {
    }
  }

  get status() {
    return this.#status;
  }

  get isRunning() {
    return (
      this.#status === TorProcessStatus.Starting ||
@@ -102,7 +96,6 @@ export class TorProcess {
      }

      this.#status = TorProcessStatus.Starting;
      this.#didConnectToTorControlPort = false;

      // useful for simulating slow tor daemon launch
      const kPrefTorDaemonLaunchDelay = "extensions.torlauncher.launch_delay";
@@ -155,13 +148,6 @@ export class TorProcess {
    this.#status = TorProcessStatus.Exited;
  }

  // The owner of the process can use this function to tell us that they
  // successfully connected to the control port. This information will be used
  // only to decide which text to show in the confirmation dialog if tor exits.
  connectionWorked() {
    this.#didConnectToTorControlPort = true;
  }

  async #dumpStdout() {
    let string;
    while (
@@ -201,20 +187,6 @@ export class TorProcess {
  #processExitedUnexpectedly(exitCode) {
    this.#subprocess = null;
    this.#status = TorProcessStatus.Exited;
    // FIXME: We can probably drop #didConnectToTorControlPort and use only one
    // callback. Then we can let the provider actually distinguish between the
    // cases.
    if (!this.#didConnectToTorControlPort) {
      logger.warn("Tor exited before we could connect to its control port.");
      // tor might be misconfigured, because we could never connect to it.
      // Two instances of Tor Browser trying to use the same port numbers is
      // also a typical scenario for this.
      // This might happen very early, before the browser UI is actually
      // available. So, we will tell the process owner that the process exited,
      // without trying to restart it.
      this.onExit(exitCode);
      return;
    }
    logger.warn("Tor exited suddenly.");
    this.onExit(exitCode);
  }
+24 −9
Original line number Diff line number Diff line
@@ -35,6 +35,15 @@ const logger = new ConsoleAPI({
 * @property {string=} host The host to connect for a TCP control port
 * @property {number=} port The port number to use for a TCP control port
 */
/**
 * @typedef {object} SocksSettings An object that includes the proxy settings to
 * be configured in the browser.
 * @property {boolean=} transproxy If true, no proxy is configured
 * @property {nsIFile=} ipcFile The nsIFile object with the path to a Unix
 * socket to use for an IPC proxy
 * @property {string=} host The host to connect for a TCP proxy
 * @property {number=} port The port number to use for a TCP proxy
 */
/**
 * @typedef {object} LogEntry An object with a log message
 * @property {Date} date The date at which we received the message
@@ -111,6 +120,13 @@ export class TorProvider {
   */
  #torProcess = null;

  /**
   * The settings for the SOCKS proxy.
   *
   * @type {SocksSettings?}
   */
  #socksSettings = null;

  /**
   * The logs we received over the control port.
   * We store a finite number of log entries which can be configured with
@@ -165,8 +181,9 @@ export class TorProvider {
  async init() {
    logger.debug("Initializing the Tor provider.");

    const socksSettings = TorLauncherUtil.getPreferredSocksConfiguration();
    logger.debug("Requested SOCKS configuration", socksSettings);
    // These settings might be customized in the following steps.
    this.#socksSettings = TorLauncherUtil.getPreferredSocksConfiguration();
    logger.debug("Requested SOCKS configuration", this.#socksSettings);

    try {
      await this.#setControlPortConfiguration();
@@ -175,11 +192,11 @@ export class TorProvider {
      throw e;
    }

    if (socksSettings.transproxy) {
    if (this.#socksSettings.transproxy) {
      logger.info("Transparent proxy required, not starting a Tor daemon.");
    } else if (this.ownsTorDaemon) {
      try {
        await this.#startDaemon(socksSettings);
        await this.#startDaemon();
      } catch (e) {
        logger.error("Failed to start the tor daemon", e);
        throw e;
@@ -197,8 +214,7 @@ export class TorProvider {
      throw e;
    }

    // We do not customize SOCKS settings, at least for now.
    TorLauncherUtil.setProxyConfiguration(socksSettings);
    TorLauncherUtil.setProxyConfiguration(this.#socksSettings);

    logger.info("The Tor provider is ready.");

@@ -464,7 +480,7 @@ export class TorProvider {

  // Process management

  async #startDaemon(socksSettings) {
  async #startDaemon() {
    // TorProcess should be instanced once, then always reused and restarted
    // only through the prompt it exposes when the controlled process dies.
    if (this.#torProcess) {
@@ -476,7 +492,7 @@ export class TorProvider {

    this.#torProcess = new lazy.TorProcess(
      this.#controlPortSettings,
      socksSettings
      this.#socksSettings
    );
    // Use a closure instead of bind because we reassign #cancelConnection.
    // Also, we now assign an exit handler that cancels the first connection,
@@ -619,7 +635,6 @@ export class TorProvider {
        }
        this.#openControlPort()
          .then(controller => {
            this.#torProcess?.connectionWorked();
            this.#cancelConnection = () => {};
            // The cancel function should have already called reject.
            if (!canceled) {