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

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

Issue 2743723003: Add buffering to MimeSniffingResourceHandler.
Patch Set: Remove unused 'first_call' variable. Created 3 years, 8 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
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/loader/mojo_async_resource_handler.h" 5 #include "content/browser/loader/mojo_async_resource_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 10 matching lines...) Expand all
21 #include "content/browser/loader/resource_controller.h" 21 #include "content/browser/loader/resource_controller.h"
22 #include "content/browser/loader/resource_dispatcher_host_impl.h" 22 #include "content/browser/loader/resource_dispatcher_host_impl.h"
23 #include "content/browser/loader/resource_request_info_impl.h" 23 #include "content/browser/loader/resource_request_info_impl.h"
24 #include "content/browser/loader/resource_scheduler.h" 24 #include "content/browser/loader/resource_scheduler.h"
25 #include "content/browser/loader/upload_progress_tracker.h" 25 #include "content/browser/loader/upload_progress_tracker.h"
26 #include "content/common/resource_request_completion_status.h" 26 #include "content/common/resource_request_completion_status.h"
27 #include "content/public/browser/global_request_id.h" 27 #include "content/public/browser/global_request_id.h"
28 #include "content/public/common/resource_response.h" 28 #include "content/public/common/resource_response.h"
29 #include "mojo/public/c/system/data_pipe.h" 29 #include "mojo/public/c/system/data_pipe.h"
30 #include "mojo/public/cpp/bindings/message.h" 30 #include "mojo/public/cpp/bindings/message.h"
31 #include "net/base/mime_sniffer.h"
32 #include "net/base/net_errors.h" 31 #include "net/base/net_errors.h"
33 #include "net/url_request/redirect_info.h" 32 #include "net/url_request/redirect_info.h"
34 33
35 namespace content { 34 namespace content {
36 namespace { 35 namespace {
37 36
38 int g_allocation_size = MojoAsyncResourceHandler::kDefaultAllocationSize; 37 int g_allocation_size = MojoAsyncResourceHandler::kDefaultAllocationSize;
39 38
40 // MimeTypeResourceHandler *implicitly* requires that the buffer size
41 // returned from OnWillRead should be larger than certain size.
42 // TODO(yhirano): Fix MimeTypeResourceHandler.
43 constexpr size_t kMinAllocationSize = 2 * net::kMaxBytesToSniff;
44
45 constexpr size_t kMaxChunkSize = 32 * 1024; 39 constexpr size_t kMaxChunkSize = 32 * 1024;
46 40
47 void GetNumericArg(const std::string& name, int* result) { 41 void GetNumericArg(const std::string& name, int* result) {
48 const std::string& value = 42 const std::string& value =
49 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name); 43 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
50 if (!value.empty()) 44 if (!value.empty())
51 base::StringToInt(value, result); 45 base::StringToInt(value, result);
52 } 46 }
53 47
54 void InitializeResourceBufferConstants() { 48 void InitializeResourceBufferConstants() {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 // final 0-byte read, so this DCHECK will also catch OnWillRead being called 225 // final 0-byte read, so this DCHECK will also catch OnWillRead being called
232 // after OnReadCompelted(0)). 226 // after OnReadCompelted(0)).
233 DCHECK(!buffer_); 227 DCHECK(!buffer_);
234 DCHECK_EQ(0u, buffer_offset_); 228 DCHECK_EQ(0u, buffer_offset_);
235 229
236 if (!CheckForSufficientResource()) { 230 if (!CheckForSufficientResource()) {
237 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); 231 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
238 return; 232 return;
239 } 233 }
240 234
241 bool first_call = false;
242 if (!shared_writer_) { 235 if (!shared_writer_) {
243 first_call = true;
244 MojoCreateDataPipeOptions options; 236 MojoCreateDataPipeOptions options;
245 options.struct_size = sizeof(MojoCreateDataPipeOptions); 237 options.struct_size = sizeof(MojoCreateDataPipeOptions);
246 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; 238 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
247 options.element_num_bytes = 1; 239 options.element_num_bytes = 1;
248 options.capacity_num_bytes = g_allocation_size; 240 options.capacity_num_bytes = g_allocation_size;
249 mojo::DataPipe data_pipe(options); 241 mojo::DataPipe data_pipe(options);
250 242
251 DCHECK(data_pipe.producer_handle.is_valid()); 243 DCHECK(data_pipe.producer_handle.is_valid());
252 DCHECK(data_pipe.consumer_handle.is_valid()); 244 DCHECK(data_pipe.consumer_handle.is_valid());
253 245
(...skipping 14 matching lines...) Expand all
268 if (defer) { 260 if (defer) {
269 DCHECK(!buffer_); 261 DCHECK(!buffer_);
270 parent_buffer_ = buf; 262 parent_buffer_ = buf;
271 parent_buffer_size_ = buf_size; 263 parent_buffer_size_ = buf_size;
272 HoldController(std::move(controller)); 264 HoldController(std::move(controller));
273 request()->LogBlockedBy("MojoAsyncResourceHandler"); 265 request()->LogBlockedBy("MojoAsyncResourceHandler");
274 did_defer_on_will_read_ = true; 266 did_defer_on_will_read_ = true;
275 return; 267 return;
276 } 268 }
277 269
278 // The first call to OnWillRead must return a buffer of at least
279 // kMinAllocationSize. If the Mojo buffer is too small, need to allocate an
280 // intermediary buffer.
281 if (first_call && static_cast<size_t>(buffer_->size()) < kMinAllocationSize) {
282 // The allocated buffer is too small, so need to create an intermediary one.
283 if (EndWrite(0) != MOJO_RESULT_OK) {
284 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
285 return;
286 }
287 DCHECK(!is_using_io_buffer_not_from_writer_);
288 is_using_io_buffer_not_from_writer_ = true;
289 buffer_ = new net::IOBufferWithSize(kMinAllocationSize);
290 }
291
292 *buf = buffer_; 270 *buf = buffer_;
293 *buf_size = buffer_->size(); 271 *buf_size = buffer_->size();
294 controller->Resume(); 272 controller->Resume();
295 } 273 }
296 274
297 void MojoAsyncResourceHandler::OnReadCompleted( 275 void MojoAsyncResourceHandler::OnReadCompleted(
298 int bytes_read, 276 int bytes_read,
299 std::unique_ptr<ResourceController> controller) { 277 std::unique_ptr<ResourceController> controller) {
300 DCHECK(!has_controller()); 278 DCHECK(!has_controller());
301 DCHECK_GE(bytes_read, 0); 279 DCHECK_GE(bytes_read, 0);
(...skipping 13 matching lines...) Expand all
315 url_loader_client_->OnTransferSizeUpdated(transfer_size_diff); 293 url_loader_client_->OnTransferSizeUpdated(transfer_size_diff);
316 } 294 }
317 295
318 if (response_body_consumer_handle_.is_valid()) { 296 if (response_body_consumer_handle_.is_valid()) {
319 // Send the data pipe on the first OnReadCompleted call. 297 // Send the data pipe on the first OnReadCompleted call.
320 url_loader_client_->OnStartLoadingResponseBody( 298 url_loader_client_->OnStartLoadingResponseBody(
321 std::move(response_body_consumer_handle_)); 299 std::move(response_body_consumer_handle_));
322 response_body_consumer_handle_.reset(); 300 response_body_consumer_handle_.reset();
323 } 301 }
324 302
325 if (is_using_io_buffer_not_from_writer_) {
326 // Couldn't allocate a large enough buffer on the data pipe in OnWillRead.
327 DCHECK_EQ(0u, buffer_bytes_read_);
328 buffer_bytes_read_ = bytes_read;
329 bool defer = false;
330 if (!CopyReadDataToDataPipe(&defer)) {
331 controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
332 return;
333 }
334 if (defer) {
335 request()->LogBlockedBy("MojoAsyncResourceHandler");
336 did_defer_on_writing_ = true;
337 HoldController(std::move(controller));
338 return;
339 }
340 controller->Resume();
341 return;
342 }
343
344 if (EndWrite(bytes_read) != MOJO_RESULT_OK) { 303 if (EndWrite(bytes_read) != MOJO_RESULT_OK) {
345 controller->Cancel(); 304 controller->Cancel();
346 return; 305 return;
347 } 306 }
348 307
349 buffer_ = nullptr; 308 buffer_ = nullptr;
350 controller->Resume(); 309 controller->Resume();
351 } 310 }
352 311
353 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { 312 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
354 url_loader_client_->OnDataDownloaded(bytes_downloaded, 313 url_loader_client_->OnDataDownloaded(bytes_downloaded,
355 CalculateRecentlyReceivedBytes()); 314 CalculateRecentlyReceivedBytes());
356 } 315 }
357 316
358 void MojoAsyncResourceHandler::FollowRedirect() { 317 void MojoAsyncResourceHandler::FollowRedirect() {
359 if (!request()->status().is_success()) { 318 if (!request()->status().is_success()) {
360 DVLOG(1) << "FollowRedirect for invalid request"; 319 DVLOG(1) << "FollowRedirect for invalid request";
361 return; 320 return;
362 } 321 }
363 if (!did_defer_on_redirect_) { 322 if (!did_defer_on_redirect_) {
364 DVLOG(1) << "Malformed FollowRedirect request"; 323 DVLOG(1) << "Malformed FollowRedirect request";
365 ReportBadMessage("Malformed FollowRedirect request"); 324 ReportBadMessage("Malformed FollowRedirect request");
366 return; 325 return;
367 } 326 }
368 327
369 DCHECK(!did_defer_on_will_read_); 328 DCHECK(!did_defer_on_will_read_);
370 DCHECK(!did_defer_on_writing_);
371 did_defer_on_redirect_ = false; 329 did_defer_on_redirect_ = false;
372 request()->LogUnblocked(); 330 request()->LogUnblocked();
373 Resume(); 331 Resume();
374 } 332 }
375 333
376 void MojoAsyncResourceHandler::SetPriority(net::RequestPriority priority, 334 void MojoAsyncResourceHandler::SetPriority(net::RequestPriority priority,
377 int32_t intra_priority_value) { 335 int32_t intra_priority_value) {
378 ResourceDispatcherHostImpl::Get()->scheduler()->ReprioritizeRequest( 336 ResourceDispatcherHostImpl::Get()->scheduler()->ReprioritizeRequest(
379 request(), priority, intra_priority_value); 337 request(), priority, intra_priority_value);
380 } 338 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 request_complete_data.exists_in_cache = request()->response_info().was_cached; 408 request_complete_data.exists_in_cache = request()->response_info().was_cached;
451 request_complete_data.completion_time = base::TimeTicks::Now(); 409 request_complete_data.completion_time = base::TimeTicks::Now();
452 request_complete_data.encoded_data_length = 410 request_complete_data.encoded_data_length =
453 request()->GetTotalReceivedBytes(); 411 request()->GetTotalReceivedBytes();
454 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); 412 request_complete_data.encoded_body_length = request()->GetRawBodyBytes();
455 413
456 url_loader_client_->OnComplete(request_complete_data); 414 url_loader_client_->OnComplete(request_complete_data);
457 controller->Resume(); 415 controller->Resume();
458 } 416 }
459 417
460 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) {
461 while (buffer_bytes_read_ > 0) {
462 scoped_refptr<net::IOBufferWithSize> dest;
463 if (!AllocateWriterIOBuffer(&dest, defer))
464 return false;
465 if (*defer)
466 return true;
467
468 size_t copied_size =
469 std::min(buffer_bytes_read_, static_cast<size_t>(dest->size()));
470 memcpy(dest->data(), buffer_->data() + buffer_offset_, copied_size);
471 buffer_offset_ += copied_size;
472 buffer_bytes_read_ -= copied_size;
473 if (EndWrite(copied_size) != MOJO_RESULT_OK)
474 return false;
475 }
476
477 // All bytes are copied.
478 buffer_ = nullptr;
479 buffer_offset_ = 0;
480 is_using_io_buffer_not_from_writer_ = false;
481 return true;
482 }
483
484 bool MojoAsyncResourceHandler::AllocateWriterIOBuffer( 418 bool MojoAsyncResourceHandler::AllocateWriterIOBuffer(
485 scoped_refptr<net::IOBufferWithSize>* buf, 419 scoped_refptr<net::IOBufferWithSize>* buf,
486 bool* defer) { 420 bool* defer) {
487 void* data = nullptr; 421 void* data = nullptr;
488 uint32_t available = 0; 422 uint32_t available = 0;
489 MojoResult result = BeginWrite(&data, &available); 423 MojoResult result = BeginWrite(&data, &available);
490 if (result == MOJO_RESULT_SHOULD_WAIT) { 424 if (result == MOJO_RESULT_SHOULD_WAIT) {
491 *defer = true; 425 *defer = true;
492 return true; 426 return true;
493 } 427 }
494 if (result != MOJO_RESULT_OK) 428 if (result != MOJO_RESULT_OK)
495 return false; 429 return false;
496 DCHECK_GT(available, 0u); 430 DCHECK_GT(available, 0u);
497 *buf = new WriterIOBuffer(shared_writer_, data, available); 431 *buf = new WriterIOBuffer(shared_writer_, data, available);
498 return true; 432 return true;
499 } 433 }
500 434
501 bool MojoAsyncResourceHandler::CheckForSufficientResource() { 435 bool MojoAsyncResourceHandler::CheckForSufficientResource() {
502 if (has_checked_for_sufficient_resources_) 436 if (has_checked_for_sufficient_resources_)
503 return true; 437 return true;
504 has_checked_for_sufficient_resources_ = true; 438 has_checked_for_sufficient_resources_ = true;
505 439
506 if (rdh_->HasSufficientResourcesForRequest(request())) 440 if (rdh_->HasSufficientResourcesForRequest(request()))
507 return true; 441 return true;
508 442
509 return false; 443 return false;
510 } 444 }
511 445
512 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { 446 void MojoAsyncResourceHandler::OnWritable(MojoResult result) {
513 if (did_defer_on_will_read_) { 447 if (!did_defer_on_will_read_)
514 DCHECK(has_controller()); 448 return;
515 DCHECK(!did_defer_on_writing_);
516 DCHECK(!did_defer_on_redirect_);
517 449
518 did_defer_on_will_read_ = false;
519
520 scoped_refptr<net::IOBuffer>* parent_buffer = parent_buffer_;
521 parent_buffer_ = nullptr;
522 int* parent_buffer_size = parent_buffer_size_;
523 parent_buffer_size_ = nullptr;
524
525 request()->LogUnblocked();
526 OnWillRead(parent_buffer, parent_buffer_size, ReleaseController());
527 return;
528 }
529
530 if (!did_defer_on_writing_)
531 return;
532 DCHECK(has_controller()); 450 DCHECK(has_controller());
533 DCHECK(!did_defer_on_redirect_); 451 DCHECK(!did_defer_on_redirect_);
534 did_defer_on_writing_ = false;
535 452
536 DCHECK(is_using_io_buffer_not_from_writer_); 453 did_defer_on_will_read_ = false;
537 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents
538 // to the data pipe.
539 DCHECK_GT(buffer_bytes_read_, 0u);
540 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) {
541 CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
542 return;
543 }
544 454
545 if (did_defer_on_writing_) { 455 scoped_refptr<net::IOBuffer>* parent_buffer = parent_buffer_;
546 // Continue waiting. 456 parent_buffer_ = nullptr;
547 return; 457 int* parent_buffer_size = parent_buffer_size_;
548 } 458 parent_buffer_size_ = nullptr;
459
549 request()->LogUnblocked(); 460 request()->LogUnblocked();
550 Resume(); 461 OnWillRead(parent_buffer, parent_buffer_size, ReleaseController());
551 } 462 }
552 463
553 void MojoAsyncResourceHandler::Cancel() { 464 void MojoAsyncResourceHandler::Cancel() {
554 const ResourceRequestInfoImpl* info = GetRequestInfo(); 465 const ResourceRequestInfoImpl* info = GetRequestInfo();
555 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( 466 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer(
556 GlobalRequestID(info->GetChildID(), info->GetRequestID())); 467 GlobalRequestID(info->GetChildID(), info->GetRequestID()));
557 } 468 }
558 469
559 int64_t MojoAsyncResourceHandler::CalculateRecentlyReceivedBytes() { 470 int64_t MojoAsyncResourceHandler::CalculateRecentlyReceivedBytes() {
560 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); 471 int64_t total_received_bytes = request()->GetTotalReceivedBytes();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK, 505 base::Bind(&MojoAsyncResourceHandler::OnUploadProgressACK,
595 weak_factory_.GetWeakPtr())); 506 weak_factory_.GetWeakPtr()));
596 } 507 }
597 508
598 void MojoAsyncResourceHandler::OnUploadProgressACK() { 509 void MojoAsyncResourceHandler::OnUploadProgressACK() {
599 if (upload_progress_tracker_) 510 if (upload_progress_tracker_)
600 upload_progress_tracker_->OnAckReceived(); 511 upload_progress_tracker_->OnAckReceived();
601 } 512 }
602 513
603 } // namespace content 514 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/mojo_async_resource_handler.h ('k') | content/browser/loader/mojo_async_resource_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698