11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ipc/mojo/ipc_mojo_bootstrap.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/logging.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/process/process_handle.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ipc/ipc_message_utils.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ipc/ipc_platform_file.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "mojo/embedder/platform_channel_pair.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace IPC { 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// MojoBootstrap for the server process. You should create the instance 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// using MojoBootstrap::Create(). 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass IPC_MOJO_EXPORT MojoServerBootstrap : public MojoBootstrap { 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoServerBootstrap(); 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnClientLaunched(base::ProcessHandle process) OVERRIDE; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void SendClientPipe(); 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void SendClientPipeIfReady(); 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Listener implementations 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual bool OnMessageReceived(const Message& message) OVERRIDE; 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::embedder::ScopedPlatformHandle server_pipe_; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ProcessHandle client_process_; 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool connected_; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap); 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMojoServerBootstrap::MojoServerBootstrap() 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : client_process_(base::kNullProcessHandle), connected_(false) { 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoServerBootstrap::SendClientPipe() { 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(state(), STATE_INITIALIZED); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(client_process_, base::kNullProcessHandle); 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(connected_); 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::embedder::PlatformChannelPair channel_pair; 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci server_pipe_ = channel_pair.PassServerHandle(); 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformFileForTransit client_pipe = GetFileHandleForProcess( 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_POSIX) 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci channel_pair.PassClientHandle().release().fd, 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci channel_pair.PassClientHandle().release().handle, 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_process_, 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true); 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(client_pipe != IPC::InvalidPlatformFileForTransit()); 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<Message> message(new Message()); 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ParamTraits<PlatformFileForTransit>::Write(message.get(), client_pipe); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Send(message.release()); 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci set_state(STATE_WAITING_ACK); 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoServerBootstrap::SendClientPipeIfReady() { 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Is the client launched? 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (client_process_ == base::kNullProcessHandle) 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Has the bootstrap channel been made? 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!connected_) 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendClientPipe(); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoServerBootstrap::OnClientLaunched(base::ProcessHandle process) { 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(state(), STATE_INITIALIZED); 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(process, base::kNullProcessHandle); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci client_process_ = process; 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendClientPipeIfReady(); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoServerBootstrap::OnChannelConnected(int32 peer_pid) { 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(state(), STATE_INITIALIZED); 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci connected_ = true; 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SendClientPipeIfReady(); 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool MojoServerBootstrap::OnMessageReceived(const Message&) { 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(state(), STATE_WAITING_ACK); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci set_state(STATE_READY); 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate()->OnPipeAvailable( 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::embedder::ScopedPlatformHandle(server_pipe_.release())); 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// MojoBootstrap for client processes. You should create the instance 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// using MojoBootstrap::Create(). 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass IPC_MOJO_EXPORT MojoClientBootstrap : public MojoBootstrap { 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MojoClientBootstrap(); 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnClientLaunched(base::ProcessHandle process) OVERRIDE; 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Listener implementations 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual bool OnMessageReceived(const Message& message) OVERRIDE; 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap); 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMojoClientBootstrap::MojoClientBootstrap() { 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool MojoClientBootstrap::OnMessageReceived(const Message& message) { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformFileForTransit pipe; 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PickleIterator iter(message); 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) { 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(WARNING) << "Failed to read a file handle from bootstrap channel."; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message.set_dispatch_error(); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Sends ACK back. 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Send(new Message()); 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci set_state(STATE_READY); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate()->OnPipeAvailable( 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle( 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformFileForTransitToPlatformFile(pipe)))); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoClientBootstrap::OnClientLaunched(base::ProcessHandle process) { 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This notification should happen only on server processes. 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED(); 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoClientBootstrap::OnChannelConnected(int32 peer_pid) { 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// MojoBootstrap 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle, 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Channel::Mode mode, 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Delegate* delegate) { 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER); 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<MojoBootstrap> self = 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mode == Channel::MODE_CLIENT 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap()) 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap()); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<Channel> bootstrap_channel = 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Channel::Create(handle, mode, self.get()); 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci self->Init(bootstrap_channel.Pass(), delegate); 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return self.Pass(); 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) { 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMojoBootstrap::~MojoBootstrap() { 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci channel_ = channel.Pass(); 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate_ = delegate; 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool MojoBootstrap::Connect() { 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return channel_->Connect(); 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoBootstrap::OnBadMessageReceived(const Message& message) { 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate_->OnBootstrapError(); 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MojoBootstrap::OnChannelError() { 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (state_ == STATE_READY) 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DLOG(WARNING) << "Detected error on Mojo bootstrap channel."; 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate()->OnBootstrapError(); 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool MojoBootstrap::Send(Message* message) { 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return channel_->Send(message); 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_POSIX) && !defined(OS_NACL) 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint MojoBootstrap::GetClientFileDescriptor() const { 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return channel_->GetClientFileDescriptor(); 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint MojoBootstrap::TakeClientFileDescriptor() { 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return channel_->TakeClientFileDescriptor(); 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(OS_POSIX) && !defined(OS_NACL) 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace IPC 206