Remove an old PangoFontDescription forward declaration.
[chromium-blink-merge.git] / ipc / mojo / ipc_channel_mojo.cc
blobc3c6e0c446f91719cdbf5ea529c7e86ad8824af1
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_channel_mojo.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h"
10 #include "ipc/ipc_listener.h"
11 #include "ipc/ipc_logging.h"
12 #include "ipc/ipc_message_attachment_set.h"
13 #include "ipc/ipc_message_macros.h"
14 #include "ipc/mojo/client_channel.mojom.h"
15 #include "ipc/mojo/ipc_mojo_bootstrap.h"
16 #include "ipc/mojo/ipc_mojo_handle_attachment.h"
17 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
18 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
20 #if defined(OS_POSIX) && !defined(OS_NACL)
21 #include "ipc/ipc_platform_file_attachment_posix.h"
22 #endif
24 namespace IPC {
26 namespace {
28 class MojoChannelFactory : public ChannelFactory {
29 public:
30 MojoChannelFactory(ChannelMojo::Delegate* delegate,
31 ChannelHandle channel_handle,
32 Channel::Mode mode)
33 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
35 std::string GetName() const override {
36 return channel_handle_.name;
39 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
40 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
43 private:
44 ChannelMojo::Delegate* delegate_;
45 ChannelHandle channel_handle_;
46 Channel::Mode mode_;
49 //------------------------------------------------------------------------------
51 class ClientChannelMojo
52 : public ChannelMojo,
53 public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
54 public:
55 ClientChannelMojo(ChannelMojo::Delegate* delegate,
56 const ChannelHandle& handle,
57 Listener* listener);
58 ~ClientChannelMojo() override;
59 // MojoBootstrap::Delegate implementation
60 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
61 // InterfaceImpl implementation
62 void OnConnectionError() override;
63 // ClientChannel implementation
64 void Init(
65 mojo::ScopedMessagePipeHandle pipe,
66 int32_t peer_pid,
67 const mojo::Callback<void(int32_t)>& callback) override;
69 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
72 ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
73 const ChannelHandle& handle,
74 Listener* listener)
75 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
78 ClientChannelMojo::~ClientChannelMojo() {
81 void ClientChannelMojo::OnPipeAvailable(
82 mojo::embedder::ScopedPlatformHandle handle) {
83 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
86 void ClientChannelMojo::OnConnectionError() {
87 listener()->OnChannelError();
90 void ClientChannelMojo::Init(
91 mojo::ScopedMessagePipeHandle pipe,
92 int32_t peer_pid,
93 const mojo::Callback<void(int32_t)>& callback) {
94 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
95 callback.Run(GetSelfPID());
98 //------------------------------------------------------------------------------
100 class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
101 public:
102 ServerChannelMojo(ChannelMojo::Delegate* delegate,
103 const ChannelHandle& handle,
104 Listener* listener);
105 ~ServerChannelMojo() override;
107 // MojoBootstrap::Delegate implementation
108 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
109 // ErrorHandler implementation
110 void OnConnectionError() override;
111 // Channel override
112 void Close() override;
114 private:
115 // ClientChannelClient implementation
116 void ClientChannelWasInitialized(int32_t peer_pid);
118 mojo::InterfacePtr<ClientChannel> client_channel_;
119 mojo::ScopedMessagePipeHandle message_pipe_;
121 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
124 ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
125 const ChannelHandle& handle,
126 Listener* listener)
127 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
130 ServerChannelMojo::~ServerChannelMojo() {
131 Close();
134 void ServerChannelMojo::OnPipeAvailable(
135 mojo::embedder::ScopedPlatformHandle handle) {
136 mojo::ScopedMessagePipeHandle peer;
137 MojoResult create_result =
138 mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
139 if (create_result != MOJO_RESULT_OK) {
140 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
141 listener()->OnChannelError();
142 return;
145 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
146 client_channel_.set_error_handler(this);
147 client_channel_->Init(
148 peer.Pass(),
149 static_cast<int32_t>(GetSelfPID()),
150 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
151 base::Unretained(this)));
154 void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
155 InitMessageReader(message_pipe_.Pass(), peer_pid);
158 void ServerChannelMojo::OnConnectionError() {
159 listener()->OnChannelError();
162 void ServerChannelMojo::Close() {
163 client_channel_.reset();
164 message_pipe_.reset();
165 ChannelMojo::Close();
168 } // namespace
170 //------------------------------------------------------------------------------
172 void ChannelMojo::ChannelInfoDeleter::operator()(
173 mojo::embedder::ChannelInfo* ptr) const {
174 mojo::embedder::DestroyChannel(ptr);
177 //------------------------------------------------------------------------------
179 // static
180 bool ChannelMojo::ShouldBeUsed() {
181 // TODO(morrita): Remove this if it sticks.
182 return true;
185 // static
186 scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
187 const ChannelHandle& channel_handle,
188 Mode mode,
189 Listener* listener) {
190 switch (mode) {
191 case Channel::MODE_CLIENT:
192 return make_scoped_ptr(
193 new ClientChannelMojo(delegate, channel_handle, listener));
194 case Channel::MODE_SERVER:
195 return make_scoped_ptr(
196 new ServerChannelMojo(delegate, channel_handle, listener));
197 default:
198 NOTREACHED();
199 return nullptr;
203 // static
204 scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
205 ChannelMojo::Delegate* delegate,
206 const ChannelHandle& channel_handle) {
207 return make_scoped_ptr(
208 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
211 // static
212 scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
213 const ChannelHandle& channel_handle) {
214 return make_scoped_ptr(
215 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
218 ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
219 const ChannelHandle& handle,
220 Mode mode,
221 Listener* listener)
222 : mode_(mode),
223 listener_(listener),
224 peer_pid_(base::kNullProcessId),
225 weak_factory_(this) {
226 // Create MojoBootstrap after all members are set as it touches
227 // ChannelMojo from a different thread.
228 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
229 if (delegate) {
230 if (delegate->GetIOTaskRunner() ==
231 base::MessageLoop::current()->message_loop_proxy()) {
232 InitDelegate(delegate);
233 } else {
234 delegate->GetIOTaskRunner()->PostTask(
235 FROM_HERE,
236 base::Bind(
237 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
242 ChannelMojo::~ChannelMojo() {
243 Close();
246 void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
247 delegate_ = delegate->ToWeakPtr();
248 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
251 mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
252 mojo::embedder::ScopedPlatformHandle handle) {
253 DCHECK(!channel_info_.get());
254 mojo::embedder::ChannelInfo* channel_info;
255 mojo::ScopedMessagePipeHandle pipe =
256 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
257 channel_info_.reset(channel_info);
258 return pipe.Pass();
261 bool ChannelMojo::Connect() {
262 DCHECK(!message_reader_);
263 return bootstrap_->Connect();
266 void ChannelMojo::Close() {
267 message_reader_.reset();
268 channel_info_.reset();
271 void ChannelMojo::OnBootstrapError() {
272 listener_->OnChannelError();
275 void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
276 int32_t peer_pid) {
277 message_reader_ =
278 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this));
280 for (size_t i = 0; i < pending_messages_.size(); ++i) {
281 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
282 pending_messages_[i] = NULL;
283 if (!sent) {
284 pending_messages_.clear();
285 listener_->OnChannelError();
286 return;
290 pending_messages_.clear();
292 set_peer_pid(peer_pid);
293 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
294 if (message_reader_)
295 message_reader_->ReadMessagesThenWait();
298 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
299 Close();
302 void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
303 listener_->OnChannelError();
307 bool ChannelMojo::Send(Message* message) {
308 if (!message_reader_) {
309 pending_messages_.push_back(message);
310 return true;
313 return message_reader_->Send(make_scoped_ptr(message));
316 base::ProcessId ChannelMojo::GetPeerPID() const {
317 return peer_pid_;
320 base::ProcessId ChannelMojo::GetSelfPID() const {
321 return base::GetCurrentProcId();
324 void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
325 bootstrap_->OnClientLaunched(handle);
328 void ChannelMojo::OnMessageReceived(Message& message) {
329 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
330 "class", IPC_MESSAGE_ID_CLASS(message.type()),
331 "line", IPC_MESSAGE_ID_LINE(message.type()));
332 listener_->OnMessageReceived(message);
333 if (message.dispatch_error())
334 listener_->OnBadMessageReceived(message);
337 #if defined(OS_POSIX) && !defined(OS_NACL)
338 int ChannelMojo::GetClientFileDescriptor() const {
339 return bootstrap_->GetClientFileDescriptor();
342 base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
343 return bootstrap_->TakeClientFileDescriptor();
345 #endif // defined(OS_POSIX) && !defined(OS_NACL)
347 // static
348 MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
349 Message* message,
350 std::vector<MojoHandle>* handles) {
351 // We dup() the handles in IPC::Message to transmit.
352 // IPC::MessageAttachmentSet has intricate lifecycle semantics
353 // of FDs, so just to dup()-and-own them is the safest option.
354 if (message->HasAttachments()) {
355 MessageAttachmentSet* set = message->attachment_set();
356 for (unsigned i = 0; i < set->size(); ++i) {
357 scoped_refptr<MessageAttachment> attachment = set->GetAttachmentAt(i);
358 switch (attachment->GetType()) {
359 case MessageAttachment::TYPE_PLATFORM_FILE:
360 #if defined(OS_POSIX) && !defined(OS_NACL)
362 base::PlatformFile file =
363 dup(static_cast<IPC::internal::PlatformFileAttachment*>(
364 attachment.get())->file());
365 if (file == -1) {
366 DPLOG(WARNING) << "Failed to dup FD to transmit.";
367 set->CommitAll();
368 return MOJO_RESULT_UNKNOWN;
371 MojoHandle wrapped_handle;
372 MojoResult wrap_result = CreatePlatformHandleWrapper(
373 mojo::embedder::ScopedPlatformHandle(
374 mojo::embedder::PlatformHandle(file)),
375 &wrapped_handle);
376 if (MOJO_RESULT_OK != wrap_result) {
377 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
378 << wrap_result;
379 set->CommitAll();
380 return wrap_result;
383 handles->push_back(wrapped_handle);
385 #else
386 NOTREACHED();
387 #endif // defined(OS_POSIX) && !defined(OS_NACL)
388 break;
389 case MessageAttachment::TYPE_MOJO_HANDLE: {
390 mojo::ScopedHandle handle =
391 static_cast<IPC::internal::MojoHandleAttachment*>(
392 attachment.get())->TakeHandle();
393 handles->push_back(handle.release().value());
394 } break;
398 set->CommitAll();
401 return MOJO_RESULT_OK;
404 // static
405 MojoResult ChannelMojo::WriteToMessageAttachmentSet(
406 const std::vector<MojoHandle>& handle_buffer,
407 Message* message) {
408 for (size_t i = 0; i < handle_buffer.size(); ++i) {
409 bool ok = message->attachment_set()->AddAttachment(
410 new IPC::internal::MojoHandleAttachment(
411 mojo::MakeScopedHandle(mojo::Handle(handle_buffer[i]))));
412 DCHECK(ok);
413 if (!ok) {
414 DLOG(ERROR) << "Failed to add new Mojo handle.";
415 return MOJO_RESULT_UNKNOWN;
419 return MOJO_RESULT_OK;
422 } // namespace IPC