1 // Copyright 2015 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 IPC_ATTACHMENT_BROKER_H_
6 #define IPC_ATTACHMENT_BROKER_H_
7 
8 #include "base/gtest_prod_util.h"
9 #include "base/macros.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/process/process_handle.h"
12 #include "base/synchronization/lock.h"
13 #include "build/build_config.h"
14 #include "ipc/brokerable_attachment.h"
15 #include "ipc/ipc_export.h"
16 #include "ipc/ipc_listener.h"
17 
18 // If the platform has no attachments that need brokering, then it shouldn't
19 // compile any code that calls member functions of AttachmentBroker. This
20 // prevents symbols only used by AttachmentBroker and its subclasses from
21 // making it into the binary.
22 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
23 #define USE_ATTACHMENT_BROKER 1
24 #else
25 #define USE_ATTACHMENT_BROKER 0
26 #endif  // defined(OS_WIN)
27 
28 namespace base {
29 class SequencedTaskRunner;
30 class SingleThreadTaskRunner;
31 };
32 
33 namespace IPC {
34 
35 class AttachmentBroker;
36 class Endpoint;
37 
38 // Classes that inherit from this abstract base class are capable of
39 // communicating with a broker to send and receive attachments to Chrome IPC
40 // messages.
41 class IPC_EXPORT SupportsAttachmentBrokering {
42  public:
43   // Returns an AttachmentBroker used to broker attachments of IPC messages to
44   // other processes. There must be exactly one AttachmentBroker per process.
45   virtual AttachmentBroker* GetAttachmentBroker() = 0;
46 };
47 
48 // Responsible for brokering attachments to Chrome IPC messages. On platforms
49 // that support attachment brokering, every IPC channel should have a reference
50 // to a AttachmentBroker.
51 // This class is not thread safe. The implementation of this class assumes that
52 // it is only ever used on the same thread as its consumers.
53 class IPC_EXPORT AttachmentBroker : public Listener {
54  public:
55   // A standard observer interface that allows consumers of the AttachmentBroker
56   // to be notified when a new attachment has been received.
57   class Observer {
58    public:
59     virtual void ReceivedBrokerableAttachmentWithId(
60         const BrokerableAttachment::AttachmentId& id) = 0;
61   };
62 
63   // Each process has at most one attachment broker. The process is responsible
64   // for ensuring that |broker| stays alive for as long as the process is
65   // sending/receiving ipc messages.
66   static void SetGlobal(AttachmentBroker* broker);
67   static AttachmentBroker* GetGlobal();
68 
69   AttachmentBroker();
70   ~AttachmentBroker() override;
71 
72   // Sends |attachment| to |destination_process|. The implementation uses an
73   // IPC::Channel to communicate with the broker process. This may be the same
74   // IPC::Channel that is requesting the brokering of an attachment.
75   // Returns true on success and false otherwise.
76   virtual bool SendAttachmentToProcess(
77       const scoped_refptr<BrokerableAttachment>& attachment,
78       base::ProcessId destination_process) = 0;
79 
80   // Returns whether the attachment was available. If the attachment was
81   // available, populates the output parameter |attachment|.
82   bool GetAttachmentWithId(BrokerableAttachment::AttachmentId id,
83                            scoped_refptr<BrokerableAttachment>* attachment);
84 
85   // Any given observer should only ever add itself once to the observer list.
86   // Notifications to |observer| will be posted to |runner|.
87   // The |observer| is expected to call RemoveObserver() before being destroyed.
88   void AddObserver(Observer* observer,
89                    const scoped_refptr<base::SequencedTaskRunner>& runner);
90   void RemoveObserver(Observer* observer);
91 
92   // These two methods should only be called by the broker process.
93   //
94   // Each unprivileged process should have one IPC channel on which it
95   // communicates attachment information with the broker process. In the broker
96   // process, these channels must be registered and deregistered with the
97   // Attachment Broker as they are created and destroyed.
98   //
99   // Invocations of Send() on |endpoint| will occur on thread bound to |runner|.
100   virtual void RegisterCommunicationChannel(
101       Endpoint* endpoint,
102       scoped_refptr<base::SingleThreadTaskRunner> runner);
103   virtual void DeregisterCommunicationChannel(Endpoint* endpoint);
104 
105   // In each unprivileged process, exactly one channel should be used to
106   // communicate brokerable attachments with the broker process.
107   virtual void RegisterBrokerCommunicationChannel(Endpoint* endpoint);
108   virtual void DeregisterBrokerCommunicationChannel(Endpoint* endpoint);
109 
110   // Informs the attachment broker that a channel endpoint has received its
111   // peer's PID.
112   virtual void ReceivedPeerPid(base::ProcessId peer_pid);
113 
114   // True if and only if this broker is privileged.
115   virtual bool IsPrivilegedBroker();
116 
117  protected:
118   using AttachmentVector = std::vector<scoped_refptr<BrokerableAttachment>>;
119 
120   // Adds |attachment| to |attachments_|, and notifies the observers.
121   void HandleReceivedAttachment(
122       const scoped_refptr<BrokerableAttachment>& attachment);
123 
124   // Informs the observers that a new BrokerableAttachment has been received.
125   void NotifyObservers(const BrokerableAttachment::AttachmentId& id);
126 
127   // Informs the observer identified by |unique_id| that a new
128   // BrokerableAttachment has been received.
129   void NotifyObserver(int unique_id,
130                       const BrokerableAttachment::AttachmentId& id);
131 
132   // This method is exposed for testing only.
get_attachments()133   AttachmentVector* get_attachments() { return &attachments_; }
134 
get_lock()135   base::Lock* get_lock() { return &lock_; }
136 
137  private:
138 #if defined(OS_WIN)
139   FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerUnprivilegedWinTest,
140                            ReceiveValidMessage);
141   FRIEND_TEST_ALL_PREFIXES(AttachmentBrokerUnprivilegedWinTest,
142                            ReceiveInvalidMessage);
143 #endif  // defined(OS_WIN)
144 
145   // A vector of BrokerableAttachments that have been received, but not yet
146   // consumed.
147   // A std::vector is used instead of a std::map because this container is
148   // expected to have few elements, for which a std::vector is expected to have
149   // better performance.
150   AttachmentVector attachments_;
151 
152   struct ObserverInfo {
153     ObserverInfo();
154     ObserverInfo(const ObserverInfo& other);
155     ~ObserverInfo();
156 
157     Observer* observer;
158     int unique_id;
159 
160     // Notifications must be dispatched onto |runner|.
161     scoped_refptr<base::SequencedTaskRunner> runner;
162   };
163   std::vector<ObserverInfo> observers_;
164 
165   // This member holds the last id given to an ObserverInfo.
166   int last_unique_id_;
167 
168   // The AttachmentBroker can be accessed from any thread, so modifications to
169   // internal state must be guarded by a lock.
170   base::Lock lock_;
171   DISALLOW_COPY_AND_ASSIGN(AttachmentBroker);
172 };
173 
174 }  // namespace IPC
175 
176 #endif  // IPC_ATTACHMENT_BROKER_H_
177