Index: content/browser/loader/detachable_resource_handler.cc |
diff --git a/content/browser/loader/detachable_resource_handler.cc b/content/browser/loader/detachable_resource_handler.cc |
index c534a25ad317cf64b74168338ec838355caf407f..aa1f7bd608369121b38a115e85e91d442973b088 100644 |
--- a/content/browser/loader/detachable_resource_handler.cc |
+++ b/content/browser/loader/detachable_resource_handler.cc |
@@ -36,7 +36,7 @@ class DetachableResourceHandler::Controller : public ResourceController { |
// ResourceController implementation: |
void Resume() override { |
MarkAsUsed(); |
- detachable_handler_->Resume(); |
+ detachable_handler_->ResumeInternal(); |
} |
void Cancel() override { |
@@ -78,6 +78,8 @@ DetachableResourceHandler::DetachableResourceHandler( |
: ResourceHandler(request), |
next_handler_(std::move(next_handler)), |
cancel_delay_(cancel_delay), |
+ parent_read_buffer_(nullptr), |
+ parent_read_buffer_size_(nullptr), |
is_finished_(false) { |
GetRequestInfo()->set_detachable_handler(this); |
} |
@@ -134,6 +136,23 @@ void DetachableResourceHandler::Detach() { |
// The nested ResourceHandler may have logged that it's blocking the |
// request. Log it as no longer doing so, to avoid a DCHECK on resume. |
request()->LogUnblocked(); |
+ |
+ // If in the middle of an OnWillRead call, need to allocate the read buffer |
+ // before resuming. |
+ if (parent_read_buffer_) { |
+ DCHECK(parent_read_buffer_size_); |
+ |
+ scoped_refptr<net::IOBuffer>* parent_read_buffer = parent_read_buffer_; |
+ int* parent_read_buffer_size = parent_read_buffer_size_; |
+ parent_read_buffer_ = nullptr; |
+ parent_read_buffer_size_ = nullptr; |
+ |
+ // Will allocate the buffer and resume the request. |
+ OnWillRead(parent_read_buffer, parent_read_buffer_size, |
+ ReleaseController()); |
+ return; |
+ } |
+ |
Resume(); |
} |
} |
@@ -183,17 +202,24 @@ void DetachableResourceHandler::OnWillStart( |
next_handler_->OnWillStart(url, base::MakeUnique<Controller>(this)); |
} |
-bool DetachableResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
- int* buf_size) { |
+void DetachableResourceHandler::OnWillRead( |
+ scoped_refptr<net::IOBuffer>* buf, |
+ int* buf_size, |
+ std::unique_ptr<ResourceController> controller) { |
if (!next_handler_) { |
if (!read_buffer_.get()) |
read_buffer_ = new net::IOBuffer(kReadBufSize); |
*buf = read_buffer_; |
*buf_size = kReadBufSize; |
- return true; |
+ controller->Resume(); |
+ return; |
} |
- return next_handler_->OnWillRead(buf, buf_size); |
+ parent_read_buffer_ = buf; |
+ parent_read_buffer_size_ = buf_size; |
+ |
+ HoldController(std::move(controller)); |
+ next_handler_->OnWillRead(buf, buf_size, base::MakeUnique<Controller>(this)); |
} |
void DetachableResourceHandler::OnReadCompleted( |
@@ -236,6 +262,12 @@ void DetachableResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
next_handler_->OnDataDownloaded(bytes_downloaded); |
} |
+void DetachableResourceHandler::ResumeInternal() { |
+ parent_read_buffer_ = nullptr; |
+ parent_read_buffer_size_ = nullptr; |
+ Resume(); |
+} |
+ |
void DetachableResourceHandler::OnTimedOut() { |
// Requests are only timed out after being detached, and shouldn't be deferred |
// once detached. |