• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 #ifndef MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
6 #define MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
7 
8 #include <queue>
9 #include <unordered_map>
10 #include <utility>
11 
12 #include "base/callback.h"
13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/process/process_handle.h"
16 #include "base/synchronization/lock.h"
17 #include "base/task_runner.h"
18 #include "build/build_config.h"
19 #include "mojo/edk/embedder/embedder.h"
20 #include "mojo/edk/embedder/platform_handle_vector.h"
21 #include "mojo/edk/embedder/scoped_platform_handle.h"
22 #include "mojo/edk/system/channel.h"
23 #include "mojo/edk/system/ports/name.h"
24 
25 #if defined(OS_MACOSX) && !defined(OS_IOS)
26 #include "mojo/edk/system/mach_port_relay.h"
27 #endif
28 
29 namespace mojo {
30 namespace edk {
31 
32 // Wraps a Channel to send and receive Node control messages.
33 class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>,
34                     public Channel::Delegate
35 #if defined(OS_MACOSX) && !defined(OS_IOS)
36                     , public MachPortRelay::Observer
37 #endif
38   {
39  public:
40   class Delegate {
41    public:
~Delegate()42     virtual ~Delegate() {}
43     virtual void OnAcceptChild(const ports::NodeName& from_node,
44                                const ports::NodeName& parent_name,
45                                const ports::NodeName& token) = 0;
46     virtual void OnAcceptParent(const ports::NodeName& from_node,
47                                 const ports::NodeName& token,
48                                 const ports::NodeName& child_name) = 0;
49     virtual void OnAddBrokerClient(const ports::NodeName& from_node,
50                                    const ports::NodeName& client_name,
51                                    base::ProcessHandle process_handle) = 0;
52     virtual void OnBrokerClientAdded(const ports::NodeName& from_node,
53                                      const ports::NodeName& client_name,
54                                      ScopedPlatformHandle broker_channel) = 0;
55     virtual void OnAcceptBrokerClient(const ports::NodeName& from_node,
56                                       const ports::NodeName& broker_name,
57                                       ScopedPlatformHandle broker_channel) = 0;
58     virtual void OnPortsMessage(const ports::NodeName& from_node,
59                                 Channel::MessagePtr message) = 0;
60     virtual void OnRequestPortMerge(const ports::NodeName& from_node,
61                                     const ports::PortName& connector_port_name,
62                                     const std::string& token) = 0;
63     virtual void OnRequestIntroduction(const ports::NodeName& from_node,
64                                        const ports::NodeName& name) = 0;
65     virtual void OnIntroduce(const ports::NodeName& from_node,
66                              const ports::NodeName& name,
67                              ScopedPlatformHandle channel_handle) = 0;
68     virtual void OnBroadcast(const ports::NodeName& from_node,
69                              Channel::MessagePtr message) = 0;
70 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
71     virtual void OnRelayPortsMessage(const ports::NodeName& from_node,
72                                      base::ProcessHandle from_process,
73                                      const ports::NodeName& destination,
74                                      Channel::MessagePtr message) = 0;
75     virtual void OnPortsMessageFromRelay(const ports::NodeName& from_node,
76                                          const ports::NodeName& source_node,
77                                          Channel::MessagePtr message) = 0;
78 #endif
79 
80     virtual void OnChannelError(const ports::NodeName& node,
81                                 NodeChannel* channel) = 0;
82 
83 #if defined(OS_MACOSX) && !defined(OS_IOS)
84     virtual MachPortRelay* GetMachPortRelay() = 0;
85 #endif
86   };
87 
88   static scoped_refptr<NodeChannel> Create(
89       Delegate* delegate,
90       ScopedPlatformHandle platform_handle,
91       scoped_refptr<base::TaskRunner> io_task_runner,
92       const ProcessErrorCallback& process_error_callback);
93 
94   static Channel::MessagePtr CreatePortsMessage(size_t payload_size,
95                                                 void** payload,
96                                                 size_t num_handles);
97 
98   static void GetPortsMessageData(Channel::Message* message, void** data,
99                                   size_t* num_data_bytes);
100 
101   // Start receiving messages.
102   void Start();
103 
104   // Permanently stop the channel from sending or receiving messages.
105   void ShutDown();
106 
107   // Leaks the pipe handle instead of closing it on shutdown.
108   void LeakHandleOnShutdown();
109 
110   // Invokes the bad message callback for this channel, if any.
111   void NotifyBadMessage(const std::string& error);
112 
113   // Note: On Windows, we take ownership of the remote process handle.
114   void SetRemoteProcessHandle(base::ProcessHandle process_handle);
115   bool HasRemoteProcessHandle();
116   // Note: The returned |ProcessHandle| is owned by the caller and should be
117   // freed if necessary.
118   base::ProcessHandle CopyRemoteProcessHandle();
119 
120   // Used for context in Delegate calls (via |from_node| arguments.)
121   void SetRemoteNodeName(const ports::NodeName& name);
122 
123   void AcceptChild(const ports::NodeName& parent_name,
124                    const ports::NodeName& token);
125   void AcceptParent(const ports::NodeName& token,
126                     const ports::NodeName& child_name);
127   void AddBrokerClient(const ports::NodeName& client_name,
128                        base::ProcessHandle process_handle);
129   void BrokerClientAdded(const ports::NodeName& client_name,
130                          ScopedPlatformHandle broker_channel);
131   void AcceptBrokerClient(const ports::NodeName& broker_name,
132                           ScopedPlatformHandle broker_channel);
133   void PortsMessage(Channel::MessagePtr message);
134   void RequestPortMerge(const ports::PortName& connector_port_name,
135                         const std::string& token);
136   void RequestIntroduction(const ports::NodeName& name);
137   void Introduce(const ports::NodeName& name,
138                  ScopedPlatformHandle channel_handle);
139   void Broadcast(Channel::MessagePtr message);
140 
141 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
142   // Relay the message to the specified node via this channel.  This is used to
143   // pass windows handles between two processes that do not have permission to
144   // duplicate handles into the other's address space. The relay process is
145   // assumed to have that permission.
146   void RelayPortsMessage(const ports::NodeName& destination,
147                          Channel::MessagePtr message);
148 
149   // Sends a message to its destination from a relay. This is interpreted by the
150   // receiver similarly to PortsMessage, but the original source node is
151   // provided as additional message metadata from the (trusted) relay node.
152   void PortsMessageFromRelay(const ports::NodeName& source,
153                              Channel::MessagePtr message);
154 #endif
155 
156  private:
157   friend class base::RefCountedThreadSafe<NodeChannel>;
158 
159   using PendingMessageQueue = std::queue<Channel::MessagePtr>;
160   using PendingRelayMessageQueue =
161       std::queue<std::pair<ports::NodeName, Channel::MessagePtr>>;
162 
163   NodeChannel(Delegate* delegate,
164               ScopedPlatformHandle platform_handle,
165               scoped_refptr<base::TaskRunner> io_task_runner,
166               const ProcessErrorCallback& process_error_callback);
167   ~NodeChannel() override;
168 
169   // Channel::Delegate:
170   void OnChannelMessage(const void* payload,
171                         size_t payload_size,
172                         ScopedPlatformHandleVectorPtr handles) override;
173   void OnChannelError() override;
174 
175 #if defined(OS_MACOSX) && !defined(OS_IOS)
176   // MachPortRelay::Observer:
177   void OnProcessReady(base::ProcessHandle process) override;
178 
179   void ProcessPendingMessagesWithMachPorts();
180 #endif
181 
182   void WriteChannelMessage(Channel::MessagePtr message);
183 
184   Delegate* const delegate_;
185   const scoped_refptr<base::TaskRunner> io_task_runner_;
186   const ProcessErrorCallback process_error_callback_;
187 
188   base::Lock channel_lock_;
189   scoped_refptr<Channel> channel_;
190 
191   // Must only be accessed from |io_task_runner_|'s thread.
192   ports::NodeName remote_node_name_;
193 
194   base::Lock remote_process_handle_lock_;
195   base::ProcessHandle remote_process_handle_ = base::kNullProcessHandle;
196 #if defined(OS_WIN)
197   ScopedPlatformHandle scoped_remote_process_handle_;
198 #endif
199 
200 #if defined(OS_MACOSX) && !defined(OS_IOS)
201   base::Lock pending_mach_messages_lock_;
202   PendingMessageQueue pending_write_messages_;
203   PendingRelayMessageQueue pending_relay_messages_;
204 #endif
205 
206   DISALLOW_COPY_AND_ASSIGN(NodeChannel);
207 };
208 
209 }  // namespace edk
210 }  // namespace mojo
211 
212 #endif  // MOJO_EDK_SYSTEM_NODE_CHANNEL_H_
213