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

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

Issue 2542843006: ResourceLoader: Fix a bunch of double-cancellation/double-error notification cases. (Closed)
Patch Set: Fix merge Created 4 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
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/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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/loader/resource_loader.h ('k') | content/browser/loader/resource_loader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698