Home | History | Annotate | Download | only in cryptotoken
      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
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * @fileoverview Provides a countdown-based timer implementation.
      7  */
      8 'use strict';
      9 
     10 /**
     11  * Constructs a new timer.  The timer has a very limited resolution, and does
     12  * not attempt to be millisecond accurate. Its intended use is as a
     13  * low-precision timer that pauses while debugging.
     14  * @param {number=} timeoutMillis how long, in milliseconds, the countdown
     15  *     lasts.
     16  * @param {Function=} cb called back when the countdown expires.
     17  * @constructor
     18  * @implements {Countdown}
     19  */
     20 function CountdownTimer(timeoutMillis, cb) {
     21   this.remainingMillis = 0;
     22   this.setTimeout(timeoutMillis || 0, cb);
     23 }
     24 
     25 /** Timer interval */
     26 CountdownTimer.TIMER_INTERVAL_MILLIS = 200;
     27 
     28 /**
     29  * Sets a new timeout for this timer. Only possible if the timer is not
     30  * currently active.
     31  * @param {number} timeoutMillis how long, in milliseconds, the countdown lasts.
     32  * @param {Function=} cb called back when the countdown expires.
     33  * @return {boolean} whether the timeout could be set.
     34  */
     35 CountdownTimer.prototype.setTimeout = function(timeoutMillis, cb) {
     36   if (this.timeoutId)
     37     return false;
     38   if (!timeoutMillis || timeoutMillis < 0)
     39     return false;
     40   this.remainingMillis = timeoutMillis;
     41   this.cb = cb;
     42   if (this.remainingMillis > CountdownTimer.TIMER_INTERVAL_MILLIS) {
     43     this.timeoutId =
     44         window.setInterval(this.timerTick.bind(this),
     45             CountdownTimer.TIMER_INTERVAL_MILLIS);
     46   } else {
     47     // Set a one-shot timer for the last interval.
     48     this.timeoutId =
     49         window.setTimeout(this.timerTick.bind(this), this.remainingMillis);
     50   }
     51   return true;
     52 };
     53 
     54 /** Clears this timer's timeout. Timers that are cleared become expired. */
     55 CountdownTimer.prototype.clearTimeout = function() {
     56   if (this.timeoutId) {
     57     window.clearTimeout(this.timeoutId);
     58     this.timeoutId = undefined;
     59   }
     60   this.remainingMillis = 0;
     61 };
     62 
     63 /**
     64  * @return {number} how many milliseconds are remaining until the timer expires.
     65  */
     66 CountdownTimer.prototype.millisecondsUntilExpired = function() {
     67   return this.remainingMillis > 0 ? this.remainingMillis : 0;
     68 };
     69 
     70 /** @return {boolean} whether the timer has expired. */
     71 CountdownTimer.prototype.expired = function() {
     72   return this.remainingMillis <= 0;
     73 };
     74 
     75 /**
     76  * Constructs a new clone of this timer, while overriding its callback.
     77  * @param {Function=} cb callback for new timer.
     78  * @return {!Countdown} new clone.
     79  */
     80 CountdownTimer.prototype.clone = function(cb) {
     81   return new CountdownTimer(this.remainingMillis, cb);
     82 };
     83 
     84 /** Timer callback. */
     85 CountdownTimer.prototype.timerTick = function() {
     86   this.remainingMillis -= CountdownTimer.TIMER_INTERVAL_MILLIS;
     87   if (this.expired()) {
     88     window.clearTimeout(this.timeoutId);
     89     this.timeoutId = undefined;
     90     if (this.cb) {
     91       this.cb();
     92     }
     93   }
     94 };
     95 
     96 /**
     97  * A factory for creating CountdownTimers.
     98  * @constructor
     99  * @implements {CountdownFactory}
    100  */
    101 function CountdownTimerFactory() {
    102 }
    103 
    104 /**
    105  * Creates a new timer.
    106  * @param {number} timeoutMillis How long, in milliseconds, the countdown lasts.
    107  * @param {function()=} opt_cb Called back when the countdown expires.
    108  * @return {!Countdown} The timer.
    109  */
    110 CountdownTimerFactory.prototype.createTimer =
    111     function(timeoutMillis, opt_cb) {
    112   return new CountdownTimer(timeoutMillis, opt_cb);
    113 };
    114 
    115 /**
    116  * Minimum timeout attenuation, below which a response couldn't be reasonably
    117  * guaranteed, in seconds.
    118  * @const
    119  */
    120 var MINIMUM_TIMEOUT_ATTENUATION_SECONDS = 0.5;
    121 
    122 /**
    123  * @param {number} timeoutSeconds Timeout value in seconds.
    124  * @return {number} The timeout value, attenuated to ensure a response can be
    125  *     given before the timeout's expiration.
    126  * @private
    127  */
    128 function attenuateTimeoutInSeconds_(timeoutSeconds) {
    129   if (timeoutSeconds < MINIMUM_TIMEOUT_ATTENUATION_SECONDS)
    130     return 0;
    131   return timeoutSeconds - MINIMUM_TIMEOUT_ATTENUATION_SECONDS;
    132 }
    133 
    134 /**
    135  * Default request timeout when none is present in the request, in seconds.
    136  * @const
    137  */
    138 var DEFAULT_REQUEST_TIMEOUT_SECONDS = 30;
    139 
    140 /**
    141  * Creates a new countdown from the given request using the given timer factory,
    142  * attenuated to ensure a response is given prior to the countdown's expiration.
    143  * @param {CountdownFactory} timerFactory The factory to use.
    144  * @param {Object} request The request containing the timeout.
    145  * @param {number=} opt_defaultTimeoutSeconds
    146  * @return {!Countdown} A countdown timer.
    147  */
    148 function createTimerForRequest(timerFactory, request,
    149     opt_defaultTimeoutSeconds) {
    150   var timeoutValueSeconds;
    151   if (request.hasOwnProperty('timeoutSeconds')) {
    152     timeoutValueSeconds = request['timeoutSeconds'];
    153   } else if (request.hasOwnProperty('timeout')) {
    154     timeoutValueSeconds = request['timeout'];
    155   } else if (opt_defaultTimeoutSeconds !== undefined) {
    156     timeoutValueSeconds = opt_defaultTimeoutSeconds;
    157   } else {
    158     timeoutValueSeconds = DEFAULT_REQUEST_TIMEOUT_SECONDS;
    159   }
    160   timeoutValueSeconds = attenuateTimeoutInSeconds_(timeoutValueSeconds);
    161   return timerFactory.createTimer(timeoutValueSeconds * 1000);
    162 }
    163