UNPKG

6.99 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.postModuleMessage = postModuleMessage;
7
8var _defered = require("../defered");
9
10// To ensure that two website don't read from/to Trezor at the same time, I need a sharedworker
11// to synchronize them.
12// However, sharedWorker cannot directly use webusb API... so I need to send messages
13// about intent to acquire/release and then send another message when that is done.
14// Other windows then can acquire/release
15// eslint-disable-next-line no-undef
16// $FlowIssue
17if (typeof onconnect !== "undefined") {
18 // eslint-disable-next-line no-undef
19 onconnect = function onconnect(e) {
20 var port = e.ports[0];
21
22 port.onmessage = function (e) {
23 handleMessage(e.data, port);
24 };
25 };
26}
27
28// path => session
29var normalSessions = {};
30var debugSessions = {};
31var lock = null;
32var waitPromise = Promise.resolve();
33
34function startLock() {
35 var newLock = (0, _defered.create)();
36 lock = newLock;
37 setTimeout(function () {
38 return newLock.reject(new Error("Timed out"));
39 }, 10 * 1000);
40}
41
42function releaseLock(obj) {
43 if (lock == null) {
44 // TODO: ???
45 return;
46 }
47
48 lock.resolve(obj);
49}
50
51function waitForLock() {
52 if (lock == null) {
53 // TODO: ???
54 return Promise.reject(new Error("???"));
55 }
56
57 return lock.promise;
58}
59
60function waitInQueue(fn) {
61 var res = waitPromise.then(function () {
62 return fn();
63 });
64 waitPromise = res["catch"](function () {});
65}
66
67function handleMessage(_ref, port) {
68 var id = _ref.id,
69 message = _ref.message;
70
71 if (message.type === "acquire-intent") {
72 var _path = message.path;
73 var previous = message.previous;
74 var debug = message.debug;
75 waitInQueue(function () {
76 return handleAcquireIntent(_path, previous, debug, id, port);
77 });
78 }
79
80 if (message.type === "acquire-done") {
81 handleAcquireDone(id); // port is the same as original
82 }
83
84 if (message.type === "acquire-failed") {
85 handleAcquireFailed(id); // port is the same as original
86 }
87
88 if (message.type === "get-sessions") {
89 waitInQueue(function () {
90 return handleGetSessions(id, port);
91 });
92 }
93
94 if (message.type === "get-sessions-and-disconnect") {
95 var devices = message.devices;
96 waitInQueue(function () {
97 return handleGetSessions(id, port, devices);
98 });
99 }
100
101 if (message.type === "release-onclose") {
102 var session = message.session;
103 waitInQueue(function () {
104 return handleReleaseOnClose(session);
105 });
106 }
107
108 if (message.type === "release-intent") {
109 var _session = message.session;
110 var _debug = message.debug;
111 waitInQueue(function () {
112 return handleReleaseIntent(_session, _debug, id, port);
113 });
114 }
115
116 if (message.type === "release-done") {
117 handleReleaseDone(id); // port is the same as original
118 }
119
120 if (message.type === "enumerate-intent") {
121 waitInQueue(function () {
122 return handleEnumerateIntent(id, port);
123 });
124 }
125
126 if (message.type === "enumerate-done") {
127 handleReleaseDone(id); // port is the same as original
128 }
129}
130
131function handleEnumerateIntent(id, port) {
132 startLock();
133 sendBack({
134 type: "ok"
135 }, id, port); // if lock times out, promise rejects and queue goes on
136
137 return waitForLock().then(function (obj) {
138 sendBack({
139 type: "ok"
140 }, obj.id, port);
141 });
142}
143
144function handleReleaseDone(id) {
145 releaseLock({
146 id: id
147 });
148}
149
150function handleReleaseOnClose(session) {
151 var path_ = null;
152 Object.keys(normalSessions).forEach(function (kpath) {
153 if (normalSessions[kpath] === session) {
154 path_ = kpath;
155 }
156 });
157
158 if (path_ == null) {
159 return Promise.resolve();
160 }
161
162 var path = path_;
163 delete normalSessions[path];
164 delete debugSessions[path];
165 return Promise.resolve();
166}
167
168function handleReleaseIntent(session, debug, id, port) {
169 var path_ = null;
170 var sessions = debug ? debugSessions : normalSessions;
171 var otherSessions = !debug ? debugSessions : normalSessions;
172 Object.keys(sessions).forEach(function (kpath) {
173 if (sessions[kpath] === session) {
174 path_ = kpath;
175 }
176 });
177
178 if (path_ == null) {
179 sendBack({
180 type: "double-release"
181 }, id, port);
182 return Promise.resolve();
183 }
184
185 var path = path_;
186 var otherSession = otherSessions[path];
187 startLock();
188 sendBack({
189 type: "path",
190 path: path,
191 otherSession: otherSession
192 }, id, port); // if lock times out, promise rejects and queue goes on
193
194 return waitForLock().then(function (obj) {
195 // failure => nothing happens, but still has to reply "ok"
196 delete sessions[path];
197 sendBack({
198 type: "ok"
199 }, obj.id, port);
200 });
201}
202
203function handleGetSessions(id, port, devices) {
204 if (devices != null) {
205 var connected = {};
206 devices.forEach(function (d) {
207 connected[d.path] = true;
208 });
209 Object.keys(normalSessions).forEach(function (path) {
210 if (!normalSessions[path]) {
211 delete normalSessions[path];
212 }
213 });
214 Object.keys(debugSessions).forEach(function (path) {
215 if (!debugSessions[path]) {
216 delete debugSessions[path];
217 }
218 });
219 }
220
221 sendBack({
222 type: "sessions",
223 debugSessions: debugSessions,
224 normalSessions: normalSessions
225 }, id, port);
226 return Promise.resolve();
227}
228
229var lastSession = 0;
230
231function handleAcquireDone(id) {
232 releaseLock({
233 good: true,
234 id: id
235 });
236}
237
238function handleAcquireFailed(id) {
239 releaseLock({
240 good: false,
241 id: id
242 });
243}
244
245function handleAcquireIntent(path, previous, debug, id, port) {
246 var error = false;
247 var thisTable = debug ? debugSessions : normalSessions;
248 var otherTable = !debug ? debugSessions : normalSessions;
249 var realPrevious = thisTable[path];
250
251 if (realPrevious == null) {
252 error = previous != null;
253 } else {
254 error = previous !== realPrevious;
255 }
256
257 if (error) {
258 sendBack({
259 type: "wrong-previous-session"
260 }, id, port);
261 return Promise.resolve();
262 } else {
263 startLock();
264 sendBack({
265 type: "other-session",
266 otherSession: otherTable[path]
267 }, id, port); // if lock times out, promise rejects and queue goes on
268
269 return waitForLock().then(function (obj) {
270 if (obj.good) {
271 lastSession++;
272 var session = lastSession.toString();
273
274 if (debug) {
275 session = "debug" + session;
276 }
277
278 thisTable[path] = session;
279 sendBack({
280 type: "session-number",
281 number: session
282 }, obj.id, port);
283 } else {
284 // failure => nothing happens, but still has to reply "ok"
285 sendBack({
286 type: "ok"
287 }, obj.id, port);
288 }
289 });
290 }
291}
292
293function sendBack(message, id, port) {
294 port.postMessage({
295 id: id,
296 message: message
297 });
298} // when shared worker is not loaded as a shared loader, use it as a module instead
299
300
301function postModuleMessage(_ref2, fn) {
302 var id = _ref2.id,
303 message = _ref2.message;
304 handleMessage({
305 id: id,
306 message: message
307 }, {
308 postMessage: fn
309 });
310}
\No newline at end of file