web-ext 7.2.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/cmd/build.js +18 -36
- package/lib/cmd/build.js.map +1 -1
- package/lib/cmd/docs.js +1 -0
- package/lib/cmd/docs.js.map +1 -1
- package/lib/cmd/index.js +3 -5
- package/lib/cmd/index.js.map +1 -1
- package/lib/cmd/lint.js +28 -17
- package/lib/cmd/lint.js.map +1 -1
- package/lib/cmd/run.js +19 -23
- package/lib/cmd/run.js.map +1 -1
- package/lib/cmd/sign.js +80 -47
- package/lib/cmd/sign.js.map +1 -1
- package/lib/config.js +18 -29
- package/lib/config.js.map +1 -1
- package/lib/errors.js +8 -18
- package/lib/errors.js.map +1 -1
- package/lib/extension-runners/base.js +2 -0
- package/lib/extension-runners/base.js.map +1 -1
- package/lib/extension-runners/chromium.js +36 -62
- package/lib/extension-runners/chromium.js.map +1 -1
- package/lib/extension-runners/firefox-android.js +65 -102
- package/lib/extension-runners/firefox-android.js.map +1 -1
- package/lib/extension-runners/firefox-desktop.js +29 -42
- package/lib/extension-runners/firefox-desktop.js.map +1 -1
- package/lib/extension-runners/index.js +33 -46
- package/lib/extension-runners/index.js.map +1 -1
- package/lib/firefox/index.js +59 -52
- package/lib/firefox/index.js.map +1 -1
- package/lib/firefox/package-identifiers.js +2 -0
- package/lib/firefox/package-identifiers.js.map +1 -1
- package/lib/firefox/preferences.js +14 -15
- package/lib/firefox/preferences.js.map +1 -1
- package/lib/firefox/rdp-client.js +16 -64
- package/lib/firefox/rdp-client.js.map +1 -1
- package/lib/firefox/remote.js +15 -30
- package/lib/firefox/remote.js.map +1 -1
- package/lib/main.js +4 -2
- package/lib/main.js.map +1 -1
- package/lib/program.js +74 -76
- package/lib/program.js.map +1 -1
- package/lib/util/adb.js +33 -63
- package/lib/util/adb.js.map +1 -1
- package/lib/util/artifacts.js +3 -5
- package/lib/util/artifacts.js.map +1 -1
- package/lib/util/desktop-notifier.js +1 -0
- package/lib/util/desktop-notifier.js.map +1 -1
- package/lib/util/file-exists.js +1 -2
- package/lib/util/file-exists.js.map +1 -1
- package/lib/util/file-filter.js +17 -19
- package/lib/util/file-filter.js.map +1 -1
- package/lib/util/is-directory.js +2 -1
- package/lib/util/is-directory.js.map +1 -1
- package/lib/util/logger.js +7 -12
- package/lib/util/logger.js.map +1 -1
- package/lib/util/manifest.js +6 -13
- package/lib/util/manifest.js.map +1 -1
- package/lib/util/promisify.js +7 -3
- package/lib/util/promisify.js.map +1 -1
- package/lib/util/stdin.js +2 -0
- package/lib/util/stdin.js.map +1 -1
- package/lib/util/submit-addon.js +288 -0
- package/lib/util/submit-addon.js.map +1 -0
- package/lib/util/temp-dir.js +8 -18
- package/lib/util/temp-dir.js.map +1 -1
- package/lib/util/updates.js +1 -1
- package/lib/util/updates.js.map +1 -1
- package/lib/watcher.js +14 -9
- package/lib/watcher.js.map +1 -1
- package/package.json +16 -14
|
@@ -1,22 +1,21 @@
|
|
|
1
|
+
|
|
1
2
|
import net from 'net';
|
|
2
3
|
import EventEmitter from 'events';
|
|
3
4
|
import domain from 'domain';
|
|
4
5
|
export const DEFAULT_PORT = 6000;
|
|
5
6
|
export const DEFAULT_HOST = '127.0.0.1';
|
|
6
|
-
const UNSOLICITED_EVENTS = new Set(['tabNavigated', 'styleApplied', 'propertyChange', 'networkEventUpdate', 'networkEvent', 'propertyChange', 'newMutations', 'frameUpdate', 'tabListChanged']);
|
|
7
|
+
const UNSOLICITED_EVENTS = new Set(['tabNavigated', 'styleApplied', 'propertyChange', 'networkEventUpdate', 'networkEvent', 'propertyChange', 'newMutations', 'frameUpdate', 'tabListChanged']);
|
|
7
8
|
|
|
9
|
+
// Parse RDP packets: BYTE_LENGTH + ':' + DATA.
|
|
8
10
|
export function parseRDPMessage(data) {
|
|
9
11
|
const str = data.toString();
|
|
10
12
|
const sepIdx = str.indexOf(':');
|
|
11
|
-
|
|
12
13
|
if (sepIdx < 1) {
|
|
13
14
|
return {
|
|
14
15
|
data
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
|
-
|
|
18
18
|
const byteLen = parseInt(str.slice(0, sepIdx));
|
|
19
|
-
|
|
20
19
|
if (isNaN(byteLen)) {
|
|
21
20
|
const error = new Error('Error parsing RDP message length');
|
|
22
21
|
return {
|
|
@@ -25,18 +24,15 @@ export function parseRDPMessage(data) {
|
|
|
25
24
|
fatal: true
|
|
26
25
|
};
|
|
27
26
|
}
|
|
28
|
-
|
|
29
27
|
if (data.length - (sepIdx + 1) < byteLen) {
|
|
30
28
|
// Can't parse yet, will retry once more data has been received.
|
|
31
29
|
return {
|
|
32
30
|
data
|
|
33
31
|
};
|
|
34
32
|
}
|
|
35
|
-
|
|
36
33
|
data = data.slice(sepIdx + 1);
|
|
37
34
|
const msg = data.slice(0, byteLen);
|
|
38
35
|
data = data.slice(byteLen);
|
|
39
|
-
|
|
40
36
|
try {
|
|
41
37
|
return {
|
|
42
38
|
data,
|
|
@@ -60,16 +56,11 @@ export default class FirefoxRDPClient extends EventEmitter {
|
|
|
60
56
|
this._incoming = Buffer.alloc(0);
|
|
61
57
|
this._pending = [];
|
|
62
58
|
this._active = new Map();
|
|
63
|
-
|
|
64
59
|
this._onData = (...args) => this.onData(...args);
|
|
65
|
-
|
|
66
60
|
this._onError = (...args) => this.onError(...args);
|
|
67
|
-
|
|
68
61
|
this._onEnd = (...args) => this.onEnd(...args);
|
|
69
|
-
|
|
70
62
|
this._onTimeout = (...args) => this.onTimeout(...args);
|
|
71
63
|
}
|
|
72
|
-
|
|
73
64
|
connect(port) {
|
|
74
65
|
return new Promise((resolve, reject) => {
|
|
75
66
|
// Create a domain to wrap the errors that may be triggered
|
|
@@ -87,9 +78,10 @@ export default class FirefoxRDPClient extends EventEmitter {
|
|
|
87
78
|
conn.on('data', this._onData);
|
|
88
79
|
conn.on('error', this._onError);
|
|
89
80
|
conn.on('end', this._onEnd);
|
|
90
|
-
conn.on('timeout', this._onTimeout);
|
|
91
|
-
// has been received.
|
|
81
|
+
conn.on('timeout', this._onTimeout);
|
|
92
82
|
|
|
83
|
+
// Resolve once the expected initial root message
|
|
84
|
+
// has been received.
|
|
93
85
|
this._expectReply('root', {
|
|
94
86
|
resolve,
|
|
95
87
|
reject
|
|
@@ -97,41 +89,32 @@ export default class FirefoxRDPClient extends EventEmitter {
|
|
|
97
89
|
});
|
|
98
90
|
});
|
|
99
91
|
}
|
|
100
|
-
|
|
101
92
|
disconnect() {
|
|
102
93
|
if (!this._rdpConnection) {
|
|
103
94
|
return;
|
|
104
95
|
}
|
|
105
|
-
|
|
106
96
|
const conn = this._rdpConnection;
|
|
107
97
|
conn.off('data', this._onData);
|
|
108
98
|
conn.off('error', this._onError);
|
|
109
99
|
conn.off('end', this._onEnd);
|
|
110
100
|
conn.off('timeout', this._onTimeout);
|
|
111
101
|
conn.end();
|
|
112
|
-
|
|
113
102
|
this._rejectAllRequests(new Error('RDP connection closed'));
|
|
114
103
|
}
|
|
115
|
-
|
|
116
104
|
_rejectAllRequests(error) {
|
|
117
105
|
for (const activeDeferred of this._active.values()) {
|
|
118
106
|
activeDeferred.reject(error);
|
|
119
107
|
}
|
|
120
|
-
|
|
121
108
|
this._active.clear();
|
|
122
|
-
|
|
123
109
|
for (const {
|
|
124
110
|
deferred
|
|
125
111
|
} of this._pending) {
|
|
126
112
|
deferred.reject(error);
|
|
127
113
|
}
|
|
128
|
-
|
|
129
114
|
this._pending = [];
|
|
130
115
|
}
|
|
131
|
-
|
|
132
116
|
async request(requestProps) {
|
|
133
117
|
let request;
|
|
134
|
-
|
|
135
118
|
if (typeof requestProps === 'string') {
|
|
136
119
|
request = {
|
|
137
120
|
to: 'root',
|
|
@@ -140,26 +123,21 @@ export default class FirefoxRDPClient extends EventEmitter {
|
|
|
140
123
|
} else {
|
|
141
124
|
request = requestProps;
|
|
142
125
|
}
|
|
143
|
-
|
|
144
126
|
if (request.to == null) {
|
|
145
127
|
throw new Error(`Unexpected RDP request without target actor: ${request.type}`);
|
|
146
128
|
}
|
|
147
|
-
|
|
148
129
|
return new Promise((resolve, reject) => {
|
|
149
130
|
const deferred = {
|
|
150
131
|
resolve,
|
|
151
132
|
reject
|
|
152
133
|
};
|
|
153
|
-
|
|
154
134
|
this._pending.push({
|
|
155
135
|
request,
|
|
156
136
|
deferred
|
|
157
137
|
});
|
|
158
|
-
|
|
159
138
|
this._flushPendingRequests();
|
|
160
139
|
});
|
|
161
140
|
}
|
|
162
|
-
|
|
163
141
|
_flushPendingRequests() {
|
|
164
142
|
this._pending = this._pending.filter(({
|
|
165
143
|
request,
|
|
@@ -170,71 +148,55 @@ export default class FirefoxRDPClient extends EventEmitter {
|
|
|
170
148
|
// active on the target RDP actor.
|
|
171
149
|
return true;
|
|
172
150
|
}
|
|
173
|
-
|
|
174
151
|
const conn = this._rdpConnection;
|
|
175
|
-
|
|
176
152
|
if (!conn) {
|
|
177
153
|
throw new Error('RDP connection closed');
|
|
178
154
|
}
|
|
179
|
-
|
|
180
155
|
try {
|
|
181
156
|
let str = JSON.stringify(request);
|
|
182
157
|
str = `${Buffer.from(str).length}:${str}`;
|
|
183
158
|
conn.write(str);
|
|
184
|
-
|
|
185
159
|
this._expectReply(request.to, deferred);
|
|
186
160
|
} catch (err) {
|
|
187
161
|
deferred.reject(err);
|
|
188
|
-
}
|
|
189
|
-
|
|
162
|
+
}
|
|
190
163
|
|
|
164
|
+
// Remove the pending request from the queue.
|
|
191
165
|
return false;
|
|
192
166
|
});
|
|
193
167
|
}
|
|
194
|
-
|
|
195
168
|
_expectReply(targetActor, deferred) {
|
|
196
169
|
if (this._active.has(targetActor)) {
|
|
197
170
|
throw new Error(`${targetActor} does already have an active request`);
|
|
198
171
|
}
|
|
199
|
-
|
|
200
172
|
this._active.set(targetActor, deferred);
|
|
201
173
|
}
|
|
202
|
-
|
|
203
174
|
_handleMessage(rdpData) {
|
|
204
175
|
if (rdpData.from == null) {
|
|
205
176
|
if (rdpData.error) {
|
|
206
177
|
this.emit('rdp-error', rdpData);
|
|
207
178
|
return;
|
|
208
179
|
}
|
|
209
|
-
|
|
210
180
|
this.emit('error', new Error(`Received an RDP message without a sender actor: ${JSON.stringify(rdpData)}`));
|
|
211
181
|
return;
|
|
212
182
|
}
|
|
213
|
-
|
|
214
183
|
if (UNSOLICITED_EVENTS.has(rdpData.type)) {
|
|
215
184
|
this.emit('unsolicited-event', rdpData);
|
|
216
185
|
return;
|
|
217
186
|
}
|
|
218
|
-
|
|
219
187
|
if (this._active.has(rdpData.from)) {
|
|
220
188
|
const deferred = this._active.get(rdpData.from);
|
|
221
|
-
|
|
222
189
|
this._active.delete(rdpData.from);
|
|
223
|
-
|
|
224
190
|
if (rdpData.error) {
|
|
225
191
|
deferred === null || deferred === void 0 ? void 0 : deferred.reject(rdpData);
|
|
226
192
|
} else {
|
|
227
193
|
deferred === null || deferred === void 0 ? void 0 : deferred.resolve(rdpData);
|
|
228
194
|
}
|
|
229
|
-
|
|
230
195
|
this._flushPendingRequests();
|
|
231
|
-
|
|
232
196
|
return;
|
|
233
197
|
}
|
|
234
|
-
|
|
235
198
|
this.emit('error', new Error(`Unexpected RDP message received: ${JSON.stringify(rdpData)}`));
|
|
236
199
|
}
|
|
237
|
-
|
|
238
200
|
_readMessage() {
|
|
239
201
|
const {
|
|
240
202
|
data,
|
|
@@ -243,50 +205,40 @@ export default class FirefoxRDPClient extends EventEmitter {
|
|
|
243
205
|
fatal
|
|
244
206
|
} = parseRDPMessage(this._incoming);
|
|
245
207
|
this._incoming = data;
|
|
246
|
-
|
|
247
208
|
if (error) {
|
|
248
|
-
this.emit('error', new Error(`Error parsing RDP packet: ${String(error)}`));
|
|
249
|
-
|
|
209
|
+
this.emit('error', new Error(`Error parsing RDP packet: ${String(error)}`));
|
|
210
|
+
// Disconnect automatically on a fatal error.
|
|
250
211
|
if (fatal) {
|
|
251
212
|
this.disconnect();
|
|
252
|
-
}
|
|
213
|
+
}
|
|
214
|
+
// Caller can parse the next message if the error wasn't fatal
|
|
253
215
|
// (e.g. the RDP packet that couldn't be parsed has been already
|
|
254
216
|
// removed from the incoming data buffer).
|
|
255
|
-
|
|
256
|
-
|
|
257
217
|
return !fatal;
|
|
258
218
|
}
|
|
259
|
-
|
|
260
219
|
if (!rdpMessage) {
|
|
261
220
|
// Caller will need to wait more data to parse the next message.
|
|
262
221
|
return false;
|
|
263
222
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
223
|
+
this._handleMessage(rdpMessage);
|
|
224
|
+
// Caller can try to parse the next message from the remining data.
|
|
268
225
|
return true;
|
|
269
226
|
}
|
|
270
|
-
|
|
271
227
|
onData(data) {
|
|
272
228
|
this._incoming = Buffer.concat([this._incoming, data]);
|
|
273
|
-
|
|
274
|
-
|
|
229
|
+
while (this._readMessage()) {
|
|
230
|
+
// Keep parsing and handling messages until readMessage
|
|
275
231
|
// returns false.
|
|
276
232
|
}
|
|
277
233
|
}
|
|
278
|
-
|
|
279
234
|
onError(error) {
|
|
280
235
|
this.emit('error', error);
|
|
281
236
|
}
|
|
282
|
-
|
|
283
237
|
onEnd() {
|
|
284
238
|
this.emit('end');
|
|
285
239
|
}
|
|
286
|
-
|
|
287
240
|
onTimeout() {
|
|
288
241
|
this.emit('timeout');
|
|
289
242
|
}
|
|
290
|
-
|
|
291
243
|
}
|
|
292
244
|
//# sourceMappingURL=rdp-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rdp-client.js","names":["net","EventEmitter","domain","DEFAULT_PORT","DEFAULT_HOST","UNSOLICITED_EVENTS","Set","parseRDPMessage","data","str","toString","sepIdx","indexOf","byteLen","parseInt","slice","isNaN","error","Error","fatal","length","msg","rdpMessage","JSON","parse","connectToFirefox","port","client","FirefoxRDPClient","connect","then","constructor","_incoming","Buffer","alloc","_pending","_active","Map","_onData","args","onData","_onError","onError","_onEnd","onEnd","_onTimeout","onTimeout","Promise","resolve","reject","d","create","once","run","conn","createConnection","host","_rdpConnection","on","_expectReply","disconnect","off","end","_rejectAllRequests","activeDeferred","values","clear","deferred","request","requestProps","to","type","push","_flushPendingRequests","filter","has","stringify","from","write","err","targetActor","set","_handleMessage","rdpData","emit","get","delete","_readMessage","String","concat"],"sources":["../../src/firefox/rdp-client.js"],"sourcesContent":["/* @flow */\nimport net from 'net';\nimport EventEmitter from 'events';\nimport domain from 'domain';\n\nexport type RDPRequest = {\n to: string,\n type: string,\n}\n\nexport type RDPResult = {\n from: string,\n type: string,\n}\n\nexport type Deferred = {|\n resolve: Function,\n reject: Function,\n|}\n\ntype ParseResult = {|\n data: Buffer,\n rdpMessage?: Object,\n error?: Error,\n fatal?: boolean,\n|}\n\nexport const DEFAULT_PORT = 6000;\nexport const DEFAULT_HOST = '127.0.0.1';\n\nconst UNSOLICITED_EVENTS = new Set([\n 'tabNavigated',\n 'styleApplied',\n 'propertyChange',\n 'networkEventUpdate',\n 'networkEvent',\n 'propertyChange',\n 'newMutations',\n 'frameUpdate',\n 'tabListChanged',\n]);\n\n// Parse RDP packets: BYTE_LENGTH + ':' + DATA.\nexport function parseRDPMessage(data: Buffer): ParseResult {\n const str = data.toString();\n const sepIdx = str.indexOf(':');\n if (sepIdx < 1) {\n return {data};\n }\n\n const byteLen = parseInt(str.slice(0, sepIdx));\n if (isNaN(byteLen)) {\n const error = new Error('Error parsing RDP message length');\n return {data, error, fatal: true};\n }\n\n if (data.length - (sepIdx + 1) < byteLen) {\n // Can't parse yet, will retry once more data has been received.\n return {data};\n }\n\n data = data.slice(sepIdx + 1);\n const msg = data.slice(0, byteLen);\n data = data.slice(byteLen);\n\n try {\n return {data, rdpMessage: JSON.parse(msg.toString())};\n } catch (error) {\n return {data, error, fatal: false};\n }\n}\n\nexport function connectToFirefox(port: number): Promise<FirefoxRDPClient> {\n const client = new FirefoxRDPClient();\n return client.connect(port).then(() => client);\n}\n\nexport default class FirefoxRDPClient extends EventEmitter {\n _incoming: Buffer;\n _pending: Array<{| request: RDPRequest, deferred: Deferred |}>;\n _active: Map<string, Deferred>;\n _rdpConnection: net.Socket;\n _onData: Function;\n _onError: Function;\n _onEnd: Function;\n _onTimeout: Function;\n\n constructor() {\n super();\n this._incoming = Buffer.alloc(0);\n this._pending = [];\n this._active = new Map();\n\n this._onData = (...args) => this.onData(...args);\n this._onError = (...args) => this.onError(...args);\n this._onEnd = (...args) => this.onEnd(...args);\n this._onTimeout = (...args) => this.onTimeout(...args);\n }\n\n connect(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n // Create a domain to wrap the errors that may be triggered\n // by creating the client connection (e.g. ECONNREFUSED)\n // so that we can reject the promise returned instead of\n // exiting the entire process.\n const d = domain.create();\n d.once('error', reject);\n d.run(() => {\n const conn = net.createConnection({\n port,\n host: DEFAULT_HOST,\n });\n\n this._rdpConnection = conn;\n conn.on('data', this._onData);\n conn.on('error', this._onError);\n conn.on('end', this._onEnd);\n conn.on('timeout', this._onTimeout);\n\n // Resolve once the expected initial root message\n // has been received.\n this._expectReply('root', {resolve, reject});\n });\n });\n }\n\n disconnect(): void {\n if (!this._rdpConnection) {\n return;\n }\n\n const conn = this._rdpConnection;\n conn.off('data', this._onData);\n conn.off('error', this._onError);\n conn.off('end', this._onEnd);\n conn.off('timeout', this._onTimeout);\n conn.end();\n\n this._rejectAllRequests(new Error('RDP connection closed'));\n }\n\n _rejectAllRequests(error: Error) {\n for (const activeDeferred of this._active.values()) {\n activeDeferred.reject(error);\n }\n this._active.clear();\n\n for (const {deferred} of this._pending) {\n deferred.reject(error);\n }\n this._pending = [];\n }\n\n async request(requestProps: string | RDPRequest): Promise<RDPResult> {\n let request: RDPRequest;\n\n if (typeof requestProps === 'string') {\n request = {to: 'root', type: requestProps};\n } else {\n request = requestProps;\n }\n\n if (request.to == null) {\n throw new Error(\n `Unexpected RDP request without target actor: ${request.type}`\n );\n }\n\n return new Promise((resolve, reject) => {\n const deferred = {resolve, reject};\n this._pending.push({request, deferred});\n this._flushPendingRequests();\n });\n }\n\n _flushPendingRequests(): void {\n this._pending = this._pending.filter(({request, deferred}) => {\n if (this._active.has(request.to)) {\n // Keep in the pending requests until there are no requests\n // active on the target RDP actor.\n return true;\n }\n\n const conn = this._rdpConnection;\n if (!conn) {\n throw new Error('RDP connection closed');\n }\n\n try {\n let str = JSON.stringify(request);\n str = `${Buffer.from(str).length}:${str}`;\n conn.write(str);\n this._expectReply(request.to, deferred);\n } catch (err) {\n deferred.reject(err);\n }\n\n // Remove the pending request from the queue.\n return false;\n });\n }\n\n _expectReply(targetActor: string, deferred: Deferred): void {\n if (this._active.has(targetActor)) {\n throw new Error(`${targetActor} does already have an active request`);\n }\n\n this._active.set(targetActor, deferred);\n }\n\n _handleMessage(rdpData: Object): void {\n if (rdpData.from == null) {\n if (rdpData.error) {\n this.emit('rdp-error', rdpData);\n return;\n }\n\n this.emit('error', new Error(\n `Received an RDP message without a sender actor: ${\n JSON.stringify(rdpData)\n }`\n ));\n return;\n }\n\n if (UNSOLICITED_EVENTS.has(rdpData.type)) {\n this.emit('unsolicited-event', rdpData);\n return;\n }\n\n if (this._active.has(rdpData.from)) {\n const deferred = this._active.get(rdpData.from);\n this._active.delete(rdpData.from);\n if (rdpData.error) {\n deferred?.reject(rdpData);\n } else {\n deferred?.resolve(rdpData);\n }\n this._flushPendingRequests();\n return;\n }\n\n this.emit('error', new Error(\n `Unexpected RDP message received: ${JSON.stringify(rdpData)}`\n ));\n }\n\n _readMessage(): boolean {\n const {\n data, rdpMessage, error, fatal,\n } = parseRDPMessage(this._incoming);\n\n this._incoming = data;\n\n if (error) {\n this.emit(\n 'error',\n new Error(`Error parsing RDP packet: ${String(error)}`)\n );\n // Disconnect automatically on a fatal error.\n if (fatal) {\n this.disconnect();\n }\n // Caller can parse the next message if the error wasn't fatal\n // (e.g. the RDP packet that couldn't be parsed has been already\n // removed from the incoming data buffer).\n return !fatal;\n }\n\n if (!rdpMessage) {\n // Caller will need to wait more data to parse the next message.\n return false;\n }\n\n this._handleMessage(rdpMessage);\n // Caller can try to parse the next message from the remining data.\n return true;\n }\n\n onData(data: Buffer) {\n this._incoming = Buffer.concat([this._incoming, data]);\n while (this._readMessage()) {\n // Keep parsing and handling messages until readMessage\n // returns false.\n }\n }\n\n onError(error: Error) {\n this.emit('error', error);\n }\n\n onEnd() {\n this.emit('end');\n }\n\n onTimeout() {\n this.emit('timeout');\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rdp-client.js","names":["net","EventEmitter","domain","DEFAULT_PORT","DEFAULT_HOST","UNSOLICITED_EVENTS","Set","parseRDPMessage","data","str","toString","sepIdx","indexOf","byteLen","parseInt","slice","isNaN","error","Error","fatal","length","msg","rdpMessage","JSON","parse","connectToFirefox","port","client","FirefoxRDPClient","connect","then","constructor","_incoming","Buffer","alloc","_pending","_active","Map","_onData","args","onData","_onError","onError","_onEnd","onEnd","_onTimeout","onTimeout","Promise","resolve","reject","d","create","once","run","conn","createConnection","host","_rdpConnection","on","_expectReply","disconnect","off","end","_rejectAllRequests","activeDeferred","values","clear","deferred","request","requestProps","to","type","push","_flushPendingRequests","filter","has","stringify","from","write","err","targetActor","set","_handleMessage","rdpData","emit","get","delete","_readMessage","String","concat"],"sources":["../../src/firefox/rdp-client.js"],"sourcesContent":["/* @flow */\nimport net from 'net';\nimport EventEmitter from 'events';\nimport domain from 'domain';\n\nexport type RDPRequest = {\n to: string,\n type: string,\n}\n\nexport type RDPResult = {\n from: string,\n type: string,\n}\n\nexport type Deferred = {|\n resolve: Function,\n reject: Function,\n|}\n\ntype ParseResult = {|\n data: Buffer,\n rdpMessage?: Object,\n error?: Error,\n fatal?: boolean,\n|}\n\nexport const DEFAULT_PORT = 6000;\nexport const DEFAULT_HOST = '127.0.0.1';\n\nconst UNSOLICITED_EVENTS = new Set([\n 'tabNavigated',\n 'styleApplied',\n 'propertyChange',\n 'networkEventUpdate',\n 'networkEvent',\n 'propertyChange',\n 'newMutations',\n 'frameUpdate',\n 'tabListChanged',\n]);\n\n// Parse RDP packets: BYTE_LENGTH + ':' + DATA.\nexport function parseRDPMessage(data: Buffer): ParseResult {\n const str = data.toString();\n const sepIdx = str.indexOf(':');\n if (sepIdx < 1) {\n return {data};\n }\n\n const byteLen = parseInt(str.slice(0, sepIdx));\n if (isNaN(byteLen)) {\n const error = new Error('Error parsing RDP message length');\n return {data, error, fatal: true};\n }\n\n if (data.length - (sepIdx + 1) < byteLen) {\n // Can't parse yet, will retry once more data has been received.\n return {data};\n }\n\n data = data.slice(sepIdx + 1);\n const msg = data.slice(0, byteLen);\n data = data.slice(byteLen);\n\n try {\n return {data, rdpMessage: JSON.parse(msg.toString())};\n } catch (error) {\n return {data, error, fatal: false};\n }\n}\n\nexport function connectToFirefox(port: number): Promise<FirefoxRDPClient> {\n const client = new FirefoxRDPClient();\n return client.connect(port).then(() => client);\n}\n\nexport default class FirefoxRDPClient extends EventEmitter {\n _incoming: Buffer;\n _pending: Array<{| request: RDPRequest, deferred: Deferred |}>;\n _active: Map<string, Deferred>;\n _rdpConnection: net.Socket;\n _onData: Function;\n _onError: Function;\n _onEnd: Function;\n _onTimeout: Function;\n\n constructor() {\n super();\n this._incoming = Buffer.alloc(0);\n this._pending = [];\n this._active = new Map();\n\n this._onData = (...args) => this.onData(...args);\n this._onError = (...args) => this.onError(...args);\n this._onEnd = (...args) => this.onEnd(...args);\n this._onTimeout = (...args) => this.onTimeout(...args);\n }\n\n connect(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n // Create a domain to wrap the errors that may be triggered\n // by creating the client connection (e.g. ECONNREFUSED)\n // so that we can reject the promise returned instead of\n // exiting the entire process.\n const d = domain.create();\n d.once('error', reject);\n d.run(() => {\n const conn = net.createConnection({\n port,\n host: DEFAULT_HOST,\n });\n\n this._rdpConnection = conn;\n conn.on('data', this._onData);\n conn.on('error', this._onError);\n conn.on('end', this._onEnd);\n conn.on('timeout', this._onTimeout);\n\n // Resolve once the expected initial root message\n // has been received.\n this._expectReply('root', {resolve, reject});\n });\n });\n }\n\n disconnect(): void {\n if (!this._rdpConnection) {\n return;\n }\n\n const conn = this._rdpConnection;\n conn.off('data', this._onData);\n conn.off('error', this._onError);\n conn.off('end', this._onEnd);\n conn.off('timeout', this._onTimeout);\n conn.end();\n\n this._rejectAllRequests(new Error('RDP connection closed'));\n }\n\n _rejectAllRequests(error: Error) {\n for (const activeDeferred of this._active.values()) {\n activeDeferred.reject(error);\n }\n this._active.clear();\n\n for (const {deferred} of this._pending) {\n deferred.reject(error);\n }\n this._pending = [];\n }\n\n async request(requestProps: string | RDPRequest): Promise<RDPResult> {\n let request: RDPRequest;\n\n if (typeof requestProps === 'string') {\n request = {to: 'root', type: requestProps};\n } else {\n request = requestProps;\n }\n\n if (request.to == null) {\n throw new Error(\n `Unexpected RDP request without target actor: ${request.type}`\n );\n }\n\n return new Promise((resolve, reject) => {\n const deferred = {resolve, reject};\n this._pending.push({request, deferred});\n this._flushPendingRequests();\n });\n }\n\n _flushPendingRequests(): void {\n this._pending = this._pending.filter(({request, deferred}) => {\n if (this._active.has(request.to)) {\n // Keep in the pending requests until there are no requests\n // active on the target RDP actor.\n return true;\n }\n\n const conn = this._rdpConnection;\n if (!conn) {\n throw new Error('RDP connection closed');\n }\n\n try {\n let str = JSON.stringify(request);\n str = `${Buffer.from(str).length}:${str}`;\n conn.write(str);\n this._expectReply(request.to, deferred);\n } catch (err) {\n deferred.reject(err);\n }\n\n // Remove the pending request from the queue.\n return false;\n });\n }\n\n _expectReply(targetActor: string, deferred: Deferred): void {\n if (this._active.has(targetActor)) {\n throw new Error(`${targetActor} does already have an active request`);\n }\n\n this._active.set(targetActor, deferred);\n }\n\n _handleMessage(rdpData: Object): void {\n if (rdpData.from == null) {\n if (rdpData.error) {\n this.emit('rdp-error', rdpData);\n return;\n }\n\n this.emit('error', new Error(\n `Received an RDP message without a sender actor: ${\n JSON.stringify(rdpData)\n }`\n ));\n return;\n }\n\n if (UNSOLICITED_EVENTS.has(rdpData.type)) {\n this.emit('unsolicited-event', rdpData);\n return;\n }\n\n if (this._active.has(rdpData.from)) {\n const deferred = this._active.get(rdpData.from);\n this._active.delete(rdpData.from);\n if (rdpData.error) {\n deferred?.reject(rdpData);\n } else {\n deferred?.resolve(rdpData);\n }\n this._flushPendingRequests();\n return;\n }\n\n this.emit('error', new Error(\n `Unexpected RDP message received: ${JSON.stringify(rdpData)}`\n ));\n }\n\n _readMessage(): boolean {\n const {\n data, rdpMessage, error, fatal,\n } = parseRDPMessage(this._incoming);\n\n this._incoming = data;\n\n if (error) {\n this.emit(\n 'error',\n new Error(`Error parsing RDP packet: ${String(error)}`)\n );\n // Disconnect automatically on a fatal error.\n if (fatal) {\n this.disconnect();\n }\n // Caller can parse the next message if the error wasn't fatal\n // (e.g. the RDP packet that couldn't be parsed has been already\n // removed from the incoming data buffer).\n return !fatal;\n }\n\n if (!rdpMessage) {\n // Caller will need to wait more data to parse the next message.\n return false;\n }\n\n this._handleMessage(rdpMessage);\n // Caller can try to parse the next message from the remining data.\n return true;\n }\n\n onData(data: Buffer) {\n this._incoming = Buffer.concat([this._incoming, data]);\n while (this._readMessage()) {\n // Keep parsing and handling messages until readMessage\n // returns false.\n }\n }\n\n onError(error: Error) {\n this.emit('error', error);\n }\n\n onEnd() {\n this.emit('end');\n }\n\n onTimeout() {\n this.emit('timeout');\n }\n}\n"],"mappings":"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"}
|
package/lib/firefox/remote.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
+
|
|
1
2
|
import net from 'net';
|
|
2
3
|
import FirefoxRDPClient, { connectToFirefox as defaultFirefoxConnector } from './rdp-client.js';
|
|
3
4
|
import { createLogger } from '../util/logger.js';
|
|
4
5
|
import { isErrorWithCode, RemoteTempInstallNotSupported, UsageError, WebExtError } from '../errors.js';
|
|
5
6
|
const log = createLogger(import.meta.url);
|
|
6
|
-
|
|
7
7
|
// Convert a request rejection to a message string.
|
|
8
8
|
function requestErrorToMessage(err) {
|
|
9
9
|
if (err instanceof Error) {
|
|
10
10
|
return String(err);
|
|
11
11
|
}
|
|
12
|
-
|
|
13
12
|
return `${err.error}: ${err.message}`;
|
|
14
13
|
}
|
|
15
|
-
|
|
16
14
|
export class RemoteFirefox {
|
|
17
15
|
constructor(client) {
|
|
18
16
|
this.client = client;
|
|
@@ -33,11 +31,9 @@ export class RemoteFirefox {
|
|
|
33
31
|
log.debug(`Received error from client: ${String(error)}`);
|
|
34
32
|
});
|
|
35
33
|
}
|
|
36
|
-
|
|
37
34
|
disconnect() {
|
|
38
35
|
this.client.disconnect();
|
|
39
36
|
}
|
|
40
|
-
|
|
41
37
|
async addonRequest(addon, request) {
|
|
42
38
|
try {
|
|
43
39
|
const response = await this.client.request({
|
|
@@ -51,30 +47,25 @@ export class RemoteFirefox {
|
|
|
51
47
|
throw new WebExtError(`Remote Firefox: addonRequest() error: ${message}`);
|
|
52
48
|
}
|
|
53
49
|
}
|
|
54
|
-
|
|
55
50
|
async getAddonsActor() {
|
|
56
51
|
try {
|
|
57
52
|
// getRoot should work since Firefox 55 (bug 1352157).
|
|
58
53
|
const response = await this.client.request('getRoot');
|
|
59
|
-
|
|
60
54
|
if (response.addonsActor == null) {
|
|
61
55
|
return Promise.reject(new RemoteTempInstallNotSupported('This version of Firefox does not provide an add-ons actor for ' + 'remote installation.'));
|
|
62
56
|
}
|
|
63
|
-
|
|
64
57
|
return response.addonsActor;
|
|
65
58
|
} catch (err) {
|
|
66
59
|
// Fallback to listTabs otherwise, Firefox 49 - 77 (bug 1618691).
|
|
67
60
|
log.debug('Falling back to listTabs because getRoot failed', err);
|
|
68
61
|
}
|
|
69
|
-
|
|
70
62
|
try {
|
|
71
|
-
const response = await this.client.request('listTabs');
|
|
72
|
-
|
|
63
|
+
const response = await this.client.request('listTabs');
|
|
64
|
+
// addonsActor was added to listTabs in Firefox 49 (bug 1273183).
|
|
73
65
|
if (response.addonsActor == null) {
|
|
74
66
|
log.debug('listTabs returned a falsey addonsActor: ' + `${JSON.stringify(response)}`);
|
|
75
67
|
return Promise.reject(new RemoteTempInstallNotSupported('This is an older version of Firefox that does not provide an ' + 'add-ons actor for remote installation. Try Firefox 49 or ' + 'higher.'));
|
|
76
68
|
}
|
|
77
|
-
|
|
78
69
|
return response.addonsActor;
|
|
79
70
|
} catch (err) {
|
|
80
71
|
log.debug('listTabs error', err);
|
|
@@ -82,15 +73,14 @@ export class RemoteFirefox {
|
|
|
82
73
|
throw new WebExtError(`Remote Firefox: listTabs() error: ${message}`);
|
|
83
74
|
}
|
|
84
75
|
}
|
|
85
|
-
|
|
86
|
-
async installTemporaryAddon(addonPath) {
|
|
76
|
+
async installTemporaryAddon(addonPath, openDevTools) {
|
|
87
77
|
const addonsActor = await this.getAddonsActor();
|
|
88
|
-
|
|
89
78
|
try {
|
|
90
79
|
const response = await this.client.request({
|
|
91
80
|
to: addonsActor,
|
|
92
81
|
type: 'installTemporaryAddon',
|
|
93
|
-
addonPath
|
|
82
|
+
addonPath,
|
|
83
|
+
openDevTools
|
|
94
84
|
});
|
|
95
85
|
log.debug(`installTemporaryAddon: ${JSON.stringify(response)}`);
|
|
96
86
|
log.info(`Installed ${addonPath} as a temporary add-on`);
|
|
@@ -100,17 +90,14 @@ export class RemoteFirefox {
|
|
|
100
90
|
throw new WebExtError(`installTemporaryAddon: Error: ${message}`);
|
|
101
91
|
}
|
|
102
92
|
}
|
|
103
|
-
|
|
104
93
|
async getInstalledAddon(addonId) {
|
|
105
94
|
try {
|
|
106
95
|
const response = await this.client.request('listAddons');
|
|
107
|
-
|
|
108
96
|
for (const addon of response.addons) {
|
|
109
97
|
if (addon.id === addonId) {
|
|
110
98
|
return addon;
|
|
111
99
|
}
|
|
112
100
|
}
|
|
113
|
-
|
|
114
101
|
log.debug(`Remote Firefox has these addons: ${response.addons.map(a => a.id)}`);
|
|
115
102
|
return Promise.reject(new WebExtError('The remote Firefox does not have your extension installed'));
|
|
116
103
|
} catch (err) {
|
|
@@ -118,14 +105,12 @@ export class RemoteFirefox {
|
|
|
118
105
|
throw new WebExtError(`Remote Firefox: listAddons() error: ${message}`);
|
|
119
106
|
}
|
|
120
107
|
}
|
|
121
|
-
|
|
122
108
|
async checkForAddonReloading(addon) {
|
|
123
109
|
if (this.checkedForAddonReloading) {
|
|
124
110
|
// We only need to check once if reload() is supported.
|
|
125
111
|
return addon;
|
|
126
112
|
} else {
|
|
127
113
|
const response = await this.addonRequest(addon, 'requestTypes');
|
|
128
|
-
|
|
129
114
|
if (response.requestTypes.indexOf('reload') === -1) {
|
|
130
115
|
const supportedRequestTypes = JSON.stringify(response.requestTypes);
|
|
131
116
|
log.debug(`Remote Firefox only supports: ${supportedRequestTypes}`);
|
|
@@ -136,7 +121,6 @@ export class RemoteFirefox {
|
|
|
136
121
|
}
|
|
137
122
|
}
|
|
138
123
|
}
|
|
139
|
-
|
|
140
124
|
async reloadAddon(addonId) {
|
|
141
125
|
const addon = await this.getInstalledAddon(addonId);
|
|
142
126
|
await this.checkForAddonReloading(addon);
|
|
@@ -144,8 +128,9 @@ export class RemoteFirefox {
|
|
|
144
128
|
process.stdout.write(`\rLast extension reload: ${new Date().toTimeString()}`);
|
|
145
129
|
log.debug('\n');
|
|
146
130
|
}
|
|
131
|
+
}
|
|
147
132
|
|
|
148
|
-
|
|
133
|
+
// Connect types and implementation
|
|
149
134
|
|
|
150
135
|
export async function connect(port, {
|
|
151
136
|
connectToFirefox = defaultFirefoxConnector
|
|
@@ -154,9 +139,12 @@ export async function connect(port, {
|
|
|
154
139
|
const client = await connectToFirefox(port);
|
|
155
140
|
log.debug(`Connected to the remote Firefox debugger on port ${port}`);
|
|
156
141
|
return new RemoteFirefox(client);
|
|
157
|
-
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ConnectWithMaxRetries types and implementation
|
|
158
145
|
|
|
159
|
-
export async function connectWithMaxRetries(
|
|
146
|
+
export async function connectWithMaxRetries(
|
|
147
|
+
// A max of 250 will try connecting for 30 seconds.
|
|
160
148
|
{
|
|
161
149
|
maxRetries = 250,
|
|
162
150
|
retryInterval = 120,
|
|
@@ -166,7 +154,6 @@ export async function connectWithMaxRetries( // A max of 250 will try connecting
|
|
|
166
154
|
} = {}) {
|
|
167
155
|
async function establishConnection() {
|
|
168
156
|
var lastError;
|
|
169
|
-
|
|
170
157
|
for (let retries = 0; retries <= maxRetries; retries++) {
|
|
171
158
|
try {
|
|
172
159
|
return await connectToFirefox(port);
|
|
@@ -184,18 +171,16 @@ export async function connectWithMaxRetries( // A max of 250 will try connecting
|
|
|
184
171
|
}
|
|
185
172
|
}
|
|
186
173
|
}
|
|
187
|
-
|
|
188
174
|
log.debug('Connect to Firefox debugger: too many retries');
|
|
189
175
|
throw lastError;
|
|
190
176
|
}
|
|
191
|
-
|
|
192
177
|
log.debug('Connecting to the remote Firefox debugger');
|
|
193
178
|
return establishConnection();
|
|
194
179
|
}
|
|
195
180
|
export function findFreeTcpPort() {
|
|
196
181
|
return new Promise(resolve => {
|
|
197
|
-
const srv = net.createServer();
|
|
198
|
-
|
|
182
|
+
const srv = net.createServer();
|
|
183
|
+
// $FlowFixMe: signature for listen() is missing - see https://github.com/facebook/flow/pull/8290
|
|
199
184
|
srv.listen(0, '127.0.0.1', () => {
|
|
200
185
|
const freeTcpPort = srv.address().port;
|
|
201
186
|
srv.close(() => resolve(freeTcpPort));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote.js","names":["net","FirefoxRDPClient","connectToFirefox","defaultFirefoxConnector","createLogger","isErrorWithCode","RemoteTempInstallNotSupported","UsageError","WebExtError","log","import","meta","url","requestErrorToMessage","err","Error","String","error","message","RemoteFirefox","constructor","client","checkedForAddonReloading","on","debug","info","JSON","stringify","rdpError","disconnect","addonRequest","addon","request","response","to","actor","type","getAddonsActor","addonsActor","Promise","reject","installTemporaryAddon","addonPath","getInstalledAddon","addonId","addons","id","map","a","checkForAddonReloading","requestTypes","indexOf","supportedRequestTypes","reloadAddon","process","stdout","write","Date","toTimeString","connect","port","connectWithMaxRetries","maxRetries","retryInterval","establishConnection","lastError","retries","resolve","setTimeout","stack","findFreeTcpPort","srv","createServer","listen","freeTcpPort","address","close"],"sources":["../../src/firefox/remote.js"],"sourcesContent":["/* @flow */\nimport net from 'net';\n\nimport FirefoxRDPClient, {\n connectToFirefox as defaultFirefoxConnector,\n} from './rdp-client.js';\nimport {createLogger} from '../util/logger.js';\nimport {\n isErrorWithCode,\n RemoteTempInstallNotSupported,\n UsageError,\n WebExtError,\n} from '../errors.js';\n\nconst log = createLogger(import.meta.url);\n\nexport type FirefoxConnectorFn =\n (port: number) => Promise<FirefoxRDPClient>;\n\nexport type FirefoxRDPAddonActor = {|\n id: string,\n actor: string,\n|};\n\nexport type FirefoxRDPResponseError = {|\n error: string,\n message: string,\n|};\n\nexport type FirefoxRDPResponseAddon = {|\n addon: FirefoxRDPAddonActor,\n|};\n\nexport type FirefoxRDPResponseRequestTypes = {|\n requestTypes: Array<string>,\n|};\n\n// NOTE: this type aliases Object to catch any other possible response.\nexport type FirefoxRDPResponseAny = Object;\n\nexport type FirefoxRDPResponseMaybe =\n FirefoxRDPResponseRequestTypes | FirefoxRDPResponseAny;\n\n// Convert a request rejection to a message string.\nfunction requestErrorToMessage(err: Error | FirefoxRDPResponseError) {\n if (err instanceof Error) {\n return String(err);\n }\n return `${err.error}: ${err.message}`;\n}\n\nexport class RemoteFirefox {\n client: Object;\n checkedForAddonReloading: boolean;\n\n constructor(client: FirefoxRDPClient) {\n this.client = client;\n this.checkedForAddonReloading = false;\n\n client.on('disconnect', () => {\n log.debug('Received \"disconnect\" from Firefox client');\n });\n client.on('end', () => {\n log.debug('Received \"end\" from Firefox client');\n });\n client.on('unsolicited-event', (info) => {\n log.debug(`Received message from client: ${JSON.stringify(info)}`);\n });\n client.on('rdp-error', (rdpError) => {\n log.debug(`Received error from client: ${JSON.stringify(rdpError)}`);\n });\n client.on('error', (error) => {\n log.debug(`Received error from client: ${String(error)}`);\n });\n }\n\n disconnect() {\n this.client.disconnect();\n }\n\n async addonRequest(\n addon: FirefoxRDPAddonActor,\n request: string\n ): Promise<FirefoxRDPResponseMaybe> {\n try {\n const response = await this.client.request({\n to: addon.actor, type: request,\n });\n return response;\n } catch (err) {\n log.debug(\n `Client responded to '${request}' request with error:`, err);\n const message = requestErrorToMessage(err);\n throw new WebExtError(`Remote Firefox: addonRequest() error: ${message}`);\n }\n }\n\n async getAddonsActor(): Promise<string> {\n try {\n // getRoot should work since Firefox 55 (bug 1352157).\n const response = await this.client.request('getRoot');\n if (response.addonsActor == null) {\n return Promise.reject(new RemoteTempInstallNotSupported(\n 'This version of Firefox does not provide an add-ons actor for ' +\n 'remote installation.'));\n }\n return response.addonsActor;\n } catch (err) {\n // Fallback to listTabs otherwise, Firefox 49 - 77 (bug 1618691).\n log.debug('Falling back to listTabs because getRoot failed', err);\n }\n\n try {\n const response = await this.client.request('listTabs');\n // addonsActor was added to listTabs in Firefox 49 (bug 1273183).\n if (response.addonsActor == null) {\n log.debug(\n 'listTabs returned a falsey addonsActor: ' +\n `${JSON.stringify(response)}`);\n return Promise.reject(new RemoteTempInstallNotSupported(\n 'This is an older version of Firefox that does not provide an ' +\n 'add-ons actor for remote installation. Try Firefox 49 or ' +\n 'higher.'));\n }\n return response.addonsActor;\n } catch (err) {\n log.debug('listTabs error', err);\n const message = requestErrorToMessage(err);\n throw new WebExtError(`Remote Firefox: listTabs() error: ${message}`);\n }\n }\n\n async installTemporaryAddon(\n addonPath: string\n ): Promise<FirefoxRDPResponseAddon> {\n const addonsActor = await this.getAddonsActor();\n\n try {\n const response = await this.client.request({\n to: addonsActor,\n type: 'installTemporaryAddon',\n addonPath,\n });\n log.debug(`installTemporaryAddon: ${JSON.stringify(response)}`);\n log.info(`Installed ${addonPath} as a temporary add-on`);\n return response;\n } catch (err) {\n const message = requestErrorToMessage(err);\n throw new WebExtError(`installTemporaryAddon: Error: ${message}`);\n }\n }\n\n async getInstalledAddon(addonId: string): Promise<FirefoxRDPAddonActor> {\n try {\n const response = await this.client.request('listAddons');\n for (const addon of response.addons) {\n if (addon.id === addonId) {\n return addon;\n }\n }\n log.debug(\n `Remote Firefox has these addons: ${response.addons.map((a) => a.id)}`);\n return Promise.reject(new WebExtError(\n 'The remote Firefox does not have your extension installed'));\n } catch (err) {\n const message = requestErrorToMessage(err);\n throw new WebExtError(`Remote Firefox: listAddons() error: ${message}`);\n }\n }\n\n async checkForAddonReloading(\n addon: FirefoxRDPAddonActor\n ): Promise<FirefoxRDPAddonActor> {\n if (this.checkedForAddonReloading) {\n // We only need to check once if reload() is supported.\n return addon;\n } else {\n const response = await this.addonRequest(addon, 'requestTypes');\n\n if (response.requestTypes.indexOf('reload') === -1) {\n const supportedRequestTypes = JSON.stringify(response.requestTypes);\n log.debug(\n `Remote Firefox only supports: ${supportedRequestTypes}`);\n throw new UsageError(\n 'This Firefox version does not support add-on reloading. ' +\n 'Re-run with --no-reload');\n } else {\n this.checkedForAddonReloading = true;\n return addon;\n }\n }\n }\n\n async reloadAddon(addonId: string): Promise<void> {\n const addon = await this.getInstalledAddon(addonId);\n await this.checkForAddonReloading(addon);\n await this.addonRequest(addon, 'reload');\n process.stdout.write(\n `\\rLast extension reload: ${(new Date()).toTimeString()}`);\n log.debug('\\n');\n }\n}\n\n\n// Connect types and implementation\n\nexport type ConnectOptions = {\n connectToFirefox: FirefoxConnectorFn,\n};\n\nexport async function connect(\n port: number,\n {connectToFirefox = defaultFirefoxConnector}: ConnectOptions = {}\n): Promise<RemoteFirefox> {\n log.debug(`Connecting to Firefox on port ${port}`);\n const client = await connectToFirefox(port);\n log.debug(`Connected to the remote Firefox debugger on port ${port}`);\n return new RemoteFirefox(client);\n}\n\n\n// ConnectWithMaxRetries types and implementation\n\nexport type ConnectWithMaxRetriesParams = {|\n maxRetries?: number,\n retryInterval?: number,\n port: number,\n|};\n\nexport type ConnectWithMaxRetriesDeps = {\n connectToFirefox: typeof connect,\n};\n\nexport async function connectWithMaxRetries(\n // A max of 250 will try connecting for 30 seconds.\n {maxRetries = 250, retryInterval = 120, port}: ConnectWithMaxRetriesParams,\n {connectToFirefox = connect}: ConnectWithMaxRetriesDeps = {}\n): Promise<RemoteFirefox> {\n async function establishConnection() {\n var lastError;\n\n for (let retries = 0; retries <= maxRetries; retries++) {\n try {\n return await connectToFirefox(port);\n } catch (error) {\n if (isErrorWithCode('ECONNREFUSED', error)) {\n // Wait for `retryInterval` ms.\n await new Promise((resolve) => {\n setTimeout(resolve, retryInterval);\n });\n\n lastError = error;\n log.debug(\n `Retrying Firefox (${retries}); connection error: ${error}`);\n } else {\n log.error(error.stack);\n throw error;\n }\n }\n }\n\n log.debug('Connect to Firefox debugger: too many retries');\n throw lastError;\n }\n\n log.debug('Connecting to the remote Firefox debugger');\n return establishConnection();\n}\n\nexport function findFreeTcpPort(): Promise<number> {\n return new Promise((resolve) => {\n const srv = net.createServer();\n // $FlowFixMe: signature for listen() is missing - see https://github.com/facebook/flow/pull/8290\n srv.listen(0, '127.0.0.1', () => {\n const freeTcpPort = srv.address().port;\n srv.close(() => resolve(freeTcpPort));\n });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"remote.js","names":["net","FirefoxRDPClient","connectToFirefox","defaultFirefoxConnector","createLogger","isErrorWithCode","RemoteTempInstallNotSupported","UsageError","WebExtError","log","import","meta","url","requestErrorToMessage","err","Error","String","error","message","RemoteFirefox","constructor","client","checkedForAddonReloading","on","debug","info","JSON","stringify","rdpError","disconnect","addonRequest","addon","request","response","to","actor","type","getAddonsActor","addonsActor","Promise","reject","installTemporaryAddon","addonPath","openDevTools","getInstalledAddon","addonId","addons","id","map","a","checkForAddonReloading","requestTypes","indexOf","supportedRequestTypes","reloadAddon","process","stdout","write","Date","toTimeString","connect","port","connectWithMaxRetries","maxRetries","retryInterval","establishConnection","lastError","retries","resolve","setTimeout","stack","findFreeTcpPort","srv","createServer","listen","freeTcpPort","address","close"],"sources":["../../src/firefox/remote.js"],"sourcesContent":["/* @flow */\nimport net from 'net';\n\nimport FirefoxRDPClient, {\n connectToFirefox as defaultFirefoxConnector,\n} from './rdp-client.js';\nimport {createLogger} from '../util/logger.js';\nimport {\n isErrorWithCode,\n RemoteTempInstallNotSupported,\n UsageError,\n WebExtError,\n} from '../errors.js';\n\nconst log = createLogger(import.meta.url);\n\nexport type FirefoxConnectorFn =\n (port: number) => Promise<FirefoxRDPClient>;\n\nexport type FirefoxRDPAddonActor = {|\n id: string,\n actor: string,\n|};\n\nexport type FirefoxRDPResponseError = {|\n error: string,\n message: string,\n|};\n\nexport type FirefoxRDPResponseAddon = {|\n addon: FirefoxRDPAddonActor,\n|};\n\nexport type FirefoxRDPResponseRequestTypes = {|\n requestTypes: Array<string>,\n|};\n\n// NOTE: this type aliases Object to catch any other possible response.\nexport type FirefoxRDPResponseAny = Object;\n\nexport type FirefoxRDPResponseMaybe =\n FirefoxRDPResponseRequestTypes | FirefoxRDPResponseAny;\n\n// Convert a request rejection to a message string.\nfunction requestErrorToMessage(err: Error | FirefoxRDPResponseError) {\n if (err instanceof Error) {\n return String(err);\n }\n return `${err.error}: ${err.message}`;\n}\n\nexport class RemoteFirefox {\n client: Object;\n checkedForAddonReloading: boolean;\n\n constructor(client: FirefoxRDPClient) {\n this.client = client;\n this.checkedForAddonReloading = false;\n\n client.on('disconnect', () => {\n log.debug('Received \"disconnect\" from Firefox client');\n });\n client.on('end', () => {\n log.debug('Received \"end\" from Firefox client');\n });\n client.on('unsolicited-event', (info) => {\n log.debug(`Received message from client: ${JSON.stringify(info)}`);\n });\n client.on('rdp-error', (rdpError) => {\n log.debug(`Received error from client: ${JSON.stringify(rdpError)}`);\n });\n client.on('error', (error) => {\n log.debug(`Received error from client: ${String(error)}`);\n });\n }\n\n disconnect() {\n this.client.disconnect();\n }\n\n async addonRequest(\n addon: FirefoxRDPAddonActor,\n request: string\n ): Promise<FirefoxRDPResponseMaybe> {\n try {\n const response = await this.client.request({\n to: addon.actor, type: request,\n });\n return response;\n } catch (err) {\n log.debug(\n `Client responded to '${request}' request with error:`, err);\n const message = requestErrorToMessage(err);\n throw new WebExtError(`Remote Firefox: addonRequest() error: ${message}`);\n }\n }\n\n async getAddonsActor(): Promise<string> {\n try {\n // getRoot should work since Firefox 55 (bug 1352157).\n const response = await this.client.request('getRoot');\n if (response.addonsActor == null) {\n return Promise.reject(new RemoteTempInstallNotSupported(\n 'This version of Firefox does not provide an add-ons actor for ' +\n 'remote installation.'));\n }\n return response.addonsActor;\n } catch (err) {\n // Fallback to listTabs otherwise, Firefox 49 - 77 (bug 1618691).\n log.debug('Falling back to listTabs because getRoot failed', err);\n }\n\n try {\n const response = await this.client.request('listTabs');\n // addonsActor was added to listTabs in Firefox 49 (bug 1273183).\n if (response.addonsActor == null) {\n log.debug(\n 'listTabs returned a falsey addonsActor: ' +\n `${JSON.stringify(response)}`);\n return Promise.reject(new RemoteTempInstallNotSupported(\n 'This is an older version of Firefox that does not provide an ' +\n 'add-ons actor for remote installation. Try Firefox 49 or ' +\n 'higher.'));\n }\n return response.addonsActor;\n } catch (err) {\n log.debug('listTabs error', err);\n const message = requestErrorToMessage(err);\n throw new WebExtError(`Remote Firefox: listTabs() error: ${message}`);\n }\n }\n\n async installTemporaryAddon(\n addonPath: string,\n openDevTools?: boolean\n ): Promise<FirefoxRDPResponseAddon> {\n const addonsActor = await this.getAddonsActor();\n\n try {\n const response = await this.client.request({\n to: addonsActor,\n type: 'installTemporaryAddon',\n addonPath,\n openDevTools,\n });\n log.debug(`installTemporaryAddon: ${JSON.stringify(response)}`);\n log.info(`Installed ${addonPath} as a temporary add-on`);\n return response;\n } catch (err) {\n const message = requestErrorToMessage(err);\n throw new WebExtError(`installTemporaryAddon: Error: ${message}`);\n }\n }\n\n async getInstalledAddon(addonId: string): Promise<FirefoxRDPAddonActor> {\n try {\n const response = await this.client.request('listAddons');\n for (const addon of response.addons) {\n if (addon.id === addonId) {\n return addon;\n }\n }\n log.debug(\n `Remote Firefox has these addons: ${response.addons.map((a) => a.id)}`);\n return Promise.reject(new WebExtError(\n 'The remote Firefox does not have your extension installed'));\n } catch (err) {\n const message = requestErrorToMessage(err);\n throw new WebExtError(`Remote Firefox: listAddons() error: ${message}`);\n }\n }\n\n async checkForAddonReloading(\n addon: FirefoxRDPAddonActor\n ): Promise<FirefoxRDPAddonActor> {\n if (this.checkedForAddonReloading) {\n // We only need to check once if reload() is supported.\n return addon;\n } else {\n const response = await this.addonRequest(addon, 'requestTypes');\n\n if (response.requestTypes.indexOf('reload') === -1) {\n const supportedRequestTypes = JSON.stringify(response.requestTypes);\n log.debug(\n `Remote Firefox only supports: ${supportedRequestTypes}`);\n throw new UsageError(\n 'This Firefox version does not support add-on reloading. ' +\n 'Re-run with --no-reload');\n } else {\n this.checkedForAddonReloading = true;\n return addon;\n }\n }\n }\n\n async reloadAddon(addonId: string): Promise<void> {\n const addon = await this.getInstalledAddon(addonId);\n await this.checkForAddonReloading(addon);\n await this.addonRequest(addon, 'reload');\n process.stdout.write(\n `\\rLast extension reload: ${(new Date()).toTimeString()}`);\n log.debug('\\n');\n }\n}\n\n\n// Connect types and implementation\n\nexport type ConnectOptions = {\n connectToFirefox: FirefoxConnectorFn,\n};\n\nexport async function connect(\n port: number,\n {connectToFirefox = defaultFirefoxConnector}: ConnectOptions = {}\n): Promise<RemoteFirefox> {\n log.debug(`Connecting to Firefox on port ${port}`);\n const client = await connectToFirefox(port);\n log.debug(`Connected to the remote Firefox debugger on port ${port}`);\n return new RemoteFirefox(client);\n}\n\n\n// ConnectWithMaxRetries types and implementation\n\nexport type ConnectWithMaxRetriesParams = {|\n maxRetries?: number,\n retryInterval?: number,\n port: number,\n|};\n\nexport type ConnectWithMaxRetriesDeps = {\n connectToFirefox: typeof connect,\n};\n\nexport async function connectWithMaxRetries(\n // A max of 250 will try connecting for 30 seconds.\n {maxRetries = 250, retryInterval = 120, port}: ConnectWithMaxRetriesParams,\n {connectToFirefox = connect}: ConnectWithMaxRetriesDeps = {}\n): Promise<RemoteFirefox> {\n async function establishConnection() {\n var lastError;\n\n for (let retries = 0; retries <= maxRetries; retries++) {\n try {\n return await connectToFirefox(port);\n } catch (error) {\n if (isErrorWithCode('ECONNREFUSED', error)) {\n // Wait for `retryInterval` ms.\n await new Promise((resolve) => {\n setTimeout(resolve, retryInterval);\n });\n\n lastError = error;\n log.debug(\n `Retrying Firefox (${retries}); connection error: ${error}`);\n } else {\n log.error(error.stack);\n throw error;\n }\n }\n }\n\n log.debug('Connect to Firefox debugger: too many retries');\n throw lastError;\n }\n\n log.debug('Connecting to the remote Firefox debugger');\n return establishConnection();\n}\n\nexport function findFreeTcpPort(): Promise<number> {\n return new Promise((resolve) => {\n const srv = net.createServer();\n // $FlowFixMe: signature for listen() is missing - see https://github.com/facebook/flow/pull/8290\n srv.listen(0, '127.0.0.1', () => {\n const freeTcpPort = srv.address().port;\n srv.close(() => resolve(freeTcpPort));\n });\n });\n}\n"],"mappings":"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"}
|
package/lib/main.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
|
|
1
2
|
import { main } from './program.js';
|
|
2
|
-
import cmd from './cmd/index.js';
|
|
3
|
-
// separate additional exports in the package.json.
|
|
3
|
+
import cmd from './cmd/index.js';
|
|
4
4
|
|
|
5
|
+
// This only exposes main and cmd, while util/logger and util/adb are defined as
|
|
6
|
+
// separate additional exports in the package.json.
|
|
5
7
|
export default {
|
|
6
8
|
main,
|
|
7
9
|
cmd
|
package/lib/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":["main","cmd"],"sources":["../src/main.js"],"sourcesContent":["/* @flow */\nimport {main} from './program.js';\nimport cmd from './cmd/index.js';\n\n// This only exposes main and cmd, while util/logger and util/adb are defined as\n// separate additional exports in the package.json.\nexport default {main, cmd};\n"],"mappings":"AACA,SAAQA,
|
|
1
|
+
{"version":3,"file":"main.js","names":["main","cmd"],"sources":["../src/main.js"],"sourcesContent":["/* @flow */\nimport {main} from './program.js';\nimport cmd from './cmd/index.js';\n\n// This only exposes main and cmd, while util/logger and util/adb are defined as\n// separate additional exports in the package.json.\nexport default {main, cmd};\n"],"mappings":";AACA,SAAQA,IAAI,QAAO,cAAc;AACjC,OAAOC,GAAG,MAAM,gBAAgB;;AAEhC;AACA;AACA,eAAe;EAACD,IAAI;EAAEC;AAAG,CAAC"}
|