Index: blimp/engine/renderer/blob_channel_sender_proxy.cc |
diff --git a/blimp/engine/renderer/blob_channel_sender_proxy.cc b/blimp/engine/renderer/blob_channel_sender_proxy.cc |
index 8b689d36c73dd840878105bb72a926845ebe97be..9b02fff422af5cb0e4eab0dd9b5d70b5197007f0 100644 |
--- a/blimp/engine/renderer/blob_channel_sender_proxy.cc |
+++ b/blimp/engine/renderer/blob_channel_sender_proxy.cc |
@@ -19,6 +19,59 @@ mojom::BlobChannelPtr GetConnectedBlobChannel() { |
return blob_channel_ptr; |
} |
+// Manages the creation and lifetime of Mojo shared memory buffers for blobs. |
+// Cleans up the shared memory state when deleted. |
+// Caller is responsible for ensuring that |this| is not deleted until the |
+// remote side has acknowledged that it is finished using the buffer. |
+class SharedMemoryBlob { |
+ public: |
+ explicit SharedMemoryBlob(BlobDataPtr data) { |
+ mojo::ScopedSharedBufferHandle local_handle; |
+ MojoResult result = |
+ mojo::CreateSharedBuffer(NULL, data->data.size(), &local_handle); |
+ CHECK_EQ(MOJO_RESULT_OK, result) |
+ << "Mojo error when creating shared buffer: " << result; |
+ |
+ result = mojo::MapBuffer(local_handle.get(), 0, data->data.size(), |
+ &mapped_data_, MOJO_MAP_BUFFER_FLAG_NONE); |
+ CHECK_EQ(MOJO_RESULT_OK, result) |
+ << "Mojo error when memory mapping shared buffer: " << result; |
+ memcpy(mapped_data_, data->data.data(), data->data.size()); |
+ |
+ // Create read-only handle for browser-side consumption. |
+ MojoDuplicateBufferHandleOptions options{ |
+ sizeof(MojoDuplicateBufferHandleOptions), |
+ MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY}; |
+ result = |
+ mojo::DuplicateBuffer(local_handle.get(), &options, &remote_handle_); |
+ CHECK_EQ(MOJO_RESULT_OK, result) |
+ << "Mojo error when creating read-only buffer handle."; |
+ DCHECK(remote_handle_.is_valid()); |
+ } |
+ |
+ ~SharedMemoryBlob() { |
+ MojoResult result = mojo::UnmapBuffer(mapped_data_); |
+ CHECK_EQ(MOJO_RESULT_OK, result); |
+ } |
+ |
+ mojo::ScopedSharedBufferHandle take_remote_handle() { |
+ return std::move(remote_handle_); |
+ } |
+ |
+ private: |
+ // Pointer to shared memory buffer. |
+ void* mapped_data_; |
+ |
+ // Handle to be passed to the remote end of the BlobChannel Mojo service. |
+ mojo::ScopedSharedBufferHandle remote_handle_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SharedMemoryBlob); |
+}; |
+ |
+void PutComplete(std::unique_ptr<SharedMemoryBlob>) { |
+ // Allow the blob to go out of scope and be deleted. |
+} |
+ |
} // namespace |
BlobChannelSenderProxy::BlobChannelSenderProxy() |
@@ -37,8 +90,17 @@ bool BlobChannelSenderProxy::IsInClientCache(const std::string& id) const { |
void BlobChannelSenderProxy::PutBlob(const BlobId& id, BlobDataPtr data) { |
DCHECK(!IsInEngineCache(id)); |
+ if (data->data.size() == 0) { |
+ return; |
+ } |
+ |
+ size_t size = data->data.size(); |
replication_state_[id] = false; |
- blob_channel_->PutBlob(id, data->data); |
+ std::unique_ptr<SharedMemoryBlob> shared_mem_blob( |
+ new SharedMemoryBlob(std::move(data))); |
+ blob_channel_->PutBlob( |
+ id, shared_mem_blob->take_remote_handle(), size, |
+ base::Bind(&PutComplete, base::Passed(std::move(shared_mem_blob)))); |
} |
void BlobChannelSenderProxy::DeliverBlob(const std::string& id) { |