@trezor/connect 9.3.0 → 9.3.1-beta.2

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.
Files changed (60) hide show
  1. package/CHANGELOG.md +121 -8
  2. package/README.md +1 -1
  3. package/lib/api/checkFirmwareAuthenticity.d.ts +2 -1
  4. package/lib/api/checkFirmwareAuthenticity.js +34 -26
  5. package/lib/api/ethereum/api/ethereumSignTypedData.d.ts +1 -0
  6. package/lib/api/ethereum/api/ethereumSignTypedData.js +3 -1
  7. package/lib/api/ethereum/ethereumDefinitions.js +1 -0
  8. package/lib/api/firmware/getBinary.d.ts +4 -4
  9. package/lib/api/firmware/getBinary.js +4 -15
  10. package/lib/api/firmware/getBinaryForFirmwareUpgrade.d.ts +11 -0
  11. package/lib/api/firmware/getBinaryForFirmwareUpgrade.js +32 -0
  12. package/lib/api/firmware/index.d.ts +1 -0
  13. package/lib/api/firmware/index.js +3 -1
  14. package/lib/api/firmware/verifyAuthenticityProof.d.ts +1 -1
  15. package/lib/api/firmware/verifyAuthenticityProof.js +37 -2
  16. package/lib/api/firmware/x509certificate.d.ts +20 -6
  17. package/lib/api/firmware/x509certificate.js +82 -13
  18. package/lib/api/getCoinInfo.d.ts +3 -0
  19. package/lib/api/getFeatures.d.ts +1 -0
  20. package/lib/backend/Blockchain.js +10 -1
  21. package/lib/core/AbstractMethod.js +1 -0
  22. package/lib/core/index.d.ts +3 -3
  23. package/lib/core/index.js +93 -111
  24. package/lib/core/onCallFirmwareUpdate.js +25 -14
  25. package/lib/data/DataManager.d.ts +11 -0
  26. package/lib/data/DataManager.js +1 -1
  27. package/lib/data/coinInfo.d.ts +14 -0
  28. package/lib/data/config.d.ts +11 -0
  29. package/lib/data/config.js +17 -1
  30. package/lib/data/connectSettings.js +3 -2
  31. package/lib/data/deviceAuthenticityConfig.d.ts +1 -28
  32. package/lib/data/deviceAuthenticityConfig.js +25 -24
  33. package/lib/data/deviceAuthenticityConfigTypes.d.ts +38 -0
  34. package/lib/data/deviceAuthenticityConfigTypes.js +28 -0
  35. package/lib/data/models.d.ts +10 -0
  36. package/lib/data/models.js +12 -10
  37. package/lib/data/version.d.ts +2 -1
  38. package/lib/data/version.js +3 -2
  39. package/lib/device/Device.d.ts +2 -3
  40. package/lib/device/Device.js +15 -24
  41. package/lib/device/DeviceCommands.js +2 -27
  42. package/lib/device/DeviceList.d.ts +42 -27
  43. package/lib/device/DeviceList.js +249 -233
  44. package/lib/events/core.d.ts +2 -2
  45. package/lib/events/popup.d.ts +1 -0
  46. package/lib/events/transport.d.ts +5 -0
  47. package/lib/index.js +20 -20
  48. package/lib/types/api/authenticateDevice.d.ts +9 -0
  49. package/lib/types/api/authenticateDevice.js +2 -2
  50. package/lib/types/api/checkFirmwareAuthenticity.d.ts +4 -1
  51. package/lib/types/api/init.d.ts +2 -2
  52. package/lib/types/coinInfo.d.ts +7 -0
  53. package/lib/types/firmware.d.ts +2 -2
  54. package/lib/types/settings.d.ts +7 -3
  55. package/lib/utils/assetUtils.js +1 -0
  56. package/lib/utils/promiseUtils.d.ts +3 -3
  57. package/lib/utils/promiseUtils.js +7 -5
  58. package/package.json +16 -17
  59. package/lib/core/coreManager.d.ts +0 -16
  60. package/lib/core/coreManager.js +0 -55
@@ -10,239 +10,264 @@ const transportInfo_1 = require("../data/transportInfo");
10
10
  const debug_1 = require("../utils/debug");
11
11
  const promiseUtils_1 = require("../utils/promiseUtils");
12
12
  const _log = (0, debug_1.initLog)('DeviceList');
13
- let autoResolveTransportEventTimeout;
13
+ const createAuthPenaltyManager = (priority) => {
14
+ const penalizedDevices = {};
15
+ const get = () => 100 * priority +
16
+ Object.keys(penalizedDevices).reduce((penalty, key) => Math.max(penalty, penalizedDevices[key]), 0);
17
+ const add = (device) => {
18
+ if (!device.isInitialized() || device.isBootloader() || !device.features.device_id)
19
+ return;
20
+ const deviceID = device.features.device_id;
21
+ const penalty = penalizedDevices[deviceID] ? penalizedDevices[deviceID] + 500 : 2000;
22
+ penalizedDevices[deviceID] = Math.min(penalty, 5000);
23
+ };
24
+ const remove = (device) => {
25
+ if (!device.isInitialized() || device.isBootloader() || !device.features.device_id)
26
+ return;
27
+ const deviceID = device.features.device_id;
28
+ delete penalizedDevices[deviceID];
29
+ };
30
+ const clear = () => Object.keys(penalizedDevices).forEach(key => delete penalizedDevices[key]);
31
+ return { get, add, remove, clear };
32
+ };
14
33
  class DeviceList extends utils_1.TypedEmitter {
15
- constructor({ settings, messages, }) {
34
+ isConnected() {
35
+ return !!this.transport;
36
+ }
37
+ assertConnected() {
38
+ if (!this.transport)
39
+ throw constants_1.ERRORS.TypedError('Transport_Missing');
40
+ }
41
+ pendingConnection() {
42
+ return this.initPromise;
43
+ }
44
+ constructor({ messages, priority, debug }) {
16
45
  super();
17
- this.transports = [];
18
46
  this.devices = {};
19
47
  this.creatingDevicesDescriptors = {};
20
- this.transportStartPending = 0;
21
- this.penalizedDevices = {};
22
- this.settings = settings;
23
- const transports = [...(settings.transports || [])];
24
- if (!transports.length) {
25
- transports.push('BridgeTransport');
26
- }
27
- const transportLogger = (0, debug_1.initLog)('@trezor/transport', this.settings.debug);
48
+ const transportLogger = (0, debug_1.initLog)('@trezor/transport', debug);
28
49
  const abortController = new AbortController();
29
- const transportCommonArgs = {
50
+ this.authPenaltyManager = createAuthPenaltyManager(priority);
51
+ this.transportCommonArgs = {
30
52
  messages,
31
53
  logger: transportLogger,
32
54
  signal: abortController.signal,
33
55
  };
34
- transports.forEach(transportType => {
35
- if (typeof transportType === 'string') {
36
- switch (transportType) {
37
- case 'WebUsbTransport':
38
- this.transports.push(new transport_1.WebUsbTransport(transportCommonArgs));
39
- break;
40
- case 'NodeUsbTransport':
41
- this.transports.push(new transport_1.NodeUsbTransport(transportCommonArgs));
42
- break;
43
- case 'BridgeTransport':
44
- this.transports.push(new transport_1.BridgeTransport({
45
- latestVersion: (0, transportInfo_1.getBridgeInfo)().version.join('.'),
46
- ...transportCommonArgs,
47
- }));
48
- break;
49
- case 'UdpTransport':
50
- this.transports.push(new transport_1.UdpTransport(transportCommonArgs));
51
- break;
52
- default:
53
- throw constants_1.ERRORS.TypedError('Runtime', `DeviceList.init: transports[] of unexpected type: ${transportType}`);
54
- }
56
+ this.transports = [
57
+ new transport_1.BridgeTransport({
58
+ latestVersion: (0, transportInfo_1.getBridgeInfo)().version.join('.'),
59
+ ...this.transportCommonArgs,
60
+ }),
61
+ ];
62
+ }
63
+ createTransport(transportType) {
64
+ const { transportCommonArgs } = this;
65
+ if (typeof transportType === 'string') {
66
+ switch (transportType) {
67
+ case 'WebUsbTransport':
68
+ return new transport_1.WebUsbTransport(transportCommonArgs);
69
+ case 'NodeUsbTransport':
70
+ return new transport_1.NodeUsbTransport(transportCommonArgs);
71
+ case 'BridgeTransport':
72
+ return new transport_1.BridgeTransport({
73
+ latestVersion: (0, transportInfo_1.getBridgeInfo)().version.join('.'),
74
+ ...transportCommonArgs,
75
+ });
76
+ case 'UdpTransport':
77
+ return new transport_1.UdpTransport(transportCommonArgs);
55
78
  }
56
- else if (typeof transportType === 'function' && 'prototype' in transportType) {
57
- const transportInstance = new transportType(transportCommonArgs);
58
- if ((0, transport_1.isTransportInstance)(transportInstance)) {
59
- this.transports.push(transportInstance);
60
- }
79
+ }
80
+ else if (typeof transportType === 'function' && 'prototype' in transportType) {
81
+ const transportInstance = new transportType(transportCommonArgs);
82
+ if ((0, transport_1.isTransportInstance)(transportInstance)) {
83
+ return transportInstance;
61
84
  }
62
- else if ((0, transport_1.isTransportInstance)(transportType)) {
63
- if (!transportType.getMessage()) {
64
- transportType.updateMessages(messages);
65
- }
66
- this.transports.push(transportType);
85
+ }
86
+ else if ((0, transport_1.isTransportInstance)(transportType)) {
87
+ if (!transportType.getMessage()) {
88
+ transportType.updateMessages(transportCommonArgs.messages);
67
89
  }
68
- else {
69
- throw constants_1.ERRORS.TypedError('Runtime', 'DeviceList.init: transports[] of unexpected type');
90
+ return transportType;
91
+ }
92
+ throw constants_1.ERRORS.TypedError('Runtime', `DeviceList.init: transports[] of unexpected type: ${transportType}`);
93
+ }
94
+ setTransports(transports) {
95
+ const transportTypes = (transports === null || transports === void 0 ? void 0 : transports.length) ? transports : ['BridgeTransport'];
96
+ this.transports = transportTypes.map(this.createTransport.bind(this));
97
+ }
98
+ onTransportUpdate(diff, transport) {
99
+ diff.disconnected.forEach(descriptor => {
100
+ const path = descriptor.path.toString();
101
+ const device = this.devices[path];
102
+ if (device) {
103
+ device.disconnect();
104
+ delete this.devices[path];
105
+ this.emit(events_1.DEVICE.DISCONNECT, device.toMessageObject());
70
106
  }
71
107
  });
72
- }
73
- async init() {
74
- try {
75
- _log.debug('Initializing transports');
76
- let lastError;
77
- for (const transport of this.transports) {
78
- this.transport = transport;
79
- const result = await this.transport.init().promise;
80
- if (result.success) {
81
- lastError = undefined;
82
- break;
83
- }
84
- else {
85
- lastError = result.error;
86
- }
108
+ diff.connected.forEach(async (descriptor) => {
109
+ const path = descriptor.path.toString();
110
+ this.creatingDevicesDescriptors[path] = descriptor;
111
+ const penalty = this.authPenaltyManager.get();
112
+ if (penalty) {
113
+ await (0, promiseUtils_1.resolveAfter)(501 + penalty, null).promise;
87
114
  }
88
- if (lastError) {
89
- this.emit(transport_1.TRANSPORT.ERROR, lastError);
90
- return;
115
+ if (this.creatingDevicesDescriptors[path].session == null) {
116
+ await this._createAndSaveDevice(descriptor, transport);
91
117
  }
92
- this.transport.on(transport_1.TRANSPORT.UPDATE, diff => {
93
- diff.disconnected.forEach(descriptor => {
94
- const path = descriptor.path.toString();
95
- const device = this.devices[path];
96
- if (device) {
97
- device.disconnect();
98
- delete this.devices[path];
99
- this.emit(events_1.DEVICE.DISCONNECT, device.toMessageObject());
100
- }
101
- });
102
- diff.connected.forEach(async (descriptor) => {
103
- const path = descriptor.path.toString();
104
- this.creatingDevicesDescriptors[path] = descriptor;
105
- const { priority } = this.settings;
106
- const penalty = this.getAuthPenalty();
107
- if (priority || penalty) {
108
- await (0, promiseUtils_1.resolveAfter)(501 + penalty + 100 * priority, null).promise;
109
- }
110
- if (this.creatingDevicesDescriptors[path].session == null) {
111
- await this._createAndSaveDevice(descriptor);
112
- }
113
- else {
114
- const device = this._createUnacquiredDevice(descriptor);
115
- this.devices[path] = device;
116
- this.emit(events_1.DEVICE.CONNECT_UNACQUIRED, device.toMessageObject());
117
- }
118
- });
119
- diff.acquiredElsewhere.forEach((descriptor) => {
120
- const path = descriptor.path.toString();
121
- const device = this.devices[path];
122
- if (device) {
123
- device.featuresNeedsReload = true;
124
- device.interruptionFromOutside();
125
- }
126
- });
127
- diff.released.forEach(descriptor => {
128
- var _a;
129
- const path = descriptor.path.toString();
130
- const device = this.devices[path];
131
- const methodStillRunning = !((_a = device === null || device === void 0 ? void 0 : device.commands) === null || _a === void 0 ? void 0 : _a.disposed);
132
- if (device && methodStillRunning) {
133
- device.keepSession = false;
134
- }
135
- });
136
- diff.releasedElsewhere.forEach(async (descriptor) => {
137
- const path = descriptor.path.toString();
138
- const device = this.devices[path];
139
- await (0, promiseUtils_1.resolveAfter)(1000, null).promise;
140
- if (device) {
141
- if (!device.isUsed() && device.isUnacquired() && !device.isInconsistent()) {
142
- _log.debug('Create device from unacquired', device.toMessageObject());
143
- await this._createAndSaveDevice(descriptor);
144
- }
145
- }
146
- });
147
- const events = [
148
- {
149
- d: diff.changedSessions,
150
- e: events_1.DEVICE.CHANGED,
151
- },
152
- {
153
- d: diff.acquired,
154
- e: events_1.DEVICE.ACQUIRED,
155
- },
156
- {
157
- d: diff.released,
158
- e: events_1.DEVICE.RELEASED,
159
- },
160
- ];
161
- events.forEach(({ d, e }) => {
162
- d.forEach(descriptor => {
163
- const path = descriptor.path.toString();
164
- const device = this.devices[path];
165
- if (device) {
166
- _log.debug('Event', e, device.toMessageObject());
167
- this.emit(e, device.toMessageObject());
168
- }
169
- });
170
- });
171
- diff.descriptors.forEach(d => {
172
- this.creatingDevicesDescriptors[d.path] = d;
173
- if (this.devices[d.path]) {
174
- this.devices[d.path].originalDescriptor = {
175
- session: d.session,
176
- path: d.path,
177
- product: d.product,
178
- type: d.type,
179
- };
180
- }
181
- });
182
- });
183
- this.transport.on(transport_1.TRANSPORT.ERROR, error => {
184
- this.emit(transport_1.TRANSPORT.ERROR, error);
185
- });
186
- const enumerateResult = await this.transport.enumerate().promise;
187
- if (!enumerateResult.success) {
188
- this.emit(transport_1.TRANSPORT.ERROR, enumerateResult.error);
189
- return;
118
+ else {
119
+ const device = this._createUnacquiredDevice(descriptor, transport);
120
+ this.devices[path] = device;
121
+ this.emit(events_1.DEVICE.CONNECT_UNACQUIRED, device.toMessageObject());
190
122
  }
191
- const descriptors = enumerateResult.payload;
192
- if (descriptors.length > 0 && this.settings.pendingTransportEvent) {
193
- this.transportStartPending = descriptors.length;
194
- this.on(events_1.DEVICE.CONNECT, this.resolveTransportEvent.bind(this));
195
- this.on(events_1.DEVICE.CONNECT_UNACQUIRED, this.resolveTransportEvent.bind(this));
196
- autoResolveTransportEventTimeout = setTimeout(() => {
197
- this.emit(transport_1.TRANSPORT.START, this.getTransportInfo());
198
- }, 10000);
123
+ });
124
+ diff.acquiredElsewhere.forEach((descriptor) => {
125
+ const path = descriptor.path.toString();
126
+ const device = this.devices[path];
127
+ if (device) {
128
+ device.featuresNeedsReload = true;
129
+ device.interruptionFromOutside();
199
130
  }
200
- else {
201
- this.emit(transport_1.TRANSPORT.START, this.getTransportInfo());
131
+ });
132
+ diff.released.forEach(descriptor => {
133
+ var _a;
134
+ const path = descriptor.path.toString();
135
+ const device = this.devices[path];
136
+ const methodStillRunning = !((_a = device === null || device === void 0 ? void 0 : device.commands) === null || _a === void 0 ? void 0 : _a.isDisposed());
137
+ if (device && methodStillRunning) {
138
+ device.keepSession = false;
202
139
  }
203
- this.transport.handleDescriptorsChange(descriptors);
204
- this.transport.listen();
205
- }
206
- catch (error) {
207
- console.error('DeviceList init error', error);
208
- }
140
+ });
141
+ diff.releasedElsewhere.forEach(async (descriptor) => {
142
+ const path = descriptor.path.toString();
143
+ const device = this.devices[path];
144
+ await (0, promiseUtils_1.resolveAfter)(1000, null).promise;
145
+ if (device) {
146
+ if (!device.isUsed() && device.isUnacquired() && !device.isInconsistent()) {
147
+ _log.debug('Create device from unacquired', device.toMessageObject());
148
+ await this._createAndSaveDevice(descriptor, transport);
149
+ }
150
+ }
151
+ });
152
+ const forEachDescriptor = (d, e) => {
153
+ d.forEach(descriptor => {
154
+ const path = descriptor.path.toString();
155
+ const device = this.devices[path];
156
+ if (device) {
157
+ _log.debug('Event', e, device.toMessageObject());
158
+ this.emit(e, device.toMessageObject());
159
+ }
160
+ });
161
+ };
162
+ forEachDescriptor(diff.changedSessions, events_1.DEVICE.CHANGED);
163
+ forEachDescriptor(diff.acquired, events_1.DEVICE.ACQUIRED);
164
+ forEachDescriptor(diff.released, events_1.DEVICE.RELEASED);
165
+ diff.descriptors.forEach(d => {
166
+ this.creatingDevicesDescriptors[d.path] = d;
167
+ if (this.devices[d.path]) {
168
+ this.devices[d.path].originalDescriptor = {
169
+ session: d.session,
170
+ path: d.path,
171
+ product: d.product,
172
+ type: d.type,
173
+ };
174
+ }
175
+ });
209
176
  }
210
- resolveTransportEvent() {
211
- this.transportStartPending--;
212
- if (autoResolveTransportEventTimeout) {
213
- clearTimeout(autoResolveTransportEventTimeout);
177
+ init(initParams = {}) {
178
+ if (!this.initPromise) {
179
+ _log.debug('Initializing transports');
180
+ this.initPromise = this.createInitPromise(initParams);
214
181
  }
215
- if (this.transportStartPending === 0) {
182
+ return this.initPromise;
183
+ }
184
+ createInitPromise(initParams) {
185
+ return this.selectTransport(this.transports)
186
+ .then(transport => this.initializeTransport(transport, initParams))
187
+ .then(transport => {
188
+ this.transport = transport;
216
189
  this.emit(transport_1.TRANSPORT.START, this.getTransportInfo());
190
+ this.initPromise = undefined;
191
+ })
192
+ .catch(error => {
193
+ this.cleanup();
194
+ this.emit(transport_1.TRANSPORT.ERROR, error);
195
+ this.initPromise = initParams.transportReconnect
196
+ ? this.createReconnectPromise(initParams)
197
+ : undefined;
198
+ });
199
+ }
200
+ createReconnectPromise(initParams) {
201
+ const { promise, reject } = (0, promiseUtils_1.resolveAfter)(1000, initParams);
202
+ this.rejectPending = reject;
203
+ return promise.then(this.createInitPromise.bind(this));
204
+ }
205
+ async selectTransport([transport, ...rest]) {
206
+ const result = await transport.init().promise;
207
+ if (result.success)
208
+ return transport;
209
+ else if (rest.length)
210
+ return this.selectTransport(rest);
211
+ else
212
+ throw new Error(result.error);
213
+ }
214
+ async initializeTransport(transport, initParams) {
215
+ transport.on(transport_1.TRANSPORT.UPDATE, diff => this.onTransportUpdate(diff, transport));
216
+ transport.on(transport_1.TRANSPORT.ERROR, error => {
217
+ this.cleanup();
218
+ this.emit(transport_1.TRANSPORT.ERROR, error);
219
+ if (initParams.transportReconnect) {
220
+ this.initPromise = this.createReconnectPromise(initParams);
221
+ }
222
+ });
223
+ const enumerateResult = await transport.enumerate().promise;
224
+ if (!enumerateResult.success) {
225
+ throw new Error(enumerateResult.error);
226
+ }
227
+ const descriptors = enumerateResult.payload;
228
+ transport.handleDescriptorsChange(descriptors);
229
+ transport.listen();
230
+ const awaitedDevices = descriptors.length - Object.keys(this.devices).length;
231
+ if (awaitedDevices > 0 && initParams.pendingTransportEvent) {
232
+ await this.waitForDevices(awaitedDevices, 10000);
217
233
  }
234
+ return transport;
218
235
  }
219
- async waitForTransportFirstEvent() {
220
- this.transportFirstEventPromise = new Promise(resolve => {
221
- const handler = () => {
222
- this.removeListener(transport_1.TRANSPORT.START, handler);
223
- this.removeListener(transport_1.TRANSPORT.ERROR, handler);
236
+ waitForDevices(deviceCount, autoResolveMs) {
237
+ const { promise, resolve, reject } = (0, utils_1.createDeferred)();
238
+ let transportStartPending = deviceCount;
239
+ const autoResolveTransportEventTimeout = setTimeout(resolve, autoResolveMs);
240
+ this.rejectPending = reject;
241
+ const onDeviceConnect = () => {
242
+ transportStartPending--;
243
+ if (transportStartPending === 0) {
224
244
  resolve();
225
- };
226
- this.on(transport_1.TRANSPORT.START, handler);
227
- this.on(transport_1.TRANSPORT.ERROR, handler);
245
+ }
246
+ };
247
+ this.on(events_1.DEVICE.CONNECT, onDeviceConnect);
248
+ this.on(events_1.DEVICE.CONNECT_UNACQUIRED, onDeviceConnect);
249
+ return promise.finally(() => {
250
+ this.rejectPending = undefined;
251
+ clearTimeout(autoResolveTransportEventTimeout);
252
+ this.off(events_1.DEVICE.CONNECT, onDeviceConnect);
253
+ this.off(events_1.DEVICE.CONNECT_UNACQUIRED, onDeviceConnect);
228
254
  });
229
- await this.transportFirstEventPromise;
230
255
  }
231
- async _createAndSaveDevice(descriptor) {
256
+ async _createAndSaveDevice(descriptor, transport) {
232
257
  _log.debug('Creating Device', descriptor);
233
- await this.handle(descriptor);
258
+ await this.handle(descriptor, transport);
234
259
  }
235
- _createUnacquiredDevice(descriptor) {
260
+ _createUnacquiredDevice(descriptor, transport) {
236
261
  _log.debug('Creating Unacquired Device', descriptor);
237
- const device = Device_1.Device.createUnacquired(this.transport, descriptor);
262
+ const device = Device_1.Device.createUnacquired(transport, descriptor);
238
263
  device.once(events_1.DEVICE.ACQUIRED, () => {
239
264
  this.emit(events_1.DEVICE.CONNECT, device.toMessageObject());
240
265
  });
241
266
  return device;
242
267
  }
243
- _createUnreadableDevice(descriptor, unreadableError) {
268
+ _createUnreadableDevice(descriptor, transport, unreadableError) {
244
269
  _log.debug('Creating Unreadable Device', descriptor, unreadableError);
245
- return Device_1.Device.createUnacquired(this.transport, descriptor, unreadableError);
270
+ return Device_1.Device.createUnacquired(transport, descriptor, unreadableError);
246
271
  }
247
272
  getDevice(path) {
248
273
  return this.devices[path];
@@ -271,20 +296,24 @@ class DeviceList extends utils_1.TypedEmitter {
271
296
  }
272
297
  dispose() {
273
298
  this.removeAllListeners();
274
- if (autoResolveTransportEventTimeout) {
275
- clearTimeout(autoResolveTransportEventTimeout);
276
- }
277
- Promise.all(this.allDevices().map(device => device.dispose())).then(() => {
278
- this.transport.stop();
279
- });
299
+ return this.cleanup();
280
300
  }
281
- disconnectDevices() {
282
- this.allDevices().forEach(device => {
301
+ async cleanup() {
302
+ var _a;
303
+ const { transport } = this;
304
+ const devices = this.allDevices();
305
+ this.transport = undefined;
306
+ this.authPenaltyManager.clear();
307
+ Object.keys(this.devices).forEach(key => delete this.devices[key]);
308
+ (_a = this.rejectPending) === null || _a === void 0 ? void 0 : _a.call(this, new Error('Disposed'));
309
+ devices.forEach(device => {
283
310
  this.emit(events_1.DEVICE.DISCONNECT, device.toMessageObject());
284
311
  });
312
+ await Promise.all(devices.map(device => device.dispose()));
313
+ transport === null || transport === void 0 ? void 0 : transport.stop();
285
314
  }
286
- async enumerate() {
287
- const res = await this.transport.enumerate().promise;
315
+ async enumerate(transport = this.transport) {
316
+ const res = await transport.enumerate().promise;
288
317
  if (!res.success) {
289
318
  return;
290
319
  }
@@ -301,29 +330,16 @@ class DeviceList extends utils_1.TypedEmitter {
301
330
  });
302
331
  }
303
332
  addAuthPenalty(device) {
304
- if (!device.isInitialized() || device.isBootloader() || !device.features.device_id)
305
- return;
306
- const deviceID = device.features.device_id;
307
- const penalty = this.penalizedDevices[deviceID]
308
- ? this.penalizedDevices[deviceID] + 500
309
- : 2000;
310
- this.penalizedDevices[deviceID] = Math.min(penalty, 5000);
311
- }
312
- getAuthPenalty() {
313
- const { penalizedDevices } = this;
314
- return Object.keys(penalizedDevices).reduce((penalty, key) => Math.max(penalty, penalizedDevices[key]), 0);
333
+ return this.authPenaltyManager.add(device);
315
334
  }
316
335
  removeAuthPenalty(device) {
317
- if (!device.isInitialized() || device.isBootloader() || !device.features.device_id)
318
- return;
319
- const deviceID = device.features.device_id;
320
- delete this.penalizedDevices[deviceID];
336
+ return this.authPenaltyManager.remove(device);
321
337
  }
322
- async handle(descriptor) {
338
+ async handle(descriptor, transport) {
323
339
  var _a;
324
340
  const path = descriptor.path.toString();
325
341
  try {
326
- await this._takeAndCreateDevice(descriptor);
342
+ await this._takeAndCreateDevice(descriptor, transport);
327
343
  }
328
344
  catch (error) {
329
345
  _log.debug('Cannot create device', error);
@@ -336,37 +352,37 @@ class DeviceList extends utils_1.TypedEmitter {
336
352
  delete this.devices[path];
337
353
  }
338
354
  else if (error.message === transport_1.TRANSPORT_ERROR.SESSION_WRONG_PREVIOUS) {
339
- this.enumerate();
340
- this._handleUsedElsewhere(descriptor);
355
+ this.enumerate(transport);
356
+ this._handleUsedElsewhere(descriptor, transport);
341
357
  }
342
358
  else if (error.message === transport_1.TRANSPORT_ERROR.INTERFACE_UNABLE_TO_OPEN_DEVICE ||
343
359
  ((_a = error.message) === null || _a === void 0 ? void 0 : _a.indexOf(constants_1.ERRORS.LIBUSB_ERROR_MESSAGE)) >= 0 ||
344
360
  error.code === 'Device_InitializeFailed') {
345
- const device = this._createUnreadableDevice(this.creatingDevicesDescriptors[path], error.message);
361
+ const device = this._createUnreadableDevice(this.creatingDevicesDescriptors[path], transport, error.message);
346
362
  this.devices[path] = device;
347
363
  this.emit(events_1.DEVICE.CONNECT_UNACQUIRED, device.toMessageObject());
348
364
  }
349
365
  else if (error.code === 'Device_UsedElsewhere') {
350
- this._handleUsedElsewhere(descriptor);
366
+ this._handleUsedElsewhere(descriptor, transport);
351
367
  }
352
368
  else {
353
369
  await (0, promiseUtils_1.resolveAfter)(501, null).promise;
354
- await this.handle(descriptor);
370
+ await this.handle(descriptor, transport);
355
371
  }
356
372
  }
357
373
  delete this.creatingDevicesDescriptors[path];
358
374
  }
359
- async _takeAndCreateDevice(descriptor) {
360
- const device = Device_1.Device.fromDescriptor(this.transport, descriptor);
375
+ async _takeAndCreateDevice(descriptor, transport) {
376
+ const device = Device_1.Device.fromDescriptor(transport, descriptor);
361
377
  const path = descriptor.path.toString();
362
378
  this.devices[path] = device;
363
379
  const promise = device.run();
364
380
  await promise;
365
381
  this.emit(events_1.DEVICE.CONNECT, device.toMessageObject());
366
382
  }
367
- _handleUsedElsewhere(descriptor) {
383
+ _handleUsedElsewhere(descriptor, transport) {
368
384
  const path = descriptor.path.toString();
369
- const device = this._createUnacquiredDevice(this.creatingDevicesDescriptors[path]);
385
+ const device = this._createUnacquiredDevice(this.creatingDevicesDescriptors[path], transport);
370
386
  this.devices[path] = device;
371
387
  this.emit(events_1.DEVICE.CONNECT_UNACQUIRED, device.toMessageObject());
372
388
  }
@@ -3,12 +3,12 @@ import type { IFrameCallMessage, MethodResponseMessage } from './call';
3
3
  import type { DeviceEventMessage } from './device';
4
4
  import type { IFrameEventMessage, IFrameInit, IFrameLogRequest } from './iframe';
5
5
  import type { PopupAnalyticsResponse, PopupClosedMessage, PopupEventMessage } from './popup';
6
- import type { TransportEventMessage, TransportDisableWebUSB, TransportRequestWebUSBDevice } from './transport';
6
+ import type { TransportEventMessage, TransportDisableWebUSB, TransportRequestWebUSBDevice, TransportGetInfo } from './transport';
7
7
  import type { UiEventMessage } from './ui-request';
8
8
  import type { UiResponseEvent } from './ui-response';
9
9
  import type { Unsuccessful } from '../types/params';
10
10
  export declare const CORE_EVENT = "CORE_EVENT";
11
- export type CoreRequestMessage = PopupClosedMessage | PopupAnalyticsResponse | TransportDisableWebUSB | TransportRequestWebUSBDevice | UiResponseEvent | IFrameInit | IFrameCallMessage | IFrameLogRequest;
11
+ export type CoreRequestMessage = PopupClosedMessage | PopupAnalyticsResponse | TransportDisableWebUSB | TransportRequestWebUSBDevice | TransportGetInfo | UiResponseEvent | IFrameInit | IFrameCallMessage | IFrameLogRequest;
12
12
  export type CoreEventMessage = {
13
13
  success?: boolean;
14
14
  channel?: {
@@ -62,6 +62,7 @@ export interface PopupContentScriptLoaded {
62
62
  type: typeof POPUP.CONTENT_SCRIPT_LOADED;
63
63
  payload: {
64
64
  id: string;
65
+ contentScriptVersion: number;
65
66
  };
66
67
  }
67
68
  export interface PopupExtensionUsbPermissions {
@@ -52,6 +52,11 @@ export interface TransportRequestWebUSBDevice {
52
52
  type: typeof TRANSPORT.REQUEST_DEVICE;
53
53
  payload?: undefined;
54
54
  }
55
+ export interface TransportGetInfo {
56
+ id: number;
57
+ type: typeof TRANSPORT.GET_INFO;
58
+ payload?: undefined;
59
+ }
55
60
  export type TransportEventMessage = TransportEvent & {
56
61
  event: typeof TRANSPORT_EVENT;
57
62
  };