Add ICU message format support
[chromium-blink-merge.git] / ipc / mojo / ipc_mojo_bootstrap.cc
blob91f3940b37a10bfccf0231c1265f249ada682843
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 private:
24 void SendClientPipe(int32 peer_pid);
26 // Listener implementations
27 bool OnMessageReceived(const Message& message) override;
28 void OnChannelConnected(int32 peer_pid) override;
30 mojo::embedder::ScopedPlatformHandle server_pipe_;
31 bool connected_;
33 DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
36 MojoServerBootstrap::MojoServerBootstrap() : connected_(false) {
39 void MojoServerBootstrap::SendClientPipe(int32 peer_pid) {
40 DCHECK_EQ(state(), STATE_INITIALIZED);
41 DCHECK(connected_);
43 mojo::embedder::PlatformChannelPair channel_pair;
44 server_pipe_ = channel_pair.PassServerHandle();
46 base::Process peer_process =
47 #if defined(OS_WIN)
48 base::Process::OpenWithAccess(peer_pid, PROCESS_DUP_HANDLE);
49 #else
50 base::Process::Open(peer_pid);
51 #endif
52 PlatformFileForTransit client_pipe = GetFileHandleForProcess(
53 #if defined(OS_POSIX)
54 channel_pair.PassClientHandle().release().fd,
55 #else
56 channel_pair.PassClientHandle().release().handle,
57 #endif
58 peer_process.Handle(), 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::OnChannelConnected(int32 peer_pid) {
77 DCHECK_EQ(state(), STATE_INITIALIZED);
78 connected_ = true;
79 SendClientPipe(peer_pid);
82 bool MojoServerBootstrap::OnMessageReceived(const Message&) {
83 if (state() != STATE_WAITING_ACK) {
84 set_state(STATE_ERROR);
85 LOG(ERROR) << "Got inconsistent message from client.";
86 return false;
89 set_state(STATE_READY);
90 CHECK(server_pipe_.is_valid());
91 delegate()->OnPipeAvailable(
92 mojo::embedder::ScopedPlatformHandle(server_pipe_.release()));
94 return true;
97 // MojoBootstrap for client processes. You should create the instance
98 // using MojoBootstrap::Create().
99 class MojoClientBootstrap : public MojoBootstrap {
100 public:
101 MojoClientBootstrap();
103 private:
104 // Listener implementations
105 bool OnMessageReceived(const Message& message) override;
106 void OnChannelConnected(int32 peer_pid) override;
108 DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
111 MojoClientBootstrap::MojoClientBootstrap() {
114 bool MojoClientBootstrap::OnMessageReceived(const Message& message) {
115 if (state() != STATE_INITIALIZED) {
116 set_state(STATE_ERROR);
117 LOG(ERROR) << "Got inconsistent message from server.";
118 return false;
121 PlatformFileForTransit pipe;
122 base::PickleIterator iter(message);
123 if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) {
124 LOG(WARNING) << "Failed to read a file handle from bootstrap channel.";
125 message.set_dispatch_error();
126 return false;
129 // Sends ACK back.
130 Send(new Message());
131 set_state(STATE_READY);
132 delegate()->OnPipeAvailable(
133 mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
134 PlatformFileForTransitToPlatformFile(pipe))));
136 return true;
139 void MojoClientBootstrap::OnChannelConnected(int32 peer_pid) {
142 } // namespace
144 // MojoBootstrap
146 // static
147 scoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle,
148 Channel::Mode mode,
149 Delegate* delegate,
150 AttachmentBroker* broker) {
151 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
152 scoped_ptr<MojoBootstrap> self =
153 mode == Channel::MODE_CLIENT
154 ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap())
155 : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap());
157 scoped_ptr<Channel> bootstrap_channel =
158 Channel::Create(handle, mode, self.get(), broker);
159 self->Init(bootstrap_channel.Pass(), delegate);
160 return self.Pass();
163 MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
166 MojoBootstrap::~MojoBootstrap() {
169 void MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) {
170 channel_ = channel.Pass();
171 delegate_ = delegate;
174 bool MojoBootstrap::Connect() {
175 return channel_->Connect();
178 base::ProcessId MojoBootstrap::GetSelfPID() const {
179 return channel_->GetSelfPID();
182 void MojoBootstrap::OnBadMessageReceived(const Message& message) {
183 Fail();
186 void MojoBootstrap::OnChannelError() {
187 if (state_ == STATE_READY || state_ == STATE_ERROR)
188 return;
189 DLOG(WARNING) << "Detected error on Mojo bootstrap channel.";
190 Fail();
193 void MojoBootstrap::Fail() {
194 set_state(STATE_ERROR);
195 delegate()->OnBootstrapError();
198 bool MojoBootstrap::HasFailed() const {
199 return state() == STATE_ERROR;
202 bool MojoBootstrap::Send(Message* message) {
203 return channel_->Send(message);
206 #if defined(OS_POSIX) && !defined(OS_NACL)
207 int MojoBootstrap::GetClientFileDescriptor() const {
208 return channel_->GetClientFileDescriptor();
211 base::ScopedFD MojoBootstrap::TakeClientFileDescriptor() {
212 return channel_->TakeClientFileDescriptor();
214 #endif // defined(OS_POSIX) && !defined(OS_NACL)
216 } // namespace IPC