| Index: mojo/edk/system/channel.cc
|
| diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
|
| index e74b9004758fd7851750ccd004314839ec9d9b3e..67c739854d06e68704616344b55feea719ff5f72 100644
|
| --- a/mojo/edk/system/channel.cc
|
| +++ b/mojo/edk/system/channel.cc
|
| @@ -8,11 +8,16 @@
|
|
|
| #include <algorithm>
|
| #include <limits>
|
| +#include <utility>
|
|
|
| #include "base/macros.h"
|
| #include "base/memory/aligned_memory.h"
|
| #include "mojo/edk/embedder/platform_handle.h"
|
|
|
| +#if defined(OS_MACOSX) && !defined(OS_IOS)
|
| +#include "base/mac/mach_logging.h"
|
| +#endif
|
| +
|
| namespace mojo {
|
| namespace edk {
|
|
|
| @@ -43,6 +48,12 @@ Channel::Message::Message(size_t payload_size,
|
| #if defined(OS_WIN)
|
| // On Windows we serialize platform handles into the extra header space.
|
| extra_header_size = max_handles_ * sizeof(PlatformHandle);
|
| +#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| + // On OSX, some of the platform handles may be mach ports, which are
|
| + // serialised into the message buffer. Since there could be a mix of fds and
|
| + // mach ports, we store the mach ports as an <index, port> pair (of uint32_t),
|
| + // so that the original ordering of handles can be re-created.
|
| + extra_header_size = max_handles * sizeof(MachPortsEntry);
|
| #endif
|
| // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes.
|
| if (extra_header_size % kChannelMessageAlignment) {
|
| @@ -78,14 +89,19 @@ Channel::Message::Message(size_t payload_size,
|
| static_cast<uint16_t>(sizeof(Header) + extra_header_size);
|
| #endif
|
|
|
| -#if defined(OS_WIN)
|
| if (max_handles_ > 0) {
|
| +#if defined(OS_WIN)
|
| handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header());
|
| // Initialize all handles to invalid values.
|
| for (size_t i = 0; i < max_handles_; ++i)
|
| handles()[i] = PlatformHandle();
|
| - }
|
| +#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| + mach_ports_ = reinterpret_cast<MachPortsEntry*>(mutable_extra_header());
|
| + // Initialize all handles to invalid values.
|
| + for (size_t i = 0; i < max_handles_; ++i)
|
| + mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)};
|
| #endif
|
| + }
|
| }
|
|
|
| Channel::Message::~Message() {
|
| @@ -100,9 +116,9 @@ Channel::Message::~Message() {
|
| // static
|
| Channel::MessagePtr Channel::Message::Deserialize(const void* data,
|
| size_t data_num_bytes) {
|
| -#if !defined(OS_WIN)
|
| +#if !defined(OS_WIN) && !(defined(OS_MACOSX) && !defined(OS_IOS))
|
| // We only serialize messages into other messages when performing message
|
| - // relay on Windows.
|
| + // relay on Windows and OSX.
|
| NOTREACHED();
|
| return nullptr;
|
| #else
|
| @@ -123,16 +139,19 @@ Channel::MessagePtr Channel::Message::Deserialize(const void* data,
|
| }
|
|
|
| uint32_t extra_header_size = header->num_header_bytes - sizeof(Header);
|
| +#if defined(OS_WIN)
|
| uint32_t max_handles = extra_header_size / sizeof(PlatformHandle);
|
| +#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| + uint32_t max_handles = extra_header_size / sizeof(MachPortsEntry);
|
| +#endif
|
| if (header->num_handles > max_handles) {
|
| - DLOG(ERROR) << "Decoding invalid message:" << header->num_handles << " > "
|
| - << max_handles;
|
| + DLOG(ERROR) << "Decoding invalid message:" << header->num_handles
|
| + << " > " << max_handles;
|
| return nullptr;
|
| }
|
|
|
| - MessagePtr message(
|
| - new Message(data_num_bytes - header->num_header_bytes, max_handles));
|
| -
|
| + MessagePtr message(new Message(data_num_bytes - header->num_header_bytes,
|
| + max_handles));
|
| DCHECK_EQ(message->data_num_bytes(), data_num_bytes);
|
| DCHECK_EQ(message->extra_header_size(), extra_header_size);
|
| DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes);
|
| @@ -184,8 +203,10 @@ bool Channel::Message::has_mach_ports() const {
|
| return false;
|
|
|
| for (const auto& handle : (*handle_vector_)) {
|
| - if (handle.type == PlatformHandle::Type::MACH)
|
| + if (handle.type == PlatformHandle::Type::MACH ||
|
| + handle.type == PlatformHandle::Type::MACH_NAME) {
|
| return true;
|
| + }
|
| }
|
| return false;
|
| }
|
| @@ -217,6 +238,21 @@ void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
|
| std::swap(handle_vector_, new_handles);
|
| #endif // defined(OS_WIN)
|
| #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID)
|
| +
|
| +#if defined(OS_MACOSX) && !defined(OS_IOS)
|
| + size_t mach_port_index = 0;
|
| + for (size_t i = 0; i < max_handles_; ++i)
|
| + mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)};
|
| + for (size_t i = 0; i < handle_vector_->size(); i++) {
|
| + if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH ||
|
| + (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) {
|
| + mach_port_t port = (*handle_vector_)[i].port;
|
| + mach_ports_[mach_port_index].index = i;
|
| + mach_ports_[mach_port_index].mach_port = port;
|
| + mach_port_index++;
|
| + }
|
| + }
|
| +#endif
|
| }
|
|
|
| ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
|
| @@ -227,7 +263,39 @@ ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
|
| new PlatformHandleVector(header_->num_handles));
|
| for (size_t i = 0; i < header_->num_handles; ++i)
|
| std::swap(moved_handles->at(i), handles()[i]);
|
| + header_->num_handles = 0;
|
| return moved_handles;
|
| +#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| + for (size_t i = 0; i < max_handles_; ++i)
|
| + mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)};
|
| + header_->num_handles = 0;
|
| + return std::move(handle_vector_);
|
| +#else
|
| + header_->num_handles = 0;
|
| + return std::move(handle_vector_);
|
| +#endif
|
| +}
|
| +
|
| +ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() {
|
| +#if defined(OS_WIN)
|
| + // Not necessary on Windows.
|
| + NOTREACHED();
|
| + return nullptr;
|
| +#elif defined(OS_MACOSX) && !defined(OS_IOS)
|
| + if (handle_vector_) {
|
| + for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) {
|
| + if (it->type == PlatformHandle::Type::MACH ||
|
| + it->type == PlatformHandle::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.
|
| + it = handle_vector_->erase(it);
|
| + } else {
|
| + ++it;
|
| + }
|
| + }
|
| + }
|
| + return std::move(handle_vector_);
|
| #else
|
| return std::move(handle_vector_);
|
| #endif
|
|
|