Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: content/browser/loader/resource_scheduler.cc

Issue 11270027: Add a ResourceScheduler to ResourceDispatcherHost. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use ResourceThrottle Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/loader/resource_scheduler.h"
6
7 #include "base/stl_util.h"
8 #include "content/public/browser/resource_controller.h"
9 #include "content/public/browser/resource_throttle.h"
10 #include "net/base/load_flags.h"
11 #include "net/base/request_priority.h"
12 #include "net/url_request/url_request.h"
13
14 namespace content {
15
16 namespace {
17
18 ResourceScheduler::ClientId MakeClientId(int child_id, int route_id) {
19 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
20 }
21
22 } // unnamed namespace
23
24 class ResourceScheduler::ScheduledResourceThrottle : public ResourceThrottle {
25 public:
26 ScheduledResourceThrottle(const ClientId& client_id,
27 const net::URLRequest& request,
28 ResourceScheduler* scheduler)
29 : client_id_(client_id),
30 request_(request),
31 ready_(false),
32 deferred_(false),
33 scheduler_(scheduler) {
34 }
35
36 virtual ~ScheduledResourceThrottle() {
37 scheduler_->RemoveRequest(this);
38 }
39
40 void Start() {
41 ready_ = true;
42 if (deferred_) {
43 controller()->Resume();
44 }
45 }
46
47 const ClientId& client_id() const { return client_id_; }
48 const net::URLRequest& url_request() const { return request_; }
49
50 private:
51 virtual void WillStartRequest(bool* defer) OVERRIDE {
52 deferred_ = *defer = !ready_;
53 }
54
55 ClientId client_id_;
56 const net::URLRequest& request_;
57 bool ready_;
58 bool deferred_;
59 ResourceScheduler* scheduler_;
60
61 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceThrottle);
62 };
63
64 ResourceScheduler::ResourceScheduler() {
65 }
66
67 ResourceScheduler::~ResourceScheduler() {
68 }
69
70 scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
71 int child_id,
72 int route_id,
73 const net::URLRequest& url_request) {
74 ClientId client_id = MakeClientId(child_id, route_id);
75 scoped_ptr<ScheduledResourceThrottle> request(
darin (slow to review) 2012/12/15 05:20:47 nit: might be nice to improve the terms here. Sch
James Simonsen 2012/12/17 21:31:38 Done. ScheduledResourceRequest. WDYT?
76 new ScheduledResourceThrottle(client_id, url_request, this));
77
78 if (route_id == 0 || !ContainsKey(client_map_, client_id)) {
79 // <a ping> requests don't belong to a specific page. Most tests don't call
80 // OnCreate et. al. as needed to register Clients either.
81 unowned_requests_.insert(request.get());
82 request->Start();
83 return request.PassAs<ResourceThrottle>();
84 }
85
86 Client* client = client_map_[client_id];
87 DCHECK(!client->has_closed);
88
89 // Treat synchronous requests as high priority.
90 bool is_low_priority = url_request.priority() < net::MEDIUM &&
91 !(url_request.load_flags() & net::LOAD_IGNORE_LIMITS);
92
93 if (is_low_priority && !client->in_flight_requests.empty() &&
94 !client->has_painted) {
95 client->pending_requests.push_back(request.get());
96 } else {
97 StartRequest(request.get(), client);
98 }
99 return request.PassAs<ResourceThrottle>();
100 }
101
102 void ResourceScheduler::RemoveRequest(ScheduledResourceThrottle* request) {
103 if (ContainsKey(unowned_requests_, request)) {
104 unowned_requests_.erase(request);
105 return;
106 }
107
108 DCHECK(ContainsKey(client_map_, request->client_id()));
109 Client* client = client_map_[request->client_id()];
110 RequestSet::iterator it = client->in_flight_requests.find(request);
111 if (it == client->in_flight_requests.end()) {
112 bool removed = false;
113 RequestQueue::iterator queue_it;
114 for (queue_it = client->pending_requests.begin();
115 queue_it != client->pending_requests.end(); ++queue_it) {
116 if (*queue_it == request) {
117 client->pending_requests.erase(queue_it);
118 removed = true;
119 break;
120 }
121 }
122 DCHECK(removed);
123 DCHECK(!ContainsKey(client->in_flight_requests, request));
124 } else {
125 size_t erased = client->in_flight_requests.erase(request);
126 DCHECK(erased);
127 }
128
129 if (client->has_closed) {
130 if (client->in_flight_requests.empty()
131 && client->pending_requests.empty()) {
132 delete client;
133 client_map_.erase(request->client_id());
134 }
135 } else if (client->in_flight_requests.empty()) {
136 LoadPendingRequests(client);
137 }
138 }
139
140 void ResourceScheduler::OnCreate(int child_id, int route_id) {
141 ClientId client_id = MakeClientId(child_id, route_id);
142 DCHECK(!ContainsKey(client_map_, client_id));
143 client_map_[client_id] = new Client;
144 }
145
146 void ResourceScheduler::OnNavigate(int child_id, int route_id) {
147 ClientId client_id = MakeClientId(child_id, route_id);
148 if (!ContainsKey(client_map_, client_id)) {
149 return;
150 }
151
152 Client* client = client_map_[client_id];
153 client->has_painted = false;
154 }
155
156 void ResourceScheduler::OnFirstPaint(int child_id, int route_id) {
157 ClientId client_id = MakeClientId(child_id, route_id);
158 if (!ContainsKey(client_map_, client_id)) {
159 return;
160 }
161
162 Client* client = client_map_[client_id];
163 if (!client->has_painted) {
164 client->has_painted = true;
165 LoadPendingRequests(client);
166 }
167 }
168
169 void ResourceScheduler::OnDestroy(int child_id, int route_id) {
170 ClientId client_id = MakeClientId(child_id, route_id);
171 if (!ContainsKey(client_map_, client_id)) {
172 return;
173 }
174
175 Client* client = client_map_[client_id];
176 if (client->pending_requests.empty() && client->in_flight_requests.empty()) {
177 delete client;
178 client_map_.erase(client_id);
179 } else {
180 client->has_closed = true;
181 }
182 }
183
184 void ResourceScheduler::StartRequest(ScheduledResourceThrottle* request,
185 Client* client) {
186 client->in_flight_requests.insert(request);
187 request->Start();
188 }
189
190 void ResourceScheduler::LoadPendingRequests(Client* client) {
191 RequestQueue::iterator it;
192 for (it = client->pending_requests.begin();
193 it != client->pending_requests.end(); ++it) {
194 StartRequest(*it, client);
195 }
196 client->pending_requests.clear();
197 }
198
199 ResourceScheduler::Client::Client()
200 : has_painted(false),
201 has_closed(false) {
202 }
203
204 ResourceScheduler::Client::~Client() {
205 }
206
207 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698