// 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 "ipc/mojo/ipc_mojo_bootstrap.h" #include #include #include "base/logging.h" #include "base/macros.h" #include "base/process/process_handle.h" #include "build/build_config.h" #include "ipc/ipc_message_utils.h" #include "ipc/ipc_platform_file.h" #include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/public/cpp/bindings/binding.h" namespace IPC { namespace { // MojoBootstrap for the server process. You should create the instance // using MojoBootstrap::Create(). class MojoServerBootstrap : public MojoBootstrap { public: MojoServerBootstrap(); private: // MojoBootstrap implementation. void Connect() override; void OnInitDone(int32_t peer_pid); mojom::BootstrapPtr bootstrap_; IPC::mojom::ChannelAssociatedPtrInfo send_channel_; IPC::mojom::ChannelAssociatedRequest receive_channel_request_; DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap); }; MojoServerBootstrap::MojoServerBootstrap() = default; void MojoServerBootstrap::Connect() { DCHECK_EQ(state(), STATE_INITIALIZED); bootstrap_.Bind(mojom::BootstrapPtrInfo(TakeHandle(), 0)); bootstrap_.set_connection_error_handler( base::Bind(&MojoServerBootstrap::Fail, base::Unretained(this))); IPC::mojom::ChannelAssociatedRequest send_channel_request; IPC::mojom::ChannelAssociatedPtrInfo receive_channel; bootstrap_.associated_group()->CreateAssociatedInterface( mojo::AssociatedGroup::WILL_PASS_REQUEST, &send_channel_, &send_channel_request); bootstrap_.associated_group()->CreateAssociatedInterface( mojo::AssociatedGroup::WILL_PASS_PTR, &receive_channel, &receive_channel_request_); bootstrap_->Init( std::move(send_channel_request), std::move(receive_channel), GetSelfPID(), base::Bind(&MojoServerBootstrap::OnInitDone, base::Unretained(this))); set_state(STATE_WAITING_ACK); } void MojoServerBootstrap::OnInitDone(int32_t peer_pid) { if (state() != STATE_WAITING_ACK) { set_state(STATE_ERROR); LOG(ERROR) << "Got inconsistent message from client."; return; } set_state(STATE_READY); bootstrap_.set_connection_error_handler(mojo::Closure()); delegate()->OnPipesAvailable(std::move(send_channel_), std::move(receive_channel_request_), peer_pid); } // MojoBootstrap for client processes. You should create the instance // using MojoBootstrap::Create(). class MojoClientBootstrap : public MojoBootstrap, public mojom::Bootstrap { public: MojoClientBootstrap(); private: // MojoBootstrap implementation. void Connect() override; // mojom::Bootstrap implementation. void Init(mojom::ChannelAssociatedRequest receive_channel, mojom::ChannelAssociatedPtrInfo send_channel, int32_t peer_pid, const mojo::Callback& callback) override; mojo::Binding binding_; DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap); }; MojoClientBootstrap::MojoClientBootstrap() : binding_(this) {} void MojoClientBootstrap::Connect() { binding_.Bind(TakeHandle()); binding_.set_connection_error_handler( base::Bind(&MojoClientBootstrap::Fail, base::Unretained(this))); } void MojoClientBootstrap::Init(mojom::ChannelAssociatedRequest receive_channel, mojom::ChannelAssociatedPtrInfo send_channel, int32_t peer_pid, const mojo::Callback& callback) { callback.Run(GetSelfPID()); set_state(STATE_READY); binding_.set_connection_error_handler(mojo::Closure()); delegate()->OnPipesAvailable(std::move(send_channel), std::move(receive_channel), peer_pid); } } // namespace // MojoBootstrap // static scoped_ptr MojoBootstrap::Create( mojo::ScopedMessagePipeHandle handle, Channel::Mode mode, Delegate* delegate) { CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER); scoped_ptr self = mode == Channel::MODE_CLIENT ? scoped_ptr(new MojoClientBootstrap()) : scoped_ptr(new MojoServerBootstrap()); self->Init(std::move(handle), delegate); return self; } MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) { } MojoBootstrap::~MojoBootstrap() {} void MojoBootstrap::Init(mojo::ScopedMessagePipeHandle handle, Delegate* delegate) { handle_ = std::move(handle); delegate_ = delegate; } base::ProcessId MojoBootstrap::GetSelfPID() const { #if defined(OS_LINUX) if (int global_pid = Channel::GetGlobalPid()) return global_pid; #endif // OS_LINUX return base::GetCurrentProcId(); } void MojoBootstrap::Fail() { set_state(STATE_ERROR); delegate()->OnBootstrapError(); } bool MojoBootstrap::HasFailed() const { return state() == STATE_ERROR; } mojo::ScopedMessagePipeHandle MojoBootstrap::TakeHandle() { return std::move(handle_); } } // namespace IPC