Commit 0ad143ac authored by Pier Angelo Vendrame's avatar Pier Angelo Vendrame 🎃 Committed by brizental
Browse files

Bug 40933: Add tor-launcher functionality

Bug 41926: Reimplement the control port
parent 235250d1
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
    "resource://messaging-system/lib/SpecialMessageActions.sys.mjs",
  TRRRacer: "resource:///modules/TRRPerformance.sys.mjs",
  TelemetryUtils: "resource://gre/modules/TelemetryUtils.sys.mjs",
  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
  UIState: "resource://services-sync/UIState.sys.mjs",
  UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
  WebChannel: "resource://gre/modules/WebChannel.sys.mjs",
@@ -1839,6 +1840,8 @@ BrowserGlue.prototype = {

    lazy.SecurityLevelRestartNotification.ready();

    lazy.TorProviderBuilder.firstWindowLoaded();

    ClipboardPrivacy.startup();

    this._firstWindowTelemetry(aWindow);
+1 −0
Original line number Diff line number Diff line
@@ -225,6 +225,7 @@
@RESPATH@/browser/chrome/browser.manifest
@RESPATH@/chrome/pdfjs.manifest
@RESPATH@/chrome/pdfjs/*
@RESPATH@/components/tor-launcher.manifest
@RESPATH@/chrome/torbutton.manifest
@RESPATH@/chrome/torbutton/*
@RESPATH@/chrome/toolkit@JAREXT@
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ DIRS += [
    "thumbnails",
    "timermanager",
    "tooltiptext",
    "tor-launcher",
    "typeaheadfind",
    "utils",
    "url-classifier",
+135 −0
Original line number Diff line number Diff line
import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs";

const lazy = {};

ChromeUtils.defineESModuleGetters(lazy, {
  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
  TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs",
});

// modeled after XMLHttpRequest
// nicely encapsulates the observer register/unregister logic
// TODO: Remove this class, and move its logic inside the TorProvider.
export class TorBootstrapRequest {
  // number of ms to wait before we abandon the bootstrap attempt
  // a value of 0 implies we never wait
  timeout = 0;

  // callbacks for bootstrap process status updates
  onbootstrapstatus = (progress, status) => {};
  onbootstrapcomplete = () => {};
  onbootstraperror = error => {};

  // internal resolve() method for bootstrap
  #bootstrapPromiseResolve = null;
  #bootstrapPromise = null;
  #timeoutID = null;

  observe(subject, topic, data) {
    const obj = subject?.wrappedJSObject;
    switch (topic) {
      case lazy.TorProviderTopics.BootstrapStatus: {
        const progress = obj.PROGRESS;
        if (this.onbootstrapstatus) {
          const status = obj.TAG;
          this.onbootstrapstatus(progress, status);
        }
        if (progress === 100) {
          if (this.onbootstrapcomplete) {
            this.onbootstrapcomplete();
          }
          this.#bootstrapPromiseResolve(true);
          clearTimeout(this.#timeoutID);
          this.#timeoutID = null;
        }

        break;
      }
      case lazy.TorProviderTopics.BootstrapError: {
        console.info("TorBootstrapRequest: observerd TorBootstrapError", obj);
        const error = new Error(obj.summary);
        Object.assign(error, obj);
        this.#stop(error);
        break;
      }
    }
  }

  // resolves 'true' if bootstrap succeeds, false otherwise
  bootstrap() {
    if (this.#bootstrapPromise) {
      return this.#bootstrapPromise;
    }

    this.#bootstrapPromise = new Promise((resolve, reject) => {
      this.#bootstrapPromiseResolve = resolve;

      // register ourselves to listen for bootstrap events
      Services.obs.addObserver(this, lazy.TorProviderTopics.BootstrapStatus);
      Services.obs.addObserver(this, lazy.TorProviderTopics.BootstrapError);

      // optionally cancel bootstrap after a given timeout
      if (this.timeout > 0) {
        this.#timeoutID = setTimeout(() => {
          this.#timeoutID = null;
          this.#stop(
            new Error(
              `Bootstrap attempt abandoned after waiting ${this.timeout} ms`
            )
          );
        }, this.timeout);
      }

      // Wait for bootstrapping to begin and maybe handle error.
      // Notice that we do not resolve the promise here in case of success, but
      // we do it from the BootstrapStatus observer.
      lazy.TorProviderBuilder.build()
        .then(provider => provider.connect())
        .catch(err => {
          this.#stop(err);
        });
    }).finally(() => {
      // and remove ourselves once bootstrap is resolved
      Services.obs.removeObserver(this, lazy.TorProviderTopics.BootstrapStatus);
      Services.obs.removeObserver(this, lazy.TorProviderTopics.BootstrapError);
      this.#bootstrapPromise = null;
    });

    return this.#bootstrapPromise;
  }

  async cancel() {
    await this.#stop();
  }

  // Internal implementation. Do not use directly, but call cancel, instead.
  async #stop(error) {
    // first stop our bootstrap timeout before handling the error
    if (this.#timeoutID !== null) {
      clearTimeout(this.#timeoutID);
      this.#timeoutID = null;
    }

    let provider;
    try {
      provider = await lazy.TorProviderBuilder.build();
    } catch {
      // This was probably the error that lead to stop in the first place.
      // No need to continue propagating it.
    }
    try {
      await provider?.stopBootstrap();
    } catch (e) {
      console.error("Failed to stop the bootstrap.", e);
      if (!error) {
        error = e;
      }
    }

    if (this.onbootstraperror && error) {
      this.onbootstraperror(error);
    }

    this.#bootstrapPromiseResolve(false);
  }
}
+1290 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading