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);