forked from google/u2f-ref-code
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcountdowntimer.js
187 lines (171 loc) · 6.06 KB
/
countdowntimer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Copyright 2014 Google Inc. All rights reserved
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
/**
* @fileoverview Provides a countdown-based timer implementation.
*/
'use strict';
/**
* Constructs a new timer. The timer has a very limited resolution, and does
* not attempt to be millisecond accurate. Its intended use is as a
* low-precision timer that pauses while debugging.
* @param {!SystemTimer} sysTimer The system timer implementation.
* @param {number=} timeoutMillis how long, in milliseconds, the countdown
* lasts.
* @param {Function=} cb called back when the countdown expires.
* @constructor
* @implements {Countdown}
*/
function CountdownTimer(sysTimer, timeoutMillis, cb) {
/** @private {!SystemTimer} */
this.sysTimer_ = sysTimer;
this.remainingMillis = 0;
this.setTimeout(timeoutMillis || 0, cb);
}
/** Timer interval */
CountdownTimer.TIMER_INTERVAL_MILLIS = 200;
/**
* Sets a new timeout for this timer. Only possible if the timer is not
* currently active.
* @param {number} timeoutMillis how long, in milliseconds, the countdown lasts.
* @param {Function=} cb called back when the countdown expires.
* @return {boolean} whether the timeout could be set.
*/
CountdownTimer.prototype.setTimeout = function(timeoutMillis, cb) {
if (this.timeoutId)
return false;
if (!timeoutMillis || timeoutMillis < 0)
return false;
this.remainingMillis = timeoutMillis;
this.cb = cb;
if (this.remainingMillis > CountdownTimer.TIMER_INTERVAL_MILLIS) {
this.timeoutId =
this.sysTimer_.setInterval(this.timerTick.bind(this),
CountdownTimer.TIMER_INTERVAL_MILLIS);
} else {
// Set a one-shot timer for the last interval.
this.timeoutId =
this.sysTimer_.setTimeout(
this.timerTick.bind(this), this.remainingMillis);
}
return true;
};
/** Clears this timer's timeout. Timers that are cleared become expired. */
CountdownTimer.prototype.clearTimeout = function() {
if (this.timeoutId) {
this.sysTimer_.clearTimeout(this.timeoutId);
this.timeoutId = undefined;
}
this.remainingMillis = 0;
};
/**
* @return {number} how many milliseconds are remaining until the timer expires.
*/
CountdownTimer.prototype.millisecondsUntilExpired = function() {
return this.remainingMillis > 0 ? this.remainingMillis : 0;
};
/** @return {boolean} whether the timer has expired. */
CountdownTimer.prototype.expired = function() {
return this.remainingMillis <= 0;
};
/**
* Constructs a new clone of this timer, while overriding its callback.
* @param {Function=} cb callback for new timer.
* @return {!Countdown} new clone.
*/
CountdownTimer.prototype.clone = function(cb) {
return new CountdownTimer(this.sysTimer_, this.remainingMillis, cb);
};
/** Timer callback. */
CountdownTimer.prototype.timerTick = function() {
this.remainingMillis -= CountdownTimer.TIMER_INTERVAL_MILLIS;
if (this.expired()) {
this.sysTimer_.clearTimeout(this.timeoutId);
this.timeoutId = undefined;
if (this.cb) {
this.cb();
}
}
};
/**
* A factory for creating CountdownTimers.
* @param {!SystemTimer} sysTimer The system timer implementation.
* @constructor
* @implements {CountdownFactory}
*/
function CountdownTimerFactory(sysTimer) {
/** @private {!SystemTimer} */
this.sysTimer_ = sysTimer;
}
/**
* Creates a new timer.
* @param {number} timeoutMillis How long, in milliseconds, the countdown lasts.
* @param {function()=} opt_cb Called back when the countdown expires.
* @return {!Countdown} The timer.
*/
CountdownTimerFactory.prototype.createTimer =
function(timeoutMillis, opt_cb) {
return new CountdownTimer(this.sysTimer_, timeoutMillis, opt_cb);
};
/**
* Minimum timeout attenuation, below which a response couldn't be reasonably
* guaranteed, in seconds.
* @const
*/
var MINIMUM_TIMEOUT_ATTENUATION_SECONDS = 1;
/**
* @param {number} timeoutSeconds Timeout value in seconds.
* @param {number=} opt_attenuationSeconds Attenuation value in seconds.
* @return {number} The timeout value, attenuated to ensure a response can be
* given before the timeout's expiration.
*/
function attenuateTimeoutInSeconds(timeoutSeconds, opt_attenuationSeconds) {
var attenuationSeconds =
opt_attenuationSeconds || MINIMUM_TIMEOUT_ATTENUATION_SECONDS;
if (timeoutSeconds < attenuationSeconds)
return 0;
return timeoutSeconds - attenuationSeconds;
}
/**
* Default request timeout when none is present in the request, in seconds.
* @const
*/
var DEFAULT_REQUEST_TIMEOUT_SECONDS = 30;
/**
* Gets the timeout value from the request, if any, substituting
* opt_defaultTimeoutSeconds or DEFAULT_REQUEST_TIMEOUT_SECONDS if the request
* does not contain a timeout value.
* @param {Object} request The request containing the timeout.
* @param {number=} opt_defaultTimeoutSeconds
* @return {number} Timeout value, in seconds.
*/
function getTimeoutValueFromRequest(request, opt_defaultTimeoutSeconds) {
var timeoutValueSeconds;
if (request.hasOwnProperty('timeoutSeconds')) {
timeoutValueSeconds = request['timeoutSeconds'];
} else if (request.hasOwnProperty('timeout')) {
timeoutValueSeconds = request['timeout'];
} else if (opt_defaultTimeoutSeconds !== undefined) {
timeoutValueSeconds = opt_defaultTimeoutSeconds;
} else {
timeoutValueSeconds = DEFAULT_REQUEST_TIMEOUT_SECONDS;
}
return timeoutValueSeconds;
}
/**
* Creates a new countdown for the given timeout value, attenuated to ensure a
* response is given prior to the countdown's expiration, using the given timer
* factory.
* @param {CountdownFactory} timerFactory The factory to use.
* @param {number} timeoutValueSeconds
* @param {number=} opt_attenuationSeconds Attenuation value in seconds.
* @return {!Countdown} A countdown timer.
*/
function createAttenuatedTimer(timerFactory, timeoutValueSeconds,
opt_attenuationSeconds) {
timeoutValueSeconds = attenuateTimeoutInSeconds(timeoutValueSeconds,
opt_attenuationSeconds);
return timerFactory.createTimer(timeoutValueSeconds * 1000);
}