ppapi: Add SHARED_MEMORY_REGION type to SerializedHandle
This CL adds a new SHARED_MEMORY_REGION type to the SerializedHandle. This new
type is backed up by the base::subtle::PlatformSharedMemoryRegion class that
provides a new recommended API for the shared memory in Chrome.
Eventually, all uses of the SHARED_MEMORY type should be converted to the
SHARED_MEMORY_REGION.
Bug: 845985
Change-Id: Icfb4605dadb6f111efe953d8b940cc879fa40763
Reviewed-on: https://chromium-review.googlesource.com/1076334
Reviewed-by: Ken Rockot <[email protected]>
Reviewed-by: Bill Budge <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: Derek Schuff <[email protected]>
Commit-Queue: Alexandr Ilin <[email protected]>
Cr-Commit-Position: refs/heads/master@{#563500}
diff --git a/components/nacl/loader/nacl_ipc_adapter.cc b/components/nacl/loader/nacl_ipc_adapter.cc
index 4727192..4c884f9 100644
--- a/components/nacl/loader/nacl_ipc_adapter.cc
+++ b/components/nacl/loader/nacl_ipc_adapter.cc
@@ -254,6 +254,25 @@
#endif
}
+std::unique_ptr<NaClDescWrapper> MakeShmRegionNaClDesc(
+ base::subtle::PlatformSharedMemoryRegion region) {
+ // Writable regions are not supported in NaCl.
+ DCHECK_NE(region.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
+ size_t size = region.GetSize();
+ base::subtle::PlatformSharedMemoryRegion::ScopedPlatformHandle handle =
+ region.PassPlatformHandle();
+ return std::make_unique<NaClDescWrapper>(
+#if defined(OS_MACOSX)
+ NaClDescImcShmMachMake(handle.release(),
+#elif defined(OS_WIN)
+ NaClDescImcShmMake(handle.Take(),
+#else
+ NaClDescImcShmMake(handle.fd.release(),
+#endif
+ size));
+}
+
} // namespace
class NaClIPCAdapter::RewrittenMessage {
@@ -556,24 +575,26 @@
// Now add any descriptors we found to rewritten_msg. |handles| is usually
// empty, unless we read a message containing a FD or handle.
- for (Handles::const_iterator iter = handles.begin();
- iter != handles.end();
- ++iter) {
+ for (ppapi::proxy::SerializedHandle& handle : handles) {
std::unique_ptr<NaClDescWrapper> nacl_desc;
- switch (iter->type()) {
+ switch (handle.type()) {
case ppapi::proxy::SerializedHandle::SHARED_MEMORY: {
- nacl_desc =
- MakeShmNaClDesc(iter->shmem(), static_cast<size_t>(iter->size()));
+ nacl_desc = MakeShmNaClDesc(handle.shmem(),
+ static_cast<size_t>(handle.size()));
+ break;
+ }
+ case ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION: {
+ nacl_desc = MakeShmRegionNaClDesc(handle.TakeSharedMemoryRegion());
break;
}
case ppapi::proxy::SerializedHandle::SOCKET: {
nacl_desc.reset(new NaClDescWrapper(NaClDescSyncSocketMake(
#if defined(OS_WIN)
- iter->descriptor().GetHandle()
+ handle.descriptor().GetHandle()
#else
- iter->descriptor().fd
+ handle.descriptor().fd
#endif
- )));
+ )));
break;
}
case ppapi::proxy::SerializedHandle::FILE: {
@@ -581,15 +602,14 @@
// required, wrap it in a NaClDescQuota.
NaClDesc* desc = NaClDescIoMakeFromHandle(
#if defined(OS_WIN)
- iter->descriptor().GetHandle(),
+ handle.descriptor().GetHandle(),
#else
- iter->descriptor().fd,
+ handle.descriptor().fd,
#endif
- TranslatePepperFileReadWriteOpenFlags(iter->open_flags()));
- if (desc && iter->file_io()) {
+ TranslatePepperFileReadWriteOpenFlags(handle.open_flags()));
+ if (desc && handle.file_io()) {
desc = MakeNaClDescQuota(
- locked_data_.nacl_msg_scanner_.GetFile(iter->file_io()),
- desc);
+ locked_data_.nacl_msg_scanner_.GetFile(handle.file_io()), desc);
}
if (desc)
nacl_desc.reset(new NaClDescWrapper(desc));
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc
index 5618b5c..208080d 100644
--- a/ipc/ipc_message_utils.cc
+++ b/ipc/ipc_message_utils.cc
@@ -876,6 +876,8 @@
void ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Write(
base::Pickle* m,
const param_type& p) {
+ // This serialization must be kept in sync with
+ // nacl_message_scanner.cc::WriteHandle().
const bool valid = p.IsValid();
WriteParam(m, valid);
@@ -1259,8 +1261,6 @@
const param_type& p) {
DCHECK(!p.is_empty());
- // This serialization must be kept in sync with
- // nacl_message_scanner.cc:WriteHandle().
ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization());
ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization());
}
diff --git a/ppapi/proxy/nacl_message_scanner.cc b/ppapi/proxy/nacl_message_scanner.cc
index b6f04d6..4fae6974 100644
--- a/ppapi/proxy/nacl_message_scanner.cc
+++ b/ppapi/proxy/nacl_message_scanner.cc
@@ -62,17 +62,32 @@
if (handle.type() == SerializedHandle::SHARED_MEMORY) {
// Now write the handle itself in POSIX style.
// This serialization must be kept in sync with
- // ParamTraits<SharedMemoryHandle>::Write and
- // ParamTraits<UnguessableToken>::Write.
+ // ParamTraits<SharedMemoryHandle>::Write.
if (handle.shmem().IsValid()) {
msg->WriteBool(true); // valid == true
msg->WriteInt(handle_index);
- msg->WriteUInt64(handle.shmem().GetGUID().GetHighForSerialization());
- msg->WriteUInt64(handle.shmem().GetGUID().GetLowForSerialization());
+ IPC::WriteParam(msg, handle.shmem().GetGUID());
msg->WriteUInt64(handle.shmem().GetSize());
} else {
msg->WriteBool(false); // valid == false
}
+ } else if (handle.type() == SerializedHandle::SHARED_MEMORY_REGION) {
+ // Write the region in POSIX style.
+ // This serialization must be kept in sync with
+ // ParamTraits<PlatformSharedMemoryRegion>::Write.
+ const auto& region = handle.shmem_region();
+ if (region.IsValid()) {
+ IPC::WriteParam(msg, true); // valid == true
+ IPC::WriteParam(msg, region.GetMode());
+ IPC::WriteParam(msg, static_cast<uint64_t>(region.GetSize()));
+ IPC::WriteParam(msg, region.GetGUID());
+ // Writable regions are not supported, so write only one handle index.
+ DCHECK_NE(region.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
+ IPC::WriteParam(msg, handle_index);
+ } else {
+ msg->WriteBool(false); // valid == false
+ }
} else if (handle.type() != SerializedHandle::INVALID) {
// Now write the handle itself in POSIX style.
// This serialization must be kept in sync with
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
index 822c61f..b663e82 100644
--- a/ppapi/proxy/ppapi_param_traits.cc
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -238,6 +238,9 @@
case ppapi::proxy::SerializedHandle::SHARED_MEMORY:
WriteParam(m, p.shmem());
break;
+ case ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION:
+ WriteParam(m, const_cast<param_type&>(p).TakeSharedMemoryRegion());
+ break;
case ppapi::proxy::SerializedHandle::SOCKET:
case ppapi::proxy::SerializedHandle::FILE:
WriteParam(m, p.descriptor());
@@ -259,33 +262,37 @@
switch (header.type) {
case ppapi::proxy::SerializedHandle::SHARED_MEMORY: {
base::SharedMemoryHandle handle;
- if (ReadParam(m, iter, &handle)) {
- r->set_shmem(handle, header.size);
- return true;
- }
+ if (!ReadParam(m, iter, &handle))
+ return false;
+ r->set_shmem(handle, header.size);
+ break;
+ }
+ case ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION: {
+ base::subtle::PlatformSharedMemoryRegion region;
+ if (!ReadParam(m, iter, ®ion))
+ return false;
+ r->set_shmem_region(std::move(region));
break;
}
case ppapi::proxy::SerializedHandle::SOCKET: {
IPC::PlatformFileForTransit socket;
- if (ReadParam(m, iter, &socket)) {
- r->set_socket(socket);
- return true;
- }
+ if (!ReadParam(m, iter, &socket))
+ return false;
+ r->set_socket(socket);
break;
}
case ppapi::proxy::SerializedHandle::FILE: {
IPC::PlatformFileForTransit desc;
- if (ReadParam(m, iter, &desc)) {
- r->set_file_handle(desc, header.open_flags, header.file_io);
- return true;
- }
+ if (!ReadParam(m, iter, &desc))
+ return false;
+ r->set_file_handle(desc, header.open_flags, header.file_io);
break;
}
case ppapi::proxy::SerializedHandle::INVALID:
- return true;
- // No default so the compiler will warn us if a new type is added.
+ break;
+ // No default so the compiler will warn us if a new type is added.
}
- return false;
+ return true;
}
// static
diff --git a/ppapi/proxy/serialized_handle.cc b/ppapi/proxy/serialized_handle.cc
index 13811b5..92f945d 100644
--- a/ppapi/proxy/serialized_handle.cc
+++ b/ppapi/proxy/serialized_handle.cc
@@ -29,6 +29,7 @@
: type_(other.type_),
shm_handle_(other.shm_handle_),
size_(other.size_),
+ shm_region_(std::move(other.shm_region_)),
descriptor_(other.descriptor_),
open_flags_(other.open_flags_),
file_io_(other.file_io_) {
@@ -40,6 +41,7 @@
type_ = other.type_;
shm_handle_ = other.shm_handle_;
size_ = other.size_;
+ shm_region_ = std::move(other.shm_region_);
descriptor_ = other.descriptor_;
open_flags_ = other.open_flags_;
file_io_ = other.file_io_;
@@ -65,6 +67,19 @@
file_io_(0) {}
SerializedHandle::SerializedHandle(
+ base::subtle::PlatformSharedMemoryRegion region)
+ : type_(SHARED_MEMORY_REGION),
+ size_(0),
+ shm_region_(std::move(region)),
+ descriptor_(IPC::InvalidPlatformFileForTransit()),
+ open_flags_(0),
+ file_io_(0) {
+ // Writable regions are not supported.
+ DCHECK_NE(shm_region_.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
+}
+
+SerializedHandle::SerializedHandle(
Type type,
const IPC::PlatformFileForTransit& socket_descriptor)
: type_(type),
@@ -78,6 +93,8 @@
switch (type_) {
case SHARED_MEMORY:
return base::SharedMemory::IsHandleValid(shm_handle_);
+ case SHARED_MEMORY_REGION:
+ return shm_region_.IsValid();
case SOCKET:
case FILE:
return !(IPC::InvalidPlatformFileForTransit() == descriptor_);
@@ -97,6 +114,9 @@
case SHARED_MEMORY:
base::SharedMemory::CloseHandle(shm_handle_);
break;
+ case SHARED_MEMORY_REGION:
+ shm_region_ = base::subtle::PlatformSharedMemoryRegion();
+ break;
case SOCKET:
case FILE:
base::File file_closer = IPC::PlatformFileForTransitToFile(descriptor_);
@@ -144,6 +164,7 @@
valid_type = true;
break;
}
+ case SHARED_MEMORY_REGION:
case SOCKET:
case INVALID:
valid_type = true;
diff --git a/ppapi/proxy/serialized_handle.h b/ppapi/proxy/serialized_handle.h
index cc1c6b4..c82008a3 100644
--- a/ppapi/proxy/serialized_handle.h
+++ b/ppapi/proxy/serialized_handle.h
@@ -12,6 +12,7 @@
#include "base/atomicops.h"
#include "base/logging.h"
+#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "build/build_config.h"
@@ -32,7 +33,9 @@
// NaClIPCAdapter for use in NaCl.
class PPAPI_PROXY_EXPORT SerializedHandle {
public:
- enum Type { INVALID, SHARED_MEMORY, SOCKET, FILE };
+ // TODO(https://crbug.com/845985): Remove SHARED_MEMORY type after all clients
+ // will be converted to the SHARED_MEMORY_REGION.
+ enum Type { INVALID, SHARED_MEMORY, SHARED_MEMORY_REGION, SOCKET, FILE };
// Header contains the fields that we send in IPC messages, apart from the
// actual handle. See comments on the SerializedHandle fields below.
struct Header {
@@ -62,12 +65,16 @@
// Create a shared memory handle.
SerializedHandle(const base::SharedMemoryHandle& handle, uint32_t size);
+ // Create a shared memory region handle.
+ explicit SerializedHandle(base::subtle::PlatformSharedMemoryRegion region);
+
// Create a socket or file handle.
SerializedHandle(const Type type,
const IPC::PlatformFileForTransit& descriptor);
Type type() const { return type_; }
bool is_shmem() const { return type_ == SHARED_MEMORY; }
+ bool is_shmem_region() const { return type_ == SHARED_MEMORY_REGION; }
bool is_socket() const { return type_ == SOCKET; }
bool is_file() const { return type_ == FILE; }
const base::SharedMemoryHandle& shmem() const {
@@ -78,6 +85,14 @@
DCHECK(is_shmem());
return size_;
}
+ const base::subtle::PlatformSharedMemoryRegion& shmem_region() const {
+ DCHECK(is_shmem_region());
+ return shm_region_;
+ }
+ base::subtle::PlatformSharedMemoryRegion TakeSharedMemoryRegion() {
+ DCHECK(is_shmem_region());
+ return std::move(shm_region_);
+ }
const IPC::PlatformFileForTransit& descriptor() const {
DCHECK(is_socket() || is_file());
return descriptor_;
@@ -92,11 +107,24 @@
size_ = size;
descriptor_ = IPC::InvalidPlatformFileForTransit();
+ shm_region_ = base::subtle::PlatformSharedMemoryRegion();
+ }
+ void set_shmem_region(base::subtle::PlatformSharedMemoryRegion region) {
+ type_ = SHARED_MEMORY_REGION;
+ shm_region_ = std::move(region);
+ // Writable regions are not supported.
+ DCHECK_NE(shm_region_.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
+
+ descriptor_ = IPC::InvalidPlatformFileForTransit();
+ shm_handle_ = base::SharedMemoryHandle();
+ size_ = 0;
}
void set_socket(const IPC::PlatformFileForTransit& socket) {
type_ = SOCKET;
descriptor_ = socket;
+ shm_region_ = base::subtle::PlatformSharedMemoryRegion();
shm_handle_ = base::SharedMemoryHandle();
size_ = 0;
}
@@ -106,6 +134,7 @@
type_ = FILE;
descriptor_ = descriptor;
+ shm_region_ = base::subtle::PlatformSharedMemoryRegion();
shm_handle_ = base::SharedMemoryHandle();
size_ = 0;
open_flags_ = open_flags;
@@ -115,6 +144,7 @@
type_ = INVALID;
shm_handle_ = base::SharedMemoryHandle();
+ shm_region_ = base::subtle::PlatformSharedMemoryRegion();
size_ = 0;
descriptor_ = IPC::InvalidPlatformFileForTransit();
}
@@ -152,6 +182,9 @@
base::SharedMemoryHandle shm_handle_;
uint32_t size_;
+ // This is valid if type == SHARED_MEMORY_REGION.
+ base::subtle::PlatformSharedMemoryRegion shm_region_;
+
// This is valid if type == SOCKET || type == FILE.
IPC::PlatformFileForTransit descriptor_;