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)
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <set>
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_scheduler.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/resource_messages.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_message_delegate.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/resource_controller.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/resource_request_info.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/resource_throttle.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_message_macros.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/host_port_pair.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/http/http_server_properties.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_context.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const size_t kCoalescedTimerPeriod = 5000;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const size_t kMaxNumDelayableRequestsPerClient = 10;
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static const size_t kMaxNumDelayableRequestsPerHost = 6;
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic const size_t kMaxNumThrottledRequestsPerClient = 1;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstruct ResourceScheduler::RequestPriorityParams {
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RequestPriorityParams()
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : priority(net::DEFAULT_PRIORITY),
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      intra_priority(0) {
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RequestPriorityParams(net::RequestPriority priority, int intra_priority)
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : priority(priority),
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      intra_priority(intra_priority) {
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool operator==(const RequestPriorityParams& other) const {
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return (priority == other.priority) &&
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        (intra_priority == other.intra_priority);
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool operator!=(const RequestPriorityParams& other) const {
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return !(*this == other);
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool GreaterThan(const RequestPriorityParams& other) const {
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (priority != other.priority)
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return priority > other.priority;
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return intra_priority > other.intra_priority;
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  net::RequestPriority priority;
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int intra_priority;
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass ResourceScheduler::RequestQueue {
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  typedef std::multiset<ScheduledResourceRequest*, ScheduledResourceSorter>
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NetQueue;
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RequestQueue() : fifo_ordering_ids_(0) {}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~RequestQueue() {}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds |request| to the queue with given |priority|.
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void Insert(ScheduledResourceRequest* request);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Removes |request| from the queue.
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Erase(ScheduledResourceRequest* request) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PointerMap::iterator it = pointers_.find(request);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(it != pointers_.end());
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (it == pointers_.end())
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    queue_.erase(it->second);
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pointers_.erase(it);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  NetQueue::iterator GetNextHighestIterator() {
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return queue_.begin();
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  NetQueue::iterator End() {
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return queue_.end();
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if |request| is queued.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsQueued(ScheduledResourceRequest* request) const {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ContainsKey(pointers_, request);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if no requests are queued.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsEmpty() const { return queue_.size() == 0; }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap;
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uint32 MakeFifoOrderingId() {
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    fifo_ordering_ids_ += 1;
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return fifo_ordering_ids_;
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Used to create an ordering ID for scheduled resources so that resources
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // with same priority/intra_priority stay in fifo order.
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uint32 fifo_ordering_ids_;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NetQueue queue_;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PointerMap pointers_;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is the handle we return to the ResourceDispatcherHostImpl so it can
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// interact with the request.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ResourceScheduler::ScheduledResourceRequest
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public ResourceMessageDelegate,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public ResourceThrottle {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScheduledResourceRequest(const ClientId& client_id,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           net::URLRequest* request,
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           ResourceScheduler* scheduler,
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           const RequestPriorityParams& priority)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : ResourceMessageDelegate(request),
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client_id_(client_id),
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_(request),
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ready_(false),
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        deferred_(false),
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        classification_(NORMAL_REQUEST),
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        scheduler_(scheduler),
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        priority_(priority),
13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        fifo_ordering_(0) {
1323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_,
1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                             "url", request->url().spec());
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ScheduledResourceRequest() {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scheduler_->RemoveRequest(this);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Start() {
1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued");
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ready_ = true;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (deferred_ && request_->status().is_success()) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      deferred_ = false;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      controller()->Resume();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void set_request_priority_params(const RequestPriorityParams& priority) {
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    priority_ = priority;
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const RequestPriorityParams& get_request_priority_params() const {
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return priority_;
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const ClientId& client_id() const { return client_id_; }
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::URLRequest* url_request() { return request_; }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const net::URLRequest* url_request() const { return request_; }
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uint32 fifo_ordering() const { return fifo_ordering_; }
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void set_fifo_ordering(uint32 fifo_ordering) {
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    fifo_ordering_ = fifo_ordering;
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RequestClassification classification() const {
16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return classification_;
1645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
16503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void set_classification(RequestClassification classification) {
16603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    classification_ = classification;
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ResourceMessageDelegate interface:
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool handled = true;
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      IPC_MESSAGE_UNHANDLED(handled = false)
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return handled;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ResourceThrottle interface:
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void WillStartRequest(bool* defer) OVERRIDE {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    deferred_ = *defer = !ready_;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual const char* GetNameForLogging() const OVERRIDE {
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return "ResourceScheduler";
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void DidChangePriority(int request_id, net::RequestPriority new_priority,
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                         int intra_priority_value) {
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientId client_id_;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::URLRequest* request_;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ready_;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool deferred_;
19803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RequestClassification classification_;
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResourceScheduler* scheduler_;
200c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RequestPriorityParams priority_;
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uint32 fifo_ordering_;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool ResourceScheduler::ScheduledResourceSorter::operator()(
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ScheduledResourceRequest* a,
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const ScheduledResourceRequest* b) const {
209c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Want the set to be ordered first by decreasing priority, then by
210c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // decreasing intra_priority.
211c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // ie. with (priority, intra_priority)
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // [(1, 0), (1, 0), (0, 100), (0, 0)]
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (a->get_request_priority_params() != b->get_request_priority_params())
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return a->get_request_priority_params().GreaterThan(
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        b->get_request_priority_params());
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // If priority/intra_priority is the same, fall back to fifo ordering.
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // std::multiset doesn't guarantee this until c++11.
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return a->fifo_ordering() < b->fifo_ordering();
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
221c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ResourceScheduler::RequestQueue::Insert(
223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ScheduledResourceRequest* request) {
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(!ContainsKey(pointers_, request));
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  request->set_fifo_ordering(MakeFifoOrderingId());
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  pointers_[request] = queue_.insert(request);
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Each client represents a tab.
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass ResourceScheduler::Client {
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  explicit Client(ResourceScheduler* scheduler, bool is_visible)
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : is_audible_(false),
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        is_visible_(is_visible),
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        is_loaded_(false),
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        is_paused_(false),
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        has_body_(false),
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        using_spdy_proxy_(false),
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        in_flight_delayable_count_(0),
24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        total_layout_blocking_count_(0),
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        throttle_state_(ResourceScheduler::THROTTLED) {
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scheduler_ = scheduler;
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ~Client() {
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Update to default state and pause to ensure the scheduler has a
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // correct count of relevant types of clients.
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_visible_ = false;
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_audible_ = false;
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_paused_ = true;
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UpdateThrottleState();
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void ScheduleRequest(
2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      net::URLRequest* url_request,
2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ScheduledResourceRequest* request) {
25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (ShouldStartRequest(request) == START_REQUEST)
2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      StartRequest(request);
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    else
2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      pending_requests_.Insert(request);
26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    SetRequestClassification(request, ClassifyRequest(request));
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void RemoveRequest(ScheduledResourceRequest* request) {
2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (pending_requests_.IsQueued(request)) {
2665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      pending_requests_.Erase(request);
2675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK(!ContainsKey(in_flight_requests_, request));
2685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    } else {
2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      EraseInFlightRequest(request);
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Removing this request may have freed up another to load.
2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      LoadAnyStartablePendingRequests();
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RequestSet RemoveAllRequests() {
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RequestSet unowned_requests;
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (RequestSet::iterator it = in_flight_requests_.begin();
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         it != in_flight_requests_.end(); ++it) {
2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      unowned_requests.insert(*it);
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      (*it)->set_classification(NORMAL_REQUEST);
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
2835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ClearInFlightRequests();
2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return unowned_requests;
2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool is_active() const { return is_visible_ || is_audible_; }
288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool is_loaded() const { return is_loaded_; }
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool is_visible() const { return is_visible_; }
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnAudibilityChanged(bool is_audible) {
294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_audible == is_audible_) {
295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    is_audible_ = is_audible;
298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    UpdateThrottleState();
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnVisibilityChanged(bool is_visible) {
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_visible == is_visible_) {
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    is_visible_ = is_visible;
306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    UpdateThrottleState();
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnLoadingStateChanged(bool is_loaded) {
310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_loaded == is_loaded_) {
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    is_loaded_ = is_loaded;
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    UpdateThrottleState();
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void SetPaused() {
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    is_paused_ = true;
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    UpdateThrottleState();
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void UpdateThrottleState() {
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ClientThrottleState old_throttle_state = throttle_state_;
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!scheduler_->should_throttle()) {
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SetThrottleState(UNTHROTTLED);
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else if (is_active() && !is_loaded_) {
327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(ACTIVE_AND_LOADING);
328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (is_active()) {
329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(UNTHROTTLED);
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (is_paused_) {
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SetThrottleState(PAUSED);
332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (!scheduler_->active_clients_loaded()) {
333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(THROTTLED);
334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (is_loaded_ && scheduler_->should_coalesce()) {
335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(COALESCED);
336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (!is_active()) {
337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(UNTHROTTLED);
338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (throttle_state_ == old_throttle_state) {
341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (throttle_state_ == ACTIVE_AND_LOADING) {
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      scheduler_->IncrementActiveClientsLoading();
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else if (old_throttle_state == ACTIVE_AND_LOADING) {
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      scheduler_->DecrementActiveClientsLoading();
347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (throttle_state_ == COALESCED) {
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scheduler_->IncrementCoalescedClients();
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (old_throttle_state == COALESCED) {
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scheduler_->DecrementCoalescedClients();
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void OnNavigate() {
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    has_body_ = false;
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    is_loaded_ = false;
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void OnWillInsertBody() {
3615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    has_body_ = true;
3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LoadAnyStartablePendingRequests();
3635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void OnReceivedSpdyProxiedHttpResponse() {
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!using_spdy_proxy_) {
3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      using_spdy_proxy_ = true;
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      LoadAnyStartablePendingRequests();
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void ReprioritizeRequest(ScheduledResourceRequest* request,
3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           RequestPriorityParams old_priority_params,
3745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                           RequestPriorityParams new_priority_params) {
3755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    request->url_request()->SetPriority(new_priority_params.priority);
3765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    request->set_request_priority_params(new_priority_params);
3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!pending_requests_.IsQueued(request)) {
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DCHECK(ContainsKey(in_flight_requests_, request));
3795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // The priority and SPDY support may have changed, so update the
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // delayable count.
38103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      SetRequestClassification(request, ClassifyRequest(request));
3825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Request has already started.
3835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return;
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    pending_requests_.Erase(request);
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    pending_requests_.Insert(request);
3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (new_priority_params.priority > old_priority_params.priority) {
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // Check if this request is now able to load at its new priority.
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      LoadAnyStartablePendingRequests();
3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Called on Client creation, when a Client changes user observability,
396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // possibly when all observable Clients have finished loading, and
397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // possibly when this Client has finished loading.
398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // State changes:
399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Client became observable.
400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   any state -> UNTHROTTLED
401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Client is unobservable, but all observable clients finished loading.
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   THROTTLED -> UNTHROTTLED
403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Non-observable client finished loading.
404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   THROTTLED || UNTHROTTLED -> COALESCED
405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Non-observable client, an observable client starts loading.
406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   COALESCED -> THROTTLED
407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // A COALESCED client will transition into UNTHROTTLED when the network is
408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // woken up by a heartbeat and then transition back into COALESCED.
409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void SetThrottleState(ResourceScheduler::ClientThrottleState throttle_state) {
410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (throttle_state == throttle_state_) {
411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    throttle_state_ = throttle_state;
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (throttle_state_ != PAUSED) {
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      is_paused_ = false;
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LoadAnyStartablePendingRequests();
418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(aiolos): Stop any started but not inflght requests when
419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // switching to stricter throttle state?
420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ResourceScheduler::ClientThrottleState throttle_state() const {
423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return throttle_state_;
424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void LoadCoalescedRequests() {
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (throttle_state_ != COALESCED) {
428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return;
429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (scheduler_->active_clients_loaded()) {
431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(UNTHROTTLED);
432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      SetThrottleState(THROTTLED);
434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LoadAnyStartablePendingRequests();
436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    SetThrottleState(COALESCED);
437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
4395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
4405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  enum ShouldStartReqResult {
441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DO_NOT_START_REQUEST_AND_KEEP_SEARCHING,
443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    START_REQUEST,
4445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  };
4455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void InsertInFlightRequest(ScheduledResourceRequest* request) {
4475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    in_flight_requests_.insert(request);
44803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    SetRequestClassification(request, ClassifyRequest(request));
4495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void EraseInFlightRequest(ScheduledResourceRequest* request) {
4525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size_t erased = in_flight_requests_.erase(request);
4535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DCHECK_EQ(1u, erased);
45403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // Clear any special state that we were tracking for this request.
45503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    SetRequestClassification(request, NORMAL_REQUEST);
4565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void ClearInFlightRequests() {
4595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    in_flight_requests_.clear();
46003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    in_flight_delayable_count_ = 0;
46103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    total_layout_blocking_count_ = 0;
46203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
46303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
46403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t CountRequestsWithClassification(
46503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      const RequestClassification classification, const bool include_pending) {
46603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    size_t classification_request_count = 0;
46703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    for (RequestSet::const_iterator it = in_flight_requests_.begin();
46803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         it != in_flight_requests_.end(); ++it) {
46903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if ((*it)->classification() == classification)
47003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        classification_request_count++;
47103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
47203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (include_pending) {
47303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      for (RequestQueue::NetQueue::const_iterator
47403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)           it = pending_requests_.GetNextHighestIterator();
47503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)           it != pending_requests_.End(); ++it) {
47603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        if ((*it)->classification() == classification)
47703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          classification_request_count++;
47803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      }
47903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
48003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return classification_request_count;
4815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
4825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
48303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void SetRequestClassification(ScheduledResourceRequest* request,
48403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                RequestClassification classification) {
48503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    RequestClassification old_classification = request->classification();
48603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (old_classification == classification)
48703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return;
48803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
48903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST)
49003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      in_flight_delayable_count_--;
49103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (old_classification == LAYOUT_BLOCKING_REQUEST)
49203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      total_layout_blocking_count_--;
49303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
49403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (classification == IN_FLIGHT_DELAYABLE_REQUEST)
49503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      in_flight_delayable_count_++;
49603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (classification == LAYOUT_BLOCKING_REQUEST)
49703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      total_layout_blocking_count_++;
49803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
49903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    request->set_classification(classification);
50003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK_EQ(
50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        in_flight_delayable_count_);
50303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
50403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              total_layout_blocking_count_);
50503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RequestClassification ClassifyRequest(ScheduledResourceRequest* request) {
50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // If a request is already marked as layout-blocking make sure to keep the
50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // classification across redirects unless the priority was lowered.
51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
51103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        request->url_request()->priority() >= net::LOW) {
51203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return LAYOUT_BLOCKING_REQUEST;
51303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
51403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
51503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!has_body_ && request->url_request()->priority() >= net::LOW)
51603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return LAYOUT_BLOCKING_REQUEST;
51703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (request->url_request()->priority() < net::LOW) {
5195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      net::HostPortPair host_port_pair =
5205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          net::HostPortPair::FromURL(request->url_request()->url());
5215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      net::HttpServerProperties& http_server_properties =
5225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          *request->url_request()->context()->http_server_properties();
52303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if (!http_server_properties.SupportsSpdy(host_port_pair) &&
52403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          ContainsKey(in_flight_requests_, request)) {
52503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        return IN_FLIGHT_DELAYABLE_REQUEST;
5265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
5275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
52803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return NORMAL_REQUEST;
5295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool ShouldKeepSearching(
5325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const net::HostPortPair& active_request_host) const {
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size_t same_host_count = 0;
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (RequestSet::const_iterator it = in_flight_requests_.begin();
5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         it != in_flight_requests_.end(); ++it) {
5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      net::HostPortPair host_port_pair =
5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          net::HostPortPair::FromURL((*it)->url_request()->url());
5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (active_request_host.Equals(host_port_pair)) {
5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        same_host_count++;
5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (same_host_count >= kMaxNumDelayableRequestsPerHost)
5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          return true;
5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
5435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
5445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
5455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void StartRequest(ScheduledResourceRequest* request) {
5485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    InsertInFlightRequest(request);
5495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    request->Start();
5505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // ShouldStartRequest is the main scheduling algorithm.
5535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //
55403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Requests are evaluated on five attributes:
5555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //
556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // 1. Non-delayable requests:
5575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //   * Synchronous requests.
5585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //   * Non-HTTP[S] requests.
5595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //
560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // 2. Requests to SPDY-capable origin servers.
5615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //
562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // 3. High-priority requests:
563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * Higher priority requests (>= net::LOW).
564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //
56503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // 4. Layout-blocking requests:
56603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   * High-priority requests initiated before the renderer has a <body>.
56703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //
56803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // 5. Low priority requests
569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //
570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //  The following rules are followed:
571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //
572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //  ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules:
57303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   * Non-delayable, High-priority and SPDY capable requests are issued
57403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //     immediately.
575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * Low priority requests are delayable.
57603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   * Allow one delayable request to load at a time while layout-blocking
57703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //     requests are loading.
57803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //   * If no high priority or layout-blocking requests are in flight, start
57903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  //     loading delayable requests.
5805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //   * Never exceed 10 delayable requests in flight per client.
5815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //   * Never exceed 6 delayable requests for a given host.
582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //
583116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //  THROTTLED Clients follow these rules:
584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * Non-delayable and SPDY-capable requests are issued immediately.
585116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * At most one non-SPDY request will be issued per THROTTLED Client
586116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * If no high priority requests are in flight, start loading low priority
587116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //     requests.
588116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //
589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //  COALESCED Clients never load requests, with the following exceptions:
590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * Non-delayable requests are issued imediately.
591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * On a (currently 5 second) heart beat, they load all requests as an
592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //     UNTHROTTLED Client, and then return to the COALESCED state.
593116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //   * When an active Client makes a request, they are THROTTLED until the
594116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  //     active Client finishes loading.
5955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ShouldStartReqResult ShouldStartRequest(
5965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ScheduledResourceRequest* request) const {
5975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const net::URLRequest& url_request = *request->url_request();
598116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Syncronous requests could block the entire render, which could impact
599116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // user-observable Clients.
600116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) {
601116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return START_REQUEST;
602116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
603116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
6045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // TODO(simonjam): This may end up causing disk contention. We should
6055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // experiment with throttling if that happens.
606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(aiolos): We probably want to Coalesce these as well to avoid
607116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // waking the disk.
6085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
6095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return START_REQUEST;
6105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
612116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (throttle_state_ == COALESCED) {
613116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
6145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme)) {
6175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return START_REQUEST;
6185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    net::HostPortPair host_port_pair =
6215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        net::HostPortPair::FromURL(url_request.url());
622116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    net::HttpServerProperties& http_server_properties =
623116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        *url_request.context()->http_server_properties();
6245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // TODO(willchan): We should really improve this algorithm as described in
6265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // crbug.com/164101. Also, theoretically we should not count a SPDY request
6275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // against the delayable requests limit.
6285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (http_server_properties.SupportsSpdy(host_port_pair)) {
6295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return START_REQUEST;
6305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
632116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (throttle_state_ == THROTTLED &&
633116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) {
634116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // There may still be SPDY-capable requests that should be issued.
635116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
636116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
63803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // High-priority and layout-blocking requests.
639116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (url_request.priority() >= net::LOW) {
640116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return START_REQUEST;
641116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
642116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
64303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) {
6445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
6455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (ShouldKeepSearching(host_port_pair)) {
6485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // There may be other requests for other hosts we'd allow,
6495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // so keep checking.
6505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
6515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool have_immediate_requests_in_flight =
65403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        in_flight_requests_.size() > in_flight_delayable_count_;
65503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (have_immediate_requests_in_flight &&
65603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        total_layout_blocking_count_ != 0 &&
65703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        in_flight_delayable_count_ != 0) {
6585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
6595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return START_REQUEST;
6625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
6635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void LoadAnyStartablePendingRequests() {
6655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // We iterate through all the pending requests, starting with the highest
6665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // priority one. For each entry, one of three things can happen:
6675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // 1) We start the request, remove it from the list, and keep checking.
6685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // 2) We do NOT start the request, but ShouldStartRequest() signals us that
6695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    //     there may be room for other requests, so we keep checking and leave
6705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    //     the previous request still in the list.
6715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // 3) We do not start the request, same as above, but StartRequest() tells
6725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    //     us there's no point in checking any further requests.
6735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RequestQueue::NetQueue::iterator request_iter =
6745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        pending_requests_.GetNextHighestIterator();
6755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    while (request_iter != pending_requests_.End()) {
6775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ScheduledResourceRequest* request = *request_iter;
6785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      ShouldStartReqResult query_result = ShouldStartRequest(request);
6795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (query_result == START_REQUEST) {
6815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        pending_requests_.Erase(request);
6825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        StartRequest(request);
6835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
6845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // StartRequest can modify the pending list, so we (re)start evaluation
6855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // from the currently highest priority request. Avoid copying a singular
6865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        // iterator, which would trigger undefined behavior.
6875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (pending_requests_.GetNextHighestIterator() ==
6885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            pending_requests_.End())
6895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          break;
6905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        request_iter = pending_requests_.GetNextHighestIterator();
6915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      } else if (query_result == DO_NOT_START_REQUEST_AND_KEEP_SEARCHING) {
6925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ++request_iter;
6935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        continue;
6945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      } else {
6955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        DCHECK(query_result == DO_NOT_START_REQUEST_AND_STOP_SEARCHING);
6965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        break;
6975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
6985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
7005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
701116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool is_audible_;
702116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool is_visible_;
703116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool is_loaded_;
7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool is_paused_;
7055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool has_body_;
7065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool using_spdy_proxy_;
7075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RequestQueue pending_requests_;
7085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RequestSet in_flight_requests_;
709116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ResourceScheduler* scheduler_;
7105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The number of delayable in-flight requests.
71103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t in_flight_delayable_count_;
71203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // The number of layout-blocking in-flight requests.
71303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  size_t total_layout_blocking_count_;
714116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ResourceScheduler::ClientThrottleState throttle_state_;
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ResourceScheduler::ResourceScheduler()
7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : should_coalesce_(false),
7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      should_throttle_(false),
7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      active_clients_loading_(0),
7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      coalesced_clients_(0),
7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      coalescing_timer_(new base::Timer(true /* retain_user_task */,
7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        true /* is_repeating */)) {
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourceScheduler::~ResourceScheduler() {
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(unowned_requests_.empty());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(client_map_.empty());
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
731116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle,
732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                     bool should_coalesce) {
733116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  should_coalesce_ = should_coalesce;
734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  should_throttle_ = should_throttle;
7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  OnLoadingActiveClientsStateChangedForAllClients();
736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
738116680a4aac90f2aa7413d9095a592090648e557Ben MurdochResourceScheduler::ClientThrottleState
739116680a4aac90f2aa7413d9095a592090648e557Ben MurdochResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
740116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Client* client = GetClient(child_id, route_id);
741116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(client);
742116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return client->throttle_state();
743116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
744116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int child_id,
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int route_id,
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net::URLRequest* url_request) {
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientId client_id = MakeClientId(child_id, route_id);
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ScheduledResourceRequest> request(
752c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new ScheduledResourceRequest(client_id, url_request, this,
753c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          RequestPriorityParams(url_request->priority(), 0)));
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientMap::iterator it = client_map_.find(client_id);
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == client_map_.end()) {
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // There are several ways this could happen:
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // 1. <a ping> requests don't have a route_id.
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // 2. Most unittests don't send the IPCs needed to register Clients.
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // 3. The tab is closed while a RequestResource IPC is in flight.
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unowned_requests_.insert(request.get());
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    request->Start();
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return request.PassAs<ResourceThrottle>();
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Client* client = it->second;
7675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  client->ScheduleRequest(url_request, request.get());
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return request.PassAs<ResourceThrottle>();
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) {
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ContainsKey(unowned_requests_, request)) {
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unowned_requests_.erase(request);
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientMap::iterator client_it = client_map_.find(request->client_id());
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_it == client_map_.end()) {
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Client* client = client_it->second;
7845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  client->RemoveRequest(request);
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ResourceScheduler::OnClientCreated(int child_id,
7881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        int route_id,
7891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        bool is_visible) {
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientId client_id = MakeClientId(child_id, route_id);
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!ContainsKey(client_map_, client_id));
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Client* client = new Client(this, is_visible);
795116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  client_map_[client_id] = client;
796116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
797116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(aiolos): set Client visibility/audibility when signals are added
798116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // this will UNTHROTTLE Clients as needed
799116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  client->UpdateThrottleState();
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientId client_id = MakeClientId(child_id, route_id);
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(ContainsKey(client_map_, client_id));
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientMap::iterator it = client_map_.find(client_id);
807f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (it == client_map_.end())
808f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
809f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Client* client = it->second;
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // FYI, ResourceDispatcherHost cancels all of the requests after this function
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is called. It should end up canceling all of the requests except for a
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // cross-renderer navigation.
8145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RequestSet client_unowned_requests = client->RemoveAllRequests();
8155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (RequestSet::iterator it = client_unowned_requests.begin();
8165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       it != client_unowned_requests.end(); ++it) {
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unowned_requests_.insert(*it);
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete client;
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_map_.erase(it);
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ResourceScheduler::OnVisibilityChanged(int child_id,
8251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            int route_id,
8261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            bool is_visible) {
8271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Client* client = GetClient(child_id, route_id);
8281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(client);
8291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  client->OnVisibilityChanged(is_visible);
8301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ResourceScheduler::OnLoadingStateChanged(int child_id,
8331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              int route_id,
8341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              bool is_loaded) {
8351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Client* client = GetClient(child_id, route_id);
8361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(client);
8371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  client->OnLoadingStateChanged(is_loaded);
8381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceScheduler::OnNavigate(int child_id, int route_id) {
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientId client_id = MakeClientId(child_id, route_id);
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientMap::iterator it = client_map_.find(client_id);
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == client_map_.end()) {
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The client was likely deleted shortly before we received this IPC.
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Client* client = it->second;
8515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  client->OnNavigate();
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceScheduler::OnWillInsertBody(int child_id, int route_id) {
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientId client_id = MakeClientId(child_id, route_id);
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientMap::iterator it = client_map_.find(client_id);
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == client_map_.end()) {
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The client was likely deleted shortly before we received this IPC.
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Client* client = it->second;
8655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  client->OnWillInsertBody();
8665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
8675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ResourceScheduler::OnReceivedSpdyProxiedHttpResponse(
8695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int child_id,
8705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int route_id) {
8715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(CalledOnValidThread());
8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ClientId client_id = MakeClientId(child_id, route_id);
8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ClientMap::iterator client_it = client_map_.find(client_id);
8755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (client_it == client_map_.end()) {
8765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Client* client = client_it->second;
8805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  client->OnReceivedSpdyProxiedHttpResponse();
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
883116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ResourceScheduler::OnAudibilityChanged(int child_id,
884116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            int route_id,
885116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            bool is_audible) {
886116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Client* client = GetClient(child_id, route_id);
887116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(client);
888116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  client->OnAudibilityChanged(is_audible);
889116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
890116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
8911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ResourceScheduler::IsClientVisibleForTesting(int child_id, int route_id) {
892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  Client* client = GetClient(child_id, route_id);
893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(client);
8941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return client->is_visible();
895116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
896116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
897116680a4aac90f2aa7413d9095a592090648e557Ben MurdochResourceScheduler::Client* ResourceScheduler::GetClient(int child_id,
898116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                        int route_id) {
899116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ClientId client_id = MakeClientId(child_id, route_id);
900116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ClientMap::iterator client_it = client_map_.find(client_id);
901116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (client_it == client_map_.end()) {
902116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return NULL;
903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
904116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return client_it->second;
905116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
906116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
907116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ResourceScheduler::DecrementActiveClientsLoading() {
908116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_NE(0u, active_clients_loading_);
909116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  --active_clients_loading_;
910116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
911116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (active_clients_loading_ == 0) {
9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OnLoadingActiveClientsStateChangedForAllClients();
913116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
916116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ResourceScheduler::IncrementActiveClientsLoading() {
917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ++active_clients_loading_;
918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
919116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (active_clients_loading_ == 1) {
9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OnLoadingActiveClientsStateChangedForAllClients();
921116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
922116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
923116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ResourceScheduler::OnLoadingActiveClientsStateChangedForAllClients() {
925116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ClientMap::iterator client_it = client_map_.begin();
926116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  while (client_it != client_map_.end()) {
927116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Client* client = client_it->second;
928116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    client->UpdateThrottleState();
929116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ++client_it;
930116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
931116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
932116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t ResourceScheduler::CountActiveClientsLoading() const {
934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t active_and_loading = 0;
9355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ClientMap::const_iterator client_it = client_map_.begin();
936116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  while (client_it != client_map_.end()) {
937116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Client* client = client_it->second;
938116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (client->throttle_state() == ACTIVE_AND_LOADING) {
939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ++active_and_loading;
940116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ++client_it;
942116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
943116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return active_and_loading;
944116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
945116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ResourceScheduler::IncrementCoalescedClients() {
9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ++coalesced_clients_;
9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(should_coalesce_);
9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(coalesced_clients_, CountCoalescedClients());
9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (coalesced_clients_ == 1) {
9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coalescing_timer_->Start(
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FROM_HERE,
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kCoalescedTimerPeriod),
9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&ResourceScheduler::LoadCoalescedRequests,
9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   base::Unretained(this)));
9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ResourceScheduler::DecrementCoalescedClients() {
9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(should_coalesce_);
9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_NE(0U, coalesced_clients_);
9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  --coalesced_clients_;
9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(coalesced_clients_, CountCoalescedClients());
9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (coalesced_clients_ == 0) {
9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    coalescing_timer_->Stop();
9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t ResourceScheduler::CountCoalescedClients() const {
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(should_coalesce_);
9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t coalesced_clients = 0;
9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ClientMap::const_iterator client_it = client_map_.begin();
9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (client_it != client_map_.end()) {
9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Client* client = client_it->second;
9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (client->throttle_state() == COALESCED) {
9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ++coalesced_clients;
9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ++client_it;
9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return coalesced_clients_;
9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ResourceScheduler::LoadCoalescedRequests() {
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(should_coalesce_);
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ClientMap::iterator client_it = client_map_.begin();
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (client_it != client_map_.end()) {
9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Client* client = client_it->second;
9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    client->LoadCoalescedRequests();
9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ++client_it;
9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
994c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                            net::RequestPriority new_priority,
995c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                            int new_intra_priority_value) {
996f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (request->url_request()->load_flags() & net::LOAD_IGNORE_LIMITS) {
997f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // We should not be re-prioritizing requests with the
998f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // IGNORE_LIMITS flag.
999f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NOTREACHED();
1000f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1001f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1002c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RequestPriorityParams new_priority_params(new_priority,
1003c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      new_intra_priority_value);
1004c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  RequestPriorityParams old_priority_params =
1005c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      request->get_request_priority_params();
1006c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1007c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(old_priority_params != new_priority_params);
1008c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ClientMap::iterator client_it = client_map_.find(request->client_id());
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (client_it == client_map_.end()) {
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The client was likely deleted shortly before we received this IPC.
10125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    request->url_request()->SetPriority(new_priority_params.priority);
10135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    request->set_request_priority_params(new_priority_params);
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
10152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1017c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (old_priority_params == new_priority_params)
1018c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
1019c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Client *client = client_it->second;
10215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  client->ReprioritizeRequest(
10225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      request, old_priority_params, new_priority_params);
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
10262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int child_id, int route_id) {
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
1031