Commits:
-
2ee1e06a
by Elena at 2026-11-05T22:52:43+01:00
fixup! TB 40933: Add tor-launcher functionality
TB 45425: Use an actual XPCOM type for status updates.
-
ab560c67
by Elena at 2026-11-05T22:52:43+01:00
fixup! TB 31286: Implementation of bridge, proxy, and firewall settings in about:preferences#connection
TB 45425: Use an actual XPCOM type for status updates.
-
89e4cd8d
by Elena at 2026-11-05T22:52:43+01:00
fixup! TB 42247: Android helpers for the TorProvider
TB 45425: Use an actual XPCOM type for status updates.
-
46369c80
by Elena at 2026-11-05T22:52:43+01:00
fixup! TB 3455: Add DomainIsolator, for isolating circuit by domain.
TB 45425: Use an actual XPCOM type for provider topics.
-
93647f33
by Pier Angelo Vendrame at 2026-11-05T22:52:44+01:00
fixup! TB 41600: Add a tor circuit display panel.
TB 45425: Use an explicit boolean for bridges in NodeData
11 changed files:
Changes:
browser/components/torcircuit/content/torCircuitPanel.js
| ... |
... |
@@ -547,9 +547,9 @@ var gTorCircuitPanel = { |
|
547
|
547
|
// bridge, or otherwise a guard.
|
|
548
|
548
|
document.l10n.setAttributes(
|
|
549
|
549
|
this._panelElements.newCircuitDescription,
|
|
550
|
|
- nodes[0].bridgeType === null
|
|
551
|
|
- ? "tor-circuit-panel-new-button-description-guard"
|
|
552
|
|
- : "tor-circuit-panel-new-button-description-bridge"
|
|
|
550
|
+ nodes[0].isBridge
|
|
|
551
|
+ ? "tor-circuit-panel-new-button-description-bridge"
|
|
|
552
|
+ : "tor-circuit-panel-new-button-description-guard"
|
|
553
|
553
|
);
|
|
554
|
554
|
},
|
|
555
|
555
|
|
| ... |
... |
@@ -565,7 +565,7 @@ var gTorCircuitPanel = { |
|
565
|
565
|
const nameEl = nodeItem.querySelector(".tor-circuit-node-name");
|
|
566
|
566
|
let flagSrc = null;
|
|
567
|
567
|
|
|
568
|
|
- if (node.bridgeType === null) {
|
|
|
568
|
+ if (!node.isBridge) {
|
|
569
|
569
|
const regionCode = node.regionCode;
|
|
570
|
570
|
flagSrc = this._regionFlagSrc(regionCode);
|
|
571
|
571
|
|
browser/components/torpreferences/content/torLogDialog.js
| ... |
... |
@@ -87,7 +87,13 @@ const gTorLogDialog = { |
|
87
|
87
|
|
|
88
|
88
|
observe(subject, topic) {
|
|
89
|
89
|
if (topic === TorProviderTopics.TorLog) {
|
|
90
|
|
- this.addLogEntry(subject.wrappedJSObject, false);
|
|
|
90
|
+ let entry;
|
|
|
91
|
+ try {
|
|
|
92
|
+ entry = subject.QueryInterface(Ci.torITorLogEntry);
|
|
|
93
|
+ } catch {
|
|
|
94
|
+ return;
|
|
|
95
|
+ }
|
|
|
96
|
+ this.addLogEntry(entry, false);
|
|
91
|
97
|
}
|
|
92
|
98
|
},
|
|
93
|
99
|
|
| ... |
... |
@@ -96,7 +102,7 @@ const gTorLogDialog = { |
|
96
|
102
|
timeEl.textContent = logEntry.timestamp;
|
|
97
|
103
|
timeEl.classList.add("time");
|
|
98
|
104
|
const messageEl = document.createElement("td");
|
|
99
|
|
- messageEl.textContent = `[${logEntry.type}] ${logEntry.msg}`;
|
|
|
105
|
+ messageEl.textContent = `[${logEntry.severity}] ${logEntry.message}`;
|
|
100
|
106
|
messageEl.classList.add("message");
|
|
101
|
107
|
|
|
102
|
108
|
const row = document.createElement("tr");
|
toolkit/components/tor-launcher/TorBootstrapRequest.sys.mjs
| ... |
... |
@@ -7,6 +7,8 @@ ChromeUtils.defineESModuleGetters(lazy, { |
|
7
|
7
|
"moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs",
|
|
8
|
8
|
TorProviderTopics:
|
|
9
|
9
|
"moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs",
|
|
|
10
|
+ TorBootstrapError:
|
|
|
11
|
+ "moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs",
|
|
10
|
12
|
});
|
|
11
|
13
|
|
|
12
|
14
|
const log = console.createInstance({
|
| ... |
... |
@@ -35,12 +37,18 @@ export class TorBootstrapRequest { |
|
35
|
37
|
#timeoutID = null;
|
|
36
|
38
|
|
|
37
|
39
|
observe(subject, topic) {
|
|
38
|
|
- const obj = subject?.wrappedJSObject;
|
|
39
|
40
|
switch (topic) {
|
|
40
|
41
|
case lazy.TorProviderTopics.BootstrapStatus: {
|
|
41
|
|
- const progress = obj.PROGRESS;
|
|
|
42
|
+ let obj;
|
|
|
43
|
+ try {
|
|
|
44
|
+ obj = subject.QueryInterface(Ci.torITorBootstrapStatus);
|
|
|
45
|
+ } catch (e) {
|
|
|
46
|
+ log.warn("BootstrapStatus with an unexpected subject", e, subject);
|
|
|
47
|
+ break;
|
|
|
48
|
+ }
|
|
|
49
|
+ const progress = obj.progress;
|
|
42
|
50
|
if (this.onbootstrapstatus) {
|
|
43
|
|
- const status = obj.TAG;
|
|
|
51
|
+ const status = obj.tag;
|
|
44
|
52
|
this.onbootstrapstatus(progress, status);
|
|
45
|
53
|
}
|
|
46
|
54
|
if (progress === 100) {
|
| ... |
... |
@@ -55,8 +63,21 @@ export class TorBootstrapRequest { |
|
55
|
63
|
break;
|
|
56
|
64
|
}
|
|
57
|
65
|
case lazy.TorProviderTopics.BootstrapError: {
|
|
|
66
|
+ let obj;
|
|
|
67
|
+ try {
|
|
|
68
|
+ obj = subject.QueryInterface(Ci.torITorBootstrapStatus);
|
|
|
69
|
+ } catch (e) {
|
|
|
70
|
+ log.warn("TorBootstrapError with an unexpected subject", e, subject);
|
|
|
71
|
+ break;
|
|
|
72
|
+ }
|
|
58
|
73
|
log.info("TorBootstrapRequest: observerd TorBootstrapError", obj);
|
|
59
|
|
- this.#stop(obj);
|
|
|
74
|
+ this.#stop(
|
|
|
75
|
+ new lazy.TorBootstrapError({
|
|
|
76
|
+ phase: obj.tag,
|
|
|
77
|
+ summary: obj.summary,
|
|
|
78
|
+ reason: obj.reason,
|
|
|
79
|
+ })
|
|
|
80
|
+ );
|
|
60
|
81
|
break;
|
|
61
|
82
|
}
|
|
62
|
83
|
}
|
toolkit/components/tor-launcher/TorDomainIsolator.sys.mjs
| ... |
... |
@@ -288,8 +288,34 @@ class TorDomainIsolatorImpl { |
|
288
|
288
|
// TODO: What UX to use here? See tor-browser#41708
|
|
289
|
289
|
}
|
|
290
|
290
|
} else if (topic === lazy.TorProviderTopics.CircuitCredentialsMatched) {
|
|
291
|
|
- const { username, password, circuits } = subject.wrappedJSObject;
|
|
292
|
|
- this.#updateCircuits(username, password, circuits);
|
|
|
291
|
+ let streamInfo;
|
|
|
292
|
+ try {
|
|
|
293
|
+ streamInfo = subject?.QueryInterface(Ci.torITorStreamInfo);
|
|
|
294
|
+ } catch (e) {
|
|
|
295
|
+ logger.warn(
|
|
|
296
|
+ "CircuitCredentialsMatched with invalid stream info",
|
|
|
297
|
+ e,
|
|
|
298
|
+ subject
|
|
|
299
|
+ );
|
|
|
300
|
+ }
|
|
|
301
|
+ if (streamInfo) {
|
|
|
302
|
+ const circuits = streamInfo.circuits?.map(circuit =>
|
|
|
303
|
+ circuit.map(node => {
|
|
|
304
|
+ return {
|
|
|
305
|
+ fingerprint: node.fingerprint,
|
|
|
306
|
+ ipAddrs: node.ipAddrs,
|
|
|
307
|
+ isBridge: node.isBridge,
|
|
|
308
|
+ bridgeType: node.bridgeType,
|
|
|
309
|
+ regionCode: node.regionCode,
|
|
|
310
|
+ };
|
|
|
311
|
+ })
|
|
|
312
|
+ );
|
|
|
313
|
+ this.#updateCircuits(
|
|
|
314
|
+ streamInfo.socksUsername,
|
|
|
315
|
+ streamInfo.socksPassword,
|
|
|
316
|
+ circuits
|
|
|
317
|
+ );
|
|
|
318
|
+ }
|
|
293
|
319
|
}
|
|
294
|
320
|
}
|
|
295
|
321
|
|
toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs
| ... |
... |
@@ -644,17 +644,22 @@ export const TorLauncherUtil = { |
|
644
|
644
|
* Therefore, the messages should avoid containing any information that might
|
|
645
|
645
|
* identify information about the user.
|
|
646
|
646
|
*
|
|
647
|
|
- * @param {string} type The log type (ERR, WARN, etc...)
|
|
648
|
|
- * @param {string} msg The log message
|
|
|
647
|
+ * @param {string} severity The log severity (ERR, WARN, etc...)
|
|
|
648
|
+ * @param {string} message The log message
|
|
649
|
649
|
*/
|
|
650
|
|
- log(type, msg) {
|
|
|
650
|
+ log(severity, message) {
|
|
651
|
651
|
const timestamp =
|
|
652
|
652
|
new Date().toISOString().replace("T", " ").replace("Z", "") + " UTC";
|
|
653
|
653
|
Services.obs.notifyObservers(
|
|
654
|
|
- { type, msg, timestamp },
|
|
|
654
|
+ {
|
|
|
655
|
+ severity,
|
|
|
656
|
+ message,
|
|
|
657
|
+ timestamp,
|
|
|
658
|
+ QueryInterface: ChromeUtils.generateQI([Ci.torITorLogEntry]),
|
|
|
659
|
+ },
|
|
655
|
660
|
lazy.TorProviderTopics.TorLog
|
|
656
|
661
|
);
|
|
657
|
|
- if (type === "WARN" || type === "ERR") {
|
|
|
662
|
+ if (severity === "WARN" || severity === "ERR") {
|
|
658
|
663
|
// Notify so that Copy Log can be enabled.
|
|
659
|
664
|
Services.obs.notifyObservers(null, lazy.TorProviderTopics.HasWarnOrErr);
|
|
660
|
665
|
}
|
toolkit/components/tor-launcher/TorProvider.sys.mjs
| ... |
... |
@@ -7,10 +7,7 @@ import { clearTimeout, setTimeout } from "resource://gre/modules/Timer.sys.mjs"; |
|
7
|
7
|
import { TorLauncherUtil } from "moz-src:///toolkit/components/tor-launcher/TorLauncherUtil.sys.mjs";
|
|
8
|
8
|
import { TorParsers } from "moz-src:///toolkit/components/tor-launcher/TorParsers.sys.mjs";
|
|
9
|
9
|
import { TorProviderBase } from "moz-src:///toolkit/components/tor-launcher/TorProviderBase.sys.mjs";
|
|
10
|
|
-import {
|
|
11
|
|
- TorBootstrapError,
|
|
12
|
|
- TorProviderTopics,
|
|
13
|
|
-} from "moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs";
|
|
|
10
|
+import { TorProviderTopics } from "moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs";
|
|
14
|
11
|
|
|
15
|
12
|
const lazy = {};
|
|
16
|
13
|
ChromeUtils.defineESModuleGetters(lazy, {
|
| ... |
... |
@@ -57,12 +54,12 @@ const logger = console.createInstance({ |
|
57
|
54
|
* @typedef NodeData
|
|
58
|
55
|
* @property {NodeFingerprint} fingerprint The node fingerprint
|
|
59
|
56
|
* @property {string[]} ipAddrs The ip addresses associated with this node
|
|
60
|
|
- * @property {string?} bridgeType The bridge type for this node, or "" if the
|
|
61
|
|
- * node is a bridge but the type is unknown, or null if this is not a bridge
|
|
62
|
|
- * node
|
|
63
|
|
- * @property {string?} regionCode An upper case 2-letter ISO3166-1 code for the
|
|
64
|
|
- * first ip address, or null if there is no region. This should also be a
|
|
65
|
|
- * valid BCP47 Region subtag
|
|
|
57
|
+ * @property {boolean} isBridge Whether the node is a bridge.
|
|
|
58
|
+ * @property {string} bridgeType The bridge type for this node, or an empty
|
|
|
59
|
+ * string if the type is unknown or the node is not a bridge.
|
|
|
60
|
+ * @property {string} regionCode An upper case 2-letter ISO3166-1 code for the
|
|
|
61
|
+ * first ip address. This should also be a valid BCP47 Region subtag.
|
|
|
62
|
+ * It will be an empty string if the node is not a bridge.
|
|
66
|
63
|
*/
|
|
67
|
64
|
|
|
68
|
65
|
const Preferences = Object.freeze({
|
| ... |
... |
@@ -929,14 +926,16 @@ export class TorProvider extends TorProviderBase { |
|
929
|
926
|
const node = {
|
|
930
|
927
|
fingerprint: id,
|
|
931
|
928
|
ipAddrs: [],
|
|
932
|
|
- bridgeType: null,
|
|
933
|
|
- regionCode: null,
|
|
|
929
|
+ isBridge: false,
|
|
|
930
|
+ bridgeType: "",
|
|
|
931
|
+ regionCode: "",
|
|
934
|
932
|
};
|
|
935
|
933
|
|
|
936
|
934
|
const bridge = (await this.#controller.getBridges())?.find(
|
|
937
|
935
|
foundBridge => foundBridge.id?.toUpperCase() === id.toUpperCase()
|
|
938
|
936
|
);
|
|
939
|
937
|
if (bridge) {
|
|
|
938
|
+ node.isBridge = true;
|
|
940
|
939
|
node.bridgeType = bridge.transport ?? "";
|
|
941
|
940
|
// Attempt to get an IP address from bridge address string.
|
|
942
|
941
|
const ip = bridge.addr.match(/^\[?([^\]]+)\]?:\d+$/)?.[1];
|
| ... |
... |
@@ -1006,7 +1005,10 @@ export class TorProvider extends TorProviderBase { |
|
1006
|
1005
|
*/
|
|
1007
|
1006
|
#processBootstrapStatus(statusObj, isNotification) {
|
|
1008
|
1007
|
// Notify observers
|
|
1009
|
|
- Services.obs.notifyObservers(statusObj, TorProviderTopics.BootstrapStatus);
|
|
|
1008
|
+ Services.obs.notifyObservers(
|
|
|
1009
|
+ new TorBootstrapStatus(statusObj),
|
|
|
1010
|
+ TorProviderTopics.BootstrapStatus
|
|
|
1011
|
+ );
|
|
1010
|
1012
|
|
|
1011
|
1013
|
if (statusObj.PROGRESS === 100) {
|
|
1012
|
1014
|
return;
|
| ... |
... |
@@ -1044,11 +1046,7 @@ export class TorProvider extends TorProviderBase { |
|
1044
|
1046
|
// anymore, since the first error eligible for notification will as a
|
|
1045
|
1047
|
// matter of fact cancel the bootstrap.
|
|
1046
|
1048
|
Services.obs.notifyObservers(
|
|
1047
|
|
- new TorBootstrapError({
|
|
1048
|
|
- phase: statusObj.TAG,
|
|
1049
|
|
- reason: statusObj.REASON,
|
|
1050
|
|
- summary: statusObj.SUMMARY,
|
|
1051
|
|
- }),
|
|
|
1049
|
+ new TorBootstrapStatus(statusObj),
|
|
1052
|
1050
|
TorProviderTopics.BootstrapError
|
|
1053
|
1051
|
);
|
|
1054
|
1052
|
}
|
| ... |
... |
@@ -1147,14 +1145,24 @@ export class TorProvider extends TorProviderBase { |
|
1147
|
1145
|
* @param {StreamID} _streamId The ID of the stream that switched to the
|
|
1148
|
1146
|
* sentconnect status.
|
|
1149
|
1147
|
* @param {CircuitID} circuitId The ID of the circuit used by the stream
|
|
1150
|
|
- * @param {string} username The SOCKS username
|
|
1151
|
|
- * @param {string} password The SOCKS password
|
|
|
1148
|
+ * @param {string} socksUsername The SOCKS username
|
|
|
1149
|
+ * @param {string} socksPassword The SOCKS password
|
|
1152
|
1150
|
*/
|
|
1153
|
|
- async onStreamSentConnect(_streamId, circuitId, username, password) {
|
|
1154
|
|
- if (!username || !password) {
|
|
|
1151
|
+ async onStreamSentConnect(
|
|
|
1152
|
+ _streamId,
|
|
|
1153
|
+ circuitId,
|
|
|
1154
|
+ socksUsername,
|
|
|
1155
|
+ socksPassword
|
|
|
1156
|
+ ) {
|
|
|
1157
|
+ if (!socksUsername || !socksPassword) {
|
|
1155
|
1158
|
return;
|
|
1156
|
1159
|
}
|
|
1157
|
|
- logger.debug("Stream sentconnect event", username, password, circuitId);
|
|
|
1160
|
+ logger.debug(
|
|
|
1161
|
+ "Stream sentconnect event",
|
|
|
1162
|
+ socksUsername,
|
|
|
1163
|
+ socksPassword,
|
|
|
1164
|
+ circuitId
|
|
|
1165
|
+ );
|
|
1158
|
1166
|
if (!this.#circuits.has(circuitId)) {
|
|
1159
|
1167
|
// tor-browser#42132: When using onion-grater (e.g., in Tails), we might
|
|
1160
|
1168
|
// not receive the CIRC BUILT event, as it is impossible to know whether
|
| ... |
... |
@@ -1194,13 +1202,33 @@ export class TorProvider extends TorProviderBase { |
|
1194
|
1202
|
);
|
|
1195
|
1203
|
Services.obs.notifyObservers(
|
|
1196
|
1204
|
{
|
|
1197
|
|
- wrappedJSObject: {
|
|
1198
|
|
- username,
|
|
1199
|
|
- password,
|
|
1200
|
|
- circuits,
|
|
1201
|
|
- },
|
|
|
1205
|
+ socksUsername,
|
|
|
1206
|
+ socksPassword,
|
|
|
1207
|
+ circuits,
|
|
|
1208
|
+ QueryInterface: ChromeUtils.generateQI([Ci.torITorStreamInfo]),
|
|
1202
|
1209
|
},
|
|
1203
|
1210
|
TorProviderTopics.CircuitCredentialsMatched
|
|
1204
|
1211
|
);
|
|
1205
|
1212
|
}
|
|
1206
|
1213
|
}
|
|
|
1214
|
+
|
|
|
1215
|
+/**
|
|
|
1216
|
+ * A _javascript_ implementation of torITorBootstrapStatus.
|
|
|
1217
|
+ */
|
|
|
1218
|
+class TorBootstrapStatus {
|
|
|
1219
|
+ /**
|
|
|
1220
|
+ * Construct a typed status object from a status object sent by TorController.
|
|
|
1221
|
+ *
|
|
|
1222
|
+ * @param {object} statusObj The status object parsed by the controller
|
|
|
1223
|
+ */
|
|
|
1224
|
+ constructor(statusObj) {
|
|
|
1225
|
+ this.progress = statusObj.PROGRESS;
|
|
|
1226
|
+ this.severity = statusObj.TYPE;
|
|
|
1227
|
+ this.tag = statusObj.TAG;
|
|
|
1228
|
+ this.summary = statusObj.SUMMARY;
|
|
|
1229
|
+ this.reason = statusObj.REASON ?? "";
|
|
|
1230
|
+ this.shouldWarn = statusObj.RECOMMENDATION !== "ignore";
|
|
|
1231
|
+ }
|
|
|
1232
|
+
|
|
|
1233
|
+ QueryInterface = ChromeUtils.generateQI([Ci.torITorBootstrapStatus]);
|
|
|
1234
|
+} |
toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs
| ... |
... |
@@ -81,9 +81,9 @@ export const TorProviders = Object.freeze({ |
|
81
|
81
|
|
|
82
|
82
|
/**
|
|
83
|
83
|
* @typedef {object} LogEntry An object with a log message
|
|
84
|
|
- * @property {string} timestamp The local date-time stamp at which we received the message
|
|
85
|
|
- * @property {string} type The message level
|
|
86
|
|
- * @property {string} msg The message
|
|
|
84
|
+ * @property {string} timestamp The UTC date-time stamp at which we received the message
|
|
|
85
|
+ * @property {string} severity The message severity
|
|
|
86
|
+ * @property {string} message The message
|
|
87
|
87
|
*/
|
|
88
|
88
|
|
|
89
|
89
|
/**
|
| ... |
... |
@@ -182,7 +182,18 @@ export class TorProviderBuilder { |
|
182
|
182
|
1000
|
|
183
|
183
|
);
|
|
184
|
184
|
this.#logObserver = subject => {
|
|
185
|
|
- this.#addLogEntry(subject.wrappedJSObject);
|
|
|
185
|
+ let entry;
|
|
|
186
|
+ try {
|
|
|
187
|
+ entry = subject.QueryInterface(Ci.torITorLogEntry);
|
|
|
188
|
+ } catch (e) {
|
|
|
189
|
+ lazy.logger.warn("TorLog with invalid subject", e, subject);
|
|
|
190
|
+ return;
|
|
|
191
|
+ }
|
|
|
192
|
+ this.#addLogEntry({
|
|
|
193
|
+ severity: entry.severity,
|
|
|
194
|
+ message: entry.message,
|
|
|
195
|
+ timestamp: entry.timestamp,
|
|
|
196
|
+ });
|
|
186
|
197
|
};
|
|
187
|
198
|
Services.obs.addObserver(this.#logObserver, TorProviderTopics.TorLog);
|
|
188
|
199
|
|
toolkit/components/tor-launcher/TorProviderMock.sys.mjs
| ... |
... |
@@ -3,19 +3,19 @@ import { TorProviderBase } from "moz-src:///toolkit/components/tor-launcher/TorP |
|
3
|
3
|
import { TorProviderTopics } from "moz-src:///toolkit/components/tor-launcher/TorProviderBuilder.sys.mjs";
|
|
4
|
4
|
|
|
5
|
5
|
const kBootstrapSteps = [
|
|
6
|
|
- { PROGRESS: 5, TAG: "starting", SUMMARY: "Starting" },
|
|
7
|
|
- { PROGRESS: 14, TAG: "handshake", SUMMARY: "Handshaking with a relay" },
|
|
|
6
|
+ { progress: 5, tag: "starting", summary: "Starting" },
|
|
|
7
|
+ { progress: 14, tag: "handshake", summary: "Handshaking with a relay" },
|
|
8
|
8
|
{
|
|
9
|
|
- PROGRESS: 45,
|
|
10
|
|
- TAG: "requesting_descriptors",
|
|
11
|
|
- SUMMARY: "Asking for relay descriptors",
|
|
|
9
|
+ progress: 45,
|
|
|
10
|
+ tag: "requesting_descriptors",
|
|
|
11
|
+ summary: "Asking for relay descriptors",
|
|
12
|
12
|
},
|
|
13
|
13
|
{
|
|
14
|
|
- PROGRESS: 75,
|
|
15
|
|
- TAG: "loading_descriptors",
|
|
16
|
|
- SUMMARY: "Loading relay descriptors",
|
|
|
14
|
+ progress: 75,
|
|
|
15
|
+ tag: "loading_descriptors",
|
|
|
16
|
+ summary: "Loading relay descriptors",
|
|
17
|
17
|
},
|
|
18
|
|
- { PROGRESS: 100, TAG: "done", SUMMARY: "Done" },
|
|
|
18
|
+ { progress: 100, tag: "done", summary: "Done" },
|
|
19
|
19
|
];
|
|
20
|
20
|
|
|
21
|
21
|
const kBootstrapStepDelayMs = 500;
|
| ... |
... |
@@ -48,7 +48,15 @@ export class TorProviderMock extends TorProviderBase { |
|
48
|
48
|
const id = setTimeout(
|
|
49
|
49
|
() => {
|
|
50
|
50
|
Services.obs.notifyObservers(
|
|
51
|
|
- { ...step, TYPE: "NOTICE" },
|
|
|
51
|
+ {
|
|
|
52
|
+ ...step,
|
|
|
53
|
+ severity: "NOTICE",
|
|
|
54
|
+ reason: "",
|
|
|
55
|
+ shouldWarn: false,
|
|
|
56
|
+ QueryInterface: ChromeUtils.generateQI([
|
|
|
57
|
+ Ci.torITorBootstrapStatus,
|
|
|
58
|
+ ]),
|
|
|
59
|
+ },
|
|
52
|
60
|
TorProviderTopics.BootstrapStatus
|
|
53
|
61
|
);
|
|
54
|
62
|
},
|
toolkit/components/tor-launcher/moz.build
|
|
1
|
+XPIDL_MODULE = "torlauncher"
|
|
|
2
|
+XPIDL_SOURCES += ["tor-launcher.idl"]
|
|
|
3
|
+
|
|
1
|
4
|
MOZ_SRC_FILES += [
|
|
2
|
5
|
"TorBootstrapRequest.sys.mjs",
|
|
3
|
6
|
"TorControlPort.sys.mjs",
|
toolkit/components/tor-launcher/tor-launcher.idl
|
|
1
|
+/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
2
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
3
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
4
|
+
|
|
|
5
|
+#include "nsISupports.idl"
|
|
|
6
|
+
|
|
|
7
|
+/**
|
|
|
8
|
+ * The information about the bootstrap status.
|
|
|
9
|
+ * The values are extracted from C-tor's STATUS_CLIENT events, except for
|
|
|
10
|
+ * shouldWarn, which is derived from the RECOMMENDATION value.
|
|
|
11
|
+ */
|
|
|
12
|
+[scriptable, uuid(64b3197d-0b1e-46a1-aa18-8cea11bacf97)]
|
|
|
13
|
+interface torITorBootstrapStatus : nsISupports {
|
|
|
14
|
+ readonly attribute octet progress;
|
|
|
15
|
+ readonly attribute ACString severity;
|
|
|
16
|
+ readonly attribute ACString tag;
|
|
|
17
|
+ readonly attribute ACString summary;
|
|
|
18
|
+ readonly attribute ACString reason;
|
|
|
19
|
+ readonly attribute boolean shouldWarn;
|
|
|
20
|
+};
|
|
|
21
|
+
|
|
|
22
|
+/**
|
|
|
23
|
+ * A tor log message.
|
|
|
24
|
+ * The severity might be also something not used by C-tor.
|
|
|
25
|
+ */
|
|
|
26
|
+[scriptable, uuid(f6d18f7d-c29c-4bf3-bf70-7d6bed3b427e)]
|
|
|
27
|
+interface torITorLogEntry : nsISupports {
|
|
|
28
|
+ readonly attribute ACString severity;
|
|
|
29
|
+ readonly attribute ACString message;
|
|
|
30
|
+ readonly attribute ACString timestamp;
|
|
|
31
|
+};
|
|
|
32
|
+
|
|
|
33
|
+/**
|
|
|
34
|
+ * A tor node information.
|
|
|
35
|
+ * The bridgeType and regionCode should be used only when isBridge is true.
|
|
|
36
|
+ */
|
|
|
37
|
+[scriptable, uuid(7547d8e5-a93e-4a0c-9876-a7a2cc44e80f)]
|
|
|
38
|
+interface torITorNodeInfo : nsISupports {
|
|
|
39
|
+ readonly attribute ACString fingerprint;
|
|
|
40
|
+ readonly attribute Array<ACString> ipAddrs;
|
|
|
41
|
+ readonly attribute boolean isBridge;
|
|
|
42
|
+ readonly attribute ACString bridgeType;
|
|
|
43
|
+ readonly attribute ACString regionCode;
|
|
|
44
|
+};
|
|
|
45
|
+
|
|
|
46
|
+/**
|
|
|
47
|
+ * The information to associate a SOCKS isolation credential (the combination
|
|
|
48
|
+ * of SOCKS username and password) to one or more circuits.
|
|
|
49
|
+ */
|
|
|
50
|
+[scriptable, uuid(a85269dc-1aca-4aec-87a6-88ff035f0eaa)]
|
|
|
51
|
+interface torITorStreamInfo : nsISupports {
|
|
|
52
|
+ readonly attribute ACString socksUsername;
|
|
|
53
|
+ readonly attribute ACString socksPassword;
|
|
|
54
|
+ readonly attribute Array<Array<torITorNodeInfo> > circuits;
|
|
|
55
|
+}; |
toolkit/modules/TorAndroidIntegration.sys.mjs
| ... |
... |
@@ -130,13 +130,19 @@ class TorAndroidIntegrationImpl { |
|
130
|
130
|
{}
|
|
131
|
131
|
);
|
|
132
|
132
|
break;
|
|
133
|
|
- case lazy.TorProviderTopics.TorLog:
|
|
134
|
|
- lazy.EventDispatcher.instance.sendRequest(EmittedEvents.torLogs, {
|
|
135
|
|
- logType: subj.wrappedJSObject.type ?? "",
|
|
136
|
|
- message: subj.wrappedJSObject.msg ?? "",
|
|
137
|
|
- timestamp: subj.wrappedJSObject.timestamp ?? "",
|
|
138
|
|
- });
|
|
|
133
|
+ case lazy.TorProviderTopics.TorLog: {
|
|
|
134
|
+ try {
|
|
|
135
|
+ const entry = subj.QueryInterface(Ci.torITorLogEntry);
|
|
|
136
|
+ lazy.EventDispatcher.instance.sendRequest(EmittedEvents.torLogs, {
|
|
|
137
|
+ logType: entry.severity,
|
|
|
138
|
+ message: entry.message,
|
|
|
139
|
+ timestamp: entry.timestamp,
|
|
|
140
|
+ });
|
|
|
141
|
+ } catch (e) {
|
|
|
142
|
+ logger.warn("Failed to dispatch a log event", e, subj);
|
|
|
143
|
+ }
|
|
139
|
144
|
break;
|
|
|
145
|
+ }
|
|
140
|
146
|
case lazy.TorSettingsTopics.Ready:
|
|
141
|
147
|
lazy.EventDispatcher.instance.sendRequest(EmittedEvents.settingsReady, {
|
|
142
|
148
|
settings: lazy.TorSettings.getSettings(),
|
|