| Index: ipc/mojo/ipc_mojo_bootstrap.cc
|
| diff --git a/ipc/mojo/ipc_mojo_bootstrap.cc b/ipc/mojo/ipc_mojo_bootstrap.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0082fb88dcac1a6118278ecf2d74c8737bd6975e
|
| --- /dev/null
|
| +++ b/ipc/mojo/ipc_mojo_bootstrap.cc
|
| @@ -0,0 +1,205 @@
|
| +// 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 "base/logging.h"
|
| +#include "base/process/process_handle.h"
|
| +#include "ipc/ipc_message_utils.h"
|
| +#include "ipc/ipc_platform_file.h"
|
| +#include "mojo/embedder/platform_channel_pair.h"
|
| +
|
| +namespace IPC {
|
| +
|
| +namespace {
|
| +
|
| +// MojoBootstrap for the server process. You should create the instance
|
| +// using MojoBootstrap::Create().
|
| +class IPC_MOJO_EXPORT MojoServerBootstrap : public MojoBootstrap {
|
| + public:
|
| + MojoServerBootstrap();
|
| +
|
| + virtual void OnClientLaunched(base::ProcessHandle process) OVERRIDE;
|
| +
|
| + private:
|
| + void SendClientPipe();
|
| + void SendClientPipeIfReady();
|
| +
|
| + // Listener implementations
|
| + virtual bool OnMessageReceived(const Message& message) OVERRIDE;
|
| + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
|
| +
|
| + mojo::embedder::ScopedPlatformHandle server_pipe_;
|
| + base::ProcessHandle client_process_;
|
| + bool connected_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
|
| +};
|
| +
|
| +MojoServerBootstrap::MojoServerBootstrap()
|
| + : client_process_(base::kNullProcessHandle), connected_(false) {
|
| +}
|
| +
|
| +void MojoServerBootstrap::SendClientPipe() {
|
| + DCHECK_EQ(state(), STATE_INITIALIZED);
|
| + DCHECK_NE(client_process_, base::kNullProcessHandle);
|
| + DCHECK(connected_);
|
| +
|
| + mojo::embedder::PlatformChannelPair channel_pair;
|
| + server_pipe_ = channel_pair.PassServerHandle();
|
| + PlatformFileForTransit client_pipe = GetFileHandleForProcess(
|
| +#if defined(OS_POSIX)
|
| + channel_pair.PassClientHandle().release().fd,
|
| +#else
|
| + channel_pair.PassClientHandle().release().handle,
|
| +#endif
|
| + client_process_,
|
| + true);
|
| + CHECK(client_pipe != IPC::InvalidPlatformFileForTransit());
|
| + scoped_ptr<Message> message(new Message());
|
| + ParamTraits<PlatformFileForTransit>::Write(message.get(), client_pipe);
|
| + Send(message.release());
|
| +
|
| + set_state(STATE_WAITING_ACK);
|
| +}
|
| +
|
| +void MojoServerBootstrap::SendClientPipeIfReady() {
|
| + // Is the client launched?
|
| + if (client_process_ == base::kNullProcessHandle)
|
| + return;
|
| + // Has the bootstrap channel been made?
|
| + if (!connected_)
|
| + return;
|
| + SendClientPipe();
|
| +}
|
| +
|
| +void MojoServerBootstrap::OnClientLaunched(base::ProcessHandle process) {
|
| + DCHECK_EQ(state(), STATE_INITIALIZED);
|
| + DCHECK_NE(process, base::kNullProcessHandle);
|
| + client_process_ = process;
|
| + SendClientPipeIfReady();
|
| +}
|
| +
|
| +void MojoServerBootstrap::OnChannelConnected(int32 peer_pid) {
|
| + DCHECK_EQ(state(), STATE_INITIALIZED);
|
| + connected_ = true;
|
| + SendClientPipeIfReady();
|
| +}
|
| +
|
| +bool MojoServerBootstrap::OnMessageReceived(const Message&) {
|
| + DCHECK_EQ(state(), STATE_WAITING_ACK);
|
| + set_state(STATE_READY);
|
| +
|
| + delegate()->OnPipeAvailable(
|
| + mojo::embedder::ScopedPlatformHandle(server_pipe_.release()));
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// MojoBootstrap for client processes. You should create the instance
|
| +// using MojoBootstrap::Create().
|
| +class IPC_MOJO_EXPORT MojoClientBootstrap : public MojoBootstrap {
|
| + public:
|
| + MojoClientBootstrap();
|
| +
|
| + virtual void OnClientLaunched(base::ProcessHandle process) OVERRIDE;
|
| +
|
| + private:
|
| + // Listener implementations
|
| + virtual bool OnMessageReceived(const Message& message) OVERRIDE;
|
| + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
|
| +};
|
| +
|
| +MojoClientBootstrap::MojoClientBootstrap() {
|
| +}
|
| +
|
| +bool MojoClientBootstrap::OnMessageReceived(const Message& message) {
|
| + PlatformFileForTransit pipe;
|
| + PickleIterator iter(message);
|
| + if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) {
|
| + DLOG(WARNING) << "Failed to read a file handle from bootstrap channel.";
|
| + message.set_dispatch_error();
|
| + return false;
|
| + }
|
| +
|
| + // Sends ACK back.
|
| + Send(new Message());
|
| + set_state(STATE_READY);
|
| + delegate()->OnPipeAvailable(
|
| + mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
|
| + PlatformFileForTransitToPlatformFile(pipe))));
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void MojoClientBootstrap::OnClientLaunched(base::ProcessHandle process) {
|
| + // This notification should happen only on server processes.
|
| + NOTREACHED();
|
| +}
|
| +
|
| +void MojoClientBootstrap::OnChannelConnected(int32 peer_pid) {
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// MojoBootstrap
|
| +
|
| +// static
|
| +scoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle,
|
| + Channel::Mode mode,
|
| + Delegate* delegate) {
|
| + CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
|
| + scoped_ptr<MojoBootstrap> self =
|
| + mode == Channel::MODE_CLIENT
|
| + ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap())
|
| + : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap());
|
| + scoped_ptr<Channel> bootstrap_channel =
|
| + Channel::Create(handle, mode, self.get());
|
| + self->Init(bootstrap_channel.Pass(), delegate);
|
| + return self.Pass();
|
| +}
|
| +
|
| +MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
|
| +}
|
| +
|
| +MojoBootstrap::~MojoBootstrap() {
|
| +}
|
| +
|
| +void MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) {
|
| + channel_ = channel.Pass();
|
| + delegate_ = delegate;
|
| +}
|
| +
|
| +bool MojoBootstrap::Connect() {
|
| + return channel_->Connect();
|
| +}
|
| +
|
| +void MojoBootstrap::OnBadMessageReceived(const Message& message) {
|
| + delegate_->OnBootstrapError();
|
| +}
|
| +
|
| +void MojoBootstrap::OnChannelError() {
|
| + if (state_ == STATE_READY)
|
| + return;
|
| + DLOG(WARNING) << "Detected error on Mojo bootstrap channel.";
|
| + delegate()->OnBootstrapError();
|
| +}
|
| +
|
| +bool MojoBootstrap::Send(Message* message) {
|
| + return channel_->Send(message);
|
| +}
|
| +
|
| +#if defined(OS_POSIX) && !defined(OS_NACL)
|
| +int MojoBootstrap::GetClientFileDescriptor() const {
|
| + return channel_->GetClientFileDescriptor();
|
| +}
|
| +
|
| +int MojoBootstrap::TakeClientFileDescriptor() {
|
| + return channel_->TakeClientFileDescriptor();
|
| +}
|
| +#endif // defined(OS_POSIX) && !defined(OS_NACL)
|
| +
|
| +} // namespace IPC
|
|
|