Commits:
-
6571ac7b
by Henry Wilkes at 2025-01-21T14:15:40+00:00
fixup! TB 40933: Add tor-launcher functionality
TB 41921: Move prompt_at_startup preference from TorProvider to
TorConnect only.
-
fa81e56c
by Henry Wilkes at 2025-01-21T14:15:40+00:00
fixup! TB 40597: Implement TorSettings module
TB 41921: Move prompt_at_startup pref from TorProvider to TorConnect
only.
This simplifies the logic, where we set the preference any time we have
a bootstrap error and clear it when we are bootstrapped.
-
093e9483
by Henry Wilkes at 2025-01-21T14:15:41+00:00
fixup! TB 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection
TB 41921: Move flushSettings call to TorSettings.
The call in connectionPane will not necessarily run when the
preference tab is closed, nor will it trigger for bridges added through
auto-bootstrapping.
-
b50c1c9c
by Henry Wilkes at 2025-01-21T14:15:42+00:00
fixup! TB 40597: Implement TorSettings module
TB 41921: Flush TorSettings settings every time they are saved.
-
06cbcd5d
by Henry Wilkes at 2025-01-21T14:15:43+00:00
fixup! TB 40933: Add tor-launcher functionality
TB 41921: Add a NOTE for future development ensuring that writeSettings
is not subject to any races between sequential calls.
5 changed files:
Changes:
browser/components/torpreferences/content/connectionPane.js
| ... |
... |
@@ -2545,19 +2545,6 @@ const gConnectionPane = (function () { |
|
2545
|
2545
|
|
|
2546
|
2546
|
// populate xul with strings and cache the relevant elements
|
|
2547
|
2547
|
_populateXUL() {
|
|
2548
|
|
- // saves tor settings to disk when navigate away from about:preferences
|
|
2549
|
|
- window.addEventListener("blur", async () => {
|
|
2550
|
|
- try {
|
|
2551
|
|
- // Build a new provider each time because this might be called also
|
|
2552
|
|
- // when closing the browser (if about:preferences was open), maybe
|
|
2553
|
|
- // when the provider was already uninitialized.
|
|
2554
|
|
- const provider = await TorProviderBuilder.build();
|
|
2555
|
|
- provider.flushSettings();
|
|
2556
|
|
- } catch (e) {
|
|
2557
|
|
- console.warn("Could not save the tor settings.", e);
|
|
2558
|
|
- }
|
|
2559
|
|
- });
|
|
2560
|
|
-
|
|
2561
|
2548
|
// Quickstart
|
|
2562
|
2549
|
this._enableQuickstartCheckbox = document.getElementById(
|
|
2563
|
2550
|
"torPreferences-quickstart-toggle"
|
toolkit/components/tor-launcher/TorControlPort.sys.mjs
| ... |
... |
@@ -364,6 +364,9 @@ export class TorController { |
|
364
|
364
|
/**
|
|
365
|
365
|
* The commands that need to be run or receive a response.
|
|
366
|
366
|
*
|
|
|
367
|
+ * NOTE: This must be in the order with the last requested command at the end
|
|
|
368
|
+ * of the queue.
|
|
|
369
|
+ *
|
|
367
|
370
|
* @type {Command[]}
|
|
368
|
371
|
*/
|
|
369
|
372
|
#commandQueue = [];
|
| ... |
... |
@@ -947,6 +950,10 @@ export class TorController { |
|
947
|
950
|
* values will be automatically unrolled.
|
|
948
|
951
|
*/
|
|
949
|
952
|
async setConf(values) {
|
|
|
953
|
+ // NOTE: This is an async method. It must ensure that sequential calls to
|
|
|
954
|
+ // this method do not race against each other. I.e. the last call to this
|
|
|
955
|
+ // method must always be the last in #commandQueue. Otherwise a delayed
|
|
|
956
|
+ // earlier call could overwrite the configuration of a later call.
|
|
950
|
957
|
const args = values
|
|
951
|
958
|
.flatMap(([key, value]) => {
|
|
952
|
959
|
if (value === undefined || value === null) {
|
toolkit/components/tor-launcher/TorProvider.sys.mjs
| ... |
... |
@@ -70,7 +70,6 @@ const Preferences = Object.freeze({ |
|
70
|
70
|
ControlHost: "extensions.torlauncher.control_host",
|
|
71
|
71
|
ControlPort: "extensions.torlauncher.control_port",
|
|
72
|
72
|
MaxLogEntries: "extensions.torlauncher.max_tor_log_entries",
|
|
73
|
|
- PromptAtStartup: "extensions.torlauncher.prompt_at_startup",
|
|
74
|
73
|
});
|
|
75
|
74
|
|
|
76
|
75
|
/* Config Keys used to configure tor daemon */
|
| ... |
... |
@@ -335,6 +334,15 @@ export class TorProvider { |
|
335
|
334
|
}
|
|
336
|
335
|
|
|
337
|
336
|
logger.debug("Mapped settings object", settings, torSettings);
|
|
|
337
|
+
|
|
|
338
|
+ // Send settings to the tor process.
|
|
|
339
|
+ // NOTE: Since everything up to this point has been non-async, the order in
|
|
|
340
|
+ // which TorProvider.writeSettings is called should match the order in which
|
|
|
341
|
+ // the configuration is passed onto setConf. In turn, TorControlPort.setConf
|
|
|
342
|
+ // should similarly ensure that the configuration reaches the tor process in
|
|
|
343
|
+ // the same order.
|
|
|
344
|
+ // In particular, we do not want a race where an earlier call to
|
|
|
345
|
+ // TorProvider.writeSettings can be delayed and override a later call.
|
|
338
|
346
|
await this.#controller.setConf(Array.from(torSettings));
|
|
339
|
347
|
}
|
|
340
|
348
|
|
| ... |
... |
@@ -962,11 +970,6 @@ export class TorProvider { |
|
962
|
970
|
|
|
963
|
971
|
if (statusObj.PROGRESS === 100) {
|
|
964
|
972
|
this.#isBootstrapDone = true;
|
|
965
|
|
- try {
|
|
966
|
|
- Services.prefs.setBoolPref(Preferences.PromptAtStartup, false);
|
|
967
|
|
- } catch (e) {
|
|
968
|
|
- logger.warn(`Cannot set ${Preferences.PromptAtStartup}`, e);
|
|
969
|
|
- }
|
|
970
|
973
|
return;
|
|
971
|
974
|
}
|
|
972
|
975
|
|
| ... |
... |
@@ -988,11 +991,6 @@ export class TorProvider { |
|
988
|
991
|
* @param {object} statusObj The bootstrap status object with the error
|
|
989
|
992
|
*/
|
|
990
|
993
|
#notifyBootstrapError(statusObj) {
|
|
991
|
|
- try {
|
|
992
|
|
- Services.prefs.setBoolPref(Preferences.PromptAtStartup, true);
|
|
993
|
|
- } catch (e) {
|
|
994
|
|
- logger.warn(`Cannot set ${Preferences.PromptAtStartup}`, e);
|
|
995
|
|
- }
|
|
996
|
994
|
logger.error("Tor bootstrap error", statusObj);
|
|
997
|
995
|
|
|
998
|
996
|
if (
|
toolkit/modules/TorConnect.sys.mjs
| ... |
... |
@@ -16,15 +16,12 @@ ChromeUtils.defineESModuleGetters(lazy, { |
|
16
|
16
|
TorSettings: "resource://gre/modules/TorSettings.sys.mjs",
|
|
17
|
17
|
});
|
|
18
|
18
|
|
|
19
|
|
-/* Relevant prefs used by tor-launcher */
|
|
20
|
|
-const TorLauncherPrefs = Object.freeze({
|
|
21
|
|
- prompt_at_startup: "extensions.torlauncher.prompt_at_startup",
|
|
22
|
|
-});
|
|
23
|
|
-
|
|
24
|
19
|
const TorConnectPrefs = Object.freeze({
|
|
25
|
20
|
censorship_level: "torbrowser.debug.censorship_level",
|
|
26
|
21
|
allow_internet_test: "torbrowser.bootstrap.allow_internet_test",
|
|
27
|
22
|
log_level: "torbrowser.bootstrap.log_level",
|
|
|
23
|
+ /* prompt_at_startup now controls whether the quickstart can trigger. */
|
|
|
24
|
+ prompt_at_startup: "extensions.torlauncher.prompt_at_startup",
|
|
28
|
25
|
});
|
|
29
|
26
|
|
|
30
|
27
|
export const TorConnectState = Object.freeze({
|
| ... |
... |
@@ -1050,7 +1047,7 @@ export const TorConnect = { |
|
1050
|
1047
|
lazy.logger.info("Starting again since the tor process exited");
|
|
1051
|
1048
|
// Treat a failure as a possibly broken configuration.
|
|
1052
|
1049
|
// So, prevent quickstart at the next start.
|
|
1053
|
|
- Services.prefs.setBoolPref(TorLauncherPrefs.prompt_at_startup, true);
|
|
|
1050
|
+ Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true);
|
|
1054
|
1051
|
this._makeStageRequest(TorConnectStage.Start, true);
|
|
1055
|
1052
|
break;
|
|
1056
|
1053
|
default:
|
| ... |
... |
@@ -1171,7 +1168,7 @@ export const TorConnect = { |
|
1171
|
1168
|
return (
|
|
1172
|
1169
|
lazy.TorSettings.quickstart.enabled &&
|
|
1173
|
1170
|
// and the previous bootstrap attempt must have succeeded
|
|
1174
|
|
- !Services.prefs.getBoolPref(TorLauncherPrefs.prompt_at_startup, true)
|
|
|
1171
|
+ !Services.prefs.getBoolPref(TorConnectPrefs.prompt_at_startup, true)
|
|
1175
|
1172
|
);
|
|
1176
|
1173
|
},
|
|
1177
|
1174
|
|
| ... |
... |
@@ -1451,6 +1448,8 @@ export const TorConnect = { |
|
1451
|
1448
|
this._tryAgain = false;
|
|
1452
|
1449
|
this._potentiallyBlocked = false;
|
|
1453
|
1450
|
this._errorDetails = null;
|
|
|
1451
|
+ // Re-enable quickstart for future sessions.
|
|
|
1452
|
+ Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, false);
|
|
1454
|
1453
|
|
|
1455
|
1454
|
if (requestedStage) {
|
|
1456
|
1455
|
lazy.logger.warn(
|
| ... |
... |
@@ -1491,6 +1490,8 @@ export const TorConnect = { |
|
1491
|
1490
|
|
|
1492
|
1491
|
this._tryAgain = true;
|
|
1493
|
1492
|
this._potentiallyBlocked = true;
|
|
|
1493
|
+ // Disable quickstart until we have a successful bootstrap.
|
|
|
1494
|
+ Services.prefs.setBoolPref(TorConnectPrefs.prompt_at_startup, true);
|
|
1494
|
1495
|
|
|
1495
|
1496
|
this._signalError(error);
|
|
1496
|
1497
|
|
toolkit/modules/TorSettings.sys.mjs
| ... |
... |
@@ -711,10 +711,15 @@ class TorSettingsImpl { |
|
711
|
711
|
*
|
|
712
|
712
|
* Even though this introduces a circular depdency, it makes the API nicer for
|
|
713
|
713
|
* frontend consumers.
|
|
|
714
|
+ *
|
|
|
715
|
+ * @param {boolean} flush - Whether to also flush the settings to disk.
|
|
714
|
716
|
*/
|
|
715
|
|
- async #applySettings() {
|
|
|
717
|
+ async #applySettings(flush) {
|
|
716
|
718
|
const provider = await lazy.TorProviderBuilder.build();
|
|
717
|
719
|
await provider.writeSettings();
|
|
|
720
|
+ if (flush) {
|
|
|
721
|
+ provider.flushSettings();
|
|
|
722
|
+ }
|
|
718
|
723
|
}
|
|
719
|
724
|
|
|
720
|
725
|
/**
|
| ... |
... |
@@ -974,7 +979,7 @@ class TorSettingsImpl { |
|
974
|
979
|
];
|
|
975
|
980
|
const shouldApply = changes.some(prop => !unreadProps.includes(prop));
|
|
976
|
981
|
if (shouldApply) {
|
|
977
|
|
- await this.#applySettings();
|
|
|
982
|
+ await this.#applySettings(true);
|
|
978
|
983
|
}
|
|
979
|
984
|
}
|
|
980
|
985
|
|
| ... |
... |
@@ -1042,7 +1047,8 @@ class TorSettingsImpl { |
|
1042
|
1047
|
|
|
1043
|
1048
|
// After checks are complete, we commit them.
|
|
1044
|
1049
|
this.#temporaryBridgeSettings = bridgeSettings;
|
|
1045
|
|
- await this.#applySettings();
|
|
|
1050
|
+ // Do not flush the temporary bridge settings until they are saved.
|
|
|
1051
|
+ await this.#applySettings(false);
|
|
1046
|
1052
|
}
|
|
1047
|
1053
|
|
|
1048
|
1054
|
/**
|
|