| 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 571c71805ed2760d1f644e1d5db86861c5ff73d6..1c4fc78a631a9dd02eba9ae36b86a1679e778aad 100644
|
| --- a/content/browser/loader/mojo_async_resource_handler.cc
|
| +++ b/content/browser/loader/mojo_async_resource_handler.cc
|
| @@ -28,8 +28,8 @@
|
| #include "content/public/common/resource_response.h"
|
| #include "mojo/public/c/system/data_pipe.h"
|
| #include "mojo/public/cpp/bindings/message.h"
|
| +#include "net/base/io_buffer.h"
|
| #include "net/base/mime_sniffer.h"
|
| -#include "net/base/net_errors.h"
|
| #include "net/url_request/redirect_info.h"
|
|
|
| namespace content {
|
| @@ -227,20 +227,12 @@
|
| scoped_refptr<net::IOBuffer>* buf,
|
| int* buf_size,
|
| std::unique_ptr<ResourceController> controller) {
|
| - // |buffer_| is set to nullptr on successful read completion (Except for the
|
| - // final 0-byte read, so this DCHECK will also catch OnWillRead being called
|
| - // after OnReadCompelted(0)).
|
| - DCHECK(!buffer_);
|
| - DCHECK_EQ(0u, buffer_offset_);
|
| -
|
| if (!CheckForSufficientResource()) {
|
| controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| return;
|
| }
|
|
|
| - bool first_call = false;
|
| if (!shared_writer_) {
|
| - first_call = true;
|
| MojoCreateDataPipeOptions options;
|
| options.struct_size = sizeof(MojoCreateDataPipeOptions);
|
| options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
|
| @@ -257,38 +249,33 @@
|
| base::Bind(&MojoAsyncResourceHandler::OnWritable,
|
| base::Unretained(this)));
|
| handle_watcher_.ArmOrNotify();
|
| - }
|
| -
|
| - bool defer = false;
|
| - if (!AllocateWriterIOBuffer(&buffer_, &defer)) {
|
| - controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| - return;
|
| - }
|
| -
|
| - if (defer) {
|
| - DCHECK(!buffer_);
|
| - parent_buffer_ = buf;
|
| - parent_buffer_size_ = buf_size;
|
| - HoldController(std::move(controller));
|
| - request()->LogBlockedBy("MojoAsyncResourceHandler");
|
| - did_defer_on_will_read_ = true;
|
| - return;
|
| - }
|
| -
|
| - // The first call to OnWillRead must return a buffer of at least
|
| - // kMinAllocationSize. If the Mojo buffer is too small, need to allocate an
|
| - // intermediary buffer.
|
| - if (first_call && static_cast<size_t>(buffer_->size()) < kMinAllocationSize) {
|
| - // The allocated buffer is too small, so need to create an intermediary one.
|
| - if (EndWrite(0) != MOJO_RESULT_OK) {
|
| +
|
| + bool defer = false;
|
| + scoped_refptr<net::IOBufferWithSize> buffer;
|
| + if (!AllocateWriterIOBuffer(&buffer, &defer)) {
|
| controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| return;
|
| + }
|
| + if (!defer) {
|
| + if (static_cast<size_t>(buffer->size()) >= kMinAllocationSize) {
|
| + *buf = buffer_ = buffer;
|
| + *buf_size = buffer_->size();
|
| + controller->Resume();
|
| + return;
|
| + }
|
| +
|
| + // The allocated buffer is too small.
|
| + if (EndWrite(0) != MOJO_RESULT_OK) {
|
| + controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| + return;
|
| + }
|
| }
|
| DCHECK(!is_using_io_buffer_not_from_writer_);
|
| is_using_io_buffer_not_from_writer_ = true;
|
| buffer_ = new net::IOBufferWithSize(kMinAllocationSize);
|
| }
|
|
|
| + DCHECK_EQ(0u, buffer_offset_);
|
| *buf = buffer_;
|
| *buf_size = buffer_->size();
|
| controller->Resume();
|
| @@ -301,9 +288,7 @@
|
| DCHECK_GE(bytes_read, 0);
|
| DCHECK(buffer_);
|
|
|
| - if (bytes_read == 0) {
|
| - // Note that |buffer_| is not cleared here, which will cause a DCHECK on
|
| - // subsequent OnWillRead calls.
|
| + if (!bytes_read) {
|
| controller->Resume();
|
| return;
|
| }
|
| @@ -323,12 +308,12 @@
|
| }
|
|
|
| if (is_using_io_buffer_not_from_writer_) {
|
| - // Couldn't allocate a large enough buffer on the data pipe in OnWillRead.
|
| + // Couldn't allocate a buffer on the data pipe in OnWillRead.
|
| DCHECK_EQ(0u, buffer_bytes_read_);
|
| buffer_bytes_read_ = bytes_read;
|
| bool defer = false;
|
| if (!CopyReadDataToDataPipe(&defer)) {
|
| - controller->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| + controller->Cancel();
|
| return;
|
| }
|
| if (defer) {
|
| @@ -345,8 +330,20 @@
|
| controller->Cancel();
|
| return;
|
| }
|
| -
|
| - buffer_ = nullptr;
|
| + // Allocate a buffer for the next OnWillRead call here, because OnWillRead
|
| + // doesn't have |defer| parameter.
|
| + bool defer = false;
|
| + if (!AllocateWriterIOBuffer(&buffer_, &defer)) {
|
| + controller->Cancel();
|
| + return;
|
| + }
|
| + if (defer) {
|
| + request()->LogBlockedBy("MojoAsyncResourceHandler");
|
| + did_defer_on_writing_ = true;
|
| + HoldController(std::move(controller));
|
| + return;
|
| + }
|
| +
|
| controller->Resume();
|
| }
|
|
|
| @@ -366,7 +363,6 @@
|
| return;
|
| }
|
|
|
| - DCHECK(!did_defer_on_will_read_);
|
| DCHECK(!did_defer_on_writing_);
|
| did_defer_on_redirect_ = false;
|
| request()->LogUnblocked();
|
| @@ -458,12 +454,17 @@
|
| }
|
|
|
| bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) {
|
| - while (buffer_bytes_read_ > 0) {
|
| + while (true) {
|
| scoped_refptr<net::IOBufferWithSize> dest;
|
| if (!AllocateWriterIOBuffer(&dest, defer))
|
| return false;
|
| if (*defer)
|
| return true;
|
| + if (buffer_bytes_read_ == 0) {
|
| + // All bytes are copied. Save the buffer for the next OnWillRead call.
|
| + buffer_ = std::move(dest);
|
| + return true;
|
| + }
|
|
|
| size_t copied_size =
|
| std::min(buffer_bytes_read_, static_cast<size_t>(dest->size()));
|
| @@ -472,13 +473,13 @@
|
| buffer_bytes_read_ -= copied_size;
|
| if (EndWrite(copied_size) != MOJO_RESULT_OK)
|
| return false;
|
| - }
|
| -
|
| - // All bytes are copied.
|
| - buffer_ = nullptr;
|
| - buffer_offset_ = 0;
|
| - is_using_io_buffer_not_from_writer_ = false;
|
| - return true;
|
| +
|
| + if (buffer_bytes_read_ == 0) {
|
| + // All bytes are copied.
|
| + buffer_offset_ = 0;
|
| + is_using_io_buffer_not_from_writer_ = false;
|
| + }
|
| + }
|
| }
|
|
|
| bool MojoAsyncResourceHandler::AllocateWriterIOBuffer(
|
| @@ -493,7 +494,6 @@
|
| }
|
| if (result != MOJO_RESULT_OK)
|
| return false;
|
| - DCHECK_GT(available, 0u);
|
| *buf = new WriterIOBuffer(shared_writer_, data, available);
|
| return true;
|
| }
|
| @@ -510,34 +510,26 @@
|
| }
|
|
|
| void MojoAsyncResourceHandler::OnWritable(MojoResult result) {
|
| - if (did_defer_on_will_read_) {
|
| - DCHECK(has_controller());
|
| - DCHECK(!did_defer_on_writing_);
|
| - DCHECK(!did_defer_on_redirect_);
|
| -
|
| - did_defer_on_will_read_ = false;
|
| -
|
| - scoped_refptr<net::IOBuffer>* parent_buffer = parent_buffer_;
|
| - parent_buffer_ = nullptr;
|
| - int* parent_buffer_size = parent_buffer_size_;
|
| - parent_buffer_size_ = nullptr;
|
| - OnWillRead(parent_buffer, parent_buffer_size, ReleaseController());
|
| - return;
|
| - }
|
| -
|
| if (!did_defer_on_writing_)
|
| return;
|
| DCHECK(has_controller());
|
| DCHECK(!did_defer_on_redirect_);
|
| did_defer_on_writing_ = false;
|
|
|
| - DCHECK(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_on_writing_)) {
|
| - CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
|
| - return;
|
| + 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_on_writing_)) {
|
| + CancelWithError(net::ERR_FAILED);
|
| + return;
|
| + }
|
| + } else {
|
| + // Allocate a buffer for the next OnWillRead call here.
|
| + if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) {
|
| + CancelWithError(net::ERR_FAILED);
|
| + return;
|
| + }
|
| }
|
|
|
| if (did_defer_on_writing_) {
|
|
|