Use UintToString() for unsigned values.
[chromium-blink-merge.git] / ipc / mojo / ipc_mojo_bootstrap.cc
blob1b1308295ad2fae5e498c7118470ba70b7ad09ed
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 <stdint.h>
9 #include "base/logging.h"
10 #include "base/process/process_handle.h"
11 #include "ipc/ipc_message_utils.h"
12 #include "ipc/ipc_platform_file.h"
13 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
15 namespace IPC {
17 namespace {
19 // MojoBootstrap for the server process. You should create the instance
20 // using MojoBootstrap::Create().
21 class MojoServerBootstrap : public MojoBootstrap {
22 public:
23 MojoServerBootstrap();
25 private:
26 void SendClientPipe(int32_t peer_pid);
28 // Listener implementations
29 bool OnMessageReceived(const Message& message) override;
30 void OnChannelConnected(int32_t peer_pid) override;
32 mojo::embedder::ScopedPlatformHandle server_pipe_;
33 bool connected_;
35 DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
38 MojoServerBootstrap::MojoServerBootstrap() : connected_(false) {
41 void MojoServerBootstrap::SendClientPipe(int32_t peer_pid) {
42 DCHECK_EQ(state(), STATE_INITIALIZED);
43 DCHECK(connected_);
45 mojo::embedder::PlatformChannelPair channel_pair;
46 server_pipe_ = channel_pair.PassServerHandle();
48 base::Process peer_process =
49 #if defined(OS_WIN)
50 base::Process::OpenWithAccess(peer_pid, PROCESS_DUP_HANDLE);
51 #else
52 base::Process::Open(peer_pid);
53 #endif
54 PlatformFileForTransit client_pipe = GetFileHandleForProcess(
55 #if defined(OS_POSIX)
56 channel_pair.PassClientHandle().release().fd,
57 #else
58 channel_pair.PassClientHandle().release().handle,
59 #endif
60 peer_process.Handle(), true);
61 if (client_pipe == IPC::InvalidPlatformFileForTransit()) {
62 #if !defined(OS_WIN)
63 // GetFileHandleForProcess() only fails on Windows.
64 NOTREACHED();
65 #endif
66 LOG(WARNING) << "Failed to translate file handle for client process.";
67 Fail();
68 return;
71 scoped_ptr<Message> message(new Message());
72 ParamTraits<PlatformFileForTransit>::Write(message.get(), client_pipe);
73 Send(message.release());
75 set_state(STATE_WAITING_ACK);
78 void MojoServerBootstrap::OnChannelConnected(int32_t peer_pid) {
79 DCHECK_EQ(state(), STATE_INITIALIZED);
80 connected_ = true;
81 SendClientPipe(peer_pid);
84 bool MojoServerBootstrap::OnMessageReceived(const Message&) {
85 if (state() != STATE_WAITING_ACK) {
86 set_state(STATE_ERROR);
87 LOG(ERROR) << "Got inconsistent message from client.";
88 return false;
91 set_state(STATE_READY);
92 CHECK(server_pipe_.is_valid());
93 delegate()->OnPipeAvailable(
94 mojo::embedder::ScopedPlatformHandle(server_pipe_.release()));
96 return true;
99 // MojoBootstrap for client processes. You should create the instance
100 // using MojoBootstrap::Create().
101 class MojoClientBootstrap : public MojoBootstrap {
102 public:
103 MojoClientBootstrap();
105 private:
106 // Listener implementations
107 bool OnMessageReceived(const Message& message) override;
108 void OnChannelConnected(int32_t peer_pid) override;
110 DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
113 MojoClientBootstrap::MojoClientBootstrap() {
116 bool MojoClientBootstrap::OnMessageReceived(const Message& message) {
117 if (state() != STATE_INITIALIZED) {
118 set_state(STATE_ERROR);
119 LOG(ERROR) << "Got inconsistent message from server.";
120 return false;
123 PlatformFileForTransit pipe;
124 base::PickleIterator iter(message);
125 if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) {
126 LOG(WARNING) << "Failed to read a file handle from bootstrap channel.";
127 message.set_dispatch_error();
128 return false;
131 // Sends ACK back.
132 Send(new Message());
133 set_state(STATE_READY);
134 delegate()->OnPipeAvailable(
135 mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
136 PlatformFileForTransitToPlatformFile(pipe))));
138 return true;
141 void MojoClientBootstrap::OnChannelConnected(int32_t peer_pid) {
144 } // namespace
146 // MojoBootstrap
148 // static
149 scoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle,
150 Channel::Mode mode,
151 Delegate* delegate,
152 AttachmentBroker* broker) {
153 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
154 scoped_ptr<MojoBootstrap> self =
155 mode == Channel::MODE_CLIENT
156 ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap())
157 : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap());
159 scoped_ptr<Channel> bootstrap_channel =
160 Channel::Create(handle, mode, self.get(), broker);
161 self->Init(bootstrap_channel.Pass(), delegate);
162 return self.Pass();
165 MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
168 MojoBootstrap::~MojoBootstrap() {
171 void MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) {
172 channel_ = channel.Pass();
173 delegate_ = delegate;
176 bool MojoBootstrap::Connect() {
177 return channel_->Connect();
180 base::ProcessId MojoBootstrap::GetSelfPID() const {
181 return channel_->GetSelfPID();
184 void MojoBootstrap::OnBadMessageReceived(const Message& message) {
185 Fail();
188 void MojoBootstrap::OnChannelError() {
189 if (state_ == STATE_READY || state_ == STATE_ERROR)
190 return;
191 DLOG(WARNING) << "Detected error on Mojo bootstrap channel.";
192 Fail();
195 void MojoBootstrap::Fail() {
196 set_state(STATE_ERROR);
197 delegate()->OnBootstrapError();
200 bool MojoBootstrap::HasFailed() const {
201 return state() == STATE_ERROR;
204 bool MojoBootstrap::Send(Message* message) {
205 return channel_->Send(message);
208 #if defined(OS_POSIX) && !defined(OS_NACL)
209 int MojoBootstrap::GetClientFileDescriptor() const {
210 return channel_->GetClientFileDescriptor();
213 base::ScopedFD MojoBootstrap::TakeClientFileDescriptor() {
214 return channel_->TakeClientFileDescriptor();
216 #endif // defined(OS_POSIX) && !defined(OS_NACL)
218 } // namespace IPC