Chromium Code Reviews| Index: content/browser/loader/resource_loader.cc |
| diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc |
| index 7c707c09da5cb0e7ab3fdbccafee12adfd7e31b2..9a94cc6fbb388a30215551fe00b76d5edd36ac6d 100644 |
| --- a/content/browser/loader/resource_loader.cc |
| +++ b/content/browser/loader/resource_loader.cc |
| @@ -512,10 +512,19 @@ void ResourceLoader::Resume(bool called_from_resource_controller) { |
| // was called from Resume(). |
| FollowDeferredRedirectInternal(); |
| break; |
| + case DEFERRED_ON_WILL_READ: |
| + // Always post a task, as synchronous resumes don't go through this |
| + // method. |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, base::Bind(&ResourceLoader::ReadMore, |
| + weak_ptr_factory_.GetWeakPtr(), false)); |
|
Charlie Harrison
2017/03/08 21:12:46
nit: false /* handle_result_asynchronously */
mmenke
2017/03/08 22:51:30
Done.
|
| + break; |
| case DEFERRED_READ: |
| if (called_from_resource_controller) { |
| - // TODO(mmenke): Call ReadMore instead? Strange that this is the only |
| - // path which calls different methods, depending on the path. |
| + // TODO(mmenke): Call PrepareToReadMore instead? Strange that this is |
| + // the only case which calls different methods, depending on the path. |
| + // ResumeReading does check for cancellation. Should other paths do that |
| + // as well? |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, |
| weak_ptr_factory_.GetWeakPtr())); |
| @@ -523,7 +532,7 @@ void ResourceLoader::Resume(bool called_from_resource_controller) { |
| // If this was called as a result of a handler succeeding synchronously, |
| // force the result of the next read to be handled asynchronously, to |
| // avoid blocking the IO thread. |
| - ReadMore(true /* handle_result_asynchronously */); |
| + PrepareToReadMore(true /* handle_result_asynchronously */); |
| } |
| break; |
| case DEFERRED_RESPONSE_COMPLETE: |
| @@ -638,40 +647,45 @@ void ResourceLoader::CompleteResponseStarted() { |
| read_deferral_start_time_ = base::TimeTicks::Now(); |
| // Using a ScopedDeferral here would result in calling ReadMore(true) on sync |
| - // success. Calling ReadMore(false) here instead allows small responses to be |
| - // handled completely synchronously, if no ResourceHandler defers handling of |
| - // the response. |
| + // success. Calling PrepareToReadMore(false) here instead allows small |
| + // responses to be handled completely synchronously, if no ResourceHandler |
| + // defers handling of the response. |
| deferred_stage_ = DEFERRED_SYNC; |
| handler_->OnResponseStarted(response.get(), |
| base::MakeUnique<Controller>(this)); |
| if (is_deferred()) { |
| deferred_stage_ = DEFERRED_READ; |
| } else { |
| - ReadMore(false); |
| + PrepareToReadMore(false); |
| } |
| } |
| -void ResourceLoader::ReadMore(bool handle_result_async) { |
| - TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, |
| +void ResourceLoader::PrepareToReadMore(bool handle_result_async) { |
| + TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::PrepareToReadMore", this, |
| TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
| DCHECK(!is_deferred()); |
| - // Make sure we track the buffer in at least one place. This ensures it gets |
| - // deleted even in the case the request has already finished its job and |
| - // doesn't use the buffer. |
| - scoped_refptr<net::IOBuffer> buf; |
| - int buf_size; |
| - if (!handler_->OnWillRead(&buf, &buf_size)) { |
| - // Cancel the request, which will then call back into |this| to inform it of |
| - // a "read error". |
| - Cancel(); |
| - return; |
| + deferred_stage_ = DEFERRED_SYNC; |
| + |
| + handler_->OnWillRead(&read_buffer_, &read_buffer_size_, |
| + base::MakeUnique<Controller>(this)); |
| + |
| + if (is_deferred()) { |
| + deferred_stage_ = DEFERRED_ON_WILL_READ; |
| + } else { |
| + ReadMore(handle_result_async); |
| } |
| +} |
| - DCHECK(buf.get()); |
| - DCHECK(buf_size > 0); |
| +void ResourceLoader::ReadMore(bool handle_result_async) { |
| + DCHECK(read_buffer_.get()); |
| + DCHECK_GT(read_buffer_size_, 0); |
| - int result = request_->Read(buf.get(), buf_size); |
| + int result = request_->Read(read_buffer_.get(), read_buffer_size_); |
| + // Have to do this after the Read call, to ensure it still has an outstanding |
| + // reference. |
| + read_buffer_ = nullptr; |
| + read_buffer_size_ = 0; |
| if (result == net::ERR_IO_PENDING) |
| return; |
| @@ -697,7 +711,7 @@ void ResourceLoader::ResumeReading() { |
| read_deferral_start_time_ = base::TimeTicks(); |
| } |
| if (request_->status().is_success()) { |
| - ReadMore(false /* handle_result_asynchronously */); |
| + PrepareToReadMore(false /* handle_result_asynchronously */); |
| } else { |
| ResponseCompleted(); |
| } |