15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @fileoverview Implements an enroll helper using USB gnubbies. 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu'use strict'; 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {!GnubbyFactory} factory A factory for Gnubby instances 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {!Countdown} timer A timer for enroll timeout 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {function(number, boolean)} errorCb Called when an enroll request 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * fails with an error code and whether any gnubbies were found. 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {function(string, string)} successCb Called with the result of a 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * successful enroll request, along with the version of the gnubby that 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * provided it. 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {(function(number, boolean)|undefined)} opt_progressCb Called with 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * progress updates to the enroll request. 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string=} opt_logMsgUrl A URL to post log messages to. 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @constructor 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @implements {EnrollHelper} 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liufunction UsbEnrollHelper(factory, timer, errorCb, successCb, opt_progressCb, 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu opt_logMsgUrl) { 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {!GnubbyFactory} */ 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.factory_ = factory; 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {!Countdown} */ 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.timer_ = timer; 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {function(number, boolean)} */ 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_ = errorCb; 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {function(string, string)} */ 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.successCb_ = successCb; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {(function(number, boolean)|undefined)} */ 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.progressCb_ = opt_progressCb; 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string|undefined} */ 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.logMsgUrl_ = opt_logMsgUrl; 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Array.<SignHelperChallenge>} */ 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signChallenges_ = []; 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signChallengesFinal_ = false; 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Array.<usbGnubby>} */ 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.waitingForTouchGnubbies_ = []; 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.closed_ = false; 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notified_ = false; 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {number|undefined} */ 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.lastProgressUpdate_ = undefined; 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signerComplete_ = false; 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.getSomeGnubbies_(); 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Attempts to enroll using the provided data. 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {Object} enrollChallenges a map of version string to enroll 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * challenges. 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {Array.<SignHelperChallenge>} signChallenges a list of sign 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * challenges for already enrolled gnubbies, to prevent double-enrolling a 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * device. 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.doEnroll = 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function(enrollChallenges, signChallenges) { 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.enrollChallenges = enrollChallenges; 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signChallengesFinal_ = true; 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.signer_) { 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_.addEncodedChallenges( 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu signChallenges, this.signChallengesFinal_); 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signChallenges_ = signChallenges; 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** Closes this helper. */ 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.close = function() { 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.closed_ = true; 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (var i = 0; i < this.waitingForTouchGnubbies_.length; i++) { 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.waitingForTouchGnubbies_[i].closeWhenIdle(); 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.waitingForTouchGnubbies_ = []; 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.signer_) { 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_.close(); 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_ = null; 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Enumerates gnubbies, and begins processing challenges upon enumeration if 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * any gnubbies are found. 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.getSomeGnubbies_ = function() { 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.factory_.enumerate(this.enumerateCallback_.bind(this)); 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called with the result of enumerating gnubbies. 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {number} rc the result of the enumerate. 102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {Array.<llGnubbyDeviceId>} indexes Device ids of enumerated gnubbies 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.enumerateCallback_ = function(rc, indexes) { 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (rc) { 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Enumerate failure is rare enough that it might be worth reporting 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // directly, rather than trying again. 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_(rc, false); 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!indexes.length) { 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.maybeReEnumerateGnubbies_(); 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.timer_.expired()) { 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_(DeviceStatusCodes.TIMEOUT_STATUS, true); 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.gotSomeGnubbies_(indexes); 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * If there's still time, re-enumerates devices and try with them. Otherwise 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * reports an error and, implicitly, stops the enroll operation. 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.maybeReEnumerateGnubbies_ = function() { 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var errorCode = DeviceStatusCodes.WRONG_DATA_STATUS; 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var anyGnubbies = false; 1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If there's still time and we're still going, retry enumerating. 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!this.closed_ && !this.timer_.expired()) { 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyProgress_(errorCode, anyGnubbies); 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var self = this; 1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Use a delayed re-enumerate to prevent hammering the system unnecessarily. 1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu window.setTimeout(function() { 1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (self.timer_.expired()) { 1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu self.notifyError_(errorCode, anyGnubbies); 1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu self.getSomeGnubbies_(); 1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu }, 200); 1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(errorCode, anyGnubbies); 1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called with the result of enumerating gnubby indexes. 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {Array.<llGnubbyDeviceId>} indexes Device ids of enumerated gnubbies 1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.gotSomeGnubbies_ = function(indexes) { 1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_ = new MultipleGnubbySigner( 1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.factory_, 1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu indexes, 1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu true /* forEnroll */, 1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signerCompleted_.bind(this), 1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signerFoundGnubby_.bind(this), 1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.timer_, 1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.logMsgUrl_); 1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.signChallengesFinal_) { 1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_.addEncodedChallenges( 1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signChallenges_, this.signChallengesFinal_); 1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.pendingSignChallenges_ = []; 1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when a MultipleGnubbySigner completes its sign request. 1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {boolean} anySucceeded whether any sign attempt completed 1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * successfully. 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {number=} errorCode an error code from a failing gnubby, if one was 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * found. 1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.signerCompleted_ = function(anySucceeded, errorCode) { 1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signerComplete_ = true; 1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The signer is not created unless some gnubbies were enumerated, so 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // anyGnubbies is mostly always true. The exception is when the last gnubby is 1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // removed, handled shortly. 1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var anyGnubbies = true; 1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!anySucceeded) { 1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (errorCode == -llGnubby.GONE) { 1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If the last gnubby was removed, report as though no gnubbies were 1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // found. 1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.maybeReEnumerateGnubbies_(); 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!errorCode) errorCode = DeviceStatusCodes.WRONG_DATA_STATUS; 1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(errorCode, anyGnubbies); 1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else if (this.anyTimeout) { 1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Some previously succeeding gnubby timed out: return its error code. 1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(this.timeoutError, anyGnubbies); 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Do nothing: signerFoundGnubby will have been called with each succeeding 1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // gnubby. 1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when a MultipleGnubbySigner finds a gnubby that can enroll. 203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {number} code Status code 204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {MultipleSignerResult} signResult Signature results 2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.signerFoundGnubby_ = function(code, signResult) { 2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var gnubby = signResult['gnubby']; 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.waitingForTouchGnubbies_.push(gnubby); 2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyProgress_(DeviceStatusCodes.WAIT_TOUCH_STATUS, true); 2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (code == DeviceStatusCodes.WRONG_DATA_STATUS) { 2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (signResult['challenge']) { 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If the signer yielded a busy open, indicate waiting for touch 2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // immediately, rather than attempting enroll. This allows the UI to 2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // update, since a busy open is a potentially long operation. 2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(DeviceStatusCodes.WAIT_TOUCH_STATUS, true); 2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.matchEnrollVersionToGnubby_(gnubby); 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Attempts to match the gnubby's U2F version with an appropriate enroll 2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * challenge. 226010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {usbGnubby} gnubby Gnubby instance 2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.matchEnrollVersionToGnubby_ = function(gnubby) { 2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!gnubby) { 2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu console.warn(UTIL_fmt('no gnubby, WTF?')); 2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gnubby.version(this.gnubbyVersioned_.bind(this, gnubby)); 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called with the result of a version command. 238010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {usbGnubby} gnubby Gnubby instance 2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {number} rc result of version command. 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {ArrayBuffer=} data version. 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.gnubbyVersioned_ = function(gnubby, rc, data) { 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (rc) { 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.removeWrongVersionGnubby_(gnubby); 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var version = UTIL_BytesToString(new Uint8Array(data || null)); 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.tryEnroll_(gnubby, version); 2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Drops the gnubby from the list of eligible gnubbies. 254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {usbGnubby} gnubby Gnubby instance 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.removeWaitingGnubby_ = function(gnubby) { 2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gnubby.closeWhenIdle(); 2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var index = this.waitingForTouchGnubbies_.indexOf(gnubby); 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (index >= 0) { 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.waitingForTouchGnubbies_.splice(index, 1); 2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Drops the gnubby from the list of eligible gnubbies, as it has the wrong 2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * version. 268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {usbGnubby} gnubby Gnubby instance 2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.removeWrongVersionGnubby_ = function(gnubby) { 2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.removeWaitingGnubby_(gnubby); 2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!this.waitingForTouchGnubbies_.length && this.signerComplete_) { 2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Whoops, this was the last gnubby: indicate there are none. 2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(DeviceStatusCodes.WRONG_DATA_STATUS, false); 2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Attempts enrolling a particular gnubby with a challenge of the appropriate 2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * version. 282010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {usbGnubby} gnubby Gnubby instance 283010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} version Protocol version 2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.tryEnroll_ = function(gnubby, version) { 2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var challenge = this.getChallengeOfVersion_(version); 2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!challenge) { 2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.removeWrongVersionGnubby_(gnubby); 2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 2925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var challengeChallenge = B64_decode(challenge['challenge']); 2935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var appIdHash = B64_decode(challenge['appIdHash']); 2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gnubby.enroll(challengeChallenge, appIdHash, 2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.enrollCallback_.bind(this, gnubby, version)); 2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Finds the (first) challenge of the given version in this helper's challenges. 300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} version Protocol version 3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return {Object} challenge, if found, or null if not. 3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.getChallengeOfVersion_ = function(version) { 3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (var i = 0; i < this.enrollChallenges.length; i++) { 3065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.enrollChallenges[i]['version'] == version) { 3075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return this.enrollChallenges[i]; 3085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return null; 3115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called with the result of an enroll request to a gnubby. 315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {usbGnubby} gnubby Gnubby instance 316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} version Protocol version 317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {number} code Status code 318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {ArrayBuffer=} infoArray Returned data 3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.enrollCallback_ = 3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function(gnubby, version, code, infoArray) { 3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.notified_) { 3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Enroll completed after previous success or failure. Disregard. 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switch (code) { 3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case -llGnubby.GONE: 3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Close this gnubby. 3305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.removeWaitingGnubby_(gnubby); 3315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!this.waitingForTouchGnubbies_.length) { 3325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Last enroll attempt is complete and last gnubby is gone: retry if 3335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // possible. 3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.maybeReEnumerateGnubbies_(); 3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 3375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DeviceStatusCodes.WAIT_TOUCH_STATUS: 3395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DeviceStatusCodes.BUSY_STATUS: 3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DeviceStatusCodes.TIMEOUT_STATUS: 3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.timer_.expired()) { 3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Store any timeout error code, to be returned from the complete 3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // callback if no other eligible gnubbies are found. 3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.anyTimeout = true; 3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.timeoutError = code; 3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Close this gnubby. 3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.removeWaitingGnubby_(gnubby); 3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!this.waitingForTouchGnubbies_.length && !this.notified_) { 3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Last enroll attempt is complete: return this error. 3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu console.log(UTIL_fmt('timeout (' + code.toString(16) + 3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ') enrolling')); 3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(code, true); 3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Notify caller of waiting for touch events. 3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (code == DeviceStatusCodes.WAIT_TOUCH_STATUS) { 3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyProgress_(code, true); 3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu window.setTimeout(this.tryEnroll_.bind(this, gnubby, version), 200); 3605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DeviceStatusCodes.OK_STATUS: 3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var info = B64_encode(new Uint8Array(infoArray || [])); 3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifySuccess_(version, info); 3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu default: 3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu console.log(UTIL_fmt('Failed to enroll gnubby: ' + code)); 3705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(code, true); 3715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 3725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 376010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {number} code Status code 377010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {boolean} anyGnubbies If any gnubbies were found 3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.notifyError_ = function(code, anyGnubbies) { 3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.notified_ || this.closed_) 3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notified_ = true; 3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.close(); 3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_(code, anyGnubbies); 3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 389010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} version Protocol version 390010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} info B64 encoded success data 3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.notifySuccess_ = function(version, info) { 3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.notified_ || this.closed_) 3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notified_ = true; 3975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.close(); 3985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.successCb_(version, info); 3995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 402010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {number} code Status code 403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {boolean} anyGnubbies If any gnubbies were found 4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelper.prototype.notifyProgress_ = function(code, anyGnubbies) { 4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.lastProgressUpdate_ == code || this.notified_ || this.closed_) 4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.lastProgressUpdate_ = code; 4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.progressCb_) this.progressCb_(code, anyGnubbies); 4115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 4125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 4145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {!GnubbyFactory} gnubbyFactory factory to create gnubbies. 4155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @constructor 4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @implements {EnrollHelperFactory} 4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liufunction UsbEnrollHelperFactory(gnubbyFactory) { 4195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {!GnubbyFactory} */ 4205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.gnubbyFactory_ = gnubbyFactory; 4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 424010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {!Countdown} timer Timeout timer 4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {function(number, boolean)} errorCb Called when an enroll request 4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * fails with an error code and whether any gnubbies were found. 4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {function(string, string)} successCb Called with the result of a 4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * successful enroll request, along with the version of the gnubby that 4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * provided it. 4305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {(function(number, boolean)|undefined)} opt_progressCb Called with 4315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * progress updates to the enroll request. 4325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string=} opt_logMsgUrl A URL to post log messages to. 4335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return {UsbEnrollHelper} the newly created helper. 4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 4355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuUsbEnrollHelperFactory.prototype.createHelper = 4365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function(timer, errorCb, successCb, opt_progressCb, opt_logMsgUrl) { 4375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var helper = 4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new UsbEnrollHelper(this.gnubbyFactory_, timer, errorCb, successCb, 4395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu opt_progressCb, opt_logMsgUrl); 4405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return helper; 4415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 442