1 // Copyright 2019 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_PUBLIC_CPP_BINDINGS_REMOTE_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_REMOTE_H_ 7 8 #include <cstdint> 9 #include <utility> 10 11 #include "base/callback_forward.h" 12 #include "base/compiler_specific.h" 13 #include "base/logging.h" 14 #include "base/macros.h" 15 #include "base/memory/scoped_refptr.h" 16 #include "base/sequenced_task_runner.h" 17 #include "base/time/time.h" 18 #include "mojo/public/cpp/bindings/async_flusher.h" 19 #include "mojo/public/cpp/bindings/interface_ptr_info.h" 20 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h" 21 #include "mojo/public/cpp/bindings/pending_flush.h" 22 #include "mojo/public/cpp/bindings/pending_remote.h" 23 #include "mojo/public/cpp/bindings/receiver.h" 24 #include "mojo/public/cpp/system/message_pipe.h" 25 26 namespace mojo { 27 28 // A Remote is used to issue Interface method calls to a single connected 29 // Receiver or PendingReceiver. The Remote must be bound in order to issue those 30 // method calls, and it becomes bound by consuming a PendingRemote either at 31 // construction time or by calling |Bind()|. 32 // 33 // Remote is NOT thread- or sequence-safe and must be used on a single 34 // (but otherwise arbitrary) sequence. All bound Remote objects are associated 35 // with a base::SequenceTaskRunner which the Remote uses exclusively to schedule 36 // response callbacks and disconnection notifications. 37 // 38 // The most common ways to bind a Remote are to consume a PendingRemote received 39 // via some IPC, or to call |BindNewPipeAndPassReceiver()| and send the returned 40 // PendingReceiver somewhere useful (i.e., to a remote Receiver who will consume 41 // it). For example: 42 // 43 // mojo::Remote<mojom::Widget> widget; 44 // widget_factory->CreateWidget(widget.BindNewPipeAndPassReceiver()); 45 // widget->Click(); 46 // 47 // IMPORTANT: There are some things to be aware of regarding Interface method 48 // calls as they relate to Remote object lifetime: 49 // 50 // - Interface method calls issued immediately before the destruction of a 51 // Remote ARE guaranteed to be transmitted to the remote's receiver as long 52 // as the receiver itself remains alive, either as a Receiver or a 53 // PendingReceiver. 54 // 55 // - In the name of memory safety, Interface method response callbacks (and in 56 // general ANY tasks which can be scheduled by a Remote) will NEVER 57 // be dispatched beyond the lifetime of the Remote object. As such, if 58 // you make a call and you need its reply, you must keep the Remote alive 59 // until the reply is received. 60 template <typename Interface> 61 class Remote { 62 public: 63 using InterfaceType = Interface; 64 using PendingType = PendingRemote<Interface>; 65 66 // Constructs an unbound Remote. This object cannot issue Interface method 67 // calls and does not schedule any tasks. 68 Remote() = default; Remote(Remote && other)69 Remote(Remote&& other) noexcept { *this = std::move(other); } 70 71 // Constructs a new Remote which is bound from |pending_remote| and which 72 // schedules response callbacks and disconnection notifications on the default 73 // SequencedTaskRunner (i.e., base::SequencedTaskRunnerHandle::Get() at 74 // construction time). Remote(PendingRemote<Interface> pending_remote)75 explicit Remote(PendingRemote<Interface> pending_remote) 76 : Remote(std::move(pending_remote), nullptr) {} 77 78 // Constructs a new Remote which is bound from |pending_remote| and which 79 // schedules response callbacks and disconnection notifications on 80 // |task_runner|. |task_runner| must run tasks on the same sequence that owns 81 // this Remote. Remote(PendingRemote<Interface> pending_remote,scoped_refptr<base::SequencedTaskRunner> task_runner)82 Remote(PendingRemote<Interface> pending_remote, 83 scoped_refptr<base::SequencedTaskRunner> task_runner) { 84 Bind(std::move(pending_remote), std::move(task_runner)); 85 } 86 87 ~Remote() = default; 88 89 Remote& operator=(Remote&& other) noexcept { 90 internal_state_.Swap(&other.internal_state_); 91 return *this; 92 } 93 94 // Exposes access to callable Interface methods directed at this Remote's 95 // receiver. Must only be called on a bound Remote. get()96 typename Interface::Proxy_* get() const { 97 DCHECK(is_bound()) 98 << "Cannot issue Interface method calls on an unbound Remote"; 99 return internal_state_.instance(); 100 } 101 102 // Shorthand form of |get()|. See above. 103 typename Interface::Proxy_* operator->() const { return get(); } 104 typename Interface::Proxy_& operator*() const { return *get(); } 105 106 // Indicates whether this Remote is bound and thus can issue Interface method 107 // calls via the above accessors. 108 // 109 // NOTE: The state of being "bound" should not be confused with the state of 110 // being "connected" (see |is_connected()| below). A Remote is NEVER passively 111 // unbound and the only way for it to become unbound is to explicitly call 112 // |reset()| or |Unbind()|. As such, unless you make explicit calls to those 113 // methods, it is always safe to assume that a Remote you've bound will remain 114 // bound and callable. is_bound()115 bool is_bound() const { return internal_state_.is_bound(); } 116 explicit operator bool() const { return is_bound(); } 117 118 // Indicates whether this Remote is connected to a receiver. Must only be 119 // called on a bound Remote. If this returns |true|, method calls made by this 120 // Remote may eventually end up at the connected receiver (though it's of 121 // course possible for this call to race with disconnection). If this returns 122 // |false| however, all future Interface method calls on this Remote will be 123 // silently dropped. 124 // 125 // A bound Remote becomes disconnected automatically either when its receiver 126 // is destroyed, or when it receives a malformed or otherwise unexpected 127 // response message from the receiver. 128 // 129 // NOTE: The state of being "bound" should not be confused with the state of 130 // being "connected". See |is_bound()| above. is_connected()131 bool is_connected() const { 132 DCHECK(is_bound()); 133 return !internal_state_.encountered_error(); 134 } 135 136 // Sets a Closure to be invoked if this Remote is cut off from its receiver. 137 // This can happen if the corresponding Receiver (or unconsumed 138 // PendingReceiver) is destroyed, or if the Receiver sends a malformed or 139 // otherwise unexpected response message to this Remote. Must only be called 140 // on a bound Remote object, and only remains set as long as the Remote is 141 // both bound and connected. 142 // 143 // If invoked at all, |handler| will be scheduled asynchronously using the 144 // Remote's bound SequencedTaskRunner. set_disconnect_handler(base::OnceClosure handler)145 void set_disconnect_handler(base::OnceClosure handler) { 146 if (is_connected()) 147 internal_state_.set_connection_error_handler(std::move(handler)); 148 } 149 150 // Like above but also receives extra user-defined metadata about why the 151 // receiving endpoint was closed. set_disconnect_with_reason_handler(ConnectionErrorWithReasonCallback handler)152 void set_disconnect_with_reason_handler( 153 ConnectionErrorWithReasonCallback handler) { 154 internal_state_.set_connection_error_with_reason_handler( 155 std::move(handler)); 156 } 157 158 // A convenient helper that resets this Remote on disconnect. Note that this 159 // replaces any previously set disconnection handler. reset_on_disconnect()160 void reset_on_disconnect() { 161 if (!is_connected()) { 162 reset(); 163 return; 164 } 165 set_disconnect_handler( 166 base::BindOnce(&Remote::reset, base::Unretained(this))); 167 } 168 169 // Sets a Closure to be invoked if the receiving endpoint reports itself as 170 // idle and there are no in-flight messages it has yet to acknowledge, and 171 // this state occurs continuously for a duration of at least |timeout|. The 172 // first time this is called, it must be called BEFORE sending any interface 173 // messages to the receiver. It may be called any number of times after that 174 // to reconfigure the idle timeout period or assign a new idle handler. 175 // 176 // Once called, the interface connection incurs some permanent additional 177 // per-message overhead to help track idle state across the interface 178 // boundary. 179 // 180 // Whenever this callback is invoked, the following conditions are guaranteed 181 // to hold: 182 // 183 // - There are no messages sent on this Remote that have not already been 184 // dispatched by the receiver. 185 // - The receiver has explicitly notified us that it considers itself to be 186 // "idle." 187 // - The receiver has not dispatched any additional messages since sending 188 // this idle notification 189 // - The Remote does not have any outstanding reply callbacks that haven't 190 // been called yet 191 // - All of the above has been true continuously for a duration of at least 192 // |timeout|. 193 // set_idle_handler(base::TimeDelta timeout,base::RepeatingClosure handler)194 void set_idle_handler(base::TimeDelta timeout, 195 base::RepeatingClosure handler) { 196 internal_state_.set_idle_handler(timeout, std::move(handler)); 197 } 198 199 // A convenient helper for common idle timeout behavior. This is equivalent to 200 // calling |set_idle_handler| with a handler that only resets this Remote. reset_on_idle_timeout(base::TimeDelta timeout)201 void reset_on_idle_timeout(base::TimeDelta timeout) { 202 set_idle_handler( 203 timeout, base::BindRepeating(&Remote::reset, base::Unretained(this))); 204 } 205 206 // Resets this Remote to an unbound state. To reset the Remote and recover an 207 // PendingRemote that can be bound again later, use |Unbind()| instead. reset()208 void reset() { 209 State doomed_state; 210 internal_state_.Swap(&doomed_state); 211 } 212 213 // Similar to the method above, but also specifies a disconnect reason. ResetWithReason(uint32_t custom_reason,const std::string & description)214 void ResetWithReason(uint32_t custom_reason, const std::string& description) { 215 if (internal_state_.is_bound()) 216 internal_state_.CloseWithReason(custom_reason, description); 217 reset(); 218 } 219 220 // Returns the version of Interface used by this Remote. Defaults to 0 but can 221 // be adjusted either at binding time, or by invoking either |QueryVersion()| 222 // or |RequireVersion()|. version()223 uint32_t version() const { return internal_state_.version(); } 224 225 // Binds this Remote, connecting it to a new PendingReceiver which is 226 // returned for transmission to some Receiver which can bind it. The Remote 227 // will schedule any response callbacks or disconnection notifications on the 228 // default SequencedTaskRunner (i.e. base::SequencedTaskRunnerHandle::Get() at 229 // the time of this call). Must only be called on an unbound Remote. BindNewPipeAndPassReceiver()230 PendingReceiver<Interface> BindNewPipeAndPassReceiver() WARN_UNUSED_RESULT { 231 return BindNewPipeAndPassReceiver(nullptr); 232 } 233 234 // Like above, but the Remote will schedule response callbacks and 235 // disconnection notifications on |task_runner| instead of the default 236 // SequencedTaskRunner. |task_runner| must run tasks on the same sequence that 237 // owns this Remote. BindNewPipeAndPassReceiver(scoped_refptr<base::SequencedTaskRunner> task_runner)238 PendingReceiver<Interface> BindNewPipeAndPassReceiver( 239 scoped_refptr<base::SequencedTaskRunner> task_runner) WARN_UNUSED_RESULT { 240 MessagePipe pipe; 241 Bind(PendingRemote<Interface>(std::move(pipe.handle0), 0), 242 std::move(task_runner)); 243 return PendingReceiver<Interface>(std::move(pipe.handle1)); 244 } 245 246 // Binds this Remote by consuming |pending_remote|, which must be valid. The 247 // Remote will schedule any response callbacks or disconnection notifications 248 // on the default SequencedTaskRunner (i.e. 249 // base::SequencedTaskRunnerHandle::Get() at the time of this call). Must only 250 // be called on an unbound Remote. Bind(PendingRemote<Interface> pending_remote)251 void Bind(PendingRemote<Interface> pending_remote) { 252 DCHECK(pending_remote.is_valid()); 253 Bind(std::move(pending_remote), nullptr); 254 } 255 256 // Like above, but the Remote will schedule response callbacks and 257 // disconnection notifications on |task_runner| instead of the default 258 // SequencedTaskRunner. Must only be called on an unbound Remote. 259 // |task_runner| must run tasks on the same sequence that owns this Remote. Bind(PendingRemote<Interface> pending_remote,scoped_refptr<base::SequencedTaskRunner> task_runner)260 void Bind(PendingRemote<Interface> pending_remote, 261 scoped_refptr<base::SequencedTaskRunner> task_runner) { 262 DCHECK(!is_bound()) << "Remote is already bound"; 263 if (!pending_remote) { 264 reset(); 265 return; 266 } 267 268 internal_state_.Bind(pending_remote.internal_state(), 269 std::move(task_runner)); 270 271 // Force the internal state to configure its proxy. Unlike InterfacePtr we 272 // do not use Remote in transit, so binding to a pipe handle can also imply 273 // binding to a SequencedTaskRunner and observing pipe handle state. This 274 // allows for e.g. |is_connected()| to be a more reliable API than 275 // |InterfacePtr::encountered_error()|. 276 ignore_result(internal_state_.instance()); 277 } 278 279 // Unbinds this Remote, rendering it unable to issue further Interface method 280 // calls. Returns a PendingRemote which may be passed across threads or 281 // processes and consumed by another Remote elsewhere. 282 // 283 // Note that it is an error (the bad, crashy kind of error) to attempt to 284 // |Unbind()| a Remote which is awaiting one or more responses to previously 285 // issued Interface method calls. Calling this method should only be 286 // considered in cases where satisfaction of that constraint can be proven. 287 // 288 // Must only be called on a bound Remote. Unbind()289 PendingRemote<Interface> Unbind() WARN_UNUSED_RESULT { 290 DCHECK(is_bound()); 291 CHECK(!internal_state_.has_pending_callbacks()); 292 State state; 293 internal_state_.Swap(&state); 294 InterfacePtrInfo<Interface> info = state.PassInterface(); 295 return PendingRemote<Interface>(info.PassHandle(), info.version()); 296 } 297 298 // Queries the max version that the receiving endpoint supports. Once a 299 // response is received, |callback| will be invoked with the version number 300 // and the version number of this Remote object will also be updated. QueryVersion(base::OnceCallback<void (uint32_t)> callback)301 void QueryVersion(base::OnceCallback<void(uint32_t)> callback) { 302 internal_state_.QueryVersion(std::move(callback)); 303 } 304 305 // Requires the receiving endpoint to support at least the specified 306 // |version|. If it does not, it will close its end of the connection 307 // immediately. RequireVersion(uint32_t version)308 void RequireVersion(uint32_t version) { 309 internal_state_.RequireVersion(version); 310 } 311 312 // Pauses the receiving endpoint until the flush corresponding to |flush| has 313 // completed. Any calls made on this Remote prior to this call will be 314 // dispatched at the receiving endpoint before pausing. The endpoint will not 315 // dispatch any subsequent calls until the flush operation corresponding to 316 // |flush| has been completed or canceled. 317 // 318 // See documentation for |FlushAsync()| on Remote and Receiver for how to 319 // acquire a PendingFlush object, and documentation on PendingFlush for 320 // example usage. PauseReceiverUntilFlushCompletes(PendingFlush flush)321 void PauseReceiverUntilFlushCompletes(PendingFlush flush) { 322 internal_state_.PauseReceiverUntilFlushCompletes(std::move(flush)); 323 } 324 325 // Flushes the receiving endpoint asynchronously using |flusher|. Once all 326 // calls made on this Remote prior to this |FlushAsyncWithFlusher()| call have 327 // dispatched at the receiving endpoint, |flusher| will signal its 328 // corresponding PendingFlush, unblocking any endpoint waiting on the flush 329 // operation. 330 // 331 // NOTE: It is more common to use |FlushAsync()| defined below. If you really 332 // want to provide your own AsyncFlusher using this method, see the 333 // single-arugment constructor on PendingFlush. This would typically be used 334 // when code executing on the current sequence wishes to immediately pause 335 // one of its remote endpoints to wait on a flush operation that needs to be 336 // initiated on a separate sequence. Rather than bouncing to the second 337 // sequence to initiate a flush and then passing a PendingFlush back to the 338 // original sequence, the AsyncFlusher/PendingFlush can be created on the 339 // original sequence and a single task can be posted to pass the AsyncFlusher 340 // to the second sequence for use with this method. FlushAsyncWithFlusher(AsyncFlusher flusher)341 void FlushAsyncWithFlusher(AsyncFlusher flusher) { 342 internal_state_.FlushAsync(std::move(flusher)); 343 } 344 345 // Same as above but an AsyncFlusher/PendingFlush pair is created on the 346 // caller's behalf. The AsyncFlusher is immediately passed to a 347 // |FlushAsyncWithFlusher()| call on this object, while the PendingFlush is 348 // returned for use by the caller. See documentation on PendingFlush for 349 // example usage. FlushAsync()350 PendingFlush FlushAsync() { 351 AsyncFlusher flusher; 352 PendingFlush flush(&flusher); 353 FlushAsyncWithFlusher(std::move(flusher)); 354 return flush; 355 } 356 357 // Sends a no-op message on the underlying message pipe and runs the current 358 // message loop until its response is received. This can be used in tests to 359 // verify that no message was sent on a message pipe in response to some 360 // stimulus. FlushForTesting()361 void FlushForTesting() { internal_state_.FlushForTesting(); } 362 363 // Same as |FlushForTesting()| but will call |callback| when the flush is 364 // complete. FlushAsyncForTesting(base::OnceClosure callback)365 void FlushAsyncForTesting(base::OnceClosure callback) { 366 internal_state_.FlushAsyncForTesting(std::move(callback)); 367 } 368 369 // Returns the number of unacknowledged messages sent by this Remote. Only 370 // non-zero when |set_idle_handler()| has been called. GetNumUnackedMessagesForTesting()371 unsigned int GetNumUnackedMessagesForTesting() const { 372 return internal_state_.GetNumUnackedMessagesForTesting(); 373 } 374 375 // DO NOT USE. Exposed only for internal use and for testing. internal_state()376 internal::InterfacePtrState<Interface>* internal_state() { 377 return &internal_state_; 378 } 379 380 private: 381 using State = internal::InterfacePtrState<Interface>; 382 mutable State internal_state_; 383 384 DISALLOW_COPY_AND_ASSIGN(Remote); 385 }; 386 387 } // namespace mojo 388 389 #endif // MOJO_PUBLIC_CPP_BINDINGS_REMOTE_H_ 390