Home | History | Annotate | Download | only in system
      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:
     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