summaryrefslogtreecommitdiffstats
path: root/ipc/mojo/ipc_channel_mojo.h
blob: e7b7b767a68a5a82d20fea25ad0a92121b3dffe5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IPC_IPC_CHANNEL_MOJO_H_
#define IPC_IPC_CHANNEL_MOJO_H_

#include <vector>

#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_factory.h"
#include "ipc/ipc_export.h"
#include "ipc/mojo/ipc_message_pipe_reader.h"
#include "ipc/mojo/ipc_mojo_bootstrap.h"
#include "ipc/mojo/scoped_ipc_support.h"
#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h"
#include "third_party/mojo/src/mojo/public/cpp/system/core.h"

namespace IPC {

// Mojo-based IPC::Channel implementation over a platform handle.
//
// ChannelMojo builds Mojo MessagePipe using underlying pipe given by
// "bootstrap" IPC::Channel which creates and owns platform pipe like
// named socket. The bootstrap Channel is used only for establishing
// the underlying connection. ChannelMojo takes its handle over once
// the it is made and puts MessagePipe on it.
//
// ChannelMojo has a couple of MessagePipes:
//
// * The first MessagePipe, which is built on top of bootstrap handle,
//   is the "control" pipe. It is used to communicate out-of-band
//   control messages that aren't visible from IPC::Listener.
//
// * The second MessagePipe, which is created by the server channel
//   and sent to client Channel over the control pipe, is used
//   to send IPC::Messages as an IPC::Sender.
//
// TODO(morrita): Extract handle creation part of IPC::Channel into
//                separate class to clarify what ChannelMojo relies
//                on.
// TODO(morrita): Add APIs to create extra MessagePipes to let
//                Mojo-based objects talk over this Channel.
//
class IPC_MOJO_EXPORT ChannelMojo
    : public Channel,
      public MojoBootstrap::Delegate,
      public NON_EXPORTED_BASE(internal::MessagePipeReader::Delegate) {
 public:
  using CreateMessagingPipeCallback =
      base::Callback<void(mojo::ScopedMessagePipeHandle)>;
  using CreateMessagingPipeOnIOThreadCallback =
      base::Callback<void(mojo::ScopedMessagePipeHandle,
                          mojo::embedder::ChannelInfo*)>;

  // True if ChannelMojo should be used regardless of the flag.
  static bool ShouldBeUsed();

  // Create ChannelMojo. A bootstrap channel is created as well.
  // |broker| must outlive the newly created channel.
  static scoped_ptr<ChannelMojo> Create(
      scoped_refptr<base::TaskRunner> io_runner,
      const ChannelHandle& channel_handle,
      Mode mode,
      Listener* listener,
      AttachmentBroker* broker);

  // Create a factory object for ChannelMojo.
  // The factory is used to create Mojo-based ChannelProxy family.
  // |host| must not be null.
  // TODO(erikchen): Remove default parameter for |broker|. It exists only to
  // make the upcoming refactor decomposable into smaller CLs.
  // http://crbug.com/493414.
  // |broker| must outlive the factory and all channels it creates.
  static scoped_ptr<ChannelFactory> CreateServerFactory(
      scoped_refptr<base::TaskRunner> io_runner,
      const ChannelHandle& channel_handle,
      AttachmentBroker* broker = nullptr);

  // TODO(erikchen): Remove default parameter for |broker|. It exists only to
  // make the upcoming refactor decomposable into smaller CLs.
  // http://crbug.com/493414.
  // |broker| must outlive the factory and all channels it creates.
  static scoped_ptr<ChannelFactory> CreateClientFactory(
      scoped_refptr<base::TaskRunner> io_runner,
      const ChannelHandle& channel_handle,
      AttachmentBroker* broker = nullptr);

  ~ChannelMojo() override;

  // Channel implementation
  bool Connect() override;
  void Close() override;
  bool Send(Message* message) override;
  bool IsSendThreadSafe() const override;
  base::ProcessId GetPeerPID() const override;
  base::ProcessId GetSelfPID() const override;

#if defined(OS_POSIX) && !defined(OS_NACL)
  int GetClientFileDescriptor() const override;
  base::ScopedFD TakeClientFileDescriptor() override;
#endif  // defined(OS_POSIX) && !defined(OS_NACL)

  // These access protected API of IPC::Message, which has ChannelMojo
  // as a friend class.
  static MojoResult WriteToMessageAttachmentSet(
      const std::vector<MojoHandle>& handle_buffer,
      Message* message);
  static MojoResult ReadFromMessageAttachmentSet(
      Message* message,
      std::vector<MojoHandle>* handles);

  // MojoBootstrapDelegate implementation
  void OnBootstrapError() override;

  // MessagePipeReader::Delegate
  void OnMessageReceived(Message& message) override;
  void OnPipeClosed(internal::MessagePipeReader* reader) override;
  void OnPipeError(internal::MessagePipeReader* reader) override;

 protected:
  ChannelMojo(scoped_refptr<base::TaskRunner> io_runner,
              const ChannelHandle& channel_handle,
              Mode mode,
              Listener* listener,
              AttachmentBroker* broker);

  void CreateMessagingPipe(mojo::embedder::ScopedPlatformHandle handle,
                           const CreateMessagingPipeCallback& callback);
  void InitMessageReader(mojo::ScopedMessagePipeHandle pipe, int32_t peer_pid);

  Listener* listener() const { return listener_; }
  void set_peer_pid(base::ProcessId pid) { peer_pid_ = pid; }

 private:
  struct ChannelInfoDeleter {
    explicit ChannelInfoDeleter(scoped_refptr<base::TaskRunner> io_runner);
    ~ChannelInfoDeleter();

    void operator()(mojo::embedder::ChannelInfo* ptr) const;

    scoped_refptr<base::TaskRunner> io_runner;
  };

  // ChannelMojo needs to kill its MessagePipeReader in delayed manner
  // because the channel wants to kill these readers during the
  // notifications invoked by them.
  typedef internal::MessagePipeReader::DelayedDeleter ReaderDeleter;

  void InitOnIOThread();

  static void CreateMessagingPipeOnIOThread(
      mojo::embedder::ScopedPlatformHandle handle,
      scoped_refptr<base::TaskRunner> callback_runner,
      const CreateMessagingPipeOnIOThreadCallback& callback);
  void OnMessagingPipeCreated(const CreateMessagingPipeCallback& callback,
                              mojo::ScopedMessagePipeHandle handle,
                              mojo::embedder::ChannelInfo* channel_info);

  scoped_ptr<MojoBootstrap> bootstrap_;
  Listener* listener_;
  base::ProcessId peer_pid_;
  scoped_refptr<base::TaskRunner> io_runner_;
  scoped_ptr<mojo::embedder::ChannelInfo,
             ChannelInfoDeleter> channel_info_;

  // Guards |message_reader_|, |waiting_connect_| and |pending_messages_|
  //
  // * The contents of |pending_messages_| can be modified from any thread.
  // * |message_reader_| is modified only from the IO thread,
  //   but they can be referenced from other threads.
  base::Lock lock_;
  scoped_ptr<internal::MessagePipeReader, ReaderDeleter> message_reader_;
  ScopedVector<Message> pending_messages_;
  bool waiting_connect_;

  scoped_ptr<ScopedIPCSupport> ipc_support_;

  base::WeakPtrFactory<ChannelMojo> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(ChannelMojo);
};

}  // namespace IPC

#endif  // IPC_IPC_CHANNEL_MOJO_H_