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. 4 5 #include "ipc/mojo/ipc_channel_mojo.h" 6 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/mojo/ipc_channel_mojo_readers.h" 12 #include "ipc/mojo/ipc_mojo_bootstrap.h" 13 #include "mojo/embedder/embedder.h" 14 15 #if defined(OS_POSIX) && !defined(OS_NACL) 16 #include "ipc/file_descriptor_set_posix.h" 17 #endif 18 19 namespace IPC { 20 21 namespace { 22 23 class MojoChannelFactory : public ChannelFactory { 24 public: 25 MojoChannelFactory(ChannelMojo::Delegate* delegate, 26 ChannelHandle channel_handle, 27 Channel::Mode mode) 28 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {} 29 30 virtual std::string GetName() const OVERRIDE { 31 return channel_handle_.name; 32 } 33 34 virtual scoped_ptr<Channel> BuildChannel(Listener* listener) OVERRIDE { 35 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener) 36 .PassAs<Channel>(); 37 } 38 39 private: 40 ChannelMojo::Delegate* delegate_; 41 ChannelHandle channel_handle_; 42 Channel::Mode mode_; 43 }; 44 45 } // namespace 46 47 //------------------------------------------------------------------------------ 48 49 void ChannelMojo::ChannelInfoDeleter::operator()( 50 mojo::embedder::ChannelInfo* ptr) const { 51 mojo::embedder::DestroyChannelOnIOThread(ptr); 52 } 53 54 //------------------------------------------------------------------------------ 55 56 // static 57 scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate, 58 const ChannelHandle& channel_handle, 59 Mode mode, 60 Listener* listener) { 61 return make_scoped_ptr( 62 new ChannelMojo(delegate, channel_handle, mode, listener)); 63 } 64 65 // static 66 scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory( 67 ChannelMojo::Delegate* delegate, 68 const ChannelHandle& channel_handle) { 69 return make_scoped_ptr(new MojoChannelFactory( 70 delegate, channel_handle, Channel::MODE_SERVER)) 71 .PassAs<ChannelFactory>(); 72 } 73 74 // static 75 scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory( 76 const ChannelHandle& channel_handle) { 77 return make_scoped_ptr( 78 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT)) 79 .PassAs<ChannelFactory>(); 80 } 81 82 ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate, 83 const ChannelHandle& handle, 84 Mode mode, 85 Listener* listener) 86 : mode_(mode), 87 listener_(listener), 88 peer_pid_(base::kNullProcessId), 89 weak_factory_(this) { 90 // Create MojoBootstrap after all members are set as it touches 91 // ChannelMojo from a different thread. 92 bootstrap_ = MojoBootstrap::Create(handle, mode, this); 93 if (delegate) { 94 if (delegate->GetIOTaskRunner() == 95 base::MessageLoop::current()->message_loop_proxy()) { 96 InitDelegate(delegate); 97 } else { 98 delegate->GetIOTaskRunner()->PostTask( 99 FROM_HERE, 100 base::Bind( 101 &ChannelMojo::InitDelegate, base::Unretained(this), delegate)); 102 } 103 } 104 } 105 106 ChannelMojo::~ChannelMojo() { 107 Close(); 108 } 109 110 void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) { 111 delegate_ = delegate->ToWeakPtr(); 112 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr()); 113 } 114 115 void ChannelMojo::InitControlReader( 116 mojo::embedder::ScopedPlatformHandle handle) { 117 DCHECK(base::MessageLoopForIO::IsCurrent()); 118 mojo::embedder::ChannelInfo* channel_info; 119 mojo::ScopedMessagePipeHandle control_pipe = 120 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info); 121 channel_info_.reset(channel_info); 122 123 switch (mode_) { 124 case MODE_SERVER: 125 control_reader_.reset( 126 new internal::ServerControlReader(control_pipe.Pass(), this)); 127 break; 128 case MODE_CLIENT: 129 control_reader_.reset( 130 new internal::ClientControlReader(control_pipe.Pass(), this)); 131 break; 132 default: 133 NOTREACHED(); 134 break; 135 } 136 } 137 138 bool ChannelMojo::Connect() { 139 DCHECK(!message_reader_); 140 DCHECK(!control_reader_); 141 return bootstrap_->Connect(); 142 } 143 144 void ChannelMojo::Close() { 145 control_reader_.reset(); 146 message_reader_.reset(); 147 channel_info_.reset(); 148 } 149 150 void ChannelMojo::OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) { 151 InitControlReader(handle.Pass()); 152 control_reader_->Connect(); 153 } 154 155 void ChannelMojo::OnBootstrapError() { 156 listener_->OnChannelError(); 157 } 158 159 void ChannelMojo::OnConnected(mojo::ScopedMessagePipeHandle pipe) { 160 message_reader_ = 161 make_scoped_ptr(new internal::MessageReader(pipe.Pass(), this)); 162 163 for (size_t i = 0; i < pending_messages_.size(); ++i) { 164 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i])); 165 pending_messages_[i] = NULL; 166 if (!sent) { 167 pending_messages_.clear(); 168 listener_->OnChannelError(); 169 return; 170 } 171 } 172 173 pending_messages_.clear(); 174 175 listener_->OnChannelConnected(GetPeerPID()); 176 } 177 178 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) { 179 Close(); 180 } 181 182 void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) { 183 listener_->OnChannelError(); 184 } 185 186 187 bool ChannelMojo::Send(Message* message) { 188 if (!message_reader_) { 189 pending_messages_.push_back(message); 190 return true; 191 } 192 193 return message_reader_->Send(make_scoped_ptr(message)); 194 } 195 196 base::ProcessId ChannelMojo::GetPeerPID() const { 197 return peer_pid_; 198 } 199 200 base::ProcessId ChannelMojo::GetSelfPID() const { 201 return base::GetCurrentProcId(); 202 } 203 204 void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) { 205 bootstrap_->OnClientLaunched(handle); 206 } 207 208 void ChannelMojo::OnMessageReceived(Message& message) { 209 listener_->OnMessageReceived(message); 210 if (message.dispatch_error()) 211 listener_->OnBadMessageReceived(message); 212 } 213 214 #if defined(OS_POSIX) && !defined(OS_NACL) 215 int ChannelMojo::GetClientFileDescriptor() const { 216 return bootstrap_->GetClientFileDescriptor(); 217 } 218 219 int ChannelMojo::TakeClientFileDescriptor() { 220 return bootstrap_->TakeClientFileDescriptor(); 221 } 222 223 // static 224 MojoResult ChannelMojo::WriteToFileDescriptorSet( 225 const std::vector<MojoHandle>& handle_buffer, 226 Message* message) { 227 for (size_t i = 0; i < handle_buffer.size(); ++i) { 228 mojo::embedder::ScopedPlatformHandle platform_handle; 229 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle( 230 handle_buffer[i], &platform_handle); 231 if (unwrap_result != MOJO_RESULT_OK) { 232 DLOG(WARNING) << "Pipe failed to covert handles. Closing: " 233 << unwrap_result; 234 return unwrap_result; 235 } 236 237 bool ok = message->file_descriptor_set()->AddToOwn( 238 base::ScopedFD(platform_handle.release().fd)); 239 DCHECK(ok); 240 } 241 242 return MOJO_RESULT_OK; 243 } 244 245 // static 246 MojoResult ChannelMojo::ReadFromFileDescriptorSet( 247 Message* message, 248 std::vector<MojoHandle>* handles) { 249 // We dup() the handles in IPC::Message to transmit. 250 // IPC::FileDescriptorSet has intricate lifecycle semantics 251 // of FDs, so just to dup()-and-own them is the safest option. 252 if (message->HasFileDescriptors()) { 253 FileDescriptorSet* fdset = message->file_descriptor_set(); 254 std::vector<base::PlatformFile> fds_to_send(fdset->size()); 255 fdset->PeekDescriptors(&fds_to_send[0]); 256 for (size_t i = 0; i < fds_to_send.size(); ++i) { 257 int fd_to_send = dup(fds_to_send[i]); 258 if (-1 == fd_to_send) { 259 DPLOG(WARNING) << "Failed to dup FD to transmit."; 260 fdset->CommitAll(); 261 return MOJO_RESULT_UNKNOWN; 262 } 263 264 MojoHandle wrapped_handle; 265 MojoResult wrap_result = CreatePlatformHandleWrapper( 266 mojo::embedder::ScopedPlatformHandle( 267 mojo::embedder::PlatformHandle(fd_to_send)), 268 &wrapped_handle); 269 if (MOJO_RESULT_OK != wrap_result) { 270 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: " 271 << wrap_result; 272 fdset->CommitAll(); 273 return wrap_result; 274 } 275 276 handles->push_back(wrapped_handle); 277 } 278 279 fdset->CommitAll(); 280 } 281 282 return MOJO_RESULT_OK; 283 } 284 285 #endif // defined(OS_POSIX) && !defined(OS_NACL) 286 287 } // namespace IPC 288