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 {!SystemTimer} sysTimer The system timer implementation.
15 * @param {number=} timeoutMillis how long, in milliseconds, the countdown
17 * @param {Function=} cb called back when the countdown expires.
19 * @implements {Countdown}
21 function CountdownTimer(sysTimer
, timeoutMillis
, cb
) {
22 /** @private {!SystemTimer} */
23 this.sysTimer_
= sysTimer
;
24 this.remainingMillis
= 0;
25 this.setTimeout(timeoutMillis
|| 0, cb
);
29 CountdownTimer
.TIMER_INTERVAL_MILLIS
= 200;
32 * Sets a new timeout for this timer. Only possible if the timer is not
34 * @param {number} timeoutMillis how long, in milliseconds, the countdown lasts.
35 * @param {Function=} cb called back when the countdown expires.
36 * @return {boolean} whether the timeout could be set.
38 CountdownTimer
.prototype.setTimeout = function(timeoutMillis
, cb
) {
41 if (!timeoutMillis
|| timeoutMillis
< 0)
43 this.remainingMillis
= timeoutMillis
;
45 if (this.remainingMillis
> CountdownTimer
.TIMER_INTERVAL_MILLIS
) {
47 this.sysTimer_
.setInterval(this.timerTick
.bind(this),
48 CountdownTimer
.TIMER_INTERVAL_MILLIS
);
50 // Set a one-shot timer for the last interval.
52 this.sysTimer_
.setTimeout(
53 this.timerTick
.bind(this), this.remainingMillis
);
58 /** Clears this timer's timeout. Timers that are cleared become expired. */
59 CountdownTimer
.prototype.clearTimeout = function() {
61 this.sysTimer_
.clearTimeout(this.timeoutId
);
62 this.timeoutId
= undefined;
64 this.remainingMillis
= 0;
68 * @return {number} how many milliseconds are remaining until the timer expires.
70 CountdownTimer
.prototype.millisecondsUntilExpired = function() {
71 return this.remainingMillis
> 0 ? this.remainingMillis
: 0;
74 /** @return {boolean} whether the timer has expired. */
75 CountdownTimer
.prototype.expired = function() {
76 return this.remainingMillis
<= 0;
80 * Constructs a new clone of this timer, while overriding its callback.
81 * @param {Function=} cb callback for new timer.
82 * @return {!Countdown} new clone.
84 CountdownTimer
.prototype.clone = function(cb
) {
85 return new CountdownTimer(this.sysTimer_
, this.remainingMillis
, cb
);
88 /** Timer callback. */
89 CountdownTimer
.prototype.timerTick = function() {
90 this.remainingMillis
-= CountdownTimer
.TIMER_INTERVAL_MILLIS
;
92 this.sysTimer_
.clearTimeout(this.timeoutId
);
93 this.timeoutId
= undefined;
101 * A factory for creating CountdownTimers.
102 * @param {!SystemTimer} sysTimer The system timer implementation.
104 * @implements {CountdownFactory}
106 function CountdownTimerFactory(sysTimer
) {
107 /** @private {!SystemTimer} */
108 this.sysTimer_
= sysTimer
;
112 * Creates a new timer.
113 * @param {number} timeoutMillis How long, in milliseconds, the countdown lasts.
114 * @param {function()=} opt_cb Called back when the countdown expires.
115 * @return {!Countdown} The timer.
117 CountdownTimerFactory
.prototype.createTimer
=
118 function(timeoutMillis
, opt_cb
) {
119 return new CountdownTimer(this.sysTimer_
, timeoutMillis
, opt_cb
);
123 * Minimum timeout attenuation, below which a response couldn't be reasonably
124 * guaranteed, in seconds.
127 var MINIMUM_TIMEOUT_ATTENUATION_SECONDS
= 1;
130 * @param {number} timeoutSeconds Timeout value in seconds.
131 * @param {number=} opt_attenuationSeconds Attenuation value in seconds.
132 * @return {number} The timeout value, attenuated to ensure a response can be
133 * given before the timeout's expiration.
135 function attenuateTimeoutInSeconds(timeoutSeconds
, opt_attenuationSeconds
) {
136 var attenuationSeconds
=
137 opt_attenuationSeconds
|| MINIMUM_TIMEOUT_ATTENUATION_SECONDS
;
138 if (timeoutSeconds
< attenuationSeconds
)
140 return timeoutSeconds
- attenuationSeconds
;
144 * Default request timeout when none is present in the request, in seconds.
147 var DEFAULT_REQUEST_TIMEOUT_SECONDS
= 30;
150 * Gets the timeout value from the request, if any, substituting
151 * opt_defaultTimeoutSeconds or DEFAULT_REQUEST_TIMEOUT_SECONDS if the request
152 * does not contain a timeout value.
153 * @param {Object} request The request containing the timeout.
154 * @param {number=} opt_defaultTimeoutSeconds
155 * @return {number} Timeout value, in seconds.
157 function getTimeoutValueFromRequest(request
, opt_defaultTimeoutSeconds
) {
158 var timeoutValueSeconds
;
159 if (request
.hasOwnProperty('timeoutSeconds')) {
160 timeoutValueSeconds
= request
['timeoutSeconds'];
161 } else if (request
.hasOwnProperty('timeout')) {
162 timeoutValueSeconds
= request
['timeout'];
163 } else if (opt_defaultTimeoutSeconds
!== undefined) {
164 timeoutValueSeconds
= opt_defaultTimeoutSeconds
;
166 timeoutValueSeconds
= DEFAULT_REQUEST_TIMEOUT_SECONDS
;
168 return timeoutValueSeconds
;
172 * Creates a new countdown for the given timeout value, attenuated to ensure a
173 * response is given prior to the countdown's expiration, using the given timer
175 * @param {CountdownFactory} timerFactory The factory to use.
176 * @param {number} timeoutValueSeconds
177 * @param {number=} opt_attenuationSeconds Attenuation value in seconds.
178 * @return {!Countdown} A countdown timer.
180 function createAttenuatedTimer(timerFactory
, timeoutValueSeconds
,
181 opt_attenuationSeconds
) {
182 timeoutValueSeconds
= attenuateTimeoutInSeconds(timeoutValueSeconds
,
183 opt_attenuationSeconds
);
184 return timerFactory
.createTimer(timeoutValueSeconds
* 1000);