OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview A multiple gnubby signer wraps the process of opening a number | 6 * @fileoverview A multiple gnubby signer wraps the process of opening a number |
7 * of gnubbies, signing each challenge in an array of challenges until a | 7 * of gnubbies, signing each challenge in an array of challenges until a |
8 * success condition is satisfied, and yielding each succeeding gnubby. | 8 * success condition is satisfied, and yielding each succeeding gnubby. |
9 * | 9 * |
10 */ | 10 */ |
(...skipping 23 matching lines...) Expand all Loading... |
34 * whether this signer expects to produce more results. The boolean is a | 34 * whether this signer expects to produce more results. The boolean is a |
35 * hint rather than a promise: it's possible for this signer to produce | 35 * hint rather than a promise: it's possible for this signer to produce |
36 * further results after saying it doesn't expect more, or to fail to | 36 * further results after saying it doesn't expect more, or to fail to |
37 * produce further results after saying it does. | 37 * produce further results after saying it does. |
38 * @param {number} timeoutMillis A timeout value, beyond whose expiration the | 38 * @param {number} timeoutMillis A timeout value, beyond whose expiration the |
39 * signer will not attempt any new operations, assuming the caller is no | 39 * signer will not attempt any new operations, assuming the caller is no |
40 * longer interested in the outcome. | 40 * longer interested in the outcome. |
41 * @param {string=} opt_logMsgUrl A URL to post log messages to. | 41 * @param {string=} opt_logMsgUrl A URL to post log messages to. |
42 * @constructor | 42 * @constructor |
43 */ | 43 */ |
44 function MultipleGnubbySigner(forEnroll, allCompleteCb, gnubbyCompleteCb, | 44 function MultipleGnubbySigner( |
45 timeoutMillis, opt_logMsgUrl) { | 45 forEnroll, allCompleteCb, gnubbyCompleteCb, timeoutMillis, opt_logMsgUrl) { |
46 /** @private {boolean} */ | 46 /** @private {boolean} */ |
47 this.forEnroll_ = forEnroll; | 47 this.forEnroll_ = forEnroll; |
48 /** @private {function(boolean)} */ | 48 /** @private {function(boolean)} */ |
49 this.allCompleteCb_ = allCompleteCb; | 49 this.allCompleteCb_ = allCompleteCb; |
50 /** @private {function(MultipleSignerResult, boolean)} */ | 50 /** @private {function(MultipleSignerResult, boolean)} */ |
51 this.gnubbyCompleteCb_ = gnubbyCompleteCb; | 51 this.gnubbyCompleteCb_ = gnubbyCompleteCb; |
52 /** @private {string|undefined} */ | 52 /** @private {string|undefined} */ |
53 this.logMsgUrl_ = opt_logMsgUrl; | 53 this.logMsgUrl_ = opt_logMsgUrl; |
54 | 54 |
55 /** @private {Array<SignHelperChallenge>} */ | 55 /** @private {Array<SignHelperChallenge>} */ |
56 this.challenges_ = []; | 56 this.challenges_ = []; |
57 /** @private {boolean} */ | 57 /** @private {boolean} */ |
58 this.challengesSet_ = false; | 58 this.challengesSet_ = false; |
59 /** @private {boolean} */ | 59 /** @private {boolean} */ |
60 this.complete_ = false; | 60 this.complete_ = false; |
61 /** @private {number} */ | 61 /** @private {number} */ |
62 this.numComplete_ = 0; | 62 this.numComplete_ = 0; |
63 /** @private {!Object<string, GnubbyTracker>} */ | 63 /** @private {!Object<string, GnubbyTracker>} */ |
64 this.gnubbies_ = {}; | 64 this.gnubbies_ = {}; |
65 /** @private {Countdown} */ | 65 /** @private {Countdown} */ |
66 this.timer_ = DEVICE_FACTORY_REGISTRY.getCountdownFactory() | 66 this.timer_ = |
67 .createTimer(timeoutMillis); | 67 DEVICE_FACTORY_REGISTRY.getCountdownFactory().createTimer(timeoutMillis); |
68 /** @private {Countdown} */ | 68 /** @private {Countdown} */ |
69 this.reenumerateTimer_ = DEVICE_FACTORY_REGISTRY.getCountdownFactory() | 69 this.reenumerateTimer_ = |
70 .createTimer(timeoutMillis); | 70 DEVICE_FACTORY_REGISTRY.getCountdownFactory().createTimer(timeoutMillis); |
71 } | 71 } |
72 | 72 |
73 /** | 73 /** |
74 * @typedef {{ | 74 * @typedef {{ |
75 * index: string, | 75 * index: string, |
76 * signer: SingleGnubbySigner, | 76 * signer: SingleGnubbySigner, |
77 * stillGoing: boolean, | 77 * stillGoing: boolean, |
78 * errorStatus: number | 78 * errorStatus: number |
79 * }} | 79 * }} |
80 */ | 80 */ |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 * @const | 176 * @const |
177 */ | 177 */ |
178 MultipleGnubbySigner.PASSIVE_REENUMERATE_INTERVAL_MILLIS = 3000; | 178 MultipleGnubbySigner.PASSIVE_REENUMERATE_INTERVAL_MILLIS = 3000; |
179 | 179 |
180 /** | 180 /** |
181 * Reenumerates gnubbies if there's still time. | 181 * Reenumerates gnubbies if there's still time. |
182 * @param {boolean} activeScan Whether to poll more aggressively, e.g. if | 182 * @param {boolean} activeScan Whether to poll more aggressively, e.g. if |
183 * there are no devices present. | 183 * there are no devices present. |
184 * @private | 184 * @private |
185 */ | 185 */ |
186 MultipleGnubbySigner.prototype.maybeReEnumerateGnubbies_ = | 186 MultipleGnubbySigner.prototype.maybeReEnumerateGnubbies_ = function( |
187 function(activeScan) { | 187 activeScan) { |
188 if (this.reenumerateTimer_.expired()) { | 188 if (this.reenumerateTimer_.expired()) { |
189 // If the timer is expired, call timeout_ if there aren't any still-running | 189 // If the timer is expired, call timeout_ if there aren't any still-running |
190 // gnubbies. (If there are some still running, the last will call timeout_ | 190 // gnubbies. (If there are some still running, the last will call timeout_ |
191 // itself.) | 191 // itself.) |
192 if (!this.anyPending_()) { | 192 if (!this.anyPending_()) { |
193 this.timeout_(false); | 193 this.timeout_(false); |
194 } | 194 } |
195 return; | 195 return; |
196 } | 196 } |
197 // Reenumerate more aggressively if there are no gnubbies present than if | 197 // Reenumerate more aggressively if there are no gnubbies present than if |
(...skipping 26 matching lines...) Expand all Loading... |
224 * @param {GnubbyDeviceId} gnubbyId The id of the gnubby to add. | 224 * @param {GnubbyDeviceId} gnubbyId The id of the gnubby to add. |
225 * @return {boolean} Whether the gnubby was added successfully. | 225 * @return {boolean} Whether the gnubby was added successfully. |
226 * @private | 226 * @private |
227 */ | 227 */ |
228 MultipleGnubbySigner.prototype.addGnubby_ = function(gnubbyId) { | 228 MultipleGnubbySigner.prototype.addGnubby_ = function(gnubbyId) { |
229 var index = JSON.stringify(gnubbyId); | 229 var index = JSON.stringify(gnubbyId); |
230 if (this.gnubbies_.hasOwnProperty(index)) { | 230 if (this.gnubbies_.hasOwnProperty(index)) { |
231 // Can't add the same gnubby twice. | 231 // Can't add the same gnubby twice. |
232 return false; | 232 return false; |
233 } | 233 } |
234 var tracker = { | 234 var tracker = {index: index, errorStatus: 0, stillGoing: false, signer: null}; |
235 index: index, | |
236 errorStatus: 0, | |
237 stillGoing: false, | |
238 signer: null | |
239 }; | |
240 tracker.signer = new SingleGnubbySigner( | 235 tracker.signer = new SingleGnubbySigner( |
241 gnubbyId, | 236 gnubbyId, this.forEnroll_, |
242 this.forEnroll_, | 237 this.signCompletedCallback_.bind(this, tracker), this.timer_.clone(), |
243 this.signCompletedCallback_.bind(this, tracker), | |
244 this.timer_.clone(), | |
245 this.logMsgUrl_); | 238 this.logMsgUrl_); |
246 this.gnubbies_[index] = tracker; | 239 this.gnubbies_[index] = tracker; |
247 this.gnubbies_[index].stillGoing = | 240 this.gnubbies_[index].stillGoing = tracker.signer.doSign(this.challenges_); |
248 tracker.signer.doSign(this.challenges_); | |
249 if (!this.gnubbies_[index].errorStatus) { | 241 if (!this.gnubbies_[index].errorStatus) { |
250 this.gnubbies_[index].errorStatus = 0; | 242 this.gnubbies_[index].errorStatus = 0; |
251 } | 243 } |
252 return true; | 244 return true; |
253 }; | 245 }; |
254 | 246 |
255 /** | 247 /** |
256 * Called by a SingleGnubbySigner upon completion. | 248 * Called by a SingleGnubbySigner upon completion. |
257 * @param {GnubbyTracker} tracker The tracker object of the gnubby whose result | 249 * @param {GnubbyTracker} tracker The tracker object of the gnubby whose result |
258 * this is. | 250 * this is. |
259 * @param {SingleSignerResult} result The result of the sign operation. | 251 * @param {SingleSignerResult} result The result of the sign operation. |
260 * @private | 252 * @private |
261 */ | 253 */ |
262 MultipleGnubbySigner.prototype.signCompletedCallback_ = | 254 MultipleGnubbySigner.prototype.signCompletedCallback_ = function( |
263 function(tracker, result) { | 255 tracker, result) { |
264 console.log( | 256 console.log(UTIL_fmt( |
265 UTIL_fmt((result.code ? 'failure.' : 'success!') + | 257 (result.code ? 'failure.' : 'success!') + ' gnubby ' + tracker.index + |
266 ' gnubby ' + tracker.index + | 258 ' got code ' + result.code.toString(16))); |
267 ' got code ' + result.code.toString(16))); | |
268 if (!tracker.stillGoing) { | 259 if (!tracker.stillGoing) { |
269 console.log(UTIL_fmt('gnubby ' + tracker.index + ' no longer running!')); | 260 console.log(UTIL_fmt('gnubby ' + tracker.index + ' no longer running!')); |
270 // Shouldn't ever happen? Disregard. | 261 // Shouldn't ever happen? Disregard. |
271 return; | 262 return; |
272 } | 263 } |
273 tracker.stillGoing = false; | 264 tracker.stillGoing = false; |
274 tracker.errorStatus = result.code; | 265 tracker.errorStatus = result.code; |
275 var moreExpected = this.tallyCompletedGnubby_(); | 266 var moreExpected = this.tallyCompletedGnubby_(); |
276 switch (result.code) { | 267 switch (result.code) { |
277 case DeviceStatusCodes.GONE_STATUS: | 268 case DeviceStatusCodes.GONE_STATUS: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 MultipleGnubbySigner.prototype.anyPending_ = function() { | 301 MultipleGnubbySigner.prototype.anyPending_ = function() { |
311 return this.numComplete_ < Object.keys(this.gnubbies_).length; | 302 return this.numComplete_ < Object.keys(this.gnubbies_).length; |
312 }; | 303 }; |
313 | 304 |
314 /** | 305 /** |
315 * Called upon timeout. | 306 * Called upon timeout. |
316 * @param {boolean} anyPending Whether any gnubbies are awaiting results. | 307 * @param {boolean} anyPending Whether any gnubbies are awaiting results. |
317 * @private | 308 * @private |
318 */ | 309 */ |
319 MultipleGnubbySigner.prototype.timeout_ = function(anyPending) { | 310 MultipleGnubbySigner.prototype.timeout_ = function(anyPending) { |
320 if (this.complete_) return; | 311 if (this.complete_) |
| 312 return; |
321 this.complete_ = true; | 313 this.complete_ = true; |
322 // Defer notifying the caller that all are complete, in case the caller is | 314 // Defer notifying the caller that all are complete, in case the caller is |
323 // doing work in response to a gnubbyFound callback and has an inconsistent | 315 // doing work in response to a gnubbyFound callback and has an inconsistent |
324 // view of the state of this signer. | 316 // view of the state of this signer. |
325 var self = this; | 317 var self = this; |
326 window.setTimeout(function() { | 318 window.setTimeout(function() { |
327 self.allCompleteCb_(anyPending); | 319 self.allCompleteCb_(anyPending); |
328 }, 0); | 320 }, 0); |
329 }; | 321 }; |
330 | 322 |
331 /** | 323 /** |
332 * @param {GnubbyTracker} tracker The tracker object of the gnubby whose result | 324 * @param {GnubbyTracker} tracker The tracker object of the gnubby whose result |
333 * this is. | 325 * this is. |
334 * @param {SingleSignerResult} result Result object. | 326 * @param {SingleSignerResult} result Result object. |
335 * @param {boolean} moreExpected Whether more gnubbies may still produce an | 327 * @param {boolean} moreExpected Whether more gnubbies may still produce an |
336 * outcome. | 328 * outcome. |
337 * @private | 329 * @private |
338 */ | 330 */ |
339 MultipleGnubbySigner.prototype.notifyGnubbyComplete_ = | 331 MultipleGnubbySigner.prototype.notifyGnubbyComplete_ = function( |
340 function(tracker, result, moreExpected) { | 332 tracker, result, moreExpected) { |
341 console.log(UTIL_fmt('gnubby ' + tracker.index + ' complete (' + | 333 console.log(UTIL_fmt( |
342 result.code.toString(16) + ')')); | 334 'gnubby ' + tracker.index + ' complete (' + result.code.toString(16) + |
| 335 ')')); |
343 var signResult = { | 336 var signResult = { |
344 'code': result.code, | 337 'code': result.code, |
345 'gnubby': result.gnubby, | 338 'gnubby': result.gnubby, |
346 'gnubbyId': tracker.signer.getDeviceId() | 339 'gnubbyId': tracker.signer.getDeviceId() |
347 }; | 340 }; |
348 if (result['challenge']) | 341 if (result['challenge']) |
349 signResult['challenge'] = result['challenge']; | 342 signResult['challenge'] = result['challenge']; |
350 if (result['info']) | 343 if (result['info']) |
351 signResult['info'] = result['info']; | 344 signResult['info'] = result['info']; |
352 this.gnubbyCompleteCb_(signResult, moreExpected); | 345 this.gnubbyCompleteCb_(signResult, moreExpected); |
353 }; | 346 }; |
OLD | NEW |