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