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

Bug 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 699f1aab
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,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 = ["mozilla.org", "firefox.com"];
+6 −6
Original line number Diff line number Diff line
@@ -25,14 +25,14 @@ MOZ_APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
# of values.
# The MAR_CHANNEL_ID must not contain the following 3 characters: ",\t "
if test "$MOZ_UPDATE_CHANNEL" = "alpha"; then
  ACCEPTED_MAR_CHANNEL_IDS=basebrowser-torproject-alpha
  MAR_CHANNEL_ID=basebrowser-torproject-alpha
  ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-alpha
  MAR_CHANNEL_ID=torbrowser-torproject-alpha
elif test "$MOZ_UPDATE_CHANNEL" = "nightly"; then
  ACCEPTED_MAR_CHANNEL_IDS=basebrowser-torproject-nightly
  MAR_CHANNEL_ID=basebrowser-torproject-nightly
  ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-nightly
  MAR_CHANNEL_ID=torbrowser-torproject-nightly
else
  ACCEPTED_MAR_CHANNEL_IDS=basebrowser-torproject-release
  MAR_CHANNEL_ID=basebrowser-torproject-release
  ACCEPTED_MAR_CHANNEL_IDS=torbrowser-torproject-release
  MAR_CHANNEL_ID=torbrowser-torproject-release
fi

# Include the DevTools client, not just the server (which is the default)
+12 −0
Original line number Diff line number Diff line
@@ -9,10 +9,18 @@
import io
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()
@@ -29,6 +37,10 @@ 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 == "TorBrowser/Data/Browser/profiles.ini"
                or rel_path_file
                == "TorBrowser/Data/Browser/profile.default/bookmarks.html"
                or rel_path_file == "TorBrowser/Data/Tor/torrc"
            ):
                rel_file_path_set.add(rel_path_file)

+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_SYS_ADDON_UPDATE_ENABLED = "extensions.systemAddon.update.enabled";
const PREF_REMOTESETTINGS_DISABLED = "extensions.remoteSettings.disabled";
const PREF_USE_REMOTE = "extensions.webextensions.remote";
const PREF_EM_LAST_FORK_VERSION = "extensions.lastBaseBrowserVersion";
const PREF_EM_LAST_FORK_VERSION = "extensions.lastTorBrowserVersion";

const PREF_MIN_WEBEXT_PLATFORM_VERSION =
  "extensions.webExtensionsMinPlatformVersion";
+77 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
  AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
  AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
  DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
  UpdateLog: "resource://gre/modules/UpdateLog.sys.mjs",
  UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
  WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs",
@@ -230,6 +231,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;
@@ -343,6 +345,15 @@ ChromeUtils.defineLazyGetter(
  }
);

async function _shouldRegisterBootstrapObserver() {
  try {
    const provider = await lazy.TorProviderBuilder.build();
    return !provider.isBootstrapDone && provider.ownsTorDaemon;
  } catch {
    return false;
  }
}

/**
 * Changes `nsIApplicationUpdateService.currentState` and causes
 * `nsIApplicationUpdateService.stateTransition` to resolve.
@@ -2778,6 +2789,9 @@ export class UpdateService {
      case "network:offline-status-changed":
        await this._offlineStatusChanged(data);
        break;
      case "torconnect:bootstrap-complete":
        this._bootstrapComplete();
        break;
      case "quit-application":
        Services.obs.removeObserver(this, topic);

@@ -3270,6 +3284,35 @@ export class UpdateService {
    await this._attemptResume();
  }

  _registerBootstrapObserver() {
    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, "torconnect:bootstrap-complete");
    this._registeredBootstrapObserver = true;
  }

  _bootstrapComplete() {
    Services.obs.removeObserver(this, "torconnect:bootstrap-complete");
    this._registeredBootstrapObserver = false;

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

    this._attemptResume();
  }

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

    // Send the error code to telemetry
@@ -6585,6 +6636,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;
@@ -6715,7 +6767,23 @@ class Downloader {
      );
      shouldRegisterOnlineObserver = true;
      deleteActiveUpdate = false;

    } else if (
      status === PROXY_SERVER_CONNECTION_REFUSED &&
      (await _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
@@ -6838,7 +6906,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);
      });
@@ -7037,6 +7109,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