
henry pushed to branch tor-browser-140.0a1-15.0-1 at The Tor Project / Applications / Tor Browser Commits: 1036d63b by Henry Wilkes at 2025-06-10T13:54:43+01:00 fixup! TB 40933: Add tor-launcher functionality TB 43636: Distinguish between bootstrap errors and TorProvider initialisation errors. - - - - - f8d973ab by Henry Wilkes at 2025-06-10T13:54:45+01:00 fixup! TB 40597: Implement TorSettings module TB 43636: Move to the Start stage when a bootstrap fails due to a TorProvider initialisation error. - - - - - 4 changed files: - toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs - toolkit/components/tor-launcher/TorProvider.sys.mjs - toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs - toolkit/modules/TorConnect.sys.mjs Changes: ===================================== toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs ===================================== @@ -54,9 +54,7 @@ export class TorBootstrapRequest { } case lazy.TorProviderTopics.BootstrapError: { log.info("TorBootstrapRequest: observerd TorBootstrapError", obj); - const error = new Error(obj.summary); - Object.assign(error, obj); - this.#stop(error); + this.#stop(obj); break; } } ===================================== toolkit/components/tor-launcher/TorProvider.sys.mjs ===================================== @@ -6,7 +6,10 @@ import { clearTimeout, setTimeout } from "resource://gre/modules/Timer.sys.mjs"; import { TorLauncherUtil } from "resource://gre/modules/TorLauncherUtil.sys.mjs"; import { TorParsers } from "resource://gre/modules/TorParsers.sys.mjs"; -import { TorProviderTopics } from "resource://gre/modules/TorProviderBuilder.sys.mjs"; +import { + TorBootstrapError, + TorProviderTopics, +} from "resource://gre/modules/TorProviderBuilder.sys.mjs"; const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { @@ -996,12 +999,11 @@ export class TorProvider { // anymore, since the first error eligible for notification will as a // matter of fact cancel the bootstrap. Services.obs.notifyObservers( - { + new TorBootstrapError({ phase: statusObj.TAG, reason: statusObj.REASON, summary: statusObj.SUMMARY, - warning: statusObj.WARNING, - }, + }), TorProviderTopics.BootstrapError ); } ===================================== toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs ===================================== @@ -18,6 +18,41 @@ export const TorProviderTopics = Object.freeze({ CircuitCredentialsMatched: "TorCircuitCredentialsMatched", }); +/** + * Wrapper error class for errors raised during TorProvider.init. + */ +export class TorProviderInitError extends Error { + /** + * Create a new instance. + * + * @param {any} error - The raised error that we want to wrap. + */ + constructor(error) { + super(error?.message, { cause: error }); + this.name = "TorProviderInitError"; + } +} + +/** + * Bootstrap errors raised by the TorProvider. + */ +export class TorBootstrapError extends Error { + /** + * Create a new instance. + * + * @param {object} details - Details about the error. + * @param {string} details.summary - A summary of the error. + * @param {string} details.phase - The bootstrap phase when the error occured. + * @param {string} details.reason - The reason for the bootsrap failure. + */ + constructor(details) { + super(details.summary); + this.name = "TorBootstrapError"; + this.phase = details.phase; + this.reason = details.reason; + } +} + export const TorProviders = Object.freeze({ none: 0, tor: 1, @@ -178,7 +213,13 @@ export class TorProviderBuilder { (await oldProvider)?.uninit(); } catch {} const provider = new lazy.TorProvider(); - await provider.init(); + try { + await provider.init(); + } catch (error) { + // Wrap in an error type for callers to know whether the error comes from + // initialisation or something else. + throw new TorProviderInitError(error); + } return provider; } ===================================== toolkit/modules/TorConnect.sys.mjs ===================================== @@ -10,6 +10,8 @@ ChromeUtils.defineESModuleGetters(lazy, { MoatRPC: "resource://gre/modules/Moat.sys.mjs", TorBootstrapRequest: "resource://gre/modules/TorBootstrapRequest.sys.mjs", TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorBootstrapError: "resource://gre/modules/TorProviderBuilder.sys.mjs", + TorProviderInitError: "resource://gre/modules/TorProviderBuilder.sys.mjs", TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs", TorSettings: "resource://gre/modules/TorSettings.sys.mjs", TorSettingsTopics: "resource://gre/modules/TorSettings.sys.mjs", @@ -223,9 +225,11 @@ class BootstrapAttempt { _timeout: 0, bootstrap() { this._timeout = setTimeout(() => { - const err = new Error("Censorship simulation"); - err.phase = "conn"; - err.reason = "noroute"; + const err = new lazy.TorBootstrapError({ + summary: "Censorship simulation", + phase: "conn", + reason: "noroute", + }); this.onbootstraperror(err); }, options.simulateDelay || 0); }, @@ -258,9 +262,7 @@ class BootstrapAttempt { return; } - this.#resolveRun({ - error: new TorConnectError(TorConnectError.BootstrapError, error), - }); + this.#resolveRun({ error }); }; this.#bootstrap.bootstrap(); @@ -595,12 +597,9 @@ class AutoBootstrapAttempt { // bootstrapAttempt. result = await this.#bootstrapAttempt.run(progressCallback, options); } catch (error) { - // Only re-try with the next settings *if* we have a BootstrapError. + // Only re-try with the next settings *if* we have a TorBootstrapError. // Other errors will end this auto-bootstrap attempt entirely. - if ( - error instanceof TorConnectError && - error.code === TorConnectError.BootstrapError - ) { + if (error instanceof lazy.TorBootstrapError) { lazy.logger.info("TorConnect setting failed", bridges, error); // Try with the next settings. // NOTE: We do not restore the user settings in between these runs. @@ -1200,7 +1199,9 @@ export const TorConnect = { // Currently it simulates the old behaviour for about:torconnect. lazy.logger.debug("Signalling error", error); - if (!(error instanceof TorConnectError)) { + if (error instanceof lazy.TorBootstrapError) { + error = new TorConnectError(TorConnectError.BootstrapError, error); + } else if (!(error instanceof TorConnectError)) { error = new TorConnectError(TorConnectError.ExternalError, error); } this._errorDetails = error; @@ -1434,6 +1435,19 @@ export const TorConnect = { lazy.logger.info("Bootstrap attempt error", error); this._tryAgain = true; + if (error instanceof lazy.TorProviderInitError) { + // Treat like TorProviderTopics.ProcessExited. We expect a user + // notification when this happens. + // Treat a failure as a possibly broken configuration. + // So, prevent quickstart at the next start. + Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true); + lazy.logger.info( + "Starting again since the tor provider failed to initialise" + ); + this._setStage(TorConnectStage.Start); + return; + } + if ( (beginStage === TorConnectStage.Start || beginStage === TorConnectStage.Offline) && @@ -1462,10 +1476,7 @@ export const TorConnect = { switch (beginStage) { case TorConnectStage.Start: case TorConnectStage.Offline: - if ( - error instanceof TorConnectError && - error.code === TorConnectError.BootstrapError - ) { + if (error instanceof lazy.TorBootstrapError) { errorStage = TorConnectStage.ChooseRegion; } // Else, some other unexpected error type. Skip straight to the View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/469928c... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/469928c... You're receiving this email because of your account on gitlab.torproject.org.
participants (1)
-
henry (@henry)