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

Commits:

7 changed files:

Changes:

  • browser/components/torpreferences/content/connectionPane.js
    ... ... @@ -96,33 +96,6 @@ const Lox = {
    96 96
     };
    
    97 97
     */
    
    98 98
     
    
    99
    -/**
    
    100
    - * Make changes to TorSettings and save them.
    
    101
    - *
    
    102
    - * Bulk changes will be frozen together.
    
    103
    - *
    
    104
    - * @param {Function} changes - Method to apply changes to TorSettings.
    
    105
    - */
    
    106
    -async function setTorSettings(changes) {
    
    107
    -  if (!TorSettings.initialized) {
    
    108
    -    log.warning("Ignoring changes to uninitialized TorSettings");
    
    109
    -    return;
    
    110
    -  }
    
    111
    -  TorSettings.freezeNotifications();
    
    112
    -  try {
    
    113
    -    changes();
    
    114
    -    // This will trigger TorSettings.#cleanupSettings()
    
    115
    -    TorSettings.saveToPrefs();
    
    116
    -    try {
    
    117
    -      await TorSettings.applySettings();
    
    118
    -    } catch (e) {
    
    119
    -      console.error("Failed to apply Tor settings", e);
    
    120
    -    }
    
    121
    -  } finally {
    
    122
    -    TorSettings.thawNotifications();
    
    123
    -  }
    
    124
    -}
    
    125
    -
    
    126 99
     /**
    
    127 100
      * Get the ID/fingerprint of the bridge used in the most recent Tor circuit.
    
    128 101
      *
    
    ... ... @@ -757,6 +730,7 @@ const gBridgeGrid = {
    757 730
           });
    
    758 731
         removeItem.addEventListener("click", () => {
    
    759 732
           const bridgeLine = row.bridgeLine;
    
    733
    +      const source = TorSettings.bridges.source;
    
    760 734
           const strings = TorSettings.bridges.bridge_strings;
    
    761 735
           const index = strings.indexOf(bridgeLine);
    
    762 736
           if (index === -1) {
    
    ... ... @@ -764,8 +738,8 @@ const gBridgeGrid = {
    764 738
           }
    
    765 739
           strings.splice(index, 1);
    
    766 740
     
    
    767
    -      setTorSettings(() => {
    
    768
    -        TorSettings.bridges.bridge_strings = strings;
    
    741
    +      TorSettings.changeSettings({
    
    742
    +        bridges: { source, bridge_strings: strings },
    
    769 743
           });
    
    770 744
         });
    
    771 745
       },
    
    ... ... @@ -1829,8 +1803,8 @@ const gBridgeSettings = {
    1829 1803
           if (!this._haveBridges) {
    
    1830 1804
             return;
    
    1831 1805
           }
    
    1832
    -      setTorSettings(() => {
    
    1833
    -        TorSettings.bridges.enabled = this._toggleButton.pressed;
    
    1806
    +      TorSettings.changeSettings({
    
    1807
    +        bridges: { enabled: this._toggleButton.pressed },
    
    1834 1808
           });
    
    1835 1809
         });
    
    1836 1810
     
    
    ... ... @@ -2215,10 +2189,10 @@ const gBridgeSettings = {
    2215 2189
               return;
    
    2216 2190
             }
    
    2217 2191
     
    
    2218
    -        setTorSettings(() => {
    
    2192
    +        TorSettings.changeSettings({
    
    2219 2193
               // This should always have the side effect of disabling bridges as
    
    2220 2194
               // well.
    
    2221
    -          TorSettings.bridges.source = TorBridgeSource.Invalid;
    
    2195
    +          bridges: { source: TorBridgeSource.Invalid },
    
    2222 2196
             });
    
    2223 2197
           });
    
    2224 2198
     
    
    ... ... @@ -2319,10 +2293,12 @@ const gBridgeSettings = {
    2319 2293
             if (!result.type) {
    
    2320 2294
               return null;
    
    2321 2295
             }
    
    2322
    -        return setTorSettings(() => {
    
    2323
    -          TorSettings.bridges.enabled = true;
    
    2324
    -          TorSettings.bridges.source = TorBridgeSource.BuiltIn;
    
    2325
    -          TorSettings.bridges.builtin_type = result.type;
    
    2296
    +        return TorSettings.changeSettings({
    
    2297
    +          bridges: {
    
    2298
    +            enabled: true,
    
    2299
    +            source: TorBridgeSource.BuiltIn,
    
    2300
    +            builtin_type: result.type,
    
    2301
    +          },
    
    2326 2302
             });
    
    2327 2303
           }
    
    2328 2304
         );
    
    ... ... @@ -2339,10 +2315,12 @@ const gBridgeSettings = {
    2339 2315
             if (!result.bridges?.length) {
    
    2340 2316
               return null;
    
    2341 2317
             }
    
    2342
    -        return setTorSettings(() => {
    
    2343
    -          TorSettings.bridges.enabled = true;
    
    2344
    -          TorSettings.bridges.source = TorBridgeSource.BridgeDB;
    
    2345
    -          TorSettings.bridges.bridge_strings = result.bridges.join("\n");
    
    2318
    +        return TorSettings.changeSettings({
    
    2319
    +          bridges: {
    
    2320
    +            enabled: true,
    
    2321
    +            source: TorBridgeSource.BridgeDB,
    
    2322
    +            bridge_strings: result.bridges.join("\n"),
    
    2323
    +          },
    
    2346 2324
             });
    
    2347 2325
           }
    
    2348 2326
         );
    
    ... ... @@ -2363,16 +2341,15 @@ const gBridgeSettings = {
    2363 2341
             if (!loxId && !result.addresses?.length) {
    
    2364 2342
               return null;
    
    2365 2343
             }
    
    2366
    -        return setTorSettings(() => {
    
    2367
    -          TorSettings.bridges.enabled = true;
    
    2368
    -          if (loxId) {
    
    2369
    -            TorSettings.bridges.source = TorBridgeSource.Lox;
    
    2370
    -            TorSettings.bridges.lox_id = loxId;
    
    2371
    -          } else {
    
    2372
    -            TorSettings.bridges.source = TorBridgeSource.UserProvided;
    
    2373
    -            TorSettings.bridges.bridge_strings = result.addresses;
    
    2374
    -          }
    
    2375
    -        });
    
    2344
    +        const bridges = { enabled: true };
    
    2345
    +        if (loxId) {
    
    2346
    +          bridges.source = TorBridgeSource.Lox;
    
    2347
    +          bridges.lox_id = loxId;
    
    2348
    +        } else {
    
    2349
    +          bridges.source = TorBridgeSource.UserProvided;
    
    2350
    +          bridges.bridge_strings = result.addresses;
    
    2351
    +        }
    
    2352
    +        return TorSettings.changeSettings({ bridges });
    
    2376 2353
           }
    
    2377 2354
         );
    
    2378 2355
       },
    
    ... ... @@ -2586,9 +2563,9 @@ const gConnectionPane = (function () {
    2586 2563
             "torPreferences-quickstart-toggle"
    
    2587 2564
           );
    
    2588 2565
           this._enableQuickstartCheckbox.addEventListener("command", () => {
    
    2589
    -        const checked = this._enableQuickstartCheckbox.checked;
    
    2590
    -        TorSettings.quickstart.enabled = checked;
    
    2591
    -        TorSettings.saveToPrefs().applySettings();
    
    2566
    +        TorSettings.changeSettings({
    
    2567
    +          quickstart: { enabled: this._enableQuickstartCheckbox.checked },
    
    2568
    +        });
    
    2592 2569
           });
    
    2593 2570
           this._enableQuickstartCheckbox.checked = TorSettings.quickstart.enabled;
    
    2594 2571
           Services.obs.addObserver(this, TorSettingsTopics.SettingsChanged);
    

  • browser/components/torpreferences/content/connectionSettingsDialog.js
    ... ... @@ -270,33 +270,34 @@ const gConnectionSettingsDialog = {
    270 270
         const port = this._proxyPortTextbox.value;
    
    271 271
         const username = this._proxyUsernameTextbox.value;
    
    272 272
         const password = this._proxyPasswordTextbox.value;
    
    273
    +    const settings = { proxy: {}, firewall: {} };
    
    273 274
         switch (type) {
    
    274 275
           case TorProxyType.Invalid:
    
    275
    -        TorSettings.proxy.enabled = false;
    
    276
    +        settings.proxy.enabled = false;
    
    276 277
             break;
    
    277 278
           case TorProxyType.Socks4:
    
    278
    -        TorSettings.proxy.enabled = true;
    
    279
    -        TorSettings.proxy.type = type;
    
    280
    -        TorSettings.proxy.address = address;
    
    281
    -        TorSettings.proxy.port = port;
    
    282
    -        TorSettings.proxy.username = "";
    
    283
    -        TorSettings.proxy.password = "";
    
    279
    +        settings.proxy.enabled = true;
    
    280
    +        settings.proxy.type = type;
    
    281
    +        settings.proxy.address = address;
    
    282
    +        settings.proxy.port = port;
    
    283
    +        settings.proxy.username = "";
    
    284
    +        settings.proxy.password = "";
    
    284 285
             break;
    
    285 286
           case TorProxyType.Socks5:
    
    286
    -        TorSettings.proxy.enabled = true;
    
    287
    -        TorSettings.proxy.type = type;
    
    288
    -        TorSettings.proxy.address = address;
    
    289
    -        TorSettings.proxy.port = port;
    
    290
    -        TorSettings.proxy.username = username;
    
    291
    -        TorSettings.proxy.password = password;
    
    287
    +        settings.proxy.enabled = true;
    
    288
    +        settings.proxy.type = type;
    
    289
    +        settings.proxy.address = address;
    
    290
    +        settings.proxy.port = port;
    
    291
    +        settings.proxy.username = username;
    
    292
    +        settings.proxy.password = password;
    
    292 293
             break;
    
    293 294
           case TorProxyType.HTTPS:
    
    294
    -        TorSettings.proxy.enabled = true;
    
    295
    -        TorSettings.proxy.type = type;
    
    296
    -        TorSettings.proxy.address = address;
    
    297
    -        TorSettings.proxy.port = port;
    
    298
    -        TorSettings.proxy.username = username;
    
    299
    -        TorSettings.proxy.password = password;
    
    295
    +        settings.proxy.enabled = true;
    
    296
    +        settings.proxy.type = type;
    
    297
    +        settings.proxy.address = address;
    
    298
    +        settings.proxy.port = port;
    
    299
    +        settings.proxy.username = username;
    
    300
    +        settings.proxy.password = password;
    
    300 301
             break;
    
    301 302
         }
    
    302 303
     
    
    ... ... @@ -304,16 +305,15 @@ const gConnectionSettingsDialog = {
    304 305
           ? this._allowedPortsTextbox.value
    
    305 306
           : "";
    
    306 307
         if (portListString) {
    
    307
    -      TorSettings.firewall.enabled = true;
    
    308
    -      TorSettings.firewall.allowed_ports = portListString;
    
    308
    +      settings.firewall.enabled = true;
    
    309
    +      settings.firewall.allowed_ports = portListString;
    
    309 310
         } else {
    
    310
    -      TorSettings.firewall.enabled = false;
    
    311
    +      settings.firewall.enabled = false;
    
    311 312
         }
    
    312 313
     
    
    313
    -    TorSettings.saveToPrefs();
    
    314 314
         // FIXME: What if this fails? Should we prevent the dialog to close and show
    
    315 315
         // an error?
    
    316
    -    TorSettings.applySettings();
    
    316
    +    TorSettings.changeSettings(settings);
    
    317 317
       },
    
    318 318
     };
    
    319 319
     
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
    ... ... @@ -80,7 +80,7 @@ class TorControllerGV(
    80 80
             set(value) {
    
    81 81
                 getTorSettings()?.let {
    
    82 82
                     it.quickstart = value
    
    83
    -                getTorIntegration().setSettings(it, true, true)
    
    83
    +                getTorIntegration().setSettings(it)
    
    84 84
                 }
    
    85 85
             }
    
    86 86
     
    
    ... ... @@ -110,7 +110,7 @@ class TorControllerGV(
    110 110
                 getTorSettings()?.let {
    
    111 111
                     if (!value || it.bridgesSource != BridgeSource.Invalid) {
    
    112 112
                         it.bridgesEnabled = value
    
    113
    -                    getTorIntegration().setSettings(it, true, true)
    
    113
    +                    getTorIntegration().setSettings(it)
    
    114 114
                     }
    
    115 115
                 }
    
    116 116
             }
    
    ... ... @@ -150,7 +150,7 @@ class TorControllerGV(
    150 150
                         }
    
    151 151
                         it.bridgesBuiltinType = bbt
    
    152 152
                     }
    
    153
    -                getTorIntegration().setSettings(it, true, true)
    
    153
    +                getTorIntegration().setSettings(it)
    
    154 154
                 }
    
    155 155
             }
    
    156 156
     
    
    ... ... @@ -175,7 +175,7 @@ class TorControllerGV(
    175 175
                     val  userProvidedLines: Array<String> = value?.split("\n")?.filter { it.length > 4 }?.toTypedArray() ?: arrayOf<String>()
    
    176 176
                     it.bridgesSource = BridgeSource.UserProvided
    
    177 177
                     it.bridgeBridgeStrings = userProvidedLines
    
    178
    -                getTorIntegration().setSettings(it, true, true)
    
    178
    +                getTorIntegration().setSettings(it)
    
    179 179
                 }
    
    180 180
             }
    
    181 181
     
    

  • mobile/android/geckoview/src/main/java/org/mozilla/geckoview/TorIntegrationAndroid.java
    ... ... @@ -48,8 +48,6 @@ public class TorIntegrationAndroid implements BundleEventListener {
    48 48
       // Events we emit
    
    49 49
       private static final String EVENT_SETTINGS_GET = "GeckoView:Tor:SettingsGet";
    
    50 50
       private static final String EVENT_SETTINGS_SET = "GeckoView:Tor:SettingsSet";
    
    51
    -  private static final String EVENT_SETTINGS_APPLY = "GeckoView:Tor:SettingsApply";
    
    52
    -  private static final String EVENT_SETTINGS_SAVE = "GeckoView:Tor:SettingsSave";
    
    53 51
       private static final String EVENT_BOOTSTRAP_BEGIN = "GeckoView:Tor:BootstrapBegin";
    
    54 52
       private static final String EVENT_BOOTSTRAP_BEGIN_AUTO = "GeckoView:Tor:BootstrapBeginAuto";
    
    55 53
       private static final String EVENT_BOOTSTRAP_CANCEL = "GeckoView:Tor:BootstrapCancel";
    
    ... ... @@ -194,7 +192,7 @@ public class TorIntegrationAndroid implements BundleEventListener {
    194 192
         protected void onPostExecute(TorSettings torSettings) {
    
    195 193
           mSettings = torSettings;
    
    196 194
           if (TorLegacyAndroidSettings.unmigrated()) {
    
    197
    -        setSettings(mSettings, true, true);
    
    195
    +        setSettings(mSettings);
    
    198 196
             TorLegacyAndroidSettings.setMigrated();
    
    199 197
           }
    
    200 198
         }
    
    ... ... @@ -657,10 +655,10 @@ public class TorIntegrationAndroid implements BundleEventListener {
    657 655
         return mSettings;
    
    658 656
       }
    
    659 657
     
    
    660
    -  public void setSettings(final TorSettings settings, boolean save, boolean apply) {
    
    658
    +  public void setSettings(final TorSettings settings) {
    
    661 659
         mSettings = settings;
    
    662 660
     
    
    663
    -    emitSetSettings(settings, save, apply)
    
    661
    +    emitSetSettings(settings)
    
    664 662
             .then(
    
    665 663
                 new GeckoResult.OnValueListener<Void, Void>() {
    
    666 664
                   public GeckoResult<Void> onValue(Void v) {
    
    ... ... @@ -677,22 +675,12 @@ public class TorIntegrationAndroid implements BundleEventListener {
    677 675
       }
    
    678 676
     
    
    679 677
       private @NonNull GeckoResult<Void> emitSetSettings(
    
    680
    -      final TorSettings settings, boolean save, boolean apply) {
    
    681
    -    GeckoBundle bundle = new GeckoBundle(3);
    
    682
    -    bundle.putBoolean("save", save);
    
    683
    -    bundle.putBoolean("apply", apply);
    
    678
    +      final TorSettings settings) {
    
    679
    +    GeckoBundle bundle = new GeckoBundle(1);
    
    684 680
         bundle.putBundle("settings", settings.asGeckoBundle());
    
    685 681
         return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SET, bundle);
    
    686 682
       }
    
    687 683
     
    
    688
    -  public @NonNull GeckoResult<Void> applySettings() {
    
    689
    -    return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_APPLY);
    
    690
    -  }
    
    691
    -
    
    692
    -  public @NonNull GeckoResult<Void> saveSettings() {
    
    693
    -    return EventDispatcher.getInstance().queryVoid(EVENT_SETTINGS_SAVE);
    
    694
    -  }
    
    695
    -
    
    696 684
       public @NonNull GeckoResult<Void> beginBootstrap() {
    
    697 685
         return EventDispatcher.getInstance().queryVoid(EVENT_BOOTSTRAP_BEGIN);
    
    698 686
       }
    

  • toolkit/components/torconnect/TorConnectParent.sys.mjs
    ... ... @@ -104,8 +104,7 @@ export class TorConnectParent extends JSWindowActorParent {
    104 104
             // If there are multiple home pages, just load the first one.
    
    105 105
             return Promise.resolve(TorConnect.fixupURIs(lazy.HomePage.get())[0]);
    
    106 106
           case "torconnect:set-quickstart":
    
    107
    -        TorSettings.quickstart.enabled = message.data;
    
    108
    -        TorSettings.saveToPrefs().applySettings();
    
    107
    +        TorSettings.changeSettings({ quickstart: { enabled: message.data } });
    
    109 108
             break;
    
    110 109
           case "torconnect:open-tor-preferences":
    
    111 110
             this.browsingContext.top.embedderElement.ownerGlobal.openPreferences(
    

  • toolkit/modules/TorAndroidIntegration.sys.mjs
    ... ... @@ -36,8 +36,6 @@ const ListenedEvents = Object.freeze({
    36 36
       settingsGet: "GeckoView:Tor:SettingsGet",
    
    37 37
       // The data is passed directly to TorSettings.
    
    38 38
       settingsSet: "GeckoView:Tor:SettingsSet",
    
    39
    -  settingsApply: "GeckoView:Tor:SettingsApply",
    
    40
    -  settingsSave: "GeckoView:Tor:SettingsSave",
    
    41 39
       bootstrapBegin: "GeckoView:Tor:BootstrapBegin",
    
    42 40
       // Optionally takes a countryCode, as data.countryCode.
    
    43 41
       bootstrapBeginAuto: "GeckoView:Tor:BootstrapBeginAuto",
    
    ... ... @@ -145,20 +143,10 @@ class TorAndroidIntegrationImpl {
    145 143
               callback?.onSuccess(lazy.TorSettings.getSettings());
    
    146 144
               return;
    
    147 145
             case ListenedEvents.settingsSet:
    
    148
    -          // This does not throw, so we do not have any way to report the error!
    
    149
    -          lazy.TorSettings.setSettings(data.settings);
    
    150
    -          if (data.save) {
    
    151
    -            lazy.TorSettings.saveToPrefs();
    
    152
    -          }
    
    153
    -          if (data.apply) {
    
    154
    -            await lazy.TorSettings.applySettings();
    
    155
    -          }
    
    156
    -          break;
    
    157
    -        case ListenedEvents.settingsApply:
    
    158
    -          await lazy.TorSettings.applySettings();
    
    159
    -          break;
    
    160
    -        case ListenedEvents.settingsSave:
    
    161
    -          await lazy.TorSettings.saveToPrefs();
    
    146
    +          // TODO: Handle setting throw? This can throw if data.settings is
    
    147
    +          // incorrectly formatted, but more like it can throw when the settings
    
    148
    +          // fail to be passed onto the TorProvider. tor-browser#43405.
    
    149
    +          await lazy.TorSettings.changeSettings(data.settings);
    
    162 150
               break;
    
    163 151
             case ListenedEvents.bootstrapBegin:
    
    164 152
               lazy.TorConnect.beginBootstrapping();
    

  • toolkit/modules/TorSettings.sys.mjs
    ... ... @@ -422,7 +422,7 @@ class TorSettingsImpl {
    422 422
        * not contradict each other.
    
    423 423
        */
    
    424 424
       #cleanupSettings() {
    
    425
    -    this.freezeNotifications();
    
    425
    +    this.#freezeNotifications();
    
    426 426
         try {
    
    427 427
           if (this.bridges.source === TorBridgeSource.Invalid) {
    
    428 428
             this.bridges.enabled = false;
    
    ... ... @@ -449,7 +449,7 @@ class TorSettingsImpl {
    449 449
             this.firewall.allowed_ports = [];
    
    450 450
           }
    
    451 451
         } finally {
    
    452
    -      this.thawNotifications();
    
    452
    +      this.#thawNotifications();
    
    453 453
         }
    
    454 454
       }
    
    455 455
     
    
    ... ... @@ -488,7 +488,7 @@ class TorSettingsImpl {
    488 488
        * changes you make with a `try` block and call thawNotifications in the
    
    489 489
        * `finally` block.
    
    490 490
        */
    
    491
    -  freezeNotifications() {
    
    491
    +  #freezeNotifications() {
    
    492 492
         this.#freezeNotificationsCount++;
    
    493 493
       }
    
    494 494
       /**
    
    ... ... @@ -497,7 +497,7 @@ class TorSettingsImpl {
    497 497
        * Note, if some other method has also frozen the notifications, this will
    
    498 498
        * only release them once it has also called this method.
    
    499 499
        */
    
    500
    -  thawNotifications() {
    
    500
    +  #thawNotifications() {
    
    501 501
         this.#freezeNotificationsCount--;
    
    502 502
         this.#tryNotification();
    
    503 503
       }
    
    ... ... @@ -571,7 +571,7 @@ class TorSettingsImpl {
    571 571
                     this.#checkIfInitialized();
    
    572 572
                   }
    
    573 573
                   const prevVal = this.#settings[groupname][name];
    
    574
    -              this.freezeNotifications();
    
    574
    +              this.#freezeNotifications();
    
    575 575
                   try {
    
    576 576
                     if (transform) {
    
    577 577
                       val = transform(val, addError);
    
    ... ... @@ -589,7 +589,7 @@ class TorSettingsImpl {
    589 589
                   } catch (e) {
    
    590 590
                     addError(e.message);
    
    591 591
                   } finally {
    
    592
    -                this.thawNotifications();
    
    592
    +                this.#thawNotifications();
    
    593 593
                   }
    
    594 594
                 },
    
    595 595
           });
    
    ... ... @@ -717,7 +717,7 @@ class TorSettingsImpl {
    717 717
           Services.prefs.getBoolPref(TorSettingsPrefs.enabled, false)
    
    718 718
         ) {
    
    719 719
           // Do not want notifications for initially loaded prefs.
    
    720
    -      this.freezeNotifications();
    
    720
    +      this.#freezeNotifications();
    
    721 721
           try {
    
    722 722
             this.#allowUninitialized = true;
    
    723 723
             this.#loadFromPrefs();
    
    ... ... @@ -726,7 +726,7 @@ class TorSettingsImpl {
    726 726
           } finally {
    
    727 727
             this.#allowUninitialized = false;
    
    728 728
             this.#notificationQueue.clear();
    
    729
    -        this.thawNotifications();
    
    729
    +        this.#thawNotifications();
    
    730 730
           }
    
    731 731
         }
    
    732 732
     
    
    ... ... @@ -755,7 +755,7 @@ class TorSettingsImpl {
    755 755
               // source. But we do pass on the changes to TorProvider.
    
    756 756
               // FIXME: This can compete with TorConnect to reach TorProvider.
    
    757 757
               // tor-browser#42316
    
    758
    -          this.applySettings();
    
    758
    +          this.#applySettings();
    
    759 759
             }
    
    760 760
             break;
    
    761 761
         }
    
    ... ... @@ -876,7 +876,7 @@ class TorSettingsImpl {
    876 876
       /**
    
    877 877
        * Save our settings to prefs.
    
    878 878
        */
    
    879
    -  saveToPrefs() {
    
    879
    +  #saveToPrefs() {
    
    880 880
         lazy.logger.debug("saveToPrefs()");
    
    881 881
     
    
    882 882
         this.#checkIfInitialized();
    
    ... ... @@ -968,8 +968,6 @@ class TorSettingsImpl {
    968 968
     
    
    969 969
         // all tor settings now stored in prefs :)
    
    970 970
         Services.prefs.setBoolPref(TorSettingsPrefs.enabled, true);
    
    971
    -
    
    972
    -    return this;
    
    973 971
       }
    
    974 972
     
    
    975 973
       /**
    
    ... ... @@ -978,23 +976,28 @@ class TorSettingsImpl {
    978 976
        * Even though this introduces a circular depdency, it makes the API nicer for
    
    979 977
        * frontend consumers.
    
    980 978
        */
    
    981
    -  async applySettings() {
    
    979
    +  async #applySettings() {
    
    982 980
         this.#checkIfInitialized();
    
    983 981
         const provider = await lazy.TorProviderBuilder.build();
    
    984 982
         await provider.writeSettings();
    
    985 983
       }
    
    986 984
     
    
    987 985
       /**
    
    988
    -   * Set blocks of settings at once from an object.
    
    986
    +   * Change the Tor settings in use.
    
    987
    +   *
    
    988
    +   * It is possible to set all settings, or only some sections:
    
    989 989
        *
    
    990
    -   * It is possible to set all settings, or only some sections (e.g., only
    
    991
    -   * bridges), but if a key is present, its settings must make sense (e.g., if
    
    992
    -   * bridges are enabled, a valid source must be provided).
    
    990
    +   * + quickstart.enabled can be set individually.
    
    991
    +   * + bridges.enabled can be set individually.
    
    992
    +   * + bridges.source can be set with a corresponding bridge specification for
    
    993
    +   *   the source (bridge_strings, lox_id, builtin_type).
    
    994
    +   * + proxy settings can be set as a group.
    
    995
    +   * + firewall settings can be set a group.
    
    993 996
        *
    
    994
    -   * @param {object} settings The settings object to set
    
    997
    +   * @param {object} settings - The settings object to set.
    
    995 998
        */
    
    996
    -  setSettings(settings) {
    
    997
    -    lazy.logger.debug("setSettings()");
    
    999
    +  async changeSettings(settings) {
    
    1000
    +    lazy.logger.debug("changeSettings()", settings);
    
    998 1001
         this.#checkIfInitialized();
    
    999 1002
     
    
    1000 1003
         const backup = this.getSettings();
    
    ... ... @@ -1003,38 +1006,39 @@ class TorSettingsImpl {
    1003 1006
         this.#settingErrors = [];
    
    1004 1007
     
    
    1005 1008
         // Hold off on lots of notifications until all settings are changed.
    
    1006
    -    this.freezeNotifications();
    
    1009
    +    this.#freezeNotifications();
    
    1007 1010
         try {
    
    1008
    -      if ("quickstart" in settings) {
    
    1011
    +      if ("quickstart" in settings && "enabled" in settings.quickstart) {
    
    1009 1012
             this.quickstart.enabled = !!settings.quickstart.enabled;
    
    1010 1013
           }
    
    1011 1014
     
    
    1012 1015
           if ("bridges" in settings) {
    
    1013
    -        this.bridges.enabled = !!settings.bridges.enabled;
    
    1014
    -        // Currently, disabling bridges in the UI does not remove the lines,
    
    1015
    -        // because we call only the `enabled` setter.
    
    1016
    -        // So, if the bridge source is undefined but bridges are disabled,
    
    1017
    -        // do not force Invalid. Instead, keep the current source.
    
    1018
    -        if (this.bridges.enabled || settings.bridges.source !== undefined) {
    
    1019
    -          this.bridges.source = settings.bridges.source;
    
    1016
    +        if ("enabled" in settings.bridges) {
    
    1017
    +          this.bridges.enabled = !!settings.bridges.enabled;
    
    1020 1018
             }
    
    1021
    -        switch (settings.bridges.source) {
    
    1022
    -          case TorBridgeSource.BridgeDB:
    
    1023
    -          case TorBridgeSource.UserProvided:
    
    1024
    -            this.bridges.bridge_strings = settings.bridges.bridge_strings;
    
    1025
    -            break;
    
    1026
    -          case TorBridgeSource.BuiltIn:
    
    1027
    -            this.bridges.builtin_type = settings.bridges.builtin_type;
    
    1028
    -            break;
    
    1029
    -          case TorBridgeSource.Lox:
    
    1030
    -            this.bridges.lox_id = settings.bridges.lox_id;
    
    1031
    -            break;
    
    1032
    -          case TorBridgeSource.Invalid:
    
    1033
    -            break;
    
    1019
    +        if ("source" in settings.bridges) {
    
    1020
    +          this.bridges.source = settings.bridges.source;
    
    1021
    +          switch (settings.bridges.source) {
    
    1022
    +            case TorBridgeSource.BridgeDB:
    
    1023
    +            case TorBridgeSource.UserProvided:
    
    1024
    +              this.bridges.bridge_strings = settings.bridges.bridge_strings;
    
    1025
    +              break;
    
    1026
    +            case TorBridgeSource.BuiltIn:
    
    1027
    +              this.bridges.builtin_type = settings.bridges.builtin_type;
    
    1028
    +              break;
    
    1029
    +            case TorBridgeSource.Lox:
    
    1030
    +              this.bridges.lox_id = settings.bridges.lox_id;
    
    1031
    +              break;
    
    1032
    +            case TorBridgeSource.Invalid:
    
    1033
    +              break;
    
    1034
    +            case undefined:
    
    1035
    +              break;
    
    1036
    +          }
    
    1034 1037
             }
    
    1035 1038
           }
    
    1036 1039
     
    
    1037 1040
           if ("proxy" in settings) {
    
    1041
    +        // proxy settings have to be set as a group.
    
    1038 1042
             this.proxy.enabled = !!settings.proxy.enabled;
    
    1039 1043
             if (this.proxy.enabled) {
    
    1040 1044
               this.proxy.type = settings.proxy.type;
    
    ... ... @@ -1046,6 +1050,7 @@ class TorSettingsImpl {
    1046 1050
           }
    
    1047 1051
     
    
    1048 1052
           if ("firewall" in settings) {
    
    1053
    +        // firewall settings have to be set as a group.
    
    1049 1054
             this.firewall.enabled = !!settings.firewall.enabled;
    
    1050 1055
             if (this.firewall.enabled) {
    
    1051 1056
               this.firewall.allowed_ports = settings.firewall.allowed_ports;
    
    ... ... @@ -1057,27 +1062,33 @@ class TorSettingsImpl {
    1057 1062
           if (this.#settingErrors.length) {
    
    1058 1063
             throw Error(this.#settingErrors.join("; "));
    
    1059 1064
           }
    
    1065
    +      this.#saveToPrefs();
    
    1060 1066
         } catch (ex) {
    
    1061 1067
           // Restore the old settings without any new notifications generated from
    
    1062 1068
           // the above code.
    
    1063
    -      // NOTE: Since this code is not async, it should not be possible for
    
    1064
    -      // some other call to TorSettings to change anything whilst we are
    
    1065
    -      // in this context (other than lower down in this call stack), so it is
    
    1066
    -      // safe to discard all changes to settings and notifications.
    
    1069
    +      // NOTE: Since the code that changes #settings is not async, it should not
    
    1070
    +      // be possible for some other call to TorSettings to change anything
    
    1071
    +      // whilst we are in this context (other than lower down in this call
    
    1072
    +      // stack), so it is safe to discard all changes to settings and
    
    1073
    +      // notifications.
    
    1067 1074
           this.#settings = backup;
    
    1068 1075
           this.#notificationQueue.clear();
    
    1069 1076
           for (const notification of backupNotifications) {
    
    1070 1077
             this.#notificationQueue.add(notification);
    
    1071 1078
           }
    
    1072 1079
     
    
    1073
    -      lazy.logger.error("setSettings failed", ex);
    
    1080
    +      throw ex;
    
    1074 1081
         } finally {
    
    1075
    -      this.thawNotifications();
    
    1082
    +      this.#thawNotifications();
    
    1076 1083
           // Stop collecting errors.
    
    1077 1084
           this.#settingErrors = null;
    
    1078 1085
         }
    
    1079 1086
     
    
    1080 1087
         lazy.logger.debug("setSettings result", this.#settings);
    
    1088
    +
    
    1089
    +    // After we have sent out the notifications for the changed settings and
    
    1090
    +    // saved the preferences we send the new settings to TorProvider.
    
    1091
    +    await this.#applySettings();
    
    1081 1092
       }
    
    1082 1093
     
    
    1083 1094
       /**
    
    ... ... @@ -1162,7 +1173,7 @@ class TorSettingsImpl {
    1162 1173
     
    
    1163 1174
         // After checks are complete, we commit them.
    
    1164 1175
         this.#temporaryBridgeSettings = bridgeSettings;
    
    1165
    -    await this.applySettings();
    
    1176
    +    await this.#applySettings();
    
    1166 1177
       }
    
    1167 1178
     
    
    1168 1179
       /**
    
    ... ... @@ -1174,10 +1185,9 @@ class TorSettingsImpl {
    1174 1185
           lazy.logger.warn("No temporary bridges to save");
    
    1175 1186
           return;
    
    1176 1187
         }
    
    1177
    -    this.setSettings({ bridges: this.#temporaryBridgeSettings });
    
    1188
    +    const bridgeSettings = this.#temporaryBridgeSettings;
    
    1178 1189
         this.#temporaryBridgeSettings = null;
    
    1179
    -    this.saveToPrefs();
    
    1180
    -    await this.applySettings();
    
    1190
    +    await this.changeSettings({ bridges: bridgeSettings });
    
    1181 1191
       }
    
    1182 1192
     
    
    1183 1193
       /**
    
    ... ... @@ -1190,7 +1200,7 @@ class TorSettingsImpl {
    1190 1200
           return;
    
    1191 1201
         }
    
    1192 1202
         this.#temporaryBridgeSettings = null;
    
    1193
    -    await this.applySettings();
    
    1203
    +    await this.#applySettings();
    
    1194 1204
       }
    
    1195 1205
     }
    
    1196 1206