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.
6 * @fileoverview Provides a countdown-based timer implementation.
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
16 * @param {Function=} cb called back when the countdown expires.
18 * @implements {Countdown}
20 function CountdownTimer(timeoutMillis
, cb
) {
21 this.remainingMillis
= 0;
22 this.setTimeout(timeoutMillis
|| 0, cb
);
26 CountdownTimer
.TIMER_INTERVAL_MILLIS
= 200;
29 * Sets a new timeout for this timer. Only possible if the timer is not
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.
35 CountdownTimer
.prototype.setTimeout = function(timeoutMillis
, cb
) {
38 if (!timeoutMillis
|| timeoutMillis
< 0)
40 this.remainingMillis
= timeoutMillis
;
42 if (this.remainingMillis
> CountdownTimer
.TIMER_INTERVAL_MILLIS
) {
44 window
.setInterval(this.timerTick
.bind(this),
45 CountdownTimer
.TIMER_INTERVAL_MILLIS
);
47 // Set a one-shot timer for the last interval.
49 window
.setTimeout(this.timerTick
.bind(this), this.remainingMillis
);
54 /** Clears this timer's timeout. Timers that are cleared become expired. */
55 CountdownTimer
.prototype.clearTimeout = function() {
57 window
.clearTimeout(this.timeoutId
);
58 this.timeoutId
= undefined;
60 this.remainingMillis
= 0;
64 * @return {number} how many milliseconds are remaining until the timer expires.
66 CountdownTimer
.prototype.millisecondsUntilExpired = function() {
67 return this.remainingMillis
> 0 ? this.remainingMillis
: 0;
70 /** @return {boolean} whether the timer has expired. */
71 CountdownTimer
.prototype.expired = function() {
72 return this.remainingMillis
<= 0;
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.
80 CountdownTimer
.prototype.clone = function(cb
) {
81 return new CountdownTimer(this.remainingMillis
, cb
);
84 /** Timer callback. */
85 CountdownTimer
.prototype.timerTick = function() {
86 this.remainingMillis
-= CountdownTimer
.TIMER_INTERVAL_MILLIS
;
88 window
.clearTimeout(this.timeoutId
);
89 this.timeoutId
= undefined;
97 * A factory for creating CountdownTimers.
99 * @implements {CountdownFactory}
101 function CountdownTimerFactory() {
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.
110 CountdownTimerFactory
.prototype.createTimer
=
111 function(timeoutMillis
, opt_cb
) {
112 return new CountdownTimer(timeoutMillis
, opt_cb
);
116 * Minimum timeout attenuation, below which a response couldn't be reasonably
117 * guaranteed, in seconds.
120 var MINIMUM_TIMEOUT_ATTENUATION_SECONDS
= 1;
123 * @param {number} timeoutSeconds Timeout value in seconds.
124 * @param {number=} opt_attenuationSeconds Attenuation value in seconds.
125 * @return {number} The timeout value, attenuated to ensure a response can be
126 * given before the timeout's expiration.
128 function attenuateTimeoutInSeconds(timeoutSeconds
, opt_attenuationSeconds
) {
129 var attenuationSeconds
=
130 opt_attenuationSeconds
|| MINIMUM_TIMEOUT_ATTENUATION_SECONDS
;
131 if (timeoutSeconds
< attenuationSeconds
)
133 return timeoutSeconds
- attenuationSeconds
;
137 * Default request timeout when none is present in the request, in seconds.
140 var DEFAULT_REQUEST_TIMEOUT_SECONDS
= 30;
143 * Gets the timeout value from the request, if any, substituting
144 * opt_defaultTimeoutSeconds or DEFAULT_REQUEST_TIMEOUT_SECONDS if the request
145 * does not contain a timeout value.
146 * @param {Object} request The request containing the timeout.
147 * @param {number=} opt_defaultTimeoutSeconds
148 * @return {number} Timeout value, in seconds.
150 function getTimeoutValueFromRequest(request
, opt_defaultTimeoutSeconds
) {
151 var timeoutValueSeconds
;
152 if (request
.hasOwnProperty('timeoutSeconds')) {
153 timeoutValueSeconds
= request
['timeoutSeconds'];
154 } else if (request
.hasOwnProperty('timeout')) {
155 timeoutValueSeconds
= request
['timeout'];
156 } else if (opt_defaultTimeoutSeconds
!== undefined) {
157 timeoutValueSeconds
= opt_defaultTimeoutSeconds
;
159 timeoutValueSeconds
= DEFAULT_REQUEST_TIMEOUT_SECONDS
;
161 return timeoutValueSeconds
;
165 * Creates a new countdown for the given timeout value, attenuated to ensure a
166 * response is given prior to the countdown's expiration, using the given timer
168 * @param {CountdownFactory} timerFactory The factory to use.
169 * @param {number} timeoutValueSeconds
170 * @param {number=} opt_attenuationSeconds Attenuation value in seconds.
171 * @return {!Countdown} A countdown timer.
173 function createAttenuatedTimer(timerFactory
, timeoutValueSeconds
,
174 opt_attenuationSeconds
) {
175 timeoutValueSeconds
= attenuateTimeoutInSeconds(timeoutValueSeconds
,
176 opt_attenuationSeconds
);
177 return timerFactory
.createTimer(timeoutValueSeconds
* 1000);