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

Side by Side Diff: content/browser/renderer_host/async_resource_handler.cc

Issue 10568005: Balance defers with Resume. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 6 months 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/async_resource_handler.h" 5 #include "content/browser/renderer_host/async_resource_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/debug/alias.h" 10 #include "base/debug/alias.h"
11 #include "base/hash_tables.h" 11 #include "base/hash_tables.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/shared_memory.h" 13 #include "base/shared_memory.h"
14 #include "content/browser/debugger/devtools_netlog_observer.h" 14 #include "content/browser/debugger/devtools_netlog_observer.h"
15 #include "content/browser/host_zoom_map_impl.h" 15 #include "content/browser/host_zoom_map_impl.h"
16 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" 16 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
17 #include "content/browser/renderer_host/resource_message_filter.h" 17 #include "content/browser/renderer_host/resource_message_filter.h"
18 #include "content/browser/renderer_host/resource_request_info_impl.h"
18 #include "content/browser/resource_context_impl.h" 19 #include "content/browser/resource_context_impl.h"
19 #include "content/common/resource_messages.h" 20 #include "content/common/resource_messages.h"
20 #include "content/common/view_messages.h" 21 #include "content/common/view_messages.h"
21 #include "content/public/browser/global_request_id.h" 22 #include "content/public/browser/global_request_id.h"
22 #include "content/public/browser/resource_dispatcher_host_delegate.h" 23 #include "content/public/browser/resource_dispatcher_host_delegate.h"
23 #include "content/public/browser/resource_request_info.h"
24 #include "content/public/common/resource_response.h" 24 #include "content/public/common/resource_response.h"
25 #include "net/base/io_buffer.h" 25 #include "net/base/io_buffer.h"
26 #include "net/base/load_flags.h" 26 #include "net/base/load_flags.h"
27 #include "net/base/net_log.h" 27 #include "net/base/net_log.h"
28 #include "webkit/glue/resource_loader_bridge.h" 28 #include "webkit/glue/resource_loader_bridge.h"
29 29
30 using base::TimeTicks; 30 using base::TimeTicks;
31 31
32 namespace content { 32 namespace content {
33 33
34 namespace { 34 namespace {
35 35
36 // When reading, we don't know if we are going to get EOF (0 bytes read), so 36 // When reading, we don't know if we are going to get EOF (0 bytes read), so
37 // we typically have a buffer that we allocated but did not use. We keep 37 // we typically have a buffer that we allocated but did not use. We keep
38 // this buffer around for the next read as a small optimization. 38 // this buffer around for the next read as a small optimization.
39 SharedIOBuffer* g_spare_read_buffer = NULL; 39 SharedIOBuffer* g_spare_read_buffer = NULL;
40 40
41 // The initial size of the shared memory buffer. (32 kilobytes). 41 // The initial size of the shared memory buffer. (32 kilobytes).
42 const int kInitialReadBufSize = 32768; 42 const int kInitialReadBufSize = 32768;
43 43
44 // The maximum size of the shared memory buffer. (512 kilobytes). 44 // The maximum size of the shared memory buffer. (512 kilobytes).
45 const int kMaxReadBufSize = 524288; 45 const int kMaxReadBufSize = 524288;
46 46
47 // Maximum number of pending data messages sent to the renderer at any
48 // given time for a given request.
49 const int kMaxPendingDataMessages = 20;
50
47 } // namespace 51 } // namespace
48 52
49 // Our version of IOBuffer that uses shared memory. 53 // Our version of IOBuffer that uses shared memory.
50 class SharedIOBuffer : public net::IOBuffer { 54 class SharedIOBuffer : public net::IOBuffer {
51 public: 55 public:
52 explicit SharedIOBuffer(int buffer_size) 56 explicit SharedIOBuffer(int buffer_size)
53 : net::IOBuffer(), 57 : net::IOBuffer(),
54 ok_(false), 58 ok_(false),
55 buffer_size_(buffer_size) {} 59 buffer_size_(buffer_size) {}
56 60
(...skipping 17 matching lines...) Expand all
74 } 78 }
75 79
76 base::SharedMemory shared_memory_; 80 base::SharedMemory shared_memory_;
77 bool ok_; 81 bool ok_;
78 int buffer_size_; 82 int buffer_size_;
79 }; 83 };
80 84
81 AsyncResourceHandler::AsyncResourceHandler( 85 AsyncResourceHandler::AsyncResourceHandler(
82 ResourceMessageFilter* filter, 86 ResourceMessageFilter* filter,
83 int routing_id, 87 int routing_id,
84 const GURL& url, 88 net::URLRequest* request,
85 ResourceDispatcherHostImpl* rdh) 89 ResourceDispatcherHostImpl* rdh)
86 : filter_(filter), 90 : filter_(filter),
87 routing_id_(routing_id), 91 routing_id_(routing_id),
92 request_(request),
88 rdh_(rdh), 93 rdh_(rdh),
89 next_buffer_size_(kInitialReadBufSize), 94 next_buffer_size_(kInitialReadBufSize),
90 url_(url) { 95 pending_data_count_(0),
96 did_defer_(false) {
91 } 97 }
92 98
93 AsyncResourceHandler::~AsyncResourceHandler() { 99 AsyncResourceHandler::~AsyncResourceHandler() {
94 } 100 }
95 101
102 void AsyncResourceHandler::OnFollowRedirect(
103 bool has_new_first_party_for_cookies,
104 const GURL& new_first_party_for_cookies) {
105 if (!request_->status().is_success()) {
106 DVLOG(1) << "OnFollowRedirect for invalid request";
107 return;
108 }
109
110 if (has_new_first_party_for_cookies)
111 request_->set_first_party_for_cookies(new_first_party_for_cookies);
112
113 ResumeIfDeferred();
114 }
115
116 void AsyncResourceHandler::OnDataReceivedACK() {
117 // If the pending data count was higher than the max, resume the request.
118 if (--pending_data_count_ == kMaxPendingDataMessages) {
119 // Decrement the pending data count one more time because we also
120 // incremented it before deferring the request.
121 --pending_data_count_;
122
123 // Resume the request.
124 ResumeIfDeferred();
125 }
126 }
127
96 bool AsyncResourceHandler::OnUploadProgress(int request_id, 128 bool AsyncResourceHandler::OnUploadProgress(int request_id,
97 uint64 position, 129 uint64 position,
98 uint64 size) { 130 uint64 size) {
99 return filter_->Send(new ResourceMsg_UploadProgress(routing_id_, request_id, 131 return filter_->Send(new ResourceMsg_UploadProgress(routing_id_, request_id,
100 position, size)); 132 position, size));
101 } 133 }
102 134
103 bool AsyncResourceHandler::OnRequestRedirected(int request_id, 135 bool AsyncResourceHandler::OnRequestRedirected(int request_id,
104 const GURL& new_url, 136 const GURL& new_url,
105 ResourceResponse* response, 137 ResourceResponse* response,
106 bool* defer) { 138 bool* defer) {
107 *defer = true; 139 *defer = true;
108 net::URLRequest* request = rdh_->GetURLRequest( 140 MarkAsDeferred(true);
109 GlobalRequestID(filter_->child_id(), request_id)); 141
110 if (rdh_->delegate()) 142 if (rdh_->delegate())
111 rdh_->delegate()->OnRequestRedirected(request, response); 143 rdh_->delegate()->OnRequestRedirected(request_, response);
112 144
113 DevToolsNetLogObserver::PopulateResponseInfo(request, response); 145 DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
114 response->request_start = request->creation_time(); 146 response->request_start = request_->creation_time();
115 response->response_start = TimeTicks::Now(); 147 response->response_start = TimeTicks::Now();
116 return filter_->Send(new ResourceMsg_ReceivedRedirect( 148 return filter_->Send(new ResourceMsg_ReceivedRedirect(
117 routing_id_, request_id, new_url, *response)); 149 routing_id_, request_id, new_url, *response));
118 } 150 }
119 151
120 bool AsyncResourceHandler::OnResponseStarted(int request_id, 152 bool AsyncResourceHandler::OnResponseStarted(int request_id,
121 ResourceResponse* response, 153 ResourceResponse* response,
122 bool* defer) { 154 bool* defer) {
123 // For changes to the main frame, inform the renderer of the new URL's 155 // For changes to the main frame, inform the renderer of the new URL's
124 // per-host settings before the request actually commits. This way the 156 // per-host settings before the request actually commits. This way the
125 // renderer will be able to set these precisely at the time the 157 // renderer will be able to set these precisely at the time the
126 // request commits, avoiding the possibility of e.g. zooming the old content 158 // request commits, avoiding the possibility of e.g. zooming the old content
127 // or of having to layout the new content twice. 159 // or of having to layout the new content twice.
128 net::URLRequest* request = rdh_->GetURLRequest(
129 GlobalRequestID(filter_->child_id(), request_id));
130 160
131 if (rdh_->delegate()) 161 if (rdh_->delegate())
132 rdh_->delegate()->OnResponseStarted(request, response, filter_); 162 rdh_->delegate()->OnResponseStarted(request_, response, filter_);
133 163
134 DevToolsNetLogObserver::PopulateResponseInfo(request, response); 164 DevToolsNetLogObserver::PopulateResponseInfo(request_, response);
135 165
136 ResourceContext* resource_context = filter_->resource_context(); 166 ResourceContext* resource_context = filter_->resource_context();
137 HostZoomMap* host_zoom_map = 167 HostZoomMap* host_zoom_map =
138 GetHostZoomMapForResourceContext(resource_context); 168 GetHostZoomMapForResourceContext(resource_context);
139 169
140 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); 170 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
141 if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) { 171 if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) {
142 GURL request_url(request->url()); 172 const GURL& request_url = request_->url();
143 filter_->Send(new ViewMsg_SetZoomLevelForLoadingURL( 173 filter_->Send(new ViewMsg_SetZoomLevelForLoadingURL(
144 info->GetRouteID(), 174 info->GetRouteID(),
145 request_url, host_zoom_map->GetZoomLevel(net::GetHostOrSpecFromURL( 175 request_url, host_zoom_map->GetZoomLevel(net::GetHostOrSpecFromURL(
146 request_url)))); 176 request_url))));
147 } 177 }
148 178
149 response->request_start = request->creation_time(); 179 response->request_start = request_->creation_time();
150 response->response_start = TimeTicks::Now(); 180 response->response_start = TimeTicks::Now();
151 filter_->Send(new ResourceMsg_ReceivedResponse( 181 filter_->Send(new ResourceMsg_ReceivedResponse(
152 routing_id_, request_id, *response)); 182 routing_id_, request_id, *response));
153 183
154 if (request->response_info().metadata) { 184 if (request_->response_info().metadata) {
155 std::vector<char> copy(request->response_info().metadata->data(), 185 std::vector<char> copy(request_->response_info().metadata->data(),
156 request->response_info().metadata->data() + 186 request_->response_info().metadata->data() +
157 request->response_info().metadata->size()); 187 request_->response_info().metadata->size());
158 filter_->Send(new ResourceMsg_ReceivedCachedMetadata( 188 filter_->Send(new ResourceMsg_ReceivedCachedMetadata(
159 routing_id_, request_id, copy)); 189 routing_id_, request_id, copy));
160 } 190 }
161 191
162 return true; 192 return true;
163 } 193 }
164 194
165 bool AsyncResourceHandler::OnWillStart(int request_id, 195 bool AsyncResourceHandler::OnWillStart(int request_id,
166 const GURL& url, 196 const GURL& url,
167 bool* defer) { 197 bool* defer) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 return true; 230 return true;
201 DCHECK(read_buffer_.get()); 231 DCHECK(read_buffer_.get());
202 232
203 if (read_buffer_->buffer_size() == *bytes_read) { 233 if (read_buffer_->buffer_size() == *bytes_read) {
204 // The network layer has saturated our buffer. Next time, we should give it 234 // The network layer has saturated our buffer. Next time, we should give it
205 // a bigger buffer for it to fill, to minimize the number of round trips we 235 // a bigger buffer for it to fill, to minimize the number of round trips we
206 // do with the renderer process. 236 // do with the renderer process.
207 next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize); 237 next_buffer_size_ = std::min(next_buffer_size_ * 2, kMaxReadBufSize);
208 } 238 }
209 239
210 if (!rdh_->WillSendData(filter_->child_id(), request_id, defer)) { 240 if (!WillSendData(defer)) {
211 // We should not send this data now, we have too many pending requests. 241 // We should not send this data now, we have too many pending requests.
212 return true; 242 return true;
213 } 243 }
214 244
215 base::SharedMemoryHandle handle; 245 base::SharedMemoryHandle handle;
216 if (!read_buffer_->shared_memory()->GiveToProcess( 246 if (!read_buffer_->shared_memory()->GiveToProcess(
217 filter_->peer_handle(), &handle)) { 247 filter_->peer_handle(), &handle)) {
218 // We wrongfully incremented the pending data count. Fake an ACK message 248 // We wrongfully incremented the pending data count. Fake an ACK message
219 // to fix this. We can't move this call above the WillSendData because 249 // to fix this. We can't move this call above the WillSendData because
220 // it's killing our read_buffer_, and we don't want that when we pause 250 // it's killing our read_buffer_, and we don't want that when we pause
221 // the request. 251 // the request.
222 rdh_->DataReceivedACK(filter_->child_id(), request_id); 252 OnDataReceivedACK();
253
223 // We just unmapped the memory. 254 // We just unmapped the memory.
224 read_buffer_ = NULL; 255 read_buffer_ = NULL;
225 return false; 256 return false;
226 } 257 }
227 // We just unmapped the memory. 258 // We just unmapped the memory.
228 read_buffer_ = NULL; 259 read_buffer_ = NULL;
229 260
230 net::URLRequest* request = rdh_->GetURLRequest(
231 GlobalRequestID(filter_->child_id(), request_id));
232 int encoded_data_length = 261 int encoded_data_length =
233 DevToolsNetLogObserver::GetAndResetEncodedDataLength(request); 262 DevToolsNetLogObserver::GetAndResetEncodedDataLength(request_);
234 filter_->Send(new ResourceMsg_DataReceived( 263 filter_->Send(new ResourceMsg_DataReceived(
235 routing_id_, request_id, handle, *bytes_read, encoded_data_length)); 264 routing_id_, request_id, handle, *bytes_read, encoded_data_length));
236 265
237 return true; 266 return true;
238 } 267 }
239 268
240 void AsyncResourceHandler::OnDataDownloaded( 269 void AsyncResourceHandler::OnDataDownloaded(
241 int request_id, int bytes_downloaded) { 270 int request_id, int bytes_downloaded) {
242 filter_->Send(new ResourceMsg_DataDownloaded( 271 filter_->Send(new ResourceMsg_DataDownloaded(
243 routing_id_, request_id, bytes_downloaded)); 272 routing_id_, request_id, bytes_downloaded));
244 } 273 }
245 274
246 bool AsyncResourceHandler::OnResponseCompleted( 275 bool AsyncResourceHandler::OnResponseCompleted(
247 int request_id, 276 int request_id,
248 const net::URLRequestStatus& status, 277 const net::URLRequestStatus& status,
249 const std::string& security_info) { 278 const std::string& security_info) {
250 // If we crash here, figure out what URL the renderer was requesting. 279 // If we crash here, figure out what URL the renderer was requesting.
251 // http://crbug.com/107692 280 // http://crbug.com/107692
252 char url_buf[128]; 281 char url_buf[128];
253 base::strlcpy(url_buf, url_.spec().c_str(), arraysize(url_buf)); 282 base::strlcpy(url_buf, request_->url().spec().c_str(), arraysize(url_buf));
254 base::debug::Alias(url_buf); 283 base::debug::Alias(url_buf);
255 284
256 TimeTicks completion_time = TimeTicks::Now(); 285 TimeTicks completion_time = TimeTicks::Now();
257 filter_->Send(new ResourceMsg_RequestComplete(routing_id_, 286 filter_->Send(new ResourceMsg_RequestComplete(routing_id_,
258 request_id, 287 request_id,
259 status, 288 status,
260 security_info, 289 security_info,
261 completion_time)); 290 completion_time));
262 291
263 // If we still have a read buffer, then see about caching it for later... 292 // If we still have a read buffer, then see about caching it for later...
(...skipping 12 matching lines...) Expand all
276 // static 305 // static
277 void AsyncResourceHandler::GlobalCleanup() { 306 void AsyncResourceHandler::GlobalCleanup() {
278 if (g_spare_read_buffer) { 307 if (g_spare_read_buffer) {
279 // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer(). 308 // Avoid the CHECK in SharedIOBuffer::~SharedIOBuffer().
280 SharedIOBuffer* tmp = g_spare_read_buffer; 309 SharedIOBuffer* tmp = g_spare_read_buffer;
281 g_spare_read_buffer = NULL; 310 g_spare_read_buffer = NULL;
282 tmp->Release(); 311 tmp->Release();
283 } 312 }
284 } 313 }
285 314
315 bool AsyncResourceHandler::WillSendData(bool* defer) {
316 if (++pending_data_count_ > kMaxPendingDataMessages) {
317 // We reached the max number of data messages that can be sent to
318 // the renderer for a given request. Pause the request and wait for
319 // the renderer to start processing them before resuming it.
320 *defer = true;
321 MarkAsDeferred(true);
322 return false;
323 }
324
325 return true;
326 }
327
328 void AsyncResourceHandler::MarkAsDeferred(bool deferred) {
329 did_defer_ = deferred;
330
331 // Set a back-pointer from ResourceRequestInfoImpl to |this| when deferred,
332 // so that the ResourceDispatcherHostImpl can send us IPC messages.
333 // TODO(darin): Implement an IPC message filter instead?
334
335 ResourceRequestInfoImpl* info =
336 ResourceRequestInfoImpl::ForRequest(request_);
337 if (deferred) {
338 info->set_async_handler(this);
339 } else {
340 info->set_async_handler(NULL);
341 }
342 }
343
344 void AsyncResourceHandler::ResumeIfDeferred() {
345 if (did_defer_) {
346 MarkAsDeferred(false);
347 controller()->Resume();
348 }
349 }
350
286 } // namespace content 351 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/async_resource_handler.h ('k') | content/browser/renderer_host/buffered_resource_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698