Avi Drissman | ea1be23 | 2022-09-14 23:29:06 | [diff] [blame] | 1 | // Copyright 2012 The Chromium Authors |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
[email protected] | 92bf906 | 2011-05-02 18:00:49 | [diff] [blame] | 5 | #ifndef IPC_IPC_CHANNEL_PROXY_H_ |
| 6 | #define IPC_IPC_CHANNEL_PROXY_H_ |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 7 | |
avi | 246998d8 | 2015-12-22 02:39:04 | [diff] [blame] | 8 | #include <stdint.h> |
| 9 | |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 10 | #include <map> |
danakj | 03de39b2 | 2016-04-23 04:21:09 | [diff] [blame] | 11 | #include <memory> |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 12 | #include <string> |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 13 | #include <vector> |
[email protected] | 7bf73095 | 2009-05-29 09:31:15 | [diff] [blame] | 14 | |
Sebastien Marchand | 6d0558fd | 2019-01-25 16:49:37 | [diff] [blame] | 15 | #include "base/bind.h" |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 16 | #include "base/callback.h" |
Ken Rockot | 3044d21 | 2018-01-23 02:44:39 | [diff] [blame] | 17 | #include "base/component_export.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 18 | #include "base/memory/raw_ptr.h" |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 19 | #include "base/memory/ref_counted.h" |
gab | 21edbfa | 2017-05-31 16:49:12 | [diff] [blame] | 20 | #include "base/sequence_checker.h" |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 21 | #include "base/synchronization/lock.h" |
avi | 246998d8 | 2015-12-22 02:39:04 | [diff] [blame] | 22 | #include "build/build_config.h" |
Takuto Ikuta | aa3b796c | 2019-02-06 02:54:56 | [diff] [blame] | 23 | #include "ipc/ipc.mojom.h" |
[email protected] | 946d1b2 | 2009-07-22 23:57:21 | [diff] [blame] | 24 | #include "ipc/ipc_channel.h" |
[email protected] | 42ce94e | 2010-12-08 19:28:09 | [diff] [blame] | 25 | #include "ipc/ipc_channel_handle.h" |
[email protected] | 57319ce | 2012-06-11 22:35:26 | [diff] [blame] | 26 | #include "ipc/ipc_listener.h" |
| 27 | #include "ipc/ipc_sender.h" |
Miyoung Shin | 998cfcf | 2019-09-05 07:31:51 | [diff] [blame] | 28 | #include "mojo/public/cpp/bindings/associated_remote.h" |
Ken Rockot | 493a59f3 | 2021-06-04 22:16:50 | [diff] [blame] | 29 | #include "mojo/public/cpp/bindings/generic_pending_associated_receiver.h" |
Sigurdur Asgeirsson | d655dd65f | 2019-11-12 19:32:20 | [diff] [blame] | 30 | #include "mojo/public/cpp/bindings/lib/message_quota_checker.h" |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 31 | #include "mojo/public/cpp/bindings/pending_associated_receiver.h" |
| 32 | #include "mojo/public/cpp/bindings/pending_associated_remote.h" |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 33 | #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 34 | #include "mojo/public/cpp/bindings/shared_associated_remote.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 35 | |
[email protected] | b243230 | 2012-07-02 21:15:52 | [diff] [blame] | 36 | namespace base { |
| 37 | class SingleThreadTaskRunner; |
| 38 | } |
| 39 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 40 | namespace IPC { |
| 41 | |
[email protected] | 6486088 | 2014-08-04 23:44:17 | [diff] [blame] | 42 | class ChannelFactory; |
[email protected] | 7412204 | 2014-04-25 00:07:30 | [diff] [blame] | 43 | class MessageFilter; |
| 44 | class MessageFilterRouter; |
[email protected] | 16395142 | 2009-07-28 22:09:45 | [diff] [blame] | 45 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 46 | //----------------------------------------------------------------------------- |
| 47 | // IPC::ChannelProxy |
| 48 | // |
| 49 | // This class is a helper class that is useful when you wish to run an IPC |
| 50 | // channel on a background thread. It provides you with the option of either |
| 51 | // handling IPC messages on that background thread or having them dispatched to |
| 52 | // your main thread (the thread on which the IPC::ChannelProxy is created). |
| 53 | // |
| 54 | // The API for an IPC::ChannelProxy is very similar to that of an IPC::Channel. |
| 55 | // When you send a message to an IPC::ChannelProxy, the message is routed to |
| 56 | // the background thread, where it is then passed to the IPC::Channel's Send |
| 57 | // method. This means that you can send a message from your thread and your |
| 58 | // message will be sent over the IPC channel when possible instead of being |
| 59 | // delayed until your thread returns to its message loop. (Often IPC messages |
| 60 | // will queue up on the IPC::Channel when there is a lot of traffic, and the |
| 61 | // channel will not get cycles to flush its message queue until the thread, on |
| 62 | // which it is running, returns to its message loop.) |
| 63 | // |
| 64 | // An IPC::ChannelProxy can have a MessageFilter associated with it, which will |
| 65 | // be notified of incoming messages on the IPC::Channel's thread. This gives |
| 66 | // the consumer of IPC::ChannelProxy the ability to respond to incoming |
| 67 | // messages on this background thread instead of on their own thread, which may |
| 68 | // be bogged down with other processing. The result can be greatly improved |
| 69 | // latency for messages that can be handled on a background thread. |
| 70 | // |
| 71 | // The consumer of IPC::ChannelProxy is responsible for allocating the Thread |
| 72 | // instance where the IPC::Channel will be created and operated. |
| 73 | // |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 74 | // Thread-safe send |
| 75 | // |
| 76 | // If a particular |Channel| implementation has a thread-safe |Send()| operation |
| 77 | // then ChannelProxy skips the inter-thread hop and calls |Send()| directly. In |
| 78 | // this case the |channel_| variable is touched by multiple threads so |
| 79 | // |channel_lifetime_lock_| is used to protect it. The locking overhead is only |
| 80 | // paid if the underlying channel supports thread-safe |Send|. |
| 81 | // |
Ken Rockot | 3044d21 | 2018-01-23 02:44:39 | [diff] [blame] | 82 | class COMPONENT_EXPORT(IPC) ChannelProxy : public Sender { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 83 | public: |
mbarbella | e97877bc | 2015-03-06 21:51:14 | [diff] [blame] | 84 | #if defined(ENABLE_IPC_FUZZER) |
| 85 | // Interface for a filter to be imposed on outgoing messages which can |
| 86 | // re-write the message. Used for testing. |
| 87 | class OutgoingMessageFilter { |
| 88 | public: |
| 89 | virtual Message* Rewrite(Message* message) = 0; |
| 90 | }; |
| 91 | #endif |
| 92 | |
[email protected] | 42ce94e | 2010-12-08 19:28:09 | [diff] [blame] | 93 | // Initializes a channel proxy. The channel_handle and mode parameters are |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 94 | // passed directly to the underlying IPC::Channel. The listener is called on |
| 95 | // the thread that creates the ChannelProxy. The filter's OnMessageReceived |
| 96 | // method is called on the thread where the IPC::Channel is running. The |
| 97 | // filter may be null if the consumer is not interested in handling messages |
| 98 | // on the background thread. Any message not handled by the filter will be |
[email protected] | b243230 | 2012-07-02 21:15:52 | [diff] [blame] | 99 | // dispatched to the listener. The given task runner correspond to a thread |
| 100 | // on which IPC::Channel is created and used (e.g. IO thread). |
danakj | 03de39b2 | 2016-04-23 04:21:09 | [diff] [blame] | 101 | static std::unique_ptr<ChannelProxy> Create( |
[email protected] | fca876a1 | 2014-06-05 16:15:38 | [diff] [blame] | 102 | const IPC::ChannelHandle& channel_handle, |
| 103 | Channel::Mode mode, |
| 104 | Listener* listener, |
Hajime Hoshi | ff15e97 | 2017-11-09 06:37:09 | [diff] [blame] | 105 | const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, |
| 106 | const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 107 | |
danakj | 03de39b2 | 2016-04-23 04:21:09 | [diff] [blame] | 108 | static std::unique_ptr<ChannelProxy> Create( |
| 109 | std::unique_ptr<ChannelFactory> factory, |
[email protected] | 6486088 | 2014-08-04 23:44:17 | [diff] [blame] | 110 | Listener* listener, |
Hajime Hoshi | ff15e97 | 2017-11-09 06:37:09 | [diff] [blame] | 111 | const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, |
| 112 | const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner); |
[email protected] | 6486088 | 2014-08-04 23:44:17 | [diff] [blame] | 113 | |
erikchen | 9097190 | 2016-04-25 23:45:31 | [diff] [blame] | 114 | // Constructs a ChannelProxy without initializing it. |
| 115 | ChannelProxy( |
| 116 | Listener* listener, |
Hajime Hoshi | ff15e97 | 2017-11-09 06:37:09 | [diff] [blame] | 117 | const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, |
| 118 | const scoped_refptr<base::SingleThreadTaskRunner>& listener_task_runner); |
erikchen | 9097190 | 2016-04-25 23:45:31 | [diff] [blame] | 119 | |
dcheng | fe61fca | 2014-10-22 02:29:52 | [diff] [blame] | 120 | ~ChannelProxy() override; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 121 | |
[email protected] | 952394af | 2011-11-16 01:06:46 | [diff] [blame] | 122 | // Initializes the channel proxy. Only call this once to initialize a channel |
rockot | 401fb2c | 2016-09-06 18:35:57 | [diff] [blame] | 123 | // proxy that was not initialized in its constructor. If |create_pipe_now| is |
[email protected] | 952394af | 2011-11-16 01:06:46 | [diff] [blame] | 124 | // true, the pipe is created synchronously. Otherwise it's created on the IO |
rockot | 1018875 | 2016-09-08 18:24:56 | [diff] [blame] | 125 | // thread. |
erikchen | 27aa7d8 | 2015-06-16 21:21:04 | [diff] [blame] | 126 | void Init(const IPC::ChannelHandle& channel_handle, |
| 127 | Channel::Mode mode, |
rockot | 1018875 | 2016-09-08 18:24:56 | [diff] [blame] | 128 | bool create_pipe_now); |
rockot | 401fb2c | 2016-09-06 18:35:57 | [diff] [blame] | 129 | void Init(std::unique_ptr<ChannelFactory> factory, |
rockot | 1018875 | 2016-09-08 18:24:56 | [diff] [blame] | 130 | bool create_pipe_now); |
rockot | 401fb2c | 2016-09-06 18:35:57 | [diff] [blame] | 131 | |
rockot | 1018875 | 2016-09-08 18:24:56 | [diff] [blame] | 132 | // Pause the channel. Subsequent calls to Send() will be internally queued |
| 133 | // until Unpause() is called. Queued messages will not be sent until the |
| 134 | // channel is flushed. |
| 135 | void Pause(); |
| 136 | |
| 137 | // Unpause the channel. If |flush| is true the channel will be flushed as soon |
| 138 | // as it's unpaused (see Flush() below.) Otherwise you must explicitly call |
| 139 | // Flush() to flush messages which were queued while the channel was paused. |
rockot | 401fb2c | 2016-09-06 18:35:57 | [diff] [blame] | 140 | void Unpause(bool flush); |
| 141 | |
| 142 | // Flush the channel. This sends any messages which were queued before calling |
| 143 | // Connect. Only useful if Unpause(false) was called previously. |
| 144 | void Flush(); |
[email protected] | 952394af | 2011-11-16 01:06:46 | [diff] [blame] | 145 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 146 | // Close the IPC::Channel. This operation completes asynchronously, once the |
| 147 | // background thread processes the command to close the channel. It is ok to |
| 148 | // call this method multiple times. Redundant calls are ignored. |
| 149 | // |
[email protected] | 7412204 | 2014-04-25 00:07:30 | [diff] [blame] | 150 | // WARNING: MessageFilter objects held by the ChannelProxy is also |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 151 | // released asynchronously, and it may in fact have its final reference |
| 152 | // released on the background thread. The caller should be careful to deal |
| 153 | // with / allow for this possibility. |
| 154 | void Close(); |
| 155 | |
rockot | f14a8ae | 2016-06-16 19:28:41 | [diff] [blame] | 156 | // Send a message asynchronously. The message is routed to the background |
| 157 | // thread where it is passed to the IPC::Channel's Send method. |
dcheng | fe61fca | 2014-10-22 02:29:52 | [diff] [blame] | 158 | bool Send(Message* message) override; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 159 | |
| 160 | // Used to intercept messages as they are received on the background thread. |
| 161 | // |
| 162 | // Ordinarily, messages sent to the ChannelProxy are routed to the matching |
| 163 | // listener on the worker thread. This API allows code to intercept messages |
| 164 | // before they are sent to the worker thread. |
[email protected] | 4b580bf | 2010-12-02 19:16:07 | [diff] [blame] | 165 | // If you call this before the target process is launched, then you're |
| 166 | // guaranteed to not miss any messages. But if you call this anytime after, |
| 167 | // then some messages might be missed since the filter is added internally on |
| 168 | // the IO thread. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 169 | void AddFilter(MessageFilter* filter); |
| 170 | void RemoveFilter(MessageFilter* filter); |
| 171 | |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 172 | using GenericAssociatedInterfaceFactory = |
Matt Falkenhagen | 6140bb1 | 2019-11-19 22:52:36 | [diff] [blame] | 173 | base::RepeatingCallback<void(mojo::ScopedInterfaceEndpointHandle)>; |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 174 | |
| 175 | // Adds a generic associated interface factory to bind incoming interface |
rockot | fd3d9084 | 2016-09-15 23:57:29 | [diff] [blame] | 176 | // requests directly on the IO thread. MUST be called either before Init() or |
| 177 | // before the remote end of the Channel is able to send messages (e.g. before |
| 178 | // its process is launched.) |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 179 | void AddGenericAssociatedInterfaceForIOThread( |
| 180 | const std::string& name, |
| 181 | const GenericAssociatedInterfaceFactory& factory); |
| 182 | |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 183 | template <typename Interface> |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 184 | using AssociatedInterfaceFactory = |
| 185 | base::RepeatingCallback<void(mojo::PendingAssociatedReceiver<Interface>)>; |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 186 | |
| 187 | // Helper to bind an IO-thread associated interface factory, inferring the |
| 188 | // interface name from the callback argument's type. MUST be called before |
| 189 | // Init(). |
| 190 | template <typename Interface> |
| 191 | void AddAssociatedInterfaceForIOThread( |
| 192 | const AssociatedInterfaceFactory<Interface>& factory) { |
| 193 | AddGenericAssociatedInterfaceForIOThread( |
| 194 | Interface::Name_, |
Matt Falkenhagen | 6140bb1 | 2019-11-19 22:52:36 | [diff] [blame] | 195 | base::BindRepeating( |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 196 | &ChannelProxy::BindPendingAssociatedReceiver<Interface>, factory)); |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 197 | } |
| 198 | |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 199 | // Requests an associated interface from the remote endpoint. |
Ken Rockot | 493a59f3 | 2021-06-04 22:16:50 | [diff] [blame] | 200 | void GetRemoteAssociatedInterface( |
| 201 | mojo::GenericPendingAssociatedReceiver receiver); |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 202 | |
Miyoung Shin | 998cfcf | 2019-09-05 07:31:51 | [diff] [blame] | 203 | // Template helper to receive associated interfaces from the remote endpoint. |
| 204 | template <typename Interface> |
| 205 | void GetRemoteAssociatedInterface(mojo::AssociatedRemote<Interface>* proxy) { |
Ken Rockot | 493a59f3 | 2021-06-04 22:16:50 | [diff] [blame] | 206 | GetRemoteAssociatedInterface(proxy->BindNewEndpointAndPassReceiver()); |
Miyoung Shin | 998cfcf | 2019-09-05 07:31:51 | [diff] [blame] | 207 | } |
| 208 | |
mbarbella | e97877bc | 2015-03-06 21:51:14 | [diff] [blame] | 209 | #if defined(ENABLE_IPC_FUZZER) |
| 210 | void set_outgoing_message_filter(OutgoingMessageFilter* filter) { |
| 211 | outgoing_message_filter_ = filter; |
| 212 | } |
| 213 | #endif |
| 214 | |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 215 | // Creates a SharedAssociatedRemote for |Interface|. This object may be used |
| 216 | // to send messages on the interface from any thread and those messages will |
| 217 | // remain ordered with respect to other messages sent on the same thread over |
| 218 | // other SharedAssociatedRemotes associated with the same Channel. |
jcivelli | 315d17f | 2016-11-29 16:15:05 | [diff] [blame] | 219 | template <typename Interface> |
rockot | a628d0b | 2017-02-09 08:40:15 | [diff] [blame] | 220 | void GetThreadSafeRemoteAssociatedInterface( |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 221 | scoped_refptr<mojo::SharedAssociatedRemote<Interface>>* out_remote) { |
| 222 | mojo::PendingAssociatedRemote<Interface> pending_remote; |
| 223 | auto receiver = pending_remote.InitWithNewEndpointAndPassReceiver(); |
| 224 | GetGenericRemoteAssociatedInterface(Interface::Name_, |
| 225 | receiver.PassHandle()); |
| 226 | *out_remote = mojo::SharedAssociatedRemote<Interface>::Create( |
| 227 | std::move(pending_remote), ipc_task_runner()); |
jcivelli | 315d17f | 2016-11-29 16:15:05 | [diff] [blame] | 228 | } |
| 229 | |
jcivelli | 35e5ff5 | 2017-01-06 18:23:01 | [diff] [blame] | 230 | base::SingleThreadTaskRunner* ipc_task_runner() const { |
| 231 | return context_->ipc_task_runner(); |
| 232 | } |
| 233 | |
xlai | 11ac780 | 2017-04-07 20:13:18 | [diff] [blame] | 234 | const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner_refptr() |
| 235 | const { |
| 236 | return context_->ipc_task_runner_refptr(); |
| 237 | } |
| 238 | |
[email protected] | b243230 | 2012-07-02 21:15:52 | [diff] [blame] | 239 | // Called to clear the pointer to the IPC task runner when it's going away. |
| 240 | void ClearIPCTaskRunner(); |
[email protected] | 42f1d782 | 2009-07-23 18:17:55 | [diff] [blame] | 241 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 242 | protected: |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 243 | class Context; |
| 244 | // A subclass uses this constructor if it needs to add more information |
[email protected] | 952394af | 2011-11-16 01:06:46 | [diff] [blame] | 245 | // to the internal state. |
rockot | 0e4de5f | 2016-07-22 21:18:07 | [diff] [blame] | 246 | explicit ChannelProxy(Context* context); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 247 | |
| 248 | // Used internally to hold state that is referenced on the IPC thread. |
| 249 | class Context : public base::RefCountedThreadSafe<Context>, |
[email protected] | 57319ce | 2012-06-11 22:35:26 | [diff] [blame] | 250 | public Listener { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 251 | public: |
dcheng | fd03370 | 2014-08-28 16:59:29 | [diff] [blame] | 252 | Context(Listener* listener, |
Hajime Hoshi | ff15e97 | 2017-11-09 06:37:09 | [diff] [blame] | 253 | const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner, |
| 254 | const scoped_refptr<base::SingleThreadTaskRunner>& |
| 255 | listener_task_runner); |
[email protected] | b243230 | 2012-07-02 21:15:52 | [diff] [blame] | 256 | void ClearIPCTaskRunner(); |
| 257 | base::SingleThreadTaskRunner* ipc_task_runner() const { |
[email protected] | 1757164 | 2013-06-01 04:11:27 | [diff] [blame] | 258 | return ipc_task_runner_.get(); |
[email protected] | 92bf906 | 2011-05-02 18:00:49 | [diff] [blame] | 259 | } |
xlai | 11ac780 | 2017-04-07 20:13:18 | [diff] [blame] | 260 | const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner_refptr() |
| 261 | const { |
| 262 | return ipc_task_runner_; |
| 263 | } |
| 264 | |
Hajime Hoshi | 138652c9 | 2018-01-12 15:11:44 | [diff] [blame] | 265 | scoped_refptr<base::SingleThreadTaskRunner> listener_task_runner() { |
Yuzu Saijo | 8866b1d | 2019-05-24 03:23:28 | [diff] [blame] | 266 | return default_listener_task_runner_; |
Hajime Hoshi | 138652c9 | 2018-01-12 15:11:44 | [diff] [blame] | 267 | } |
| 268 | |
[email protected] | 827ab81 | 2009-03-12 07:17:17 | [diff] [blame] | 269 | // Dispatches a message on the listener thread. |
| 270 | void OnDispatchMessage(const Message& message); |
| 271 | |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 272 | // Sends |message| from appropriate thread. |
Etienne Bergeron | 0a07d73d | 2019-06-27 16:40:47 | [diff] [blame] | 273 | void Send(Message* message); |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 274 | |
Yuzu Saijo | 8866b1d | 2019-05-24 03:23:28 | [diff] [blame] | 275 | // Adds |task_runner| for the task to be executed later. |
| 276 | void AddListenerTaskRunner( |
| 277 | int32_t routing_id, |
| 278 | scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
| 279 | |
| 280 | // Removes task runner for |routing_id|. |
| 281 | void RemoveListenerTaskRunner(int32_t routing_id); |
| 282 | |
| 283 | // Called on the IPC::Channel thread. |
| 284 | // Returns the task runner associated with |routing_id|. |
Yuzu Saijo | 3b633001 | 2019-07-11 03:51:27 | [diff] [blame] | 285 | scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( |
| 286 | int32_t routing_id); |
Yuzu Saijo | 8866b1d | 2019-05-24 03:23:28 | [diff] [blame] | 287 | |
[email protected] | d3ae7a07 | 2008-12-05 20:27:20 | [diff] [blame] | 288 | protected: |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 289 | friend class base::RefCountedThreadSafe<Context>; |
dcheng | fe61fca | 2014-10-22 02:29:52 | [diff] [blame] | 290 | ~Context() override; |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 291 | |
[email protected] | 57319ce | 2012-06-11 22:35:26 | [diff] [blame] | 292 | // IPC::Listener methods: |
dcheng | fe61fca | 2014-10-22 02:29:52 | [diff] [blame] | 293 | bool OnMessageReceived(const Message& message) override; |
tfarina | 10a5c06 | 2015-09-04 18:47:57 | [diff] [blame] | 294 | void OnChannelConnected(int32_t peer_pid) override; |
dcheng | fe61fca | 2014-10-22 02:29:52 | [diff] [blame] | 295 | void OnChannelError() override; |
rockot | f62002a | 2016-09-15 00:08:59 | [diff] [blame] | 296 | void OnAssociatedInterfaceRequest( |
| 297 | const std::string& interface_name, |
| 298 | mojo::ScopedInterfaceEndpointHandle handle) override; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 299 | |
[email protected] | 3cdb7af81 | 2008-10-24 19:21:13 | [diff] [blame] | 300 | // Like OnMessageReceived but doesn't try the filters. |
[email protected] | a95986a8 | 2010-12-24 06:19:28 | [diff] [blame] | 301 | bool OnMessageReceivedNoFilter(const Message& message); |
[email protected] | 3cdb7af81 | 2008-10-24 19:21:13 | [diff] [blame] | 302 | |
[email protected] | d65cab7a | 2008-08-12 01:25:41 | [diff] [blame] | 303 | // Gives the filters a chance at processing |message|. |
| 304 | // Returns true if the message was processed, false otherwise. |
| 305 | bool TryFilters(const Message& message); |
| 306 | |
rockot | 1018875 | 2016-09-08 18:24:56 | [diff] [blame] | 307 | void PauseChannel(); |
rockot | 401fb2c | 2016-09-06 18:35:57 | [diff] [blame] | 308 | void UnpauseChannel(bool flush); |
| 309 | void FlushChannel(); |
| 310 | |
[email protected] | 3cdb7af81 | 2008-10-24 19:21:13 | [diff] [blame] | 311 | // Like Open and Close, but called on the IPC thread. |
rockot | 1018875 | 2016-09-08 18:24:56 | [diff] [blame] | 312 | virtual void OnChannelOpened(); |
[email protected] | 3cdb7af81 | 2008-10-24 19:21:13 | [diff] [blame] | 313 | virtual void OnChannelClosed(); |
| 314 | |
| 315 | // Called on the consumers thread when the ChannelProxy is closed. At that |
| 316 | // point the consumer is telling us that they don't want to receive any |
| 317 | // more messages, so we honor that wish by forgetting them! |
[email protected] | 772a5b2 | 2012-08-09 20:39:12 | [diff] [blame] | 318 | virtual void Clear(); |
[email protected] | 3cdb7af81 | 2008-10-24 19:21:13 | [diff] [blame] | 319 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 320 | private: |
| 321 | friend class ChannelProxy; |
nick | 4c8dfd4 | 2014-11-14 04:11:49 | [diff] [blame] | 322 | friend class IpcSecurityTestUtil; |
[email protected] | 877d55d | 2009-11-05 21:53:08 | [diff] [blame] | 323 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 324 | // Create the Channel |
danakj | 03de39b2 | 2016-04-23 04:21:09 | [diff] [blame] | 325 | void CreateChannel(std::unique_ptr<ChannelFactory> factory); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 326 | |
[email protected] | 4b580bf | 2010-12-02 19:16:07 | [diff] [blame] | 327 | // Methods called on the IO thread. |
Etienne Bergeron | 0a07d73d | 2019-06-27 16:40:47 | [diff] [blame] | 328 | void OnSendMessage(std::unique_ptr<Message> message_ptr); |
[email protected] | 4b580bf | 2010-12-02 19:16:07 | [diff] [blame] | 329 | void OnAddFilter(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 330 | void OnRemoveFilter(MessageFilter* filter); |
[email protected] | 4b580bf | 2010-12-02 19:16:07 | [diff] [blame] | 331 | |
| 332 | // Methods called on the listener thread. |
| 333 | void AddFilter(MessageFilter* filter); |
[email protected] | 827ab81 | 2009-03-12 07:17:17 | [diff] [blame] | 334 | void OnDispatchConnected(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 335 | void OnDispatchError(); |
[email protected] | ef2f6ba | 2014-05-15 23:06:07 | [diff] [blame] | 336 | void OnDispatchBadMessage(const Message& message); |
rockot | f62002a | 2016-09-15 00:08:59 | [diff] [blame] | 337 | void OnDispatchAssociatedInterfaceRequest( |
| 338 | const std::string& interface_name, |
| 339 | mojo::ScopedInterfaceEndpointHandle handle); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 340 | |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 341 | void ClearChannel(); |
| 342 | |
rockot | a628d0b | 2017-02-09 08:40:15 | [diff] [blame] | 343 | mojom::Channel& thread_safe_channel() { |
| 344 | return thread_safe_channel_->proxy(); |
| 345 | } |
rockot | 0e4de5f | 2016-07-22 21:18:07 | [diff] [blame] | 346 | |
rockot | 0e4de5f | 2016-07-22 21:18:07 | [diff] [blame] | 347 | void AddGenericAssociatedInterfaceForIOThread( |
| 348 | const std::string& name, |
| 349 | const GenericAssociatedInterfaceFactory& factory); |
| 350 | |
Yuzu Saijo | 8866b1d | 2019-05-24 03:23:28 | [diff] [blame] | 351 | base::Lock listener_thread_task_runners_lock_; |
| 352 | // Map of routing_id and listener's thread task runner. |
| 353 | std::map<int32_t, scoped_refptr<base::SingleThreadTaskRunner>> |
| 354 | listener_thread_task_runners_ |
| 355 | GUARDED_BY(listener_thread_task_runners_lock_); |
| 356 | |
| 357 | scoped_refptr<base::SingleThreadTaskRunner> default_listener_task_runner_; |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 358 | raw_ptr<Listener> listener_; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 359 | |
| 360 | // List of filters. This is only accessed on the IPC thread. |
[email protected] | d4651ff | 2008-12-02 16:51:58 | [diff] [blame] | 361 | std::vector<scoped_refptr<MessageFilter> > filters_; |
[email protected] | b243230 | 2012-07-02 21:15:52 | [diff] [blame] | 362 | scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_; |
[email protected] | 7e3d752 | 2014-03-20 21:00:50 | [diff] [blame] | 363 | |
| 364 | // Note, channel_ may be set on the Listener thread or the IPC thread. |
| 365 | // But once it has been set, it must only be read or cleared on the IPC |
| 366 | // thread. |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 367 | // One exception is the thread-safe send. See the class comment. |
danakj | 03de39b2 | 2016-04-23 04:21:09 | [diff] [blame] | 368 | std::unique_ptr<Channel> channel_; |
[email protected] | 827ab81 | 2009-03-12 07:17:17 | [diff] [blame] | 369 | bool channel_connected_called_; |
[email protected] | 4b580bf | 2010-12-02 19:16:07 | [diff] [blame] | 370 | |
Sigurdur Asgeirsson | d655dd65f | 2019-11-12 19:32:20 | [diff] [blame] | 371 | // The quota checker associated with this channel, if any. |
| 372 | scoped_refptr<mojo::internal::MessageQuotaChecker> quota_checker_; |
| 373 | |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 374 | // Lock for |channel_| value. This is only relevant in the context of |
| 375 | // thread-safe send. |
| 376 | base::Lock channel_lifetime_lock_; |
morrita | b447214 | 2015-04-20 21:20:12 | [diff] [blame] | 377 | |
[email protected] | b51352a | 2014-02-26 05:18:04 | [diff] [blame] | 378 | // Routes a given message to a proper subset of |filters_|, depending |
| 379 | // on which message classes a filter might support. |
danakj | 03de39b2 | 2016-04-23 04:21:09 | [diff] [blame] | 380 | std::unique_ptr<MessageFilterRouter> message_filter_router_; |
[email protected] | b51352a | 2014-02-26 05:18:04 | [diff] [blame] | 381 | |
[email protected] | 4b580bf | 2010-12-02 19:16:07 | [diff] [blame] | 382 | // Holds filters between the AddFilter call on the listerner thread and the |
| 383 | // IPC thread when they're added to filters_. |
| 384 | std::vector<scoped_refptr<MessageFilter> > pending_filters_; |
| 385 | // Lock for pending_filters_. |
[email protected] | 20305ec | 2011-01-21 04:55:52 | [diff] [blame] | 386 | base::Lock pending_filters_lock_; |
[email protected] | 0a6fc4b | 2012-04-05 02:38:34 | [diff] [blame] | 387 | |
| 388 | // Cached copy of the peer process ID. Set on IPC but read on both IPC and |
| 389 | // listener threads. |
| 390 | base::ProcessId peer_pid_; |
amistry | 78ef5f1b | 2016-07-19 02:52:31 | [diff] [blame] | 391 | base::Lock peer_pid_lock_; |
erikchen | bcc7961 | 2015-07-31 00:04:42 | [diff] [blame] | 392 | |
rockot | a628d0b | 2017-02-09 08:40:15 | [diff] [blame] | 393 | // A thread-safe mojom::Channel interface we use to make remote interface |
| 394 | // requests from the proxy thread. |
| 395 | std::unique_ptr<mojo::ThreadSafeForwarder<mojom::Channel>> |
| 396 | thread_safe_channel_; |
| 397 | |
rockot | 70bbb5949 | 2017-01-25 00:56:51 | [diff] [blame] | 398 | // Holds associated interface binders added by |
| 399 | // AddGenericAssociatedInterfaceForIOThread until the underlying channel has |
| 400 | // been initialized. |
| 401 | base::Lock pending_io_thread_interfaces_lock_; |
rockot | 0e4de5f | 2016-07-22 21:18:07 | [diff] [blame] | 402 | std::vector<std::pair<std::string, GenericAssociatedInterfaceFactory>> |
rockot | 70bbb5949 | 2017-01-25 00:56:51 | [diff] [blame] | 403 | pending_io_thread_interfaces_; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 404 | }; |
| 405 | |
[email protected] | 1757164 | 2013-06-01 04:11:27 | [diff] [blame] | 406 | Context* context() { return context_.get(); } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 407 | |
mbarbella | e97877bc | 2015-03-06 21:51:14 | [diff] [blame] | 408 | #if defined(ENABLE_IPC_FUZZER) |
| 409 | OutgoingMessageFilter* outgoing_message_filter() const { |
| 410 | return outgoing_message_filter_; |
| 411 | } |
| 412 | #endif |
| 413 | |
rockot | 29ade1b | 2015-08-07 06:23:59 | [diff] [blame] | 414 | bool did_init() const { return did_init_; } |
| 415 | |
John Abd-El-Malek | d1d6f6a | 2017-07-18 20:01:00 | [diff] [blame] | 416 | // A Send() which doesn't DCHECK if the message is synchronous. |
Etienne Bergeron | 0a07d73d | 2019-06-27 16:40:47 | [diff] [blame] | 417 | void SendInternal(Message* message); |
John Abd-El-Malek | d1d6f6a | 2017-07-18 20:01:00 | [diff] [blame] | 418 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 419 | private: |
nick | 4c8dfd4 | 2014-11-14 04:11:49 | [diff] [blame] | 420 | friend class IpcSecurityTestUtil; |
[email protected] | 16395142 | 2009-07-28 22:09:45 | [diff] [blame] | 421 | |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 422 | template <typename Interface> |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 423 | static void BindPendingAssociatedReceiver( |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 424 | const AssociatedInterfaceFactory<Interface>& factory, |
| 425 | mojo::ScopedInterfaceEndpointHandle handle) { |
Julie Jeongeun Kim | a6c8e67 | 2019-12-07 03:27:05 | [diff] [blame] | 426 | factory.Run(mojo::PendingAssociatedReceiver<Interface>(std::move(handle))); |
rockot | 8d890f6 | 2016-07-14 16:37:14 | [diff] [blame] | 427 | } |
| 428 | |
rockot | 29ade1b | 2015-08-07 06:23:59 | [diff] [blame] | 429 | // Always called once immediately after Init. |
| 430 | virtual void OnChannelInit(); |
| 431 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 432 | // By maintaining this indirection (ref-counted) to our internal state, we |
| 433 | // can safely be destroyed while the background thread continues to do stuff |
| 434 | // that involves this data. |
| 435 | scoped_refptr<Context> context_; |
[email protected] | 8948031 | 2011-05-04 17:14:16 | [diff] [blame] | 436 | |
[email protected] | 952394af | 2011-11-16 01:06:46 | [diff] [blame] | 437 | // Whether the channel has been initialized. |
| 438 | bool did_init_; |
mbarbella | e97877bc | 2015-03-06 21:51:14 | [diff] [blame] | 439 | |
| 440 | #if defined(ENABLE_IPC_FUZZER) |
| 441 | OutgoingMessageFilter* outgoing_message_filter_; |
| 442 | #endif |
gab | 21edbfa | 2017-05-31 16:49:12 | [diff] [blame] | 443 | |
| 444 | SEQUENCE_CHECKER(sequence_checker_); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 445 | }; |
| 446 | |
| 447 | } // namespace IPC |
| 448 | |
[email protected] | 92bf906 | 2011-05-02 18:00:49 | [diff] [blame] | 449 | #endif // IPC_IPC_CHANNEL_PROXY_H_ |