Chromium Code Reviews| Index: content/browser/loader/mojo_async_resource_handler.cc |
| diff --git a/content/browser/loader/mojo_async_resource_handler.cc b/content/browser/loader/mojo_async_resource_handler.cc |
| index 6d5a9d7c4a08f396856ebee72852a861a6a3eb21..fbdb4bb78439b0c01f5362a95e4e205f279e2f65 100644 |
| --- a/content/browser/loader/mojo_async_resource_handler.cc |
| +++ b/content/browser/loader/mojo_async_resource_handler.cc |
| @@ -127,8 +127,24 @@ bool MojoAsyncResourceHandler::OnRequestRedirected( |
| const net::RedirectInfo& redirect_info, |
| ResourceResponse* response, |
| bool* defer) { |
| - // Not implemented. |
| - return false; |
| + // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by |
| + // OnWillRead. |
| + DCHECK(!shared_writer_); |
| + |
| + *defer = true; |
| + request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| + did_defer_on_redirect_ = true; |
| + |
| + NetLogObserver::PopulateResponseInfo(request(), response); |
| + response->head.encoded_data_length = request()->GetTotalReceivedBytes(); |
| + response->head.request_start = request()->creation_time(); |
| + response->head.response_start = base::TimeTicks::Now(); |
| + // TODO(davidben): Is it necessary to pass the new first party URL for |
| + // cookies? The only case where it can change is top-level navigation requests |
| + // and hopefully those will eventually all be owned by the browser. It's |
| + // possible this is still needed while renderer-owned ones exist. |
| + url_loader_client_->OnReceiveRedirect(redirect_info, response->head); |
| + return true; |
| } |
| bool MojoAsyncResourceHandler::OnResponseStarted(ResourceResponse* response, |
| @@ -218,8 +234,10 @@ bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { |
| buffer_bytes_read_ = bytes_read; |
| if (!CopyReadDataToDataPipe(defer)) |
| return false; |
| - if (*defer) |
| - OnDefer(); |
| + if (*defer) { |
| + request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| + did_defer_on_writing_ = true; |
| + } |
| return true; |
| } |
| @@ -229,8 +247,10 @@ bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { |
| // doesn't have |defer| parameter. |
| if (!AllocateWriterIOBuffer(&buffer_, defer)) |
| return false; |
| - if (*defer) |
| - OnDefer(); |
| + if (*defer) { |
| + request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| + did_defer_on_writing_ = true; |
| + } |
| return true; |
| } |
| @@ -245,11 +265,24 @@ void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
| } |
| void MojoAsyncResourceHandler::FollowRedirect() { |
| - NOTIMPLEMENTED(); |
| + if (!request()->status().is_success()) { |
| + DVLOG(1) << "FollowRedirect for invalid request"; |
| + return; |
| + } |
| + if (!did_defer_on_redirect_) { |
| + DVLOG(1) << "Malformed FollowRedirect request"; |
| + controller()->CancelWithError(net::ERR_ABORTED); |
| + return; |
| + } |
| + |
| + DCHECK(!did_defer_on_writing_); |
|
dcheng
2016/11/15 07:41:41
So in general, loading is a large state machine. I
yhirano
2016/11/15 08:08:24
This dcheck is not affected by a malformed rendere
|
| + did_defer_on_redirect_ = false; |
| + request()->LogUnblocked(); |
| + controller()->Resume(); |
| } |
| -void MojoAsyncResourceHandler::ResumeForTesting() { |
| - Resume(); |
| +void MojoAsyncResourceHandler::OnWritableForTesting() { |
| + OnWritable(MOJO_RESULT_OK); |
| } |
| void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { |
| @@ -351,28 +384,41 @@ bool MojoAsyncResourceHandler::AllocateWriterIOBuffer( |
| return true; |
| } |
| -void MojoAsyncResourceHandler::Resume() { |
| - if (!did_defer_) |
| +bool MojoAsyncResourceHandler::CheckForSufficientResource() { |
| + if (has_checked_for_sufficient_resources_) |
| + return true; |
| + has_checked_for_sufficient_resources_ = true; |
| + |
| + if (rdh_->HasSufficientResourcesForRequest(request())) |
| + return true; |
| + |
| + controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); |
| + return false; |
| +} |
| + |
| +void MojoAsyncResourceHandler::OnWritable(MojoResult result) { |
| + if (!did_defer_on_writing_) |
| return; |
| - did_defer_ = false; |
| + DCHECK(!did_defer_on_redirect_); |
| + did_defer_on_writing_ = false; |
| if (is_using_io_buffer_not_from_writer_) { |
| // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents |
| // to the data pipe. |
| DCHECK_GT(buffer_bytes_read_, 0u); |
| - if (!CopyReadDataToDataPipe(&did_defer_)) { |
| + if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { |
| controller()->CancelWithError(net::ERR_FAILED); |
| return; |
| } |
| } else { |
| // Allocate a buffer for the next OnWillRead call here. |
| - if (!AllocateWriterIOBuffer(&buffer_, &did_defer_)) { |
| + if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { |
| controller()->CancelWithError(net::ERR_FAILED); |
| return; |
| } |
| } |
| - if (did_defer_) { |
| + if (did_defer_on_writing_) { |
| // Continue waiting. |
| return; |
| } |
| @@ -380,27 +426,6 @@ void MojoAsyncResourceHandler::Resume() { |
| controller()->Resume(); |
| } |
| -void MojoAsyncResourceHandler::OnDefer() { |
| - request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| - did_defer_ = true; |
| -} |
| - |
| -bool MojoAsyncResourceHandler::CheckForSufficientResource() { |
| - if (has_checked_for_sufficient_resources_) |
| - return true; |
| - has_checked_for_sufficient_resources_ = true; |
| - |
| - if (rdh_->HasSufficientResourcesForRequest(request())) |
| - return true; |
| - |
| - controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); |
| - return false; |
| -} |
| - |
| -void MojoAsyncResourceHandler::OnWritable(MojoResult unused) { |
| - Resume(); |
| -} |
| - |
| void MojoAsyncResourceHandler::Cancel() { |
| const ResourceRequestInfoImpl* info = GetRequestInfo(); |
| ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( |