Chromium Code Reviews| 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..3fe80c0bebdd0feb862c22c61076124ea0247070 |
| --- /dev/null |
| +++ b/ipc/mojo/ipc_mojo_bootstrap.cc |
| @@ -0,0 +1,206 @@ |
| +// 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() |
|
viettrungluu
2014/09/15 22:37:28
nit: Needs a period at the end.
Hajime Morrita
2014/09/15 23:51:33
Done.
|
| +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); |
| +}; |
| + |
| +// MojoBootstrap for client processes. You should create the instance |
| +// using MojoBootstrap::Create() |
|
viettrungluu
2014/09/15 22:37:27
"
Hajime Morrita
2014/09/15 23:51:33
Done.
|
| +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); |
| +}; |
| + |
| +} // 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) |
| + |
| +// MojoServerBootstrap |
| + |
| +MojoServerBootstrap::MojoServerBootstrap() |
|
viettrungluu
2014/09/15 22:37:28
Apparently, it's legal to define stuff that's decl
Hajime Morrita
2014/09/15 23:51:33
Ouch. This is indeed weird. Surprised that the com
|
| + : 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( |
| + channel_pair.PassClientHandle().release().ToPlaformFile(), |
| + 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(state() == STATE_INITIALIZED); |
| + connected_ = true; |
| + SendClientPipeIfReady(); |
| +} |
| + |
| +bool MojoServerBootstrap::OnMessageReceived(const Message&) { |
| + DCHECK(state() == STATE_WAITING_ACK); |
| + set_state(STATE_READY); |
| + |
| + delegate()->OnPipeAvailable( |
| + mojo::embedder::ScopedPlatformHandle(server_pipe_.release())); |
| + |
| + return true; |
| +} |
| + |
| +// 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 IPC |