diff options
author | amistry <amistry@chromium.org> | 2016-02-21 18:54:03 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-22 02:55:26 +0000 |
commit | af22d8630a5ded9cd9ce5f1cdc4a66132ec507ed (patch) | |
tree | 9d3337b3419b0b58f954055adf8d6b05e5721f73 | |
parent | 05bb3a24ac49d7fbfff7eb6885a1d96b83e40064 (diff) | |
download | chromium_src-af22d8630a5ded9cd9ce5f1cdc4a66132ec507ed.zip chromium_src-af22d8630a5ded9cd9ce5f1cdc4a66132ec507ed.tar.gz chromium_src-af22d8630a5ded9cd9ce5f1cdc4a66132ec507ed.tar.bz2 |
[mojo-edk] Embedder API for MojoHandle to base::SharedMemoryHandle.
Add an embedder function that retrieves a base::SharedMemoryHandle from
a shared buffer MojoHandle. The MojoHandle is closed as a result.
BUG=588268,582993
Review URL: https://codereview.chromium.org/1718963002
Cr-Commit-Position: refs/heads/master@{#376679}
-rw-r--r-- | mojo/edk/embedder/embedder.cc | 9 | ||||
-rw-r--r-- | mojo/edk/embedder/embedder.h | 15 | ||||
-rw-r--r-- | mojo/edk/embedder/embedder_unittest.cc | 15 | ||||
-rw-r--r-- | mojo/edk/embedder/platform_shared_buffer.cc | 7 | ||||
-rw-r--r-- | mojo/edk/embedder/platform_shared_buffer.h | 3 | ||||
-rw-r--r-- | mojo/edk/system/core.cc | 42 | ||||
-rw-r--r-- | mojo/edk/system/core.h | 6 | ||||
-rw-r--r-- | mojo/edk/system/shared_buffer_dispatcher.cc | 13 | ||||
-rw-r--r-- | mojo/edk/system/shared_buffer_dispatcher.h | 4 |
9 files changed, 111 insertions, 3 deletions
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 1feadda..62702af 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc @@ -87,6 +87,15 @@ MojoResult CreateSharedBufferWrapper( shared_memory_handle, num_bytes, read_only, mojo_wrapper_handle); } +MojoResult PassSharedMemoryHandle( + MojoHandle mojo_handle, + base::SharedMemoryHandle* shared_memory_handle, + size_t* num_bytes, + bool* read_only) { + return internal::g_core->PassSharedMemoryHandle( + mojo_handle, shared_memory_handle, num_bytes, read_only); +} + void InitIPCSupport(ProcessDelegate* process_delegate, scoped_refptr<base::TaskRunner> io_thread_task_runner) { CHECK(internal::g_core); diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index e34ef5c..95b3b21 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h @@ -94,6 +94,21 @@ CreateSharedBufferWrapper(base::SharedMemoryHandle shared_memory_handle, bool read_only, MojoHandle* mojo_wrapper_handle); +// Retrieves the underlying |SharedMemoryHandle| from a shared buffer +// |MojoHandle| and closes the handle. If successful, |num_bytes| will contain +// the size of the shared memory buffer and |read_only| will contain whether the +// buffer handle is read-only. Both |num_bytes| and |read_only| may be null. +// Note: The value of |shared_memory_handle| may be +// base::SharedMemory::NULLHandle(), even if this function returns success. +// Callers should perform appropriate checks. +// TODO(crbug.com/556587): Support read-only handles. Currently, |read_only| +// will always return |false|. +MOJO_SYSTEM_IMPL_EXPORT MojoResult +PassSharedMemoryHandle(MojoHandle mojo_handle, + base::SharedMemoryHandle* shared_memory_handle, + size_t* num_bytes, + bool* read_only); + // Initialialization/shutdown for interprocess communication (IPC) ------------- // |InitIPCSupport()| sets up the subsystem for interprocess communication, diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc index 1a36378..9b96c1f 100644 --- a/mojo/edk/embedder/embedder_unittest.cc +++ b/mojo/edk/embedder/embedder_unittest.cc @@ -362,8 +362,19 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessSharedMemoryClient, EmbedderTest, memcpy(buffer, kByeWorld, sizeof(kByeWorld)); WriteMessage(client_mp, "bye"); - // 5. Close |sb1|. - EXPECT_EQ(MOJO_RESULT_OK, MojoClose(sb1)); + // 5. Extract the shared memory handle and ensure we can map it and read the + // contents. + base::SharedMemoryHandle shm_handle; + ASSERT_EQ(MOJO_RESULT_OK, + PassSharedMemoryHandle(sb1, &shm_handle, nullptr, nullptr)); + base::SharedMemory shared_memory(shm_handle, false); + ASSERT_TRUE(shared_memory.Map(123)); + EXPECT_NE(buffer, shared_memory.memory()); + EXPECT_EQ(kByeWorld, std::string(static_cast<char*>(shared_memory.memory()))); + + // 6. Close |sb1|. Should fail because |PassSharedMemoryHandle()| should have + // closed the handle. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(sb1)); } // TODO(vtl): Test immediate write & close. diff --git a/mojo/edk/embedder/platform_shared_buffer.cc b/mojo/edk/embedder/platform_shared_buffer.cc index 9dce8d5..bbcf15d 100644 --- a/mojo/edk/embedder/platform_shared_buffer.cc +++ b/mojo/edk/embedder/platform_shared_buffer.cc @@ -152,6 +152,13 @@ ScopedPlatformHandle PlatformSharedBuffer::PassPlatformHandle() { return handle; } +base::SharedMemoryHandle PlatformSharedBuffer::DuplicateSharedMemoryHandle() { + DCHECK(shared_memory_); + + base::AutoLock locker(lock_); + return base::SharedMemory::DuplicateHandle(shared_memory_->handle()); +} + PlatformSharedBuffer::PlatformSharedBuffer(size_t num_bytes) : num_bytes_(num_bytes) {} diff --git a/mojo/edk/embedder/platform_shared_buffer.h b/mojo/edk/embedder/platform_shared_buffer.h index 623fb9e..5494122 100644 --- a/mojo/edk/embedder/platform_shared_buffer.h +++ b/mojo/edk/embedder/platform_shared_buffer.h @@ -74,6 +74,9 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer // TODO(vtl): On POSIX, we'll need two FDs to support sharing read-only. ScopedPlatformHandle DuplicatePlatformHandle(); + // Duplicates the underlying shared memory handle and passes it to the caller. + base::SharedMemoryHandle DuplicateSharedMemoryHandle(); + // Passes the underlying platform handle to the caller. This should only be // called if there's a unique reference to this object (owned by the caller). // After calling this, this object should no longer be used, but should only diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index 11892be..69c918c 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc @@ -163,6 +163,48 @@ MojoResult Core::CreateSharedBufferWrapper( return MOJO_RESULT_OK; } +MojoResult Core::PassSharedMemoryHandle( + MojoHandle mojo_handle, + base::SharedMemoryHandle* shared_memory_handle, + size_t* num_bytes, + bool* read_only) { + if (!shared_memory_handle) + return MOJO_RESULT_INVALID_ARGUMENT; + + scoped_refptr<Dispatcher> dispatcher; + MojoResult result = MOJO_RESULT_OK; + { + base::AutoLock lock(handles_lock_); + // Get the dispatcher and check it before removing it from the handle table + // to ensure that the dispatcher is of the correct type. This ensures we + // don't close and remove the wrong type of dispatcher. + dispatcher = handles_.GetDispatcher(mojo_handle); + if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) + return MOJO_RESULT_INVALID_ARGUMENT; + + result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher); + if (result != MOJO_RESULT_OK) + return result; + } + + SharedBufferDispatcher* shm_dispatcher = + static_cast<SharedBufferDispatcher*>(dispatcher.get()); + scoped_refptr<PlatformSharedBuffer> platform_shared_buffer = + shm_dispatcher->PassPlatformSharedBuffer(); + + if (!platform_shared_buffer) + return MOJO_RESULT_INVALID_ARGUMENT; + + if (num_bytes) + *num_bytes = platform_shared_buffer->GetNumBytes(); + if (read_only) + *read_only = false; + *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle(); + + shm_dispatcher->Close(); + return result; +} + void Core::RequestShutdown(const base::Closure& callback) { base::Closure on_shutdown; if (base::ThreadTaskRunnerHandle::IsSet()) { diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 938726a..e2a22b0 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h @@ -88,6 +88,12 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { bool read_only, MojoHandle* mojo_wrapper_handle); + MojoResult PassSharedMemoryHandle( + MojoHandle mojo_handle, + base::SharedMemoryHandle* shared_memory_handle, + size_t* num_bytes, + bool* read_only); + // Requests that the EDK tear itself down. |callback| will be called once // the shutdown process is complete. Note that |callback| is always called // asynchronously on the calling thread if said thread is running a message diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc index 1484166..1805a92 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/mojo/edk/system/shared_buffer_dispatcher.cc @@ -139,13 +139,24 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( return CreateInternal(std::move(shared_buffer)); } +scoped_refptr<PlatformSharedBuffer> +SharedBufferDispatcher::PassPlatformSharedBuffer() { + base::AutoLock lock(lock_); + if (!shared_buffer_ || in_transit_) + return nullptr; + + scoped_refptr<PlatformSharedBuffer> retval = shared_buffer_; + shared_buffer_ = nullptr; + return retval; +} + Dispatcher::Type SharedBufferDispatcher::GetType() const { return Type::SHARED_BUFFER; } MojoResult SharedBufferDispatcher::Close() { base::AutoLock lock(lock_); - if (!shared_buffer_ || in_transit_) + if (in_transit_) return MOJO_RESULT_INVALID_ARGUMENT; shared_buffer_ = nullptr; diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h index 011a43a..a8d5bcd 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.h +++ b/mojo/edk/system/shared_buffer_dispatcher.h @@ -61,6 +61,10 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher { PlatformHandle* platform_handles, size_t num_platform_handles); + // Passes the underlying platform shared buffer. This dispatcher must be + // closed after calling this function. + scoped_refptr<PlatformSharedBuffer> PassPlatformSharedBuffer(); + // Dispatcher: Type GetType() const override; MojoResult Close() override; |