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

TB 41668: Tweaks to the Base Browser updater for Tor Browser

This commit was once part of "Bug 4234: Use the Firefox Update Process
for Tor Browser.".
However, some parts of it were not needed for Base Browser and some
derivative browsers.
Therefore, we extracted from that commit the parts for Tor Browser
legacy, and we add them back to the patch set with this commit.
parent 60b4b5b7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ ChromeUtils.defineLazyGetter(lazy, "gWindowsAlertsService", () => {
});

const FORK_VERSION_PREF =
  "browser.startup.homepage_override.basebrowser.version";
  "browser.startup.homepage_override.torbrowser.version";

// One-time startup homepage override configurations
const ONCE_DOMAINS = new Set(["mozilla.org", "firefox.com"]);
+14 −0
Original line number Diff line number Diff line
@@ -8,10 +8,18 @@

import os

# TODO When TOR_BROWSER_DATA_OUTSIDE_APP_DIR is used on all platforms,
# we should remove all lines in this file that contain:
#      TorBrowser/Data


def get_build_entries(root_path):
    """Iterates through the root_path, creating a list for each file and
    directory. Excludes any file paths ending with channel-prefs.js.
    To support Tor Browser updates, excludes:
      TorBrowser/Data/Browser/profiles.ini
      TorBrowser/Data/Browser/profile.default/bookmarks.html
      TorBrowser/Data/Tor/torrc
    """
    rel_file_path_set = set()
    rel_dir_path_set = set()
@@ -20,6 +28,11 @@ def get_build_entries(root_path):
            parent_dir_rel_path = root[len(root_path) + 1 :]
            rel_path_file = os.path.join(parent_dir_rel_path, file_name)
            rel_path_file = rel_path_file.replace("\\", "/")
            tb_data_files = {
                "TorBrowser/Data/Browser/profiles.ini",
                "TorBrowser/Data/Browser/profile.default/bookmarks.html",
                "TorBrowser/Data/Tor/torrc",
            }
            if not (
                rel_path_file.endswith("channel-prefs.js")
                or rel_path_file.endswith("update-settings.ini")
@@ -28,6 +41,7 @@ def get_build_entries(root_path):
                or "/UpdateSettings.framework/" in rel_path_file
                or rel_path_file.startswith("UpdateSettings.framework/")
                or "distribution/" in rel_path_file
                or rel_path_file in tb_data_files
            ):
                rel_file_path_set.add(rel_path_file)

+7 −0
Original line number Diff line number Diff line
@@ -137,6 +137,13 @@ nsURLFormatterService.prototype = {
    BB_VERSION() {
      return AppConstants.BASE_BROWSER_VERSION;
    },
    BB_VERSION_FOR_URLS() {
      let version = AppConstants.BASE_BROWSER_VERSION;
      if (/^[0-9a\.]+$/.test(version)) {
        version = version.replaceAll(".", "");
      }
      return version;
    },
  },

  formatURL: function uf_formatURL(aFormat) {
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ const PREF_GLEAN_PING_ADDONS_UPDATED_IDLE_TIMEOUT_MS =
  "extensions.gleanPingAddons.updated.idleTimeout";
const PREF_GLEAN_PING_ADDONS_UPDATED_TESTING =
  "extensions.gleanPingAddons.updated.testing";
const PREF_EM_LAST_FORK_VERSION = "extensions.lastBaseBrowserVersion";
const PREF_EM_LAST_FORK_VERSION = "extensions.lastTorBrowserVersion";

const PREF_MIN_WEBEXT_PLATFORM_VERSION =
  "extensions.webExtensionsMinPlatformVersion";
+108 −2
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ ChromeUtils.defineESModuleGetters(lazy, {
  AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
  AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
  DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
  TorConnect: "moz-src:///toolkit/modules/TorConnect.sys.mjs",
  TorConnectStage: "moz-src:///toolkit/modules/TorConnect.sys.mjs",
  TorConnectTopics: "moz-src:///toolkit/modules/TorConnect.sys.mjs",
  UpdateLog: "resource://gre/modules/UpdateLog.sys.mjs",
  UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
  WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs",
@@ -241,6 +244,7 @@ const SERVICE_ERRORS = [
// Custom update error codes
const BACKGROUNDCHECK_MULTIPLE_FAILURES = 110;
const NETWORK_ERROR_OFFLINE = 111;
const PROXY_SERVER_CONNECTION_REFUSED = 2152398920;

// Error codes should be < 1000. Errors above 1000 represent http status codes
const HTTP_ERROR_OFFSET = 1000;
@@ -2818,6 +2822,9 @@ export class UpdateService {
      case "network:offline-status-changed":
        await this._offlineStatusChanged(data);
        break;
      case lazy.TorConnectTopics.BootstrapComplete:
        this._bootstrapComplete();
        break;
      case "quit-application":
        Services.obs.removeObserver(this, topic);

@@ -3431,6 +3438,73 @@ export class UpdateService {
    await this._attemptResume();
  }

  /**
   * Whether we should wait for the Tor bootstrap event to try again because we
   * are not yet bootstrapped.
   *
   * If the browser does not monitor the Tor connection state, this will return
   * `false` since the event will never fire.
   *
   * @returns {boolean} - Whether we should wait for the bootstrap event.
   */
  _shouldRegisterBootstrapObserver() {
    return (
      lazy.TorConnect.enabled &&
      lazy.TorConnect.stageName !== lazy.TorConnectStage.Bootstrapped
    );
  }

  /**
   * Wait for the Tor connection to be bootstrapped before trying again.
   */
  _registerBootstrapObserver() {
    // Double check that we haven't since become bootstrapped between the call
    // to _shouldRegisterBootstrapObserver and _registerBootstrapObserver, which
    // may be delayed. If so, we do not wait for the BootstrapComplete signal
    // since it has already fired.
    if (lazy.TorConnect.stageName === lazy.TorConnectStage.Bootstrapped) {
      LOG("UpdateService:_registerBootstrapObserver - already bootstrapped");
      this._bootstrapComplete();
      return;
    }

    if (this._registeredBootstrapObserver) {
      LOG(
        "UpdateService:_registerBootstrapObserver - observer already registered"
      );
      return;
    }

    LOG(
      "UpdateService:_registerBootstrapObserver - waiting for tor bootstrap " +
        "to be complete, then forcing another check"
    );

    Services.obs.addObserver(this, lazy.TorConnectTopics.BootstrapComplete);
    this._registeredBootstrapObserver = true;
  }

  /**
   * Called when the Tor connection becomes bootstrapped. This will trigger a
   * retry.
   */
  _bootstrapComplete() {
    if (this._registeredBootstrapObserver) {
      Services.obs.removeObserver(
        this,
        lazy.TorConnectTopics.BootstrapComplete
      );
      this._registeredBootstrapObserver = false;
    }

    LOG(
      "UpdateService:_bootstrapComplete - bootstrapping complete, forcing " +
        "another background check"
    );

    this._attemptResume();
  }

  /**
   * See nsIUpdateService.idl
   */
@@ -3464,6 +3538,14 @@ export class UpdateService {
        AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_OFFLINE);
      }
      return;
    } else if (
      update.errorCode === PROXY_SERVER_CONNECTION_REFUSED &&
      this._shouldRegisterBootstrapObserver()
    ) {
      // Register boostrap observer to try again, but only when we own the
      // tor process.
      this._registerBootstrapObserver();
      return;
    }

    // Send the error code to telemetry
@@ -6919,6 +7001,7 @@ class Downloader {
    var state = this._patch.state;
    var shouldShowPrompt = false;
    var shouldRegisterOnlineObserver = false;
    var shouldRegisterBootstrapObserver = false;
    var shouldRetrySoon = false;
    var deleteActiveUpdate = false;
    let migratedToReadyUpdate = false;
@@ -7049,7 +7132,23 @@ class Downloader {
      );
      shouldRegisterOnlineObserver = true;
      deleteActiveUpdate = false;

    } else if (
      status === PROXY_SERVER_CONNECTION_REFUSED &&
      this.updateService._shouldRegisterBootstrapObserver()
    ) {
      // Register a bootstrap observer to try again.
      // The bootstrap observer will continue the incremental download by
      // calling downloadUpdate on the active update which continues
      // downloading the file from where it was.
      LOG(
        "Downloader:onStopRequest - not bootstrapped, register bootstrap observer: true"
      );
      AUSTLMY.pingDownloadCode(
        this.isCompleteUpdate,
        AUSTLMY.DWNLD_RETRY_OFFLINE
      );
      shouldRegisterBootstrapObserver = true;
      deleteActiveUpdate = false;
      // Each of NS_ERROR_NET_TIMEOUT, ERROR_CONNECTION_REFUSED,
      // NS_ERROR_NET_RESET and NS_ERROR_DOCUMENT_NOT_CACHED can be returned
      // when disconnecting the internet while a download of a MAR is in
@@ -7177,7 +7276,11 @@ class Downloader {

    // Only notify listeners about the stopped state if we
    // aren't handling an internal retry.
    if (!shouldRetrySoon && !shouldRegisterOnlineObserver) {
    if (
      !shouldRetrySoon &&
      !shouldRegisterOnlineObserver &&
      !shouldRegisterBootstrapObserver
    ) {
      this.updateService.forEachDownloadListener(listener => {
        listener.onStopRequest(request, status);
      });
@@ -7373,6 +7476,9 @@ class Downloader {
    if (shouldRegisterOnlineObserver) {
      LOG("Downloader:onStopRequest - Registering online observer");
      this.updateService._registerOnlineObserver();
    } else if (shouldRegisterBootstrapObserver) {
      LOG("Downloader:onStopRequest - Registering bootstrap observer");
      this.updateService._registerBootstrapObserver();
    } else if (shouldRetrySoon) {
      LOG("Downloader:onStopRequest - Retrying soon");
      this.updateService._consecutiveSocketErrors++;
Loading