Re-land: C++ readability review
[chromium-blink-merge.git] / ipc / mojo / ipc_mojo_bootstrap.cc
blobd307246033ffced61d2c4ba3a3b6a0dc72b67c9d
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/mojo/ipc_mojo_bootstrap.h"
7 #include "base/logging.h"
8 #include "base/process/process_handle.h"
9 #include "ipc/ipc_message_utils.h"
10 #include "ipc/ipc_platform_file.h"
11 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
13 namespace IPC {
15 namespace {
17 // MojoBootstrap for the server process. You should create the instance
18 // using MojoBootstrap::Create().
19 class MojoServerBootstrap : public MojoBootstrap {
20 public:
21 MojoServerBootstrap();
23 void OnClientLaunched(base::ProcessHandle process) override;
25 private:
26 void SendClientPipe();
27 void SendClientPipeIfReady();
29 // Listener implementations
30 bool OnMessageReceived(const Message& message) override;
31 void OnChannelConnected(int32 peer_pid) override;
33 mojo::embedder::ScopedPlatformHandle server_pipe_;
34 base::ProcessHandle client_process_;
35 bool connected_;
37 DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
40 MojoServerBootstrap::MojoServerBootstrap()
41 : client_process_(base::kNullProcessHandle), connected_(false) {
44 void MojoServerBootstrap::SendClientPipe() {
45 DCHECK_EQ(state(), STATE_INITIALIZED);
46 DCHECK_NE(client_process_, base::kNullProcessHandle);
47 DCHECK(connected_);
49 mojo::embedder::PlatformChannelPair channel_pair;
50 server_pipe_ = channel_pair.PassServerHandle();
51 PlatformFileForTransit client_pipe = GetFileHandleForProcess(
52 #if defined(OS_POSIX)
53 channel_pair.PassClientHandle().release().fd,
54 #else
55 channel_pair.PassClientHandle().release().handle,
56 #endif
57 client_process_,
58 true);
59 if (client_pipe == IPC::InvalidPlatformFileForTransit()) {
60 #if !defined(OS_WIN)
61 // GetFileHandleForProcess() only fails on Windows.
62 NOTREACHED();
63 #endif
64 LOG(WARNING) << "Failed to translate file handle for client process.";
65 Fail();
66 return;
69 scoped_ptr<Message> message(new Message());
70 ParamTraits<PlatformFileForTransit>::Write(message.get(), client_pipe);
71 Send(message.release());
73 set_state(STATE_WAITING_ACK);
76 void MojoServerBootstrap::SendClientPipeIfReady() {
77 // Is the client launched?
78 if (client_process_ == base::kNullProcessHandle)
79 return;
80 // Has the bootstrap channel been made?
81 if (!connected_)
82 return;
83 SendClientPipe();
86 void MojoServerBootstrap::OnClientLaunched(base::ProcessHandle process) {
87 if (HasFailed())
88 return;
90 DCHECK_EQ(state(), STATE_INITIALIZED);
91 DCHECK_NE(process, base::kNullProcessHandle);
92 client_process_ = process;
93 SendClientPipeIfReady();
96 void MojoServerBootstrap::OnChannelConnected(int32 peer_pid) {
97 DCHECK_EQ(state(), STATE_INITIALIZED);
98 connected_ = true;
99 SendClientPipeIfReady();
102 bool MojoServerBootstrap::OnMessageReceived(const Message&) {
103 if (state() != STATE_WAITING_ACK) {
104 set_state(STATE_ERROR);
105 LOG(ERROR) << "Got inconsistent message from client.";
106 return false;
109 set_state(STATE_READY);
110 CHECK(server_pipe_.is_valid());
111 delegate()->OnPipeAvailable(
112 mojo::embedder::ScopedPlatformHandle(server_pipe_.release()));
114 return true;
117 // MojoBootstrap for client processes. You should create the instance
118 // using MojoBootstrap::Create().
119 class MojoClientBootstrap : public MojoBootstrap {
120 public:
121 MojoClientBootstrap();
123 void OnClientLaunched(base::ProcessHandle process) override;
125 private:
126 // Listener implementations
127 bool OnMessageReceived(const Message& message) override;
128 void OnChannelConnected(int32 peer_pid) override;
130 DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
133 MojoClientBootstrap::MojoClientBootstrap() {
136 bool MojoClientBootstrap::OnMessageReceived(const Message& message) {
137 if (state() != STATE_INITIALIZED) {
138 set_state(STATE_ERROR);
139 LOG(ERROR) << "Got inconsistent message from server.";
140 return false;
143 PlatformFileForTransit pipe;
144 PickleIterator iter(message);
145 if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) {
146 LOG(WARNING) << "Failed to read a file handle from bootstrap channel.";
147 message.set_dispatch_error();
148 return false;
151 // Sends ACK back.
152 Send(new Message());
153 set_state(STATE_READY);
154 delegate()->OnPipeAvailable(
155 mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
156 PlatformFileForTransitToPlatformFile(pipe))));
158 return true;
161 void MojoClientBootstrap::OnClientLaunched(base::ProcessHandle process) {
162 // This notification should happen only on server processes.
163 NOTREACHED();
166 void MojoClientBootstrap::OnChannelConnected(int32 peer_pid) {
169 } // namespace
171 // MojoBootstrap
173 // static
174 scoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle,
175 Channel::Mode mode,
176 Delegate* delegate) {
177 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
178 scoped_ptr<MojoBootstrap> self =
179 mode == Channel::MODE_CLIENT
180 ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap())
181 : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap());
182 scoped_ptr<Channel> bootstrap_channel =
183 Channel::Create(handle, mode, self.get());
184 self->Init(bootstrap_channel.Pass(), delegate);
185 return self.Pass();
188 MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
191 MojoBootstrap::~MojoBootstrap() {
194 void MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) {
195 channel_ = channel.Pass();
196 delegate_ = delegate;
199 bool MojoBootstrap::Connect() {
200 return channel_->Connect();
203 base::ProcessId MojoBootstrap::GetSelfPID() const {
204 return channel_->GetSelfPID();
207 void MojoBootstrap::OnBadMessageReceived(const Message& message) {
208 Fail();
211 void MojoBootstrap::OnChannelError() {
212 if (state_ == STATE_READY || state_ == STATE_ERROR)
213 return;
214 DLOG(WARNING) << "Detected error on Mojo bootstrap channel.";
215 Fail();
218 void MojoBootstrap::Fail() {
219 set_state(STATE_ERROR);
220 delegate()->OnBootstrapError();
223 bool MojoBootstrap::HasFailed() const {
224 return state() == STATE_ERROR;
227 bool MojoBootstrap::Send(Message* message) {
228 return channel_->Send(message);
231 #if defined(OS_POSIX) && !defined(OS_NACL)
232 int MojoBootstrap::GetClientFileDescriptor() const {
233 return channel_->GetClientFileDescriptor();
236 base::ScopedFD MojoBootstrap::TakeClientFileDescriptor() {
237 return channel_->TakeClientFileDescriptor();
239 #endif // defined(OS_POSIX) && !defined(OS_NACL)
241 } // namespace IPC