signer.js revision 116680a4aac90f2aa7413d9095a592090648e557
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 Handles web page requests for gnubby sign requests. 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu'use strict'; 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvar signRequestQueue = new OriginKeyedRequestQueue(); 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Handles a sign request. 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {!SignHelperFactory} factory Factory to create a sign helper. 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {MessageSender} sender The sender of the message. 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {Object} request The web page's sign request. 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {Function} sendResponse Called back with the result of the sign. 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @return {Closeable} Request handler that should be closed when the browser 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * message channel is closed. 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfunction handleSignRequest(factory, sender, request, sendResponse) { 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var sentResponse = false; 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function sendResponseOnce(r) { 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (queuedSignRequest) { 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu queuedSignRequest.close(); 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu queuedSignRequest = null; 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!sentResponse) { 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sentResponse = true; 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu try { 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If the page has gone away or the connection has otherwise gone, 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // sendResponse fails. 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sendResponse(r); 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } catch (exception) { 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu console.warn('sendResponse failed: ' + exception); 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu console.warn(UTIL_fmt('Tried to reply more than once! Juan, FIX ME')); 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function sendErrorResponse(code) { 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var response = formatWebPageResponse(GnubbyMsgTypes.SIGN_WEB_REPLY, code); 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sendResponseOnce(response); 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function sendSuccessResponse(challenge, info, browserData) { 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var responseData = {}; 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (var k in challenge) { 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu responseData[k] = challenge[k]; 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu responseData['browserData'] = B64_encode(UTIL_StringToBytes(browserData)); 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu responseData['signatureData'] = info; 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var response = formatWebPageResponse(GnubbyMsgTypes.SIGN_WEB_REPLY, 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GnubbyCodeTypes.OK, responseData); 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sendResponseOnce(response); 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var origin = getOriginFromUrl(/** @type {string} */ (sender.url)); 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!origin) { 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sendErrorResponse(GnubbyCodeTypes.BAD_REQUEST); 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return null; 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // More closure type inference fail. 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var nonNullOrigin = /** @type {string} */ (origin); 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!isValidSignRequest(request)) { 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sendErrorResponse(GnubbyCodeTypes.BAD_REQUEST); 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return null; 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var signData = request['signData']; 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // A valid sign data has at least one challenge, so get the first appId from 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // the first challenge. 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var firstAppId = signData[0]['appId']; 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var timeoutMillis = Signer.DEFAULT_TIMEOUT_MILLIS; 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (request['timeout']) { 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Request timeout is in seconds. 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu timeoutMillis = request['timeout'] * 1000; 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var timer = new CountdownTimer(timeoutMillis); 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var logMsgUrl = request['logMsgUrl']; 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Queue sign requests from the same origin, to protect against simultaneous 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // sign-out on many tabs resulting in repeated sign-in requests. 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var queuedSignRequest = new QueuedSignRequest(signData, factory, timer, 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) nonNullOrigin, sendErrorResponse, sendSuccessResponse, 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sender.tlsChannelId, logMsgUrl); 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var requestToken = signRequestQueue.queueRequest(firstAppId, nonNullOrigin, 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu queuedSignRequest.begin.bind(queuedSignRequest), timer); 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu queuedSignRequest.setToken(requestToken); 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return queuedSignRequest; 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Returns whether the request appears to be a valid sign request. 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {Object} request the request. 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return {boolean} whether the request appears valid. 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liufunction isValidSignRequest(request) { 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!request.hasOwnProperty('signData')) 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var signData = request['signData']; 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If a sign request contains an empty array of challenges, it could never 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // be fulfilled. Fail. 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!signData.length) 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return isValidSignData(signData); 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Adapter class representing a queued sign request. 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {!SignData} signData Signature data 115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {!SignHelperFactory} factory Factory for SignHelper instances 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {Countdown} timer Timeout timer 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} origin Signature origin 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {function(number)} errorCb Error callback 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {function(SignChallenge, string, string)} successCb Success callback 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string|undefined} opt_tlsChannelId TLS Channel Id 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string|undefined} opt_logMsgUrl Url to post log messages to 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @constructor 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @implements {Closeable} 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)function QueuedSignRequest(signData, factory, timer, origin, errorCb, successCb, 12646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) opt_tlsChannelId, opt_logMsgUrl) { 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {!SignData} */ 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signData_ = signData; 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {!SignHelperFactory} */ 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.factory_ = factory; 1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Countdown} */ 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.timer_ = timer; 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string} */ 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.origin_ = origin; 1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {function(number)} */ 1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_ = errorCb; 1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {function(SignChallenge, string, string)} */ 1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.successCb_ = successCb; 1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string|undefined} */ 1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.tlsChannelId_ = opt_tlsChannelId; 1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string|undefined} */ 1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.logMsgUrl_ = opt_logMsgUrl; 1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.begun_ = false; 1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.closed_ = false; 1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** Closes this sign request. */ 1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuQueuedSignRequest.prototype.close = function() { 1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.closed_) return; 1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.begun_ && this.signer_) { 1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_.close(); 1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.token_) { 1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.token_.complete(); 1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.closed_ = true; 1595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {QueuedRequestToken} token Token for this sign request. 1635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuQueuedSignRequest.prototype.setToken = function(token) { 1655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {QueuedRequestToken} */ 1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.token_ = token; 1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when this sign request may begin work. 1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {QueuedRequestToken} token Token for this sign request. 1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuQueuedSignRequest.prototype.begin = function(token) { 1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.begun_ = true; 1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.setToken(token); 1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signer_ = new Signer(this.factory_, this.timer_, this.origin_, 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) this.signerFailed_.bind(this), this.signerSucceeded_.bind(this), 1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.tlsChannelId_, this.logMsgUrl_); 1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!this.signer_.setChallenges(this.signData_)) { 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu token.complete(); 1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_(GnubbyCodeTypes.BAD_REQUEST); 1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when this request's signer fails. 1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {number} code The failure code reported by the signer. 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuQueuedSignRequest.prototype.signerFailed_ = function(code) { 1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.token_.complete(); 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_(code); 1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when this request's signer succeeds. 1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {SignChallenge} challenge The challenge that was signed. 1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string} info The sign result. 199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} browserData Browser data JSON 2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuQueuedSignRequest.prototype.signerSucceeded_ = 2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu function(challenge, info, browserData) { 2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.token_.complete(); 2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.successCb_(challenge, info, browserData); 2065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Creates an object to track signing with a gnubby. 2105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {!SignHelperFactory} helperFactory Factory to create a sign helper. 2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {Countdown} timer Timer for sign request. 2125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string} origin The origin making the request. 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {function(number)} errorCb Called when the sign operation fails. 2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {function(SignChallenge, string, string)} successCb Called when the 2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * sign operation succeeds. 2165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string=} opt_tlsChannelId the TLS channel ID, if any, of the origin 2175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * making the request. 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string=} opt_logMsgUrl The url to post log messages to. 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @constructor 2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)function Signer(helperFactory, timer, origin, errorCb, successCb, 22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) opt_tlsChannelId, opt_logMsgUrl) { 2235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Countdown} */ 2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.timer_ = timer; 2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string} */ 2265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.origin_ = origin; 2275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {function(number)} */ 2285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_ = errorCb; 2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {function(SignChallenge, string, string)} */ 2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.successCb_ = successCb; 2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string|undefined} */ 2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.tlsChannelId_ = opt_tlsChannelId; 2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {string|undefined} */ 2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.logMsgUrl_ = opt_logMsgUrl; 2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.challengesSet_ = false; 2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.done_ = false; 2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Object.<string, string>} */ 2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.browserData_ = {}; 2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Object.<string, SignChallenge>} */ 2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.serverChallenges_ = {}; 2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Allow http appIds for http origins. (Broken, but the caller deserves 2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // what they get.) 2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.allowHttp_ = this.origin_ ? this.origin_.indexOf('http://') == 0 : false; 2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Protect against helper failure with a watchdog. 2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.createWatchdog_(timer); 2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {SignHelper} */ 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.helper_ = helperFactory.createHelper(); 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Creates a timer with an expiry greater than the expiration time of the given 2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * timer. 259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {Countdown} timer Timeout timer 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.createWatchdog_ = function(timer) { 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var millis = timer.millisecondsUntilExpired(); 2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu millis += CountdownTimer.TIMER_INTERVAL_MILLIS; 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {Countdown|undefined} */ 2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.watchdogTimer_ = new CountdownTimer(millis, this.timeout_.bind(this)); 2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Default timeout value in case the caller never provides a valid timeout. 2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.DEFAULT_TIMEOUT_MILLIS = 30 * 1000; 2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Sets the challenges to be signed. 2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {SignData} signData The challenges to set. 2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return {boolean} Whether the challenges could be set. 2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.setChallenges = function(signData) { 2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.challengesSet_ || this.done_) 2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {SignData} */ 2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.signData_ = signData; 2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu /** @private {boolean} */ 2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.challengesSet_ = true; 2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.checkAppIds_(); 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 2905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Checks the app ids of incoming requests. 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @private 2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 295116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSigner.prototype.checkAppIds_ = function() { 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var appIds = getDistinctAppIds(this.signData_); 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!appIds || !appIds.length) { 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.notifyError_(GnubbyCodeTypes.BAD_REQUEST); 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** @private {!AppIdChecker} */ 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.appIdChecker_ = new AppIdChecker(this.timer_.clone(), this.origin_, 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** @type {!Array.<string>} */ (appIds), this.allowHttp_, 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.logMsgUrl_); 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.appIdChecker_.doCheck(this.appIdChecked_.bind(this)); 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/** 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Called with the result of checking app ids. When the app ids are valid, 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * adds the sign challenges to those being signed. 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @param {boolean} result Whether the app ids are valid. 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @private 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 314116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSigner.prototype.appIdChecked_ = function(result) { 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!result) { 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.notifyError_(GnubbyCodeTypes.BAD_APP_ID); 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!this.doSign_()) { 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.notifyError_(GnubbyCodeTypes.BAD_REQUEST); 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 3225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Begins signing this signer's challenges. 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @return {boolean} Whether the challenge could be added. 3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 330116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSigner.prototype.doSign_ = function() { 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var encodedChallenges = []; 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (var i = 0; i < this.signData_.length; i++) { 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var incomingChallenge = this.signData_[i]; 3345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var serverChallenge = incomingChallenge['challenge']; 3355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var appId = incomingChallenge['appId']; 3365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var encodedKeyHandle = incomingChallenge['keyHandle']; 3375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var version = incomingChallenge['version']; 3385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var browserData = 3405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu makeSignBrowserData(serverChallenge, this.origin_, this.tlsChannelId_); 3415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var encodedChallenge = makeChallenge(browserData, appId, encodedKeyHandle, 3425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu version); 3435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var key = encodedKeyHandle + encodedChallenge['challengeHash']; 3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.browserData_[key] = browserData; 3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.serverChallenges_[key] = incomingChallenge; 3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch encodedChallenges.push(encodedChallenge); 3495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var timeoutSeconds = this.timer_.millisecondsUntilExpired() / 1000.0; 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var request = makeSignHelperRequest(encodedChallenges, timeoutSeconds, 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.logMsgUrl_); 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return this.helper_.doSign(request, this.helperComplete_.bind(this)); 3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Called when the timeout expires on this signer. 3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.timeout_ = function() { 3615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.watchdogTimer_ = undefined; 3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The web page gets grumpy if it doesn't get WAIT_TOUCH within a reasonable 3635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // time. 3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.notifyError_(GnubbyCodeTypes.WAIT_TOUCH); 3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** Closes this signer. */ 3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.close = function() { 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (this.appIdChecker_) { 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.appIdChecker_.close(); 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (this.helper_) { 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.helper_.close(); 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 3755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Notifies the caller of error with the given error code. 379010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {number} code Error code 3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.notifyError_ = function(code) { 3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.done_) 3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.close(); 3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.done_ = true; 3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.errorCb_(code); 3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Notifies the caller of success. 3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {SignChallenge} challenge The challenge that was signed. 3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {string} info The sign result. 394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) * @param {string} browserData Browser data JSON 3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 3975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.notifySuccess_ = function(challenge, info, browserData) { 3985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.done_) 3995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return; 4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.close(); 4015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.done_ = true; 4025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.successCb_(challenge, info, browserData); 4035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 4045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Maps a sign helper's error code namespace to the page's error code namespace. 4075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @param {number} code Error code from DeviceStatusCodes namespace. 4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @return {number} A GnubbyCodeTypes error code. 4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 411116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSigner.mapError_ = function(code) { 4125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu var reportedError; 4135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switch (code) { 4145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DeviceStatusCodes.WRONG_DATA_STATUS: 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reportedError = GnubbyCodeTypes.NONE_PLUGGED_ENROLLED; 4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case DeviceStatusCodes.TIMEOUT_STATUS: 4195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case DeviceStatusCodes.WAIT_TOUCH_STATUS: 4205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reportedError = GnubbyCodeTypes.WAIT_TOUCH; 4215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 4225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu default: 4245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu reportedError = GnubbyCodeTypes.UNKNOWN_ERROR; 4255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 4265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 4275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return reportedError; 4285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Called by the helper upon completion. 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @param {SignHelperReply} reply The result of the sign request. 433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @param {string=} opt_source The source of the sign result. 4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 4355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 436116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSigner.prototype.helperComplete_ = function(reply, opt_source) { 4375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.clearTimeout_(); 4385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (reply.code) { 440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var reportedError = Signer.mapError_(reply.code); 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch console.log(UTIL_fmt('helper reported ' + reply.code.toString(16) + 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ', returning ' + reportedError)); 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.notifyError_(reportedError); 444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (this.logMsgUrl_ && opt_source) { 446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var logMsg = 'signed&source=' + opt_source; 447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch logMessage(logMsg, this.logMsgUrl_); 448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var key = 451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reply.responseData['keyHandle'] + reply.responseData['challengeHash']; 452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var browserData = this.browserData_[key]; 453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Notify with server-provided challenge, not the encoded one: the 454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // server-provided challenge contains additional fields it relies on. 455116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var serverChallenge = this.serverChallenges_[key]; 456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.notifySuccess_(serverChallenge, reply.responseData.signatureData, 457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browserData); 45846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 4595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 4605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu/** 4625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * Clears the timeout for this signer. 4635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu * @private 4645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu */ 4655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSigner.prototype.clearTimeout_ = function() { 4665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (this.watchdogTimer_) { 4675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.watchdogTimer_.clearTimeout(); 4685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu this.watchdogTimer_ = undefined; 4695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 4705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 471