12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CHROME_BROWSER_EXTENSIONS_UPDATER_REQUEST_QUEUE_IMPL_H_ 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_UPDATER_REQUEST_QUEUE_IMPL_H_ 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/updater/request_queue.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RequestQueue<T>::RequestQueue( 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::BackoffEntry::Policy* const backoff_policy, 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& start_request_callback) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : backoff_policy_(backoff_policy), 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start_request_callback_(start_request_callback), 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_(false, false) { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)RequestQueue<T>::~RequestQueue() {} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)T* RequestQueue<T>::active_request() { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return active_request_.get(); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int RequestQueue<T>::active_request_failure_count() { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return active_backoff_entry_->failure_count(); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<T> RequestQueue<T>::reset_active_request() { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_backoff_entry_.reset(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return active_request_.Pass(); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RequestQueue<T>::ScheduleRequest(scoped_ptr<T> request) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushImpl(request.Pass(), scoped_ptr<net::BackoffEntry>( 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new net::BackoffEntry(backoff_policy_))); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartNextRequest(); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RequestQueue<T>::PushImpl(scoped_ptr<T> request, 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<net::BackoffEntry> backoff_entry) { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_requests_.push_back(Request( 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) backoff_entry.release(), request.release())); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::push_heap(pending_requests_.begin(), pending_requests_.end(), 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CompareRequests); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool RequestQueue<T>::empty() const { 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pending_requests_.empty(); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t RequestQueue<T>::size() const { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pending_requests_.size(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::TimeTicks RequestQueue<T>::NextReleaseTime() const { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return pending_requests_.front().backoff_entry->GetReleaseTime(); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RequestQueue<T>::StartNextRequest() { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (active_request_) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Already running a request, assume this method will be called again when 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the request is done. 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (empty()) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No requests in the queue, so we're done. 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks next_release = NextReleaseTime(); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks now = base::TimeTicks::Now(); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (next_release > now) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Not ready for the next update check yet, call this method when it is 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // time. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_.Start(FROM_HERE, next_release - now, 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&RequestQueue<T>::StartNextRequest, 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // pop_heap swaps the first and last elements of pending_requests_, and after 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that assures that the rest of pending_requests_ (excluding the 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // now last/formerly first element) forms a proper heap. After pop_heap 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // [begin, end-1) is a valid heap, and *(end - 1) contains the element that 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // used to be at the top of the heap. Since no elements are actually 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // removed from the container it is safe to read the entry being removed after 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // pop_heap is called (but before pop_back is called). 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::pop_heap(pending_requests_.begin(), pending_requests_.end(), 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CompareRequests); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_backoff_entry_.reset(pending_requests_.back().backoff_entry.release()); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_request_.reset(pending_requests_.back().request.release()); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_requests_.pop_back(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start_request_callback_.Run(); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RequestQueue<T>::RetryRequest(const base::TimeDelta& min_backoff_delay) { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_backoff_entry_->InformOfRequest(false); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (active_backoff_entry_->GetTimeUntilRelease() < min_backoff_delay) { 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) active_backoff_entry_->SetCustomReleaseTime( 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeTicks::Now() + min_backoff_delay); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushImpl(active_request_.Pass(), active_backoff_entry_.Pass()); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typename RequestQueue<T>::iterator RequestQueue<T>::begin() { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return iterator(pending_requests_.begin()); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typename RequestQueue<T>::iterator RequestQueue<T>::end() { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return iterator(pending_requests_.end()); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RequestQueue<T>::set_backoff_policy( 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::BackoffEntry::Policy* backoff_policy) { 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) backoff_policy_ = backoff_policy; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool RequestQueue<T>::CompareRequests( 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Request& a, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Request& b) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return a.backoff_entry->GetReleaseTime() > 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) b.backoff_entry->GetReleaseTime(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // CHROME_BROWSER_EXTENSIONS_UPDATER_REQUEST_QUEUE_IMPL_H_ 155