Commit 39bd21e4 authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

Mojo: More shared buffer API prep work

Cherry-picks a couple of things:

  - Adds support for wrapping and unwrapping new base shm regions
  - Ports one use (PDF compositor test code) to use the above
  - Updates base::SharedMemory wrapping to force read-only regions
    when wrapping a handle as read-only

Bug: 826213
Change-Id: I11d923b23688454ffdbf26ba5efa93ba1605b855
Reviewed-on: https://chromium-review.googlesource.com/992360Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarJay Civelli <jcivelli@chromium.org>
Commit-Queue: Ken Rockot <rockot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547728}
parent 5f02ed92
......@@ -7,7 +7,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/shared_memory.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/test_discardable_memory_allocator.h"
......@@ -139,19 +139,11 @@ class PdfCompositorServiceTest : public service_manager::test::ServiceTest {
doc->close();
size_t len = stream.bytesWritten();
base::SharedMemoryCreateOptions options;
options.size = len;
options.share_read_only = true;
base::SharedMemory shared_memory;
if (shared_memory.Create(options) && shared_memory.Map(len)) {
stream.copyTo(shared_memory.memory());
auto handle = shared_memory.GetReadOnlyHandle();
return mojo::WrapSharedMemoryHandle(
handle, handle.GetSize(),
mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly);
}
return mojo::ScopedSharedBufferHandle();
base::MappedReadOnlyRegion memory =
base::ReadOnlySharedMemoryRegion::Create(len);
CHECK(memory.mapping.IsValid());
stream.copyTo(memory.mapping.memory());
return mojo::WrapReadOnlySharedMemoryRegion(std::move(memory.region));
}
void CallCompositorWithSuccess(mojom::PdfCompositorPtr ptr) {
......
......@@ -4,6 +4,9 @@
#include "mojo/public/cpp/system/platform_handle.h"
#include "base/memory/platform_shared_memory_region.h"
#include "build/build_config.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include <mach/mach.h>
#include "base/mac/mach_logging.h"
......@@ -29,6 +32,103 @@ base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
#endif
}
ScopedSharedBufferHandle WrapPlatformSharedMemoryRegion(
base::subtle::PlatformSharedMemoryRegion region) {
if (!region.IsValid())
return ScopedSharedBufferHandle();
// TODO(https://crbug.com/826213): Support writable regions too, then simplify
// mojom base shared memory traits using this code. This will require the C
// API to be extended first.
DCHECK_NE(base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
region.GetMode());
base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle =
region.PassPlatformHandle();
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(platform_handle);
#if defined(OS_WIN)
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
platform_handle.value = reinterpret_cast<uint64_t>(handle.Take());
#elif defined(OS_FUCHSIA)
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE;
platform_handle.value = static_cast<uint64_t>(handle.release());
#elif defined(OS_MACOSX) && !defined(OS_IOS)
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
platform_handle.value = static_cast<uint64_t>(handle.release());
#elif defined(OS_ANDROID)
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
platform_handle.value = static_cast<uint64_t>(handle.release());
#else
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
platform_handle.value = static_cast<uint64_t>(handle.fd.release());
#endif
const auto& guid = region.GetGUID();
MojoSharedBufferGuid mojo_guid = {guid.GetHighForSerialization(),
guid.GetLowForSerialization()};
MojoHandle mojo_handle;
MojoResult result = MojoWrapPlatformSharedBufferHandle(
&platform_handle, region.GetSize(), &mojo_guid,
region.GetMode() ==
base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly
? MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY
: MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE,
&mojo_handle);
if (result != MOJO_RESULT_OK)
return ScopedSharedBufferHandle();
return ScopedSharedBufferHandle(SharedBufferHandle(mojo_handle));
}
base::subtle::PlatformSharedMemoryRegion UnwrapPlatformSharedMemoryRegion(
ScopedSharedBufferHandle mojo_handle) {
if (!mojo_handle.is_valid())
return base::subtle::PlatformSharedMemoryRegion();
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(platform_handle);
size_t size;
MojoSharedBufferGuid mojo_guid;
MojoPlatformSharedBufferHandleFlags flags;
MojoResult result = MojoUnwrapPlatformSharedBufferHandle(
mojo_handle.release().value(), &platform_handle, &size, &mojo_guid,
&flags);
if (result != MOJO_RESULT_OK)
return base::subtle::PlatformSharedMemoryRegion();
base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle region_handle;
#if defined(OS_WIN)
if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE)
return base::subtle::PlatformSharedMemoryRegion();
region_handle.Set(reinterpret_cast<HANDLE>(platform_handle.value));
#elif defined(OS_FUCHSIA)
if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE)
return base::subtle::PlatformSharedMemoryRegion();
region_handle.reset(static_cast<zx_handle_t>(platform_handle.value));
#elif defined(OS_MACOSX) && !defined(OS_IOS)
if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT)
return base::subtle::PlatformSharedMemoryRegion();
region_handle.reset(static_cast<mach_port_t>(platform_handle.value));
#elif defined(OS_ANDROID)
if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
return base::subtle::PlatformSharedMemoryRegion();
region_handle.reset(static_cast<int>(platform_handle.value));
#else
if (platform_handle.type != MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR)
return base::subtle::PlatformSharedMemoryRegion();
region_handle.fd.reset(static_cast<int>(platform_handle.value));
#endif
// TODO(https://crbug.com/826213): Support unwrapping writable regions. See
// comment in |WrapPlatformSharedMemoryRegion()| above.
base::subtle::PlatformSharedMemoryRegion::Mode mode =
flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY
? base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly
: base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe;
return base::subtle::PlatformSharedMemoryRegion::Take(
std::move(region_handle), mode, size,
base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low));
}
} // namespace
ScopedHandle WrapPlatformFile(base::PlatformFile platform_file) {
......@@ -81,9 +181,22 @@ ScopedSharedBufferHandle WrapSharedMemoryHandle(
MojoPlatformSharedBufferHandleFlags flags =
MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
if (protection == UnwrappedSharedMemoryHandleProtection::kReadOnly)
if (protection == UnwrappedSharedMemoryHandleProtection::kReadOnly) {
flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY;
#if defined(OS_ANDROID)
// Many callers assume that base::SharedMemory::GetReadOnlyHandle() gives
// them a handle which is actually read-only. This assumption is invalid on
// Android. As a precursor to migrating all base::SharedMemory usage --
// including Mojo internals -- to the new base shared memory API, we ensure
// that regions are set to read-only if any of their handles are wrapped
// read-only. This relies on existing usages not attempting to map the
// region writable any time after this call.
if (!memory_handle.IsRegionReadOnly())
memory_handle.SetRegionReadOnly();
#endif
}
MojoSharedBufferGuid guid;
guid.high = memory_handle.GetGUID().GetHighForSerialization();
guid.low = memory_handle.GetGUID().GetLowForSerialization();
......@@ -148,6 +261,48 @@ MojoResult UnwrapSharedMemoryHandle(
return MOJO_RESULT_OK;
}
ScopedSharedBufferHandle WrapReadOnlySharedMemoryRegion(
base::ReadOnlySharedMemoryRegion region) {
return WrapPlatformSharedMemoryRegion(
base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
std::move(region)));
}
ScopedSharedBufferHandle WrapUnsafeSharedMemoryRegion(
base::UnsafeSharedMemoryRegion region) {
return WrapPlatformSharedMemoryRegion(
base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
std::move(region)));
}
ScopedSharedBufferHandle WrapWritableSharedMemoryRegion(
base::WritableSharedMemoryRegion region) {
// TODO(https://crbug.com/826213): Support wrapping writable regions. See
// comment in |WrapPlatformSharedMemoryRegion()| above.
NOTIMPLEMENTED();
return ScopedSharedBufferHandle();
}
base::ReadOnlySharedMemoryRegion UnwrapReadOnlySharedMemoryRegion(
ScopedSharedBufferHandle handle) {
return base::ReadOnlySharedMemoryRegion::Deserialize(
UnwrapPlatformSharedMemoryRegion(std::move(handle)));
}
base::UnsafeSharedMemoryRegion UnwrapUnsafeSharedMemoryRegion(
ScopedSharedBufferHandle handle) {
return base::UnsafeSharedMemoryRegion::Deserialize(
UnwrapPlatformSharedMemoryRegion(std::move(handle)));
}
base::WritableSharedMemoryRegion UnwrapWritableSharedMemoryRegion(
ScopedSharedBufferHandle handle) {
// TODO(https://crbug.com/826213): Support unwrapping writable regions. See
// comment in |WrapPlatformSharedMemoryRegion()| above.
NOTIMPLEMENTED();
return base::WritableSharedMemoryRegion();
}
#if defined(OS_MACOSX) && !defined(OS_IOS)
ScopedHandle WrapMachPort(mach_port_t port) {
kern_return_t kr =
......
......@@ -17,7 +17,10 @@
#include "base/files/file.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/shared_memory_handle.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/memory/writable_shared_memory_region.h"
#include "base/process/process_handle.h"
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/cpp/system/buffer.h"
......@@ -120,6 +123,26 @@ UnwrapSharedMemoryHandle(ScopedSharedBufferHandle handle,
size_t* size,
UnwrappedSharedMemoryHandleProtection* protection);
// Helpers for wrapping and unwrapping new base shared memory API primitives.
MOJO_CPP_SYSTEM_EXPORT ScopedSharedBufferHandle
WrapReadOnlySharedMemoryRegion(base::ReadOnlySharedMemoryRegion region);
MOJO_CPP_SYSTEM_EXPORT ScopedSharedBufferHandle
WrapUnsafeSharedMemoryRegion(base::UnsafeSharedMemoryRegion region);
MOJO_CPP_SYSTEM_EXPORT ScopedSharedBufferHandle
WrapWritableSharedMemoryRegion(base::WritableSharedMemoryRegion region);
MOJO_CPP_SYSTEM_EXPORT base::ReadOnlySharedMemoryRegion
UnwrapReadOnlySharedMemoryRegion(ScopedSharedBufferHandle handle);
MOJO_CPP_SYSTEM_EXPORT base::UnsafeSharedMemoryRegion
UnwrapUnsafeSharedMemoryRegion(ScopedSharedBufferHandle handle);
MOJO_CPP_SYSTEM_EXPORT base::WritableSharedMemoryRegion
UnwrapWritableSharedMemoryRegion(ScopedSharedBufferHandle handle);
#if defined(OS_MACOSX) && !defined(OS_IOS)
// Wraps a mach_port_t as a Mojo handle. This takes a reference to the
// Mach port.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment