1 // Copyright (c) 2012 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 #ifndef EXTENSIONS_BROWSER_UPDATER_REQUEST_QUEUE_IMPL_H_
6 #define EXTENSIONS_BROWSER_UPDATER_REQUEST_QUEUE_IMPL_H_
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "extensions/browser/updater/request_queue.h"
16 namespace extensions
{
19 RequestQueue
<T
>::RequestQueue(
20 const net::BackoffEntry::Policy
* const backoff_policy
,
21 const base::Closure
& start_request_callback
)
22 : backoff_policy_(backoff_policy
),
23 start_request_callback_(start_request_callback
),
24 timer_(false, false) {
28 RequestQueue
<T
>::~RequestQueue() {
32 T
* RequestQueue
<T
>::active_request() {
33 return active_request_
.get();
37 int RequestQueue
<T
>::active_request_failure_count() {
38 return active_backoff_entry_
->failure_count();
42 scoped_ptr
<T
> RequestQueue
<T
>::reset_active_request() {
43 active_backoff_entry_
.reset();
44 return active_request_
.Pass();
48 void RequestQueue
<T
>::ScheduleRequest(scoped_ptr
<T
> request
) {
51 scoped_ptr
<net::BackoffEntry
>(new net::BackoffEntry(backoff_policy_
)));
56 void RequestQueue
<T
>::PushImpl(scoped_ptr
<T
> request
,
57 scoped_ptr
<net::BackoffEntry
> backoff_entry
) {
58 pending_requests_
.push_back(
59 Request(backoff_entry
.release(), request
.release()));
61 pending_requests_
.begin(), pending_requests_
.end(), CompareRequests
);
65 bool RequestQueue
<T
>::empty() const {
66 return pending_requests_
.empty();
70 size_t RequestQueue
<T
>::size() const {
71 return pending_requests_
.size();
75 base::TimeTicks RequestQueue
<T
>::NextReleaseTime() const {
76 return pending_requests_
.front().backoff_entry
->GetReleaseTime();
80 void RequestQueue
<T
>::StartNextRequest() {
82 // Already running a request, assume this method will be called again when
83 // the request is done.
87 // No requests in the queue, so we're done.
90 base::TimeTicks next_release
= NextReleaseTime();
91 base::TimeTicks now
= base::TimeTicks::Now();
92 if (next_release
> now
) {
93 // Not ready for the next update check yet, call this method when it is
98 base::Bind(&RequestQueue
<T
>::StartNextRequest
, base::Unretained(this)));
102 // pop_heap swaps the first and last elements of pending_requests_, and after
103 // that assures that the rest of pending_requests_ (excluding the
104 // now last/formerly first element) forms a proper heap. After pop_heap
105 // [begin, end-1) is a valid heap, and *(end - 1) contains the element that
106 // used to be at the top of the heap. Since no elements are actually
107 // removed from the container it is safe to read the entry being removed after
108 // pop_heap is called (but before pop_back is called).
110 pending_requests_
.begin(), pending_requests_
.end(), CompareRequests
);
112 active_backoff_entry_
.reset(pending_requests_
.back().backoff_entry
.release());
113 active_request_
.reset(pending_requests_
.back().request
.release());
115 pending_requests_
.pop_back();
117 start_request_callback_
.Run();
120 template <typename T
>
121 void RequestQueue
<T
>::RetryRequest(const base::TimeDelta
& min_backoff_delay
) {
122 active_backoff_entry_
->InformOfRequest(false);
123 if (active_backoff_entry_
->GetTimeUntilRelease() < min_backoff_delay
) {
124 active_backoff_entry_
->SetCustomReleaseTime(base::TimeTicks::Now() +
127 PushImpl(active_request_
.Pass(), active_backoff_entry_
.Pass());
130 template <typename T
>
131 typename RequestQueue
<T
>::iterator RequestQueue
<T
>::begin() {
132 return iterator(pending_requests_
.begin());
135 template <typename T
>
136 typename RequestQueue
<T
>::iterator RequestQueue
<T
>::end() {
137 return iterator(pending_requests_
.end());
140 template <typename T
>
141 void RequestQueue
<T
>::set_backoff_policy(
142 const net::BackoffEntry::Policy
* backoff_policy
) {
143 backoff_policy_
= backoff_policy
;
147 template <typename T
>
148 bool RequestQueue
<T
>::CompareRequests(const Request
& a
, const Request
& b
) {
149 return a
.backoff_entry
->GetReleaseTime() > b
.backoff_entry
->GetReleaseTime();
152 } // namespace extensions
154 #endif // EXTENSIONS_BROWSER_UPDATER_REQUEST_QUEUE_IMPL_H_