... |
... |
@@ -18,6 +18,11 @@ export const TorProviderTopics = Object.freeze({ |
18
|
18
|
StreamSucceeded: "TorStreamSucceeded",
|
19
|
19
|
});
|
20
|
20
|
|
|
21
|
+export const TorProviders = Object.freeze({
|
|
22
|
+ none: 0,
|
|
23
|
+ tor: 1,
|
|
24
|
+});
|
|
25
|
+
|
21
|
26
|
/**
|
22
|
27
|
* The factory to get a Tor provider.
|
23
|
28
|
* Currently we support only TorProvider, i.e., the one that interacts with
|
... |
... |
@@ -35,9 +40,9 @@ export class TorProviderBuilder { |
35
|
40
|
* The observer that checks when the tor process exits, and reinitializes the
|
36
|
41
|
* provider.
|
37
|
42
|
*
|
38
|
|
- * @type {nsIObserver?}
|
|
43
|
+ * @type {Function}
|
39
|
44
|
*/
|
40
|
|
- static #observer = null;
|
|
45
|
+ static #exitObserver = null;
|
41
|
46
|
|
42
|
47
|
/**
|
43
|
48
|
* Tell whether the browser UI is ready.
|
... |
... |
@@ -54,25 +59,30 @@ export class TorProviderBuilder { |
54
|
59
|
* initialization anyway (and re-throw any initialization error).
|
55
|
60
|
*/
|
56
|
61
|
static async init() {
|
57
|
|
- this.#observer = {
|
58
|
|
- observe(subject, topic, data) {
|
59
|
|
- if (topic !== TorProviderTopics.ProcessExited) {
|
60
|
|
- return;
|
61
|
|
- }
|
62
|
|
- if (!TorProviderBuilder.#uiReady) {
|
63
|
|
- console.warn(
|
64
|
|
- `Seen ${TorProviderTopics.ProcessExited}, but not doing anything because the UI is not ready yet.`
|
65
|
|
- );
|
66
|
|
- return;
|
67
|
|
- }
|
68
|
|
- TorProviderBuilder.#torExited();
|
69
|
|
- },
|
70
|
|
- };
|
71
|
|
- Services.obs.addObserver(this.#observer, TorProviderTopics.ProcessExited);
|
72
|
|
- await this.#initProvider();
|
|
62
|
+ switch (this.providerType) {
|
|
63
|
+ case TorProviders.tor:
|
|
64
|
+ await this.#initTorProvider();
|
|
65
|
+ break;
|
|
66
|
+ case TorProviders.none:
|
|
67
|
+ lazy.TorLauncherUtil.setProxyConfiguration(
|
|
68
|
+ lazy.TorLauncherUtil.getPreferredSocksConfiguration()
|
|
69
|
+ );
|
|
70
|
+ break;
|
|
71
|
+ default:
|
|
72
|
+ console.error(`Unknown tor provider ${this.providerType}.`);
|
|
73
|
+ break;
|
|
74
|
+ }
|
73
|
75
|
}
|
74
|
76
|
|
75
|
|
- static async #initProvider() {
|
|
77
|
+ static async #initTorProvider() {
|
|
78
|
+ if (!this.#exitObserver) {
|
|
79
|
+ this.#exitObserver = this.#torExited.bind(this);
|
|
80
|
+ Services.obs.addObserver(
|
|
81
|
+ this.#exitObserver,
|
|
82
|
+ TorProviderTopics.ProcessExited
|
|
83
|
+ );
|
|
84
|
+ }
|
|
85
|
+
|
76
|
86
|
try {
|
77
|
87
|
const old = await this.#provider;
|
78
|
88
|
old?.uninit();
|
... |
... |
@@ -92,12 +102,12 @@ export class TorProviderBuilder { |
92
|
102
|
provider.uninit();
|
93
|
103
|
this.#provider = null;
|
94
|
104
|
});
|
95
|
|
- if (this.#observer) {
|
|
105
|
+ if (this.#exitObserver) {
|
96
|
106
|
Services.obs.removeObserver(
|
97
|
|
- this.#observer,
|
|
107
|
+ this.#exitObserver,
|
98
|
108
|
TorProviderTopics.ProcessExited
|
99
|
109
|
);
|
100
|
|
- this.#observer = null;
|
|
110
|
+ this.#exitObserver = null;
|
101
|
111
|
}
|
102
|
112
|
}
|
103
|
113
|
|
... |
... |
@@ -107,7 +117,11 @@ export class TorProviderBuilder { |
107
|
117
|
* catch also any initialization errors.
|
108
|
118
|
*/
|
109
|
119
|
static async build() {
|
110
|
|
- if (!this.#provider) {
|
|
120
|
+ if (!this.#provider && this.providerType === TorProviders.none) {
|
|
121
|
+ throw new Error(
|
|
122
|
+ "Tor Browser has been configured to use only the proxy functionalities."
|
|
123
|
+ );
|
|
124
|
+ } else if (!this.#provider) {
|
111
|
125
|
throw new Error(
|
112
|
126
|
"The provider has not been initialized or already uninitialized."
|
113
|
127
|
);
|
... |
... |
@@ -125,7 +139,10 @@ export class TorProviderBuilder { |
125
|
139
|
*/
|
126
|
140
|
static async firstWindowLoaded() {
|
127
|
141
|
// FIXME: Just integrate this with the about:torconnect or about:tor UI.
|
128
|
|
- if (!lazy.TorLauncherUtil.shouldStartAndOwnTor) {
|
|
142
|
+ if (
|
|
143
|
+ !lazy.TorLauncherUtil.shouldStartAndOwnTor ||
|
|
144
|
+ this.providerType !== TorProviders.tor
|
|
145
|
+ ) {
|
129
|
146
|
// If we are not managing the Tor daemon we cannot restart it, so just
|
130
|
147
|
// early return.
|
131
|
148
|
return;
|
... |
... |
@@ -143,7 +160,7 @@ export class TorProviderBuilder { |
143
|
160
|
}
|
144
|
161
|
while (!running && lazy.TorLauncherUtil.showRestartPrompt(true)) {
|
145
|
162
|
try {
|
146
|
|
- await this.#initProvider();
|
|
163
|
+ await this.#initTorProvider();
|
147
|
164
|
running = true;
|
148
|
165
|
} catch {}
|
149
|
166
|
}
|
... |
... |
@@ -153,11 +170,40 @@ export class TorProviderBuilder { |
153
|
170
|
}
|
154
|
171
|
|
155
|
172
|
static async #torExited() {
|
|
173
|
+ if (!this.#uiReady) {
|
|
174
|
+ console.warn(
|
|
175
|
+ `Seen ${TorProviderTopics.ProcessExited}, but not doing anything because the UI is not ready yet.`
|
|
176
|
+ );
|
|
177
|
+ return;
|
|
178
|
+ }
|
156
|
179
|
while (lazy.TorLauncherUtil.showRestartPrompt(false)) {
|
157
|
180
|
try {
|
158
|
|
- await this.#initProvider();
|
|
181
|
+ await this.#initTorProvider();
|
159
|
182
|
break;
|
160
|
183
|
} catch {}
|
161
|
184
|
}
|
162
|
185
|
}
|
|
186
|
+
|
|
187
|
+ /**
|
|
188
|
+ * Return the provider chosen by the user.
|
|
189
|
+ * This function checks the TOR_PROVIDER environment variable and if it is a
|
|
190
|
+ * known provider, it returns its associated value.
|
|
191
|
+ * Otherwise, if it is not valid, the C tor implementation is chosen as the
|
|
192
|
+ * default one.
|
|
193
|
+ *
|
|
194
|
+ * @returns {number} An entry from TorProviders
|
|
195
|
+ */
|
|
196
|
+ static get providerType() {
|
|
197
|
+ // TODO: Add a preference to permanently save this without and avoid always
|
|
198
|
+ // using an environment variable.
|
|
199
|
+ let provider = TorProviders.tor;
|
|
200
|
+ const kEnvName = "TOR_PROVIDER";
|
|
201
|
+ if (
|
|
202
|
+ Services.env.exists(kEnvName) &&
|
|
203
|
+ Services.env.get(kEnvName) in TorProviders
|
|
204
|
+ ) {
|
|
205
|
+ provider = TorProviders[Services.env.get(kEnvName)];
|
|
206
|
+ }
|
|
207
|
+ return provider;
|
|
208
|
+ }
|
163
|
209
|
} |