Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / resources / cryptotoken / requestqueue.js
blob872acefdbfaddb5090d360275f29d3e9e014e22e
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.
5 /**
6  * @fileoverview Queue of pending requests from an origin.
7  *
8  */
9 'use strict';
11 /**
12  * Represents a queued request. Once given a token, call complete() once the
13  * request is processed (or dropped.)
14  * @interface
15  */
16 function QueuedRequestToken() {}
18 /** Completes (or cancels) this queued request. */
19 QueuedRequestToken.prototype.complete = function() {};
21 /**
22  * @param {!RequestQueue} queue The queue for this request.
23  * @param {number} id An id for this request.
24  * @param {function(QueuedRequestToken)} beginCb Called when work may begin on
25  *     this request.
26  * @param {RequestToken} opt_prev Previous request in the same queue.
27  * @param {RequestToken} opt_next Next request in the same queue.
28  * @constructor
29  * @implements {QueuedRequestToken}
30  */
31 function RequestToken(queue, id, beginCb, opt_prev, opt_next) {
32   /** @private {!RequestQueue} */
33   this.queue_ = queue;
34   /** @private {number} */
35   this.id_ = id;
36   /** @type {function(QueuedRequestToken)} */
37   this.beginCb = beginCb;
38   /** @type {RequestToken} */
39   this.prev = null;
40   /** @type {RequestToken} */
41   this.next = null;
42   /** @private {boolean} */
43   this.completed_ = false;
46 /** Completes (or cancels) this queued request. */
47 RequestToken.prototype.complete = function() {
48   if (this.completed_) {
49     // Either the caller called us more than once, or the timer is firing.
50     // Either way, nothing more to do here.
51     return;
52   }
53   this.completed_ = true;
54   this.queue_.complete(this);
57 /** @return {boolean} Whether this token has already completed. */
58 RequestToken.prototype.completed = function() {
59   return this.completed_;
62 /**
63  * @constructor
64  */
65 function RequestQueue() {
66   /** @private {RequestToken} */
67   this.head_ = null;
68   /** @private {RequestToken} */
69   this.tail_ = null;
70   /** @private {number} */
71   this.id_ = 0;
74 /**
75  * Inserts this token into the queue.
76  * @param {RequestToken} token Queue token
77  * @private
78  */
79 RequestQueue.prototype.insertToken_ = function(token) {
80   console.log(UTIL_fmt('token ' + this.id_ + ' inserted'));
81   if (this.head_ === null) {
82     this.head_ = token;
83     this.tail_ = token;
84   } else {
85     if (!this.tail_) throw 'Non-empty list missing tail';
86     this.tail_.next = token;
87     token.prev = this.tail_;
88     this.tail_ = token;
89   }
92 /**
93  * Removes this token from the queue.
94  * @param {RequestToken} token Queue token
95  * @private
96  */
97 RequestQueue.prototype.removeToken_ = function(token) {
98   if (token.next) {
99     token.next.prev = token.prev;
100   }
101   if (token.prev) {
102     token.prev.next = token.next;
103   }
104   if (this.head_ === token && this.tail_ === token) {
105     this.head_ = this.tail_ = null;
106   } else {
107     if (this.head_ === token) {
108       this.head_ = token.next;
109       this.head_.prev = null;
110     }
111     if (this.tail_ === token) {
112       this.tail_ = token.prev;
113       this.tail_.next = null;
114     }
115   }
116   token.prev = token.next = null;
120  * Completes this token's request, and begins the next queued request, if one
121  * exists.
122  * @param {RequestToken} token Queue token
123  */
124 RequestQueue.prototype.complete = function(token) {
125   console.log(UTIL_fmt('token ' + this.id_ + ' completed'));
126   var next = token.next;
127   this.removeToken_(token);
128   if (next) {
129     next.beginCb(next);
130   }
133 /** @return {boolean} Whether this queue is empty. */
134 RequestQueue.prototype.empty = function() {
135   return this.head_ === null;
139  * Queues this request, and, if it's the first request, begins work on it.
140  * @param {function(QueuedRequestToken)} beginCb Called when work begins on this
141  *     request.
142  * @param {Countdown} timer Countdown timer
143  * @return {QueuedRequestToken} A token for the request.
144  */
145 RequestQueue.prototype.queueRequest = function(beginCb, timer) {
146   var startNow = this.empty();
147   var token = new RequestToken(this, ++this.id_, beginCb);
148   // Clone the timer to set a callback on it, which will ensure complete() is
149   // eventually called, even if the caller never gets around to it.
150   timer.clone(token.complete.bind(token));
151   this.insertToken_(token);
152   if (startNow) {
153     window.setTimeout(function() {
154       if (!token.completed()) {
155         token.beginCb(token);
156       }
157     }, 0);
158   }
159   return token;
163  * @constructor
164  */
165 function OriginKeyedRequestQueue() {
166   /** @private {Object<!RequestQueue>} */
167   this.requests_ = {};
171  * Queues this request, and, if it's the first request, begins work on it.
172  * @param {string} appId Application Id
173  * @param {string} origin Request origin
174  * @param {function(QueuedRequestToken)} beginCb Called when work begins on this
175  *     request.
176  * @param {Countdown} timer Countdown timer
177  * @return {QueuedRequestToken} A token for the request.
178  */
179 OriginKeyedRequestQueue.prototype.queueRequest =
180     function(appId, origin, beginCb, timer) {
181   var key = appId + ' ' + origin;
182   if (!this.requests_.hasOwnProperty(key)) {
183     this.requests_[key] = new RequestQueue();
184   }
185   var queue = this.requests_[key];
186   return queue.queueRequest(beginCb, timer);