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