Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / resources / cryptotoken / requestqueue.js
bloba787e59f40d454620ea8859aab10355d40c663d5
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  * @param {!SystemTimer} sysTimer A system timer implementation.
64  * @constructor
65  */
66 function RequestQueue(sysTimer) {
67   /** @private {!SystemTimer} */
68   this.sysTimer_ = sysTimer;
69   /** @private {RequestToken} */
70   this.head_ = null;
71   /** @private {RequestToken} */
72   this.tail_ = null;
73   /** @private {number} */
74   this.id_ = 0;
77 /**
78  * Inserts this token into the queue.
79  * @param {RequestToken} token Queue token
80  * @private
81  */
82 RequestQueue.prototype.insertToken_ = function(token) {
83   console.log(UTIL_fmt('token ' + this.id_ + ' inserted'));
84   if (this.head_ === null) {
85     this.head_ = token;
86     this.tail_ = token;
87   } else {
88     if (!this.tail_) throw 'Non-empty list missing tail';
89     this.tail_.next = token;
90     token.prev = this.tail_;
91     this.tail_ = token;
92   }
95 /**
96  * Removes this token from the queue.
97  * @param {RequestToken} token Queue token
98  * @private
99  */
100 RequestQueue.prototype.removeToken_ = function(token) {
101   if (token.next) {
102     token.next.prev = token.prev;
103   }
104   if (token.prev) {
105     token.prev.next = token.next;
106   }
107   if (this.head_ === token && this.tail_ === token) {
108     this.head_ = this.tail_ = null;
109   } else {
110     if (this.head_ === token) {
111       this.head_ = token.next;
112       this.head_.prev = null;
113     }
114     if (this.tail_ === token) {
115       this.tail_ = token.prev;
116       this.tail_.next = null;
117     }
118   }
119   token.prev = token.next = null;
123  * Completes this token's request, and begins the next queued request, if one
124  * exists.
125  * @param {RequestToken} token Queue token
126  */
127 RequestQueue.prototype.complete = function(token) {
128   console.log(UTIL_fmt('token ' + this.id_ + ' completed'));
129   var next = token.next;
130   this.removeToken_(token);
131   if (next) {
132     next.beginCb(next);
133   }
136 /** @return {boolean} Whether this queue is empty. */
137 RequestQueue.prototype.empty = function() {
138   return this.head_ === null;
142  * Queues this request, and, if it's the first request, begins work on it.
143  * @param {function(QueuedRequestToken)} beginCb Called when work begins on this
144  *     request.
145  * @param {Countdown} timer Countdown timer
146  * @return {QueuedRequestToken} A token for the request.
147  */
148 RequestQueue.prototype.queueRequest = function(beginCb, timer) {
149   var startNow = this.empty();
150   var token = new RequestToken(this, ++this.id_, beginCb);
151   // Clone the timer to set a callback on it, which will ensure complete() is
152   // eventually called, even if the caller never gets around to it.
153   timer.clone(token.complete.bind(token));
154   this.insertToken_(token);
155   if (startNow) {
156     this.sysTimer_.setTimeout(function() {
157       if (!token.completed()) {
158         token.beginCb(token);
159       }
160     }, 0);
161   }
162   return token;
166  * @param {!SystemTimer} sysTimer A system timer implementation.
167  * @constructor
168  */
169 function OriginKeyedRequestQueue(sysTimer) {
170   /** @private {!SystemTimer} */
171   this.sysTimer_ = sysTimer;
172   /** @private {Object<string, !RequestQueue>} */
173   this.requests_ = {};
177  * Queues this request, and, if it's the first request, begins work on it.
178  * @param {string} appId Application Id
179  * @param {string} origin Request origin
180  * @param {function(QueuedRequestToken)} beginCb Called when work begins on this
181  *     request.
182  * @param {Countdown} timer Countdown timer
183  * @return {QueuedRequestToken} A token for the request.
184  */
185 OriginKeyedRequestQueue.prototype.queueRequest =
186     function(appId, origin, beginCb, timer) {
187   var key = appId + ' ' + origin;
188   if (!this.requests_.hasOwnProperty(key)) {
189     this.requests_[key] = new RequestQueue(this.sysTimer_);
190   }
191   var queue = this.requests_[key];
192   return queue.queueRequest(beginCb, timer);