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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/loader/resource_loader.cc
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index 0b3833a655ec3c9a6f44b7826de333f460f26f68..bb77021ac8fa20c3d369154da1b6f0adcd0df945 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -350,13 +350,13 @@ void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
CompleteResponseStarted();
- if (is_deferred())
+ // If the handler deferred the request, it will resume the request later. If
+ // the request was cancelled, the request will call back into |this| with a
+ // bogus read completed error.
+ if (is_deferred() || !request_->status().is_success())
return;
- if (request_->status().is_success())
- StartReading(false); // Read the first chunk.
- else
- ResponseCompleted();
+ ReadMore(false); // Read the first chunk.
}
void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
@@ -375,17 +375,14 @@ void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
CompleteRead(bytes_read);
// If the handler cancelled or deferred the request, do not continue
- // processing the read. If cancelled, the URLRequest has already been
- // cancelled and will schedule an erroring OnReadCompleted later. If deferred,
- // do nothing until resumed.
- //
- // Note: if bytes_read is 0 (EOF) and the handler defers, resumption will call
- // ResponseCompleted().
+ // processing the read. If canceled, either the request will call into |this|
+ // with a bogus read error, or, if the request was completed, a task posted
+ // from ResourceLoader::CancelREquestInternal will run OnResponseCompleted.
if (is_deferred() || !request_->status().is_success())
return;
if (bytes_read > 0) {
- StartReading(true); // Read the next chunk.
+ ReadMore(true); // Read the next chunk.
} else {
// TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed.
tracked_objects::ScopedTracker tracking_profile(
@@ -557,42 +554,7 @@ void ResourceLoader::CompleteResponseStarted() {
}
}
-void ResourceLoader::StartReading(bool is_continuation) {
- int bytes_read = 0;
- ReadMore(&bytes_read);
-
- // If IO is pending, wait for the URLRequest to call OnReadCompleted.
- if (request_->status().is_io_pending())
- return;
-
- if (!is_continuation || bytes_read <= 0) {
- OnReadCompleted(request_.get(), bytes_read);
- } else {
- // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
- // thread in case the URLRequest can provide data synchronously.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&ResourceLoader::OnReadCompleted,
- weak_ptr_factory_.GetWeakPtr(), request_.get(), bytes_read));
- }
-}
-
-void ResourceLoader::ResumeReading() {
- DCHECK(!is_deferred());
-
- if (!read_deferral_start_time_.is_null()) {
- UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
- base::TimeTicks::Now() - read_deferral_start_time_);
- read_deferral_start_time_ = base::TimeTicks();
- }
- if (request_->status().is_success()) {
- StartReading(false); // Read the next chunk (OK to complete synchronously).
- } else {
- ResponseCompleted();
- }
-}
-
-void ResourceLoader::ReadMore(int* bytes_read) {
+void ResourceLoader::ReadMore(bool is_continuation) {
TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this,
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(!is_deferred());
@@ -608,6 +570,8 @@ void ResourceLoader::ReadMore(int* bytes_read) {
FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnWillRead()"));
if (!handler_->OnWillRead(&buf, &buf_size, -1)) {
+ // Cancel the request, which will then call back into |this| to inform it
+ // of a "read error".
Cancel();
return;
}
@@ -616,10 +580,36 @@ void ResourceLoader::ReadMore(int* bytes_read) {
DCHECK(buf.get());
DCHECK(buf_size > 0);
- request_->Read(buf.get(), buf_size, bytes_read);
+ int result = request_->Read(buf.get(), buf_size);
+
+ if (result == net::ERR_IO_PENDING)
+ return;
+
+ if (!is_continuation || result <= 0) {
+ OnReadCompleted(request_.get(), result);
+ } else {
+ // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
+ // thread in case the URLRequest can provide data synchronously.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&ResourceLoader::OnReadCompleted,
+ weak_ptr_factory_.GetWeakPtr(), request_.get(), result));
+ }
+}
- // No need to check the return value here as we'll detect errors by
- // inspecting the URLRequest's status.
+void ResourceLoader::ResumeReading() {
+ DCHECK(!is_deferred());
+
+ if (!read_deferral_start_time_.is_null()) {
+ UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
+ base::TimeTicks::Now() - read_deferral_start_time_);
+ read_deferral_start_time_ = base::TimeTicks();
+ }
+ if (request_->status().is_success()) {
+ ReadMore(false); // Read the next chunk (OK to complete synchronously).
+ } else {
+ ResponseCompleted();
+ }
}
void ResourceLoader::CompleteRead(int bytes_read) {
« 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