OLD | NEW |
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/loader/resource_loader.h" | 5 #include "content/browser/loader/resource_loader.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 | 343 |
344 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); | 344 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); |
345 | 345 |
346 if (!request_->status().is_success()) { | 346 if (!request_->status().is_success()) { |
347 ResponseCompleted(); | 347 ResponseCompleted(); |
348 return; | 348 return; |
349 } | 349 } |
350 | 350 |
351 CompleteResponseStarted(); | 351 CompleteResponseStarted(); |
352 | 352 |
353 if (is_deferred()) | 353 // If the handler deferred the request, it will resume the request later. If |
| 354 // the request was cancelled, the request will call back into |this| with a |
| 355 // bogus read completed error. |
| 356 if (is_deferred() || !request_->status().is_success()) |
354 return; | 357 return; |
355 | 358 |
356 if (request_->status().is_success()) | 359 ReadMore(false); // Read the first chunk. |
357 StartReading(false); // Read the first chunk. | |
358 else | |
359 ResponseCompleted(); | |
360 } | 360 } |
361 | 361 |
362 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { | 362 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { |
363 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 363 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
364 "ResourceLoader::OnReadCompleted"); | 364 "ResourceLoader::OnReadCompleted"); |
365 DCHECK_EQ(request_.get(), unused); | 365 DCHECK_EQ(request_.get(), unused); |
366 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" | 366 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" |
367 << " bytes_read = " << bytes_read; | 367 << " bytes_read = " << bytes_read; |
368 | 368 |
369 // bytes_read == -1 always implies an error. | 369 // bytes_read == -1 always implies an error. |
370 if (bytes_read == -1 || !request_->status().is_success()) { | 370 if (bytes_read == -1 || !request_->status().is_success()) { |
371 ResponseCompleted(); | 371 ResponseCompleted(); |
372 return; | 372 return; |
373 } | 373 } |
374 | 374 |
375 CompleteRead(bytes_read); | 375 CompleteRead(bytes_read); |
376 | 376 |
377 // If the handler cancelled or deferred the request, do not continue | 377 // If the handler cancelled or deferred the request, do not continue |
378 // processing the read. If cancelled, the URLRequest has already been | 378 // processing the read. If canceled, either the request will call into |this| |
379 // cancelled and will schedule an erroring OnReadCompleted later. If deferred, | 379 // with a bogus read error, or, if the request was completed, a task posted |
380 // do nothing until resumed. | 380 // from ResourceLoader::CancelREquestInternal will run OnResponseCompleted. |
381 // | |
382 // Note: if bytes_read is 0 (EOF) and the handler defers, resumption will call | |
383 // ResponseCompleted(). | |
384 if (is_deferred() || !request_->status().is_success()) | 381 if (is_deferred() || !request_->status().is_success()) |
385 return; | 382 return; |
386 | 383 |
387 if (bytes_read > 0) { | 384 if (bytes_read > 0) { |
388 StartReading(true); // Read the next chunk. | 385 ReadMore(true); // Read the next chunk. |
389 } else { | 386 } else { |
390 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 387 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
391 tracked_objects::ScopedTracker tracking_profile( | 388 tracked_objects::ScopedTracker tracking_profile( |
392 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 ResponseCompleted()")); | 389 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 ResponseCompleted()")); |
393 | 390 |
394 // URLRequest reported an EOF. Call ResponseCompleted. | 391 // URLRequest reported an EOF. Call ResponseCompleted. |
395 DCHECK_EQ(0, bytes_read); | 392 DCHECK_EQ(0, bytes_read); |
396 ResponseCompleted(); | 393 ResponseCompleted(); |
397 } | 394 } |
398 } | 395 } |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 | 547 |
551 bool defer = false; | 548 bool defer = false; |
552 if (!handler_->OnResponseStarted(response.get(), &defer)) { | 549 if (!handler_->OnResponseStarted(response.get(), &defer)) { |
553 Cancel(); | 550 Cancel(); |
554 } else if (defer) { | 551 } else if (defer) { |
555 read_deferral_start_time_ = base::TimeTicks::Now(); | 552 read_deferral_start_time_ = base::TimeTicks::Now(); |
556 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. | 553 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. |
557 } | 554 } |
558 } | 555 } |
559 | 556 |
560 void ResourceLoader::StartReading(bool is_continuation) { | 557 void ResourceLoader::ReadMore(bool is_continuation) { |
561 int bytes_read = 0; | |
562 ReadMore(&bytes_read); | |
563 | |
564 // If IO is pending, wait for the URLRequest to call OnReadCompleted. | |
565 if (request_->status().is_io_pending()) | |
566 return; | |
567 | |
568 if (!is_continuation || bytes_read <= 0) { | |
569 OnReadCompleted(request_.get(), bytes_read); | |
570 } else { | |
571 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO | |
572 // thread in case the URLRequest can provide data synchronously. | |
573 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
574 FROM_HERE, | |
575 base::Bind(&ResourceLoader::OnReadCompleted, | |
576 weak_ptr_factory_.GetWeakPtr(), request_.get(), bytes_read)); | |
577 } | |
578 } | |
579 | |
580 void ResourceLoader::ResumeReading() { | |
581 DCHECK(!is_deferred()); | |
582 | |
583 if (!read_deferral_start_time_.is_null()) { | |
584 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral", | |
585 base::TimeTicks::Now() - read_deferral_start_time_); | |
586 read_deferral_start_time_ = base::TimeTicks(); | |
587 } | |
588 if (request_->status().is_success()) { | |
589 StartReading(false); // Read the next chunk (OK to complete synchronously). | |
590 } else { | |
591 ResponseCompleted(); | |
592 } | |
593 } | |
594 | |
595 void ResourceLoader::ReadMore(int* bytes_read) { | |
596 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, | 558 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, |
597 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 559 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
598 DCHECK(!is_deferred()); | 560 DCHECK(!is_deferred()); |
599 | 561 |
600 // Make sure we track the buffer in at least one place. This ensures it gets | 562 // Make sure we track the buffer in at least one place. This ensures it gets |
601 // deleted even in the case the request has already finished its job and | 563 // deleted even in the case the request has already finished its job and |
602 // doesn't use the buffer. | 564 // doesn't use the buffer. |
603 scoped_refptr<net::IOBuffer> buf; | 565 scoped_refptr<net::IOBuffer> buf; |
604 int buf_size; | 566 int buf_size; |
605 { | 567 { |
606 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 568 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
607 tracked_objects::ScopedTracker tracking_profile2( | 569 tracked_objects::ScopedTracker tracking_profile2( |
608 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnWillRead()")); | 570 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnWillRead()")); |
609 | 571 |
610 if (!handler_->OnWillRead(&buf, &buf_size, -1)) { | 572 if (!handler_->OnWillRead(&buf, &buf_size, -1)) { |
| 573 // Cancel the request, which will then call back into |this| to inform it |
| 574 // of a "read error". |
611 Cancel(); | 575 Cancel(); |
612 return; | 576 return; |
613 } | 577 } |
614 } | 578 } |
615 | 579 |
616 DCHECK(buf.get()); | 580 DCHECK(buf.get()); |
617 DCHECK(buf_size > 0); | 581 DCHECK(buf_size > 0); |
618 | 582 |
619 request_->Read(buf.get(), buf_size, bytes_read); | 583 int result = request_->Read(buf.get(), buf_size); |
620 | 584 |
621 // No need to check the return value here as we'll detect errors by | 585 if (result == net::ERR_IO_PENDING) |
622 // inspecting the URLRequest's status. | 586 return; |
| 587 |
| 588 if (!is_continuation || result <= 0) { |
| 589 OnReadCompleted(request_.get(), result); |
| 590 } else { |
| 591 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO |
| 592 // thread in case the URLRequest can provide data synchronously. |
| 593 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 594 FROM_HERE, |
| 595 base::Bind(&ResourceLoader::OnReadCompleted, |
| 596 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); |
| 597 } |
| 598 } |
| 599 |
| 600 void ResourceLoader::ResumeReading() { |
| 601 DCHECK(!is_deferred()); |
| 602 |
| 603 if (!read_deferral_start_time_.is_null()) { |
| 604 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral", |
| 605 base::TimeTicks::Now() - read_deferral_start_time_); |
| 606 read_deferral_start_time_ = base::TimeTicks(); |
| 607 } |
| 608 if (request_->status().is_success()) { |
| 609 ReadMore(false); // Read the next chunk (OK to complete synchronously). |
| 610 } else { |
| 611 ResponseCompleted(); |
| 612 } |
623 } | 613 } |
624 | 614 |
625 void ResourceLoader::CompleteRead(int bytes_read) { | 615 void ResourceLoader::CompleteRead(int bytes_read) { |
626 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, | 616 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, |
627 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 617 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
628 | 618 |
629 DCHECK(bytes_read >= 0); | 619 DCHECK(bytes_read >= 0); |
630 DCHECK(request_->status().is_success()); | 620 DCHECK(request_->status().is_success()); |
631 | 621 |
632 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 622 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, | 727 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, |
738 STATUS_MAX); | 728 STATUS_MAX); |
739 } | 729 } |
740 } else if (request_->response_info().unused_since_prefetch) { | 730 } else if (request_->response_info().unused_since_prefetch) { |
741 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); | 731 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); |
742 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); | 732 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); |
743 } | 733 } |
744 } | 734 } |
745 | 735 |
746 } // namespace content | 736 } // namespace content |
OLD | NEW |