summaryrefslogtreecommitdiff
path: root/chromium/mojo/edk/system
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-24 12:15:48 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:30:04 +0000
commitb014812705fc80bff0a5c120dfcef88f349816dc (patch)
tree25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/mojo/edk/system
parent9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff)
downloadqtwebengine-chromium-b014812705fc80bff0a5c120dfcef88f349816dc.tar.gz
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/mojo/edk/system')
-rw-r--r--chromium/mojo/edk/system/BUILD.gn1
-rw-r--r--chromium/mojo/edk/system/broker.h14
-rw-r--r--chromium/mojo/edk/system/broker_host.cc61
-rw-r--r--chromium/mojo/edk/system/broker_host.h23
-rw-r--r--chromium/mojo/edk/system/broker_posix.cc56
-rw-r--r--chromium/mojo/edk/system/broker_win.cc40
-rw-r--r--chromium/mojo/edk/system/channel.cc54
-rw-r--r--chromium/mojo/edk/system/channel.h32
-rw-r--r--chromium/mojo/edk/system/channel_fuchsia.cc63
-rw-r--r--chromium/mojo/edk/system/channel_posix.cc59
-rw-r--r--chromium/mojo/edk/system/channel_unittest.cc22
-rw-r--r--chromium/mojo/edk/system/channel_win.cc32
-rw-r--r--chromium/mojo/edk/system/core.cc849
-rw-r--r--chromium/mojo/edk/system/core.h137
-rw-r--r--chromium/mojo/edk/system/core_test_base.cc17
-rw-r--r--chromium/mojo/edk/system/core_unittest.cc147
-rw-r--r--chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc128
-rw-r--r--chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h36
-rw-r--r--chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc107
-rw-r--r--chromium/mojo/edk/system/data_pipe_producer_dispatcher.h33
-rw-r--r--chromium/mojo/edk/system/data_pipe_unittest.cc293
-rw-r--r--chromium/mojo/edk/system/dispatcher.cc41
-rw-r--r--chromium/mojo/edk/system/dispatcher.h64
-rw-r--r--chromium/mojo/edk/system/handle_table.cc2
-rw-r--r--chromium/mojo/edk/system/invitation_dispatcher.cc78
-rw-r--r--chromium/mojo/edk/system/invitation_dispatcher.h50
-rw-r--r--chromium/mojo/edk/system/invitation_unittest.cc610
-rw-r--r--chromium/mojo/edk/system/mach_port_relay.cc27
-rw-r--r--chromium/mojo/edk/system/mach_port_relay.h13
-rw-r--r--chromium/mojo/edk/system/mapping_table.cc49
-rw-r--r--chromium/mojo/edk/system/mapping_table.h51
-rw-r--r--chromium/mojo/edk/system/message_pipe_dispatcher.cc12
-rw-r--r--chromium/mojo/edk/system/message_pipe_dispatcher.h19
-rw-r--r--chromium/mojo/edk/system/message_pipe_unittest.cc26
-rw-r--r--chromium/mojo/edk/system/message_unittest.cc72
-rw-r--r--chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc62
-rw-r--r--chromium/mojo/edk/system/node_channel.cc118
-rw-r--r--chromium/mojo/edk/system/node_channel.h44
-rw-r--r--chromium/mojo/edk/system/node_controller.cc105
-rw-r--r--chromium/mojo/edk/system/node_controller.h23
-rw-r--r--chromium/mojo/edk/system/platform_handle_dispatcher.cc18
-rw-r--r--chromium/mojo/edk/system/platform_handle_dispatcher.h12
-rw-r--r--chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc19
-rw-r--r--chromium/mojo/edk/system/platform_shared_memory_mapping.cc104
-rw-r--r--chromium/mojo/edk/system/platform_shared_memory_mapping.h60
-rw-r--r--chromium/mojo/edk/system/platform_wrapper_unittest.cc93
-rw-r--r--chromium/mojo/edk/system/scoped_process_handle.cc45
-rw-r--r--chromium/mojo/edk/system/scoped_process_handle.h81
-rw-r--r--chromium/mojo/edk/system/shared_buffer_dispatcher.cc257
-rw-r--r--chromium/mojo/edk/system/shared_buffer_dispatcher.h44
-rw-r--r--chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc135
-rw-r--r--chromium/mojo/edk/system/shared_buffer_unittest.cc32
-rw-r--r--chromium/mojo/edk/system/signals_unittest.cc2
-rw-r--r--chromium/mojo/edk/system/trap_unittest.cc12
-rw-r--r--chromium/mojo/edk/system/user_message_impl.cc6
55 files changed, 2986 insertions, 1604 deletions
diff --git a/chromium/mojo/edk/system/BUILD.gn b/chromium/mojo/edk/system/BUILD.gn
index 6387dcda11b..235f32e31e1 100644
--- a/chromium/mojo/edk/system/BUILD.gn
+++ b/chromium/mojo/edk/system/BUILD.gn
@@ -52,6 +52,7 @@ source_set("test_sources") {
if (!is_ios) {
sources += [
"data_pipe_unittest.cc",
+ "invitation_unittest.cc",
"multiprocess_message_pipe_unittest.cc",
"platform_wrapper_unittest.cc",
]
diff --git a/chromium/mojo/edk/system/broker.h b/chromium/mojo/edk/system/broker.h
index 8fb61aa9b83..6961f641e0c 100644
--- a/chromium/mojo/edk/system/broker.h
+++ b/chromium/mojo/edk/system/broker.h
@@ -7,38 +7,38 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/writable_shared_memory_region.h"
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
namespace mojo {
namespace edk {
-class PlatformSharedBuffer;
-
// The Broker is a channel to the broker process, which allows synchronous IPCs
// to fulfill shared memory allocation requests on some platforms.
class Broker {
public:
// Note: This is blocking, and will wait for the first message over
// |platform_handle|.
- explicit Broker(ScopedPlatformHandle platform_handle);
+ explicit Broker(ScopedInternalPlatformHandle platform_handle);
~Broker();
// Returns the platform handle that should be used to establish a NodeChannel
// to the process which is inviting us to join its network. This is the first
// handle read off the Broker channel upon construction.
- ScopedPlatformHandle GetInviterPlatformHandle();
+ ScopedInternalPlatformHandle GetInviterInternalPlatformHandle();
// Request a shared buffer from the broker process. Blocks the current thread.
- scoped_refptr<PlatformSharedBuffer> GetSharedBuffer(size_t num_bytes);
+ base::WritableSharedMemoryRegion GetWritableSharedMemoryRegion(
+ size_t num_bytes);
private:
// Handle to the broker process, used for synchronous IPCs.
- ScopedPlatformHandle sync_channel_;
+ ScopedInternalPlatformHandle sync_channel_;
// Handle to the inviter process which is recieved in the first first message
// over |sync_channel_|.
- ScopedPlatformHandle inviter_channel_;
+ ScopedInternalPlatformHandle inviter_channel_;
// Lock to only allow one sync message at a time. This avoids having to deal
// with message ordering since we can only have one request at a time
diff --git a/chromium/mojo/edk/system/broker_host.cc b/chromium/mojo/edk/system/broker_host.cc
index 8076383d1b6..8966e239654 100644
--- a/chromium/mojo/edk/system/broker_host.cc
+++ b/chromium/mojo/edk/system/broker_host.cc
@@ -7,12 +7,13 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "mojo/edk/embedder/named_platform_channel_pair.h"
#include "mojo/edk/embedder/named_platform_handle.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/broker_messages.h"
@@ -20,17 +21,17 @@ namespace mojo {
namespace edk {
BrokerHost::BrokerHost(base::ProcessHandle client_process,
- ScopedPlatformHandle platform_handle,
+ ScopedInternalPlatformHandle platform_handle,
const ProcessErrorCallback& process_error_callback)
: process_error_callback_(process_error_callback)
#if defined(OS_WIN)
,
- client_process_(client_process)
+ client_process_(ScopedProcessHandle::CloneFrom(client_process))
#endif
{
CHECK(platform_handle.is_valid());
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
channel_ = Channel::Create(
this,
@@ -41,17 +42,17 @@ BrokerHost::BrokerHost(base::ProcessHandle client_process,
BrokerHost::~BrokerHost() {
// We're always destroyed on the creation thread, which is the IO thread.
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
if (channel_)
channel_->ShutDown();
}
bool BrokerHost::PrepareHandlesForClient(
- std::vector<ScopedPlatformHandle>* handles) {
+ std::vector<ScopedInternalPlatformHandle>* handles) {
#if defined(OS_WIN)
if (!Channel::Message::RewriteHandles(base::GetCurrentProcessHandle(),
- client_process_, handles)) {
+ client_process_.get(), handles)) {
// NOTE: We only log an error here. We do not signal a logical error or
// prevent any message from being sent. The client should handle unexpected
// invalid handles appropriately.
@@ -62,7 +63,7 @@ bool BrokerHost::PrepareHandlesForClient(
return true;
}
-bool BrokerHost::SendChannel(ScopedPlatformHandle handle) {
+bool BrokerHost::SendChannel(ScopedInternalPlatformHandle handle) {
CHECK(handle.is_valid());
CHECK(channel_);
@@ -75,7 +76,7 @@ bool BrokerHost::SendChannel(ScopedPlatformHandle handle) {
Channel::MessagePtr message =
CreateBrokerMessage(BrokerMessageType::INIT, 1, nullptr);
#endif
- std::vector<ScopedPlatformHandle> handles(1);
+ std::vector<ScopedInternalPlatformHandle> handles(1);
handles[0] = std::move(handle);
// This may legitimately fail on Windows if the client process is in another
@@ -104,24 +105,31 @@ void BrokerHost::SendNamedChannel(const base::StringPiece16& pipe_name) {
#endif // defined(OS_WIN)
void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
- scoped_refptr<PlatformSharedBuffer> read_only_buffer;
- scoped_refptr<PlatformSharedBuffer> buffer =
- PlatformSharedBuffer::Create(num_bytes);
- if (buffer)
- read_only_buffer = buffer->CreateReadOnlyDuplicate();
- if (!read_only_buffer)
- buffer = nullptr;
+ base::subtle::PlatformSharedMemoryRegion region =
+ base::subtle::PlatformSharedMemoryRegion::CreateWritable(num_bytes);
+
+ std::vector<ScopedInternalPlatformHandle> handles(2);
+ if (region.IsValid()) {
+ ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &handles[0], &handles[1]);
+#if !defined(OS_POSIX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) || \
+ (defined(OS_MACOSX) && !defined(OS_IOS))
+ // Non-POSIX systems, as well as Android, Fuchsia, and non-iOS Mac, only use
+ // a single handle to represent a writable region.
+ DCHECK(!handles[1].is_valid());
+ handles.resize(1);
+#else
+ DCHECK(handles[1].is_valid());
+#endif
+ }
BufferResponseData* response;
Channel::MessagePtr message = CreateBrokerMessage(
- BrokerMessageType::BUFFER_RESPONSE, buffer ? 2 : 0, 0, &response);
- if (buffer) {
- base::UnguessableToken guid = buffer->GetGUID();
+ BrokerMessageType::BUFFER_RESPONSE, handles.size(), 0, &response);
+ if (!handles.empty()) {
+ base::UnguessableToken guid = region.GetGUID();
response->guid_high = guid.GetHighForSerialization();
response->guid_low = guid.GetLowForSerialization();
- std::vector<ScopedPlatformHandle> handles(2);
- handles[0] = buffer->PassPlatformHandle();
- handles[1] = read_only_buffer->PassPlatformHandle();
PrepareHandlesForClient(&handles);
message->SetHandles(std::move(handles));
}
@@ -129,9 +137,10 @@ void BrokerHost::OnBufferRequest(uint32_t num_bytes) {
channel_->Write(std::move(message));
}
-void BrokerHost::OnChannelMessage(const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) {
+void BrokerHost::OnChannelMessage(
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) {
if (payload_size < sizeof(BrokerMessageHeader))
return;
diff --git a/chromium/mojo/edk/system/broker_host.h b/chromium/mojo/edk/system/broker_host.h
index 3f1b7ce1bef..1681bdca6c2 100644
--- a/chromium/mojo/edk/system/broker_host.h
+++ b/chromium/mojo/edk/system/broker_host.h
@@ -9,12 +9,13 @@
#include <vector>
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/process/process_handle.h"
#include "base/strings/string_piece.h"
#include "mojo/edk/embedder/process_error_callback.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
+#include "mojo/edk/system/scoped_process_handle.h"
namespace mojo {
namespace edk {
@@ -22,14 +23,14 @@ namespace edk {
// The BrokerHost is a channel to a broker client process, servicing synchronous
// IPCs issued by the client.
class BrokerHost : public Channel::Delegate,
- public base::MessageLoop::DestructionObserver {
+ public base::MessageLoopCurrent::DestructionObserver {
public:
BrokerHost(base::ProcessHandle client_process,
- ScopedPlatformHandle handle,
+ ScopedInternalPlatformHandle handle,
const ProcessErrorCallback& process_error_callback);
// Send |handle| to the client, to be used to establish a NodeChannel to us.
- bool SendChannel(ScopedPlatformHandle handle);
+ bool SendChannel(ScopedInternalPlatformHandle handle);
#if defined(OS_WIN)
// Sends a named channel to the client. Like above, but for named pipes.
@@ -39,15 +40,17 @@ class BrokerHost : public Channel::Delegate,
private:
~BrokerHost() override;
- bool PrepareHandlesForClient(std::vector<ScopedPlatformHandle>* handles);
+ bool PrepareHandlesForClient(
+ std::vector<ScopedInternalPlatformHandle>* handles);
// Channel::Delegate:
- void OnChannelMessage(const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) override;
+ void OnChannelMessage(
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) override;
void OnChannelError(Channel::Error error) override;
- // base::MessageLoop::DestructionObserver:
+ // base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override;
void OnBufferRequest(uint32_t num_bytes);
@@ -55,7 +58,7 @@ class BrokerHost : public Channel::Delegate,
const ProcessErrorCallback process_error_callback_;
#if defined(OS_WIN)
- base::ProcessHandle client_process_;
+ ScopedProcessHandle client_process_;
#endif
scoped_refptr<Channel> channel_;
diff --git a/chromium/mojo/edk/system/broker_posix.cc b/chromium/mojo/edk/system/broker_posix.cc
index 88695e9b646..4b5c15c0fbc 100644
--- a/chromium/mojo/edk/system/broker_posix.cc
+++ b/chromium/mojo/edk/system/broker_posix.cc
@@ -10,9 +10,10 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/platform_shared_memory_region.h"
+#include "build/build_config.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_handle_utils.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/broker_messages.h"
#include "mojo/edk/system/channel.h"
@@ -23,14 +24,14 @@ namespace edk {
namespace {
Channel::MessagePtr WaitForBrokerMessage(
- const ScopedPlatformHandle& platform_handle,
+ const ScopedInternalPlatformHandle& platform_handle,
BrokerMessageType expected_type,
size_t expected_num_handles,
size_t expected_data_size,
- std::vector<ScopedPlatformHandle>* incoming_handles) {
+ std::vector<ScopedInternalPlatformHandle>* incoming_handles) {
Channel::MessagePtr message(new Channel::Message(
sizeof(BrokerMessageHeader) + expected_data_size, expected_num_handles));
- base::circular_deque<ScopedPlatformHandle> incoming_platform_handles;
+ base::circular_deque<ScopedInternalPlatformHandle> incoming_platform_handles;
ssize_t read_result = PlatformChannelRecvmsg(
platform_handle, const_cast<void*>(message->data()),
message->data_num_bytes(), &incoming_platform_handles, true /* block */);
@@ -65,7 +66,7 @@ Channel::MessagePtr WaitForBrokerMessage(
} // namespace
-Broker::Broker(ScopedPlatformHandle platform_handle)
+Broker::Broker(ScopedInternalPlatformHandle platform_handle)
: sync_channel_(std::move(platform_handle)) {
CHECK(sync_channel_.is_valid());
@@ -76,7 +77,7 @@ Broker::Broker(ScopedPlatformHandle platform_handle)
PCHECK(flags != -1);
// Wait for the first message, which should contain a handle.
- std::vector<ScopedPlatformHandle> incoming_platform_handles;
+ std::vector<ScopedInternalPlatformHandle> incoming_platform_handles;
if (WaitForBrokerMessage(sync_channel_, BrokerMessageType::INIT, 1, 0,
&incoming_platform_handles)) {
inviter_channel_ = std::move(incoming_platform_handles[0]);
@@ -85,11 +86,12 @@ Broker::Broker(ScopedPlatformHandle platform_handle)
Broker::~Broker() = default;
-ScopedPlatformHandle Broker::GetInviterPlatformHandle() {
+ScopedInternalPlatformHandle Broker::GetInviterInternalPlatformHandle() {
return std::move(inviter_channel_);
}
-scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
+base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
+ size_t num_bytes) {
base::AutoLock lock(lock_);
BufferRequestData* buffer_request;
@@ -100,29 +102,45 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
sync_channel_, out_message->data(), out_message->data_num_bytes());
if (write_result < 0) {
PLOG(ERROR) << "Error sending sync broker message";
- return nullptr;
+ return base::WritableSharedMemoryRegion();
} else if (static_cast<size_t>(write_result) !=
out_message->data_num_bytes()) {
LOG(ERROR) << "Error sending complete broker message";
- return nullptr;
+ return base::WritableSharedMemoryRegion();
}
- std::vector<ScopedPlatformHandle> incoming_platform_handles;
+#if !defined(OS_POSIX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) || \
+ (defined(OS_MACOSX) && !defined(OS_IOS))
+ // Non-POSIX systems, as well as Android, Fuchsia, and non-iOS Mac, only use
+ // a single handle to represent a writable region.
+ constexpr size_t kNumExpectedHandles = 1;
+#else
+ constexpr size_t kNumExpectedHandles = 2;
+#endif
+
+ std::vector<ScopedInternalPlatformHandle> incoming_platform_handles;
Channel::MessagePtr message = WaitForBrokerMessage(
- sync_channel_, BrokerMessageType::BUFFER_RESPONSE, 2,
+ sync_channel_, BrokerMessageType::BUFFER_RESPONSE, kNumExpectedHandles,
sizeof(BufferResponseData), &incoming_platform_handles);
if (message) {
const BufferResponseData* data;
if (!GetBrokerMessageData(message.get(), &data))
- return nullptr;
- base::UnguessableToken guid =
- base::UnguessableToken::Deserialize(data->guid_high, data->guid_low);
- return PlatformSharedBuffer::CreateFromPlatformHandlePair(
- num_bytes, guid, std::move(incoming_platform_handles[0]),
- std::move(incoming_platform_handles[1]));
+ return base::WritableSharedMemoryRegion();
+
+ if (incoming_platform_handles.size() == 1)
+ incoming_platform_handles.emplace_back();
+ return base::WritableSharedMemoryRegion::Deserialize(
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ std::move(incoming_platform_handles[0]),
+ std::move(incoming_platform_handles[1])),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
+ num_bytes,
+ base::UnguessableToken::Deserialize(data->guid_high,
+ data->guid_low)));
}
- return nullptr;
+ return base::WritableSharedMemoryRegion();
}
} // namespace edk
diff --git a/chromium/mojo/edk/system/broker_win.cc b/chromium/mojo/edk/system/broker_win.cc
index 0d489649797..a2dea366c0c 100644
--- a/chromium/mojo/edk/system/broker_win.cc
+++ b/chromium/mojo/edk/system/broker_win.cc
@@ -8,12 +8,13 @@
#include <utility>
#include "base/debug/alias.h"
+#include "base/memory/platform_shared_memory_region.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/named_platform_handle_utils.h"
#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/broker.h"
#include "mojo/edk/system/broker_messages.h"
@@ -29,13 +30,13 @@ const size_t kMaxBrokerMessageSize = 256;
bool TakeHandlesFromBrokerMessage(Channel::Message* message,
size_t num_handles,
- ScopedPlatformHandle* out_handles) {
+ ScopedInternalPlatformHandle* out_handles) {
if (message->num_handles() != num_handles) {
DLOG(ERROR) << "Received unexpected number of handles in broker message";
return false;
}
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
DCHECK_EQ(handles.size(), num_handles);
DCHECK(out_handles);
@@ -44,7 +45,7 @@ bool TakeHandlesFromBrokerMessage(Channel::Message* message,
return true;
}
-Channel::MessagePtr WaitForBrokerMessage(PlatformHandle platform_handle,
+Channel::MessagePtr WaitForBrokerMessage(InternalPlatformHandle platform_handle,
BrokerMessageType expected_type) {
char buffer[kMaxBrokerMessageSize];
DWORD bytes_read = 0;
@@ -85,7 +86,8 @@ Channel::MessagePtr WaitForBrokerMessage(PlatformHandle platform_handle,
} // namespace
-Broker::Broker(ScopedPlatformHandle handle) : sync_channel_(std::move(handle)) {
+Broker::Broker(ScopedInternalPlatformHandle handle)
+ : sync_channel_(std::move(handle)) {
CHECK(sync_channel_.is_valid());
Channel::MessagePtr message =
WaitForBrokerMessage(sync_channel_.get(), BrokerMessageType::INIT);
@@ -115,11 +117,12 @@ Broker::Broker(ScopedPlatformHandle handle) : sync_channel_(std::move(handle)) {
Broker::~Broker() {}
-ScopedPlatformHandle Broker::GetInviterPlatformHandle() {
+ScopedInternalPlatformHandle Broker::GetInviterInternalPlatformHandle() {
return std::move(inviter_channel_);
}
-scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
+base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
+ size_t num_bytes) {
base::AutoLock lock(lock_);
BufferRequestData* buffer_request;
Channel::MessagePtr out_message = CreateBrokerMessage(
@@ -132,24 +135,27 @@ scoped_refptr<PlatformSharedBuffer> Broker::GetSharedBuffer(size_t num_bytes) {
if (!result ||
static_cast<size_t>(bytes_written) != out_message->data_num_bytes()) {
PLOG(ERROR) << "Error sending sync broker message";
- return nullptr;
+ return base::WritableSharedMemoryRegion();
}
- ScopedPlatformHandle handles[2];
+ ScopedInternalPlatformHandle handle;
Channel::MessagePtr response = WaitForBrokerMessage(
sync_channel_.get(), BrokerMessageType::BUFFER_RESPONSE);
- if (response &&
- TakeHandlesFromBrokerMessage(response.get(), 2, &handles[0])) {
+ if (response && TakeHandlesFromBrokerMessage(response.get(), 1, &handle)) {
BufferResponseData* data;
if (!GetBrokerMessageData(response.get(), &data))
- return nullptr;
- base::UnguessableToken guid =
- base::UnguessableToken::Deserialize(data->guid_high, data->guid_low);
- return PlatformSharedBuffer::CreateFromPlatformHandlePair(
- num_bytes, guid, std::move(handles[0]), std::move(handles[1]));
+ return base::WritableSharedMemoryRegion();
+ return base::WritableSharedMemoryRegion::Deserialize(
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ std::move(handle), ScopedInternalPlatformHandle()),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
+ num_bytes,
+ base::UnguessableToken::Deserialize(data->guid_high,
+ data->guid_low)));
}
- return nullptr;
+ return base::WritableSharedMemoryRegion();
}
} // namespace edk
diff --git a/chromium/mojo/edk/system/channel.cc b/chromium/mojo/edk/system/channel.cc
index 41ff3ee3509..0005193ca3d 100644
--- a/chromium/mojo/edk/system/channel.cc
+++ b/chromium/mojo/edk/system/channel.cc
@@ -250,10 +250,10 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data,
}
#if defined(OS_WIN)
- std::vector<ScopedPlatformHandle> handles(num_handles);
+ std::vector<ScopedInternalPlatformHandle> handles(num_handles);
for (size_t i = 0; i < num_handles; i++) {
- handles[i] = ScopedPlatformHandle(
- PlatformHandle(base::win::Uint32ToHandle(message->handles_[i].handle)));
+ handles[i] = ScopedInternalPlatformHandle(InternalPlatformHandle(
+ base::win::Uint32ToHandle(message->handles_[i].handle)));
}
message->SetHandles(std::move(handles));
#endif
@@ -343,8 +343,8 @@ bool Channel::Message::has_mach_ports() const {
return false;
for (const auto& handle : handle_vector_) {
- if (handle.get().type == PlatformHandle::Type::MACH ||
- handle.get().type == PlatformHandle::Type::MACH_NAME) {
+ if (handle.get().type == InternalPlatformHandle::Type::MACH ||
+ handle.get().type == InternalPlatformHandle::Type::MACH_NAME) {
return true;
}
}
@@ -366,7 +366,7 @@ Channel::Message::Header* Channel::Message::header() const {
}
void Channel::Message::SetHandles(
- std::vector<ScopedPlatformHandle> new_handles) {
+ std::vector<ScopedInternalPlatformHandle> new_handles) {
if (is_legacy_message()) {
// Old semantics for ChromeOS and Android
if (legacy_header()->num_handles == 0) {
@@ -401,8 +401,9 @@ void Channel::Message::SetHandles(
{0, static_cast<uint32_t>(MACH_PORT_NULL)};
}
for (size_t i = 0; i < handle_vector_.size(); i++) {
- if (handle_vector_[i].get().type == PlatformHandle::Type::MACH ||
- handle_vector_[i].get().type == PlatformHandle::Type::MACH_NAME) {
+ if (handle_vector_[i].get().type == InternalPlatformHandle::Type::MACH ||
+ handle_vector_[i].get().type ==
+ InternalPlatformHandle::Type::MACH_NAME) {
mach_port_t port = handle_vector_[i].get().port;
mach_ports_header_->entries[mach_port_index].index = i;
mach_ports_header_->entries[mach_port_index].mach_port = port;
@@ -414,7 +415,7 @@ void Channel::Message::SetHandles(
#endif
}
-std::vector<ScopedPlatformHandle> Channel::Message::TakeHandles() {
+std::vector<ScopedInternalPlatformHandle> Channel::Message::TakeHandles() {
#if defined(OS_MACOSX) && !defined(OS_IOS)
if (mach_ports_header_) {
for (size_t i = 0; i < max_handles_; ++i) {
@@ -431,15 +432,16 @@ std::vector<ScopedPlatformHandle> Channel::Message::TakeHandles() {
return std::move(handle_vector_);
}
-std::vector<ScopedPlatformHandle> Channel::Message::TakeHandlesForTransport() {
+std::vector<ScopedInternalPlatformHandle>
+Channel::Message::TakeHandlesForTransport() {
#if defined(OS_WIN)
// Not necessary on Windows.
NOTREACHED();
- return std::vector<ScopedPlatformHandle>();
+ return std::vector<ScopedInternalPlatformHandle>();
#elif defined(OS_MACOSX) && !defined(OS_IOS)
for (auto it = handle_vector_.begin(); it != handle_vector_.end();) {
- if (it->get().type == PlatformHandle::Type::MACH ||
- it->get().type == PlatformHandle::Type::MACH_NAME) {
+ if (it->get().type == InternalPlatformHandle::Type::MACH ||
+ it->get().type == InternalPlatformHandle::Type::MACH_NAME) {
// For Mach port names, we can can just leak them. They're not real
// ports anyways. For real ports, they're leaked because this is a child
// process and the remote process will take ownership.
@@ -463,7 +465,7 @@ std::vector<ScopedPlatformHandle> Channel::Message::TakeHandlesForTransport() {
bool Channel::Message::RewriteHandles(
base::ProcessHandle from_process,
base::ProcessHandle to_process,
- std::vector<ScopedPlatformHandle>* handles) {
+ std::vector<ScopedInternalPlatformHandle>* handles) {
bool success = true;
for (size_t i = 0; i < handles->size(); ++i) {
if (!(*handles)[i].is_valid()) {
@@ -476,7 +478,14 @@ bool Channel::Message::RewriteHandles(
&(*handles)[i].get().handle, 0, FALSE,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
if (result) {
- (*handles)[i].get().owning_process = to_process;
+ if (to_process == base::GetCurrentProcessHandle()) {
+ (*handles)[i].get().owning_process = to_process;
+ } else {
+ // If this handle is bound for an external process, make sure it owns
+ // its own copy of the target process handle.
+ (*handles)[i].get().owning_process =
+ ScopedProcessHandle::CloneFrom(to_process).release();
+ }
} else {
success = false;
@@ -699,10 +708,10 @@ bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) {
const uint16_t num_handles =
header ? header->num_handles : legacy_header->num_handles;
- std::vector<ScopedPlatformHandle> handles;
+ std::vector<ScopedInternalPlatformHandle> handles;
if (num_handles > 0) {
- if (!GetReadPlatformHandles(num_handles, extra_header, extra_header_size,
- &handles)) {
+ if (!GetReadInternalPlatformHandles(num_handles, extra_header,
+ extra_header_size, &handles)) {
return false;
}
@@ -737,10 +746,11 @@ void Channel::OnError(Error error) {
delegate_->OnChannelError(error);
}
-bool Channel::OnControlMessage(Message::MessageType message_type,
- const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) {
+bool Channel::OnControlMessage(
+ Message::MessageType message_type,
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) {
return false;
}
diff --git a/chromium/mojo/edk/system/channel.h b/chromium/mojo/edk/system/channel.h
index 57c8ed81ec6..ef9669cc39a 100644
--- a/chromium/mojo/edk/system/channel.h
+++ b/chromium/mojo/edk/system/channel.h
@@ -88,7 +88,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
#if defined(OS_MACOSX) && !defined(OS_IOS)
struct MachPortsEntry {
- // Index of Mach port in the original vector of PlatformHandles.
+ // Index of Mach port in the original vector of InternalPlatformHandles.
uint16_t index;
// Mach port name.
@@ -179,13 +179,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Note: SetHandles() and TakeHandles() invalidate any previous value of
// handles().
- void SetHandles(std::vector<ScopedPlatformHandle> new_handles);
- std::vector<ScopedPlatformHandle> TakeHandles();
+ void SetHandles(std::vector<ScopedInternalPlatformHandle> new_handles);
+ std::vector<ScopedInternalPlatformHandle> TakeHandles();
// Version of TakeHandles that returns a vector of platform handles suitable
// for transfer over an underlying OS mechanism. i.e. file descriptors over
// a unix domain socket. Any handle that cannot be transferred this way,
// such as Mach ports, will be removed.
- std::vector<ScopedPlatformHandle> TakeHandlesForTransport();
+ std::vector<ScopedInternalPlatformHandle> TakeHandlesForTransport();
#if defined(OS_WIN)
// Prepares the handles in this message for use in a different process.
@@ -193,9 +193,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// call they'll belong to |to_process|. The source handles are always
// closed by this call. Returns false iff one or more handles failed
// duplication.
- static bool RewriteHandles(base::ProcessHandle from_process,
- base::ProcessHandle to_process,
- std::vector<ScopedPlatformHandle>* handles);
+ static bool RewriteHandles(
+ base::ProcessHandle from_process,
+ base::ProcessHandle to_process,
+ std::vector<ScopedInternalPlatformHandle>* handles);
#endif
void SetVersionForTest(uint16_t version_number);
@@ -215,7 +216,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// Maximum number of handles which may be attached to this message.
size_t max_handles_ = 0;
- std::vector<ScopedPlatformHandle> handle_vector_;
+ std::vector<ScopedInternalPlatformHandle> handle_vector_;
#if defined(OS_WIN)
// On Windows, handles are serialised into the extra header section.
@@ -255,7 +256,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
virtual void OnChannelMessage(
const void* payload,
size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) = 0;
+ std::vector<ScopedInternalPlatformHandle> handles) = 0;
// Notify that an error has occured and the Channel will cease operation.
virtual void OnChannelError(Error error) = 0;
@@ -326,18 +327,19 @@ class MOJO_SYSTEM_IMPL_EXPORT Channel
// insufficient number of handles to be available when this call is made, but
// this is not necessarily an error condition. In such cases this returns
// |true| but |*handles| will also be reset to null.
- virtual bool GetReadPlatformHandles(
+ virtual bool GetReadInternalPlatformHandles(
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
- std::vector<ScopedPlatformHandle>* handles) = 0;
+ std::vector<ScopedInternalPlatformHandle>* handles) = 0;
// Handles a received control message. Returns |true| if the message is
// accepted, or |false| otherwise.
- virtual bool OnControlMessage(Message::MessageType message_type,
- const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles);
+ virtual bool OnControlMessage(
+ Message::MessageType message_type,
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles);
private:
friend class base::RefCountedThreadSafe<Channel>;
diff --git a/chromium/mojo/edk/system/channel_fuchsia.cc b/chromium/mojo/edk/system/channel_fuchsia.cc
index 31ddb9486c1..364792cc32b 100644
--- a/chromium/mojo/edk/system/channel_fuchsia.cc
+++ b/chromium/mojo/edk/system/channel_fuchsia.cc
@@ -19,7 +19,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
@@ -31,9 +31,10 @@ namespace {
const size_t kMaxBatchReadCapacity = 256 * 1024;
-bool UnwrapPlatformHandle(ScopedPlatformHandle handle,
- Channel::Message::HandleInfoEntry* info_out,
- std::vector<ScopedPlatformHandle>* handles_out) {
+bool UnwrapInternalPlatformHandle(
+ ScopedInternalPlatformHandle handle,
+ Channel::Message::HandleInfoEntry* info_out,
+ std::vector<ScopedInternalPlatformHandle>* handles_out) {
DCHECK(handle.get().is_valid());
if (!handle.get().is_valid_fd()) {
@@ -53,8 +54,8 @@ bool UnwrapPlatformHandle(ScopedPlatformHandle handle,
zx_status_t result = fdio_transfer_fd(handle.get().as_fd(), 0, handles, info);
if (result > 0) {
// On success, the fd in |handle| has been transferred and is no longer
- // valid. Release from the ScopedPlatformHandle to avoid close()ing an
- // invalid handle.
+ // valid. Release from the ScopedInternalPlatformHandle to avoid close()ing
+ // an invalid handle.
ignore_result(handle.release());
} else if (result == ZX_ERR_UNAVAILABLE) {
// No luck, try cloning instead.
@@ -74,22 +75,23 @@ bool UnwrapPlatformHandle(ScopedPlatformHandle handle,
for (int i = 0; i < result; ++i) {
DCHECK_EQ(PA_HND_TYPE(info[0]), PA_HND_TYPE(info[i]));
DCHECK_EQ(0u, PA_HND_SUBTYPE(info[i]));
- handles_out->emplace_back(PlatformHandle::ForHandle(handles[i]));
+ handles_out->emplace_back(InternalPlatformHandle::ForHandle(handles[i]));
}
return true;
}
-ScopedPlatformHandle WrapPlatformHandles(
+ScopedInternalPlatformHandle WrapInternalPlatformHandles(
Channel::Message::HandleInfoEntry info,
base::circular_deque<base::ScopedZxHandle>* handles) {
- ScopedPlatformHandle out_handle;
+ ScopedInternalPlatformHandle out_handle;
if (!info.type) {
- out_handle.reset(PlatformHandle::ForHandle(handles->front().release()));
+ out_handle.reset(
+ InternalPlatformHandle::ForHandle(handles->front().release()));
handles->pop_front();
} else {
if (info.count > FDIO_MAX_HANDLES)
- return ScopedPlatformHandle();
+ return ScopedInternalPlatformHandle();
// Fetch the required number of handles from |handles| and set up type info.
zx_handle_t fd_handles[FDIO_MAX_HANDLES] = {};
@@ -105,7 +107,7 @@ ScopedPlatformHandle WrapPlatformHandles(
fdio_create_fd(fd_handles, fd_infos, info.count, out_fd.receive());
if (result != ZX_OK) {
DLOG(ERROR) << "fdio_create_fd: " << zx_status_get_string(result);
- return ScopedPlatformHandle();
+ return ScopedInternalPlatformHandle();
}
// The handles are owned by FDIO now, so |release()| them before removing
@@ -115,7 +117,7 @@ ScopedPlatformHandle WrapPlatformHandles(
handles->pop_front();
}
- out_handle.reset(PlatformHandle::ForFd(out_fd.release()));
+ out_handle.reset(InternalPlatformHandle::ForFd(out_fd.release()));
}
return out_handle;
}
@@ -155,9 +157,9 @@ class MessageView {
offset_ += num_bytes;
}
- std::vector<ScopedPlatformHandle> TakeHandles() {
+ std::vector<ScopedInternalPlatformHandle> TakeHandles() {
if (handles_.empty())
- return std::vector<ScopedPlatformHandle>();
+ return std::vector<ScopedInternalPlatformHandle>();
// We can only pass Fuchsia handles via IPC, so unwrap any FDIO file-
// descriptors in |handles_| into the underlying handles, and serialize the
@@ -166,12 +168,12 @@ class MessageView {
message_->mutable_extra_header());
memset(handles_info, 0, message_->extra_header_size());
- std::vector<ScopedPlatformHandle> in_handles = std::move(handles_);
+ std::vector<ScopedInternalPlatformHandle> in_handles = std::move(handles_);
handles_.reserve(in_handles.size());
for (size_t i = 0; i < in_handles.size(); i++) {
- if (!UnwrapPlatformHandle(std::move(in_handles[i]), &handles_info[i],
- &handles_))
- return std::vector<ScopedPlatformHandle>();
+ if (!UnwrapInternalPlatformHandle(std::move(in_handles[i]),
+ &handles_info[i], &handles_))
+ return std::vector<ScopedInternalPlatformHandle>();
}
return std::move(handles_);
}
@@ -179,13 +181,13 @@ class MessageView {
private:
Channel::MessagePtr message_;
size_t offset_;
- std::vector<ScopedPlatformHandle> handles_;
+ std::vector<ScopedInternalPlatformHandle> handles_;
DISALLOW_COPY_AND_ASSIGN(MessageView);
};
class ChannelFuchsia : public Channel,
- public base::MessageLoop::DestructionObserver,
+ public base::MessageLoopCurrent::DestructionObserver,
public base::MessagePumpForIO::ZxHandleWatcher {
public:
ChannelFuchsia(Delegate* delegate,
@@ -236,11 +238,11 @@ class ChannelFuchsia : public Channel,
leak_handle_ = true;
}
- bool GetReadPlatformHandles(
+ bool GetReadInternalPlatformHandles(
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
- std::vector<ScopedPlatformHandle>* handles) override {
+ std::vector<ScopedInternalPlatformHandle>* handles) override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
@@ -271,7 +273,8 @@ class ChannelFuchsia : public Channel,
handles->reserve(num_handles);
for (size_t i = 0; i < num_handles; ++i) {
handles->emplace_back(
- WrapPlatformHandles(handles_info[i], &incoming_handles_).release());
+ WrapInternalPlatformHandles(handles_info[i], &incoming_handles_)
+ .release());
}
return true;
}
@@ -284,17 +287,17 @@ class ChannelFuchsia : public Channel,
void StartOnIOThread() {
DCHECK(!read_watch_);
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
read_watch_.reset(
new base::MessagePumpForIO::ZxHandleWatchController(FROM_HERE));
- base::MessageLoopForIO::current()->WatchZxHandle(
+ base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
handle_.get().as_handle(), true /* persistent */,
ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, read_watch_.get(), this);
}
void ShutDownOnIOThread() {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
read_watch_.reset();
if (leak_handle_)
@@ -305,7 +308,7 @@ class ChannelFuchsia : public Channel,
self_ = nullptr;
}
- // base::MessageLoop::DestructionObserver:
+ // base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (self_)
@@ -378,7 +381,7 @@ class ChannelFuchsia : public Channel,
do {
message_view.advance_data_offset(write_bytes);
- std::vector<ScopedPlatformHandle> outgoing_handles =
+ std::vector<ScopedInternalPlatformHandle> outgoing_handles =
message_view.TakeHandles();
zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES] = {};
size_t handles_count = outgoing_handles.size();
@@ -433,7 +436,7 @@ class ChannelFuchsia : public Channel,
// Keeps the Channel alive at least until explicit shutdown on the IO thread.
scoped_refptr<Channel> self_;
- ScopedPlatformHandle handle_;
+ ScopedInternalPlatformHandle handle_;
scoped_refptr<base::TaskRunner> io_task_runner_;
// These members are only used on the IO thread.
diff --git a/chromium/mojo/edk/system/channel_posix.cc b/chromium/mojo/edk/system/channel_posix.cc
index 998fe5d6716..42d78d533f1 100644
--- a/chromium/mojo/edk/system/channel_posix.cc
+++ b/chromium/mojo/edk/system/channel_posix.cc
@@ -16,7 +16,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
@@ -69,25 +69,25 @@ class MessageView {
offset_ += num_bytes;
}
- std::vector<ScopedPlatformHandle> TakeHandles() {
+ std::vector<ScopedInternalPlatformHandle> TakeHandles() {
return std::move(handles_);
}
Channel::MessagePtr TakeMessage() { return std::move(message_); }
- void SetHandles(std::vector<ScopedPlatformHandle> handles) {
+ void SetHandles(std::vector<ScopedInternalPlatformHandle> handles) {
handles_ = std::move(handles);
}
private:
Channel::MessagePtr message_;
size_t offset_;
- std::vector<ScopedPlatformHandle> handles_;
+ std::vector<ScopedInternalPlatformHandle> handles_;
DISALLOW_COPY_AND_ASSIGN(MessageView);
};
class ChannelPosix : public Channel,
- public base::MessageLoop::DestructionObserver,
+ public base::MessageLoopCurrent::DestructionObserver,
public base::MessagePumpForIO::FdWatcher {
public:
ChannelPosix(Delegate* delegate,
@@ -143,11 +143,11 @@ class ChannelPosix : public Channel,
leak_handle_ = true;
}
- bool GetReadPlatformHandles(
+ bool GetReadInternalPlatformHandles(
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
- std::vector<ScopedPlatformHandle>* handles) override {
+ std::vector<ScopedInternalPlatformHandle>* handles) override {
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
#if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -172,12 +172,13 @@ class ChannelPosix : public Channel,
for (size_t i = 0, mach_port_index = 0; i < num_handles; ++i) {
if (mach_port_index < num_mach_ports &&
mach_ports[mach_port_index].index == i) {
- handles->at(i).reset(PlatformHandle(
+ handles->at(i).reset(InternalPlatformHandle(
static_cast<mach_port_t>(mach_ports[mach_port_index].mach_port)));
- DCHECK_EQ(handles->at(i).get().type, PlatformHandle::Type::MACH);
+ DCHECK_EQ(handles->at(i).get().type,
+ InternalPlatformHandle::Type::MACH);
// These are actually just Mach port names until they're resolved from
// the remote process.
- handles->at(i).get().type = PlatformHandle::Type::MACH_NAME;
+ handles->at(i).get().type = InternalPlatformHandle::Type::MACH_NAME;
mach_port_index++;
} else {
if (incoming_platform_handles_.empty())
@@ -211,15 +212,15 @@ class ChannelPosix : public Channel,
DCHECK(!write_watcher_);
read_watcher_.reset(
new base::MessagePumpForIO::FdWatchController(FROM_HERE));
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
if (handle_.get().needs_connection) {
- base::MessageLoopForIO::current()->WatchFileDescriptor(
+ base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
handle_.get().handle, false /* persistent */,
base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
} else {
write_watcher_.reset(
new base::MessagePumpForIO::FdWatchController(FROM_HERE));
- base::MessageLoopForIO::current()->WatchFileDescriptor(
+ base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
handle_.get().handle, true /* persistent */,
base::MessagePumpForIO::WATCH_READ, read_watcher_.get(), this);
base::AutoLock lock(write_lock_);
@@ -239,7 +240,7 @@ class ChannelPosix : public Channel,
return;
if (io_task_runner_->RunsTasksInCurrentSequence()) {
pending_write_ = true;
- base::MessageLoopForIO::current()->WatchFileDescriptor(
+ base::MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
handle_.get().handle, false /* persistent */,
base::MessagePumpForIO::WATCH_WRITE, write_watcher_.get(), this);
} else {
@@ -250,7 +251,7 @@ class ChannelPosix : public Channel,
}
void ShutDownOnIOThread() {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
read_watcher_.reset();
write_watcher_.reset();
@@ -265,7 +266,7 @@ class ChannelPosix : public Channel,
self_ = nullptr;
}
- // base::MessageLoop::DestructionObserver:
+ // base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (self_)
@@ -278,9 +279,9 @@ class ChannelPosix : public Channel,
if (handle_.get().needs_connection) {
#if !defined(OS_NACL)
read_watcher_.reset();
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
- ScopedPlatformHandle accept_fd;
+ ScopedInternalPlatformHandle accept_fd;
ServerAcceptConnection(handle_, &accept_fd);
if (!accept_fd.is_valid()) {
OnError(Error::kConnectionFailed);
@@ -358,7 +359,8 @@ class ChannelPosix : public Channel,
message_view.advance_data_offset(bytes_written);
ssize_t result;
- std::vector<ScopedPlatformHandle> handles = message_view.TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles =
+ message_view.TakeHandles();
if (!handles.empty()) {
iovec iov = {const_cast<void*>(message_view.data()),
message_view.data_num_bytes()};
@@ -457,10 +459,11 @@ class ChannelPosix : public Channel,
}
#if defined(OS_MACOSX)
- bool OnControlMessage(Message::MessageType message_type,
- const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) override {
+ bool OnControlMessage(
+ Message::MessageType message_type,
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) override {
switch (message_type) {
case Message::MessageType::HANDLES_SENT: {
if (payload_size == 0)
@@ -499,7 +502,7 @@ class ChannelPosix : public Channel,
auto start =
std::find_if(handles_to_close_.begin(), handles_to_close_.end(),
- [&fds](const ScopedPlatformHandle& handle) {
+ [&fds](const ScopedInternalPlatformHandle& handle) {
return handle.get().handle == fds[0];
});
if (start == handles_to_close_.end())
@@ -520,7 +523,7 @@ class ChannelPosix : public Channel,
if (i != num_fds)
return false;
- // Close the FDs by erase()ing their ScopedPlatformHandles.
+ // Close the FDs by erase()ing their ScopedInternalPlatformHandles.
handles_to_close_.erase(start, it);
return true;
}
@@ -546,14 +549,14 @@ class ChannelPosix : public Channel,
// Keeps the Channel alive at least until explicit shutdown on the IO thread.
scoped_refptr<Channel> self_;
- ScopedPlatformHandle handle_;
+ ScopedInternalPlatformHandle handle_;
scoped_refptr<base::TaskRunner> io_task_runner_;
// These watchers must only be accessed on the IO thread.
std::unique_ptr<base::MessagePumpForIO::FdWatchController> read_watcher_;
std::unique_ptr<base::MessagePumpForIO::FdWatchController> write_watcher_;
- base::circular_deque<ScopedPlatformHandle> incoming_platform_handles_;
+ base::circular_deque<ScopedInternalPlatformHandle> incoming_platform_handles_;
// Protects |pending_write_| and |outgoing_messages_|.
base::Lock write_lock_;
@@ -565,7 +568,7 @@ class ChannelPosix : public Channel,
#if defined(OS_MACOSX)
base::Lock handles_to_close_lock_;
- std::vector<ScopedPlatformHandle> handles_to_close_;
+ std::vector<ScopedInternalPlatformHandle> handles_to_close_;
#endif
DISALLOW_COPY_AND_ASSIGN(ChannelPosix);
diff --git a/chromium/mojo/edk/system/channel_unittest.cc b/chromium/mojo/edk/system/channel_unittest.cc
index de6aa850640..90ff9b3728f 100644
--- a/chromium/mojo/edk/system/channel_unittest.cc
+++ b/chromium/mojo/edk/system/channel_unittest.cc
@@ -28,16 +28,16 @@ class TestChannel : public Channel {
return OnReadComplete(bytes_read, next_read_size_hint);
}
- MOCK_METHOD4(GetReadPlatformHandles,
+ MOCK_METHOD4(GetReadInternalPlatformHandles,
bool(size_t num_handles,
const void* extra_header,
size_t extra_header_size,
- std::vector<ScopedPlatformHandle>* handles));
+ std::vector<ScopedInternalPlatformHandle>* handles));
MOCK_METHOD0(Start, void());
MOCK_METHOD0(ShutDownImpl, void());
MOCK_METHOD0(LeakHandle, void());
- void Write(MessagePtr message) {}
+ void Write(MessagePtr message) override {}
protected:
~TestChannel() override {}
@@ -53,9 +53,10 @@ class MockChannelDelegate : public Channel::Delegate {
const void* GetReceivedPayload() const { return payload_.get(); }
protected:
- void OnChannelMessage(const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) override {
+ void OnChannelMessage(
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) override {
payload_.reset(new char[payload_size]);
memcpy(payload_.get(), payload, payload_size);
payload_size_ = payload_size;
@@ -180,7 +181,7 @@ TEST(ChannelTest, OnReadNonLegacyMessage) {
class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate {
public:
ChannelTestShutdownAndWriteDelegate(
- ScopedPlatformHandle handle,
+ ScopedInternalPlatformHandle handle,
scoped_refptr<base::TaskRunner> task_runner,
scoped_refptr<Channel> client_channel,
std::unique_ptr<base::Thread> client_thread,
@@ -196,9 +197,10 @@ class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate {
~ChannelTestShutdownAndWriteDelegate() override { channel_->ShutDown(); }
// Channel::Delegate implementation
- void OnChannelMessage(const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) override {
+ void OnChannelMessage(
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) override {
++message_count_;
// If |client_channel_| exists then close it and its thread.
diff --git a/chromium/mojo/edk/system/channel_win.cc b/chromium/mojo/edk/system/channel_win.cc
index ff4c8135fc3..123e295f9db 100644
--- a/chromium/mojo/edk/system/channel_win.cc
+++ b/chromium/mojo/edk/system/channel_win.cc
@@ -16,7 +16,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/synchronization/lock.h"
#include "base/task_runner.h"
@@ -29,11 +29,11 @@ namespace edk {
namespace {
class ChannelWin : public Channel,
- public base::MessageLoop::DestructionObserver,
+ public base::MessageLoopCurrent::DestructionObserver,
public base::MessagePumpForIO::IOHandler {
public:
ChannelWin(Delegate* delegate,
- ScopedPlatformHandle handle,
+ ScopedInternalPlatformHandle handle,
scoped_refptr<base::TaskRunner> io_task_runner)
: Channel(delegate),
self_(this),
@@ -79,11 +79,11 @@ class ChannelWin : public Channel,
leak_handle_ = true;
}
- bool GetReadPlatformHandles(
+ bool GetReadInternalPlatformHandles(
size_t num_handles,
const void* extra_header,
size_t extra_header_size,
- std::vector<ScopedPlatformHandle>* handles) override {
+ std::vector<ScopedInternalPlatformHandle>* handles) override {
DCHECK(extra_header);
if (num_handles > std::numeric_limits<uint16_t>::max())
return false;
@@ -95,7 +95,7 @@ class ChannelWin : public Channel,
const HandleEntry* extra_header_handles =
reinterpret_cast<const HandleEntry*>(extra_header);
for (size_t i = 0; i < num_handles; i++) {
- handles->emplace_back(ScopedPlatformHandle(PlatformHandle(
+ handles->emplace_back(ScopedInternalPlatformHandle(InternalPlatformHandle(
base::win::Uint32ToHandle(extra_header_handles[i].handle))));
}
return true;
@@ -106,8 +106,8 @@ class ChannelWin : public Channel,
~ChannelWin() override {}
void StartOnIOThread() {
- base::MessageLoop::current()->AddDestructionObserver(this);
- base::MessageLoopForIO::current()->RegisterIOHandler(
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+ base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(
handle_.get().handle, this);
if (handle_.get().needs_connection) {
@@ -150,7 +150,7 @@ class ChannelWin : public Channel,
}
void ShutDownOnIOThread() {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
// BUG(crbug.com/583525): This function is expected to be called once, and
// |handle_| should be valid at this point.
@@ -164,7 +164,7 @@ class ChannelWin : public Channel,
self_ = nullptr;
}
- // base::MessageLoop::DestructionObserver:
+ // base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (self_)
@@ -235,10 +235,14 @@ class ChannelWin : public Channel,
Channel::MessagePtr message = std::move(outgoing_messages_.front());
outgoing_messages_.pop_front();
- // Clear any handles so they don't get closed on destruction.
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ // Invalidate all the scoped handles so we don't attempt to close them.
+ // Note that we don't simply release these objects because they also own
+ // an internal process handle (in |owning_process|) which *does* need to
+ // be closed.
+ std::vector<ScopedInternalPlatformHandle> handles =
+ message->TakeHandles();
for (auto& handle : handles)
- ignore_result(handle.release());
+ handle.get().handle = INVALID_HANDLE_VALUE;
// Overlapped WriteFile() to a pipe should always fully complete.
if (message->data_num_bytes() != bytes_written)
@@ -311,7 +315,7 @@ class ChannelWin : public Channel,
// Keeps the Channel alive at least until explicit shutdown on the IO thread.
scoped_refptr<Channel> self_;
- ScopedPlatformHandle handle_;
+ ScopedInternalPlatformHandle handle_;
const scoped_refptr<base::TaskRunner> io_task_runner_;
base::MessagePumpForIO::IOContext connect_context_;
diff --git a/chromium/mojo/edk/system/core.cc b/chromium/mojo/edk/system/core.cc
index bf2f95c06b4..58bc403cd50 100644
--- a/chromium/mojo/edk/system/core.cc
+++ b/chromium/mojo/edk/system/core.cc
@@ -6,6 +6,7 @@
#include <string.h>
+#include <algorithm>
#include <utility>
#include "base/bind.h"
@@ -14,21 +15,25 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/memory/writable_shared_memory_region.h"
#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/embedder/process_error_callback.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/data_pipe_consumer_dispatcher.h"
#include "mojo/edk/system/data_pipe_producer_dispatcher.h"
#include "mojo/edk/system/handle_signals_state.h"
+#include "mojo/edk/system/invitation_dispatcher.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/platform_handle_dispatcher.h"
+#include "mojo/edk/system/platform_shared_memory_mapping.h"
#include "mojo/edk/system/ports/event.h"
#include "mojo/edk/system/ports/name.h"
#include "mojo/edk/system/ports/node.h"
@@ -49,96 +54,69 @@ const uint32_t kMaxHandlesPerMessage = 1024 * 1024;
// pipes too; for now we just use a constant. This only affects bootstrap pipes.
const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL;
-MojoResult MojoPlatformHandleToScopedPlatformHandle(
- const MojoPlatformHandle* platform_handle,
- ScopedPlatformHandle* out_handle) {
- if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) {
- out_handle->reset();
- return MOJO_RESULT_OK;
- }
-
- PlatformHandle handle;
- switch (platform_handle->type) {
-#if defined(OS_FUCHSIA)
- case MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE:
- handle = PlatformHandle::ForHandle(platform_handle->value);
- break;
- case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
- handle = PlatformHandle::ForFd(platform_handle->value);
- break;
-
-#elif defined(OS_POSIX)
- case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR:
- handle.handle = static_cast<int>(platform_handle->value);
- break;
-#endif
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT:
- handle.type = PlatformHandle::Type::MACH;
- handle.port = static_cast<mach_port_t>(platform_handle->value);
- break;
-#endif
-
-#if defined(OS_WIN)
- case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE:
- handle.handle = reinterpret_cast<HANDLE>(platform_handle->value);
- break;
-#endif
-
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-
- out_handle->reset(handle);
- return MOJO_RESULT_OK;
-}
-
-MojoResult ScopedPlatformHandleToMojoPlatformHandle(
- ScopedPlatformHandle handle,
- MojoPlatformHandle* platform_handle) {
- if (platform_handle->struct_size != sizeof(MojoPlatformHandle))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- if (!handle.is_valid()) {
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
- return MOJO_RESULT_OK;
- }
-
-#if defined(OS_FUCHSIA)
- if (handle.get().is_valid_fd()) {
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
- platform_handle->value = handle.release().as_fd();
- } else {
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE;
- platform_handle->value = handle.release().as_handle();
+void InvokeProcessErrorCallbackOnTaskRunner(
+ scoped_refptr<base::TaskRunner> task_runner,
+ MojoProcessErrorHandler handler,
+ uintptr_t context,
+ const std::string& error,
+ MojoProcessErrorFlags flags) {
+ // We always run the handler asynchronously to ensure no Mojo core reentrancy.
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](MojoProcessErrorHandler handler, uintptr_t context,
+ const std::string& error, MojoProcessErrorFlags flags) {
+ MojoProcessErrorDetails details;
+ details.struct_size = sizeof(details);
+ DCHECK(base::IsValueInRangeForNumericType<uint32_t>(error.size()));
+ details.error_message_length = static_cast<uint32_t>(error.size());
+ if (!error.empty())
+ details.error_message = error.data();
+ else
+ details.error_message = nullptr;
+ details.flags = flags;
+ handler(context, &details);
+ },
+ handler, context, error, flags));
+}
+
+// Helper class which is bound to the lifetime of a ProcessErrorCallback
+// generated by the |MojoSendInvitation()| API. When the last reference to the
+// error callback is lost within the EDK, which will happen shortly after a
+// connection to the process is lost, that obviously guarantees that no more
+// invocations of the callback will occur. At that point, the corresponding
+// instance of this object (owned by the callback -- see Core::SendInvitation)
+// will be destroyed.
+class ProcessDisconnectHandler {
+ public:
+ ProcessDisconnectHandler(scoped_refptr<base::TaskRunner> task_runner,
+ MojoProcessErrorHandler handler,
+ uintptr_t context)
+ : task_runner_(std::move(task_runner)),
+ handler_(handler),
+ context_(context) {}
+
+ ~ProcessDisconnectHandler() {
+ InvokeProcessErrorCallbackOnTaskRunner(
+ task_runner_, handler_, context_, std::string(),
+ MOJO_PROCESS_ERROR_FLAG_DISCONNECTED);
}
-#elif defined(OS_POSIX)
- switch (handle.get().type) {
- case PlatformHandle::Type::POSIX:
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
- platform_handle->value = static_cast<uint64_t>(handle.release().handle);
- break;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- case PlatformHandle::Type::MACH:
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT;
- platform_handle->value = static_cast<uint64_t>(handle.release().port);
- break;
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+ private:
+ const scoped_refptr<base::TaskRunner> task_runner_;
+ const MojoProcessErrorHandler handler_;
+ const uintptr_t context_;
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-#elif defined(OS_WIN)
- platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE;
- platform_handle->value = reinterpret_cast<uint64_t>(handle.release().handle);
-#endif // defined(OS_WIN)
+ DISALLOW_COPY_AND_ASSIGN(ProcessDisconnectHandler);
+};
- return MOJO_RESULT_OK;
+void RunMojoProcessErrorHandler(ProcessDisconnectHandler* disconnect_handler,
+ scoped_refptr<base::TaskRunner> task_runner,
+ MojoProcessErrorHandler handler,
+ uintptr_t context,
+ const std::string& error) {
+ InvokeProcessErrorCallbackOnTaskRunner(task_runner, handler, context, error,
+ MOJO_PROCESS_ERROR_FLAG_NONE);
}
} // namespace
@@ -180,6 +158,13 @@ scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) {
return handles_->GetDispatcher(handle);
}
+scoped_refptr<Dispatcher> Core::GetAndRemoveDispatcher(MojoHandle handle) {
+ scoped_refptr<Dispatcher> dispatcher;
+ base::AutoLock lock(handles_->GetLock());
+ handles_->GetAndRemoveDispatcher(handle, &dispatcher);
+ return dispatcher;
+}
+
void Core::SetDefaultProcessErrorCallback(
const ProcessErrorCallback& callback) {
default_process_error_callback_ = callback;
@@ -278,8 +263,8 @@ void Core::ReleaseDispatchersForTransit(
handles_->CancelTransit(dispatchers);
}
-MojoResult Core::CreatePlatformHandleWrapper(
- ScopedPlatformHandle platform_handle,
+MojoResult Core::CreateInternalPlatformHandleWrapper(
+ ScopedInternalPlatformHandle platform_handle,
MojoHandle* wrapper_handle) {
MojoHandle h = AddDispatcher(
PlatformHandleDispatcher::Create(std::move(platform_handle)));
@@ -289,9 +274,9 @@ MojoResult Core::CreatePlatformHandleWrapper(
return MOJO_RESULT_OK;
}
-MojoResult Core::PassWrappedPlatformHandle(
+MojoResult Core::PassWrappedInternalPlatformHandle(
MojoHandle wrapper_handle,
- ScopedPlatformHandle* platform_handle) {
+ ScopedInternalPlatformHandle* platform_handle) {
base::AutoLock lock(handles_->GetLock());
scoped_refptr<Dispatcher> d;
MojoResult result = handles_->GetAndRemoveDispatcher(wrapper_handle, &d);
@@ -300,7 +285,7 @@ MojoResult Core::PassWrappedPlatformHandle(
if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) {
PlatformHandleDispatcher* phd =
static_cast<PlatformHandleDispatcher*>(d.get());
- *platform_handle = phd->PassPlatformHandle();
+ *platform_handle = phd->PassInternalPlatformHandle();
} else {
result = MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -308,72 +293,6 @@ MojoResult Core::PassWrappedPlatformHandle(
return result;
}
-MojoResult Core::CreateSharedBufferWrapper(
- base::SharedMemoryHandle shared_memory_handle,
- size_t num_bytes,
- bool read_only,
- MojoHandle* mojo_wrapper_handle) {
- DCHECK(num_bytes);
- scoped_refptr<PlatformSharedBuffer> platform_buffer =
- PlatformSharedBuffer::CreateFromSharedMemoryHandle(num_bytes, read_only,
- shared_memory_handle);
- if (!platform_buffer)
- return MOJO_RESULT_UNKNOWN;
-
- scoped_refptr<SharedBufferDispatcher> dispatcher;
- MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
- platform_buffer, &dispatcher);
- if (result != MOJO_RESULT_OK)
- return result;
- MojoHandle h = AddDispatcher(dispatcher);
- if (h == MOJO_HANDLE_INVALID)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
- *mojo_wrapper_handle = h;
- 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_->GetLock());
- // 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 = platform_shared_buffer->IsReadOnly();
- *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle();
-
- shm_dispatcher->Close();
- return result;
-}
-
void Core::RequestShutdown(const base::Closure& callback) {
GetNodeController()->RequestShutdown(callback);
}
@@ -388,17 +307,6 @@ MojoHandle Core::ExtractMessagePipeFromInvitation(const std::string& name) {
return handle;
}
-MojoResult Core::SetProperty(MojoPropertyType type, const void* value) {
- base::AutoLock locker(property_lock_);
- switch (type) {
- case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
- property_sync_call_allowed_ = *static_cast<const bool*>(value);
- return MOJO_RESULT_OK;
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-}
-
MojoTimeTicks Core::GetTimeTicksNow() {
return base::TimeTicks::Now().ToInternalValue();
}
@@ -641,17 +549,6 @@ MojoResult Core::GetMessageContext(MojoMessageHandle message_handle,
return MOJO_RESULT_OK;
}
-MojoResult Core::GetProperty(MojoPropertyType type, void* value) {
- base::AutoLock locker(property_lock_);
- switch (type) {
- case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED:
- *static_cast<bool*>(value) = property_sync_call_allowed_;
- return MOJO_RESULT_OK;
- default:
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
-}
-
MojoResult Core::CreateMessagePipe(const MojoCreateMessagePipeOptions* options,
MojoHandle* message_pipe_handle0,
MojoHandle* message_pipe_handle1) {
@@ -686,7 +583,7 @@ MojoResult Core::CreateMessagePipe(const MojoCreateMessagePipeOptions* options,
MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
MojoMessageHandle message_handle,
- MojoWriteMessageFlags flags) {
+ const MojoWriteMessageOptions* options) {
RequestContext request_context;
if (!message_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
@@ -698,12 +595,12 @@ MojoResult Core::WriteMessage(MojoHandle message_pipe_handle,
auto dispatcher = GetDispatcher(message_pipe_handle);
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
- return dispatcher->WriteMessage(std::move(message_event), flags);
+ return dispatcher->WriteMessage(std::move(message_event));
}
MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
- MojoMessageHandle* message_handle,
- MojoReadMessageFlags flags) {
+ const MojoReadMessageOptions* options,
+ MojoMessageHandle* message_handle) {
RequestContext request_context;
auto dispatcher = GetDispatcher(message_pipe_handle);
if (!dispatcher || !message_handle)
@@ -719,7 +616,9 @@ MojoResult Core::ReadMessage(MojoHandle message_pipe_handle,
return MOJO_RESULT_OK;
}
-MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) {
+MojoResult Core::FuseMessagePipes(MojoHandle handle0,
+ MojoHandle handle1,
+ const MojoFuseMessagePipesOptions* options) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher0;
scoped_refptr<Dispatcher> dispatcher1;
@@ -758,7 +657,8 @@ MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) {
MojoResult Core::NotifyBadMessage(MojoMessageHandle message_handle,
const char* error,
- size_t error_num_bytes) {
+ size_t error_num_bytes,
+ const MojoNotifyBadMessageOptions* options) {
if (!message_handle)
return MOJO_RESULT_INVALID_ARGUMENT;
@@ -797,10 +697,30 @@ MojoResult Core::CreateDataPipe(const MojoCreateDataPipeOptions* options,
return MOJO_RESULT_INVALID_ARGUMENT;
}
- scoped_refptr<PlatformSharedBuffer> ring_buffer =
- GetNodeController()->CreateSharedBuffer(
- create_options.capacity_num_bytes);
- if (!ring_buffer)
+ base::subtle::PlatformSharedMemoryRegion ring_buffer_region =
+ base::WritableSharedMemoryRegion::TakeHandleForSerialization(
+ GetNodeController()->CreateSharedBuffer(
+ create_options.capacity_num_bytes));
+
+ // NOTE: We demote the writable region to an unsafe region so that the
+ // producer handle can be transferred freely. There is no compelling reason
+ // to restrict access rights of consumers since they are the exclusive
+ // consumer of this pipe, and it would be impossible to support such access
+ // control on Android anyway.
+ auto writable_region_handle = ring_buffer_region.PassPlatformHandle();
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ // This isn't strictly necessary, but it does make the handle configuration
+ // consistent with regular UnsafeSharedMemoryRegions.
+ writable_region_handle.readonly_fd.reset();
+#endif
+ base::UnsafeSharedMemoryRegion producer_region =
+ base::UnsafeSharedMemoryRegion::Deserialize(
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ std::move(writable_region_handle),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ create_options.capacity_num_bytes, ring_buffer_region.GetGUID()));
+ if (!producer_region.IsValid())
return MOJO_RESULT_RESOURCE_EXHAUSTED;
ports::PortRef port0, port1;
@@ -809,14 +729,17 @@ MojoResult Core::CreateDataPipe(const MojoCreateDataPipeOptions* options,
DCHECK(data_pipe_producer_handle);
DCHECK(data_pipe_consumer_handle);
+ base::UnsafeSharedMemoryRegion consumer_region = producer_region.Duplicate();
uint64_t pipe_id = base::RandUint64();
scoped_refptr<Dispatcher> producer = DataPipeProducerDispatcher::Create(
- GetNodeController(), port0, ring_buffer, create_options, pipe_id);
+ GetNodeController(), port0, std::move(producer_region), create_options,
+ pipe_id);
if (!producer)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
scoped_refptr<Dispatcher> consumer = DataPipeConsumerDispatcher::Create(
- GetNodeController(), port1, ring_buffer, create_options, pipe_id);
+ GetNodeController(), port1, std::move(consumer_region), create_options,
+ pipe_id);
if (!consumer) {
producer->Close();
return MOJO_RESULT_RESOURCE_EXHAUSTED;
@@ -842,80 +765,131 @@ MojoResult Core::CreateDataPipe(const MojoCreateDataPipeOptions* options,
MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle,
const void* elements,
uint32_t* num_bytes,
- MojoWriteDataFlags flags) {
+ const MojoWriteDataOptions* options) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher(
GetDispatcher(data_pipe_producer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
- return dispatcher->WriteData(elements, num_bytes, flags);
+ MojoWriteDataOptions validated_options;
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ constexpr MojoWriteDataFlags kSupportedFlags =
+ MOJO_WRITE_DATA_FLAG_NONE | MOJO_WRITE_DATA_FLAG_ALL_OR_NONE;
+ if (options->flags & ~kSupportedFlags)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ validated_options.flags = options->flags;
+ } else {
+ validated_options.flags = MOJO_WRITE_DATA_FLAG_NONE;
+ }
+ return dispatcher->WriteData(elements, num_bytes, validated_options);
}
MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle,
+ const MojoBeginWriteDataOptions* options,
void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags) {
+ uint32_t* buffer_num_bytes) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher(
GetDispatcher(data_pipe_producer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
-
- return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags);
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options->flags != MOJO_BEGIN_WRITE_DATA_FLAG_NONE)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
+ return dispatcher->BeginWriteData(buffer, buffer_num_bytes);
}
MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle,
- uint32_t num_bytes_written) {
+ uint32_t num_bytes_written,
+ const MojoEndWriteDataOptions* options) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher(
GetDispatcher(data_pipe_producer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
-
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options->flags != MOJO_END_WRITE_DATA_FLAG_NONE)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
return dispatcher->EndWriteData(num_bytes_written);
}
MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle,
+ const MojoReadDataOptions* options,
void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags) {
+ uint32_t* num_bytes) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher(
GetDispatcher(data_pipe_consumer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
- return dispatcher->ReadData(elements, num_bytes, flags);
+ MojoReadDataOptions validated_options;
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ constexpr MojoReadDataFlags kSupportedFlags =
+ MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_ALL_OR_NONE |
+ MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_QUERY |
+ MOJO_READ_DATA_FLAG_PEEK;
+ if (options->flags & ~kSupportedFlags)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ validated_options.flags = options->flags;
+ } else {
+ validated_options.flags = MOJO_WRITE_DATA_FLAG_NONE;
+ }
+ return dispatcher->ReadData(validated_options, elements, num_bytes);
}
MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle,
+ const MojoBeginReadDataOptions* options,
const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags) {
+ uint32_t* buffer_num_bytes) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher(
GetDispatcher(data_pipe_consumer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
- return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags);
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options->flags != MOJO_BEGIN_READ_DATA_FLAG_NONE)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
+ return dispatcher->BeginReadData(buffer, buffer_num_bytes);
}
MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle,
- uint32_t num_bytes_read) {
+ uint32_t num_bytes_read,
+ const MojoEndReadDataOptions* options) {
RequestContext request_context;
scoped_refptr<Dispatcher> dispatcher(
GetDispatcher(data_pipe_consumer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
-
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options->flags != MOJO_END_READ_DATA_FLAG_NONE)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
return dispatcher->EndReadData(num_bytes_read);
}
MojoResult Core::CreateSharedBuffer(
- const MojoCreateSharedBufferOptions* options,
uint64_t num_bytes,
+ const MojoCreateSharedBufferOptions* options,
MojoHandle* shared_buffer_handle) {
RequestContext request_context;
MojoCreateSharedBufferOptions validated_options = {};
@@ -971,15 +945,20 @@ MojoResult Core::DuplicateBufferHandle(
MojoResult Core::MapBuffer(MojoHandle buffer_handle,
uint64_t offset,
uint64_t num_bytes,
- void** buffer,
- MojoMapBufferFlags flags) {
- RequestContext request_context;
+ const MojoMapBufferOptions* options,
+ void** buffer) {
scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
if (!dispatcher)
return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options->flags != MOJO_MAP_BUFFER_FLAG_NONE)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
- std::unique_ptr<PlatformSharedBufferMapping> mapping;
- MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping;
+ MojoResult result = dispatcher->MapBuffer(offset, num_bytes, &mapping);
if (result != MOJO_RESULT_OK)
return result;
@@ -987,33 +966,42 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle,
void* address = mapping->GetBase();
{
base::AutoLock locker(mapping_table_lock_);
- result = mapping_table_.AddMapping(std::move(mapping));
+ if (mapping_table_.size() >= GetConfiguration().max_mapping_table_size)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+ auto emplace_result = mapping_table_.emplace(address, std::move(mapping));
+ DCHECK(emplace_result.second);
}
- if (result != MOJO_RESULT_OK)
- return result;
*buffer = address;
return MOJO_RESULT_OK;
}
MojoResult Core::UnmapBuffer(void* buffer) {
- RequestContext request_context;
- std::unique_ptr<PlatformSharedBufferMapping> mapping;
- MojoResult result;
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping;
// Destroy |mapping| while not holding the lock.
{
base::AutoLock lock(mapping_table_lock_);
- result = mapping_table_.RemoveMapping(buffer, &mapping);
+ auto iter = mapping_table_.find(buffer);
+ if (iter == mapping_table_.end())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ // Grab a reference so that it gets unmapped outside of this lock.
+ mapping = std::move(iter->second);
+ mapping_table_.erase(iter);
}
- return result;
+ return MOJO_RESULT_OK;
}
MojoResult Core::GetBufferInfo(MojoHandle buffer_handle,
- const MojoSharedBufferOptions* options,
+ const MojoGetBufferInfoOptions* options,
MojoSharedBufferInfo* info) {
- if (options && options->struct_size != sizeof(MojoSharedBufferOptions))
- return MOJO_RESULT_INVALID_ARGUMENT;
- if (!info || info->struct_size != sizeof(MojoSharedBufferInfo))
+ if (options) {
+ if (options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (options->flags != MOJO_GET_BUFFER_INFO_FLAG_NONE)
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
+ if (!info || info->struct_size < sizeof(MojoSharedBufferInfo))
return MOJO_RESULT_INVALID_ARGUMENT;
scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
@@ -1023,54 +1011,94 @@ MojoResult Core::GetBufferInfo(MojoHandle buffer_handle,
return dispatcher->GetBufferInfo(info);
}
-MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
- MojoHandle* mojo_handle) {
- ScopedPlatformHandle handle;
- MojoResult result =
- MojoPlatformHandleToScopedPlatformHandle(platform_handle, &handle);
+MojoResult Core::WrapInternalPlatformHandle(
+ const MojoPlatformHandle* platform_handle,
+ const MojoWrapPlatformHandleOptions* options,
+ MojoHandle* mojo_handle) {
+ ScopedInternalPlatformHandle handle;
+ MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
+ platform_handle, &handle);
if (result != MOJO_RESULT_OK)
return result;
- return CreatePlatformHandleWrapper(std::move(handle), mojo_handle);
+ return CreateInternalPlatformHandleWrapper(std::move(handle), mojo_handle);
}
-MojoResult Core::UnwrapPlatformHandle(MojoHandle mojo_handle,
- MojoPlatformHandle* platform_handle) {
- ScopedPlatformHandle handle;
- MojoResult result = PassWrappedPlatformHandle(mojo_handle, &handle);
+MojoResult Core::UnwrapInternalPlatformHandle(
+ MojoHandle mojo_handle,
+ const MojoUnwrapPlatformHandleOptions* options,
+ MojoPlatformHandle* platform_handle) {
+ ScopedInternalPlatformHandle handle;
+ MojoResult result = PassWrappedInternalPlatformHandle(mojo_handle, &handle);
if (result != MOJO_RESULT_OK)
return result;
- return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
- platform_handle);
+ return ScopedInternalPlatformHandleToMojoPlatformHandle(std::move(handle),
+ platform_handle);
}
-MojoResult Core::WrapPlatformSharedBufferHandle(
- const MojoPlatformHandle* platform_handle,
- size_t size,
+MojoResult Core::WrapPlatformSharedMemoryRegion(
+ const MojoPlatformHandle* platform_handles,
+ uint32_t num_platform_handles,
+ uint64_t size,
const MojoSharedBufferGuid* guid,
- MojoPlatformSharedBufferHandleFlags flags,
+ MojoPlatformSharedMemoryRegionAccessMode access_mode,
+ const MojoWrapPlatformSharedMemoryRegionOptions* options,
MojoHandle* mojo_handle) {
DCHECK(size);
- ScopedPlatformHandle handle;
- MojoResult result =
- MojoPlatformHandleToScopedPlatformHandle(platform_handle, &handle);
- if (result != MOJO_RESULT_OK)
- return result;
+
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ if (access_mode == MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
+ if (num_platform_handles != 2)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+#else
+ if (num_platform_handles != 1)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+#endif
+
+ ScopedInternalPlatformHandle handles[2];
+ bool handles_ok = true;
+ for (size_t i = 0; i < num_platform_handles; ++i) {
+ MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
+ &platform_handles[i], &handles[i]);
+ if (result != MOJO_RESULT_OK)
+ handles_ok = false;
+ }
+ if (!handles_ok)
+ return MOJO_RESULT_INVALID_ARGUMENT;
base::UnguessableToken token =
base::UnguessableToken::Deserialize(guid->high, guid->low);
- const bool read_only =
- flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY;
- scoped_refptr<PlatformSharedBuffer> platform_buffer =
- PlatformSharedBuffer::CreateFromPlatformHandle(size, read_only, token,
- std::move(handle));
- if (!platform_buffer)
+
+ base::subtle::PlatformSharedMemoryRegion::Mode mode;
+ switch (access_mode) {
+ case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_READ_ONLY:
+ mode = base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly;
+ break;
+ case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE:
+ mode = base::subtle::PlatformSharedMemoryRegion::Mode::kWritable;
+ break;
+ case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE:
+ mode = base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe;
+ break;
+ default:
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ base::subtle::PlatformSharedMemoryRegion region =
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ std::move(handles[0]), std::move(handles[1])),
+ mode, size, token);
+ if (!region.IsValid())
return MOJO_RESULT_UNKNOWN;
scoped_refptr<SharedBufferDispatcher> dispatcher;
- result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
- platform_buffer, &dispatcher);
+ MojoResult result =
+ SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
+ std::move(region), &dispatcher);
if (result != MOJO_RESULT_OK)
return result;
@@ -1084,12 +1112,14 @@ MojoResult Core::WrapPlatformSharedBufferHandle(
return MOJO_RESULT_OK;
}
-MojoResult Core::UnwrapPlatformSharedBufferHandle(
+MojoResult Core::UnwrapPlatformSharedMemoryRegion(
MojoHandle mojo_handle,
- MojoPlatformHandle* platform_handle,
- size_t* size,
+ const MojoUnwrapPlatformSharedMemoryRegionOptions* options,
+ MojoPlatformHandle* platform_handles,
+ uint32_t* num_platform_handles,
+ uint64_t* size,
MojoSharedBufferGuid* guid,
- MojoPlatformSharedBufferHandleFlags* flags) {
+ MojoPlatformSharedMemoryRegionAccessMode* access_mode) {
scoped_refptr<Dispatcher> dispatcher;
MojoResult result = MOJO_RESULT_OK;
{
@@ -1106,25 +1136,298 @@ MojoResult Core::UnwrapPlatformSharedBufferHandle(
SharedBufferDispatcher* shm_dispatcher =
static_cast<SharedBufferDispatcher*>(dispatcher.get());
- scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
- shm_dispatcher->PassPlatformSharedBuffer();
- DCHECK(platform_shared_buffer);
-
+ base::subtle::PlatformSharedMemoryRegion region =
+ shm_dispatcher->PassPlatformSharedMemoryRegion();
+ DCHECK(region.IsValid());
DCHECK(size);
- *size = platform_shared_buffer->GetNumBytes();
+ *size = region.GetSize();
- base::UnguessableToken token = platform_shared_buffer->GetGUID();
+ base::UnguessableToken token = region.GetGUID();
guid->high = token.GetHighForSerialization();
guid->low = token.GetLowForSerialization();
- DCHECK(flags);
- *flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
- if (platform_shared_buffer->IsReadOnly())
- *flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_HANDLE_IS_READ_ONLY;
+ DCHECK(access_mode);
+ switch (region.GetMode()) {
+ case base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly:
+ *access_mode = MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_READ_ONLY;
+ break;
+ case base::subtle::PlatformSharedMemoryRegion::Mode::kWritable:
+ *access_mode = MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE;
+ break;
+ case base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe:
+ *access_mode = MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE;
+ break;
+ default:
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ ScopedInternalPlatformHandle handle;
+ ScopedInternalPlatformHandle read_only_handle;
+ ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &handle, &read_only_handle);
+
+ const uint32_t available_handle_storage_slots = *num_platform_handles;
+ if (available_handle_storage_slots < 1)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+ *num_platform_handles = 1;
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ if (region.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
+ if (available_handle_storage_slots < 2)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (ScopedInternalPlatformHandleToMojoPlatformHandle(
+ std::move(read_only_handle), &platform_handles[1]) !=
+ MOJO_RESULT_OK) {
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+ *num_platform_handles = 2;
+ }
+#endif
+
+ if (ScopedInternalPlatformHandleToMojoPlatformHandle(
+ std::move(handle), &platform_handles[0]) != MOJO_RESULT_OK) {
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+ return MOJO_RESULT_OK;
+}
+
+MojoResult Core::CreateInvitation(const MojoCreateInvitationOptions* options,
+ MojoHandle* invitation_handle) {
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (!invitation_handle)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ *invitation_handle = AddDispatcher(new InvitationDispatcher);
+ if (*invitation_handle == MOJO_HANDLE_INVALID)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+ return MOJO_RESULT_OK;
+}
+
+MojoResult Core::AttachMessagePipeToInvitation(
+ MojoHandle invitation_handle,
+ const void* name,
+ uint32_t name_num_bytes,
+ const MojoAttachMessagePipeToInvitationOptions* options,
+ MojoHandle* message_pipe_handle) {
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (!message_pipe_handle)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (name_num_bytes == 0)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ scoped_refptr<Dispatcher> dispatcher = GetDispatcher(invitation_handle);
+ if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::INVITATION)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ auto* invitation_dispatcher =
+ static_cast<InvitationDispatcher*>(dispatcher.get());
+
+ RequestContext request_context;
+
+ ports::PortRef remote_peer_port;
+ MojoHandle local_handle = CreatePartialMessagePipe(&remote_peer_port);
+ if (local_handle == MOJO_HANDLE_INVALID)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+ MojoResult result = invitation_dispatcher->AttachMessagePipe(
+ base::StringPiece(static_cast<const char*>(name), name_num_bytes),
+ std::move(remote_peer_port));
+ if (result != MOJO_RESULT_OK) {
+ Close(local_handle);
+ return result;
+ }
+
+ *message_pipe_handle = local_handle;
+ return MOJO_RESULT_OK;
+}
+
+MojoResult Core::ExtractMessagePipeFromInvitation(
+ MojoHandle invitation_handle,
+ const void* name,
+ uint32_t name_num_bytes,
+ const MojoExtractMessagePipeFromInvitationOptions* options,
+ MojoHandle* message_pipe_handle) {
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (!message_pipe_handle)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (name_num_bytes == 0)
+ return MOJO_RESULT_INVALID_ARGUMENT;
- ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle();
- return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle),
- platform_handle);
+ RequestContext request_context;
+
+ base::StringPiece name_string(static_cast<const char*>(name), name_num_bytes);
+ scoped_refptr<Dispatcher> dispatcher = GetDispatcher(invitation_handle);
+ if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::INVITATION)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ auto* invitation_dispatcher =
+ static_cast<InvitationDispatcher*>(dispatcher.get());
+ // First attempt to extract from the invitation object itself. This is for
+ // cases where this creation was created in-process.
+ MojoResult extract_result = invitation_dispatcher->ExtractMessagePipe(
+ name_string, message_pipe_handle);
+ if (extract_result == MOJO_RESULT_OK ||
+ extract_result == MOJO_RESULT_RESOURCE_EXHAUSTED) {
+ return extract_result;
+ }
+
+ *message_pipe_handle =
+ ExtractMessagePipeFromInvitation(name_string.as_string());
+ if (*message_pipe_handle == MOJO_HANDLE_INVALID)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+ return MOJO_RESULT_OK;
+}
+
+MojoResult Core::SendInvitation(
+ MojoHandle invitation_handle,
+ const MojoPlatformProcessHandle* process_handle,
+ const MojoInvitationTransportEndpoint* transport_endpoint,
+ MojoProcessErrorHandler error_handler,
+ uintptr_t error_handler_context,
+ const MojoSendInvitationOptions* options) {
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ base::ProcessHandle target_process = base::kNullProcessHandle;
+ if (process_handle) {
+ if (process_handle->struct_size < sizeof(*process_handle))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+#if defined(OS_WIN)
+ target_process = reinterpret_cast<base::ProcessHandle>(
+ static_cast<uintptr_t>(process_handle->value));
+#else
+ target_process = static_cast<base::ProcessHandle>(process_handle->value);
+#endif
+ }
+
+ ProcessErrorCallback process_error_callback;
+ if (error_handler) {
+ auto error_handler_task_runner = GetNodeController()->io_task_runner();
+ process_error_callback = base::BindRepeating(
+ &RunMojoProcessErrorHandler,
+ base::Owned(new ProcessDisconnectHandler(
+ error_handler_task_runner, error_handler, error_handler_context)),
+ error_handler_task_runner, error_handler, error_handler_context);
+ } else if (default_process_error_callback_) {
+ process_error_callback = default_process_error_callback_;
+ }
+
+ if (!transport_endpoint)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (transport_endpoint->struct_size < sizeof(*transport_endpoint))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (transport_endpoint->num_platform_handles == 0)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (!transport_endpoint->platform_handles)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (transport_endpoint->type != MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL &&
+ transport_endpoint->type !=
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
+
+ scoped_refptr<Dispatcher> dispatcher = GetDispatcher(invitation_handle);
+ if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::INVITATION)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ auto* invitation_dispatcher =
+ static_cast<InvitationDispatcher*>(dispatcher.get());
+
+ ScopedInternalPlatformHandle endpoint_handle;
+ MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
+ &transport_endpoint->platform_handles[0], &endpoint_handle);
+ if (result != MOJO_RESULT_OK || !endpoint_handle.is_valid())
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_FUCHSIA))
+ if (transport_endpoint->type == MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER)
+ endpoint_handle.get().needs_connection = true;
+#endif
+
+ // At this point everything else has been validated, so we can take ownership
+ // of the dispatcher.
+ {
+ base::AutoLock lock(handles_->GetLock());
+ scoped_refptr<Dispatcher> removed_dispatcher;
+ MojoResult result = handles_->GetAndRemoveDispatcher(invitation_handle,
+ &removed_dispatcher);
+ if (result != MOJO_RESULT_OK) {
+ // Release ownership of the endpoint platform handle, per the API
+ // contract. The caller retains ownership on failure.
+ ignore_result(endpoint_handle.release());
+ return result;
+ }
+ DCHECK_EQ(removed_dispatcher.get(), invitation_dispatcher);
+ }
+
+ ConnectionParams connection_params(TransportProtocol::kLegacy,
+ std::move(endpoint_handle));
+
+ std::vector<std::pair<std::string, ports::PortRef>> attached_ports;
+ InvitationDispatcher::PortMapping attached_port_map =
+ invitation_dispatcher->TakeAttachedPorts();
+ invitation_dispatcher->Close();
+ for (auto& entry : attached_port_map)
+ attached_ports.emplace_back(entry.first, std::move(entry.second));
+
+ RequestContext request_context;
+ GetNodeController()->SendBrokerClientInvitation(
+ target_process, std::move(connection_params), attached_ports,
+ process_error_callback);
+
+ return MOJO_RESULT_OK;
+}
+
+MojoResult Core::AcceptInvitation(
+ const MojoInvitationTransportEndpoint* transport_endpoint,
+ const MojoAcceptInvitationOptions* options,
+ MojoHandle* invitation_handle) {
+ if (options && options->struct_size < sizeof(*options))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+
+ if (!transport_endpoint)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (transport_endpoint->struct_size < sizeof(*transport_endpoint))
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (transport_endpoint->num_platform_handles == 0)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (!transport_endpoint->platform_handles)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ if (transport_endpoint->type != MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL &&
+ transport_endpoint->type !=
+ MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
+ return MOJO_RESULT_UNIMPLEMENTED;
+ }
+
+ if (!invitation_handle)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ *invitation_handle = AddDispatcher(new InvitationDispatcher);
+ if (*invitation_handle == MOJO_HANDLE_INVALID)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+ ScopedInternalPlatformHandle endpoint_handle;
+ MojoResult result = MojoPlatformHandleToScopedInternalPlatformHandle(
+ &transport_endpoint->platform_handles[0], &endpoint_handle);
+ if (result != MOJO_RESULT_OK) {
+ Close(*invitation_handle);
+ *invitation_handle = MOJO_HANDLE_INVALID;
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ }
+
+#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_FUCHSIA))
+ if (transport_endpoint->type == MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER)
+ endpoint_handle.get().needs_connection = true;
+#endif
+
+ RequestContext request_context;
+ ConnectionParams connection_params(TransportProtocol::kLegacy,
+ std::move(endpoint_handle));
+ GetNodeController()->AcceptBrokerClientInvitation(
+ std::move(connection_params));
+ return MOJO_RESULT_OK;
}
void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
diff --git a/chromium/mojo/edk/system/core.h b/chromium/mojo/edk/system/core.h
index 478971e2dc6..9401189c809 100644
--- a/chromium/mojo/edk/system/core.h
+++ b/chromium/mojo/edk/system/core.h
@@ -19,11 +19,11 @@
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/handle_table.h"
-#include "mojo/edk/system/mapping_table.h"
#include "mojo/edk/system/node_controller.h"
#include "mojo/edk/system/system_impl_export.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
+#include "mojo/public/c/system/invitation.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/c/system/trap.h"
@@ -36,6 +36,8 @@ class PortProvider;
namespace mojo {
namespace edk {
+class PlatformSharedMemoryMapping;
+
// |Core| is an object that implements the Mojo system calls. All public methods
// are thread-safe.
class MOJO_SYSTEM_IMPL_EXPORT Core {
@@ -53,6 +55,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
NodeController* GetNodeController();
scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
+ scoped_refptr<Dispatcher> GetAndRemoveDispatcher(MojoHandle handle);
void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback);
@@ -137,23 +140,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
bool in_transit);
// See "mojo/edk/embedder/embedder.h" for more information on these functions.
- MojoResult CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle,
- MojoHandle* wrapper_handle);
-
- MojoResult PassWrappedPlatformHandle(MojoHandle wrapper_handle,
- ScopedPlatformHandle* platform_handle);
+ MojoResult CreateInternalPlatformHandleWrapper(
+ ScopedInternalPlatformHandle platform_handle,
+ MojoHandle* wrapper_handle);
- MojoResult CreateSharedBufferWrapper(
- base::SharedMemoryHandle shared_memory_handle,
- size_t num_bytes,
- bool read_only,
- MojoHandle* mojo_wrapper_handle);
-
- MojoResult PassSharedMemoryHandle(
- MojoHandle mojo_handle,
- base::SharedMemoryHandle* shared_memory_handle,
- size_t* num_bytes,
- bool* read_only);
+ MojoResult PassWrappedInternalPlatformHandle(
+ MojoHandle wrapper_handle,
+ ScopedInternalPlatformHandle* platform_handle);
// Requests that the EDK tear itself down. |callback| will be called once
// the shutdown process is complete. Note that |callback| is always called
@@ -163,8 +156,6 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
// may be called from any thread. Beware!
void RequestShutdown(const base::Closure& callback);
- MojoResult SetProperty(MojoPropertyType type, const void* value);
-
// ---------------------------------------------------------------------------
// The following methods are essentially implementations of the Mojo Core
@@ -223,7 +214,6 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoResult GetMessageContext(MojoMessageHandle message_handle,
const MojoGetMessageContextOptions* options,
uintptr_t* context);
- MojoResult GetProperty(MojoPropertyType type, void* value);
// These methods correspond to the API functions defined in
// "mojo/public/c/system/message_pipe.h":
@@ -232,14 +222,17 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoHandle* message_pipe_handle1);
MojoResult WriteMessage(MojoHandle message_pipe_handle,
MojoMessageHandle message_handle,
- MojoWriteMessageFlags flags);
+ const MojoWriteMessageOptions* options);
MojoResult ReadMessage(MojoHandle message_pipe_handle,
- MojoMessageHandle* message_handle,
- MojoReadMessageFlags flags);
- MojoResult FuseMessagePipes(MojoHandle handle0, MojoHandle handle1);
+ const MojoReadMessageOptions* options,
+ MojoMessageHandle* message_handle);
+ MojoResult FuseMessagePipes(MojoHandle handle0,
+ MojoHandle handle1,
+ const MojoFuseMessagePipesOptions* options);
MojoResult NotifyBadMessage(MojoMessageHandle message_handle,
const char* error,
- size_t error_num_bytes);
+ size_t error_num_bytes,
+ const MojoNotifyBadMessageOptions* options);
// These methods correspond to the API functions defined in
// "mojo/public/c/system/data_pipe.h":
@@ -249,28 +242,30 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoResult WriteData(MojoHandle data_pipe_producer_handle,
const void* elements,
uint32_t* num_bytes,
- MojoWriteDataFlags flags);
+ const MojoWriteDataOptions* options);
MojoResult BeginWriteData(MojoHandle data_pipe_producer_handle,
+ const MojoBeginWriteDataOptions* options,
void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags);
+ uint32_t* buffer_num_bytes);
MojoResult EndWriteData(MojoHandle data_pipe_producer_handle,
- uint32_t num_bytes_written);
+ uint32_t num_bytes_written,
+ const MojoEndWriteDataOptions* options);
MojoResult ReadData(MojoHandle data_pipe_consumer_handle,
+ const MojoReadDataOptions* options,
void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags);
+ uint32_t* num_bytes);
MojoResult BeginReadData(MojoHandle data_pipe_consumer_handle,
+ const MojoBeginReadDataOptions* options,
const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags);
+ uint32_t* buffer_num_bytes);
MojoResult EndReadData(MojoHandle data_pipe_consumer_handle,
- uint32_t num_bytes_read);
+ uint32_t num_bytes_read,
+ const MojoEndReadDataOptions* options);
// These methods correspond to the API functions defined in
// "mojo/public/c/system/buffer.h":
- MojoResult CreateSharedBuffer(const MojoCreateSharedBufferOptions* options,
- uint64_t num_bytes,
+ MojoResult CreateSharedBuffer(uint64_t num_bytes,
+ const MojoCreateSharedBufferOptions* options,
MojoHandle* shared_buffer_handle);
MojoResult DuplicateBufferHandle(
MojoHandle buffer_handle,
@@ -279,31 +274,66 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
MojoResult MapBuffer(MojoHandle buffer_handle,
uint64_t offset,
uint64_t num_bytes,
- void** buffer,
- MojoMapBufferFlags flags);
+ const MojoMapBufferOptions* options,
+ void** buffer);
MojoResult UnmapBuffer(void* buffer);
MojoResult GetBufferInfo(MojoHandle buffer_handle,
- const MojoSharedBufferOptions* options,
+ const MojoGetBufferInfoOptions* options,
MojoSharedBufferInfo* info);
// These methods correspond to the API functions defined in
// "mojo/public/c/system/platform_handle.h".
- MojoResult WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
- MojoHandle* mojo_handle);
- MojoResult UnwrapPlatformHandle(MojoHandle mojo_handle,
- MojoPlatformHandle* platform_handle);
- MojoResult WrapPlatformSharedBufferHandle(
+ MojoResult WrapInternalPlatformHandle(
const MojoPlatformHandle* platform_handle,
- size_t size,
+ const MojoWrapPlatformHandleOptions* options,
+ MojoHandle* mojo_handle);
+ MojoResult UnwrapInternalPlatformHandle(
+ MojoHandle mojo_handle,
+ const MojoUnwrapPlatformHandleOptions* options,
+ MojoPlatformHandle* platform_handle);
+ MojoResult WrapPlatformSharedMemoryRegion(
+ const MojoPlatformHandle* platform_handles,
+ uint32_t num_platform_handles,
+ uint64_t size,
const MojoSharedBufferGuid* guid,
- MojoPlatformSharedBufferHandleFlags flags,
+ MojoPlatformSharedMemoryRegionAccessMode access_mode,
+ const MojoWrapPlatformSharedMemoryRegionOptions* options,
MojoHandle* mojo_handle);
- MojoResult UnwrapPlatformSharedBufferHandle(
+ MojoResult UnwrapPlatformSharedMemoryRegion(
MojoHandle mojo_handle,
- MojoPlatformHandle* platform_handle,
- size_t* size,
+ const MojoUnwrapPlatformSharedMemoryRegionOptions* options,
+ MojoPlatformHandle* platform_handles,
+ uint32_t* num_platform_handles,
+ uint64_t* size,
MojoSharedBufferGuid* guid,
- MojoPlatformSharedBufferHandleFlags* flags);
+ MojoPlatformSharedMemoryRegionAccessMode* access_mode);
+
+ // Invitation API.
+ MojoResult CreateInvitation(const MojoCreateInvitationOptions* options,
+ MojoHandle* invitation_handle);
+ MojoResult AttachMessagePipeToInvitation(
+ MojoHandle invitation_handle,
+ const void* name,
+ uint32_t name_num_bytes,
+ const MojoAttachMessagePipeToInvitationOptions* options,
+ MojoHandle* message_pipe_handle);
+ MojoResult ExtractMessagePipeFromInvitation(
+ MojoHandle invitation_handle,
+ const void* name,
+ uint32_t name_num_bytes,
+ const MojoExtractMessagePipeFromInvitationOptions* options,
+ MojoHandle* message_pipe_handle);
+ MojoResult SendInvitation(
+ MojoHandle invitation_handle,
+ const MojoPlatformProcessHandle* process_handle,
+ const MojoInvitationTransportEndpoint* transport_endpoint,
+ MojoProcessErrorHandler error_handler,
+ uintptr_t error_handler_context,
+ const MojoSendInvitationOptions* options);
+ MojoResult AcceptInvitation(
+ const MojoInvitationTransportEndpoint* transport_endpoint,
+ const MojoAcceptInvitationOptions* options,
+ MojoHandle* invitation_handle);
void GetActiveHandlesForTest(std::vector<MojoHandle>* handles);
@@ -334,11 +364,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
std::unique_ptr<HandleTable> handles_;
base::Lock mapping_table_lock_; // Protects |mapping_table_|.
- MappingTable mapping_table_;
- base::Lock property_lock_;
- // Properties that can be read using the MojoGetProperty() API.
- bool property_sync_call_allowed_ = true;
+ using MappingTable =
+ std::unordered_map<void*, std::unique_ptr<PlatformSharedMemoryMapping>>;
+ MappingTable mapping_table_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
diff --git a/chromium/mojo/edk/system/core_test_base.cc b/chromium/mojo/edk/system/core_test_base.cc
index ff7b7c3ae52..a025a9bbf3b 100644
--- a/chromium/mojo/edk/system/core_test_base.cc
+++ b/chromium/mojo/edk/system/core_test_base.cc
@@ -41,8 +41,7 @@ class MockDispatcher : public Dispatcher {
}
MojoResult WriteMessage(
- std::unique_ptr<ports::UserMessageEvent> message_event,
- MojoWriteMessageFlags /*flags*/) override {
+ std::unique_ptr<ports::UserMessageEvent> message_event) override {
info_->IncrementWriteMessageCallCount();
return MOJO_RESULT_OK;
}
@@ -55,14 +54,13 @@ class MockDispatcher : public Dispatcher {
MojoResult WriteData(const void* elements,
uint32_t* num_bytes,
- MojoWriteDataFlags flags) override {
+ const MojoWriteDataOptions& options) override {
info_->IncrementWriteDataCallCount();
return MOJO_RESULT_UNIMPLEMENTED;
}
MojoResult BeginWriteData(void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags) override {
+ uint32_t* buffer_num_bytes) override {
info_->IncrementBeginWriteDataCallCount();
return MOJO_RESULT_UNIMPLEMENTED;
}
@@ -72,16 +70,15 @@ class MockDispatcher : public Dispatcher {
return MOJO_RESULT_UNIMPLEMENTED;
}
- MojoResult ReadData(void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags) override {
+ MojoResult ReadData(const MojoReadDataOptions& options,
+ void* elements,
+ uint32_t* num_bytes) override {
info_->IncrementReadDataCallCount();
return MOJO_RESULT_UNIMPLEMENTED;
}
MojoResult BeginReadData(const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags) override {
+ uint32_t* buffer_num_bytes) override {
info_->IncrementBeginReadDataCallCount();
return MOJO_RESULT_UNIMPLEMENTED;
}
diff --git a/chromium/mojo/edk/system/core_unittest.cc b/chromium/mojo/edk/system/core_unittest.cc
index 7fe7ba0e95b..a35208b7a46 100644
--- a/chromium/mojo/edk/system/core_unittest.cc
+++ b/chromium/mojo/edk/system/core_unittest.cc
@@ -51,46 +51,41 @@ TEST_F(CoreTest, Basic) {
ASSERT_EQ(0u, info.GetWriteMessageCallCount());
MojoMessageHandle message;
ASSERT_EQ(MOJO_RESULT_OK, core()->CreateMessage(nullptr, &message));
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h, message, nullptr));
ASSERT_EQ(1u, info.GetWriteMessageCallCount());
ASSERT_EQ(0u, info.GetReadMessageCallCount());
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(h, &message, MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h, nullptr, &message));
ASSERT_EQ(1u, info.GetReadMessageCallCount());
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(h, &message, MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h, nullptr, &message));
ASSERT_EQ(2u, info.GetReadMessageCallCount());
ASSERT_EQ(0u, info.GetWriteDataCallCount());
ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- core()->WriteData(h, nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE));
+ core()->WriteData(h, nullptr, nullptr, nullptr));
ASSERT_EQ(1u, info.GetWriteDataCallCount());
ASSERT_EQ(0u, info.GetBeginWriteDataCallCount());
- ASSERT_EQ(
- MOJO_RESULT_UNIMPLEMENTED,
- core()->BeginWriteData(h, nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
+ core()->BeginWriteData(h, nullptr, nullptr, nullptr));
ASSERT_EQ(1u, info.GetBeginWriteDataCallCount());
ASSERT_EQ(0u, info.GetEndWriteDataCallCount());
- ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0));
+ ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0, nullptr));
ASSERT_EQ(1u, info.GetEndWriteDataCallCount());
ASSERT_EQ(0u, info.GetReadDataCallCount());
ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
- core()->ReadData(h, nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE));
+ core()->ReadData(h, nullptr, nullptr, nullptr));
ASSERT_EQ(1u, info.GetReadDataCallCount());
ASSERT_EQ(0u, info.GetBeginReadDataCallCount());
- ASSERT_EQ(
- MOJO_RESULT_UNIMPLEMENTED,
- core()->BeginReadData(h, nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED,
+ core()->BeginReadData(h, nullptr, nullptr, nullptr));
ASSERT_EQ(1u, info.GetBeginReadDataCallCount());
ASSERT_EQ(0u, info.GetEndReadDataCallCount());
- ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0));
+ ASSERT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0, nullptr));
ASSERT_EQ(1u, info.GetEndReadDataCallCount());
ASSERT_EQ(0u, info.GetDtorCallCount());
@@ -122,23 +117,20 @@ TEST_F(CoreTest, InvalidArguments) {
// |WriteMessageNew()|:
// Only check arguments checked by |Core|, namely |handle|, |handles|, and
// |num_handles|.
- {
- ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(MOJO_HANDLE_INVALID, 0,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
- }
+ ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ core()->WriteMessage(MOJO_HANDLE_INVALID, 0, nullptr));
// |ReadMessageNew()|:
// Only check arguments checked by |Core|, namely |handle|, |handles|, and
// |num_handles|.
{
ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadMessage(MOJO_HANDLE_INVALID, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ core()->ReadMessage(MOJO_HANDLE_INVALID, nullptr, nullptr));
+
MockHandleInfo info;
MojoHandle h = CreateMockHandle(&info);
ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadMessage(h, nullptr, MOJO_READ_MESSAGE_FLAG_NONE));
+ core()->ReadMessage(h, nullptr, nullptr));
// Checked by |Core|, shouldn't go through to the dispatcher.
ASSERT_EQ(0u, info.GetReadMessageCallCount());
ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h));
@@ -168,7 +160,7 @@ TEST_F(CoreTest, MessagePipe) {
// Try to read anyway.
MojoMessageHandle message;
ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT,
- core()->ReadMessage(h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE));
+ core()->ReadMessage(h[0], nullptr, &message));
// Write to |h[1]|.
const uintptr_t kTestMessageContext = 123;
@@ -176,16 +168,14 @@ TEST_F(CoreTest, MessagePipe) {
ASSERT_EQ(MOJO_RESULT_OK,
core()->SetMessageContext(message, kTestMessageContext, nullptr,
nullptr, nullptr));
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h[1], message, nullptr));
// Wait for |h[0]| to become readable.
EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h[0]),
MOJO_HANDLE_SIGNAL_READABLE, &hss[0]));
// Read from |h[0]|.
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(h[0], &message, MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h[0], nullptr, &message));
uintptr_t context;
ASSERT_EQ(MOJO_RESULT_OK,
core()->GetMessageContext(message, nullptr, &context));
@@ -205,8 +195,7 @@ TEST_F(CoreTest, MessagePipe) {
ASSERT_EQ(MOJO_RESULT_OK,
core()->SetMessageContext(message, kTestMessageContext, nullptr,
nullptr, nullptr));
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->WriteMessage(h[0], message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h[0], message, nullptr));
// Close |h[0]|.
ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[0]));
@@ -229,8 +218,7 @@ TEST_F(CoreTest, MessagePipe) {
hss[1].satisfiable_signals);
// Discard a message from |h[1]|.
- ASSERT_EQ(MOJO_RESULT_OK,
- core()->ReadMessage(h[1], &message, MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h[1], nullptr, &message));
ASSERT_EQ(MOJO_RESULT_OK, core()->DestroyMessage(message));
// |h[1]| is no longer readable (and will never be).
@@ -245,7 +233,7 @@ TEST_F(CoreTest, MessagePipe) {
core()->SetMessageContext(message, kTestMessageContext, nullptr,
nullptr, nullptr));
ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- core()->WriteMessage(h[1], message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ core()->WriteMessage(h[1], message, nullptr));
ASSERT_EQ(MOJO_RESULT_OK, core()->Close(h[1]));
}
@@ -264,8 +252,8 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
ASSERT_EQ(MOJO_RESULT_OK,
core()->SetMessageContext(message, kTestMessageContext, nullptr,
nullptr, nullptr));
- ASSERT_EQ(MOJO_RESULT_OK, core()->WriteMessage(h_passing[0], message,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->WriteMessage(h_passing[0], message, nullptr));
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, mojo::Wait(mojo::Handle(h_passing[1]),
MOJO_HANDLE_SIGNAL_READABLE, &hss));
@@ -273,8 +261,8 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
hss.satisfied_signals);
ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
MojoMessageHandle message_handle;
- ASSERT_EQ(MOJO_RESULT_OK, core()->ReadMessage(h_passing[1], &message_handle,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->ReadMessage(h_passing[1], nullptr, &message_handle));
uintptr_t context;
ASSERT_EQ(MOJO_RESULT_OK,
core()->GetMessageContext(message_handle, nullptr, &context));
@@ -317,8 +305,8 @@ TEST_F(CoreTest, DataPipe) {
// Write.
signed char elements[2] = {'A', 'B'};
uint32_t num_bytes = 2u;
- ASSERT_EQ(MOJO_RESULT_OK, core()->WriteData(ph, elements, &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->WriteData(ph, elements, &num_bytes, nullptr));
ASSERT_EQ(2u, num_bytes);
// Wait for the data to arrive to the consumer.
@@ -339,9 +327,11 @@ TEST_F(CoreTest, DataPipe) {
elements[0] = -1;
elements[1] = -1;
num_bytes = 1u;
- ASSERT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, elements, &num_bytes,
- MOJO_READ_DATA_FLAG_NONE |
- MOJO_READ_DATA_FLAG_PEEK));
+ MojoReadDataOptions read_options;
+ read_options.struct_size = sizeof(read_options);
+ read_options.flags = MOJO_READ_DATA_FLAG_NONE | MOJO_READ_DATA_FLAG_PEEK;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->ReadData(ch, &read_options, elements, &num_bytes));
ASSERT_EQ('A', elements[0]);
ASSERT_EQ(-1, elements[1]);
@@ -349,30 +339,31 @@ TEST_F(CoreTest, DataPipe) {
elements[0] = -1;
elements[1] = -1;
num_bytes = 1u;
- ASSERT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, elements, &num_bytes,
- MOJO_READ_DATA_FLAG_NONE));
+ read_options.flags = MOJO_READ_DATA_FLAG_NONE;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->ReadData(ch, &read_options, elements, &num_bytes));
ASSERT_EQ('A', elements[0]);
ASSERT_EQ(-1, elements[1]);
// Two-phase write.
void* write_ptr = nullptr;
num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK, core()->BeginWriteData(ph, &write_ptr, &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->BeginWriteData(ph, nullptr, &write_ptr, &num_bytes));
// We count on the default options providing a decent buffer size.
ASSERT_GE(num_bytes, 3u);
// Trying to do a normal write during a two-phase write should fail.
elements[0] = 'X';
num_bytes = 1u;
- ASSERT_EQ(MOJO_RESULT_BUSY, core()->WriteData(ph, elements, &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_BUSY,
+ core()->WriteData(ph, elements, &num_bytes, nullptr));
// Actually write the data, and complete it now.
static_cast<char*>(write_ptr)[0] = 'C';
static_cast<char*>(write_ptr)[1] = 'D';
static_cast<char*>(write_ptr)[2] = 'E';
- ASSERT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 3u, nullptr));
// Wait for the data to arrive to the consumer.
ASSERT_EQ(MOJO_RESULT_OK,
@@ -380,73 +371,61 @@ TEST_F(CoreTest, DataPipe) {
// Query how much data we have.
num_bytes = 0;
- ASSERT_EQ(MOJO_RESULT_OK, core()->ReadData(ch, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_QUERY));
+ read_options.flags = MOJO_READ_DATA_FLAG_QUERY;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->ReadData(ch, &read_options, nullptr, &num_bytes));
ASSERT_GE(num_bytes, 1u);
// Try to query with peek. Should fail.
num_bytes = 0;
- ASSERT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadData(ch, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK));
+ read_options.flags = MOJO_READ_DATA_FLAG_QUERY | MOJO_READ_DATA_FLAG_PEEK;
+ ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ core()->ReadData(ch, &read_options, nullptr, &num_bytes));
ASSERT_EQ(0u, num_bytes);
// Try to discard ten characters, in all-or-none mode. Should fail.
num_bytes = 10;
+ read_options.flags =
+ MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE;
ASSERT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- core()->ReadData(
- ch, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+ core()->ReadData(ch, &read_options, nullptr, &num_bytes));
// Try to discard two characters, in peek mode. Should fail.
num_bytes = 2;
- ASSERT_EQ(
- MOJO_RESULT_INVALID_ARGUMENT,
- core()->ReadData(ch, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK));
+ read_options.flags = MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_PEEK;
+ ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ core()->ReadData(ch, &read_options, nullptr, &num_bytes));
// Discard a character.
num_bytes = 1;
+ read_options.flags =
+ MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE;
ASSERT_EQ(MOJO_RESULT_OK,
- core()->ReadData(
- ch, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+ core()->ReadData(ch, &read_options, nullptr, &num_bytes));
// Ensure the 3 bytes were read.
ASSERT_EQ(MOJO_RESULT_OK,
mojo::Wait(mojo::Handle(ch), MOJO_HANDLE_SIGNAL_READABLE, &hss));
- // Try a two-phase read of the remaining three bytes with peek. Should fail.
- const void* read_ptr = nullptr;
- num_bytes = 3;
- ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->BeginReadData(ch, &read_ptr, &num_bytes,
- MOJO_READ_DATA_FLAG_PEEK));
-
- // Try a two-phase read of the remaining two bytes with all-or-none. Should
- // fail.
- ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->BeginReadData(ch, &read_ptr, &num_bytes,
- MOJO_READ_DATA_FLAG_ALL_OR_NONE));
-
// Read the remaining three characters, in two-phase mode.
+ const void* read_ptr = nullptr;
num_bytes = 3;
- ASSERT_EQ(MOJO_RESULT_OK, core()->BeginReadData(ch, &read_ptr, &num_bytes,
- MOJO_READ_DATA_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ core()->BeginReadData(ch, nullptr, &read_ptr, &num_bytes));
// Note: Count on still being able to do the contiguous read here.
ASSERT_EQ(3u, num_bytes);
// Discarding right now should fail.
num_bytes = 1;
- ASSERT_EQ(MOJO_RESULT_BUSY, core()->ReadData(ch, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_DISCARD));
+ read_options.flags = MOJO_READ_DATA_FLAG_DISCARD;
+ ASSERT_EQ(MOJO_RESULT_BUSY,
+ core()->ReadData(ch, &read_options, nullptr, &num_bytes));
// Actually check our data and end the two-phase read.
ASSERT_EQ('C', static_cast<const char*>(read_ptr)[0]);
ASSERT_EQ('D', static_cast<const char*>(read_ptr)[1]);
ASSERT_EQ('E', static_cast<const char*>(read_ptr)[2]);
- ASSERT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 3u));
+ ASSERT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 3u, nullptr));
// Consumer should now be no longer readable.
hss = kFullMojoHandleSignalsState;
diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
index f5c0c7e6b25..78d6d129e86 100644
--- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.cc
@@ -14,8 +14,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/system/core.h"
#include "mojo/edk/system/data_pipe_control_message.h"
#include "mojo/edk/system/node_controller.h"
@@ -74,12 +73,13 @@ class DataPipeConsumerDispatcher::PortObserverThunk
scoped_refptr<DataPipeConsumerDispatcher> DataPipeConsumerDispatcher::Create(
NodeController* node_controller,
const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
const MojoCreateDataPipeOptions& options,
uint64_t pipe_id) {
scoped_refptr<DataPipeConsumerDispatcher> consumer =
new DataPipeConsumerDispatcher(node_controller, control_port,
- shared_ring_buffer, options, pipe_id);
+ std::move(shared_ring_buffer), options,
+ pipe_id);
base::AutoLock lock(consumer->lock_);
if (!consumer->InitializeNoLock())
return nullptr;
@@ -96,12 +96,13 @@ MojoResult DataPipeConsumerDispatcher::Close() {
return CloseNoLock();
}
-MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags) {
+MojoResult DataPipeConsumerDispatcher::ReadData(
+ const MojoReadDataOptions& options,
+ void* elements,
+ uint32_t* num_bytes) {
base::AutoLock lock(lock_);
- if (!shared_ring_buffer_ || in_transit_)
+ if (!shared_ring_buffer_.IsValid() || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
if (in_two_phase_read_)
@@ -110,11 +111,11 @@ MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
const bool had_new_data = new_data_available_;
new_data_available_ = false;
- if ((flags & MOJO_READ_DATA_FLAG_QUERY)) {
- if ((flags & MOJO_READ_DATA_FLAG_PEEK) ||
- (flags & MOJO_READ_DATA_FLAG_DISCARD))
+ if ((options.flags & MOJO_READ_DATA_FLAG_QUERY)) {
+ if ((options.flags & MOJO_READ_DATA_FLAG_PEEK) ||
+ (options.flags & MOJO_READ_DATA_FLAG_DISCARD))
return MOJO_RESULT_INVALID_ARGUMENT;
- DCHECK(!(flags & MOJO_READ_DATA_FLAG_DISCARD)); // Handled above.
+ DCHECK(!(options.flags & MOJO_READ_DATA_FLAG_DISCARD)); // Handled above.
DVLOG_IF(2, elements) << "Query mode: ignoring non-null |elements|";
*num_bytes = static_cast<uint32_t>(bytes_available_);
@@ -124,9 +125,9 @@ MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
}
bool discard = false;
- if ((flags & MOJO_READ_DATA_FLAG_DISCARD)) {
+ if ((options.flags & MOJO_READ_DATA_FLAG_DISCARD)) {
// These flags are mutally exclusive.
- if (flags & MOJO_READ_DATA_FLAG_PEEK)
+ if (options.flags & MOJO_READ_DATA_FLAG_PEEK)
return MOJO_RESULT_INVALID_ARGUMENT;
DVLOG_IF(2, elements) << "Discard mode: ignoring non-null |elements|";
discard = true;
@@ -136,7 +137,7 @@ MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
if (max_num_bytes_to_read % options_.element_num_bytes != 0)
return MOJO_RESULT_INVALID_ARGUMENT;
- bool all_or_none = flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE;
+ bool all_or_none = options.flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE;
uint32_t min_num_bytes_to_read = all_or_none ? max_num_bytes_to_read : 0;
if (min_num_bytes_to_read > bytes_available_) {
@@ -155,7 +156,8 @@ MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
}
if (!discard) {
- uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_->GetBase());
+ const uint8_t* data =
+ static_cast<const uint8_t*>(ring_buffer_mapping_.memory());
CHECK(data);
uint8_t* destination = static_cast<uint8_t*>(elements);
@@ -172,7 +174,7 @@ MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
}
*num_bytes = bytes_to_read;
- bool peek = !!(flags & MOJO_READ_DATA_FLAG_PEEK);
+ bool peek = !!(options.flags & MOJO_READ_DATA_FLAG_PEEK);
if (discard || !peek) {
read_offset_ = (read_offset_ + bytes_to_read) % options_.capacity_num_bytes;
bytes_available_ -= bytes_to_read;
@@ -188,23 +190,16 @@ MojoResult DataPipeConsumerDispatcher::ReadData(void* elements,
return MOJO_RESULT_OK;
}
-MojoResult DataPipeConsumerDispatcher::BeginReadData(const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags) {
+MojoResult DataPipeConsumerDispatcher::BeginReadData(
+ const void** buffer,
+ uint32_t* buffer_num_bytes) {
base::AutoLock lock(lock_);
- if (!shared_ring_buffer_ || in_transit_)
+ if (!shared_ring_buffer_.IsValid() || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
if (in_two_phase_read_)
return MOJO_RESULT_BUSY;
- // These flags may not be used in two-phase mode.
- if ((flags & MOJO_READ_DATA_FLAG_DISCARD) ||
- (flags & MOJO_READ_DATA_FLAG_QUERY) ||
- (flags & MOJO_READ_DATA_FLAG_PEEK) ||
- (flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE))
- return MOJO_RESULT_INVALID_ARGUMENT;
-
const bool had_new_data = new_data_available_;
new_data_available_ = false;
@@ -219,8 +214,8 @@ MojoResult DataPipeConsumerDispatcher::BeginReadData(const void** buffer,
uint32_t bytes_to_read =
std::min(bytes_available_, options_.capacity_num_bytes - read_offset_);
- CHECK(ring_buffer_mapping_);
- uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_->GetBase());
+ CHECK(ring_buffer_mapping_.IsValid());
+ uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_.memory());
CHECK(data);
in_two_phase_read_ = true;
@@ -242,7 +237,7 @@ MojoResult DataPipeConsumerDispatcher::EndReadData(uint32_t num_bytes_read) {
if (in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
- CHECK(shared_ring_buffer_);
+ CHECK(shared_ring_buffer_.IsValid());
MojoResult rv;
if (num_bytes_read > two_phase_max_bytes_read_ ||
@@ -304,7 +299,7 @@ void DataPipeConsumerDispatcher::StartSerialize(uint32_t* num_bytes,
bool DataPipeConsumerDispatcher::EndSerialize(
void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* platform_handles) {
+ ScopedInternalPlatformHandle* platform_handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions));
memset(state->padding, 0, sizeof(state->padding));
@@ -316,14 +311,20 @@ bool DataPipeConsumerDispatcher::EndSerialize(
state->bytes_available = bytes_available_;
state->flags = peer_closed_ ? kFlagPeerClosed : 0;
- base::UnguessableToken guid = shared_ring_buffer_->GetGUID();
+ auto region_handle =
+ base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
+ std::move(shared_ring_buffer_));
+ const base::UnguessableToken& guid = region_handle.GetGUID();
state->buffer_guid_high = guid.GetHighForSerialization();
state->buffer_guid_low = guid.GetLowForSerialization();
ports[0] = control_port_.name();
- platform_handles[0] = shared_ring_buffer_->DuplicatePlatformHandle();
- if (!platform_handles[0].is_valid())
+ ScopedInternalPlatformHandle ignored_handle;
+ ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ region_handle.PassPlatformHandle(), &platform_handles[0],
+ &ignored_handle);
+ if (!platform_handles[0].is_valid() || ignored_handle.is_valid())
return false;
return true;
@@ -360,7 +361,7 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles != 1 ||
num_bytes != sizeof(SerializedState)) {
@@ -378,22 +379,28 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
if (node_controller->node()->GetPort(ports[0], &port) != ports::OK)
return nullptr;
- base::UnguessableToken guid = base::UnguessableToken::Deserialize(
- state->buffer_guid_high, state->buffer_guid_low);
- ScopedPlatformHandle buffer_handle;
+ ScopedInternalPlatformHandle buffer_handle;
std::swap(buffer_handle, handles[0]);
- scoped_refptr<PlatformSharedBuffer> ring_buffer =
- PlatformSharedBuffer::CreateFromPlatformHandle(
- state->options.capacity_num_bytes, false /* read_only */, guid,
- std::move(buffer_handle));
- if (!ring_buffer) {
+ auto region_handle =
+ CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ std::move(buffer_handle), ScopedInternalPlatformHandle());
+ auto region = base::subtle::PlatformSharedMemoryRegion::Take(
+ std::move(region_handle),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ state->options.capacity_num_bytes,
+ base::UnguessableToken::Deserialize(state->buffer_guid_high,
+ state->buffer_guid_low));
+ auto ring_buffer =
+ base::UnsafeSharedMemoryRegion::Deserialize(std::move(region));
+ if (!ring_buffer.IsValid()) {
DLOG(ERROR) << "Failed to deserialize shared buffer handle.";
return nullptr;
}
scoped_refptr<DataPipeConsumerDispatcher> dispatcher =
- new DataPipeConsumerDispatcher(node_controller, port, ring_buffer,
- state->options, state->pipe_id);
+ new DataPipeConsumerDispatcher(node_controller, port,
+ std::move(ring_buffer), state->options,
+ state->pipe_id);
{
base::AutoLock lock(dispatcher->lock_);
@@ -412,7 +419,7 @@ DataPipeConsumerDispatcher::Deserialize(const void* data,
DataPipeConsumerDispatcher::DataPipeConsumerDispatcher(
NodeController* node_controller,
const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
const MojoCreateDataPipeOptions& options,
uint64_t pipe_id)
: options_(options),
@@ -420,24 +427,23 @@ DataPipeConsumerDispatcher::DataPipeConsumerDispatcher(
control_port_(control_port),
pipe_id_(pipe_id),
watchers_(this),
- shared_ring_buffer_(shared_ring_buffer) {}
+ shared_ring_buffer_(std::move(shared_ring_buffer)) {}
DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() {
- DCHECK(is_closed_ && !shared_ring_buffer_ && !ring_buffer_mapping_ &&
- !in_transit_);
+ DCHECK(is_closed_ && !shared_ring_buffer_.IsValid() &&
+ !ring_buffer_mapping_.IsValid() && !in_transit_);
}
bool DataPipeConsumerDispatcher::InitializeNoLock() {
lock_.AssertAcquired();
- if (!shared_ring_buffer_)
+ if (!shared_ring_buffer_.IsValid())
return false;
- DCHECK(!ring_buffer_mapping_);
- ring_buffer_mapping_ =
- shared_ring_buffer_->Map(0, options_.capacity_num_bytes);
- if (!ring_buffer_mapping_) {
+ DCHECK(!ring_buffer_mapping_.IsValid());
+ ring_buffer_mapping_ = shared_ring_buffer_.Map();
+ if (!ring_buffer_mapping_.IsValid()) {
DLOG(ERROR) << "Failed to map shared buffer.";
- shared_ring_buffer_ = nullptr;
+ shared_ring_buffer_ = base::UnsafeSharedMemoryRegion();
return false;
}
@@ -453,8 +459,8 @@ MojoResult DataPipeConsumerDispatcher::CloseNoLock() {
if (is_closed_ || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
is_closed_ = true;
- ring_buffer_mapping_.reset();
- shared_ring_buffer_ = nullptr;
+ ring_buffer_mapping_ = base::WritableSharedMemoryMapping();
+ shared_ring_buffer_ = base::UnsafeSharedMemoryRegion();
watchers_.NotifyClosed();
if (!transferred_) {
@@ -470,18 +476,18 @@ HandleSignalsState DataPipeConsumerDispatcher::GetHandleSignalsStateNoLock()
lock_.AssertAcquired();
HandleSignalsState rv;
- if (shared_ring_buffer_ && bytes_available_) {
+ if (shared_ring_buffer_.IsValid() && bytes_available_) {
if (!in_two_phase_read_) {
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_READABLE;
if (new_data_available_)
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE;
}
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
- } else if (!peer_closed_ && shared_ring_buffer_) {
+ } else if (!peer_closed_ && shared_ring_buffer_.IsValid()) {
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
}
- if (shared_ring_buffer_) {
+ if (shared_ring_buffer_.IsValid()) {
if (new_data_available_ || !peer_closed_)
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE;
}
diff --git a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h
index 15cce6d9286..48a63f1ba4a 100644
--- a/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h
+++ b/chromium/mojo/edk/system/data_pipe_consumer_dispatcher.h
@@ -12,8 +12,9 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ports/port_ref.h"
@@ -34,19 +35,18 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
static scoped_refptr<DataPipeConsumerDispatcher> Create(
NodeController* node_controller,
const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
const MojoCreateDataPipeOptions& options,
uint64_t pipe_id);
// Dispatcher:
Type GetType() const override;
MojoResult Close() override;
- MojoResult ReadData(void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags) override;
+ MojoResult ReadData(const MojoReadDataOptions& validated_options,
+ void* elements,
+ uint32_t* num_bytes) override;
MojoResult BeginReadData(const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags) override;
+ uint32_t* buffer_num_bytes) override;
MojoResult EndReadData(uint32_t num_bytes_read) override;
HandleSignalsState GetHandleSignalsState() const override;
MojoResult AddWatcherRef(const scoped_refptr<WatcherDispatcher>& watcher,
@@ -58,7 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles) override;
+ ScopedInternalPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -68,19 +68,18 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles);
private:
class PortObserverThunk;
friend class PortObserverThunk;
- DataPipeConsumerDispatcher(
- NodeController* node_controller,
- const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
- const MojoCreateDataPipeOptions& options,
- uint64_t pipe_id);
+ DataPipeConsumerDispatcher(NodeController* node_controller,
+ const ports::PortRef& control_port,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
+ const MojoCreateDataPipeOptions& options,
+ uint64_t pipe_id);
~DataPipeConsumerDispatcher() override;
bool InitializeNoLock();
@@ -100,8 +99,11 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher final
WatcherSet watchers_;
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer_;
- std::unique_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_;
+ base::UnsafeSharedMemoryRegion shared_ring_buffer_;
+
+ // We don't really write to it, and it's safe because we're the only consumer
+ // of this buffer.
+ base::WritableSharedMemoryMapping ring_buffer_mapping_;
bool in_two_phase_read_ = false;
uint32_t two_phase_max_bytes_read_ = 0;
diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
index 987e4d61de2..caa76d959ef 100644
--- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.cc
@@ -12,8 +12,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/core.h"
#include "mojo/edk/system/data_pipe_control_message.h"
@@ -73,12 +72,13 @@ class DataPipeProducerDispatcher::PortObserverThunk
scoped_refptr<DataPipeProducerDispatcher> DataPipeProducerDispatcher::Create(
NodeController* node_controller,
const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
const MojoCreateDataPipeOptions& options,
uint64_t pipe_id) {
scoped_refptr<DataPipeProducerDispatcher> producer =
new DataPipeProducerDispatcher(node_controller, control_port,
- shared_ring_buffer, options, pipe_id);
+ std::move(shared_ring_buffer), options,
+ pipe_id);
base::AutoLock lock(producer->lock_);
if (!producer->InitializeNoLock())
return nullptr;
@@ -95,11 +95,12 @@ MojoResult DataPipeProducerDispatcher::Close() {
return CloseNoLock();
}
-MojoResult DataPipeProducerDispatcher::WriteData(const void* elements,
- uint32_t* num_bytes,
- MojoWriteDataFlags flags) {
+MojoResult DataPipeProducerDispatcher::WriteData(
+ const void* elements,
+ uint32_t* num_bytes,
+ const MojoWriteDataOptions& options) {
base::AutoLock lock(lock_);
- if (!shared_ring_buffer_ || in_transit_)
+ if (!shared_ring_buffer_.IsValid() || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
if (in_two_phase_write_)
@@ -113,7 +114,7 @@ MojoResult DataPipeProducerDispatcher::WriteData(const void* elements,
if (*num_bytes == 0)
return MOJO_RESULT_OK; // Nothing to do.
- if ((flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) &&
+ if ((options.flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) &&
(*num_bytes > available_capacity_)) {
// Don't return "should wait" since you can't wait for a specified amount of
// data.
@@ -127,8 +128,8 @@ MojoResult DataPipeProducerDispatcher::WriteData(const void* elements,
*num_bytes = num_bytes_to_write;
- CHECK(ring_buffer_mapping_);
- uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_->GetBase());
+ CHECK(ring_buffer_mapping_.IsValid());
+ uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_.memory());
CHECK(data);
const uint8_t* source = static_cast<const uint8_t*>(elements);
@@ -159,14 +160,9 @@ MojoResult DataPipeProducerDispatcher::WriteData(const void* elements,
MojoResult DataPipeProducerDispatcher::BeginWriteData(
void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags) {
+ uint32_t* buffer_num_bytes) {
base::AutoLock lock(lock_);
- if (!shared_ring_buffer_ || in_transit_)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- // These flags may not be used in two-phase mode.
- if (flags & MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)
+ if (!shared_ring_buffer_.IsValid() || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
if (in_two_phase_write_)
@@ -184,8 +180,8 @@ MojoResult DataPipeProducerDispatcher::BeginWriteData(
available_capacity_);
DCHECK_GT(*buffer_num_bytes, 0u);
- CHECK(ring_buffer_mapping_);
- uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_->GetBase());
+ CHECK(ring_buffer_mapping_.IsValid());
+ uint8_t* data = static_cast<uint8_t*>(ring_buffer_mapping_.memory());
*buffer = data + write_offset_;
return MOJO_RESULT_OK;
@@ -200,9 +196,6 @@ MojoResult DataPipeProducerDispatcher::EndWriteData(
if (!in_two_phase_write_)
return MOJO_RESULT_FAILED_PRECONDITION;
- DCHECK(shared_ring_buffer_);
- DCHECK(ring_buffer_mapping_);
-
// Note: Allow successful completion of the two-phase write even if the other
// side has been closed.
MojoResult rv = MOJO_RESULT_OK;
@@ -265,7 +258,7 @@ void DataPipeProducerDispatcher::StartSerialize(uint32_t* num_bytes,
bool DataPipeProducerDispatcher::EndSerialize(
void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* platform_handles) {
+ ScopedInternalPlatformHandle* platform_handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
memcpy(&state->options, &options_, sizeof(MojoCreateDataPipeOptions));
memset(state->padding, 0, sizeof(state->padding));
@@ -277,14 +270,20 @@ bool DataPipeProducerDispatcher::EndSerialize(
state->available_capacity = available_capacity_;
state->flags = peer_closed_ ? kFlagPeerClosed : 0;
- base::UnguessableToken guid = shared_ring_buffer_->GetGUID();
+ auto region_handle =
+ base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
+ std::move(shared_ring_buffer_));
+ const base::UnguessableToken& guid = region_handle.GetGUID();
state->buffer_guid_high = guid.GetHighForSerialization();
state->buffer_guid_low = guid.GetLowForSerialization();
ports[0] = control_port_.name();
- platform_handles[0] = shared_ring_buffer_->DuplicatePlatformHandle();
- if (!platform_handles[0].is_valid())
+ ScopedInternalPlatformHandle ignored_handle;
+ ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ region_handle.PassPlatformHandle(), &platform_handles[0],
+ &ignored_handle);
+ if (!platform_handles[0].is_valid() || ignored_handle.is_valid())
return false;
return true;
@@ -323,7 +322,7 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles != 1 ||
num_bytes != sizeof(SerializedState)) {
@@ -341,22 +340,28 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
if (node_controller->node()->GetPort(ports[0], &port) != ports::OK)
return nullptr;
- base::UnguessableToken guid = base::UnguessableToken::Deserialize(
- state->buffer_guid_high, state->buffer_guid_low);
- ScopedPlatformHandle buffer_handle;
+ ScopedInternalPlatformHandle buffer_handle;
std::swap(buffer_handle, handles[0]);
- scoped_refptr<PlatformSharedBuffer> ring_buffer =
- PlatformSharedBuffer::CreateFromPlatformHandle(
- state->options.capacity_num_bytes, false /* read_only */, guid,
- std::move(buffer_handle));
- if (!ring_buffer) {
+ auto region_handle =
+ CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ std::move(buffer_handle), ScopedInternalPlatformHandle());
+ auto region = base::subtle::PlatformSharedMemoryRegion::Take(
+ std::move(region_handle),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ state->options.capacity_num_bytes,
+ base::UnguessableToken::Deserialize(state->buffer_guid_high,
+ state->buffer_guid_low));
+ auto ring_buffer =
+ base::UnsafeSharedMemoryRegion::Deserialize(std::move(region));
+ if (!ring_buffer.IsValid()) {
DLOG(ERROR) << "Failed to deserialize shared buffer handle.";
return nullptr;
}
scoped_refptr<DataPipeProducerDispatcher> dispatcher =
- new DataPipeProducerDispatcher(node_controller, port, ring_buffer,
- state->options, state->pipe_id);
+ new DataPipeProducerDispatcher(node_controller, port,
+ std::move(ring_buffer), state->options,
+ state->pipe_id);
{
base::AutoLock lock(dispatcher->lock_);
@@ -374,7 +379,7 @@ DataPipeProducerDispatcher::Deserialize(const void* data,
DataPipeProducerDispatcher::DataPipeProducerDispatcher(
NodeController* node_controller,
const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
const MojoCreateDataPipeOptions& options,
uint64_t pipe_id)
: options_(options),
@@ -382,25 +387,24 @@ DataPipeProducerDispatcher::DataPipeProducerDispatcher(
control_port_(control_port),
pipe_id_(pipe_id),
watchers_(this),
- shared_ring_buffer_(shared_ring_buffer),
+ shared_ring_buffer_(std::move(shared_ring_buffer)),
available_capacity_(options_.capacity_num_bytes) {}
DataPipeProducerDispatcher::~DataPipeProducerDispatcher() {
- DCHECK(is_closed_ && !in_transit_ && !shared_ring_buffer_ &&
- !ring_buffer_mapping_);
+ DCHECK(is_closed_ && !in_transit_ && !shared_ring_buffer_.IsValid() &&
+ !ring_buffer_mapping_.IsValid());
}
bool DataPipeProducerDispatcher::InitializeNoLock() {
lock_.AssertAcquired();
- if (!shared_ring_buffer_)
+ if (!shared_ring_buffer_.IsValid())
return false;
- DCHECK(!ring_buffer_mapping_);
- ring_buffer_mapping_ =
- shared_ring_buffer_->Map(0, options_.capacity_num_bytes);
- if (!ring_buffer_mapping_) {
+ DCHECK(!ring_buffer_mapping_.IsValid());
+ ring_buffer_mapping_ = shared_ring_buffer_.Map();
+ if (!ring_buffer_mapping_.IsValid()) {
DLOG(ERROR) << "Failed to map shared buffer.";
- shared_ring_buffer_ = nullptr;
+ shared_ring_buffer_ = base::UnsafeSharedMemoryRegion();
return false;
}
@@ -416,8 +420,8 @@ MojoResult DataPipeProducerDispatcher::CloseNoLock() {
if (is_closed_ || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
is_closed_ = true;
- ring_buffer_mapping_.reset();
- shared_ring_buffer_ = nullptr;
+ ring_buffer_mapping_ = base::WritableSharedMemoryMapping();
+ shared_ring_buffer_ = base::UnsafeSharedMemoryRegion();
watchers_.NotifyClosed();
if (!transferred_) {
@@ -433,7 +437,8 @@ HandleSignalsState DataPipeProducerDispatcher::GetHandleSignalsStateNoLock()
lock_.AssertAcquired();
HandleSignalsState rv;
if (!peer_closed_) {
- if (!in_two_phase_write_ && shared_ring_buffer_ && available_capacity_ > 0)
+ if (!in_two_phase_write_ && shared_ring_buffer_.IsValid() &&
+ available_capacity_ > 0)
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
if (peer_remote_)
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_REMOTE;
diff --git a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h
index 735d72a2261..4ee72c8e426 100644
--- a/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h
+++ b/chromium/mojo/edk/system/data_pipe_producer_dispatcher.h
@@ -12,8 +12,9 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ports/port_ref.h"
@@ -34,7 +35,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
static scoped_refptr<DataPipeProducerDispatcher> Create(
NodeController* node_controller,
const ports::PortRef& control_port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
const MojoCreateDataPipeOptions& options,
uint64_t pipe_id);
@@ -43,10 +44,8 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
MojoResult Close() override;
MojoResult WriteData(const void* elements,
uint32_t* num_bytes,
- MojoReadDataFlags flags) override;
- MojoResult BeginWriteData(void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags) override;
+ const MojoWriteDataOptions& options) override;
+ MojoResult BeginWriteData(void** buffer, uint32_t* buffer_num_bytes) override;
MojoResult EndWriteData(uint32_t num_bytes_written) override;
HandleSignalsState GetHandleSignalsState() const override;
MojoResult AddWatcherRef(const scoped_refptr<WatcherDispatcher>& watcher,
@@ -58,7 +57,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles) override;
+ ScopedInternalPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -68,22 +67,20 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles);
private:
class PortObserverThunk;
friend class PortObserverThunk;
- DataPipeProducerDispatcher(
- NodeController* node_controller,
- const ports::PortRef& port,
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer,
- const MojoCreateDataPipeOptions& options,
- uint64_t pipe_id);
+ DataPipeProducerDispatcher(NodeController* node_controller,
+ const ports::PortRef& port,
+ base::UnsafeSharedMemoryRegion shared_ring_buffer,
+ const MojoCreateDataPipeOptions& options,
+ uint64_t pipe_id);
~DataPipeProducerDispatcher() override;
- void OnSharedBufferCreated(const scoped_refptr<PlatformSharedBuffer>& buffer);
bool InitializeNoLock();
MojoResult CloseNoLock();
HandleSignalsState GetHandleSignalsStateNoLock() const;
@@ -101,10 +98,8 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher final
WatcherSet watchers_;
- bool buffer_requested_ = false;
-
- scoped_refptr<PlatformSharedBuffer> shared_ring_buffer_;
- std::unique_ptr<PlatformSharedBufferMapping> ring_buffer_mapping_;
+ base::UnsafeSharedMemoryRegion shared_ring_buffer_;
+ base::WritableSharedMemoryMapping ring_buffer_mapping_;
bool in_transit_ = false;
bool is_closed_ = false;
diff --git a/chromium/mojo/edk/system/data_pipe_unittest.cc b/chromium/mojo/edk/system/data_pipe_unittest.cc
index a8a65f85791..dbee3ed8b45 100644
--- a/chromium/mojo/edk/system/data_pipe_unittest.cc
+++ b/chromium/mojo/edk/system/data_pipe_unittest.cc
@@ -80,9 +80,11 @@ class DataPipeTest : public test::MojoTestBase {
MojoResult WriteData(const void* elements,
uint32_t* num_bytes,
bool all_or_none = false) {
- return MojoWriteData(producer_, elements, num_bytes,
- all_or_none ? MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
- : MOJO_WRITE_DATA_FLAG_NONE);
+ MojoWriteDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = all_or_none ? MOJO_WRITE_DATA_FLAG_ALL_OR_NONE
+ : MOJO_WRITE_DATA_FLAG_NONE;
+ return MojoWriteData(producer_, elements, num_bytes, &options);
}
MojoResult ReadData(void* elements,
@@ -94,41 +96,44 @@ class DataPipeTest : public test::MojoTestBase {
flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE;
if (peek)
flags |= MOJO_READ_DATA_FLAG_PEEK;
- return MojoReadData(consumer_, elements, num_bytes, flags);
+
+ MojoReadDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = flags;
+ return MojoReadData(consumer_, &options, elements, num_bytes);
}
MojoResult QueryData(uint32_t* num_bytes) {
- return MojoReadData(consumer_, nullptr, num_bytes,
- MOJO_READ_DATA_FLAG_QUERY);
+ MojoReadDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_READ_DATA_FLAG_QUERY;
+ return MojoReadData(consumer_, &options, nullptr, num_bytes);
}
MojoResult DiscardData(uint32_t* num_bytes, bool all_or_none = false) {
MojoReadDataFlags flags = MOJO_READ_DATA_FLAG_DISCARD;
if (all_or_none)
flags |= MOJO_READ_DATA_FLAG_ALL_OR_NONE;
- return MojoReadData(consumer_, nullptr, num_bytes, flags);
+ MojoReadDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = flags;
+ return MojoReadData(consumer_, &options, nullptr, num_bytes);
}
MojoResult BeginReadData(const void** elements, uint32_t* num_bytes) {
- return MojoBeginReadData(consumer_, elements, num_bytes,
- MOJO_READ_DATA_FLAG_NONE);
+ return MojoBeginReadData(consumer_, nullptr, elements, num_bytes);
}
MojoResult EndReadData(uint32_t num_bytes_read) {
- return MojoEndReadData(consumer_, num_bytes_read);
+ return MojoEndReadData(consumer_, num_bytes_read, nullptr);
}
- MojoResult BeginWriteData(void** elements,
- uint32_t* num_bytes,
- bool all_or_none = false) {
- MojoReadDataFlags flags = MOJO_WRITE_DATA_FLAG_NONE;
- if (all_or_none)
- flags |= MOJO_WRITE_DATA_FLAG_ALL_OR_NONE;
- return MojoBeginWriteData(producer_, elements, num_bytes, flags);
+ MojoResult BeginWriteData(void** elements, uint32_t* num_bytes) {
+ return MojoBeginWriteData(producer_, nullptr, elements, num_bytes);
}
MojoResult EndWriteData(uint32_t num_bytes_written) {
- return MojoEndWriteData(producer_, num_bytes_written);
+ return MojoEndWriteData(producer_, num_bytes_written, nullptr);
}
MojoResult CloseProducer() {
@@ -151,10 +156,10 @@ class DataPipeTest : public test::MojoTestBase {
TEST_F(DataPipeTest, Basic) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -191,20 +196,20 @@ TEST_F(DataPipeTest, CreateAndMaybeTransfer) {
// Default options.
{},
// Trivial element size, non-default capacity.
- {kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1, // |element_num_bytes|.
- 1000}, // |capacity_num_bytes|.
+ {kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1, // |element_num_bytes|.
+ 1000}, // |capacity_num_bytes|.
// Nontrivial element size, non-default capacity.
- {kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 4, // |element_num_bytes|.
- 4000}, // |capacity_num_bytes|.
+ {kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 4, // |element_num_bytes|.
+ 4000}, // |capacity_num_bytes|.
// Nontrivial element size, default capacity.
- {kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 100, // |element_num_bytes|.
- 0} // |capacity_num_bytes|.
+ {kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 100, // |element_num_bytes|.
+ 0} // |capacity_num_bytes|.
};
for (size_t i = 0; i < arraysize(test_options); i++) {
MojoHandle producer_handle, consumer_handle;
@@ -218,10 +223,10 @@ TEST_F(DataPipeTest, CreateAndMaybeTransfer) {
TEST_F(DataPipeTest, SimpleReadWrite) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -337,10 +342,10 @@ TEST_F(DataPipeTest, BasicProducerWaiting) {
// the API.
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 2 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 2 * sizeof(int32_t) // |capacity_num_bytes|.
};
Create(&options);
MojoHandleSignalsState hss;
@@ -427,10 +432,10 @@ TEST_F(DataPipeTest, BasicProducerWaiting) {
TEST_F(DataPipeTest, PeerClosedProducerWaiting) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 2 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 2 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -448,10 +453,10 @@ TEST_F(DataPipeTest, PeerClosedProducerWaiting) {
TEST_F(DataPipeTest, PeerClosedConsumerWaiting) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 2 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 2 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -469,10 +474,10 @@ TEST_F(DataPipeTest, PeerClosedConsumerWaiting) {
TEST_F(DataPipeTest, BasicConsumerWaiting) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -604,13 +609,13 @@ TEST_F(DataPipeTest, BasicConsumerWaiting) {
}
TEST_F(DataPipeTest, ConsumerNewDataReadable) {
- const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ const MojoCreateDataPipeOptions create_options = {
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
- EXPECT_EQ(MOJO_RESULT_OK, Create(&options));
+ EXPECT_EQ(MOJO_RESULT_OK, Create(&create_options));
int32_t elements[2] = {123, 456};
uint32_t num_bytes = static_cast<uint32_t>(2u * sizeof(elements[0]));
@@ -625,9 +630,12 @@ TEST_F(DataPipeTest, ConsumerNewDataReadable) {
// Now try to read a minimum of 6 elements.
int32_t read_elements[6];
uint32_t num_read_bytes = sizeof(read_elements);
- EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- MojoReadData(consumer_, read_elements, &num_read_bytes,
- MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+ MojoReadDataOptions read_options;
+ read_options.struct_size = sizeof(read_options);
+ read_options.flags = MOJO_READ_DATA_FLAG_ALL_OR_NONE;
+ EXPECT_EQ(
+ MOJO_RESULT_OUT_OF_RANGE,
+ MojoReadData(consumer_, &read_options, read_elements, &num_read_bytes));
// The consumer should still appear to be readable but not with new data.
EXPECT_TRUE(GetSignalsState(consumer_).satisfied_signals &
@@ -644,9 +652,8 @@ TEST_F(DataPipeTest, ConsumerNewDataReadable) {
WaitForSignals(consumer_, MOJO_HANDLE_SIGNAL_READABLE));
// Try again to read a minimum of 6 elements. Should succeed this time.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadData(consumer_, read_elements, &num_read_bytes,
- MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(consumer_, &read_options,
+ read_elements, &num_read_bytes));
// And now the consumer is unreadable.
EXPECT_FALSE(GetSignalsState(consumer_).satisfied_signals &
@@ -659,10 +666,10 @@ TEST_F(DataPipeTest, ConsumerNewDataReadable) {
// consumer waiter.
TEST_F(DataPipeTest, ConsumerWaitingTwoPhase) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -672,7 +679,7 @@ TEST_F(DataPipeTest, ConsumerWaitingTwoPhase) {
void* buffer = nullptr;
// Request room for three (but we'll only write two).
uint32_t num_bytes = static_cast<uint32_t>(3u * sizeof(elements[0]));
- ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&buffer, &num_bytes, false));
+ ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&buffer, &num_bytes));
EXPECT_TRUE(buffer);
EXPECT_GE(num_bytes, static_cast<uint32_t>(3u * sizeof(elements[0])));
elements = static_cast<int32_t*>(buffer);
@@ -736,10 +743,10 @@ TEST_F(DataPipeTest, ConsumerWaitingTwoPhase) {
// Tests that data pipes aren't writable/readable during two-phase writes/reads.
TEST_F(DataPipeTest, BasicTwoPhaseWaiting) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -856,10 +863,10 @@ void Seq(int32_t start, size_t count, int32_t* out) {
TEST_F(DataPipeTest, AllOrNone) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 10 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -1026,10 +1033,10 @@ TEST_F(DataPipeTest, WrapAround) {
test_data[i] = static_cast<unsigned char>(i);
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 100u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 100u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -1060,8 +1067,7 @@ TEST_F(DataPipeTest, WrapAround) {
// checks an implementation detail; this behavior is not guaranteed.)
void* write_buffer_ptr = nullptr;
num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK,
- BeginWriteData(&write_buffer_ptr, &num_bytes, false));
+ ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_buffer_ptr, &num_bytes));
EXPECT_TRUE(write_buffer_ptr);
ASSERT_EQ(80u, num_bytes);
ASSERT_EQ(MOJO_RESULT_OK, EndWriteData(0));
@@ -1114,10 +1120,10 @@ TEST_F(DataPipeTest, WriteCloseProducerRead) {
const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 1000u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -1134,8 +1140,7 @@ TEST_F(DataPipeTest, WriteCloseProducerRead) {
// Start two-phase write.
void* write_buffer_ptr = nullptr;
num_bytes = 0u;
- ASSERT_EQ(MOJO_RESULT_OK,
- BeginWriteData(&write_buffer_ptr, &num_bytes, false));
+ ASSERT_EQ(MOJO_RESULT_OK, BeginWriteData(&write_buffer_ptr, &num_bytes));
EXPECT_TRUE(write_buffer_ptr);
EXPECT_GT(num_bytes, 0u);
@@ -1179,10 +1184,10 @@ TEST_F(DataPipeTest, TwoPhaseWriteReadCloseConsumer) {
const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 1000u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -1252,10 +1257,10 @@ TEST_F(DataPipeTest, TwoPhaseWriteCloseBoth) {
const uint32_t kTestDataSize = 15u;
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 1000u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -1274,10 +1279,10 @@ TEST_F(DataPipeTest, WriteCloseProducerReadNoData) {
const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 1000u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -1338,10 +1343,10 @@ TEST_F(DataPipeTest, TwoPhaseReadMemoryStable) {
const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 1000u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -1396,10 +1401,10 @@ TEST_F(DataPipeTest, TwoPhaseReadMemoryStable) {
// arguments.
TEST_F(DataPipeTest, TwoPhaseMoreInvalidArguments) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 10 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 10 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -1522,10 +1527,10 @@ TEST_F(DataPipeTest, SendProducer) {
const uint32_t kTestDataSize = static_cast<uint32_t>(sizeof(kTestData));
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1u, // |element_num_bytes|.
- 1000u // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1u, // |element_num_bytes|.
+ 1000u // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
MojoHandleSignalsState hss;
@@ -1598,10 +1603,10 @@ TEST_F(DataPipeTest, SendProducer) {
// peer.
TEST_F(DataPipeTest, ConsumerWithClosedProducerSent) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
- 1000 * sizeof(int32_t) // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 1000 * sizeof(int32_t) // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -1659,8 +1664,8 @@ bool WriteAllData(MojoHandle producer,
for (size_t i = 0; i < kMaxPoll; i++) {
// Write as much data as we can.
uint32_t write_bytes = num_bytes;
- MojoResult result = MojoWriteData(producer, elements, &write_bytes,
- MOJO_WRITE_DATA_FLAG_NONE);
+ MojoResult result =
+ MojoWriteData(producer, elements, &write_bytes, nullptr);
if (result == MOJO_RESULT_OK) {
num_bytes -= write_bytes;
elements = static_cast<const uint8_t*>(elements) + write_bytes;
@@ -1690,8 +1695,7 @@ bool ReadAllData(MojoHandle consumer,
for (size_t i = 0; i < kMaxPoll; i++) {
// Read as much data as we can.
uint32_t read_bytes = num_bytes;
- MojoResult result =
- MojoReadData(consumer, elements, &read_bytes, MOJO_READ_DATA_FLAG_NONE);
+ MojoResult result = MojoReadData(consumer, nullptr, elements, &read_bytes);
if (result == MOJO_RESULT_OK) {
num_bytes -= read_bytes;
elements = static_cast<uint8_t*>(elements) + read_bytes;
@@ -1699,8 +1703,10 @@ bool ReadAllData(MojoHandle consumer,
if (expect_empty) {
// Expect no more data.
test::Sleep(test::TinyDeadline());
- MojoReadData(consumer, nullptr, &num_bytes,
- MOJO_READ_DATA_FLAG_QUERY);
+ MojoReadDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_READ_DATA_FLAG_QUERY;
+ MojoReadData(consumer, &options, nullptr, &num_bytes);
EXPECT_EQ(0u, num_bytes);
}
return true;
@@ -1727,10 +1733,10 @@ TEST_F(DataPipeTest, Multiprocess) {
const uint32_t kTestDataSize =
static_cast<uint32_t>(sizeof(kMultiprocessTestData));
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1, // |element_num_bytes|.
- kMultiprocessCapacity // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1, // |element_num_bytes|.
+ kMultiprocessCapacity // |capacity_num_bytes|.
};
ASSERT_EQ(MOJO_RESULT_OK, Create(&options));
@@ -1848,8 +1854,8 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteAndCloseProducer, DataPipeTest, h) {
// Write some data to the producer and close it.
uint32_t num_bytes = static_cast<uint32_t>(message.size());
- EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(p, message.data(), &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoWriteData(p, message.data(), &num_bytes, nullptr));
EXPECT_EQ(num_bytes, static_cast<uint32_t>(message.size()));
// Close the producer before quitting.
@@ -1869,8 +1875,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndCloseConsumer, DataPipeTest, h) {
// Drain the consumer and expect to find the given message.
uint32_t num_bytes = static_cast<uint32_t>(expected_message.size());
std::vector<char> bytes(expected_message.size());
- EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(c, bytes.data(), &num_bytes,
- MOJO_READ_DATA_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(c, nullptr, bytes.data(), &num_bytes));
EXPECT_EQ(num_bytes, static_cast<uint32_t>(bytes.size()));
std::string message(bytes.data(), bytes.size());
@@ -1902,10 +1907,10 @@ TEST_F(DataPipeTest, SendConsumerAndCloseProducer) {
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndWrite, DataPipeTest, h) {
const MojoCreateDataPipeOptions options = {
- kSizeOfOptions, // |struct_size|.
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
- 1, // |element_num_bytes|.
- kMultiprocessCapacity // |capacity_num_bytes|.
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_FLAG_NONE, // |flags|.
+ 1, // |element_num_bytes|.
+ kMultiprocessCapacity // |capacity_num_bytes|.
};
MojoHandle p, c;
@@ -1916,8 +1921,8 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndWrite, DataPipeTest, h) {
// Write some data to the producer and close it.
uint32_t num_bytes = static_cast<uint32_t>(kMessage.size());
- EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(p, kMessage.data(), &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoWriteData(p, kMessage.data(), &num_bytes, nullptr));
EXPECT_EQ(num_bytes, static_cast<uint32_t>(kMessage.size()));
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(p));
@@ -1936,8 +1941,8 @@ TEST_F(DataPipeTest, CreateInChild) {
// Drain the consumer and expect to find the given message.
uint32_t num_bytes = static_cast<uint32_t>(expected_message.size());
std::vector<char> bytes(expected_message.size());
- EXPECT_EQ(MOJO_RESULT_OK, MojoReadData(c, bytes.data(), &num_bytes,
- MOJO_READ_DATA_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoReadData(c, nullptr, bytes.data(), &num_bytes));
EXPECT_EQ(num_bytes, static_cast<uint32_t>(bytes.size()));
std::string message(bytes.data(), bytes.size());
@@ -1998,8 +2003,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient,
MojoResult result;
do {
uint32_t num_bytes = 0;
- result = MojoWriteData(producers[2], nullptr, &num_bytes,
- MOJO_WRITE_DATA_FLAG_NONE);
+ result = MojoWriteData(producers[2], nullptr, &num_bytes, nullptr);
} while (result == MOJO_RESULT_OK);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
@@ -2007,8 +2011,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient,
do {
char byte;
uint32_t num_bytes = 1;
- result =
- MojoReadData(consumers[2], &byte, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ result = MojoReadData(consumers[2], nullptr, &byte, &num_bytes);
} while (result == MOJO_RESULT_SHOULD_WAIT);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
diff --git a/chromium/mojo/edk/system/dispatcher.cc b/chromium/mojo/edk/system/dispatcher.cc
index e736276dfd3..6d9f875a1c0 100644
--- a/chromium/mojo/edk/system/dispatcher.cc
+++ b/chromium/mojo/edk/system/dispatcher.cc
@@ -42,8 +42,7 @@ MojoResult Dispatcher::Arm(uint32_t* num_ready_contexts,
}
MojoResult Dispatcher::WriteMessage(
- std::unique_ptr<ports::UserMessageEvent> message,
- MojoWriteMessageFlags flags) {
+ std::unique_ptr<ports::UserMessageEvent> message) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -61,8 +60,7 @@ MojoResult Dispatcher::DuplicateBufferHandle(
MojoResult Dispatcher::MapBuffer(
uint64_t offset,
uint64_t num_bytes,
- MojoMapBufferFlags flags,
- std::unique_ptr<PlatformSharedBufferMapping>* mapping) {
+ std::unique_ptr<PlatformSharedMemoryMapping>* mapping) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -70,15 +68,14 @@ MojoResult Dispatcher::GetBufferInfo(MojoSharedBufferInfo* info) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
-MojoResult Dispatcher::ReadData(void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags) {
+MojoResult Dispatcher::ReadData(const MojoReadDataOptions& options,
+ void* elements,
+ uint32_t* num_bytes) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
MojoResult Dispatcher::BeginReadData(const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags) {
+ uint32_t* buffer_num_bytes) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -88,13 +85,12 @@ MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
MojoResult Dispatcher::WriteData(const void* elements,
uint32_t* num_bytes,
- MojoWriteDataFlags flags) {
+ const MojoWriteDataOptions& options) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
MojoResult Dispatcher::BeginWriteData(void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags) {
+ uint32_t* buffer_num_bytes) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -102,22 +98,13 @@ MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
-MojoResult Dispatcher::AddWaitingDispatcher(
- const scoped_refptr<Dispatcher>& dispatcher,
- MojoHandleSignals signals,
- uintptr_t context) {
- return MOJO_RESULT_INVALID_ARGUMENT;
-}
-
-MojoResult Dispatcher::RemoveWaitingDispatcher(
- const scoped_refptr<Dispatcher>& dispatcher) {
+MojoResult Dispatcher::AttachMessagePipe(base::StringPiece name,
+ ports::PortRef remote_peer_port) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
-MojoResult Dispatcher::GetReadyDispatchers(uint32_t* count,
- DispatcherVector* dispatchers,
- MojoResult* results,
- uintptr_t* contexts) {
+MojoResult Dispatcher::ExtractMessagePipe(base::StringPiece name,
+ MojoHandle* message_pipe_handle) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
@@ -146,7 +133,7 @@ void Dispatcher::StartSerialize(uint32_t* num_bytes,
bool Dispatcher::EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles) {
+ ScopedInternalPlatformHandle* handles) {
LOG(ERROR) << "Attempting to serialize a non-transferrable dispatcher.";
return true;
}
@@ -166,7 +153,7 @@ scoped_refptr<Dispatcher> Dispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* platform_handles,
+ ScopedInternalPlatformHandle* platform_handles,
size_t num_platform_handles) {
switch (type) {
case Type::MESSAGE_PIPE:
diff --git a/chromium/mojo/edk/system/dispatcher.h b/chromium/mojo/edk/system/dispatcher.h
index 3e13c1bd143..3776be2e812 100644
--- a/chromium/mojo/edk/system/dispatcher.h
+++ b/chromium/mojo/edk/system/dispatcher.h
@@ -14,12 +14,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "mojo/edk/embedder/platform_handle.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/ports/name.h"
+#include "mojo/edk/system/ports/port_ref.h"
#include "mojo/edk/system/system_impl_export.h"
#include "mojo/edk/system/watch.h"
#include "mojo/public/c/system/buffer.h"
@@ -36,6 +37,7 @@ class UserMessageEvent;
}
class Dispatcher;
+class PlatformSharedMemoryMapping;
using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>;
@@ -60,6 +62,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
DATA_PIPE_CONSUMER,
SHARED_BUFFER,
WATCHER,
+ INVITATION,
// "Private" types (not exposed via the public interface):
PLATFORM_HANDLE = -1,
@@ -85,8 +88,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
///////////// Message pipe API /////////////
virtual MojoResult WriteMessage(
- std::unique_ptr<ports::UserMessageEvent> message,
- MojoWriteMessageFlags flags);
+ std::unique_ptr<ports::UserMessageEvent> message);
virtual MojoResult ReadMessage(
std::unique_ptr<ports::UserMessageEvent>* message);
@@ -103,20 +105,18 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
virtual MojoResult MapBuffer(
uint64_t offset,
uint64_t num_bytes,
- MojoMapBufferFlags flags,
- std::unique_ptr<PlatformSharedBufferMapping>* mapping);
+ std::unique_ptr<PlatformSharedMemoryMapping>* mapping);
virtual MojoResult GetBufferInfo(MojoSharedBufferInfo* info);
///////////// Data pipe consumer API /////////////
- virtual MojoResult ReadData(void* elements,
- uint32_t* num_bytes,
- MojoReadDataFlags flags);
+ virtual MojoResult ReadData(const MojoReadDataOptions& options,
+ void* elements,
+ uint32_t* num_bytes);
virtual MojoResult BeginReadData(const void** buffer,
- uint32_t* buffer_num_bytes,
- MojoReadDataFlags flags);
+ uint32_t* buffer_num_bytes);
virtual MojoResult EndReadData(uint32_t num_bytes_read);
@@ -124,37 +124,17 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
virtual MojoResult WriteData(const void* elements,
uint32_t* num_bytes,
- MojoWriteDataFlags flags);
+ const MojoWriteDataOptions& options);
- virtual MojoResult BeginWriteData(void** buffer,
- uint32_t* buffer_num_bytes,
- MojoWriteDataFlags flags);
+ virtual MojoResult BeginWriteData(void** buffer, uint32_t* buffer_num_bytes);
virtual MojoResult EndWriteData(uint32_t num_bytes_written);
- ///////////// Wait set API /////////////
-
- // Adds a dispatcher to wait on. When the dispatcher satisfies |signals|, it
- // will be returned in the next call to |GetReadyDispatchers()|. If
- // |dispatcher| has been added, it must be removed before adding again,
- // otherwise |MOJO_RESULT_ALREADY_EXISTS| will be returned.
- virtual MojoResult AddWaitingDispatcher(
- const scoped_refptr<Dispatcher>& dispatcher,
- MojoHandleSignals signals,
- uintptr_t context);
-
- // Removes a dispatcher to wait on. If |dispatcher| has not been added,
- // |MOJO_RESULT_NOT_FOUND| will be returned.
- virtual MojoResult RemoveWaitingDispatcher(
- const scoped_refptr<Dispatcher>& dispatcher);
-
- // Returns a set of ready dispatchers. |*count| is the maximum number of
- // dispatchers to return, and will contain the number of dispatchers returned
- // in |dispatchers| on completion.
- virtual MojoResult GetReadyDispatchers(uint32_t* count,
- DispatcherVector* dispatchers,
- MojoResult* results,
- uintptr_t* contexts);
+ // Invitation API.
+ virtual MojoResult AttachMessagePipe(base::StringPiece name,
+ ports::PortRef remote_peer_port);
+ virtual MojoResult ExtractMessagePipe(base::StringPiece name,
+ MojoHandle* message_pipe_handle);
///////////// General-purpose API for all handle types /////////
@@ -197,13 +177,13 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
// will close.
//
// NOTE: Transit MAY still fail after this call returns. Implementations
- // should not assume PlatformHandle ownership has transferred until
+ // should not assume InternalPlatformHandle ownership has transferred until
// CompleteTransitAndClose() is called. In other words, if CancelTransit() is
- // called, the implementation should retain its PlatformHandles in working
- // condition.
+ // called, the implementation should retain its InternalPlatformHandles in
+ // working condition.
virtual bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles);
+ ScopedInternalPlatformHandle* handles);
// Does whatever is necessary to begin transit of the dispatcher. This
// should return |true| if transit is OK, or false if the underlying resource
@@ -226,7 +206,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* platform_handles,
+ ScopedInternalPlatformHandle* platform_handles,
size_t platform_handle_count);
protected:
diff --git a/chromium/mojo/edk/system/handle_table.cc b/chromium/mojo/edk/system/handle_table.cc
index 91ed4694303..a9fcc651414 100644
--- a/chromium/mojo/edk/system/handle_table.cc
+++ b/chromium/mojo/edk/system/handle_table.cc
@@ -31,6 +31,8 @@ const char* GetNameForDispatcherType(Dispatcher::Type type) {
return "watcher";
case Dispatcher::Type::PLATFORM_HANDLE:
return "platform_handle";
+ case Dispatcher::Type::INVITATION:
+ return "invitation";
}
NOTREACHED();
return "unknown";
diff --git a/chromium/mojo/edk/system/invitation_dispatcher.cc b/chromium/mojo/edk/system/invitation_dispatcher.cc
new file mode 100644
index 00000000000..aa684bc0409
--- /dev/null
+++ b/chromium/mojo/edk/system/invitation_dispatcher.cc
@@ -0,0 +1,78 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/edk/system/invitation_dispatcher.h"
+
+#include "mojo/edk/system/core.h"
+
+namespace mojo {
+namespace edk {
+
+InvitationDispatcher::InvitationDispatcher() = default;
+
+Dispatcher::Type InvitationDispatcher::GetType() const {
+ return Type::INVITATION;
+}
+
+MojoResult InvitationDispatcher::Close() {
+ PortMapping attached_ports;
+ {
+ base::AutoLock lock(lock_);
+ if (is_closed_)
+ return MOJO_RESULT_INVALID_ARGUMENT;
+ is_closed_ = true;
+ std::swap(attached_ports, attached_ports_);
+ }
+ for (auto& entry : attached_ports)
+ Core::Get()->GetNodeController()->ClosePort(entry.second);
+ return MOJO_RESULT_OK;
+}
+
+MojoResult InvitationDispatcher::AttachMessagePipe(
+ base::StringPiece name,
+ ports::PortRef remote_peer_port) {
+ base::AutoLock lock(lock_);
+ auto result = attached_ports_.emplace(name.as_string(), remote_peer_port);
+ if (!result.second) {
+ Core::Get()->GetNodeController()->ClosePort(remote_peer_port);
+ return MOJO_RESULT_ALREADY_EXISTS;
+ }
+ return MOJO_RESULT_OK;
+}
+
+MojoResult InvitationDispatcher::ExtractMessagePipe(
+ base::StringPiece name,
+ MojoHandle* message_pipe_handle) {
+ ports::PortRef remote_peer_port;
+ {
+ base::AutoLock lock(lock_);
+ auto it = attached_ports_.find(name.as_string());
+ if (it == attached_ports_.end())
+ return MOJO_RESULT_NOT_FOUND;
+ remote_peer_port = std::move(it->second);
+ attached_ports_.erase(it);
+ }
+
+ *message_pipe_handle =
+ Core::Get()->CreatePartialMessagePipe(remote_peer_port);
+ if (*message_pipe_handle == MOJO_HANDLE_INVALID)
+ return MOJO_RESULT_RESOURCE_EXHAUSTED;
+ return MOJO_RESULT_OK;
+}
+
+InvitationDispatcher::PortMapping InvitationDispatcher::TakeAttachedPorts() {
+ PortMapping attached_ports;
+ {
+ base::AutoLock lock(lock_);
+ std::swap(attached_ports, attached_ports_);
+ }
+ return attached_ports;
+}
+
+InvitationDispatcher::~InvitationDispatcher() {
+ DCHECK(is_closed_);
+}
+
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/invitation_dispatcher.h b/chromium/mojo/edk/system/invitation_dispatcher.h
new file mode 100644
index 00000000000..21c530be02a
--- /dev/null
+++ b/chromium/mojo/edk/system/invitation_dispatcher.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_SYSTEM_INVITATION_DISPATCHER_H_
+#define MOJO_EDK_SYSTEM_INVITATION_DISPATCHER_H_
+
+#include <stdint.h>
+
+#include "base/containers/flat_map.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/system/ports/port_ref.h"
+#include "mojo/edk/system/system_impl_export.h"
+
+namespace mojo {
+namespace edk {
+
+class MOJO_SYSTEM_IMPL_EXPORT InvitationDispatcher : public Dispatcher {
+ public:
+ InvitationDispatcher();
+
+ // Dispatcher:
+ Type GetType() const override;
+ MojoResult Close() override;
+ MojoResult AttachMessagePipe(base::StringPiece name,
+ ports::PortRef remote_peer_port) override;
+ MojoResult ExtractMessagePipe(base::StringPiece name,
+ MojoHandle* message_pipe_handle) override;
+
+ using PortMapping = base::flat_map<std::string, ports::PortRef>;
+ PortMapping TakeAttachedPorts();
+
+ private:
+ ~InvitationDispatcher() override;
+
+ base::Lock lock_;
+ bool is_closed_ = false;
+ PortMapping attached_ports_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvitationDispatcher);
+};
+
+} // namespace edk
+} // namespace mojo
+
+#endif // MOJO_EDK_SYSTEM_INVITATION_DISPATCHER_H
diff --git a/chromium/mojo/edk/system/invitation_unittest.cc b/chromium/mojo/edk/system/invitation_unittest.cc
new file mode 100644
index 00000000000..ddb86ae0659
--- /dev/null
+++ b/chromium/mojo/edk/system/invitation_unittest.cc
@@ -0,0 +1,610 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstdint>
+#include <string>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/synchronization/lock.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "build/build_config.h"
+#include "mojo/edk/test/mojo_test_base.h"
+#include "mojo/public/c/system/invitation.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+namespace mojo {
+namespace edk {
+namespace {
+
+enum class TransportType {
+ kChannel,
+ kChannelServer,
+};
+
+class InvitationTest : public test::MojoTestBase {
+ public:
+ InvitationTest() = default;
+ ~InvitationTest() override = default;
+
+ protected:
+ static base::Process LaunchChildTestClient(
+ const std::string& test_client_name,
+ MojoHandle* primordial_pipes,
+ size_t num_primordial_pipes,
+ TransportType transport_type,
+ MojoProcessErrorHandler error_handler = nullptr,
+ uintptr_t error_handler_context = 0);
+
+ private:
+ base::test::ScopedTaskEnvironment task_environment_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvitationTest);
+};
+
+TEST_F(InvitationTest, Create) {
+ MojoHandle invitation;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ MojoCreateInvitationOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_CREATE_INVITATION_FLAG_NONE;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(&options, &invitation));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+}
+
+TEST_F(InvitationTest, InvalidArguments) {
+ MojoHandle invitation;
+ MojoCreateInvitationOptions invalid_create_options;
+ invalid_create_options.struct_size = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoCreateInvitation(&invalid_create_options, &invitation));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoCreateInvitation(nullptr, nullptr));
+
+ // We need a valid invitation handle to exercise some of the other invalid
+ // argument cases below.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
+
+ MojoHandle pipe;
+ MojoAttachMessagePipeToInvitationOptions invalid_attach_options;
+ invalid_attach_options.struct_size = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAttachMessagePipeToInvitation(MOJO_HANDLE_INVALID, "x", 1,
+ nullptr, &pipe));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAttachMessagePipeToInvitation(invitation, "x", 1,
+ &invalid_attach_options, &pipe));
+ EXPECT_EQ(
+ MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAttachMessagePipeToInvitation(invitation, "x", 1, nullptr, nullptr));
+
+ MojoExtractMessagePipeFromInvitationOptions invalid_extract_options;
+ invalid_extract_options.struct_size = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoExtractMessagePipeFromInvitation(MOJO_HANDLE_INVALID, "x", 1,
+ nullptr, &pipe));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoExtractMessagePipeFromInvitation(
+ invitation, "x", 1, &invalid_extract_options, &pipe));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoExtractMessagePipeFromInvitation(invitation, "x", 1, nullptr,
+ nullptr));
+
+ PlatformChannel channel;
+ MojoPlatformHandle endpoint_handle;
+ endpoint_handle.struct_size = sizeof(endpoint_handle);
+ PlatformHandleToMojoPlatformHandle(
+ channel.TakeLocalEndpoint().TakePlatformHandle(), &endpoint_handle);
+ ASSERT_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+
+ MojoInvitationTransportEndpoint valid_endpoint;
+ valid_endpoint.struct_size = sizeof(valid_endpoint);
+ valid_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+ valid_endpoint.num_platform_handles = 1;
+ valid_endpoint.platform_handles = &endpoint_handle;
+
+ MojoSendInvitationOptions invalid_send_options;
+ invalid_send_options.struct_size = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(MOJO_HANDLE_INVALID, nullptr, &valid_endpoint,
+ nullptr, 0, nullptr));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(invitation, nullptr, &valid_endpoint, nullptr, 0,
+ &invalid_send_options));
+
+ MojoInvitationTransportEndpoint invalid_endpoint;
+ invalid_endpoint.struct_size = 0;
+ invalid_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+ invalid_endpoint.num_platform_handles = 1;
+ invalid_endpoint.platform_handles = &endpoint_handle;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(invitation, nullptr, &invalid_endpoint, nullptr,
+ 0, nullptr));
+
+ invalid_endpoint.struct_size = sizeof(invalid_endpoint);
+ invalid_endpoint.num_platform_handles = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(invitation, nullptr, &invalid_endpoint, nullptr,
+ 0, nullptr));
+
+ MojoPlatformHandle invalid_platform_handle;
+ invalid_platform_handle.struct_size = 0;
+ invalid_endpoint.num_platform_handles = 1;
+ invalid_endpoint.platform_handles = &invalid_platform_handle;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(invitation, nullptr, &invalid_endpoint, nullptr,
+ 0, nullptr));
+ invalid_platform_handle.struct_size = sizeof(invalid_platform_handle);
+ invalid_platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(invitation, nullptr, &invalid_endpoint, nullptr,
+ 0, nullptr));
+
+ invalid_endpoint.num_platform_handles = 1;
+ invalid_endpoint.platform_handles = nullptr;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoSendInvitation(invitation, nullptr, &invalid_endpoint, nullptr,
+ 0, nullptr));
+
+ MojoHandle accepted_invitation;
+ MojoAcceptInvitationOptions invalid_accept_options;
+ invalid_accept_options.struct_size = 0;
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAcceptInvitation(nullptr, nullptr, &accepted_invitation));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAcceptInvitation(&valid_endpoint, &invalid_accept_options,
+ &accepted_invitation));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+ MojoAcceptInvitation(&valid_endpoint, nullptr, nullptr));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+}
+
+TEST_F(InvitationTest, AttachAndExtractLocally) {
+ MojoHandle invitation;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
+
+ MojoHandle pipe0 = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoAttachMessagePipeToInvitation(
+ invitation, "x", 1, nullptr, &pipe0));
+ EXPECT_NE(MOJO_HANDLE_INVALID, pipe0);
+
+ MojoHandle pipe1 = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoExtractMessagePipeFromInvitation(
+ invitation, "x", 1, nullptr, &pipe1));
+ EXPECT_NE(MOJO_HANDLE_INVALID, pipe1);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ // Should be able to communicate over the pipe.
+ const std::string kMessage = "RSVP LOL";
+ WriteMessage(pipe0, kMessage);
+ EXPECT_EQ(kMessage, ReadMessage(pipe1));
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe0));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe1));
+}
+
+TEST_F(InvitationTest, ClosedInvitationClosesAttachments) {
+ MojoHandle invitation;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
+
+ MojoHandle pipe = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoAttachMessagePipeToInvitation(
+ invitation, "x", 1, nullptr, &pipe));
+ EXPECT_NE(MOJO_HANDLE_INVALID, pipe);
+
+ // Closing the invitation should close |pipe|'s peer.
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe));
+}
+
+TEST_F(InvitationTest, AttachNameInUse) {
+ MojoHandle invitation;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
+
+ MojoHandle pipe0 = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_OK, MojoAttachMessagePipeToInvitation(
+ invitation, "x", 1, nullptr, &pipe0));
+ EXPECT_NE(MOJO_HANDLE_INVALID, pipe0);
+
+ MojoHandle pipe1 = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(
+ MOJO_RESULT_ALREADY_EXISTS,
+ MojoAttachMessagePipeToInvitation(invitation, "x", 1, nullptr, &pipe1));
+ EXPECT_EQ(MOJO_HANDLE_INVALID, pipe1);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoAttachMessagePipeToInvitation(
+ invitation, "y", 1, nullptr, &pipe1));
+ EXPECT_NE(MOJO_HANDLE_INVALID, pipe1);
+
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe0));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe1));
+}
+
+// static
+base::Process InvitationTest::LaunchChildTestClient(
+ const std::string& test_client_name,
+ MojoHandle* primordial_pipes,
+ size_t num_primordial_pipes,
+ TransportType transport_type,
+ MojoProcessErrorHandler error_handler,
+ uintptr_t error_handler_context) {
+ base::CommandLine command_line(
+ base::GetMultiProcessTestChildBaseCommandLine());
+
+ base::LaunchOptions launch_options;
+ base::Optional<PlatformChannel> channel;
+ base::Optional<NamedPlatformChannel> named_channel;
+ PlatformHandle local_endpoint_handle;
+ if (transport_type == TransportType::kChannel) {
+ channel.emplace();
+#if defined(OS_FUCHSIA)
+ channel->PrepareToPassRemoteEndpoint(&launch_options.handles_to_transfer,
+ &command_line);
+#elif defined(OS_POSIX)
+ channel->PrepareToPassRemoteEndpoint(&launch_options.fds_to_remap,
+ &command_line);
+#elif defined(OS_WIN)
+ launch_options.start_hidden = true;
+ channel->PrepareToPassRemoteEndpoint(&launch_options.handles_to_inherit,
+ &command_line);
+#else
+#error "Platform not yet supported."
+#endif
+ local_endpoint_handle = channel->TakeLocalEndpoint().TakePlatformHandle();
+ } else {
+#if defined(OS_FUCHSIA)
+ NOTREACHED() << "Named pipe support does not exist for Mojo on Fuchsia.";
+#else
+ NamedPlatformChannel::Options named_channel_options;
+#if !defined(OS_WIN)
+ CHECK(base::PathService::Get(base::DIR_TEMP,
+ &named_channel_options.socket_dir));
+#endif
+ named_channel.emplace(named_channel_options);
+ named_channel->PassServerNameOnCommandLine(&command_line);
+ local_endpoint_handle =
+ named_channel->TakeServerEndpoint().TakePlatformHandle();
+#endif
+ }
+
+ MojoPlatformHandle endpoint_handle;
+ PlatformHandleToMojoPlatformHandle(std::move(local_endpoint_handle),
+ &endpoint_handle);
+ CHECK_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+
+ MojoHandle invitation;
+ CHECK_EQ(MOJO_RESULT_OK, MojoCreateInvitation(nullptr, &invitation));
+ for (uint32_t name = 0; name < num_primordial_pipes; ++name) {
+ CHECK_EQ(MOJO_RESULT_OK,
+ MojoAttachMessagePipeToInvitation(invitation, &name, 4, nullptr,
+ &primordial_pipes[name]));
+ }
+
+ base::Process child_process = base::SpawnMultiProcessTestChild(
+ test_client_name, command_line, launch_options);
+ if (channel)
+ channel->RemoteProcessLaunched();
+
+ MojoPlatformProcessHandle process_handle;
+ process_handle.struct_size = sizeof(process_handle);
+#if defined(OS_WIN)
+ process_handle.value = static_cast<uint64_t>(
+ reinterpret_cast<uintptr_t>(child_process.Handle()));
+#else
+ process_handle.value = static_cast<uint64_t>(child_process.Handle());
+#endif
+
+ MojoInvitationTransportEndpoint transport_endpoint;
+ transport_endpoint.struct_size = sizeof(transport_endpoint);
+ if (transport_type == TransportType::kChannel)
+ transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+ else
+ transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER;
+ transport_endpoint.num_platform_handles = 1;
+ transport_endpoint.platform_handles = &endpoint_handle;
+ CHECK_EQ(MOJO_RESULT_OK,
+ MojoSendInvitation(invitation, &process_handle, &transport_endpoint,
+ error_handler, error_handler_context, nullptr));
+ return child_process;
+}
+
+class TestClientBase : public InvitationTest {
+ public:
+ static MojoHandle AcceptInvitation() {
+ const auto& command_line = *base::CommandLine::ForCurrentProcess();
+ PlatformChannelEndpoint channel_endpoint =
+ NamedPlatformChannel::ConnectToServer(command_line);
+ if (!channel_endpoint.is_valid()) {
+ channel_endpoint =
+ PlatformChannel::RecoverPassedEndpointFromCommandLine(command_line);
+ }
+ MojoPlatformHandle endpoint_handle;
+ PlatformHandleToMojoPlatformHandle(channel_endpoint.TakePlatformHandle(),
+ &endpoint_handle);
+ CHECK_NE(endpoint_handle.type, MOJO_PLATFORM_HANDLE_TYPE_INVALID);
+
+ MojoInvitationTransportEndpoint transport_endpoint;
+ transport_endpoint.struct_size = sizeof(transport_endpoint);
+ transport_endpoint.type = MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL;
+ transport_endpoint.num_platform_handles = 1;
+ transport_endpoint.platform_handles = &endpoint_handle;
+
+ MojoHandle invitation;
+ CHECK_EQ(MOJO_RESULT_OK,
+ MojoAcceptInvitation(&transport_endpoint, nullptr, &invitation));
+ return invitation;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestClientBase);
+};
+
+#define DEFINE_TEST_CLIENT(name) \
+ class name##Impl : public TestClientBase { \
+ public: \
+ static void Run(); \
+ }; \
+ MULTIPROCESS_TEST_MAIN(name) { \
+ name##Impl::Run(); \
+ return 0; \
+ } \
+ void name##Impl::Run()
+
+const std::string kTestMessage1 = "i am the pusher robot";
+const std::string kTestMessage2 = "i push the messages down the pipe";
+const std::string kTestMessage3 = "i am the shover robot";
+const std::string kTestMessage4 = "i shove the messages down the pipe";
+
+TEST_F(InvitationTest, SendInvitation) {
+ MojoHandle primordial_pipe;
+ base::Process child_process = LaunchChildTestClient(
+ "SendInvitationClient", &primordial_pipe, 1, TransportType::kChannel);
+
+ WriteMessage(primordial_pipe, kTestMessage1);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(kTestMessage3, ReadMessage(primordial_pipe));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(SendInvitationClient) {
+ MojoHandle primordial_pipe;
+ MojoHandle invitation = AcceptInvitation();
+ const uint32_t pipe_name = 0;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
+ nullptr, &primordial_pipe));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_EQ(kTestMessage1, ReadMessage(primordial_pipe));
+ WriteMessage(primordial_pipe, kTestMessage3);
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+}
+
+TEST_F(InvitationTest, SendInvitationMultiplePipes) {
+ MojoHandle pipes[2];
+ base::Process child_process = LaunchChildTestClient(
+ "SendInvitationMultiplePipesClient", pipes, 2, TransportType::kChannel);
+
+ WriteMessage(pipes[0], kTestMessage1);
+ WriteMessage(pipes[1], kTestMessage2);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(pipes[0], MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(pipes[1], MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(kTestMessage3, ReadMessage(pipes[0]));
+ EXPECT_EQ(kTestMessage4, ReadMessage(pipes[1]));
+
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(pipes[0]));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(pipes[1]));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(SendInvitationMultiplePipesClient) {
+ MojoHandle pipes[2];
+ MojoHandle invitation = AcceptInvitation();
+ const uint32_t pipe_names[] = {0, 1};
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_names[0], 4,
+ nullptr, &pipes[0]));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_names[1], 4,
+ nullptr, &pipes[1]));
+
+ WaitForSignals(pipes[0], MOJO_HANDLE_SIGNAL_READABLE);
+ WaitForSignals(pipes[1], MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_EQ(kTestMessage1, ReadMessage(pipes[0]));
+ ASSERT_EQ(kTestMessage2, ReadMessage(pipes[1]));
+ WriteMessage(pipes[0], kTestMessage3);
+ WriteMessage(pipes[1], kTestMessage4);
+ WaitForSignals(pipes[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ WaitForSignals(pipes[1], MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+}
+
+#if !defined(OS_FUCHSIA)
+TEST_F(InvitationTest, SendInvitationWithServer) {
+ MojoHandle primordial_pipe;
+ base::Process child_process =
+ LaunchChildTestClient("SendInvitationWithServerClient", &primordial_pipe,
+ 1, TransportType::kChannelServer);
+
+ WriteMessage(primordial_pipe, kTestMessage1);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE));
+ EXPECT_EQ(kTestMessage3, ReadMessage(primordial_pipe));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(SendInvitationWithServerClient) {
+ MojoHandle primordial_pipe;
+ MojoHandle invitation = AcceptInvitation();
+ const uint32_t pipe_name = 0;
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoExtractMessagePipeFromInvitation(invitation, &pipe_name, 4,
+ nullptr, &primordial_pipe));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ ASSERT_EQ(kTestMessage1, ReadMessage(primordial_pipe));
+ WriteMessage(primordial_pipe, kTestMessage3);
+ WaitForSignals(primordial_pipe, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(primordial_pipe));
+}
+#endif // !defined(OS_FUCHSIA)
+
+const char kErrorMessage[] = "ur bad :(";
+const char kDisconnectMessage[] = "go away plz";
+
+class RemoteProcessState {
+ public:
+ RemoteProcessState()
+ : callback_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
+ ~RemoteProcessState() = default;
+
+ bool disconnected() {
+ base::AutoLock lock(lock_);
+ return disconnected_;
+ }
+
+ void set_error_callback(base::RepeatingClosure callback) {
+ error_callback_ = std::move(callback);
+ }
+
+ void set_expected_error_message(const std::string& expected) {
+ expected_error_message_ = expected;
+ }
+
+ void NotifyError(const std::string& error_message, bool disconnected) {
+ base::AutoLock lock(lock_);
+ CHECK(!disconnected_);
+ EXPECT_NE(error_message.find(expected_error_message_), std::string::npos);
+ disconnected_ = disconnected;
+ ++call_count_;
+ if (error_callback_)
+ callback_task_runner_->PostTask(FROM_HERE, error_callback_);
+ }
+
+ private:
+ const scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
+
+ base::Lock lock_;
+ int call_count_ = 0;
+ bool disconnected_ = false;
+ std::string expected_error_message_;
+ base::RepeatingClosure error_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoteProcessState);
+};
+
+void TestProcessErrorHandler(uintptr_t context,
+ const MojoProcessErrorDetails* details) {
+ auto* state = reinterpret_cast<RemoteProcessState*>(context);
+ std::string error_message;
+ if (details->error_message) {
+ error_message =
+ std::string(details->error_message, details->error_message_length - 1);
+ }
+ state->NotifyError(error_message,
+ details->flags & MOJO_PROCESS_ERROR_FLAG_DISCONNECTED);
+}
+
+TEST_F(InvitationTest, ProcessErrors) {
+ RemoteProcessState process_state;
+ MojoHandle pipe;
+ base::Process child_process = LaunchChildTestClient(
+ "ProcessErrorsClient", &pipe, 1, TransportType::kChannel,
+ &TestProcessErrorHandler, reinterpret_cast<uintptr_t>(&process_state));
+
+ MojoMessageHandle message;
+ WaitForSignals(pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(pipe, nullptr, &message));
+
+ base::RunLoop error_loop;
+ process_state.set_error_callback(error_loop.QuitClosure());
+
+ // Report this message as "bad". This should cause the error handler to be
+ // invoked and the RunLoop to be quit.
+ process_state.set_expected_error_message(kErrorMessage);
+ EXPECT_EQ(MOJO_RESULT_OK,
+ MojoNotifyBadMessage(message, kErrorMessage, sizeof(kErrorMessage),
+ nullptr));
+ error_loop.Run();
+ EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
+
+ // Now tell the child it can exit, and wait for it to disconnect.
+ base::RunLoop disconnect_loop;
+ process_state.set_error_callback(disconnect_loop.QuitClosure());
+ process_state.set_expected_error_message(std::string());
+ WriteMessage(pipe, kDisconnectMessage);
+ disconnect_loop.Run();
+
+ EXPECT_TRUE(process_state.disconnected());
+
+ int wait_result = -1;
+ base::WaitForMultiprocessTestChildExit(
+ child_process, TestTimeouts::action_timeout(), &wait_result);
+ child_process.Close();
+ EXPECT_EQ(0, wait_result);
+}
+
+DEFINE_TEST_CLIENT(ProcessErrorsClient) {
+ MojoHandle pipe;
+ MojoHandle invitation = AcceptInvitation();
+ const uint32_t pipe_name = 0;
+ ASSERT_EQ(MOJO_RESULT_OK, MojoExtractMessagePipeFromInvitation(
+ invitation, &pipe_name, 4, nullptr, &pipe));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoClose(invitation));
+
+ // Send a message. Contents are irrelevant, the test process is just going to
+ // flag it as a bad.
+ WriteMessage(pipe, "doesn't matter");
+
+ // Wait for our goodbye before exiting.
+ WaitForSignals(pipe, MOJO_HANDLE_SIGNAL_READABLE);
+ EXPECT_EQ(kDisconnectMessage, ReadMessage(pipe));
+}
+
+} // namespace
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/mach_port_relay.cc b/chromium/mojo/edk/system/mach_port_relay.cc
index a9cc48029c9..b3380a86d29 100644
--- a/chromium/mojo/edk/system/mach_port_relay.cc
+++ b/chromium/mojo/edk/system/mach_port_relay.cc
@@ -65,22 +65,23 @@ void ReportChildError(ChildUMAError error) {
} // namespace
// static
-void MachPortRelay::ReceivePorts(std::vector<ScopedPlatformHandle>* handles) {
+void MachPortRelay::ReceivePorts(
+ std::vector<ScopedInternalPlatformHandle>* handles) {
DCHECK(handles);
for (auto& handle : *handles) {
- DCHECK(handle.get().type != PlatformHandle::Type::MACH);
- if (handle.get().type != PlatformHandle::Type::MACH_NAME)
+ DCHECK(handle.get().type != InternalPlatformHandle::Type::MACH);
+ if (handle.get().type != InternalPlatformHandle::Type::MACH_NAME)
continue;
- handle.get().type = PlatformHandle::Type::MACH;
+ handle.get().type = InternalPlatformHandle::Type::MACH;
// MACH_PORT_NULL doesn't need translation.
if (handle.get().port == MACH_PORT_NULL)
continue;
// TODO(wez): Wrapping handle.get().port in this way causes it to be
- // Free()d via mach_port_mod_refs() - should PlatformHandle also do
+ // Free()d via mach_port_mod_refs() - should InternalPlatformHandle also do
// that if the handle never reaches here, or should this code not be
// wrapping it?
base::mac::ScopedMachReceiveRight message_port(handle.get().port);
@@ -112,17 +113,17 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
DCHECK(message);
mach_port_t task_port = port_provider_->TaskForPid(process);
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
// Message should have handles, otherwise there's no point in calling this
// function.
DCHECK(!handles.empty());
for (auto& handle : handles) {
- DCHECK(handle.get().type != PlatformHandle::Type::MACH_NAME);
- if (handle.get().type != PlatformHandle::Type::MACH)
+ DCHECK(handle.get().type != InternalPlatformHandle::Type::MACH_NAME);
+ if (handle.get().type != InternalPlatformHandle::Type::MACH)
continue;
if (!handle.is_valid()) {
- handle.get().type = PlatformHandle::Type::MACH_NAME;
+ handle.get().type = InternalPlatformHandle::Type::MACH_NAME;
continue;
}
@@ -169,15 +170,15 @@ void MachPortRelay::SendPortsToProcess(Channel::Message* message,
ReportBrokerError(BrokerUMAError::SUCCESS);
handle.get().port = intermediate_port;
- handle.get().type = PlatformHandle::Type::MACH_NAME;
+ handle.get().type = InternalPlatformHandle::Type::MACH_NAME;
}
message->SetHandles(std::move(handles));
}
-void MachPortRelay::ExtractPort(ScopedPlatformHandle* handle,
+void MachPortRelay::ExtractPort(ScopedInternalPlatformHandle* handle,
base::ProcessHandle process) {
- DCHECK_EQ(handle->get().type, PlatformHandle::Type::MACH_NAME);
- handle->get().type = PlatformHandle::Type::MACH;
+ DCHECK_EQ(handle->get().type, InternalPlatformHandle::Type::MACH_NAME);
+ handle->get().type = InternalPlatformHandle::Type::MACH;
// No extraction necessary for MACH_PORT_NULL.
if (!handle->is_valid())
diff --git a/chromium/mojo/edk/system/mach_port_relay.h b/chromium/mojo/edk/system/mach_port_relay.h
index b24264452ec..b8d232f20c3 100644
--- a/chromium/mojo/edk/system/mach_port_relay.h
+++ b/chromium/mojo/edk/system/mach_port_relay.h
@@ -44,7 +44,7 @@ class MachPortRelay : public base::PortProvider::Observer {
//
// See SendPortsToProcess() for the definition of intermediate and final Mach
// ports.
- static void ReceivePorts(std::vector<ScopedPlatformHandle>* handles);
+ static void ReceivePorts(std::vector<ScopedInternalPlatformHandle>* handles);
explicit MachPortRelay(base::PortProvider* port_provider);
~MachPortRelay() override;
@@ -59,11 +59,12 @@ class MachPortRelay : public base::PortProvider::Observer {
void SendPortsToProcess(Channel::Message* message,
base::ProcessHandle process);
- // Given a PlatformHandle of Type::MACH_NAME, extracts the Mach port, and
- // updates the contents of the PlatformHandle to have Type::MACH and have the
- // actual Mach port. On failure, replaces the contents with Type::MACH and
- // MACH_PORT_NULL.
- void ExtractPort(ScopedPlatformHandle* handle, base::ProcessHandle process);
+ // Given a InternalPlatformHandle of Type::MACH_NAME, extracts the Mach port,
+ // and updates the contents of the InternalPlatformHandle to have Type::MACH
+ // and have the actual Mach port. On failure, replaces the contents with
+ // Type::MACH and MACH_PORT_NULL.
+ void ExtractPort(ScopedInternalPlatformHandle* handle,
+ base::ProcessHandle process);
// Observer interface.
void AddObserver(Observer* observer);
diff --git a/chromium/mojo/edk/system/mapping_table.cc b/chromium/mojo/edk/system/mapping_table.cc
deleted file mode 100644
index 4b28282ea58..00000000000
--- a/chromium/mojo/edk/system/mapping_table.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/edk/system/mapping_table.h"
-
-#include "base/logging.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
-#include "mojo/edk/system/configuration.h"
-
-namespace mojo {
-namespace edk {
-
-MappingTable::MappingTable() {
-}
-
-MappingTable::~MappingTable() {
- // This should usually not be reached (the only instance should be owned by
- // the singleton |Core|, which lives forever), except in tests.
-}
-
-MojoResult MappingTable::AddMapping(
- std::unique_ptr<PlatformSharedBufferMapping> mapping) {
- DCHECK(mapping);
-
- if (address_to_mapping_map_.size() >=
- GetConfiguration().max_mapping_table_size)
- return MOJO_RESULT_RESOURCE_EXHAUSTED;
-
- void* address = mapping->GetBase();
- DCHECK(address_to_mapping_map_.find(address) ==
- address_to_mapping_map_.end());
- address_to_mapping_map_[address] = mapping.release();
- return MOJO_RESULT_OK;
-}
-
-MojoResult MappingTable::RemoveMapping(
- void* address,
- std::unique_ptr<PlatformSharedBufferMapping>* mapping) {
- AddressToMappingMap::iterator it = address_to_mapping_map_.find(address);
- if (it == address_to_mapping_map_.end())
- return MOJO_RESULT_INVALID_ARGUMENT;
- mapping->reset(it->second);
- address_to_mapping_map_.erase(it);
- return MOJO_RESULT_OK;
-}
-
-} // namespace edk
-} // namespace mojo
diff --git a/chromium/mojo/edk/system/mapping_table.h b/chromium/mojo/edk/system/mapping_table.h
deleted file mode 100644
index a9498201977..00000000000
--- a/chromium/mojo/edk/system/mapping_table.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_EDK_SYSTEM_MAPPING_TABLE_H_
-#define MOJO_EDK_SYSTEM_MAPPING_TABLE_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "mojo/edk/system/system_impl_export.h"
-#include "mojo/public/c/system/types.h"
-
-namespace mojo {
-
-namespace edk {
-class Core;
-class PlatformSharedBufferMapping;
-
-// This class provides the (global) table of memory mappings (owned by |Core|),
-// which maps mapping base addresses to |PlatformSharedBufferMapping|s.
-//
-// This class is NOT thread-safe; locking is left to |Core|.
-class MOJO_SYSTEM_IMPL_EXPORT MappingTable {
- public:
- MappingTable();
- ~MappingTable();
-
- // Tries to add a mapping. (Takes ownership of the mapping in all cases; on
- // failure, it will be destroyed.)
- MojoResult AddMapping(std::unique_ptr<PlatformSharedBufferMapping> mapping);
- MojoResult RemoveMapping(
- void* address,
- std::unique_ptr<PlatformSharedBufferMapping>* mapping);
-
- private:
- using AddressToMappingMap =
- base::hash_map<void*, PlatformSharedBufferMapping*>;
- AddressToMappingMap address_to_mapping_map_;
-
- DISALLOW_COPY_AND_ASSIGN(MappingTable);
-};
-
-} // namespace edk
-} // namespace mojo
-
-#endif // MOJO_EDK_SYSTEM_MAPPING_TABLE_H_
diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.cc b/chromium/mojo/edk/system/message_pipe_dispatcher.cc
index a095ab4e497..219ad4ccab8 100644
--- a/chromium/mojo/edk/system/message_pipe_dispatcher.cc
+++ b/chromium/mojo/edk/system/message_pipe_dispatcher.cc
@@ -136,8 +136,7 @@ MojoResult MessagePipeDispatcher::Close() {
}
MojoResult MessagePipeDispatcher::WriteMessage(
- std::unique_ptr<ports::UserMessageEvent> message,
- MojoWriteMessageFlags flags) {
+ std::unique_ptr<ports::UserMessageEvent> message) {
if (port_closed_ || in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
@@ -224,9 +223,10 @@ void MessagePipeDispatcher::StartSerialize(uint32_t* num_bytes,
*num_handles = 0;
}
-bool MessagePipeDispatcher::EndSerialize(void* destination,
- ports::PortName* ports,
- ScopedPlatformHandle* handles) {
+bool MessagePipeDispatcher::EndSerialize(
+ void* destination,
+ ports::PortName* ports,
+ ScopedInternalPlatformHandle* handles) {
SerializedState* state = static_cast<SerializedState*>(destination);
state->pipe_id = pipe_id_;
state->endpoint = static_cast<int8_t>(endpoint_);
@@ -266,7 +266,7 @@ scoped_refptr<Dispatcher> MessagePipeDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles) {
if (num_ports != 1 || num_handles || num_bytes != sizeof(SerializedState))
return nullptr;
diff --git a/chromium/mojo/edk/system/message_pipe_dispatcher.h b/chromium/mojo/edk/system/message_pipe_dispatcher.h
index 141e8450996..64ad3d70a05 100644
--- a/chromium/mojo/edk/system/message_pipe_dispatcher.h
+++ b/chromium/mojo/edk/system/message_pipe_dispatcher.h
@@ -47,8 +47,8 @@ class MessagePipeDispatcher : public Dispatcher {
// Dispatcher:
Type GetType() const override;
MojoResult Close() override;
- MojoResult WriteMessage(std::unique_ptr<ports::UserMessageEvent> message,
- MojoWriteMessageFlags flags) override;
+ MojoResult WriteMessage(
+ std::unique_ptr<ports::UserMessageEvent> message) override;
MojoResult ReadMessage(
std::unique_ptr<ports::UserMessageEvent>* message) override;
HandleSignalsState GetHandleSignalsState() const override;
@@ -61,17 +61,18 @@ class MessagePipeDispatcher : public Dispatcher {
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles) override;
+ ScopedInternalPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
- static scoped_refptr<Dispatcher> Deserialize(const void* data,
- size_t num_bytes,
- const ports::PortName* ports,
- size_t num_ports,
- ScopedPlatformHandle* handles,
- size_t num_handles);
+ static scoped_refptr<Dispatcher> Deserialize(
+ const void* data,
+ size_t num_bytes,
+ const ports::PortName* ports,
+ size_t num_ports,
+ ScopedInternalPlatformHandle* handles,
+ size_t num_handles);
private:
class PortObserverThunk;
diff --git a/chromium/mojo/edk/system/message_pipe_unittest.cc b/chromium/mojo/edk/system/message_pipe_unittest.cc
index 6ec0bfb077d..2cdc58edd3a 100644
--- a/chromium/mojo/edk/system/message_pipe_unittest.cc
+++ b/chromium/mojo/edk/system/message_pipe_unittest.cc
@@ -54,8 +54,8 @@ class MessagePipeTest : public test::MojoTestBase {
uint32_t* num_bytes,
bool may_discard = false) {
MojoMessageHandle message_handle;
- MojoResult rv = MojoReadMessage(message_pipe_handle, &message_handle,
- MOJO_READ_MESSAGE_FLAG_NONE);
+ MojoResult rv =
+ MojoReadMessage(message_pipe_handle, nullptr, &message_handle);
if (rv != MOJO_RESULT_OK)
return rv;
@@ -318,7 +318,7 @@ TEST_F(MessagePipeTest, BasicWaiting) {
#if !defined(OS_IOS)
-const size_t kPingPongHandlesPerIteration = 50;
+const size_t kPingPongHandlesPerIteration = 30;
const size_t kPingPongIterations = 500;
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(HandlePingPong, MessagePipeTest, h) {
@@ -376,7 +376,7 @@ TEST_F(MessagePipeTest, DISABLED_DataPipeProducerHandlePingPong) {
TEST_F(MessagePipeTest, SharedBufferHandlePingPong) {
MojoHandle buffers[kPingPongHandlesPerIteration];
for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
- EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 1, &buffers[i]));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(1, nullptr, &buffers[i]));
RunTestClient("HandlePingPong", [&](MojoHandle h) {
for (size_t i = 0; i < kPingPongIterations; i++) {
@@ -398,7 +398,7 @@ TEST_F(FuseMessagePipeTest, Basic) {
CreateMessagePipe(&a, &b);
CreateMessagePipe(&c, &d);
- EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
// Handles b and c should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
@@ -429,7 +429,7 @@ TEST_F(FuseMessagePipeTest, FuseAfterPeerWrite) {
WriteMessage(a, kTestMessage1);
WriteMessage(d, kTestMessage2);
- EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
// Handles b and c should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
@@ -450,7 +450,8 @@ TEST_F(FuseMessagePipeTest, NoFuseAfterWrite) {
CreateMessagePipe(&c, &d);
WriteMessage(b, "shouldn't have done that!");
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, MojoFuseMessagePipes(b, c));
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoFuseMessagePipes(b, c, nullptr));
// Handles b and c should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
@@ -466,7 +467,8 @@ TEST_F(FuseMessagePipeTest, NoFuseSelf) {
MojoHandle a, b;
CreateMessagePipe(&a, &b);
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, MojoFuseMessagePipes(a, b));
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ MojoFuseMessagePipes(a, b, nullptr));
// Handles a and b should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(a));
@@ -481,7 +483,7 @@ TEST_F(FuseMessagePipeTest, FuseInvalidArguments) {
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
// Can't fuse an invalid handle.
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(b, c));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(b, c, nullptr));
// Handle c should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
@@ -490,7 +492,7 @@ TEST_F(FuseMessagePipeTest, FuseInvalidArguments) {
MojoHandle e, f;
CreateDataPipe(&e, &f, 16);
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(e, d));
+ EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(e, d, nullptr));
// Handles d and e should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(d));
@@ -508,7 +510,7 @@ TEST_F(FuseMessagePipeTest, FuseAfterPeerClosure) {
CreateMessagePipe(&c, &d);
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
// Handles b and c should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
@@ -530,7 +532,7 @@ TEST_F(FuseMessagePipeTest, FuseAfterPeerWriteAndClosure) {
WriteMessage(a, kTestMessage);
EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
- EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
// Handles b and c should be closed.
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
diff --git a/chromium/mojo/edk/system/message_unittest.cc b/chromium/mojo/edk/system/message_unittest.cc
index 8a3df875e8a..b493bad3166 100644
--- a/chromium/mojo/edk/system/message_unittest.cc
+++ b/chromium/mojo/edk/system/message_unittest.cc
@@ -193,15 +193,14 @@ TEST_F(MessageTest, SendLocalMessageWithContext) {
MojoHandle a, b;
CreateMessagePipe(&a, &b);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(
- a, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoWriteMessage(
+ a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
MojoMessageHandle read_message_handle;
- EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, &read_message_handle,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &read_message_handle));
message = TestMessageBase::UnwrapMessageHandle<NeverSerializedMessage>(
&read_message_handle);
EXPECT_EQ(original_message, message.get());
@@ -240,7 +239,7 @@ TEST_F(MessageTest, SerializeSimpleMessageNoHandlesWithContext) {
RunTestClient("ReceiveMessageNoHandles", [&](MojoHandle h) {
auto message = std::make_unique<SimpleMessage>(kTestMessageWithContext1);
MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE);
+ nullptr);
});
}
@@ -264,7 +263,7 @@ TEST_F(MessageTest, SerializeDynamicallySizedMessage) {
memcpy(buffer, kTestMessageWithContext1,
sizeof(kTestMessageWithContext1) - 1);
- MojoWriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE);
+ MojoWriteMessage(h, message, nullptr);
});
}
@@ -282,7 +281,7 @@ TEST_F(MessageTest, SerializeSimpleMessageOneHandleWithContext) {
mojo::MessagePipe pipe;
message->AddMessagePipe(std::move(pipe.handle0));
MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE);
+ nullptr);
EXPECT_EQ(kTestMessageWithContext2,
MojoTestBase::ReadMessage(pipe.handle1.get().value()));
});
@@ -308,7 +307,7 @@ TEST_F(MessageTest, SerializeSimpleMessageWithHandlesWithContext) {
message->AddMessagePipe(std::move(pipes[2].handle0));
message->AddMessagePipe(std::move(pipes[3].handle0));
MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE);
+ nullptr);
EXPECT_EQ(kTestMessageWithContext1,
MojoTestBase::ReadMessage(pipes[0].handle1.get().value()));
EXPECT_EQ(kTestMessageWithContext2,
@@ -337,15 +336,14 @@ TEST_F(MessageTest, SendLocalSimpleMessageWithHandlesWithContext) {
MojoHandle a, b;
CreateMessagePipe(&a, &b);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(
- a, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoWriteMessage(
+ a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
MojoMessageHandle read_message_handle;
- EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, &read_message_handle,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &read_message_handle));
message =
TestMessageBase::UnwrapMessageHandle<SimpleMessage>(&read_message_handle);
EXPECT_EQ(original_message, message.get());
@@ -373,10 +371,10 @@ TEST_F(MessageTest, DropUnreadLocalMessageWithContext) {
message->AddMessagePipe(std::move(pipe.handle0));
MojoHandle a, b;
CreateMessagePipe(&a, &b);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(
- a, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoWriteMessage(
+ a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
MojoClose(a);
MojoClose(b);
@@ -441,15 +439,14 @@ TEST_F(MessageTest, ReadMessageWithContextAsSerializedMessage) {
MojoHandle a, b;
CreateMessagePipe(&a, &b);
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(
- a, TestMessageBase::MakeMessageHandle(std::move(message)),
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoWriteMessage(
+ a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
MojoMessageHandle message_handle;
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(b, &message_handle, MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &message_handle));
EXPECT_FALSE(message_was_destroyed);
// Not a serialized message, so we can't get serialized contents.
@@ -475,8 +472,7 @@ TEST_F(MessageTest, ReadSerializedMessageAsMessageWithContext) {
EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
MojoMessageHandle message_handle;
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(b, &message_handle, MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &message_handle));
uintptr_t context;
EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
MojoGetMessageContext(message_handle, nullptr, &context));
@@ -569,13 +565,11 @@ TEST_F(MessageTest, DoubleSerialize) {
// message object from a pipe.
MessagePipe pipe;
EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(pipe.handle0->value(), message_handle,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ MojoWriteMessage(pipe.handle0->value(), message_handle, nullptr));
EXPECT_EQ(MOJO_RESULT_OK,
WaitForSignals(pipe.handle1->value(), MOJO_HANDLE_SIGNAL_READABLE));
EXPECT_EQ(MOJO_RESULT_OK,
- MojoReadMessage(pipe.handle1->value(), &message_handle,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ MojoReadMessage(pipe.handle1->value(), nullptr, &message_handle));
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
MojoSerializeMessage(message_handle, nullptr));
@@ -822,9 +816,9 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttached) {
MojoHandle handles[5];
CreateMessagePipe(&handles[0], &handles[1]);
PlatformChannelPair channel;
- ASSERT_EQ(MOJO_RESULT_OK, CreatePlatformHandleWrapper(
+ ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
channel.PassServerHandle(), &handles[2]));
- ASSERT_EQ(MOJO_RESULT_OK, CreatePlatformHandleWrapper(
+ ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
channel.PassClientHandle(), &handles[3]));
handles[4] = SharedBufferHandle::Create(64).release().value();
@@ -854,8 +848,7 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttached) {
// Send the message out of process to exercise the regression path where
// internally cached, stale payload pointers may be dereferenced and written
// into.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, message, nullptr));
});
}
@@ -872,9 +865,9 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttachedViaExtension) {
MojoHandle handles[5];
CreateMessagePipe(&handles[0], &handles[4]);
PlatformChannelPair channel;
- ASSERT_EQ(MOJO_RESULT_OK, CreatePlatformHandleWrapper(
+ ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
channel.PassServerHandle(), &handles[1]));
- ASSERT_EQ(MOJO_RESULT_OK, CreatePlatformHandleWrapper(
+ ASSERT_EQ(MOJO_RESULT_OK, CreateInternalPlatformHandleWrapper(
channel.PassClientHandle(), &handles[2]));
handles[3] = SharedBufferHandle::Create(64).release().value();
@@ -904,8 +897,7 @@ TEST_F(MessageTest, ExtendPayloadWithHandlesAttachedViaExtension) {
// Send the message out of process to exercise the regression path where
// internally cached, stale payload pointers may be dereferenced and written
// into.
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoWriteMessage(h, message, MOJO_WRITE_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, message, nullptr));
});
}
diff --git a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
index c9a00de91d3..946a21a53b2 100644
--- a/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ b/chromium/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -284,9 +284,7 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer,
// Make a mapping.
void* buffer;
- CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer,
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE),
- MOJO_RESULT_OK);
+ CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, nullptr, &buffer), MOJO_RESULT_OK);
// Write some stuff to the shared buffer.
static const char kHello[] = "hello";
@@ -333,16 +331,16 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) {
// Make a shared buffer.
MojoCreateSharedBufferOptions options;
options.struct_size = sizeof(options);
- options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
MojoHandle shared_buffer;
ASSERT_EQ(MOJO_RESULT_OK,
- MojoCreateSharedBuffer(&options, 100, &shared_buffer));
+ MojoCreateSharedBuffer(100, &options, &shared_buffer));
MojoSharedBufferInfo buffer_info;
buffer_info.struct_size = sizeof(buffer_info);
ASSERT_EQ(MOJO_RESULT_OK,
MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info));
- EXPECT_EQ(100U, buffer_info.size);
+ EXPECT_GE(buffer_info.size, 100U);
// Send the shared buffer.
const std::string go1("go 1");
@@ -354,7 +352,7 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) {
buffer_info.size = 0;
ASSERT_EQ(MOJO_RESULT_OK,
MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info));
- EXPECT_EQ(100U, buffer_info.size);
+ EXPECT_GE(buffer_info.size, 100U);
MojoHandle handles[1];
handles[0] = duplicated_shared_buffer;
ASSERT_EQ(MOJO_RESULT_OK,
@@ -381,8 +379,7 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) {
// buffer.
static const char kHello[] = "hello";
void* buffer;
- CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer,
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE),
+ CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, nullptr, &buffer),
MOJO_RESULT_OK);
ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello)));
@@ -405,7 +402,7 @@ TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) {
});
}
-DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile,
+DEFINE_TEST_CLIENT_WITH_PIPE(CheckInternalPlatformHandleFile,
MultiprocessMessagePipeTest,
h) {
HandleSignalsState hss;
@@ -434,12 +431,13 @@ DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile,
CHECK_GT(num_handles, 0);
for (int i = 0; i < num_handles; ++i) {
- ScopedPlatformHandle h;
- CHECK_EQ(PassWrappedPlatformHandle(handles[i], &h), MOJO_RESULT_OK);
+ ScopedInternalPlatformHandle h;
+ CHECK_EQ(PassWrappedInternalPlatformHandle(handles[i], &h), MOJO_RESULT_OK);
CHECK(h.is_valid());
MojoClose(handles[i]);
- base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h), "r"));
+ base::ScopedFILE fp(
+ test::FILEFromInternalPlatformHandle(std::move(h), "r"));
CHECK(fp);
std::string fread_buffer(100, '\0');
size_t bytes_read =
@@ -455,11 +453,12 @@ class MultiprocessMessagePipeTestWithPipeCount
: public MultiprocessMessagePipeTest,
public testing::WithParamInterface<size_t> {};
-TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
+TEST_P(MultiprocessMessagePipeTestWithPipeCount,
+ InternalPlatformHandlePassing) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- RunTestClient("CheckPlatformHandleFile", [&](MojoHandle h) {
+ RunTestClient("CheckInternalPlatformHandleFile", [&](MojoHandle h) {
std::vector<MojoHandle> handles;
size_t pipe_count = GetParam();
@@ -472,11 +471,11 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
fflush(fp.get());
rewind(fp.get());
MojoHandle handle;
- ASSERT_EQ(
- CreatePlatformHandleWrapper(
- ScopedPlatformHandle(test::PlatformHandleFromFILE(std::move(fp))),
- &handle),
- MOJO_RESULT_OK);
+ ASSERT_EQ(CreateInternalPlatformHandleWrapper(
+ ScopedInternalPlatformHandle(
+ test::InternalPlatformHandleFromFILE(std::move(fp))),
+ &handle),
+ MOJO_RESULT_OK);
handles.push_back(handle);
}
@@ -561,7 +560,7 @@ TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipePassing) {
RunTestClient("CheckMessagePipe", [&](MojoHandle h) {
MojoCreateSharedBufferOptions options;
options.struct_size = sizeof(options);
- options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
MojoHandle mp1, mp2;
ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp1, &mp2));
@@ -679,7 +678,7 @@ TEST_F(MultiprocessMessagePipeTest, DataPipeConsumer) {
RunTestClient("DataPipeConsumer", [&](MojoHandle h) {
MojoCreateSharedBufferOptions options;
options.struct_size = sizeof(options);
- options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
+ options.flags = MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
MojoHandle mp1, mp2;
ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp1));
@@ -1374,20 +1373,21 @@ TEST_F(MultiprocessMessagePipeTest, NotifyBadMessage) {
// Read a message from the pipe we sent to child1 and flag it as bad.
ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_READABLE));
MojoMessageHandle message;
- ASSERT_EQ(MOJO_RESULT_OK,
- ::MojoReadMessage(a, &message, MOJO_READ_MESSAGE_FLAG_NONE));
+ ASSERT_EQ(MOJO_RESULT_OK, ::MojoReadMessage(a, nullptr, &message));
EXPECT_EQ(MOJO_RESULT_OK,
- MojoNotifyBadMessage(message, kFirstErrorMessage.data(),
- kFirstErrorMessage.size()));
+ MojoNotifyBadMessage(
+ message, kFirstErrorMessage.data(),
+ static_cast<uint32_t>(kFirstErrorMessage.size()), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
// Read a message from the pipe we sent to child2 and flag it as bad.
ASSERT_EQ(MOJO_RESULT_OK, WaitForSignals(c, MOJO_HANDLE_SIGNAL_READABLE));
- ASSERT_EQ(MOJO_RESULT_OK,
- ::MojoReadMessage(c, &message, MOJO_READ_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_OK,
- MojoNotifyBadMessage(message, kSecondErrorMessage.data(),
- kSecondErrorMessage.size()));
+ ASSERT_EQ(MOJO_RESULT_OK, ::MojoReadMessage(c, nullptr, &message));
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ MojoNotifyBadMessage(
+ message, kSecondErrorMessage.data(),
+ static_cast<uint32_t>(kSecondErrorMessage.size()), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
WriteMessage(child2, "bye");
diff --git a/chromium/mojo/edk/system/node_channel.cc b/chromium/mojo/edk/system/node_channel.cc
index 70312f5d322..f2e4ade4298 100644
--- a/chromium/mojo/edk/system/node_channel.cc
+++ b/chromium/mojo/edk/system/node_channel.cc
@@ -232,41 +232,24 @@ void NodeChannel::NotifyBadMessage(const std::string& error) {
process_error_callback_.Run("Received bad user message: " + error);
}
-void NodeChannel::SetRemoteProcessHandle(base::ProcessHandle process_handle) {
+void NodeChannel::SetRemoteProcessHandle(ScopedProcessHandle process_handle) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
base::AutoLock lock(remote_process_handle_lock_);
- DCHECK_EQ(base::kNullProcessHandle, remote_process_handle_);
- CHECK_NE(remote_process_handle_, base::GetCurrentProcessHandle());
- remote_process_handle_ = process_handle;
-#if defined(OS_WIN)
- DCHECK(!scoped_remote_process_handle_.is_valid());
- scoped_remote_process_handle_.reset(PlatformHandle(process_handle));
-#endif
+ DCHECK(!remote_process_handle_.is_valid());
+ CHECK_NE(remote_process_handle_.get(), base::GetCurrentProcessHandle());
+ remote_process_handle_ = std::move(process_handle);
}
bool NodeChannel::HasRemoteProcessHandle() {
base::AutoLock lock(remote_process_handle_lock_);
- return remote_process_handle_ != base::kNullProcessHandle;
+ return remote_process_handle_.is_valid();
}
-base::ProcessHandle NodeChannel::CopyRemoteProcessHandle() {
+ScopedProcessHandle NodeChannel::CloneRemoteProcessHandle() {
base::AutoLock lock(remote_process_handle_lock_);
-#if defined(OS_WIN)
- if (remote_process_handle_ != base::kNullProcessHandle) {
- // Privileged nodes use this to pass their invitees' process handles to the
- // broker on launch.
- HANDLE handle = remote_process_handle_;
- BOOL result = DuplicateHandle(
- base::GetCurrentProcessHandle(), remote_process_handle_,
- base::GetCurrentProcessHandle(), &handle, 0, FALSE,
- DUPLICATE_SAME_ACCESS);
- DPCHECK(result);
- return handle;
- }
- return base::kNullProcessHandle;
-#else
- return remote_process_handle_;
-#endif
+ if (!remote_process_handle_.is_valid())
+ return ScopedProcessHandle();
+ return remote_process_handle_.Clone();
}
void NodeChannel::SetRemoteNodeName(const ports::NodeName& name) {
@@ -307,11 +290,12 @@ void NodeChannel::AcceptPeer(const ports::NodeName& sender_name,
}
void NodeChannel::AddBrokerClient(const ports::NodeName& client_name,
- base::ProcessHandle process_handle) {
+ ScopedProcessHandle process_handle) {
AddBrokerClientData* data;
- std::vector<ScopedPlatformHandle> handles;
+ std::vector<ScopedInternalPlatformHandle> handles;
#if defined(OS_WIN)
- handles.emplace_back(ScopedPlatformHandle(PlatformHandle(process_handle)));
+ handles.emplace_back(ScopedInternalPlatformHandle(
+ InternalPlatformHandle(process_handle.release())));
#endif
Channel::MessagePtr message =
CreateMessage(MessageType::ADD_BROKER_CLIENT, sizeof(AddBrokerClientData),
@@ -319,16 +303,17 @@ void NodeChannel::AddBrokerClient(const ports::NodeName& client_name,
message->SetHandles(std::move(handles));
data->client_name = client_name;
#if !defined(OS_WIN)
- data->process_handle = process_handle;
+ data->process_handle = process_handle.get();
data->padding = 0;
#endif
WriteChannelMessage(std::move(message));
}
-void NodeChannel::BrokerClientAdded(const ports::NodeName& client_name,
- ScopedPlatformHandle broker_channel) {
+void NodeChannel::BrokerClientAdded(
+ const ports::NodeName& client_name,
+ ScopedInternalPlatformHandle broker_channel) {
BrokerClientAddedData* data;
- std::vector<ScopedPlatformHandle> handles;
+ std::vector<ScopedInternalPlatformHandle> handles;
if (broker_channel.is_valid())
handles.push_back(std::move(broker_channel));
Channel::MessagePtr message =
@@ -339,10 +324,11 @@ void NodeChannel::BrokerClientAdded(const ports::NodeName& client_name,
WriteChannelMessage(std::move(message));
}
-void NodeChannel::AcceptBrokerClient(const ports::NodeName& broker_name,
- ScopedPlatformHandle broker_channel) {
+void NodeChannel::AcceptBrokerClient(
+ const ports::NodeName& broker_name,
+ ScopedInternalPlatformHandle broker_channel) {
AcceptBrokerClientData* data;
- std::vector<ScopedPlatformHandle> handles;
+ std::vector<ScopedInternalPlatformHandle> handles;
if (broker_channel.is_valid())
handles.push_back(std::move(broker_channel));
Channel::MessagePtr message =
@@ -373,9 +359,9 @@ void NodeChannel::RequestIntroduction(const ports::NodeName& name) {
}
void NodeChannel::Introduce(const ports::NodeName& name,
- ScopedPlatformHandle channel_handle) {
+ ScopedInternalPlatformHandle channel_handle) {
IntroductionData* data;
- std::vector<ScopedPlatformHandle> handles;
+ std::vector<ScopedInternalPlatformHandle> handles;
if (channel_handle.is_valid())
handles.push_back(std::move(channel_handle));
Channel::MessagePtr message = CreateMessage(
@@ -423,7 +409,7 @@ void NodeChannel::RelayEventMessage(const ports::NodeName& destination,
// above stated assumption. We should not leak handles in cases where we
// outlive the broker, as we may continue existing and eventually accept a new
// broker invitation.
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
for (auto& handle : handles)
ignore_result(handle.release());
@@ -435,7 +421,7 @@ void NodeChannel::RelayEventMessage(const ports::NodeName& destination,
// moves them back to the relayed message. This is necessary because the
// message may contain fds which need to be attached to the outer message so
// that they can be transferred to the broker.
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
size_t num_bytes = sizeof(RelayEventMessageData) + message->data_num_bytes();
RelayEventMessageData* data;
Channel::MessagePtr relay_message = CreateMessage(
@@ -483,9 +469,10 @@ NodeChannel::~NodeChannel() {
ShutDown();
}
-void NodeChannel::OnChannelMessage(const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) {
+void NodeChannel::OnChannelMessage(
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
RequestContext request_context(RequestContext::Source::SYSTEM);
@@ -501,14 +488,13 @@ void NodeChannel::OnChannelMessage(const void* payload,
// from a privileged descendant.
{
base::AutoLock lock(remote_process_handle_lock_);
- if (!handles.empty() &&
- remote_process_handle_ != base::kNullProcessHandle) {
+ if (!handles.empty() && remote_process_handle_.is_valid()) {
// Note that we explicitly mark the handles as being owned by the sending
// process before rewriting them, in order to accommodate RewriteHandles'
// internal sanity checks.
for (auto& handle : handles)
- handle.get().owning_process = remote_process_handle_;
- if (!Channel::Message::RewriteHandles(remote_process_handle_,
+ handle.get().owning_process = remote_process_handle_.get();
+ if (!Channel::Message::RewriteHandles(remote_process_handle_.get(),
base::GetCurrentProcessHandle(),
&handles)) {
DLOG(ERROR) << "Received one or more invalid handles.";
@@ -598,7 +584,7 @@ void NodeChannel::OnChannelMessage(const void* payload,
case MessageType::ACCEPT_BROKER_CLIENT: {
const AcceptBrokerClientData* data;
if (GetMessagePayload(payload, payload_size, &data)) {
- ScopedPlatformHandle broker_channel;
+ ScopedInternalPlatformHandle broker_channel;
if (handles.size() > 1) {
DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message.";
break;
@@ -653,7 +639,7 @@ void NodeChannel::OnChannelMessage(const void* payload,
DLOG(ERROR) << "Dropping invalid introduction message.";
break;
}
- ScopedPlatformHandle channel_handle;
+ ScopedInternalPlatformHandle channel_handle;
if (handles.size() == 1) {
channel_handle = std::move(handles.at(0));
}
@@ -669,7 +655,10 @@ void NodeChannel::OnChannelMessage(const void* payload,
base::ProcessHandle from_process;
{
base::AutoLock lock(remote_process_handle_lock_);
- from_process = remote_process_handle_;
+ // NOTE: It's safe to retain a weak reference to this process handle
+ // through the extent of this call because |this| is kept alive and
+ // |remote_process_handle_| is never reset once set.
+ from_process = remote_process_handle_.get();
}
const RelayEventMessageData* data;
if (GetMessagePayload(payload, payload_size, &data)) {
@@ -800,7 +789,7 @@ void NodeChannel::ProcessPendingMessagesWithMachPorts() {
base::ProcessHandle remote_process_handle;
{
base::AutoLock lock(remote_process_handle_lock_);
- remote_process_handle = remote_process_handle_;
+ remote_process_handle = remote_process_handle_.get();
}
PendingMessageQueue pending_writes;
PendingRelayMessageQueue pending_relays;
@@ -846,17 +835,15 @@ void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) {
// here (they'll be unpacked and duplicated by the broker).
if (message->has_handles()) {
- base::ProcessHandle remote_process_handle;
- {
- base::AutoLock lock(remote_process_handle_lock_);
- remote_process_handle = remote_process_handle_;
- }
+ base::AutoLock lock(remote_process_handle_lock_);
// Rewrite outgoing handles if we have a handle to the destination process.
- if (remote_process_handle != base::kNullProcessHandle) {
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ if (remote_process_handle_.is_valid()) {
+ std::vector<ScopedInternalPlatformHandle> handles =
+ message->TakeHandles();
if (!Channel::Message::RewriteHandles(base::GetCurrentProcessHandle(),
- remote_process_handle, &handles)) {
+ remote_process_handle_.get(),
+ &handles)) {
DLOG(ERROR) << "Failed to duplicate one or more outgoing handles.";
}
message->SetHandles(std::move(handles));
@@ -868,16 +855,11 @@ void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) {
if (message->has_mach_ports()) {
MachPortRelay* relay = delegate_->GetMachPortRelay();
if (relay) {
- base::ProcessHandle remote_process_handle;
- {
- base::AutoLock lock(remote_process_handle_lock_);
- // Expect that the receiving node is a known process.
- DCHECK(remote_process_handle_ != base::kNullProcessHandle);
- remote_process_handle = remote_process_handle_;
- }
+ base::AutoLock lock(remote_process_handle_lock_);
+ DCHECK(remote_process_handle_.is_valid());
{
base::AutoLock lock(pending_mach_messages_lock_);
- if (relay->port_provider()->TaskForPid(remote_process_handle) ==
+ if (relay->port_provider()->TaskForPid(remote_process_handle_.get()) ==
MACH_PORT_NULL) {
// It is also possible for TaskForPid() to return MACH_PORT_NULL when
// the process has started, then died. In that case, the queued
@@ -888,7 +870,7 @@ void NodeChannel::WriteChannelMessage(Channel::MessagePtr message) {
}
}
- relay->SendPortsToProcess(message.get(), remote_process_handle);
+ relay->SendPortsToProcess(message.get(), remote_process_handle_.get());
}
}
#endif
diff --git a/chromium/mojo/edk/system/node_channel.h b/chromium/mojo/edk/system/node_channel.h
index 864ed1c45bf..95fd6ed6410 100644
--- a/chromium/mojo/edk/system/node_channel.h
+++ b/chromium/mojo/edk/system/node_channel.h
@@ -21,6 +21,7 @@
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/ports/name.h"
+#include "mojo/edk/system/scoped_process_handle.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "mojo/edk/system/mach_port_relay.h"
@@ -49,12 +50,14 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
virtual void OnAddBrokerClient(const ports::NodeName& from_node,
const ports::NodeName& client_name,
base::ProcessHandle process_handle) = 0;
- virtual void OnBrokerClientAdded(const ports::NodeName& from_node,
- const ports::NodeName& client_name,
- ScopedPlatformHandle broker_channel) = 0;
- virtual void OnAcceptBrokerClient(const ports::NodeName& from_node,
- const ports::NodeName& broker_name,
- ScopedPlatformHandle broker_channel) = 0;
+ virtual void OnBrokerClientAdded(
+ const ports::NodeName& from_node,
+ const ports::NodeName& client_name,
+ ScopedInternalPlatformHandle broker_channel) = 0;
+ virtual void OnAcceptBrokerClient(
+ const ports::NodeName& from_node,
+ const ports::NodeName& broker_name,
+ ScopedInternalPlatformHandle broker_channel) = 0;
virtual void OnEventMessage(const ports::NodeName& from_node,
Channel::MessagePtr message) = 0;
virtual void OnRequestPortMerge(const ports::NodeName& from_node,
@@ -64,7 +67,7 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
const ports::NodeName& name) = 0;
virtual void OnIntroduce(const ports::NodeName& from_node,
const ports::NodeName& name,
- ScopedPlatformHandle channel_handle) = 0;
+ ScopedInternalPlatformHandle channel_handle) = 0;
virtual void OnBroadcast(const ports::NodeName& from_node,
Channel::MessagePtr message) = 0;
#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
@@ -115,12 +118,9 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
// Invokes the bad message callback for this channel, if any.
void NotifyBadMessage(const std::string& error);
- // Note: On Windows, we take ownership of the remote process handle.
- void SetRemoteProcessHandle(base::ProcessHandle process_handle);
+ void SetRemoteProcessHandle(ScopedProcessHandle process_handle);
bool HasRemoteProcessHandle();
- // Note: The returned |ProcessHandle| is owned by the caller and should be
- // freed if necessary.
- base::ProcessHandle CopyRemoteProcessHandle();
+ ScopedProcessHandle CloneRemoteProcessHandle();
// Used for context in Delegate calls (via |from_node| arguments.)
void SetRemoteNodeName(const ports::NodeName& name);
@@ -133,16 +133,16 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
const ports::NodeName& token,
const ports::PortName& port_name);
void AddBrokerClient(const ports::NodeName& client_name,
- base::ProcessHandle process_handle);
+ ScopedProcessHandle process_handle);
void BrokerClientAdded(const ports::NodeName& client_name,
- ScopedPlatformHandle broker_channel);
+ ScopedInternalPlatformHandle broker_channel);
void AcceptBrokerClient(const ports::NodeName& broker_name,
- ScopedPlatformHandle broker_channel);
+ ScopedInternalPlatformHandle broker_channel);
void RequestPortMerge(const ports::PortName& connector_port_name,
const std::string& token);
void RequestIntroduction(const ports::NodeName& name);
void Introduce(const ports::NodeName& name,
- ScopedPlatformHandle channel_handle);
+ ScopedInternalPlatformHandle channel_handle);
void SendChannelMessage(Channel::MessagePtr message);
void Broadcast(Channel::MessagePtr message);
@@ -175,9 +175,10 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
~NodeChannel() override;
// Channel::Delegate:
- void OnChannelMessage(const void* payload,
- size_t payload_size,
- std::vector<ScopedPlatformHandle> handles) override;
+ void OnChannelMessage(
+ const void* payload,
+ size_t payload_size,
+ std::vector<ScopedInternalPlatformHandle> handles) override;
void OnChannelError(Channel::Error error) override;
#if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -200,10 +201,7 @@ class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
ports::NodeName remote_node_name_;
base::Lock remote_process_handle_lock_;
- base::ProcessHandle remote_process_handle_ = base::kNullProcessHandle;
-#if defined(OS_WIN)
- ScopedPlatformHandle scoped_remote_process_handle_;
-#endif
+ ScopedProcessHandle remote_process_handle_;
#if defined(OS_MACOSX) && !defined(OS_IOS)
base::Lock pending_mach_messages_lock_;
diff --git a/chromium/mojo/edk/system/node_controller.cc b/chromium/mojo/edk/system/node_controller.cc
index b8638a55f08..ee602c46340 100644
--- a/chromium/mojo/edk/system/node_controller.cc
+++ b/chromium/mojo/edk/system/node_controller.cc
@@ -13,7 +13,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
@@ -103,8 +103,8 @@ ports::ScopedEvent DeserializeEventMessage(
// Used by NodeController to watch for shutdown. Since no IO can happen once
// the IO thread is killed, the NodeController can cleanly drop all its peers
// at that time.
-class ThreadDestructionObserver :
- public base::MessageLoop::DestructionObserver {
+class ThreadDestructionObserver
+ : public base::MessageLoopCurrent::DestructionObserver {
public:
static void Create(scoped_refptr<base::TaskRunner> task_runner,
const base::Closure& callback) {
@@ -120,14 +120,14 @@ class ThreadDestructionObserver :
private:
explicit ThreadDestructionObserver(const base::Closure& callback)
: callback_(callback) {
- base::MessageLoop::current()->AddDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
}
~ThreadDestructionObserver() override {
- base::MessageLoop::current()->RemoveDestructionObserver(this);
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
}
- // base::MessageLoop::DestructionObserver:
+ // base::MessageLoopCurrent::DestructionObserver:
void WillDestroyCurrentMessageLoop() override {
callback_.Run();
delete this;
@@ -185,22 +185,12 @@ void NodeController::SendBrokerClientInvitation(
}
}
-#if defined(OS_WIN)
- // On Windows, we need to duplicate the process handle because we have no
- // control over its lifetime and it may become invalid by the time the posted
- // task runs.
- HANDLE dup_handle = INVALID_HANDLE_VALUE;
- BOOL ok = ::DuplicateHandle(base::GetCurrentProcessHandle(), target_process,
- base::GetCurrentProcessHandle(), &dup_handle, 0,
- FALSE, DUPLICATE_SAME_ACCESS);
- DPCHECK(ok);
- target_process = dup_handle;
-#endif
-
+ ScopedProcessHandle scoped_target_process =
+ ScopedProcessHandle::CloneFrom(target_process);
io_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&NodeController::SendBrokerClientInvitationOnIOThread,
- base::Unretained(this), target_process,
+ base::Unretained(this), std::move(scoped_target_process),
std::move(connection_params), temporary_node_name,
process_error_callback));
}
@@ -213,7 +203,8 @@ void NodeController::AcceptBrokerClientInvitation(
// synchronously as the first message from the broker.
base::ElapsedTimer timer;
broker_.reset(new Broker(connection_params.TakeChannelHandle()));
- ScopedPlatformHandle platform_handle = broker_->GetInviterPlatformHandle();
+ ScopedInternalPlatformHandle platform_handle =
+ broker_->GetInviterInternalPlatformHandle();
if (!platform_handle.is_valid()) {
// Most likely the inviter's side of the channel has already been closed and
@@ -303,15 +294,15 @@ int NodeController::MergeLocalPorts(const ports::PortRef& port0,
return node_->MergeLocalPorts(port0, port1);
}
-scoped_refptr<PlatformSharedBuffer> NodeController::CreateSharedBuffer(
+base::WritableSharedMemoryRegion NodeController::CreateSharedBuffer(
size_t num_bytes) {
#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
// Shared buffer creation failure is fatal, so always use the broker when we
// have one; unless of course the embedder forces us not to.
if (!GetConfiguration().force_direct_shared_memory_allocation && broker_)
- return broker_->GetSharedBuffer(num_bytes);
+ return broker_->GetWritableSharedMemoryRegion(num_bytes);
#endif
- return PlatformSharedBuffer::Create(num_bytes);
+ return base::WritableSharedMemoryRegion::Create(num_bytes);
}
void NodeController::RequestShutdown(const base::Closure& callback) {
@@ -332,7 +323,7 @@ void NodeController::NotifyBadMessageFrom(const ports::NodeName& source_node,
}
void NodeController::SendBrokerClientInvitationOnIOThread(
- base::ProcessHandle target_process,
+ ScopedProcessHandle target_process,
ConnectionParams connection_params,
ports::NodeName temporary_node_name,
const ProcessErrorCallback& process_error_callback) {
@@ -340,11 +331,11 @@ void NodeController::SendBrokerClientInvitationOnIOThread(
#if !defined(OS_MACOSX) && !defined(OS_NACL) && !defined(OS_FUCHSIA)
PlatformChannelPair node_channel;
- ScopedPlatformHandle server_handle = node_channel.PassServerHandle();
+ ScopedInternalPlatformHandle server_handle = node_channel.PassServerHandle();
// BrokerHost owns itself.
- BrokerHost* broker_host =
- new BrokerHost(target_process, connection_params.TakeChannelHandle(),
- process_error_callback);
+ BrokerHost* broker_host = new BrokerHost(
+ target_process.get(), connection_params.TakeChannelHandle(),
+ process_error_callback);
bool channel_ok = broker_host->SendChannel(node_channel.PassClientHandle());
#if defined(OS_WIN)
@@ -378,7 +369,7 @@ void NodeController::SendBrokerClientInvitationOnIOThread(
pending_invitations_.insert(std::make_pair(temporary_node_name, channel));
channel->SetRemoteNodeName(temporary_node_name);
- channel->SetRemoteProcessHandle(target_process);
+ channel->SetRemoteProcessHandle(std::move(target_process));
channel->Start();
channel->AcceptInvitee(name_, temporary_node_name);
@@ -796,7 +787,7 @@ void NodeController::OnAcceptInvitation(const ports::NodeName& from_node,
scoped_refptr<NodeChannel> broker = GetBrokerChannel();
if (broker) {
// Inform the broker of this new client.
- broker->AddBrokerClient(invitee_name, channel->CopyRemoteProcessHandle());
+ broker->AddBrokerClient(invitee_name, channel->CloneRemoteProcessHandle());
} else {
// If we have no broker, either we need to wait for one, or we *are* the
// broker.
@@ -808,7 +799,7 @@ void NodeController::OnAcceptInvitation(const ports::NodeName& from_node,
if (!inviter) {
// Yes, we're the broker. We can initialize the client directly.
- channel->AcceptBrokerClient(name_, ScopedPlatformHandle());
+ channel->AcceptBrokerClient(name_, ScopedInternalPlatformHandle());
} else {
// We aren't the broker, so wait for a broker connection.
base::AutoLock lock(broker_lock_);
@@ -820,11 +811,8 @@ void NodeController::OnAcceptInvitation(const ports::NodeName& from_node,
void NodeController::OnAddBrokerClient(const ports::NodeName& from_node,
const ports::NodeName& client_name,
base::ProcessHandle process_handle) {
-#if defined(OS_WIN)
- // Scoped handle to avoid leaks on error.
- ScopedPlatformHandle scoped_process_handle =
- ScopedPlatformHandle(PlatformHandle(process_handle));
-#endif
+ ScopedProcessHandle scoped_process_handle(process_handle);
+
scoped_refptr<NodeChannel> sender = GetPeerChannel(from_node);
if (!sender) {
DLOG(ERROR) << "Ignoring AddBrokerClient from unknown sender.";
@@ -851,10 +839,8 @@ void NodeController::OnAddBrokerClient(const ports::NodeName& from_node,
DLOG(ERROR) << "Broker rejecting client with invalid process handle.";
return;
}
- client->SetRemoteProcessHandle(scoped_process_handle.release().handle);
-#else
- client->SetRemoteProcessHandle(process_handle);
#endif
+ client->SetRemoteProcessHandle(std::move(scoped_process_handle));
AddPeer(client_name, client, true /* start_channel */);
@@ -864,9 +850,10 @@ void NodeController::OnAddBrokerClient(const ports::NodeName& from_node,
sender->BrokerClientAdded(client_name, broker_channel.PassClientHandle());
}
-void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node,
- const ports::NodeName& client_name,
- ScopedPlatformHandle broker_channel) {
+void NodeController::OnBrokerClientAdded(
+ const ports::NodeName& from_node,
+ const ports::NodeName& client_name,
+ ScopedInternalPlatformHandle broker_channel) {
scoped_refptr<NodeChannel> client = GetPeerChannel(client_name);
if (!client) {
DLOG(ERROR) << "BrokerClientAdded for unknown client " << client_name;
@@ -884,9 +871,10 @@ void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node,
client->AcceptBrokerClient(from_node, std::move(broker_channel));
}
-void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
- const ports::NodeName& broker_name,
- ScopedPlatformHandle broker_channel) {
+void NodeController::OnAcceptBrokerClient(
+ const ports::NodeName& from_node,
+ const ports::NodeName& broker_name,
+ ScopedInternalPlatformHandle broker_channel) {
DCHECK(!GetConfiguration().is_broker_process);
// This node should already have an inviter in bootstrap mode.
@@ -941,9 +929,13 @@ void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
while (!pending_broker_clients.empty()) {
const ports::NodeName& invitee_name = pending_broker_clients.front();
auto it = pending_invitations_.find(invitee_name);
- DCHECK(it != pending_invitations_.end());
- broker->AddBrokerClient(invitee_name,
- it->second->CopyRemoteProcessHandle());
+ // If for any reason we don't have a pending invitation for the invitee,
+ // there's nothing left to do: we've already swapped the relevant state into
+ // the stack.
+ if (it != pending_invitations_.end()) {
+ broker->AddBrokerClient(invitee_name,
+ it->second->CloneRemoteProcessHandle());
+ }
pending_broker_clients.pop();
}
@@ -992,6 +984,11 @@ void NodeController::OnRequestPortMerge(
{
base::AutoLock lock(reserved_ports_lock_);
auto it = reserved_ports_.find(from_node);
+ // TODO(https://crbug.com/822034): We should send a notification back to the
+ // requestor so they can clean up their dangling port in this failure case.
+ // This requires changes to the internal protocol, which can't be made yet.
+ // Until this is done, pipes from |MojoExtractMessagePipeFromInvitation()|
+ // will never break if the given name was invalid.
if (it == reserved_ports_.end()) {
DVLOG(1) << "Ignoring port merge request from node " << from_node << ". "
<< "No ports reserved for that node.";
@@ -1031,7 +1028,7 @@ void NodeController::OnRequestIntroduction(const ports::NodeName& from_node,
scoped_refptr<NodeChannel> new_friend = GetPeerChannel(name);
if (!new_friend) {
// We don't know who they're talking about!
- requestor->Introduce(name, ScopedPlatformHandle());
+ requestor->Introduce(name, ScopedInternalPlatformHandle());
} else {
PlatformChannelPair new_channel;
requestor->Introduce(name, new_channel.PassServerHandle());
@@ -1041,7 +1038,7 @@ void NodeController::OnRequestIntroduction(const ports::NodeName& from_node,
void NodeController::OnIntroduce(const ports::NodeName& from_node,
const ports::NodeName& name,
- ScopedPlatformHandle channel_handle) {
+ ScopedInternalPlatformHandle channel_handle) {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
if (!channel_handle.is_valid()) {
@@ -1118,7 +1115,7 @@ void NodeController::OnRelayEventMessage(const ports::NodeName& from_node,
// Note that we explicitly mark the handles as being owned by the sending
// process before rewriting them, in order to accommodate RewriteHandles'
// internal sanity checks.
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
for (auto& handle : handles)
handle.get().owning_process = from_process;
if (!Channel::Message::RewriteHandles(
@@ -1127,12 +1124,12 @@ void NodeController::OnRelayEventMessage(const ports::NodeName& from_node,
}
message->SetHandles(std::move(handles));
#else
- std::vector<ScopedPlatformHandle> handles = message->TakeHandles();
+ std::vector<ScopedInternalPlatformHandle> handles = message->TakeHandles();
for (auto& handle : handles) {
- if (handle.get().type == PlatformHandle::Type::MACH_NAME) {
+ if (handle.get().type == InternalPlatformHandle::Type::MACH_NAME) {
MachPortRelay* relay = GetMachPortRelay();
if (!relay) {
- handle.get().type = PlatformHandle::Type::MACH;
+ handle.get().type = InternalPlatformHandle::Type::MACH;
handle.get().port = MACH_PORT_NULL;
DLOG(ERROR) << "Receiving Mach ports without a port relay from "
<< from_node << ".";
diff --git a/chromium/mojo/edk/system/node_controller.h b/chromium/mojo/edk/system/node_controller.h
index 853442da197..e6ccd428aa8 100644
--- a/chromium/mojo/edk/system/node_controller.h
+++ b/chromium/mojo/edk/system/node_controller.h
@@ -18,9 +18,9 @@
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/writable_shared_memory_region.h"
#include "base/task_runner.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/atomic_flag.h"
#include "mojo/edk/system/node_channel.h"
@@ -28,6 +28,7 @@
#include "mojo/edk/system/ports/name.h"
#include "mojo/edk/system/ports/node.h"
#include "mojo/edk/system/ports/node_delegate.h"
+#include "mojo/edk/system/scoped_process_handle.h"
#include "mojo/edk/system/system_impl_export.h"
namespace base {
@@ -116,7 +117,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
int MergeLocalPorts(const ports::PortRef& port0, const ports::PortRef& port1);
// Creates a new shared buffer for use in the current process.
- scoped_refptr<PlatformSharedBuffer> CreateSharedBuffer(size_t num_bytes);
+ base::WritableSharedMemoryRegion CreateSharedBuffer(size_t num_bytes);
// Request that the Node be shut down cleanly. This may take an arbitrarily
// long time to complete, at which point |callback| will be called.
@@ -159,7 +160,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
};
void SendBrokerClientInvitationOnIOThread(
- base::ProcessHandle target_process,
+ ScopedProcessHandle target_process,
ConnectionParams connection_params,
ports::NodeName token,
const ProcessErrorCallback& process_error_callback);
@@ -198,12 +199,14 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
void OnAddBrokerClient(const ports::NodeName& from_node,
const ports::NodeName& client_name,
base::ProcessHandle process_handle) override;
- void OnBrokerClientAdded(const ports::NodeName& from_node,
- const ports::NodeName& client_name,
- ScopedPlatformHandle broker_channel) override;
- void OnAcceptBrokerClient(const ports::NodeName& from_node,
- const ports::NodeName& broker_name,
- ScopedPlatformHandle broker_channel) override;
+ void OnBrokerClientAdded(
+ const ports::NodeName& from_node,
+ const ports::NodeName& client_name,
+ ScopedInternalPlatformHandle broker_channel) override;
+ void OnAcceptBrokerClient(
+ const ports::NodeName& from_node,
+ const ports::NodeName& broker_name,
+ ScopedInternalPlatformHandle broker_channel) override;
void OnEventMessage(const ports::NodeName& from_node,
Channel::MessagePtr message) override;
void OnRequestPortMerge(const ports::NodeName& from_node,
@@ -213,7 +216,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
const ports::NodeName& name) override;
void OnIntroduce(const ports::NodeName& from_node,
const ports::NodeName& name,
- ScopedPlatformHandle channel_handle) override;
+ ScopedInternalPlatformHandle channel_handle) override;
void OnBroadcast(const ports::NodeName& from_node,
Channel::MessagePtr message) override;
#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher.cc b/chromium/mojo/edk/system/platform_handle_dispatcher.cc
index 02df31f3bcd..19b1ed3fb19 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher.cc
+++ b/chromium/mojo/edk/system/platform_handle_dispatcher.cc
@@ -12,11 +12,12 @@ namespace edk {
// static
scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Create(
- ScopedPlatformHandle platform_handle) {
+ ScopedInternalPlatformHandle platform_handle) {
return new PlatformHandleDispatcher(std::move(platform_handle));
}
-ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() {
+ScopedInternalPlatformHandle
+PlatformHandleDispatcher::PassInternalPlatformHandle() {
return std::move(platform_handle_);
}
@@ -41,13 +42,14 @@ void PlatformHandleDispatcher::StartSerialize(uint32_t* num_bytes,
*num_handles = 1;
}
-bool PlatformHandleDispatcher::EndSerialize(void* destination,
- ports::PortName* ports,
- ScopedPlatformHandle* handles) {
+bool PlatformHandleDispatcher::EndSerialize(
+ void* destination,
+ ports::PortName* ports,
+ ScopedInternalPlatformHandle* handles) {
base::AutoLock lock(lock_);
if (is_closed_)
return false;
- handles[0] = ScopedPlatformHandle(platform_handle_.get());
+ handles[0] = ScopedInternalPlatformHandle(platform_handle_.get());
return true;
}
@@ -80,7 +82,7 @@ scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles) {
if (num_bytes || num_ports || num_handles != 1)
return nullptr;
@@ -89,7 +91,7 @@ scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize(
}
PlatformHandleDispatcher::PlatformHandleDispatcher(
- ScopedPlatformHandle platform_handle)
+ ScopedInternalPlatformHandle platform_handle)
: platform_handle_(std::move(platform_handle)) {}
PlatformHandleDispatcher::~PlatformHandleDispatcher() {
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher.h b/chromium/mojo/edk/system/platform_handle_dispatcher.h
index e13c79a1a43..8a377e47fa7 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher.h
+++ b/chromium/mojo/edk/system/platform_handle_dispatcher.h
@@ -18,9 +18,9 @@ namespace edk {
class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
public:
static scoped_refptr<PlatformHandleDispatcher> Create(
- ScopedPlatformHandle platform_handle);
+ ScopedInternalPlatformHandle platform_handle);
- ScopedPlatformHandle PassPlatformHandle();
+ ScopedInternalPlatformHandle PassInternalPlatformHandle();
// Dispatcher:
Type GetType() const override;
@@ -30,7 +30,7 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
uint32_t* num_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles) override;
+ ScopedInternalPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
@@ -40,17 +40,17 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformHandleDispatcher : public Dispatcher {
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* handles,
+ ScopedInternalPlatformHandle* handles,
size_t num_handles);
private:
- PlatformHandleDispatcher(ScopedPlatformHandle platform_handle);
+ PlatformHandleDispatcher(ScopedInternalPlatformHandle platform_handle);
~PlatformHandleDispatcher() override;
base::Lock lock_;
bool in_transit_ = false;
bool is_closed_ = false;
- ScopedPlatformHandle platform_handle_;
+ ScopedInternalPlatformHandle platform_handle_;
DISALLOW_COPY_AND_ASSIGN(PlatformHandleDispatcher);
};
diff --git a/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
index 5a86decf16f..0313b8fdccf 100644
--- a/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
+++ b/chromium/mojo/edk/system/platform_handle_dispatcher_unittest.cc
@@ -33,7 +33,8 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_EQ(sizeof(kHelloWorld),
fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get()));
- ScopedPlatformHandle h(test::PlatformHandleFromFILE(std::move(fp)));
+ ScopedInternalPlatformHandle h(
+ test::InternalPlatformHandleFromFILE(std::move(fp)));
EXPECT_FALSE(fp);
ASSERT_TRUE(h.is_valid());
@@ -42,10 +43,10 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_FALSE(h.is_valid());
EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, dispatcher->GetType());
- h = dispatcher->PassPlatformHandle();
+ h = dispatcher->PassInternalPlatformHandle();
EXPECT_TRUE(h.is_valid());
- fp = test::FILEFromPlatformHandle(std::move(h), "rb");
+ fp = test::FILEFromInternalPlatformHandle(std::move(h), "rb");
EXPECT_FALSE(h.is_valid());
EXPECT_TRUE(fp);
@@ -56,7 +57,7 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_STREQ(kHelloWorld, read_buffer);
// Try getting the handle again. (It should fail cleanly.)
- h = dispatcher->PassPlatformHandle();
+ h = dispatcher->PassInternalPlatformHandle();
EXPECT_FALSE(h.is_valid());
EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
@@ -75,7 +76,7 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
scoped_refptr<PlatformHandleDispatcher> dispatcher =
PlatformHandleDispatcher::Create(
- test::PlatformHandleFromFILE(std::move(fp)));
+ test::InternalPlatformHandleFromFILE(std::move(fp)));
uint32_t num_bytes = 0;
uint32_t num_ports = 0;
@@ -87,14 +88,15 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
EXPECT_EQ(0u, num_ports);
EXPECT_EQ(1u, num_handles);
- ScopedPlatformHandle received_handle;
+ ScopedInternalPlatformHandle received_handle;
EXPECT_TRUE(dispatcher->EndSerialize(nullptr, nullptr, &received_handle));
dispatcher->CompleteTransitAndClose();
EXPECT_TRUE(received_handle.is_valid());
- ScopedPlatformHandle handle = dispatcher->PassPlatformHandle();
+ ScopedInternalPlatformHandle handle =
+ dispatcher->PassInternalPlatformHandle();
EXPECT_FALSE(handle.is_valid());
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher->Close());
@@ -108,7 +110,8 @@ TEST(PlatformHandleDispatcherTest, Serialization) {
EXPECT_FALSE(received_handle.is_valid());
EXPECT_TRUE(dispatcher->GetType() == Dispatcher::Type::PLATFORM_HANDLE);
- fp = test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(), "rb");
+ fp = test::FILEFromInternalPlatformHandle(
+ dispatcher->PassInternalPlatformHandle(), "rb");
EXPECT_TRUE(fp);
rewind(fp.get());
diff --git a/chromium/mojo/edk/system/platform_shared_memory_mapping.cc b/chromium/mojo/edk/system/platform_shared_memory_mapping.cc
new file mode 100644
index 00000000000..80f14f6546c
--- /dev/null
+++ b/chromium/mojo/edk/system/platform_shared_memory_mapping.cc
@@ -0,0 +1,104 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/edk/system/platform_shared_memory_mapping.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/memory/writable_shared_memory_region.h"
+#include "base/sys_info.h"
+#include "build/build_config.h"
+
+#if defined(OS_NACL)
+// For getpagesize() on NaCl.
+#include <unistd.h>
+#endif
+
+namespace mojo {
+namespace edk {
+
+namespace {
+
+size_t GetPageSize() {
+#if defined(OS_NACL)
+ // base::SysInfo isn't available under NaCl.
+ return getpagesize();
+#else
+ return base::SysInfo::VMAllocationGranularity();
+#endif
+}
+
+} // namespace
+
+PlatformSharedMemoryMapping::PlatformSharedMemoryMapping(
+ base::subtle::PlatformSharedMemoryRegion* region,
+ size_t offset,
+ size_t length)
+ : type_(region->GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly
+ ? Type::kReadOnly
+ : Type::kWritable),
+ offset_(offset),
+ length_(length) {
+ // Mojo shared buffers can be mapped at any offset, but //base shared memory
+ // regions must be mapped at a page boundary. We calculate the nearest whole
+ // page offset and map from there.
+ size_t offset_rounding = offset_ % GetPageSize();
+ off_t real_offset = static_cast<off_t>(offset_ - offset_rounding);
+ size_t real_length = length_ + offset_rounding;
+ void* mapped_memory = nullptr;
+ if (type_ == Type::kReadOnly) {
+ auto read_only_region =
+ base::ReadOnlySharedMemoryRegion::Deserialize(std::move(*region));
+ auto read_only_mapping = read_only_region.MapAt(real_offset, real_length);
+ mapped_memory = const_cast<void*>(read_only_mapping.memory());
+ mapping_ = std::make_unique<base::ReadOnlySharedMemoryMapping>(
+ std::move(read_only_mapping));
+ *region = base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
+ std::move(read_only_region));
+ } else if (region->GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe) {
+ auto unsafe_region =
+ base::UnsafeSharedMemoryRegion::Deserialize(std::move(*region));
+ auto writable_mapping = unsafe_region.MapAt(real_offset, real_length);
+ mapped_memory = writable_mapping.memory();
+ mapping_ = std::make_unique<base::WritableSharedMemoryMapping>(
+ std::move(writable_mapping));
+ *region = base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
+ std::move(unsafe_region));
+ } else {
+ DCHECK_EQ(region->GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable);
+ auto writable_region =
+ base::WritableSharedMemoryRegion::Deserialize(std::move(*region));
+ auto writable_mapping = writable_region.MapAt(real_offset, real_length);
+ mapped_memory = writable_mapping.memory();
+ mapping_ = std::make_unique<base::WritableSharedMemoryMapping>(
+ std::move(writable_mapping));
+ *region = base::WritableSharedMemoryRegion::TakeHandleForSerialization(
+ std::move(writable_region));
+ }
+
+ base_ = static_cast<char*>(mapped_memory) + offset_rounding;
+}
+
+PlatformSharedMemoryMapping::~PlatformSharedMemoryMapping() = default;
+
+bool PlatformSharedMemoryMapping::IsValid() const {
+ return mapping_ && mapping_->IsValid();
+}
+
+void* PlatformSharedMemoryMapping::GetBase() const {
+ return base_;
+}
+
+size_t PlatformSharedMemoryMapping::GetLength() const {
+ return length_;
+}
+
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/platform_shared_memory_mapping.h b/chromium/mojo/edk/system/platform_shared_memory_mapping.h
new file mode 100644
index 00000000000..764fe4f4c1e
--- /dev/null
+++ b/chromium/mojo/edk/system/platform_shared_memory_mapping.h
@@ -0,0 +1,60 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_SYSTEM_PLATFORM_SHARED_MEMORY_MAPPING_H_
+#define MOJO_EDK_SYSTEM_PLATFORM_SHARED_MEMORY_MAPPING_H_
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/platform_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "mojo/edk/system/system_impl_export.h"
+
+namespace mojo {
+namespace edk {
+
+// A mapping of a |base::subtle::PlatformSharedMemoryRegion|, created
+// exclusively by |SharedBufferDispatcher::MapBuffer()|. Automatically maps
+// upon construction and unmaps upon destruction.
+//
+// Mappings are NOT thread-safe.
+//
+// This may represent either a |base::ReadOnlySharedMemoryMapping| OR a
+// |base::WritableSharedMemoryMapping|, and it supports non-page-aligned base
+// offsets for convenience.
+class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedMemoryMapping {
+ public:
+ enum class Type {
+ kReadOnly,
+ kWritable,
+ };
+
+ PlatformSharedMemoryMapping(base::subtle::PlatformSharedMemoryRegion* region,
+ size_t offset,
+ size_t length);
+ ~PlatformSharedMemoryMapping();
+
+ bool IsValid() const;
+
+ void* GetBase() const;
+ size_t GetLength() const;
+
+ private:
+ const Type type_;
+ const size_t offset_;
+ const size_t length_;
+ void* base_ = nullptr;
+ std::unique_ptr<base::SharedMemoryMapping> mapping_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformSharedMemoryMapping);
+};
+
+} // namespace edk
+} // namespace mojo
+
+#endif // MOJO_EDK_SYSTEM_PLATFORM_SHARED_MEMORY_MAPPING_H_
diff --git a/chromium/mojo/edk/system/platform_wrapper_unittest.cc b/chromium/mojo/edk/system/platform_wrapper_unittest.cc
index 6ed99667ee6..f7770ba711c 100644
--- a/chromium/mojo/edk/system/platform_wrapper_unittest.cc
+++ b/chromium/mojo/edk/system/platform_wrapper_unittest.cc
@@ -14,7 +14,6 @@
#include "base/memory/shared_memory.h"
#include "base/process/process_handle.h"
#include "build/build_config.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/test/mojo_test_base.h"
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -24,33 +23,33 @@
#include <windows.h>
#endif
-#if defined(OS_POSIX)
-#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+#define SIMPLE_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT
-#elif defined(OS_FUCHSIA)
+#if defined(OS_FUCHSIA)
#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE \
MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE
-#else
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT
+#elif defined(OS_WIN) || defined(OS_POSIX)
#define SHARED_BUFFER_PLATFORM_HANDLE_TYPE SIMPLE_PLATFORM_HANDLE_TYPE
#endif
-uint64_t PlatformHandleValueFromPlatformFile(base::PlatformFile file) {
+uint64_t InternalPlatformHandleValueFromPlatformFile(base::PlatformFile file) {
#if defined(OS_WIN)
return reinterpret_cast<uint64_t>(file);
-#else
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
return static_cast<uint64_t>(file);
#endif
}
-base::PlatformFile PlatformFileFromPlatformHandleValue(uint64_t value) {
+base::PlatformFile PlatformFileFromInternalPlatformHandleValue(uint64_t value) {
#if defined(OS_WIN)
return reinterpret_cast<base::PlatformFile>(value);
-#else
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
return static_cast<base::PlatformFile>(value);
#endif
}
@@ -61,7 +60,7 @@ namespace {
using PlatformWrapperTest = test::MojoTestBase;
-TEST_F(PlatformWrapperTest, WrapPlatformHandle) {
+TEST_F(PlatformWrapperTest, WrapInternalPlatformHandle) {
// Create a temporary file and write a message to it.
base::FilePath temp_file_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
@@ -82,9 +81,9 @@ TEST_F(PlatformWrapperTest, WrapPlatformHandle) {
os_file.struct_size = sizeof(MojoPlatformHandle);
os_file.type = SIMPLE_PLATFORM_HANDLE_TYPE;
os_file.value =
- PlatformHandleValueFromPlatformFile(file.TakePlatformFile());
+ InternalPlatformHandleValueFromPlatformFile(file.TakePlatformFile());
EXPECT_EQ(MOJO_RESULT_OK,
- MojoWrapPlatformHandle(&os_file, &wrapped_handle));
+ MojoWrapPlatformHandle(&os_file, nullptr, &wrapped_handle));
WriteMessageWithHandles(h, kMessage, &wrapped_handle, 1);
});
@@ -99,10 +98,11 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformFile, PlatformWrapperTest, h) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(MojoPlatformHandle);
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoUnwrapPlatformHandle(wrapped_handle, &platform_handle));
+ ASSERT_EQ(MOJO_RESULT_OK, MojoUnwrapPlatformHandle(wrapped_handle, nullptr,
+ &platform_handle));
EXPECT_EQ(SIMPLE_PLATFORM_HANDLE_TYPE, platform_handle.type);
- base::File file(PlatformFileFromPlatformHandleValue(platform_handle.value));
+ base::File file(
+ PlatformFileFromInternalPlatformHandleValue(platform_handle.value));
// Expect to read the same message from the file.
std::vector<char> data(message.size());
@@ -111,7 +111,7 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformFile, PlatformWrapperTest, h) {
EXPECT_TRUE(std::equal(message.begin(), message.end(), data.begin()));
}
-TEST_F(PlatformWrapperTest, WrapPlatformSharedBufferHandle) {
+TEST_F(PlatformWrapperTest, WrapPlatformSharedMemoryRegion) {
// Allocate a new platform shared buffer and write a message into it.
const std::string kMessage = "Hello, world!";
base::SharedMemory buffer;
@@ -127,12 +127,14 @@ TEST_F(PlatformWrapperTest, WrapPlatformSharedBufferHandle) {
MojoPlatformHandle os_buffer;
os_buffer.struct_size = sizeof(MojoPlatformHandle);
os_buffer.type = SHARED_BUFFER_PLATFORM_HANDLE_TYPE;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- os_buffer.value = static_cast<uint64_t>(memory_handle.GetMemoryObject());
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
os_buffer.value = reinterpret_cast<uint64_t>(memory_handle.GetHandle());
-#else
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ os_buffer.value = static_cast<uint64_t>(memory_handle.GetMemoryObject());
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
os_buffer.value = static_cast<uint64_t>(memory_handle.GetHandle());
+#else
+#error Unsupported platform
#endif
MojoSharedBufferGuid mojo_guid;
@@ -141,10 +143,11 @@ TEST_F(PlatformWrapperTest, WrapPlatformSharedBufferHandle) {
mojo_guid.low = guid.GetLowForSerialization();
MojoHandle wrapped_handle;
- ASSERT_EQ(MOJO_RESULT_OK, MojoWrapPlatformSharedBufferHandle(
- &os_buffer, kMessage.size(), &mojo_guid,
- MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE,
- &wrapped_handle));
+ ASSERT_EQ(MOJO_RESULT_OK,
+ MojoWrapPlatformSharedMemoryRegion(
+ &os_buffer, 1, kMessage.size(), &mojo_guid,
+ MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE,
+ nullptr, &wrapped_handle));
WriteMessageWithHandles(h, kMessage, &wrapped_handle, 1);
// As a sanity check, send the GUID explicitly in a second message. We'll
@@ -169,37 +172,37 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadPlatformSharedBuffer,
// works as expected.
MojoPlatformHandle os_buffer;
os_buffer.struct_size = sizeof(MojoPlatformHandle);
- size_t size;
+ uint32_t num_handles = 1;
+ uint64_t size;
MojoSharedBufferGuid mojo_guid;
- MojoPlatformSharedBufferHandleFlags flags;
- ASSERT_EQ(MOJO_RESULT_OK,
- MojoUnwrapPlatformSharedBufferHandle(wrapped_handle, &os_buffer,
- &size, &mojo_guid, &flags));
- bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE;
- EXPECT_FALSE(read_only);
+ MojoPlatformSharedMemoryRegionAccessMode access_mode;
+ ASSERT_EQ(MOJO_RESULT_OK, MojoUnwrapPlatformSharedMemoryRegion(
+ wrapped_handle, nullptr, &os_buffer,
+ &num_handles, &size, &mojo_guid, &access_mode));
+ EXPECT_EQ(MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE, access_mode);
base::UnguessableToken guid =
base::UnguessableToken::Deserialize(mojo_guid.high, mojo_guid.low);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, os_buffer.type);
+#if defined(OS_WIN)
+ ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type);
base::SharedMemoryHandle memory_handle(
- static_cast<mach_port_t>(os_buffer.value), size, guid);
+ reinterpret_cast<HANDLE>(os_buffer.value), size, guid);
#elif defined(OS_FUCHSIA)
ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_FUCHSIA_HANDLE, os_buffer.type);
base::SharedMemoryHandle memory_handle(
static_cast<zx_handle_t>(os_buffer.value), size, guid);
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+ ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT, os_buffer.type);
+ base::SharedMemoryHandle memory_handle(
+ static_cast<mach_port_t>(os_buffer.value), size, guid);
#elif defined(OS_POSIX)
ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR, os_buffer.type);
base::SharedMemoryHandle memory_handle(
base::FileDescriptor(static_cast<int>(os_buffer.value), false), size,
guid);
-#elif defined(OS_WIN)
- ASSERT_EQ(MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE, os_buffer.type);
- base::SharedMemoryHandle memory_handle(
- reinterpret_cast<HANDLE>(os_buffer.value), size, guid);
#endif
- base::SharedMemory memory(memory_handle, read_only);
+ base::SharedMemory memory(memory_handle, false);
memory.Map(message.size());
ASSERT_TRUE(memory.memory());
@@ -227,9 +230,9 @@ TEST_F(PlatformWrapperTest, InvalidHandle) {
invalid_handle.struct_size = sizeof(MojoPlatformHandle);
invalid_handle.type = MOJO_PLATFORM_HANDLE_TYPE_INVALID;
EXPECT_EQ(MOJO_RESULT_OK,
- MojoWrapPlatformHandle(&invalid_handle, &wrapped_handle));
+ MojoWrapPlatformHandle(&invalid_handle, nullptr, &wrapped_handle));
EXPECT_EQ(MOJO_RESULT_OK,
- MojoUnwrapPlatformHandle(wrapped_handle, &invalid_handle));
+ MojoUnwrapPlatformHandle(wrapped_handle, nullptr, &invalid_handle));
EXPECT_EQ(MOJO_PLATFORM_HANDLE_TYPE_INVALID, invalid_handle.type);
}
@@ -239,7 +242,7 @@ TEST_F(PlatformWrapperTest, InvalidArgument) {
MojoPlatformHandle platform_handle;
platform_handle.struct_size = 0;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- MojoWrapPlatformHandle(&platform_handle, &wrapped_handle));
+ MojoWrapPlatformHandle(&platform_handle, nullptr, &wrapped_handle));
}
} // namespace
diff --git a/chromium/mojo/edk/system/scoped_process_handle.cc b/chromium/mojo/edk/system/scoped_process_handle.cc
new file mode 100644
index 00000000000..43d719df410
--- /dev/null
+++ b/chromium/mojo/edk/system/scoped_process_handle.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/edk/system/scoped_process_handle.h"
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+namespace mojo {
+namespace edk {
+
+ScopedProcessHandle::ScopedProcessHandle() = default;
+
+ScopedProcessHandle::ScopedProcessHandle(base::ProcessHandle handle)
+ : handle_(handle) {}
+
+ScopedProcessHandle::ScopedProcessHandle(ScopedProcessHandle&&) = default;
+
+ScopedProcessHandle::~ScopedProcessHandle() = default;
+
+// static
+ScopedProcessHandle ScopedProcessHandle::CloneFrom(base::ProcessHandle handle) {
+#if defined(OS_WIN)
+ BOOL ok = ::DuplicateHandle(base::GetCurrentProcessHandle(), handle,
+ base::GetCurrentProcessHandle(), &handle, 0,
+ FALSE, DUPLICATE_SAME_ACCESS);
+ DCHECK(ok);
+#endif
+ return ScopedProcessHandle(handle);
+}
+
+ScopedProcessHandle& ScopedProcessHandle::operator=(ScopedProcessHandle&&) =
+ default;
+
+ScopedProcessHandle ScopedProcessHandle::Clone() const {
+ DCHECK(is_valid());
+ return CloneFrom(get());
+}
+
+} // namespace edk
+} // namespace mojo
diff --git a/chromium/mojo/edk/system/scoped_process_handle.h b/chromium/mojo/edk/system/scoped_process_handle.h
new file mode 100644
index 00000000000..dbefdfe0593
--- /dev/null
+++ b/chromium/mojo/edk/system/scoped_process_handle.h
@@ -0,0 +1,81 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EDK_SYSTEM_SCOPED_PROCESS_HANDLE_H_
+#define MOJO_EDK_SYSTEM_SCOPED_PROCESS_HANDLE_H_
+
+#include "base/macros.h"
+#include "base/process/process_handle.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "base/win/scoped_handle.h"
+#endif
+
+namespace mojo {
+namespace edk {
+
+// Wraps a |base::ProcessHandle| with additional scoped lifetime semantics on
+// applicable platforms. For platforms where process handles aren't ownable
+// references, this is just a wrapper around |base::ProcessHandle|.
+//
+// This essentially exists to support passing around process handles internally
+// in a generic way while also supporting Windows process handle ownership
+// semantics.
+class ScopedProcessHandle {
+ public:
+ ScopedProcessHandle();
+
+ // Assumes ownership of |handle|.
+ explicit ScopedProcessHandle(base::ProcessHandle handle);
+
+ ScopedProcessHandle(ScopedProcessHandle&&);
+
+ ~ScopedProcessHandle();
+
+ // Creates a new ScopedProcessHandle from a clone of |handle|.
+ static ScopedProcessHandle CloneFrom(base::ProcessHandle handle);
+
+ ScopedProcessHandle& operator=(ScopedProcessHandle&&);
+
+ bool is_valid() const {
+#if defined(OS_WIN)
+ return handle_.IsValid();
+#else
+ return handle_ != base::kNullProcessHandle;
+#endif
+ }
+
+ base::ProcessHandle get() const {
+#if defined(OS_WIN)
+ return handle_.Get();
+#else
+ return handle_;
+#endif
+ }
+
+ base::ProcessHandle release() {
+#if defined(OS_WIN)
+ return handle_.Take();
+#else
+ return handle_;
+#endif
+ }
+
+ ScopedProcessHandle Clone() const;
+
+ private:
+#if defined(OS_WIN)
+ base::win::ScopedHandle handle_;
+#else
+ base::ProcessHandle handle_ = base::kNullProcessHandle;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedProcessHandle);
+};
+
+} // namespace edk
+} // namespace mojo
+
+#endif // MOJO_EDK_SYSTEM_SCOPED_PROCESS_HANDLE_H_
diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc b/chromium/mojo/edk/system/shared_buffer_dispatcher.cc
index ca9a1a84359..73b2c03d624 100644
--- a/chromium/mojo/edk/system/shared_buffer_dispatcher.cc
+++ b/chromium/mojo/edk/system/shared_buffer_dispatcher.cc
@@ -12,9 +12,14 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
+#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/node_controller.h"
#include "mojo/edk/system/options_validation.h"
+#include "mojo/edk/system/platform_shared_memory_mapping.h"
+#include "mojo/public/c/system/platform_handle.h"
namespace mojo {
namespace edk {
@@ -25,14 +30,12 @@ namespace {
struct SerializedState {
uint64_t num_bytes;
- uint32_t flags;
+ uint32_t access_mode;
uint64_t guid_high;
uint64_t guid_low;
uint32_t padding;
};
-const uint32_t kSerializedStateFlagsReadOnly = 1 << 0;
-
#pragma pack(pop)
static_assert(sizeof(SerializedState) % 8 == 0,
@@ -44,14 +47,14 @@ static_assert(sizeof(SerializedState) % 8 == 0,
const MojoCreateSharedBufferOptions
SharedBufferDispatcher::kDefaultCreateOptions = {
static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
+ MOJO_CREATE_SHARED_BUFFER_FLAG_NONE};
// static
MojoResult SharedBufferDispatcher::ValidateCreateOptions(
const MojoCreateSharedBufferOptions* in_options,
MojoCreateSharedBufferOptions* out_options) {
- const MojoCreateSharedBufferOptionsFlags kKnownFlags =
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE;
+ const MojoCreateSharedBufferFlags kKnownFlags =
+ MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
*out_options = kDefaultCreateOptions;
if (!in_options)
@@ -85,29 +88,31 @@ MojoResult SharedBufferDispatcher::Create(
if (num_bytes > GetConfiguration().max_shared_memory_num_bytes)
return MOJO_RESULT_RESOURCE_EXHAUSTED;
- scoped_refptr<PlatformSharedBuffer> shared_buffer;
+ base::WritableSharedMemoryRegion writable_region;
if (node_controller) {
- shared_buffer =
+ writable_region =
node_controller->CreateSharedBuffer(static_cast<size_t>(num_bytes));
} else {
- shared_buffer =
- PlatformSharedBuffer::Create(static_cast<size_t>(num_bytes));
+ writable_region = base::WritableSharedMemoryRegion::Create(
+ static_cast<size_t>(num_bytes));
}
- if (!shared_buffer)
+ if (!writable_region.IsValid())
return MOJO_RESULT_RESOURCE_EXHAUSTED;
- *result = CreateInternal(std::move(shared_buffer));
+ *result = CreateInternal(
+ base::WritableSharedMemoryRegion::TakeHandleForSerialization(
+ std::move(writable_region)));
return MOJO_RESULT_OK;
}
// static
-MojoResult SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
- const scoped_refptr<PlatformSharedBuffer>& shared_buffer,
+MojoResult SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
+ base::subtle::PlatformSharedMemoryRegion region,
scoped_refptr<SharedBufferDispatcher>* result) {
- if (!shared_buffer)
+ if (!region.IsValid())
return MOJO_RESULT_INVALID_ARGUMENT;
- *result = CreateInternal(shared_buffer);
+ *result = CreateInternal(std::move(region));
return MOJO_RESULT_OK;
}
@@ -117,7 +122,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* platform_handles,
+ ScopedInternalPlatformHandle* platform_handles,
size_t num_platform_handles) {
if (num_bytes != sizeof(SerializedState)) {
LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)";
@@ -132,38 +137,65 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
return nullptr;
}
- if (num_platform_handles != 1 || num_ports) {
- LOG(ERROR)
- << "Invalid serialized shared buffer dispatcher (missing handles)";
+ if (num_ports)
return nullptr;
+
+ ScopedInternalPlatformHandle handles[2];
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ if (serialized_state->access_mode ==
+ MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
+ if (num_platform_handles != 2)
+ return nullptr;
+ handles[1] = std::move(platform_handles[1]);
+ } else {
+ if (num_platform_handles != 1)
+ return nullptr;
}
+#else
+ if (num_platform_handles != 1)
+ return nullptr;
+#endif
+ handles[0] = std::move(platform_handles[0]);
base::UnguessableToken guid = base::UnguessableToken::Deserialize(
serialized_state->guid_high, serialized_state->guid_low);
- bool read_only = (serialized_state->flags & kSerializedStateFlagsReadOnly);
- scoped_refptr<PlatformSharedBuffer> shared_buffer(
- PlatformSharedBuffer::CreateFromPlatformHandle(
- static_cast<size_t>(serialized_state->num_bytes), read_only, guid,
- std::move(platform_handles[0])));
- if (!shared_buffer) {
+ base::subtle::PlatformSharedMemoryRegion::Mode mode;
+ switch (serialized_state->access_mode) {
+ case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_READ_ONLY:
+ mode = base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly;
+ break;
+ case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE:
+ mode = base::subtle::PlatformSharedMemoryRegion::Mode::kWritable;
+ break;
+ case MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE:
+ mode = base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe;
+ break;
+ default:
+ LOG(ERROR) << "Invalid serialized shared buffer access mode.";
+ return nullptr;
+ }
+ auto region = base::subtle::PlatformSharedMemoryRegion::Take(
+ CreateSharedMemoryRegionHandleFromInternalPlatformHandles(
+ std::move(handles[0]), std::move(handles[1])),
+ mode, static_cast<size_t>(serialized_state->num_bytes), guid);
+ if (!region.IsValid()) {
LOG(ERROR)
<< "Invalid serialized shared buffer dispatcher (invalid num_bytes?)";
return nullptr;
}
- return CreateInternal(std::move(shared_buffer));
+ return CreateInternal(std::move(region));
}
-scoped_refptr<PlatformSharedBuffer>
-SharedBufferDispatcher::PassPlatformSharedBuffer() {
+base::subtle::PlatformSharedMemoryRegion
+SharedBufferDispatcher::PassPlatformSharedMemoryRegion() {
base::AutoLock lock(lock_);
- if (!shared_buffer_ || in_transit_)
- return nullptr;
+ if (!region_.IsValid() || in_transit_)
+ return base::subtle::PlatformSharedMemoryRegion();
- scoped_refptr<PlatformSharedBuffer> retval = shared_buffer_;
- shared_buffer_ = nullptr;
- return retval;
+ return std::move(region_);
}
Dispatcher::Type SharedBufferDispatcher::GetType() const {
@@ -175,7 +207,7 @@ MojoResult SharedBufferDispatcher::Close() {
if (in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
- shared_buffer_ = nullptr;
+ region_ = base::subtle::PlatformSharedMemoryRegion();
return MOJO_RESULT_OK;
}
@@ -187,52 +219,76 @@ MojoResult SharedBufferDispatcher::DuplicateBufferHandle(
if (result != MOJO_RESULT_OK)
return result;
- // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|.
base::AutoLock lock(lock_);
if (in_transit_)
return MOJO_RESULT_INVALID_ARGUMENT;
- if ((validated_options.flags &
- MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY) &&
- (!shared_buffer_->IsReadOnly())) {
- // If a read-only duplicate is requested and |shared_buffer_| is not
- // read-only, make a read-only duplicate of |shared_buffer_|.
- scoped_refptr<PlatformSharedBuffer> read_only_buffer =
- shared_buffer_->CreateReadOnlyDuplicate();
- if (!read_only_buffer)
+ if ((validated_options.flags & MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY)) {
+ // If a read-only duplicate is requested and this handle is not already
+ // read-only, we need to make it read-only before duplicating. If it's
+ // unsafe it can't be made read-only, and we must fail instead.
+ if (region_.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe) {
return MOJO_RESULT_FAILED_PRECONDITION;
- DCHECK(read_only_buffer->IsReadOnly());
- *new_dispatcher = CreateInternal(std::move(read_only_buffer));
- return MOJO_RESULT_OK;
+ } else if (region_.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
+ region_ = base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
+ base::WritableSharedMemoryRegion::ConvertToReadOnly(
+ base::WritableSharedMemoryRegion::Deserialize(
+ std::move(region_))));
+ }
+
+ DCHECK_EQ(region_.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly);
+ } else {
+ // A writable duplicate was requested. If this is already a read-only handle
+ // we have to reject. Otherwise we have to convert to unsafe to ensure that
+ // no future read-only duplication requests can succeed.
+ if (region_.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly) {
+ return MOJO_RESULT_FAILED_PRECONDITION;
+ } else if (region_.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
+ auto handle = region_.PassPlatformHandle();
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ // On POSIX systems excluding Android, Fuchsia, and OSX, we explicitly
+ // wipe out the secondary (read-only) FD from the platform handle to
+ // repurpose it for exclusive unsafe usage.
+ handle.readonly_fd.reset();
+#endif
+ region_ = base::subtle::PlatformSharedMemoryRegion::Take(
+ std::move(handle),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
+ region_.GetSize(), region_.GetGUID());
+ }
}
- *new_dispatcher = CreateInternal(shared_buffer_);
+ *new_dispatcher = CreateInternal(region_.Duplicate());
return MOJO_RESULT_OK;
}
MojoResult SharedBufferDispatcher::MapBuffer(
uint64_t offset,
uint64_t num_bytes,
- MojoMapBufferFlags flags,
- std::unique_ptr<PlatformSharedBufferMapping>* mapping) {
+ std::unique_ptr<PlatformSharedMemoryMapping>* mapping) {
if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
return MOJO_RESULT_INVALID_ARGUMENT;
if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
return MOJO_RESULT_INVALID_ARGUMENT;
base::AutoLock lock(lock_);
- DCHECK(shared_buffer_);
- if (in_transit_ ||
- !shared_buffer_->IsValidMap(static_cast<size_t>(offset),
- static_cast<size_t>(num_bytes))) {
+ DCHECK(region_.IsValid());
+ if (in_transit_ || num_bytes == 0 ||
+ static_cast<size_t>(offset + num_bytes) > region_.GetSize()) {
return MOJO_RESULT_INVALID_ARGUMENT;
}
DCHECK(mapping);
- *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset),
- static_cast<size_t>(num_bytes));
- if (!*mapping) {
- LOG(ERROR) << "Unable to map: read_only" << shared_buffer_->IsReadOnly();
+ *mapping = std::make_unique<PlatformSharedMemoryMapping>(
+ &region_, static_cast<size_t>(offset), static_cast<size_t>(num_bytes));
+ if (!(*mapping)->IsValid()) {
+ LOG(ERROR) << "Failed to map shared memory region.";
return MOJO_RESULT_RESOURCE_EXHAUSTED;
}
@@ -244,7 +300,8 @@ MojoResult SharedBufferDispatcher::GetBufferInfo(MojoSharedBufferInfo* info) {
return MOJO_RESULT_INVALID_ARGUMENT;
base::AutoLock lock(lock_);
- info->size = shared_buffer_->GetNumBytes();
+ info->struct_size = sizeof(*info);
+ info->size = region_.GetSize();
return MOJO_RESULT_OK;
}
@@ -254,28 +311,60 @@ void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes,
*num_bytes = sizeof(SerializedState);
*num_ports = 0;
*num_platform_handles = 1;
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ if (region_.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
+ *num_platform_handles = 2;
+ }
+#endif
}
-bool SharedBufferDispatcher::EndSerialize(void* destination,
- ports::PortName* ports,
- ScopedPlatformHandle* handles) {
+bool SharedBufferDispatcher::EndSerialize(
+ void* destination,
+ ports::PortName* ports,
+ ScopedInternalPlatformHandle* handles) {
SerializedState* serialized_state =
static_cast<SerializedState*>(destination);
base::AutoLock lock(lock_);
- serialized_state->num_bytes =
- static_cast<uint64_t>(shared_buffer_->GetNumBytes());
- serialized_state->flags =
- (shared_buffer_->IsReadOnly() ? kSerializedStateFlagsReadOnly : 0);
- base::UnguessableToken guid = shared_buffer_->GetGUID();
+ serialized_state->num_bytes = region_.GetSize();
+ switch (region_.GetMode()) {
+ case base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly:
+ serialized_state->access_mode =
+ MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_READ_ONLY;
+ break;
+ case base::subtle::PlatformSharedMemoryRegion::Mode::kWritable:
+ serialized_state->access_mode =
+ MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE;
+ break;
+ case base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe:
+ serialized_state->access_mode =
+ MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_UNSAFE;
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ const base::UnguessableToken& guid = region_.GetGUID();
serialized_state->guid_high = guid.GetHighForSerialization();
serialized_state->guid_low = guid.GetLowForSerialization();
serialized_state->padding = 0;
- handles[0] = shared_buffer_->DuplicatePlatformHandleForIPC();
- if (!handles[0].is_valid()) {
- shared_buffer_ = nullptr;
- return false;
+ auto region = std::move(region_);
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+ (!defined(OS_MACOSX) || defined(OS_IOS))
+ if (region.GetMode() ==
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
+ ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &handles[0], &handles[1]);
+ return true;
}
+#endif
+
+ ScopedInternalPlatformHandle ignored_handle;
+ ExtractInternalPlatformHandlesFromSharedMemoryRegionHandle(
+ region.PassPlatformHandle(), &handles[0], &ignored_handle);
return true;
}
@@ -283,42 +372,46 @@ bool SharedBufferDispatcher::BeginTransit() {
base::AutoLock lock(lock_);
if (in_transit_)
return false;
- in_transit_ = static_cast<bool>(shared_buffer_);
+ in_transit_ = region_.IsValid();
return in_transit_;
}
void SharedBufferDispatcher::CompleteTransitAndClose() {
base::AutoLock lock(lock_);
in_transit_ = false;
- shared_buffer_ = nullptr;
- ignore_result(handle_for_transit_.release());
+ region_ = base::subtle::PlatformSharedMemoryRegion();
}
void SharedBufferDispatcher::CancelTransit() {
base::AutoLock lock(lock_);
in_transit_ = false;
- handle_for_transit_.reset();
}
SharedBufferDispatcher::SharedBufferDispatcher(
- scoped_refptr<PlatformSharedBuffer> shared_buffer)
- : shared_buffer_(shared_buffer) {
- DCHECK(shared_buffer_);
+ base::subtle::PlatformSharedMemoryRegion region)
+ : region_(std::move(region)) {
+ DCHECK(region_.IsValid());
}
SharedBufferDispatcher::~SharedBufferDispatcher() {
- DCHECK(!shared_buffer_ && !in_transit_);
+ DCHECK(!region_.IsValid() && !in_transit_);
+}
+
+// static
+scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::CreateInternal(
+ base::subtle::PlatformSharedMemoryRegion region) {
+ return base::WrapRefCounted(new SharedBufferDispatcher(std::move(region)));
}
// static
MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
const MojoDuplicateBufferHandleOptions* in_options,
MojoDuplicateBufferHandleOptions* out_options) {
- const MojoDuplicateBufferHandleOptionsFlags kKnownFlags =
- MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY;
+ const MojoDuplicateBufferHandleFlags kKnownFlags =
+ MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY;
static const MojoDuplicateBufferHandleOptions kDefaultOptions = {
static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)),
- MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
+ MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_NONE};
*out_options = kDefaultOptions;
if (!in_options)
diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher.h b/chromium/mojo/edk/system/shared_buffer_dispatcher.h
index fcaf5c19139..30c0dd6f60e 100644
--- a/chromium/mojo/edk/system/shared_buffer_dispatcher.h
+++ b/chromium/mojo/edk/system/shared_buffer_dispatcher.h
@@ -11,7 +11,7 @@
#include <utility>
#include "base/macros.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "base/memory/platform_shared_memory_region.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/system_impl_export.h"
@@ -19,7 +19,9 @@
namespace mojo {
namespace edk {
+
class NodeController;
+class PlatformSharedMemoryMapping;
class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
public:
@@ -48,8 +50,8 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
scoped_refptr<SharedBufferDispatcher>* result);
// Create a |SharedBufferDispatcher| from |shared_buffer|.
- static MojoResult CreateFromPlatformSharedBuffer(
- const scoped_refptr<PlatformSharedBuffer>& shared_buffer,
+ static MojoResult CreateFromPlatformSharedMemoryRegion(
+ base::subtle::PlatformSharedMemoryRegion region,
scoped_refptr<SharedBufferDispatcher>* result);
// The "opposite" of SerializeAndClose(). Called by Dispatcher::Deserialize().
@@ -58,12 +60,17 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
size_t num_bytes,
const ports::PortName* ports,
size_t num_ports,
- ScopedPlatformHandle* platform_handles,
+ ScopedInternalPlatformHandle* platform_handles,
size_t num_handles);
- // Passes the underlying platform shared buffer. This dispatcher must be
+ // Passes the underlying PlatformSharedMemoryRegion. This dispatcher must be
// closed after calling this function.
- scoped_refptr<PlatformSharedBuffer> PassPlatformSharedBuffer();
+ base::subtle::PlatformSharedMemoryRegion PassPlatformSharedMemoryRegion();
+
+ // NOTE: This is not thread-safe. Definitely never use it outside of tests.
+ base::subtle::PlatformSharedMemoryRegion& GetRegionForTesting() {
+ return region_;
+ }
// Dispatcher:
Type GetType() const override;
@@ -74,30 +81,26 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
MojoResult MapBuffer(
uint64_t offset,
uint64_t num_bytes,
- MojoMapBufferFlags flags,
- std::unique_ptr<PlatformSharedBufferMapping>* mapping) override;
+ std::unique_ptr<PlatformSharedMemoryMapping>* mapping) override;
MojoResult GetBufferInfo(MojoSharedBufferInfo* info) override;
void StartSerialize(uint32_t* num_bytes,
uint32_t* num_ports,
uint32_t* num_platform_handles) override;
bool EndSerialize(void* destination,
ports::PortName* ports,
- ScopedPlatformHandle* handles) override;
+ ScopedInternalPlatformHandle* handles) override;
bool BeginTransit() override;
void CompleteTransitAndClose() override;
void CancelTransit() override;
private:
- static scoped_refptr<SharedBufferDispatcher> CreateInternal(
- scoped_refptr<PlatformSharedBuffer> shared_buffer) {
- return base::WrapRefCounted(
- new SharedBufferDispatcher(std::move(shared_buffer)));
- }
-
explicit SharedBufferDispatcher(
- scoped_refptr<PlatformSharedBuffer> shared_buffer);
+ base::subtle::PlatformSharedMemoryRegion region);
~SharedBufferDispatcher() override;
+ static scoped_refptr<SharedBufferDispatcher> CreateInternal(
+ base::subtle::PlatformSharedMemoryRegion region);
+
// Validates and/or sets default options for
// |MojoDuplicateBufferHandleOptions|. If non-null, |in_options| must point to
// a struct of at least |in_options->struct_size| bytes. |out_options| must
@@ -107,16 +110,11 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher {
const MojoDuplicateBufferHandleOptions* in_options,
MojoDuplicateBufferHandleOptions* out_options);
- // Guards access to |shared_buffer_|.
+ // Guards access to the fields below.
base::Lock lock_;
bool in_transit_ = false;
-
- // We keep a copy of the buffer's platform handle during transit so we can
- // close it if something goes wrong.
- ScopedPlatformHandle handle_for_transit_;
-
- scoped_refptr<PlatformSharedBuffer> shared_buffer_;
+ base::subtle::PlatformSharedMemoryRegion region_;
DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher);
};
diff --git a/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc
index 5348c5f18e4..768c7aa7475 100644
--- a/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc
+++ b/chromium/mojo/edk/system/shared_buffer_dispatcher_unittest.cc
@@ -10,9 +10,11 @@
#include <limits>
#include "base/macros.h"
+#include "base/memory/platform_shared_memory_region.h"
#include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/platform_shared_buffer.h"
+#include "base/memory/writable_shared_memory_region.h"
#include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/system/platform_shared_memory_mapping.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
@@ -62,10 +64,10 @@ TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
}
// Different flags.
- MojoCreateSharedBufferOptionsFlags flags_values[] = {
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
+ MojoCreateSharedBufferFlags flags_values[] = {
+ MOJO_CREATE_SHARED_BUFFER_FLAG_NONE};
for (size_t i = 0; i < arraysize(flags_values); i++) {
- const MojoCreateSharedBufferOptionsFlags flags = flags_values[i];
+ const MojoCreateSharedBufferFlags flags = flags_values[i];
// Different capacities (size 1).
for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
@@ -88,8 +90,8 @@ TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
// Invalid |struct_size|.
{
MojoCreateSharedBufferOptions options = {
- 1, // |struct_size|.
- MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE // |flags|.
+ 1, // |struct_size|.
+ MOJO_CREATE_SHARED_BUFFER_FLAG_NONE // |flags|.
};
MojoCreateSharedBufferOptions unused;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
@@ -119,18 +121,16 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) {
EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType());
// Make a couple of mappings.
- std::unique_ptr<PlatformSharedBufferMapping> mapping1;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1));
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping1;
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, &mapping1));
ASSERT_TRUE(mapping1);
ASSERT_TRUE(mapping1->GetBase());
EXPECT_EQ(100u, mapping1->GetLength());
// Write something.
static_cast<char*>(mapping1->GetBase())[50] = 'x';
- std::unique_ptr<PlatformSharedBufferMapping> mapping2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2));
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping2;
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(50, 50, &mapping2));
ASSERT_TRUE(mapping2);
ASSERT_TRUE(mapping2->GetBase());
EXPECT_EQ(50u, mapping2->GetLength());
@@ -145,29 +145,29 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) {
}
TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) {
- scoped_refptr<PlatformSharedBuffer> platform_shared_buffer =
- PlatformSharedBuffer::Create(100);
- ASSERT_TRUE(platform_shared_buffer);
+ base::WritableSharedMemoryRegion region =
+ base::WritableSharedMemoryRegion::Create(100);
+ ASSERT_TRUE(region.IsValid());
scoped_refptr<SharedBufferDispatcher> dispatcher;
EXPECT_EQ(MOJO_RESULT_OK,
- SharedBufferDispatcher::CreateFromPlatformSharedBuffer(
- platform_shared_buffer, &dispatcher));
+ SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
+ base::WritableSharedMemoryRegion::TakeHandleForSerialization(
+ std::move(region)),
+ &dispatcher));
ASSERT_TRUE(dispatcher);
EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType());
// Make a couple of mappings.
- std::unique_ptr<PlatformSharedBufferMapping> mapping1;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1));
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping1;
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, &mapping1));
ASSERT_TRUE(mapping1);
ASSERT_TRUE(mapping1->GetBase());
EXPECT_EQ(100u, mapping1->GetLength());
// Write something.
static_cast<char*>(mapping1->GetBase())[50] = 'x';
- std::unique_ptr<PlatformSharedBufferMapping> mapping2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(
- 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2));
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping2;
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(50, 50, &mapping2));
ASSERT_TRUE(mapping2);
ASSERT_TRUE(mapping2->GetBase());
EXPECT_EQ(50u, mapping2->GetLength());
@@ -188,9 +188,8 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) {
nullptr, 100, &dispatcher1));
// Map and write something.
- std::unique_ptr<PlatformSharedBufferMapping> mapping;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping;
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer(0, 100, &mapping));
static_cast<char*>(mapping->GetBase())[0] = 'x';
mapping.reset();
@@ -204,8 +203,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) {
EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
// Map |dispatcher2| and read something.
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(
- 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(0, 100, &mapping));
EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]);
EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
@@ -217,29 +215,57 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) {
SharedBufferDispatcher::kDefaultCreateOptions,
nullptr, 100, &dispatcher1));
- // NOTE: On Android, once a region has been mapped read-only, it cannot
- // be mapped writable anymore, so ensure that the READ_ONLY case
- // appears last in the options[] table below.
- MojoDuplicateBufferHandleOptions options[] = {
- {sizeof(MojoDuplicateBufferHandleOptionsFlags), ~0u},
- {sizeof(MojoDuplicateBufferHandleOptions),
- MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE},
- {sizeof(MojoDuplicateBufferHandleOptions),
- MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY}};
- for (size_t i = 0; i < arraysize(options); i++) {
- scoped_refptr<Dispatcher> dispatcher2;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
- &options[i], &dispatcher2));
- ASSERT_TRUE(dispatcher2);
- EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType());
- {
- std::unique_ptr<PlatformSharedBufferMapping> mapping;
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(0, 100, 0, &mapping));
- }
- EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
+ scoped_refptr<SharedBufferDispatcher> dispatcher2;
+ EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
+ SharedBufferDispatcher::kDefaultCreateOptions,
+ nullptr, 100, &dispatcher2));
+
+ MojoDuplicateBufferHandleOptions kReadOnlyOptions = {
+ sizeof(MojoCreateSharedBufferOptions),
+ MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY};
+
+ // NOTE: We forbid handles from being duplicated read-only after they've been
+ // duplicated non-read-only; conversely we also forbid handles from being
+ // duplicated non-read-only after they've been duplicated read-only.
+ scoped_refptr<Dispatcher> writable_duped_dispatcher1;
+ scoped_refptr<Dispatcher> read_only_duped_dispatcher1;
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
+ nullptr, &writable_duped_dispatcher1));
+ EXPECT_TRUE(writable_duped_dispatcher1);
+ EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER,
+ writable_duped_dispatcher1->GetType());
+ {
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ writable_duped_dispatcher1->MapBuffer(0, 100, &mapping));
}
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ dispatcher1->DuplicateBufferHandle(&kReadOnlyOptions,
+ &read_only_duped_dispatcher1));
+ EXPECT_FALSE(read_only_duped_dispatcher1);
+
+ scoped_refptr<Dispatcher> read_only_duped_dispatcher2;
+ scoped_refptr<Dispatcher> writable_duped_dispatcher2;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ dispatcher2->DuplicateBufferHandle(&kReadOnlyOptions,
+ &read_only_duped_dispatcher2));
+ EXPECT_TRUE(read_only_duped_dispatcher2);
+ EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER,
+ read_only_duped_dispatcher2->GetType());
+ {
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ read_only_duped_dispatcher2->MapBuffer(0, 100, &mapping));
+ }
+ EXPECT_EQ(
+ MOJO_RESULT_FAILED_PRECONDITION,
+ dispatcher2->DuplicateBufferHandle(nullptr, &writable_duped_dispatcher2));
+ EXPECT_FALSE(writable_duped_dispatcher2);
EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
+ EXPECT_EQ(MOJO_RESULT_OK, writable_duped_dispatcher1->Close());
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
+ EXPECT_EQ(MOJO_RESULT_OK, read_only_duped_dispatcher2->Close());
}
TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
@@ -251,7 +277,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
// Invalid |struct_size|.
{
MojoDuplicateBufferHandleOptions options = {
- 1u, MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
+ 1u, MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_NONE};
scoped_refptr<Dispatcher> dispatcher2;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
@@ -294,17 +320,20 @@ TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
SharedBufferDispatcher::kDefaultCreateOptions,
nullptr, 100, &dispatcher));
- std::unique_ptr<PlatformSharedBufferMapping> mapping;
+ MojoSharedBufferInfo info = {sizeof(info), 0u};
+ EXPECT_EQ(MOJO_RESULT_OK, dispatcher->GetBufferInfo(&info));
+
+ std::unique_ptr<PlatformSharedMemoryMapping> mapping;
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+ dispatcher->MapBuffer(0, info.size + 1, &mapping));
EXPECT_FALSE(mapping);
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher->MapBuffer(1, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+ dispatcher->MapBuffer(1, info.size, &mapping));
EXPECT_FALSE(mapping);
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- dispatcher->MapBuffer(0, 0, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+ dispatcher->MapBuffer(0, 0, &mapping));
EXPECT_FALSE(mapping);
EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
diff --git a/chromium/mojo/edk/system/shared_buffer_unittest.cc b/chromium/mojo/edk/system/shared_buffer_unittest.cc
index af2c7beb570..2e09b60059d 100644
--- a/chromium/mojo/edk/system/shared_buffer_unittest.cc
+++ b/chromium/mojo/edk/system/shared_buffer_unittest.cc
@@ -10,6 +10,8 @@
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/strings/string_piece.h"
+#include "mojo/edk/system/core.h"
+#include "mojo/edk/system/shared_buffer_dispatcher.h"
#include "mojo/edk/test/mojo_test_base.h"
#include "mojo/public/c/system/types.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -238,14 +240,13 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndMapWriteSharedBuffer,
// Read from the bufer.
ExpectBufferContents(b, 0, "hello");
- // Extract the shared memory handle and try to map it writable.
- base::SharedMemoryHandle shm_handle;
- bool read_only = false;
- ASSERT_EQ(MOJO_RESULT_OK,
- PassSharedMemoryHandle(b, &shm_handle, nullptr, &read_only));
- base::SharedMemory shared_memory(shm_handle, false);
- EXPECT_TRUE(read_only);
- EXPECT_FALSE(shared_memory.Map(1234));
+ // Extract the shared memory handle and verify that it is read-only.
+ auto* dispatcher =
+ static_cast<SharedBufferDispatcher*>(Core::Get()->GetDispatcher(b).get());
+ base::subtle::PlatformSharedMemoryRegion& region =
+ dispatcher->GetRegionForTesting();
+ EXPECT_EQ(region.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly);
EXPECT_EQ("quit", ReadMessage(h));
WriteMessage(h, "ok");
@@ -301,14 +302,13 @@ TEST_F(SharedBufferTest, MAYBE_CreateAndPassFromChildReadOnlyBuffer) {
EXPECT_EQ("", ReadMessageWithHandles(h, &b, 1));
ExpectBufferContents(b, 0, "hello");
- // Extract the shared memory handle and try to map it writable.
- base::SharedMemoryHandle shm_handle;
- bool read_only = false;
- ASSERT_EQ(MOJO_RESULT_OK,
- PassSharedMemoryHandle(b, &shm_handle, nullptr, &read_only));
- base::SharedMemory shared_memory(shm_handle, false);
- EXPECT_TRUE(read_only);
- EXPECT_FALSE(shared_memory.Map(1234));
+ // Extract the shared memory handle and verify that it is read-only.
+ auto* dispatcher = static_cast<SharedBufferDispatcher*>(
+ Core::Get()->GetDispatcher(b).get());
+ base::subtle::PlatformSharedMemoryRegion& region =
+ dispatcher->GetRegionForTesting();
+ EXPECT_EQ(region.GetMode(),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly);
WriteMessage(h, "quit");
EXPECT_EQ("ok", ReadMessage(h));
diff --git a/chromium/mojo/edk/system/signals_unittest.cc b/chromium/mojo/edk/system/signals_unittest.cc
index becba29e6ff..34f2105ea94 100644
--- a/chromium/mojo/edk/system/signals_unittest.cc
+++ b/chromium/mojo/edk/system/signals_unittest.cc
@@ -159,7 +159,7 @@ TEST_F(SignalsTest, RemotePeers) {
// And so should |c| after we fuse |d| to |a|.
MojoHandle c, d;
CreateMessagePipe(&c, &d);
- EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(d, a));
+ EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(d, a, nullptr));
EXPECT_EQ(MOJO_RESULT_OK,
WaitForSignals(c, MOJO_HANDLE_SIGNAL_PEER_REMOTE,
MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED));
diff --git a/chromium/mojo/edk/system/trap_unittest.cc b/chromium/mojo/edk/system/trap_unittest.cc
index 3081a223019..011f988020e 100644
--- a/chromium/mojo/edk/system/trap_unittest.cc
+++ b/chromium/mojo/edk/system/trap_unittest.cc
@@ -448,9 +448,11 @@ TEST_F(WatcherTest, WatchDataPipeConsumerNewDataReadable) {
// NEW_DATA_READABLE signal.
char large_buffer[512];
uint32_t large_read_size = 512;
+ MojoReadDataOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_READ_DATA_FLAG_ALL_OR_NONE;
EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
- MojoReadData(consumer, large_buffer, &large_read_size,
- MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+ MojoReadData(consumer, &options, large_buffer, &large_read_size));
// Attempt to arm again. Should succeed.
EXPECT_EQ(MOJO_RESULT_OK,
@@ -1746,10 +1748,8 @@ void ReadAllMessages(const MojoTrapEvent* event) {
if (event->result == MOJO_RESULT_OK) {
MojoHandle handle = static_cast<MojoHandle>(event->trigger_context);
MojoMessageHandle message;
- while (MojoReadMessage(handle, &message, MOJO_READ_MESSAGE_FLAG_NONE) ==
- MOJO_RESULT_OK) {
+ while (MojoReadMessage(handle, nullptr, &message) == MOJO_RESULT_OK)
MojoDestroyMessage(message);
- }
}
constexpr size_t kNumRandomThingsToDoOnNotify = 5;
@@ -1780,7 +1780,7 @@ void DoRandomThing(MojoHandle* watchers,
ASSERT_EQ(MOJO_RESULT_OK,
MojoSetMessageContext(message, 1, nullptr, nullptr, nullptr));
MojoWriteMessage(RandomHandle(watched_handles, num_watched_handles),
- message, MOJO_WRITE_MESSAGE_FLAG_NONE);
+ message, nullptr);
break;
}
case 5:
diff --git a/chromium/mojo/edk/system/user_message_impl.cc b/chromium/mojo/edk/system/user_message_impl.cc
index c894aa5e740..dc36c1f99e7 100644
--- a/chromium/mojo/edk/system/user_message_impl.cc
+++ b/chromium/mojo/edk/system/user_message_impl.cc
@@ -152,7 +152,7 @@ MojoResult CreateOrExtendSerializedEventMessage(
DispatcherHeader* new_dispatcher_headers;
char* new_dispatcher_data;
size_t total_num_dispatchers = num_new_dispatchers;
- std::vector<ScopedPlatformHandle> handles;
+ std::vector<ScopedInternalPlatformHandle> handles;
if (original_message) {
DCHECK(original_header);
size_t original_dispatcher_headers_size =
@@ -582,7 +582,7 @@ MojoResult UserMessageImpl::ExtractSerializedHandles(
dispatcher_headers + header->num_dispatchers);
size_t port_index = 0;
size_t platform_handle_index = 0;
- std::vector<ScopedPlatformHandle> msg_handles =
+ std::vector<ScopedInternalPlatformHandle> msg_handles =
channel_message_->TakeHandles();
for (size_t i = 0; i < header->num_dispatchers; ++i) {
const DispatcherHeader& dh = dispatcher_headers[i];
@@ -610,7 +610,7 @@ MojoResult UserMessageImpl::ExtractSerializedHandles(
return MOJO_RESULT_ABORTED;
}
- ScopedPlatformHandle* out_handles =
+ ScopedInternalPlatformHandle* out_handles =
!msg_handles.empty() ? msg_handles.data() + platform_handle_index
: nullptr;
dispatchers[i].dispatcher = Dispatcher::Deserialize(