| Index: mojo/edk/system/child_broker.cc
|
| diff --git a/mojo/edk/system/child_broker.cc b/mojo/edk/system/child_broker.cc
|
| deleted file mode 100644
|
| index 7a79173f7446a3f9b4ece3d22263f451ea1f2f49..0000000000000000000000000000000000000000
|
| --- a/mojo/edk/system/child_broker.cc
|
| +++ /dev/null
|
| @@ -1,348 +0,0 @@
|
| -// Copyright 2015 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/child_broker.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include <utility>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/logging.h"
|
| -#include "mojo/edk/embedder/embedder_internal.h"
|
| -#include "mojo/edk/embedder/platform_channel_pair.h"
|
| -#include "mojo/edk/system/broker_messages.h"
|
| -#include "mojo/edk/system/message_pipe_dispatcher.h"
|
| -
|
| -namespace mojo {
|
| -namespace edk {
|
| -
|
| -ChildBroker* ChildBroker::GetInstance() {
|
| - return base::Singleton<
|
| - ChildBroker, base::LeakySingletonTraits<ChildBroker>>::get();
|
| -}
|
| -
|
| -void ChildBroker::SetChildBrokerHostHandle(ScopedPlatformHandle handle) {
|
| - ScopedPlatformHandle parent_async_channel_handle;
|
| -#if defined(OS_POSIX)
|
| - parent_async_channel_handle = std::move(handle);
|
| -#else
|
| - // On Windows we have two pipes to the parent. The first is for the token
|
| - // exchange for creating and passing handles, since the child needs the
|
| - // parent's help if it is sandboxed. The second is the same as POSIX, which is
|
| - // used for multiplexing related messages. So on Windows, we send the second
|
| - // pipe as the first string over the first one.
|
| - parent_sync_channel_ = std::move(handle);
|
| -
|
| - HANDLE parent_handle = INVALID_HANDLE_VALUE;
|
| - DWORD bytes_read = 0;
|
| - BOOL rv = ReadFile(parent_sync_channel_.get().handle, &parent_handle,
|
| - sizeof(parent_handle), &bytes_read, NULL);
|
| - CHECK(rv);
|
| - parent_async_channel_handle.reset(PlatformHandle(parent_handle));
|
| - sync_channel_lock_.Unlock();
|
| -#endif
|
| -
|
| - internal::g_io_thread_task_runner->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ChildBroker::InitAsyncChannel, base::Unretained(this),
|
| - base::Passed(&parent_async_channel_handle)));
|
| -}
|
| -
|
| -#if defined(OS_WIN)
|
| -void ChildBroker::CreatePlatformChannelPair(
|
| - ScopedPlatformHandle* server, ScopedPlatformHandle* client) {
|
| - sync_channel_lock_.Lock();
|
| - CreatePlatformChannelPairNoLock(server, client);
|
| - sync_channel_lock_.Unlock();
|
| -}
|
| -
|
| -void ChildBroker::HandleToToken(const PlatformHandle* platform_handles,
|
| - size_t count,
|
| - uint64_t* tokens) {
|
| - uint32_t size = kBrokerMessageHeaderSize +
|
| - static_cast<int>(count) * sizeof(HANDLE);
|
| - std::vector<char> message_buffer(size);
|
| - BrokerMessage* message = reinterpret_cast<BrokerMessage*>(&message_buffer[0]);
|
| - message->size = size;
|
| - message->id = HANDLE_TO_TOKEN;
|
| - for (size_t i = 0; i < count; ++i)
|
| - message->handles[i] = platform_handles[i].handle;
|
| -
|
| - uint32_t response_size = static_cast<int>(count) * sizeof(uint64_t);
|
| - sync_channel_lock_.Lock();
|
| - WriteAndReadResponse(message, tokens, response_size);
|
| - sync_channel_lock_.Unlock();
|
| -}
|
| -
|
| -void ChildBroker::TokenToHandle(const uint64_t* tokens,
|
| - size_t count,
|
| - PlatformHandle* handles) {
|
| - uint32_t size = kBrokerMessageHeaderSize +
|
| - static_cast<int>(count) * sizeof(uint64_t);
|
| - std::vector<char> message_buffer(size);
|
| - BrokerMessage* message =
|
| - reinterpret_cast<BrokerMessage*>(&message_buffer[0]);
|
| - message->size = size;
|
| - message->id = TOKEN_TO_HANDLE;
|
| - memcpy(&message->tokens[0], tokens, count * sizeof(uint64_t));
|
| -
|
| - std::vector<HANDLE> handles_temp(count);
|
| - uint32_t response_size =
|
| - static_cast<uint32_t>(handles_temp.size()) * sizeof(HANDLE);
|
| - sync_channel_lock_.Lock();
|
| - if (WriteAndReadResponse(message, &handles_temp[0], response_size)) {
|
| - for (uint32_t i = 0; i < count; ++i)
|
| - handles[i].handle = handles_temp[i];
|
| - sync_channel_lock_.Unlock();
|
| - }
|
| -}
|
| -#endif
|
| -
|
| -void ChildBroker::ConnectMessagePipe(uint64_t pipe_id,
|
| - MessagePipeDispatcher* message_pipe) {
|
| - DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
|
| -
|
| - ConnectMessagePipeMessage data;
|
| - memset(&data, 0, sizeof(data));
|
| - data.pipe_id = pipe_id;
|
| - if (pending_connects_.find(pipe_id) != pending_connects_.end()) {
|
| - if (!parent_async_channel_) {
|
| - // On Windows, we can't create the local RoutedRawChannel yet because we
|
| - // don't have parent_sync_channel_. Treat all platforms the same and just
|
| - // queue this.
|
| - CHECK(pending_inprocess_connects_.find(pipe_id) ==
|
| - pending_inprocess_connects_.end());
|
| - pending_inprocess_connects_[pipe_id] = message_pipe;
|
| - return;
|
| - }
|
| - // Both ends of the message pipe are in the same process.
|
| - // First, tell the browser side that to remove its bookkeeping for a pending
|
| - // connect, since it'll never get the other side.
|
| -
|
| - data.type = CANCEL_CONNECT_MESSAGE_PIPE;
|
| - scoped_ptr<MessageInTransit> message(new MessageInTransit(
|
| - MessageInTransit::Type::MESSAGE, sizeof(data), &data));
|
| - WriteAsyncMessage(std::move(message));
|
| -
|
| - if (!in_process_pipes_channel1_) {
|
| - ScopedPlatformHandle server_handle, client_handle;
|
| -#if defined(OS_WIN)
|
| - CreatePlatformChannelPairNoLock(&server_handle, &client_handle);
|
| -#else
|
| - PlatformChannelPair channel_pair;
|
| - server_handle = channel_pair.PassServerHandle();
|
| - client_handle = channel_pair.PassClientHandle();
|
| -#endif
|
| - in_process_pipes_channel1_ = new RoutedRawChannel(
|
| - std::move(server_handle),
|
| - base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
|
| - in_process_pipes_channel2_ = new RoutedRawChannel(
|
| - std::move(client_handle),
|
| - base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
|
| - }
|
| -
|
| - AttachMessagePipe(pending_connects_[pipe_id], pipe_id,
|
| - in_process_pipes_channel1_);
|
| - AttachMessagePipe(message_pipe, pipe_id, in_process_pipes_channel2_);
|
| - pending_connects_.erase(pipe_id);
|
| - return;
|
| - }
|
| -
|
| - data.type = CONNECT_MESSAGE_PIPE;
|
| - scoped_ptr<MessageInTransit> message(new MessageInTransit(
|
| - MessageInTransit::Type::MESSAGE, sizeof(data), &data));
|
| - pending_connects_[pipe_id] = message_pipe;
|
| - WriteAsyncMessage(std::move(message));
|
| -}
|
| -
|
| -void ChildBroker::CloseMessagePipe(
|
| - uint64_t pipe_id, MessagePipeDispatcher* message_pipe) {
|
| - DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
|
| - CHECK(connected_pipes_.find(message_pipe) != connected_pipes_.end());
|
| - connected_pipes_[message_pipe]->RemoveRoute(pipe_id);
|
| - connected_pipes_.erase(message_pipe);
|
| -}
|
| -
|
| -ChildBroker::ChildBroker()
|
| - : parent_async_channel_(nullptr),
|
| - in_process_pipes_channel1_(nullptr),
|
| - in_process_pipes_channel2_(nullptr) {
|
| - DCHECK(!internal::g_broker);
|
| - internal::g_broker = this;
|
| -#if defined(OS_WIN)
|
| - // Block any threads from calling this until we have a pipe to the parent.
|
| - sync_channel_lock_.Lock();
|
| -#endif
|
| -}
|
| -
|
| -ChildBroker::~ChildBroker() {
|
| -}
|
| -
|
| -void ChildBroker::OnReadMessage(
|
| - const MessageInTransit::View& message_view,
|
| - ScopedPlatformHandleVectorPtr platform_handles) {
|
| - DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
|
| - MultiplexMessages type =
|
| - *static_cast<const MultiplexMessages*>(message_view.bytes());
|
| - if (type == CONNECT_TO_PROCESS) {
|
| - DCHECK_EQ(platform_handles->size(), 1u);
|
| - ScopedPlatformHandle handle((*platform_handles.get())[0]);
|
| - (*platform_handles.get())[0] = PlatformHandle();
|
| -
|
| - const ConnectToProcessMessage* message =
|
| - static_cast<const ConnectToProcessMessage*>(message_view.bytes());
|
| -
|
| - CHECK(channels_.find(message->process_id) == channels_.end());
|
| - channels_[message->process_id] = new RoutedRawChannel(
|
| - std::move(handle),
|
| - base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
|
| - } else if (type == PEER_PIPE_CONNECTED) {
|
| - DCHECK(!platform_handles);
|
| - const PeerPipeConnectedMessage* message =
|
| - static_cast<const PeerPipeConnectedMessage*>(message_view.bytes());
|
| -
|
| - uint64_t pipe_id = message->pipe_id;
|
| - uint64_t peer_pid = message->process_id;
|
| -
|
| - CHECK(pending_connects_.find(pipe_id) != pending_connects_.end());
|
| - MessagePipeDispatcher* pipe = pending_connects_[pipe_id];
|
| - pending_connects_.erase(pipe_id);
|
| - if (peer_pid == 0) {
|
| - // The other side is in the parent process.
|
| - AttachMessagePipe(pipe, pipe_id, parent_async_channel_);
|
| - } else if (channels_.find(peer_pid) == channels_.end()) {
|
| - // We saw the peer process die before we got the reply from the parent.
|
| - pipe->OnError(ERROR_READ_SHUTDOWN);
|
| - } else {
|
| - CHECK(connected_pipes_.find(pipe) == connected_pipes_.end());
|
| - AttachMessagePipe(pipe, pipe_id, channels_[peer_pid]);
|
| - }
|
| - } else if (type == PEER_DIED) {
|
| - DCHECK(!platform_handles);
|
| - const PeerDiedMessage* message =
|
| - static_cast<const PeerDiedMessage*>(message_view.bytes());
|
| -
|
| - uint64_t pipe_id = message->pipe_id;
|
| -
|
| - CHECK(pending_connects_.find(pipe_id) != pending_connects_.end());
|
| - MessagePipeDispatcher* pipe = pending_connects_[pipe_id];
|
| - pending_connects_.erase(pipe_id);
|
| - pipe->OnError(ERROR_READ_SHUTDOWN);
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| -}
|
| -
|
| -void ChildBroker::OnError(Error error) {
|
| - // The parent process shut down.
|
| -}
|
| -
|
| -void ChildBroker::ChannelDestructed(RoutedRawChannel* channel) {
|
| - DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
|
| - for (auto it : channels_) {
|
| - if (it.second == channel) {
|
| - channels_.erase(it.first);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void ChildBroker::WriteAsyncMessage(scoped_ptr<MessageInTransit> message) {
|
| - DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
|
| - message->set_route_id(kBrokerRouteId);
|
| - if (parent_async_channel_) {
|
| - parent_async_channel_->channel()->WriteMessage(std::move(message));
|
| - } else {
|
| - async_channel_queue_.AddMessage(std::move(message));
|
| - }
|
| -}
|
| -
|
| -void ChildBroker::InitAsyncChannel(
|
| - ScopedPlatformHandle parent_async_channel_handle) {
|
| - DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread());
|
| -
|
| - parent_async_channel_ = new RoutedRawChannel(
|
| - std::move(parent_async_channel_handle),
|
| - base::Bind(&ChildBroker::ChannelDestructed, base::Unretained(this)));
|
| - parent_async_channel_->AddRoute(kBrokerRouteId, this);
|
| - while (!async_channel_queue_.IsEmpty()) {
|
| - parent_async_channel_->channel()->WriteMessage(
|
| - async_channel_queue_.GetMessage());
|
| - }
|
| -
|
| - while (!pending_inprocess_connects_.empty()) {
|
| - ConnectMessagePipe(pending_inprocess_connects_.begin()->first,
|
| - pending_inprocess_connects_.begin()->second);
|
| - pending_inprocess_connects_.erase(pending_inprocess_connects_.begin());
|
| - }
|
| -}
|
| -
|
| -void ChildBroker::AttachMessagePipe(MessagePipeDispatcher* message_pipe,
|
| - uint64_t pipe_id,
|
| - RoutedRawChannel* raw_channel) {
|
| - connected_pipes_[message_pipe] = raw_channel;
|
| - // Note: we must call GotNonTransferableChannel before AddRoute because there
|
| - // could be race conditions if the pipe got queued messages in |AddRoute| but
|
| - // then when it's read it returns no messages because it doesn't have the
|
| - // channel yet.
|
| - message_pipe->GotNonTransferableChannel(raw_channel->channel());
|
| - // The above call could have caused |CloseMessagePipe| to be called.
|
| - if (connected_pipes_.find(message_pipe) != connected_pipes_.end())
|
| - raw_channel->AddRoute(pipe_id, message_pipe);
|
| -}
|
| -
|
| -#if defined(OS_WIN)
|
| -
|
| -bool ChildBroker::WriteAndReadResponse(BrokerMessage* message,
|
| - void* response,
|
| - uint32_t response_size) {
|
| - CHECK(parent_sync_channel_.is_valid());
|
| -
|
| - bool result = true;
|
| - DWORD bytes_written = 0;
|
| - // This will always write in one chunk per
|
| - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150.aspx.
|
| - BOOL rv = WriteFile(parent_sync_channel_.get().handle, message, message->size,
|
| - &bytes_written, NULL);
|
| - if (!rv || bytes_written != message->size) {
|
| - LOG(ERROR) << "Child token serializer couldn't write message.";
|
| - result = false;
|
| - } else {
|
| - while (response_size) {
|
| - DWORD bytes_read = 0;
|
| - rv = ReadFile(parent_sync_channel_.get().handle, response, response_size,
|
| - &bytes_read, NULL);
|
| - if (!rv) {
|
| - LOG(ERROR) << "Child token serializer couldn't read result.";
|
| - result = false;
|
| - break;
|
| - }
|
| - response_size -= bytes_read;
|
| - response = static_cast<char*>(response) + bytes_read;
|
| - }
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| -void ChildBroker::CreatePlatformChannelPairNoLock(
|
| - ScopedPlatformHandle* server, ScopedPlatformHandle* client) {
|
| - BrokerMessage message;
|
| - message.size = kBrokerMessageHeaderSize;
|
| - message.id = CREATE_PLATFORM_CHANNEL_PAIR;
|
| -
|
| - uint32_t response_size = 2 * sizeof(HANDLE);
|
| - HANDLE handles[2];
|
| - if (WriteAndReadResponse(&message, handles, response_size)) {
|
| - server->reset(PlatformHandle(handles[0]));
|
| - client->reset(PlatformHandle(handles[1]));
|
| - }
|
| -}
|
| -
|
| -#endif
|
| -
|
| -} // namespace edk
|
| -} // namespace mojo
|
|
|