Index: content/browser/loader/async_resource_handler.cc |
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc |
index 3b3cb0c5b926d0db247ca97f2a391ecd9ec2dc0a..3b7d1c1e0a9206a65e8fa996587ac12b08614d74 100644 |
--- a/content/browser/loader/async_resource_handler.cc |
+++ b/content/browser/loader/async_resource_handler.cc |
@@ -29,6 +29,8 @@ |
#include "content/public/browser/resource_dispatcher_host_delegate.h" |
#include "content/public/common/content_features.h" |
#include "content/public/common/resource_response.h" |
+#include "mojo/message_pump/handle_watcher.h" |
+#include "mojo/public/cpp/system/data_pipe.h" |
#include "net/base/io_buffer.h" |
#include "net/base/load_flags.h" |
#include "net/log/net_log.h" |
@@ -191,9 +193,85 @@ class DependentIOBuffer : public net::WrappedIOBuffer { |
scoped_refptr<ResourceBuffer> backing_; |
}; |
-AsyncResourceHandler::AsyncResourceHandler( |
- net::URLRequest* request, |
- ResourceDispatcherHostImpl* rdh) |
+// This class is used when the resource is being loaded via mojo. This class |
+// uses mojo data pipe instead of shared memory transferred via ChromeIPC. |
+class AsyncResourceHandler::MojoHelper final { |
mmenke
2016/05/24 20:01:35
Long term, is the plan to merge this into AsyncRes
yhirano
2016/05/25 12:47:05
Yes, our plan is replacing ChromeIPC with mojo.
|
+ public: |
+ explicit MojoHelper(AsyncResourceHandler* owner) : owner_(owner) {} |
+ // Called from AsyncResourceHandler::OnWillRead. |
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
+ int* buf_size, |
+ int min_size) { |
+ void* buffer = nullptr; |
+ uint32_t available = 0; |
+ if (!writer_.is_valid()) { |
+ MojoCreateDataPipeOptions options; |
+ options.struct_size = sizeof(MojoCreateDataPipeOptions); |
+ options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
+ options.element_num_bytes = 1; |
+ options.capacity_num_bytes = kMaxAllocationSize; |
+ mojo::DataPipe data_pipe(options); |
+ |
+ writer_ = std::move(data_pipe.producer_handle); |
+ ResourceMessageFilter* filter = owner_->GetRequestInfo()->filter(); |
+ if (filter) { |
+ filter->OnStartLoadingResponseBodyWithMojo( |
+ owner_->GetRequestInfo()->GetGlobalRequestID(), |
+ std::move(data_pipe.consumer_handle)); |
+ } |
+ } |
+ if (!writer_.is_valid()) { |
+ owner_->controller()->CancelWithError(net::ERR_FAILED); |
+ return false; |
+ } |
+ |
+ MojoResult result = mojo::BeginWriteDataRaw( |
+ writer_.get(), &buffer, &available, MOJO_WRITE_DATA_FLAG_NONE); |
+ // Note that SHOULD_WAIT should be handled in OnReadCompleted. |
+ if (result == MOJO_RESULT_OK) { |
+ *buf = new net::WrappedIOBuffer(static_cast<const char*>(buffer)); |
+ *buf_size = available; |
+ return true; |
+ } |
+ return false; |
mmenke
2016/05/24 20:01:35
This case is currently a fatal error?
yhirano
2016/05/25 12:47:05
Done.
|
+ } |
+ |
+ // Called from AsyncResourceHandler::OnReadCompleted. |
+ bool OnReadCompleted(int bytes_read, bool* defer) { |
+ MojoResult result = mojo::EndWriteDataRaw(writer_.get(), bytes_read); |
+ if (result != MOJO_RESULT_OK) |
+ return false; |
+ void* buffer = nullptr; |
+ uint32_t available = 0; |
+ // To see if the handle is still writable. |
+ result = mojo::BeginWriteDataRaw(writer_.get(), &buffer, &available, |
+ MOJO_WRITE_DATA_FLAG_NONE); |
+ if (result == MOJO_RESULT_SHOULD_WAIT || |
+ (result == MOJO_RESULT_OK && available == 0)) { |
+ *defer = owner_->did_defer_ = true; |
+ owner_->OnDefer(); |
+ handle_watcher_.Start( |
+ writer_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, |
+ base::Bind(&MojoHelper::OnWritable, base::Unretained(this))); |
+ } |
+ if (result == MOJO_RESULT_OK) |
+ mojo::EndWriteDataRaw(writer_.get(), 0); |
+ return true; |
+ } |
+ |
+ private: |
+ void OnWritable(MojoResult result) { owner_->ResumeIfDeferred(); } |
+ |
+ mojo::ScopedDataPipeProducerHandle writer_; |
+ mojo::common::HandleWatcher handle_watcher_; |
+ AsyncResourceHandler* owner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MojoHelper); |
+}; |
+ |
+AsyncResourceHandler::AsyncResourceHandler(net::URLRequest* request, |
+ ResourceDispatcherHostImpl* rdh, |
+ bool using_mojo_data_handle) |
: ResourceHandler(request), |
ResourceMessageDelegate(request), |
rdh_(rdh), |
@@ -206,7 +284,8 @@ AsyncResourceHandler::AsyncResourceHandler( |
inlining_helper_(new InliningHelper), |
last_upload_position_(0), |
waiting_for_upload_progress_ack_(false), |
- reported_transfer_size_(0) { |
+ reported_transfer_size_(0), |
+ mojo_helper_(using_mojo_data_handle ? new MojoHelper(this) : nullptr) { |
InitializeResourceBufferConstants(); |
} |
@@ -396,6 +475,9 @@ bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
if (!CheckForSufficientResource()) |
return false; |
+ if (mojo_helper_) |
+ return mojo_helper_->OnWillRead(buf, buf_size, min_size); |
+ |
// Return early if InliningHelper allocates the buffer, so that we should |
// inline the data into the IPC message without allocating SharedMemory. |
if (inlining_helper_->PrepareInlineBufferIfApplicable(buf, buf_size)) |
@@ -420,6 +502,9 @@ bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { |
if (!bytes_read) |
return true; |
+ if (mojo_helper_) |
+ return mojo_helper_->OnReadCompleted(bytes_read, defer); |
+ |
ResourceMessageFilter* filter = GetFilter(); |
if (!filter) |
return false; |