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

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

Issue 10332130: Use defer out-params instead of ResourceDispatcherHostImpl::PauseRequest(...true) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 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/buffered_resource_handler.h" 5 #include "content/browser/renderer_host/buffered_resource_handler.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 ResourceHandler* handler, 65 ResourceHandler* handler,
66 ResourceDispatcherHostImpl* host, 66 ResourceDispatcherHostImpl* host,
67 net::URLRequest* request) 67 net::URLRequest* request)
68 : LayeredResourceHandler(handler), 68 : LayeredResourceHandler(handler),
69 host_(host), 69 host_(host),
70 request_(request), 70 request_(request),
71 read_buffer_size_(0), 71 read_buffer_size_(0),
72 bytes_read_(0), 72 bytes_read_(0),
73 sniff_content_(false), 73 sniff_content_(false),
74 wait_for_plugins_(false), 74 wait_for_plugins_(false),
75 deferred_waiting_for_plugins_(false),
75 buffering_(false), 76 buffering_(false),
76 next_handler_needs_response_started_(false), 77 next_handler_needs_response_started_(false),
77 next_handler_needs_will_read_(false), 78 next_handler_needs_will_read_(false),
78 finished_(false) { 79 finished_(false) {
79 } 80 }
80 81
81 bool BufferedResourceHandler::OnResponseStarted( 82 bool BufferedResourceHandler::OnResponseStarted(
82 int request_id, 83 int request_id,
83 ResourceResponse* response) { 84 ResourceResponse* response,
85 bool* defer) {
84 response_ = response; 86 response_ = response;
87
85 if (!DelayResponse()) 88 if (!DelayResponse())
86 return CompleteResponseStarted(request_id); 89 return CompleteResponseStarted(request_id, defer);
90
91 if (wait_for_plugins_) {
92 deferred_waiting_for_plugins_ = true;
93 *defer = true;
94 }
87 return true; 95 return true;
88 } 96 }
89 97
90 void BufferedResourceHandler::OnRequestClosed() { 98 void BufferedResourceHandler::OnRequestClosed() {
91 request_ = NULL; 99 request_ = NULL;
92 next_handler_->OnRequestClosed(); 100 next_handler_->OnRequestClosed();
93 } 101 }
94 102
95 // We'll let the original event handler provide a buffer, and reuse it for 103 // We'll let the original event handler provide a buffer, and reuse it for
96 // subsequent reads until we're done buffering. 104 // subsequent reads until we're done buffering.
97 bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf, 105 bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
98 int* buf_size, int min_size) { 106 int* buf_size, int min_size) {
99 if (buffering_) { 107 if (buffering_) {
100 DCHECK(!my_buffer_.get()); 108 DCHECK(!my_buffer_.get());
101 my_buffer_ = new net::IOBuffer(net::kMaxBytesToSniff); 109 my_buffer_ = new net::IOBuffer(net::kMaxBytesToSniff);
102 *buf = my_buffer_.get(); 110 *buf = my_buffer_.get();
103 *buf_size = net::kMaxBytesToSniff; 111 *buf_size = net::kMaxBytesToSniff;
104 return true; 112 return true;
105 } 113 }
106 114
107 if (finished_) 115 if (finished_)
108 return false; 116 return false;
109 117
110 if (!next_handler_->OnWillRead(request_id, buf, buf_size, min_size)) { 118 if (!next_handler_->OnWillRead(request_id, buf, buf_size, min_size))
111 return false; 119 return false;
112 } 120
113 read_buffer_ = *buf; 121 read_buffer_ = *buf;
114 read_buffer_size_ = *buf_size; 122 read_buffer_size_ = *buf_size;
115 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2); 123 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
116 bytes_read_ = 0; 124 bytes_read_ = 0;
117 return true; 125 return true;
118 } 126 }
119 127
120 bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { 128 bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read,
121 ResourceRequestInfoImpl* info = 129 bool* defer) {
122 ResourceRequestInfoImpl::ForRequest(request_);
123
124 if (sniff_content_) { 130 if (sniff_content_) {
125 if (KeepBuffering(*bytes_read)) 131 if (KeepBuffering(*bytes_read)) {
132 if (wait_for_plugins_) {
133 deferred_waiting_for_plugins_ = true;
134 *defer = true;
135 }
126 return true; 136 return true;
137 }
127 138
128 *bytes_read = bytes_read_; 139 *bytes_read = bytes_read_;
129 140
130 // Done buffering, send the pending ResponseStarted event. 141 // Done buffering, send the pending ResponseStarted event.
131 if (!CompleteResponseStarted(request_id)) 142 if (!CompleteResponseStarted(request_id, defer))
132 return false; 143 return false;
133 144 if (*defer)
134 // The next handler might have paused the request in OnResponseStarted.
135 if (info->pause_count())
136 return true; 145 return true;
137 } else if (wait_for_plugins_) { 146 } else if (wait_for_plugins_) {
147 deferred_waiting_for_plugins_ = true;
148 *defer = true;
138 return true; 149 return true;
139 } 150 }
140 151
141 if (!ForwardPendingEventsToNextHandler(request_id)) 152 if (!ForwardPendingEventsToNextHandler(request_id, defer))
142 return false; 153 return false;
143 if (info->pause_count()) 154 if (*defer)
144 return true; 155 return true;
145 156
146 // Release the reference that we acquired at OnWillRead. 157 // Release the reference that we acquired at OnWillRead.
147 read_buffer_ = NULL; 158 read_buffer_ = NULL;
148 return next_handler_->OnReadCompleted(request_id, bytes_read); 159 return next_handler_->OnReadCompleted(request_id, bytes_read, defer);
149 } 160 }
150 161
151 BufferedResourceHandler::~BufferedResourceHandler() {} 162 BufferedResourceHandler::~BufferedResourceHandler() {}
152 163
153 bool BufferedResourceHandler::DelayResponse() { 164 bool BufferedResourceHandler::DelayResponse() {
154 std::string mime_type; 165 std::string mime_type;
155 request_->GetMimeType(&mime_type); 166 request_->GetMimeType(&mime_type);
156 167
157 std::string content_type_options; 168 std::string content_type_options;
158 request_->GetResponseHeaderByName("x-content-type-options", 169 request_->GetResponseHeaderByName("x-content-type-options",
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 } 247 }
237 248
238 buffering_ = false; 249 buffering_ = false;
239 250
240 if (wait_for_plugins_) 251 if (wait_for_plugins_)
241 return true; 252 return true;
242 253
243 return false; 254 return false;
244 } 255 }
245 256
246 bool BufferedResourceHandler::CompleteResponseStarted(int request_id) { 257 bool BufferedResourceHandler::CompleteResponseStarted(int request_id,
258 bool* defer) {
247 ResourceRequestInfoImpl* info = 259 ResourceRequestInfoImpl* info =
248 ResourceRequestInfoImpl::ForRequest(request_); 260 ResourceRequestInfoImpl::ForRequest(request_);
249 std::string mime_type; 261 std::string mime_type;
250 request_->GetMimeType(&mime_type); 262 request_->GetMimeType(&mime_type);
251 263
252 // Check if this is an X.509 certificate, if yes, let it be handled 264 // Check if this is an X.509 certificate, if yes, let it be handled
253 // by X509UserCertResourceHandler. 265 // by X509UserCertResourceHandler.
254 if (mime_type == "application/x-x509-user-cert") { 266 if (mime_type == "application/x-x509-user-cert") {
255 // This is entirely similar to how DownloadResourceThrottle works except we 267 // This is entirely similar to how DownloadResourceThrottle works except we
256 // are doing it for an X.509 client certificates. 268 // are doing it for an X.509 client certificates.
257 // TODO(darin): This does not belong here! 269 // TODO(darin): This does not belong here!
258 270
259 if (response_->headers && // Can be NULL if FTP. 271 if (response_->headers && // Can be NULL if FTP.
260 response_->headers->response_code() / 100 != 2) { 272 response_->headers->response_code() / 100 != 2) {
261 // The response code indicates that this is an error page, but we are 273 // The response code indicates that this is an error page, but we are
262 // expecting an X.509 user certificate. We follow Firefox here and show 274 // expecting an X.509 user certificate. We follow Firefox here and show
263 // our own error page instead of handling the error page as a 275 // our own error page instead of handling the error page as a
264 // certificate. 276 // certificate.
265 // TODO(abarth): We should abstract the response_code test, but this kind 277 // TODO(abarth): We should abstract the response_code test, but this kind
266 // of check is scattered throughout our codebase. 278 // of check is scattered throughout our codebase.
267 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); 279 request_->CancelWithError(net::ERR_FILE_NOT_FOUND);
268 return false; 280 return false;
269 } 281 }
270 282
271 X509UserCertResourceHandler* x509_cert_handler = 283 X509UserCertResourceHandler* x509_cert_handler =
272 new X509UserCertResourceHandler(request_, 284 new X509UserCertResourceHandler(request_,
273 info->GetChildID(), 285 info->GetChildID(),
274 info->GetRouteID()); 286 info->GetRouteID());
275 if (!UseAlternateResourceHandler(request_id, x509_cert_handler)) 287 if (!UseAlternateResourceHandler(request_id, x509_cert_handler, defer))
276 return false; 288 return false;
277 } 289 }
278
279 // Check to see if we should forward the data from this request to the 290 // Check to see if we should forward the data from this request to the
280 // download thread. 291 // download thread.
281 // TODO(paulg): Only download if the context from the renderer allows it. 292 // TODO(paulg): Only download if the context from the renderer allows it.
282 if (info->allow_download() && ShouldDownload(NULL)) { 293 else if (info->allow_download() && ShouldDownload(NULL)) {
Randy Smith (Not in Mondays) 2012/05/18 20:17:02 Suggestion (as I can't find any support for my pos
darin (slow to review) 2012/05/18 23:09:05 Yes, that can probably be done.
283 if (response_->headers && // Can be NULL if FTP. 294 if (response_->headers && // Can be NULL if FTP.
284 response_->headers->response_code() / 100 != 2) { 295 response_->headers->response_code() / 100 != 2) {
285 // The response code indicates that this is an error page, but we don't 296 // The response code indicates that this is an error page, but we don't
286 // know how to display the content. We follow Firefox here and show our 297 // know how to display the content. We follow Firefox here and show our
287 // own error page instead of triggering a download. 298 // own error page instead of triggering a download.
288 // TODO(abarth): We should abstract the response_code test, but this kind 299 // TODO(abarth): We should abstract the response_code test, but this kind
289 // of check is scattered throughout our codebase. 300 // of check is scattered throughout our codebase.
290 request_->CancelWithError(net::ERR_FILE_NOT_FOUND); 301 request_->CancelWithError(net::ERR_FILE_NOT_FOUND);
291 return false; 302 return false;
292 } 303 }
293 304
294 info->set_is_download(true); 305 info->set_is_download(true);
295 306
296 scoped_refptr<ResourceHandler> handler( 307 scoped_refptr<ResourceHandler> handler(
297 host_->CreateResourceHandlerForDownload( 308 host_->CreateResourceHandlerForDownload(
298 request_, 309 request_,
299 info->GetContext(), 310 info->GetContext(),
300 info->GetChildID(), 311 info->GetChildID(),
301 info->GetRouteID(), 312 info->GetRouteID(),
302 info->GetRequestID(), 313 info->GetRequestID(),
303 DownloadSaveInfo(), 314 DownloadSaveInfo(),
304 DownloadResourceHandler::OnStartedCallback())); 315 DownloadResourceHandler::OnStartedCallback()));
305 316
306 if (!UseAlternateResourceHandler(request_id, handler)) 317 if (!UseAlternateResourceHandler(request_id, handler, defer))
307 return false; 318 return false;
308 } 319 }
309 320
310 if (info->pause_count()) 321 if (*defer)
311 return true; 322 return true;
312 323
313 return next_handler_->OnResponseStarted(request_id, response_); 324 return next_handler_->OnResponseStarted(request_id, response_, defer);
314 } 325 }
315 326
316 bool BufferedResourceHandler::ShouldWaitForPlugins() { 327 bool BufferedResourceHandler::ShouldWaitForPlugins() {
317 bool need_plugin_list; 328 bool need_plugin_list;
318 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list) 329 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list)
319 return false; 330 return false;
320 331
321 // We don't want to keep buffering as our buffer will fill up.
322 ResourceRequestInfoImpl* info =
323 ResourceRequestInfoImpl::ForRequest(request_);
324 host_->PauseRequest(info->GetChildID(), info->GetRequestID(), true);
325
326 // Get the plugins asynchronously. 332 // Get the plugins asynchronously.
327 PluginServiceImpl::GetInstance()->GetPlugins( 333 PluginServiceImpl::GetInstance()->GetPlugins(
328 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this)); 334 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this));
335
336 // We don't want to keep buffering as our buffer will fill up.
Randy Smith (Not in Mondays) 2012/05/18 20:17:02 nit, suggestion: This comment feels a little stran
darin (slow to review) 2012/05/18 23:09:05 Agreed.
329 return true; 337 return true;
330 } 338 }
331 339
332 // This test mirrors the decision that WebKit makes in 340 // This test mirrors the decision that WebKit makes in
333 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType. 341 // WebFrameLoaderClient::dispatchDecidePolicyForMIMEType.
334 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { 342 bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) {
335 if (need_plugin_list) 343 if (need_plugin_list)
336 *need_plugin_list = false; 344 *need_plugin_list = false;
337 std::string type = StringToLowerASCII(response_->mime_type); 345 std::string type = StringToLowerASCII(response_->mime_type);
338 346
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 } 379 }
372 } else { 380 } else {
373 DCHECK(!stale); 381 DCHECK(!stale);
374 } 382 }
375 383
376 return !found; 384 return !found;
377 } 385 }
378 386
379 bool BufferedResourceHandler::UseAlternateResourceHandler( 387 bool BufferedResourceHandler::UseAlternateResourceHandler(
380 int request_id, 388 int request_id,
381 ResourceHandler* handler) { 389 ResourceHandler* handler,
390 bool* defer) {
382 // Inform the original ResourceHandler that this will be handled entirely by 391 // Inform the original ResourceHandler that this will be handled entirely by
383 // the new ResourceHandler. 392 // the new ResourceHandler.
384 // TODO(darin): We should probably check the return values of these. 393 // TODO(darin): We should probably check the return values of these.
385 next_handler_->OnResponseStarted(request_id, response_); 394 bool defer_ignored = false;
395 next_handler_->OnResponseStarted(request_id, response_, &defer_ignored);
396 DCHECK(!defer_ignored);
Randy Smith (Not in Mondays) 2012/05/18 20:17:02 What's the rational for this?
darin (slow to review) 2012/05/18 23:09:05 The old code fails to handle pausing done by the o
Randy Smith (Not in Mondays) 2012/05/19 00:42:14 SG.
386 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0); 397 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0);
387 next_handler_->OnResponseCompleted(request_id, status, std::string()); 398 next_handler_->OnResponseCompleted(request_id, status, std::string());
388 399
389 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any, 400 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any,
390 // from the extra request info because the CrossSiteResourceHandler (part of 401 // from the extra request info because the CrossSiteResourceHandler (part of
391 // the original ResourceHandler chain) will be deleted by the next statement. 402 // the original ResourceHandler chain) will be deleted by the next statement.
392 ResourceRequestInfoImpl* info = 403 ResourceRequestInfoImpl* info =
393 ResourceRequestInfoImpl::ForRequest(request_); 404 ResourceRequestInfoImpl::ForRequest(request_);
394 info->set_cross_site_handler(NULL); 405 info->set_cross_site_handler(NULL);
395 406
396 // This is handled entirely within the new ResourceHandler, so just reset the 407 // This is handled entirely within the new ResourceHandler, so just reset the
397 // original ResourceHandler. 408 // original ResourceHandler.
398 next_handler_ = handler; 409 next_handler_ = handler;
399 410
400 next_handler_needs_response_started_ = true; 411 next_handler_needs_response_started_ = true;
401 next_handler_needs_will_read_ = true; 412 next_handler_needs_will_read_ = true;
402 413
403 return ForwardPendingEventsToNextHandler(request_id); 414 return ForwardPendingEventsToNextHandler(request_id, defer);
404 } 415 }
405 416
406 bool BufferedResourceHandler::ForwardPendingEventsToNextHandler( 417 bool BufferedResourceHandler::ForwardPendingEventsToNextHandler(
407 int request_id) { 418 int request_id,
408 ResourceRequestInfoImpl* info = 419 bool* defer) {
Randy Smith (Not in Mondays) 2012/05/18 20:17:02 nit: Why two lines?
darin (slow to review) 2012/05/18 23:09:05 Looks like the first parameter actually fits on th
409 ResourceRequestInfoImpl::ForRequest(request_);
410 if (info->pause_count())
411 return true;
412
413 if (next_handler_needs_response_started_) { 420 if (next_handler_needs_response_started_) {
414 if (!next_handler_->OnResponseStarted(request_id, response_)) 421 if (!next_handler_->OnResponseStarted(request_id, response_, defer))
415 return false; 422 return false;
416 // If the request was paused during OnResponseStarted, we need to avoid 423 // If the request was deferred during OnResponseStarted, we need to avoid
417 // calling OnResponseStarted again. 424 // calling OnResponseStarted again.
418 next_handler_needs_response_started_ = false; 425 next_handler_needs_response_started_ = false;
419 if (info->pause_count()) 426 if (*defer)
420 return true; 427 return true;
421 } 428 }
422 429
423 if (next_handler_needs_will_read_) { 430 if (next_handler_needs_will_read_) {
424 CopyReadBufferToNextHandler(request_id); 431 CopyReadBufferToNextHandler(request_id);
425 // If the request was paused during OnWillRead, we need to be sure to try
426 // calling OnWillRead again.
427 if (info->pause_count())
428 return true;
429 next_handler_needs_will_read_ = false; 432 next_handler_needs_will_read_ = false;
430 } 433 }
431 return true; 434 return true;
432 } 435 }
433 436
434 void BufferedResourceHandler::CopyReadBufferToNextHandler(int request_id) { 437 void BufferedResourceHandler::CopyReadBufferToNextHandler(int request_id) {
435 if (!bytes_read_) 438 if (!bytes_read_)
436 return; 439 return;
437 440
438 net::IOBuffer* buf = NULL; 441 net::IOBuffer* buf = NULL;
439 int buf_len = 0; 442 int buf_len = 0;
440 if (next_handler_->OnWillRead(request_id, &buf, &buf_len, bytes_read_)) { 443 if (next_handler_->OnWillRead(request_id, &buf, &buf_len, bytes_read_)) {
441 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0)); 444 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
442 memcpy(buf->data(), read_buffer_->data(), bytes_read_); 445 memcpy(buf->data(), read_buffer_->data(), bytes_read_);
443 } 446 }
444 } 447 }
445 448
446 void BufferedResourceHandler::OnPluginsLoaded( 449 void BufferedResourceHandler::OnPluginsLoaded(
447 const std::vector<webkit::WebPluginInfo>& plugins) { 450 const std::vector<webkit::WebPluginInfo>& plugins) {
451 bool needs_resume = deferred_waiting_for_plugins_;
452 deferred_waiting_for_plugins_ = false;
453
448 wait_for_plugins_ = false; 454 wait_for_plugins_ = false;
449 if (!request_) 455 if (!request_)
450 return; 456 return;
451 457
452 ResourceRequestInfoImpl* info = 458 ResourceRequestInfoImpl* info =
453 ResourceRequestInfoImpl::ForRequest(request_); 459 ResourceRequestInfoImpl::ForRequest(request_);
454 int child_id = info->GetChildID(); 460 int child_id = info->GetChildID();
455 int request_id = info->GetRequestID(); 461 int request_id = info->GetRequestID();
456 462
457 host_->PauseRequest(child_id, request_id, false); 463 bool defer = false;
458 if (!CompleteResponseStarted(request_id)) 464 if (!CompleteResponseStarted(request_id, &defer)) {
459 host_->CancelRequest(child_id, request_id, false); 465 host_->CancelRequest(child_id, request_id, false);
466 } else if (!defer && needs_resume) {
467 host_->ResumeDeferredRequest(child_id, request_id);
468 }
460 } 469 }
461 470
462 } // namespace content 471 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698