summaryrefslogtreecommitdiff
path: root/chromium/mojo/edk/system/core.cc
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/core.cc
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/core.cc')
-rw-r--r--chromium/mojo/edk/system/core.cc849
1 files changed, 576 insertions, 273 deletions
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) {