Pier Angelo Vendrame pushed to branch tor-browser-115.8.0esr-13.5-1 at The Tor Project / Applications / Tor Browser

Commits:

10 changed files:

Changes:

  • browser/components/torpreferences/content/connectionPane.js
    ... ... @@ -114,10 +114,9 @@ async function setTorSettings(changes) {
    114 114
         // This will trigger TorSettings.#cleanupSettings()
    
    115 115
         TorSettings.saveToPrefs();
    
    116 116
         try {
    
    117
    -      // May throw.
    
    118 117
           await TorSettings.applySettings();
    
    119 118
         } catch (e) {
    
    120
    -      console.error("Failed to save Tor settings", e);
    
    119
    +      console.error("Failed to apply Tor settings", e);
    
    121 120
         }
    
    122 121
       } finally {
    
    123 122
         TorSettings.thawNotifications();
    

  • browser/components/torpreferences/content/connectionSettingsDialog.js
    ... ... @@ -362,6 +362,8 @@ const gConnectionSettingsDialog = {
    362 362
         }
    
    363 363
     
    
    364 364
         TorSettings.saveToPrefs();
    
    365
    +    // FIXME: What if this fails? Should we prevent the dialog to close and show
    
    366
    +    // an error?
    
    365 367
         TorSettings.applySettings();
    
    366 368
       },
    
    367 369
     };
    

  • toolkit/components/tor-launcher/TorControlPort.sys.mjs
    ... ... @@ -838,10 +838,12 @@ export class TorController {
    838 838
       /**
    
    839 839
        * Send multiple configuration values to tor.
    
    840 840
        *
    
    841
    -   * @param {object} values The values to set
    
    841
    +   * @param {Array} values The values to set. It should be an array of
    
    842
    +   * [key, value] pairs to pass to SETCONF. Keys can be repeated, and array
    
    843
    +   * values will be automatically unrolled.
    
    842 844
        */
    
    843 845
       async setConf(values) {
    
    844
    -    const args = Object.entries(values)
    
    846
    +    const args = values
    
    845 847
           .flatMap(([key, value]) => {
    
    846 848
             if (value === undefined || value === null) {
    
    847 849
               return [key];
    
    ... ... @@ -871,7 +873,7 @@ export class TorController {
    871 873
        * @param {boolean} enabled Tell whether the network should be enabled
    
    872 874
        */
    
    873 875
       async setNetworkEnabled(enabled) {
    
    874
    -    return this.setConf({ DisableNetwork: !enabled });
    
    876
    +    return this.setConf([["DisableNetwork", !enabled]]);
    
    875 877
       }
    
    876 878
     
    
    877 879
       /**
    

  • toolkit/components/tor-launcher/TorProvider.sys.mjs
    ... ... @@ -15,6 +15,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
    15 15
       TorController: "resource://gre/modules/TorControlPort.sys.mjs",
    
    16 16
       TorProcess: "resource://gre/modules/TorProcess.sys.mjs",
    
    17 17
       TorProcessAndroid: "resource://gre/modules/TorProcessAndroid.sys.mjs",
    
    18
    +  TorProxyType: "resource://gre/modules/TorSettings.sys.mjs",
    
    19
    +  TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
    
    18 20
     });
    
    19 21
     
    
    20 22
     const logger = new ConsoleAPI({
    
    ... ... @@ -73,6 +75,20 @@ const Preferences = Object.freeze({
    73 75
       PromptAtStartup: "extensions.torlauncher.prompt_at_startup",
    
    74 76
     });
    
    75 77
     
    
    78
    +/* Config Keys used to configure tor daemon */
    
    79
    +const TorConfigKeys = Object.freeze({
    
    80
    +  useBridges: "UseBridges",
    
    81
    +  bridgeList: "Bridge",
    
    82
    +  socks4Proxy: "Socks4Proxy",
    
    83
    +  socks5Proxy: "Socks5Proxy",
    
    84
    +  socks5ProxyUsername: "Socks5ProxyUsername",
    
    85
    +  socks5ProxyPassword: "Socks5ProxyPassword",
    
    86
    +  httpsProxy: "HTTPSProxy",
    
    87
    +  httpsProxyAuthenticator: "HTTPSProxyAuthenticator",
    
    88
    +  reachableAddresses: "ReachableAddresses",
    
    89
    +  clientTransportPlugin: "ClientTransportPlugin",
    
    90
    +});
    
    91
    +
    
    76 92
     /**
    
    77 93
      * This is a Tor provider for the C Tor daemon.
    
    78 94
      *
    
    ... ... @@ -166,15 +182,6 @@ export class TorProvider {
    166 182
        */
    
    167 183
       #currentBridge = null;
    
    168 184
     
    
    169
    -  /**
    
    170
    -   * Maintain a map of tor settings set by Tor Browser so that we don't
    
    171
    -   * repeatedly set the same key/values over and over.
    
    172
    -   * This map contains string keys to primitives or array values.
    
    173
    -   *
    
    174
    -   * @type {Map<string, any>}
    
    175
    -   */
    
    176
    -  #settingsCache = new Map();
    
    177
    -
    
    178 185
       /**
    
    179 186
        * Starts a new tor process and connect to its control port, or connect to the
    
    180 187
        * control port of an existing tor daemon.
    
    ... ... @@ -219,13 +226,22 @@ export class TorProvider {
    219 226
           throw e;
    
    220 227
         }
    
    221 228
     
    
    229
    +    try {
    
    230
    +      await lazy.TorSettings.initializedPromise;
    
    231
    +      await this.writeSettings(lazy.TorSettings.getSettings());
    
    232
    +    } catch (e) {
    
    233
    +      logger.warn(
    
    234
    +        "Failed to initialize TorSettings or to write our settings, so uninitializing.",
    
    235
    +        e
    
    236
    +      );
    
    237
    +      this.uninit();
    
    238
    +      throw e;
    
    239
    +    }
    
    240
    +
    
    222 241
         TorLauncherUtil.setProxyConfiguration(this.#socksSettings);
    
    223 242
     
    
    224 243
         logger.info("The Tor provider is ready.");
    
    225 244
     
    
    226
    -    logger.debug(`Notifying ${TorProviderTopics.ProcessIsReady}`);
    
    227
    -    Services.obs.notifyObservers(null, TorProviderTopics.ProcessIsReady);
    
    228
    -
    
    229 245
         // If we are using an external Tor daemon, we might need to fetch circuits
    
    230 246
         // already, in case streams use them. Do not await because we do not want to
    
    231 247
         // block the intialization on this (it should not fail anyway...).
    
    ... ... @@ -252,42 +268,74 @@ export class TorProvider {
    252 268
     
    
    253 269
       // Provider API
    
    254 270
     
    
    255
    -  async writeSettings(settingsObj) {
    
    256
    -    // TODO: Move the translation from settings object to settings understood by
    
    257
    -    // tor here.
    
    258
    -    const entries =
    
    259
    -      settingsObj instanceof Map
    
    260
    -        ? Array.from(settingsObj.entries())
    
    261
    -        : Object.entries(settingsObj);
    
    262
    -    // only write settings that have changed
    
    263
    -    const newSettings = entries.filter(([setting, value]) => {
    
    264
    -      if (!this.#settingsCache.has(setting)) {
    
    265
    -        // no cached setting, so write
    
    266
    -        return true;
    
    267
    -      }
    
    271
    +  /**
    
    272
    +   * Send settings to the tor daemon.
    
    273
    +   *
    
    274
    +   * @param {object} settings A settings object, as returned by
    
    275
    +   * TorSettings.getSettings(). This allow to try settings without passing
    
    276
    +   * through TorSettings.
    
    277
    +   */
    
    278
    +  async writeSettings(settings) {
    
    279
    +    logger.debug("TorProvider.writeSettings", settings);
    
    280
    +    const torSettings = new Map();
    
    281
    +
    
    282
    +    // Bridges
    
    283
    +    const haveBridges =
    
    284
    +      settings.bridges?.enabled && !!settings.bridges.bridge_strings.length;
    
    285
    +    torSettings.set(TorConfigKeys.useBridges, haveBridges);
    
    286
    +    if (haveBridges) {
    
    287
    +      torSettings.set(
    
    288
    +        TorConfigKeys.bridgeList,
    
    289
    +        settings.bridges.bridge_strings
    
    290
    +      );
    
    291
    +    } else {
    
    292
    +      torSettings.set(TorConfigKeys.bridgeList, null);
    
    293
    +    }
    
    268 294
     
    
    269
    -      const cachedValue = this.#settingsCache.get(setting);
    
    270
    -      // Arrays are the only special case for which === could fail.
    
    271
    -      // The other values we accept (strings, booleans, numbers, null and
    
    272
    -      // undefined) work correctly with ===.
    
    273
    -      if (Array.isArray(value) && Array.isArray(cachedValue)) {
    
    274
    -        return (
    
    275
    -          value.length !== cachedValue.length ||
    
    276
    -          value.some((val, idx) => val !== cachedValue[idx])
    
    295
    +    // Proxy
    
    296
    +    torSettings.set(TorConfigKeys.socks4Proxy, null);
    
    297
    +    torSettings.set(TorConfigKeys.socks5Proxy, null);
    
    298
    +    torSettings.set(TorConfigKeys.socks5ProxyUsername, null);
    
    299
    +    torSettings.set(TorConfigKeys.socks5ProxyPassword, null);
    
    300
    +    torSettings.set(TorConfigKeys.httpsProxy, null);
    
    301
    +    torSettings.set(TorConfigKeys.httpsProxyAuthenticator, null);
    
    302
    +    if (settings.proxy && !settings.proxy.enabled) {
    
    303
    +      settings.proxy.type = null;
    
    304
    +    }
    
    305
    +    const address = settings.proxy?.address;
    
    306
    +    const port = settings.proxy?.port;
    
    307
    +    const username = settings.proxy?.username;
    
    308
    +    const password = settings.proxy?.password;
    
    309
    +    switch (settings.proxy?.type) {
    
    310
    +      case lazy.TorProxyType.Socks4:
    
    311
    +        torSettings.set(TorConfigKeys.socks4Proxy, `${address}:${port}`);
    
    312
    +        break;
    
    313
    +      case lazy.TorProxyType.Socks5:
    
    314
    +        torSettings.set(TorConfigKeys.socks5Proxy, `${address}:${port}`);
    
    315
    +        torSettings.set(TorConfigKeys.socks5ProxyUsername, username);
    
    316
    +        torSettings.set(TorConfigKeys.socks5ProxyPassword, password);
    
    317
    +        break;
    
    318
    +      case lazy.TorProxyType.HTTPS:
    
    319
    +        torSettings.set(TorConfigKeys.httpsProxy, `${address}:${port}`);
    
    320
    +        torSettings.set(
    
    321
    +          TorConfigKeys.httpsProxyAuthenticator,
    
    322
    +          `${username}:${password}`
    
    277 323
             );
    
    278
    -      }
    
    279
    -      return value !== cachedValue;
    
    280
    -    });
    
    281
    -
    
    282
    -    // only write if new setting to save
    
    283
    -    if (newSettings.length) {
    
    284
    -      await this.#controller.setConf(Object.fromEntries(newSettings));
    
    324
    +        break;
    
    325
    +    }
    
    285 326
     
    
    286
    -      // save settings to cache after successfully writing to Tor
    
    287
    -      for (const [setting, value] of newSettings) {
    
    288
    -        this.#settingsCache.set(setting, value);
    
    289
    -      }
    
    327
    +    // Firewall
    
    328
    +    if (settings.firewall?.enabled) {
    
    329
    +      const reachableAddresses = settings.firewall.allowed_ports
    
    330
    +        .map(port => `*:${port}`)
    
    331
    +        .join(",");
    
    332
    +      torSettings.set(TorConfigKeys.reachableAddresses, reachableAddresses);
    
    333
    +    } else {
    
    334
    +      torSettings.set(TorConfigKeys.reachableAddresses, null);
    
    290 335
         }
    
    336
    +
    
    337
    +    logger.debug("Mapped settings object", settings, torSettings);
    
    338
    +    await this.#controller.setConf(Array.from(torSettings));
    
    291 339
       }
    
    292 340
     
    
    293 341
       async flushSettings() {
    

  • toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs
    ... ... @@ -9,7 +9,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
    9 9
     });
    
    10 10
     
    
    11 11
     export const TorProviderTopics = Object.freeze({
    
    12
    -  ProcessIsReady: "TorProcessIsReady",
    
    13 12
       ProcessExited: "TorProcessExited",
    
    14 13
       BootstrapStatus: "TorBootstrapStatus",
    
    15 14
       BootstrapError: "TorBootstrapError",
    

  • toolkit/components/tor-launcher/TorStartupService.sys.mjs
    ... ... @@ -31,15 +31,16 @@ export class TorStartupService {
    31 31
         }
    
    32 32
       }
    
    33 33
     
    
    34
    -  async #init() {
    
    34
    +  #init() {
    
    35 35
         Services.obs.addObserver(this, BrowserTopics.QuitApplicationGranted);
    
    36 36
     
    
    37
    -    // Do not await on this init. build() is expected to await the
    
    38
    -    // initialization, so anything that should need the Tor Provider should
    
    39
    -    // block there, instead.
    
    37
    +    lazy.TorSettings.init();
    
    38
    +
    
    39
    +    // Theoretically, build() is expected to await the initialization of the
    
    40
    +    // provider, and anything needing the Tor Provider should be able to just
    
    41
    +    // await on TorProviderBuilder.build().
    
    40 42
         lazy.TorProviderBuilder.init();
    
    41 43
     
    
    42
    -    await lazy.TorSettings.init();
    
    43 44
         lazy.TorConnect.init();
    
    44 45
     
    
    45 46
         lazy.TorDomainIsolator.init();
    

  • toolkit/modules/Moat.sys.mjs
    ... ... @@ -2,13 +2,13 @@
    2 2
      * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3 3
      * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4 4
     
    
    5
    -import { TorBridgeSource } from "resource://gre/modules/TorSettings.sys.mjs";
    
    6
    -
    
    7 5
     const lazy = {};
    
    8 6
     
    
    9 7
     ChromeUtils.defineESModuleGetters(lazy, {
    
    10 8
       DomainFrontRequestBuilder:
    
    11 9
         "resource://gre/modules/DomainFrontedRequests.sys.mjs",
    
    10
    +  TorBridgeSource: "resource://gre/modules/TorSettings.sys.mjs",
    
    11
    +  TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
    
    12 12
     });
    
    13 13
     
    
    14 14
     const TorLauncherPrefs = Object.freeze({
    
    ... ... @@ -211,13 +211,23 @@ export class MoatRPC {
    211 211
         };
    
    212 212
         switch (settings.bridges.source) {
    
    213 213
           case "builtin":
    
    214
    -        retval.bridges.source = TorBridgeSource.BuiltIn;
    
    214
    +        retval.bridges.source = lazy.TorBridgeSource.BuiltIn;
    
    215 215
             retval.bridges.builtin_type = settings.bridges.type;
    
    216 216
             // TorSettings will ignore strings for built-in bridges, and use the
    
    217
    -        // ones it already knows, instead.
    
    217
    +        // ones it already knows, instead. However, when we try these settings
    
    218
    +        // in the connect assist, we skip TorSettings. Therefore, we set the
    
    219
    +        // lines also here (the ones we already known, not the ones we receive
    
    220
    +        // from Moat). This needs TorSettings to be initialized, which by now
    
    221
    +        // should have already happened (this method is used only by TorConnect,
    
    222
    +        // that needs TorSettings to be initialized).
    
    223
    +        // In any case, getBuiltinBridges will throw if the data is not ready,
    
    224
    +        // yet.
    
    225
    +        retval.bridges.bridge_strings = lazy.TorSettings.getBuiltinBridges(
    
    226
    +          settings.bridges.type
    
    227
    +        );
    
    218 228
             break;
    
    219 229
           case "bridgedb":
    
    220
    -        retval.bridges.source = TorBridgeSource.BridgeDB;
    
    230
    +        retval.bridges.source = lazy.TorBridgeSource.BridgeDB;
    
    221 231
             if (settings.bridges.bridge_strings) {
    
    222 232
               retval.bridges.bridge_strings = settings.bridges.bridge_strings;
    
    223 233
             } else {
    

  • toolkit/modules/TorAndroidIntegration.sys.mjs
    ... ... @@ -150,7 +150,7 @@ class TorAndroidIntegrationImpl {
    150 150
                 lazy.TorSettings.saveToPrefs();
    
    151 151
               }
    
    152 152
               if (data.apply) {
    
    153
    -            lazy.TorSettings.applySettings();
    
    153
    +            await lazy.TorSettings.applySettings();
    
    154 154
               }
    
    155 155
               break;
    
    156 156
             case ListenedEvents.settingsApply:
    

  • toolkit/modules/TorConnect.sys.mjs
    ... ... @@ -2,14 +2,17 @@
    2 2
      * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3 3
      * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4 4
     
    
    5
    +import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
    
    5 6
     import { setTimeout, clearTimeout } from "resource://gre/modules/Timer.sys.mjs";
    
    6 7
     
    
    7 8
     const lazy = {};
    
    8 9
     
    
    9 10
     ChromeUtils.defineESModuleGetters(lazy, {
    
    11
    +  ConsoleAPI: "resource://gre/modules/Console.sys.mjs",
    
    10 12
       EventDispatcher: "resource://gre/modules/Messaging.sys.mjs",
    
    11 13
       MoatRPC: "resource://gre/modules/Moat.sys.mjs",
    
    12 14
       TorBootstrapRequest: "resource://gre/modules/TorBootstrapRequest.sys.mjs",
    
    15
    +  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    13 16
     });
    
    14 17
     
    
    15 18
     // TODO: Should we move this to the about:torconnect actor?
    
    ... ... @@ -20,10 +23,7 @@ ChromeUtils.defineModuleGetter(
    20 23
     );
    
    21 24
     
    
    22 25
     import { TorLauncherUtil } from "resource://gre/modules/TorLauncherUtil.sys.mjs";
    
    23
    -import {
    
    24
    -  TorSettings,
    
    25
    -  TorSettingsTopics,
    
    26
    -} from "resource://gre/modules/TorSettings.sys.mjs";
    
    26
    +import { TorSettings } from "resource://gre/modules/TorSettings.sys.mjs";
    
    27 27
     
    
    28 28
     import { TorStrings } from "resource://gre/modules/TorStrings.sys.mjs";
    
    29 29
     
    
    ... ... @@ -40,6 +40,7 @@ const TorLauncherPrefs = Object.freeze({
    40 40
     const TorConnectPrefs = Object.freeze({
    
    41 41
       censorship_level: "torbrowser.debug.censorship_level",
    
    42 42
       allow_internet_test: "torbrowser.bootstrap.allow_internet_test",
    
    43
    +  log_level: "torbrowser.bootstrap.log_level",
    
    43 44
     });
    
    44 45
     
    
    45 46
     export const TorConnectState = Object.freeze({
    
    ... ... @@ -59,6 +60,17 @@ export const TorConnectState = Object.freeze({
    59 60
       Disabled: "Disabled",
    
    60 61
     });
    
    61 62
     
    
    63
    +XPCOMUtils.defineLazyGetter(
    
    64
    +  lazy,
    
    65
    +  "logger",
    
    66
    +  () =>
    
    67
    +    new lazy.ConsoleAPI({
    
    68
    +      maxLogLevel: "info",
    
    69
    +      maxLogLevelPref: TorConnectPrefs.log_level,
    
    70
    +      prefix: "TorConnect",
    
    71
    +    })
    
    72
    +);
    
    73
    +
    
    62 74
     /*
    
    63 75
                                  TorConnect State Transitions
    
    64 76
     
    
    ... ... @@ -194,12 +206,12 @@ class StateCallback {
    194 206
       }
    
    195 207
     
    
    196 208
       async begin(...args) {
    
    197
    -    console.log(`TorConnect: Entering ${this._state} state`);
    
    209
    +    lazy.logger.trace(`Entering ${this._state} state`);
    
    198 210
         this._init();
    
    199 211
         try {
    
    200 212
           // this Promise will block until this StateCallback has completed its work
    
    201 213
           await Promise.resolve(this._callback.call(this._context, ...args));
    
    202
    -      console.log(`TorConnect: Exited ${this._state} state`);
    
    214
    +      lazy.logger.info(`Exited ${this._state} state`);
    
    203 215
     
    
    204 216
           // handled state transition
    
    205 217
           Services.obs.notifyObservers(
    
    ... ... @@ -267,16 +279,14 @@ class InternetTest {
    267 279
         this.cancel();
    
    268 280
         this._pending = true;
    
    269 281
     
    
    270
    -    console.log("TorConnect: starting the Internet test");
    
    282
    +    lazy.logger.info("Starting the Internet test");
    
    271 283
         this._testAsync()
    
    272 284
           .then(status => {
    
    273 285
             this._pending = false;
    
    274 286
             this._status = status.successful
    
    275 287
               ? InternetStatus.Online
    
    276 288
               : InternetStatus.Offline;
    
    277
    -        console.log(
    
    278
    -          `TorConnect: performed Internet test, outcome ${this._status}`
    
    279
    -        );
    
    289
    +        lazy.logger.info(`Performed Internet test, outcome ${this._status}`);
    
    280 290
             this.onResult(this.status, status.date);
    
    281 291
           })
    
    282 292
           .catch(error => {
    
    ... ... @@ -305,7 +315,7 @@ class InternetTest {
    305 315
           await mrpc.init();
    
    306 316
           status = await mrpc.testInternetConnection();
    
    307 317
         } catch (err) {
    
    308
    -      console.error("Error while checking the Internet connection", err);
    
    318
    +      lazy.logger.error("Error while checking the Internet connection", err);
    
    309 319
           error = err;
    
    310 320
         } finally {
    
    311 321
           mrpc.uninit();
    
    ... ... @@ -523,8 +533,8 @@ export const TorConnect = (() => {
    523 533
                       // get "Building circuits: Establishing a Tor circuit failed".
    
    524 534
                       // TODO: Maybe move this logic deeper in the process to know
    
    525 535
                       // when to filter out such errors triggered by cancelling.
    
    526
    -                  console.log(
    
    527
    -                    `TorConnect: Post-cancel error => ${message}; ${details}`
    
    536
    +                  lazy.logger.warn(
    
    537
    +                    `Post-cancel error => ${message}; ${details}`
    
    528 538
                       );
    
    529 539
                       return;
    
    530 540
                     }
    
    ... ... @@ -628,7 +638,7 @@ export const TorConnect = (() => {
    628 638
                           "vanilla",
    
    629 639
                         ]);
    
    630 640
                       } catch (err) {
    
    631
    -                    console.error(
    
    641
    +                    lazy.logger.error(
    
    632 642
                           "We did not get localized settings, and default settings failed as well",
    
    633 643
                           err
    
    634 644
                         );
    
    ... ... @@ -651,10 +661,19 @@ export const TorConnect = (() => {
    651 661
                       }
    
    652 662
                     }
    
    653 663
     
    
    664
    +                const restoreOriginalSettings = async () => {
    
    665
    +                  try {
    
    666
    +                    await TorSettings.applySettings();
    
    667
    +                  } catch (e) {
    
    668
    +                    // We cannot do much if the original settings were bad or
    
    669
    +                    // if the connection closed, so just report it in the
    
    670
    +                    // console.
    
    671
    +                    lazy.logger.warn("Failed to restore original settings.", e);
    
    672
    +                  }
    
    673
    +                };
    
    674
    +
    
    654 675
                     // apply each of our settings and try to bootstrap with each
    
    655 676
                     try {
    
    656
    -                  this.originalSettings = TorSettings.getSettings();
    
    657
    -
    
    658 677
                       for (const [
    
    659 678
                         index,
    
    660 679
                         currentSetting,
    
    ... ... @@ -664,14 +683,32 @@ export const TorConnect = (() => {
    664 683
                           break;
    
    665 684
                         }
    
    666 685
     
    
    667
    -                    console.log(
    
    668
    -                      `TorConnect: Attempting Bootstrap with configuration ${
    
    669
    -                        index + 1
    
    670
    -                      }/${this.settings.length}`
    
    686
    +                    lazy.logger.info(
    
    687
    +                      `Attempting Bootstrap with configuration ${index + 1}/${
    
    688
    +                        this.settings.length
    
    689
    +                      }`
    
    671 690
                         );
    
    672 691
     
    
    673
    -                    TorSettings.setSettings(currentSetting);
    
    674
    -                    await TorSettings.applySettings();
    
    692
    +                    // Send the new settings directly to the provider. We will
    
    693
    +                    // save them only if the bootstrap succeeds.
    
    694
    +                    // FIXME: We should somehow signal TorSettings users that we
    
    695
    +                    // have set custom settings, and they should not apply
    
    696
    +                    // theirs until we are done with trying ours.
    
    697
    +                    // Otherwise, the new settings provided by the user while we
    
    698
    +                    // were bootstrapping could be the ones that cause the
    
    699
    +                    // bootstrap to succeed, but we overwrite them (unless we
    
    700
    +                    // backup the original settings, and then save our new
    
    701
    +                    // settings only if they have not changed).
    
    702
    +                    // Another idea (maybe easier to implement) is to disable
    
    703
    +                    // the settings UI while *any* bootstrap is going on.
    
    704
    +                    // This is also documented in tor-browser#41921.
    
    705
    +                    const provider = await lazy.TorProviderBuilder.build();
    
    706
    +                    // We need to merge with old settings, in case the user is
    
    707
    +                    // using a proxy or is behind a firewall.
    
    708
    +                    await provider.writeSettings({
    
    709
    +                      ...TorSettings.getSettings(),
    
    710
    +                      ...currentSetting,
    
    711
    +                    });
    
    675 712
     
    
    676 713
                         // build out our bootstrap request
    
    677 714
                         const tbr = new lazy.TorBootstrapRequest();
    
    ... ... @@ -679,8 +716,8 @@ export const TorConnect = (() => {
    679 716
                           TorConnect._updateBootstrapStatus(progress, status);
    
    680 717
                         };
    
    681 718
                         tbr.onbootstraperror = (message, details) => {
    
    682
    -                      console.log(
    
    683
    -                        `TorConnect: Auto-Bootstrap error => ${message}; ${details}`
    
    719
    +                      lazy.logger.error(
    
    720
    +                        `Auto-Bootstrap error => ${message}; ${details}`
    
    684 721
                           );
    
    685 722
                         };
    
    686 723
     
    
    ... ... @@ -688,6 +725,7 @@ export const TorConnect = (() => {
    688 725
                         this.on_transition = async nextState => {
    
    689 726
                           if (nextState === TorConnectState.Configuring) {
    
    690 727
                             await tbr.cancel();
    
    728
    +                        await restoreOriginalSettings();
    
    691 729
                           }
    
    692 730
                           resolve();
    
    693 731
                         };
    
    ... ... @@ -695,23 +733,20 @@ export const TorConnect = (() => {
    695 733
                         // begin bootstrap
    
    696 734
                         if (await tbr.bootstrap()) {
    
    697 735
                           // persist the current settings to preferences
    
    736
    +                      TorSettings.setSettings(currentSetting);
    
    698 737
                           TorSettings.saveToPrefs();
    
    738
    +                      await TorSettings.applySettings();
    
    699 739
                           TorConnect._changeState(TorConnectState.Bootstrapped);
    
    700 740
                           return;
    
    701 741
                         }
    
    702 742
                       }
    
    703 743
     
    
    704
    -                  // bootstrapped failed for all potential settings, so reset daemon to use original
    
    705
    -                  TorSettings.setSettings(this.originalSettings);
    
    706
    -                  // The original settings should be good, so we save them to
    
    707
    -                  // preferences before trying to apply them, as it might fail
    
    708
    -                  // if the actual problem is with the connection to the control
    
    709
    -                  // port.
    
    710
    -                  // FIXME: We should handle this case in a better way.
    
    711
    -                  TorSettings.saveToPrefs();
    
    712
    -                  await TorSettings.applySettings();
    
    713
    -
    
    714
    -                  // only explicitly change state here if something else has not transitioned us
    
    744
    +                  // Bootstrap failed for all potential settings, so restore the
    
    745
    +                  // original settings the provider.
    
    746
    +                  await restoreOriginalSettings();
    
    747
    +
    
    748
    +                  // Only explicitly change state here if something else has not
    
    749
    +                  // transitioned us.
    
    715 750
                       if (!this.transitioning) {
    
    716 751
                         throw_error(
    
    717 752
                           TorStrings.torConnect.autoBootstrappingFailed,
    
    ... ... @@ -720,18 +755,8 @@ export const TorConnect = (() => {
    720 755
                       }
    
    721 756
                       return;
    
    722 757
                     } catch (err) {
    
    723
    -                  // restore original settings in case of error
    
    724
    -                  try {
    
    725
    -                    TorSettings.setSettings(this.originalSettings);
    
    726
    -                    // As above
    
    727
    -                    TorSettings.saveToPrefs();
    
    728
    -                    await TorSettings.applySettings();
    
    729
    -                  } catch (errRestore) {
    
    730
    -                    console.log(
    
    731
    -                      `TorConnect: Failed to restore original settings => ${errRestore}`
    
    732
    -                    );
    
    733
    -                  }
    
    734
    -                  // throw to outer catch to transition us
    
    758
    +                  await restoreOriginalSettings();
    
    759
    +                  // throw to outer catch to transition us.
    
    735 760
                       throw err;
    
    736 761
                     }
    
    737 762
                   } catch (err) {
    
    ... ... @@ -748,8 +773,8 @@ export const TorConnect = (() => {
    748 773
                         true
    
    749 774
                       );
    
    750 775
                     } else {
    
    751
    -                  console.error(
    
    752
    -                    "TorConnect: Received AutoBootstrapping error after transitioning",
    
    776
    +                  lazy.logger.error(
    
    777
    +                    "Received AutoBootstrapping error after transitioning",
    
    753 778
                         err
    
    754 779
                       );
    
    755 780
                     }
    
    ... ... @@ -793,8 +818,8 @@ export const TorConnect = (() => {
    793 818
     
    
    794 819
                   TorConnect._errorMessage = errorMessage;
    
    795 820
                   TorConnect._errorDetails = errorDetails;
    
    796
    -              console.error(
    
    797
    -                `[TorConnect] Entering error state (${errorMessage}, ${errorDetails})`
    
    821
    +              lazy.logger.error(
    
    822
    +                `Entering error state (${errorMessage}, ${errorDetails})`
    
    798 823
                   );
    
    799 824
     
    
    800 825
                   Services.obs.notifyObservers(
    
    ... ... @@ -835,9 +860,7 @@ export const TorConnect = (() => {
    835 860
             );
    
    836 861
           }
    
    837 862
     
    
    838
    -      console.log(
    
    839
    -        `TorConnect: Try transitioning from ${prevState} to ${newState}`
    
    840
    -      );
    
    863
    +      lazy.logger.trace(`Try transitioning from ${prevState} to ${newState}`);
    
    841 864
     
    
    842 865
           // set our new state first so that state transitions can themselves trigger
    
    843 866
           // a state transition
    
    ... ... @@ -851,8 +874,8 @@ export const TorConnect = (() => {
    851 874
           this._bootstrapProgress = progress;
    
    852 875
           this._bootstrapStatus = status;
    
    853 876
     
    
    854
    -      console.log(
    
    855
    -        `TorConnect: Bootstrapping ${this._bootstrapProgress}% complete (${this._bootstrapStatus})`
    
    877
    +      lazy.logger.info(
    
    878
    +        `Bootstrapping ${this._bootstrapProgress}% complete (${this._bootstrapStatus})`
    
    856 879
           );
    
    857 880
           Services.obs.notifyObservers(
    
    858 881
             {
    
    ... ... @@ -866,7 +889,7 @@ export const TorConnect = (() => {
    866 889
     
    
    867 890
         // init should be called by TorStartupService
    
    868 891
         init() {
    
    869
    -      console.log("TorConnect: init()");
    
    892
    +      lazy.logger.debug("TorConnect.init()");
    
    870 893
           this._callback(TorConnectState.Initial).begin();
    
    871 894
     
    
    872 895
           if (!this.enabled) {
    
    ... ... @@ -875,9 +898,17 @@ export const TorConnect = (() => {
    875 898
           } else {
    
    876 899
             let observeTopic = addTopic => {
    
    877 900
               Services.obs.addObserver(this, addTopic);
    
    878
    -          console.log(`TorConnect: Observing topic '${addTopic}'`);
    
    901
    +          lazy.logger.debug(`Observing topic '${addTopic}'`);
    
    879 902
             };
    
    880 903
     
    
    904
    +        // Wait for TorSettings, as we will need it.
    
    905
    +        // We will wait for a TorProvider only after TorSettings is ready,
    
    906
    +        // because the TorProviderBuilder initialization might not have finished
    
    907
    +        // at this point, and TorSettings initialization is a prerequisite for
    
    908
    +        // having a provider.
    
    909
    +        // So, we prefer initializing TorConnect as soon as possible, so that
    
    910
    +        // the UI will be able to detect it is in the Initializing state and act
    
    911
    +        // consequently.
    
    881 912
             TorSettings.initializedPromise.then(() => this._settingsInitialized());
    
    882 913
     
    
    883 914
             // register the Tor topics we always care about
    
    ... ... @@ -887,7 +918,7 @@ export const TorConnect = (() => {
    887 918
         },
    
    888 919
     
    
    889 920
         async observe(subject, topic, data) {
    
    890
    -      console.log(`TorConnect: Observed ${topic}`);
    
    921
    +      lazy.logger.debug(`Observed ${topic}`);
    
    891 922
     
    
    892 923
           switch (topic) {
    
    893 924
             case TorTopics.LogHasWarnOrErr: {
    
    ... ... @@ -919,19 +950,25 @@ export const TorConnect = (() => {
    919 950
           }
    
    920 951
         },
    
    921 952
     
    
    922
    -    _settingsInitialized() {
    
    953
    +    async _settingsInitialized() {
    
    954
    +      // TODO: Handle failures here, instead of the prompt to restart the
    
    955
    +      // daemon when it exits (tor-browser#21053, tor-browser#41921).
    
    956
    +      await lazy.TorProviderBuilder.build();
    
    957
    +
    
    923 958
           // tor-browser#41907: This is only a workaround to avoid users being
    
    924 959
           // bounced back to the initial panel without any explanation.
    
    925 960
           // Longer term we should disable the clickable elements, or find a UX
    
    926 961
           // to prevent this from happening (e.g., allow buttons to be clicked,
    
    927 962
           // but show an intermediate starting state, or a message that tor is
    
    928 963
           // starting while the butons are disabled, etc...).
    
    964
    +      // See also tor-browser#41921.
    
    929 965
           if (this.state !== TorConnectState.Initial) {
    
    930
    -        console.warn(
    
    931
    -          "TorConnect: Seen the torsettings:ready after the state has already changed, ignoring the notification."
    
    966
    +        lazy.logger.warn(
    
    967
    +          "The TorProvider was built after the state had already changed."
    
    932 968
             );
    
    933 969
             return;
    
    934 970
           }
    
    971
    +      lazy.logger.debug("The TorProvider is ready, changing state.");
    
    935 972
           if (this.shouldQuickStart) {
    
    936 973
             // Quickstart
    
    937 974
             this._changeState(TorConnectState.Bootstrapping);
    
    ... ... @@ -1074,17 +1111,17 @@ export const TorConnect = (() => {
    1074 1111
             */
    
    1075 1112
     
    
    1076 1113
         beginBootstrap() {
    
    1077
    -      console.log("TorConnect: beginBootstrap()");
    
    1114
    +      lazy.logger.debug("TorConnect.beginBootstrap()");
    
    1078 1115
           this._changeState(TorConnectState.Bootstrapping);
    
    1079 1116
         },
    
    1080 1117
     
    
    1081 1118
         cancelBootstrap() {
    
    1082
    -      console.log("TorConnect: cancelBootstrap()");
    
    1119
    +      lazy.logger.debug("TorConnect.cancelBootstrap()");
    
    1083 1120
           this._changeState(TorConnectState.Configuring);
    
    1084 1121
         },
    
    1085 1122
     
    
    1086 1123
         beginAutoBootstrap(countryCode) {
    
    1087
    -      console.log("TorConnect: beginAutoBootstrap()");
    
    1124
    +      lazy.logger.debug("TorConnect.beginAutoBootstrap()");
    
    1088 1125
           this._changeState(TorConnectState.AutoBootstrapping, countryCode);
    
    1089 1126
         },
    
    1090 1127
     
    
    ... ... @@ -1154,7 +1191,10 @@ export const TorConnect = (() => {
    1154 1191
             await mrpc.init();
    
    1155 1192
             this._countryCodes = await mrpc.circumvention_countries();
    
    1156 1193
           } catch (err) {
    
    1157
    -        console.log("An error occurred while fetching country codes", err);
    
    1194
    +        lazy.logger.error(
    
    1195
    +          "An error occurred while fetching country codes",
    
    1196
    +          err
    
    1197
    +        );
    
    1158 1198
           } finally {
    
    1159 1199
             mrpc.uninit();
    
    1160 1200
           }
    
    ... ... @@ -1187,8 +1227,8 @@ export const TorConnect = (() => {
    1187 1227
             uriArray = uriVariant;
    
    1188 1228
           } else {
    
    1189 1229
             // about:tor as safe fallback
    
    1190
    -        console.error(
    
    1191
    -          `TorConnect: received unknown variant '${JSON.stringify(uriVariant)}'`
    
    1230
    +        lazy.logger.error(
    
    1231
    +          `Received unknown variant '${JSON.stringify(uriVariant)}'`
    
    1192 1232
             );
    
    1193 1233
             uriArray = ["about:tor"];
    
    1194 1234
           }
    
    ... ... @@ -1209,9 +1249,7 @@ export const TorConnect = (() => {
    1209 1249
         // which redirect after bootstrapping
    
    1210 1250
         getURIsToLoad(uriVariant) {
    
    1211 1251
           const uris = this.fixupURIs(uriVariant);
    
    1212
    -      console.log(
    
    1213
    -        `TorConnect: Will load after bootstrap => [${uris.join(", ")}]`
    
    1214
    -      );
    
    1252
    +      lazy.logger.debug(`Will load after bootstrap => [${uris.join(", ")}]`);
    
    1215 1253
           return uris.map(uri => this.getRedirectURL(uri));
    
    1216 1254
         },
    
    1217 1255
       };
    

  • toolkit/modules/TorSettings.sys.mjs
    ... ... @@ -6,10 +6,9 @@ const lazy = {};
    6 6
     
    
    7 7
     ChromeUtils.defineESModuleGetters(lazy, {
    
    8 8
       TorLauncherUtil: "resource://gre/modules/TorLauncherUtil.sys.mjs",
    
    9
    -  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    10
    -  TorProviderTopics: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    11 9
       Lox: "resource://gre/modules/Lox.sys.mjs",
    
    12 10
       TorParsers: "resource://gre/modules/TorParsers.sys.mjs",
    
    11
    +  TorProviderBuilder: "resource://gre/modules/TorProviderBuilder.sys.mjs",
    
    13 12
     });
    
    14 13
     
    
    15 14
     ChromeUtils.defineLazyGetter(lazy, "logger", () => {
    
    ... ... @@ -71,20 +70,6 @@ const TorSettingsPrefs = Object.freeze({
    71 70
       },
    
    72 71
     });
    
    73 72
     
    
    74
    -/* Config Keys used to configure tor daemon */
    
    75
    -const TorConfigKeys = Object.freeze({
    
    76
    -  useBridges: "UseBridges",
    
    77
    -  bridgeList: "Bridge",
    
    78
    -  socks4Proxy: "Socks4Proxy",
    
    79
    -  socks5Proxy: "Socks5Proxy",
    
    80
    -  socks5ProxyUsername: "Socks5ProxyUsername",
    
    81
    -  socks5ProxyPassword: "Socks5ProxyPassword",
    
    82
    -  httpsProxy: "HTTPSProxy",
    
    83
    -  httpsProxyAuthenticator: "HTTPSProxyAuthenticator",
    
    84
    -  reachableAddresses: "ReachableAddresses",
    
    85
    -  clientTransportPlugin: "ClientTransportPlugin",
    
    86
    -});
    
    87
    -
    
    88 73
     export const TorBridgeSource = Object.freeze({
    
    89 74
       Invalid: -1,
    
    90 75
       BuiltIn: 0,
    
    ... ... @@ -322,7 +307,7 @@ class TorSettingsImpl {
    322 307
               if (!val) {
    
    323 308
                 return;
    
    324 309
               }
    
    325
    -          const bridgeStrings = this.#getBuiltinBridges(val);
    
    310
    +          const bridgeStrings = this.getBuiltinBridges(val);
    
    326 311
               if (bridgeStrings.length) {
    
    327 312
                 this.bridges.bridge_strings = bridgeStrings;
    
    328 313
                 return;
    
    ... ... @@ -659,14 +644,17 @@ class TorSettingsImpl {
    659 644
        * @param {string} pt The pluggable transport to return the lines for
    
    660 645
        * @returns {string[]} The bridge lines in random order
    
    661 646
        */
    
    662
    -  #getBuiltinBridges(pt) {
    
    647
    +  getBuiltinBridges(pt) {
    
    648
    +    if (!this.#allowUninitialized) {
    
    649
    +      this.#checkIfInitialized();
    
    650
    +    }
    
    663 651
         // Shuffle so that Tor Browser users do not all try the built-in bridges in
    
    664 652
         // the same order.
    
    665 653
         return arrayShuffle(this.#builtinBridges[pt] ?? []);
    
    666 654
       }
    
    667 655
     
    
    668 656
       /**
    
    669
    -   * Load or init our settings, and register observers.
    
    657
    +   * Load or init our settings.
    
    670 658
        */
    
    671 659
       async init() {
    
    672 660
         if (this.#initialized) {
    
    ... ... @@ -677,6 +665,7 @@ class TorSettingsImpl {
    677 665
           await this.#initInternal();
    
    678 666
           this.#initialized = true;
    
    679 667
           this.#initComplete();
    
    668
    +      Services.obs.notifyObservers(null, TorSettingsTopics.Ready);
    
    680 669
         } catch (e) {
    
    681 670
           this.#initFailed(e);
    
    682 671
           throw e;
    
    ... ... @@ -698,45 +687,35 @@ class TorSettingsImpl {
    698 687
           lazy.logger.error("Could not load the built-in PT config.", e);
    
    699 688
         }
    
    700 689
     
    
    701
    -    // Initialize this before loading from prefs because we need Lox initialized before
    
    702
    -    // any calls to Lox.getBridges()
    
    690
    +    // Initialize this before loading from prefs because we need Lox initialized
    
    691
    +    // before any calls to Lox.getBridges().
    
    703 692
         try {
    
    704 693
           await lazy.Lox.init();
    
    705 694
         } catch (e) {
    
    706 695
           lazy.logger.error("Could not initialize Lox.", e.type);
    
    707 696
         }
    
    708 697
     
    
    709
    -    // TODO: We could use a shared promise, and wait for it to be fullfilled
    
    710
    -    // instead of Service.obs.
    
    711
    -    if (lazy.TorLauncherUtil.shouldStartAndOwnTor) {
    
    712
    -      // if the settings branch exists, load settings from prefs
    
    713
    -      if (Services.prefs.getBoolPref(TorSettingsPrefs.enabled, false)) {
    
    714
    -        // Do not want notifications for initially loaded prefs.
    
    715
    -        this.freezeNotifications();
    
    716
    -        try {
    
    717
    -          this.#allowUninitialized = true;
    
    718
    -          this.#loadFromPrefs();
    
    719
    -        } finally {
    
    720
    -          this.#allowUninitialized = false;
    
    721
    -          this.#notificationQueue.clear();
    
    722
    -          this.thawNotifications();
    
    723
    -        }
    
    724
    -      }
    
    698
    +    if (
    
    699
    +      lazy.TorLauncherUtil.shouldStartAndOwnTor &&
    
    700
    +      Services.prefs.getBoolPref(TorSettingsPrefs.enabled, false)
    
    701
    +    ) {
    
    702
    +      // Do not want notifications for initially loaded prefs.
    
    703
    +      this.freezeNotifications();
    
    725 704
           try {
    
    726
    -        const provider = await lazy.TorProviderBuilder.build();
    
    727
    -        if (provider.isRunning) {
    
    728
    -          this.#handleProcessReady();
    
    729
    -          // No need to add an observer to call this again.
    
    730
    -          return;
    
    731
    -        }
    
    732
    -      } catch {}
    
    733
    -
    
    734
    -      Services.obs.addObserver(this, lazy.TorProviderTopics.ProcessIsReady);
    
    705
    +        this.#allowUninitialized = true;
    
    706
    +        this.#loadFromPrefs();
    
    707
    +      } finally {
    
    708
    +        this.#allowUninitialized = false;
    
    709
    +        this.#notificationQueue.clear();
    
    710
    +        this.thawNotifications();
    
    711
    +      }
    
    735 712
         }
    
    713
    +
    
    714
    +    lazy.logger.info("Ready");
    
    736 715
       }
    
    737 716
     
    
    738 717
       /**
    
    739
    -   * Unload or uninit our settings, and unregister observers.
    
    718
    +   * Unload or uninit our settings.
    
    740 719
        */
    
    741 720
       async uninit() {
    
    742 721
         await lazy.Lox.uninit();
    
    ... ... @@ -764,34 +743,6 @@ class TorSettingsImpl {
    764 743
         return this.#initialized;
    
    765 744
       }
    
    766 745
     
    
    767
    -  /**
    
    768
    -   * Wait for relevant life-cycle events to apply saved settings.
    
    769
    -   */
    
    770
    -  async observe(subject, topic, data) {
    
    771
    -    lazy.logger.debug(`Observed ${topic}`);
    
    772
    -
    
    773
    -    switch (topic) {
    
    774
    -      case lazy.TorProviderTopics.ProcessIsReady:
    
    775
    -        Services.obs.removeObserver(
    
    776
    -          this,
    
    777
    -          lazy.TorProviderTopics.ProcessIsReady
    
    778
    -        );
    
    779
    -        await this.#handleProcessReady();
    
    780
    -        break;
    
    781
    -    }
    
    782
    -  }
    
    783
    -
    
    784
    -  /**
    
    785
    -   * Apply the settings once the tor provider is ready and notify any observer
    
    786
    -   * that the settings can be used.
    
    787
    -   */
    
    788
    -  async #handleProcessReady() {
    
    789
    -    // push down settings to tor
    
    790
    -    await this.#applySettings(true);
    
    791
    -    lazy.logger.info("Ready");
    
    792
    -    Services.obs.notifyObservers(null, TorSettingsTopics.Ready);
    
    793
    -  }
    
    794
    -
    
    795 746
       /**
    
    796 747
        * Load our settings from prefs.
    
    797 748
        */
    
    ... ... @@ -972,85 +923,14 @@ class TorSettingsImpl {
    972 923
     
    
    973 924
       /**
    
    974 925
        * Push our settings down to the tor provider.
    
    926
    +   *
    
    927
    +   * Even though this introduces a circular depdency, it makes the API nicer for
    
    928
    +   * frontend consumers.
    
    975 929
        */
    
    976 930
       async applySettings() {
    
    977 931
         this.#checkIfInitialized();
    
    978
    -    return this.#applySettings(false);
    
    979
    -  }
    
    980
    -
    
    981
    -  /**
    
    982
    -   * Internal implementation of applySettings that does not check if we are
    
    983
    -   * initialized.
    
    984
    -   */
    
    985
    -  async #applySettings(allowUninitialized) {
    
    986
    -    lazy.logger.debug("#applySettings()");
    
    987
    -
    
    988
    -    this.#cleanupSettings();
    
    989
    -
    
    990
    -    const settingsMap = new Map();
    
    991
    -
    
    992
    -    // #applySettings can be called only when #allowUninitialized is false
    
    993
    -    this.#allowUninitialized = allowUninitialized;
    
    994
    -
    
    995
    -    try {
    
    996
    -      /* Bridges */
    
    997
    -      const haveBridges =
    
    998
    -        this.bridges.enabled && !!this.bridges.bridge_strings.length;
    
    999
    -      settingsMap.set(TorConfigKeys.useBridges, haveBridges);
    
    1000
    -      if (haveBridges) {
    
    1001
    -        settingsMap.set(TorConfigKeys.bridgeList, this.bridges.bridge_strings);
    
    1002
    -      } else {
    
    1003
    -        settingsMap.set(TorConfigKeys.bridgeList, null);
    
    1004
    -      }
    
    1005
    -
    
    1006
    -      /* Proxy */
    
    1007
    -      settingsMap.set(TorConfigKeys.socks4Proxy, null);
    
    1008
    -      settingsMap.set(TorConfigKeys.socks5Proxy, null);
    
    1009
    -      settingsMap.set(TorConfigKeys.socks5ProxyUsername, null);
    
    1010
    -      settingsMap.set(TorConfigKeys.socks5ProxyPassword, null);
    
    1011
    -      settingsMap.set(TorConfigKeys.httpsProxy, null);
    
    1012
    -      settingsMap.set(TorConfigKeys.httpsProxyAuthenticator, null);
    
    1013
    -      if (this.proxy.enabled) {
    
    1014
    -        const address = this.proxy.address;
    
    1015
    -        const port = this.proxy.port;
    
    1016
    -        const username = this.proxy.username;
    
    1017
    -        const password = this.proxy.password;
    
    1018
    -
    
    1019
    -        switch (this.proxy.type) {
    
    1020
    -          case TorProxyType.Socks4:
    
    1021
    -            settingsMap.set(TorConfigKeys.socks4Proxy, `${address}:${port}`);
    
    1022
    -            break;
    
    1023
    -          case TorProxyType.Socks5:
    
    1024
    -            settingsMap.set(TorConfigKeys.socks5Proxy, `${address}:${port}`);
    
    1025
    -            settingsMap.set(TorConfigKeys.socks5ProxyUsername, username);
    
    1026
    -            settingsMap.set(TorConfigKeys.socks5ProxyPassword, password);
    
    1027
    -            break;
    
    1028
    -          case TorProxyType.HTTPS:
    
    1029
    -            settingsMap.set(TorConfigKeys.httpsProxy, `${address}:${port}`);
    
    1030
    -            settingsMap.set(
    
    1031
    -              TorConfigKeys.httpsProxyAuthenticator,
    
    1032
    -              `${username}:${password}`
    
    1033
    -            );
    
    1034
    -            break;
    
    1035
    -        }
    
    1036
    -      }
    
    1037
    -
    
    1038
    -      /* Firewall */
    
    1039
    -      if (this.firewall.enabled) {
    
    1040
    -        const reachableAddresses = this.firewall.allowed_ports
    
    1041
    -          .map(port => `*:${port}`)
    
    1042
    -          .join(",");
    
    1043
    -        settingsMap.set(TorConfigKeys.reachableAddresses, reachableAddresses);
    
    1044
    -      } else {
    
    1045
    -        settingsMap.set(TorConfigKeys.reachableAddresses, null);
    
    1046
    -      }
    
    1047
    -    } finally {
    
    1048
    -      this.#allowUninitialized = false;
    
    1049
    -    }
    
    1050
    -
    
    1051
    -    /* Push to Tor */
    
    1052 932
         const provider = await lazy.TorProviderBuilder.build();
    
    1053
    -    await provider.writeSettings(settingsMap);
    
    933
    +    await provider.writeSettings(this.getSettings());
    
    1054 934
       }
    
    1055 935
     
    
    1056 936
       /**