Home | History | Annotate | Download | only in bindings
      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 MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
      7 
      8 #include <memory>
      9 #include <string>
     10 #include <utility>
     11 
     12 #include "base/bind.h"
     13 #include "base/callback.h"
     14 #include "base/logging.h"
     15 #include "base/macros.h"
     16 #include "base/memory/ptr_util.h"
     17 #include "base/memory/ref_counted.h"
     18 #include "base/single_thread_task_runner.h"
     19 #include "base/threading/thread_task_runner_handle.h"
     20 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
     21 #include "mojo/public/cpp/bindings/associated_interface_request.h"
     22 #include "mojo/public/cpp/bindings/bindings_export.h"
     23 #include "mojo/public/cpp/bindings/connection_error_callback.h"
     24 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
     25 #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
     26 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
     27 
     28 namespace mojo {
     29 
     30 class MessageReceiver;
     31 
     32 // Base class used to factor out code in AssociatedBinding<T> expansions, in
     33 // particular for Bind().
     34 class MOJO_CPP_BINDINGS_EXPORT AssociatedBindingBase {
     35  public:
     36   AssociatedBindingBase();
     37   ~AssociatedBindingBase();
     38 
     39   // Adds a message filter to be notified of each incoming message before
     40   // dispatch. If a filter returns |false| from Accept(), the message is not
     41   // dispatched and the pipe is closed. Filters cannot be removed.
     42   void AddFilter(std::unique_ptr<MessageReceiver> filter);
     43 
     44   // Closes the associated interface. Puts this object into a state where it can
     45   // be rebound.
     46   void Close();
     47 
     48   // Similar to the method above, but also specifies a disconnect reason.
     49   void CloseWithReason(uint32_t custom_reason, const std::string& description);
     50 
     51   // Sets an error handler that will be called if a connection error occurs.
     52   //
     53   // This method may only be called after this AssociatedBinding has been bound
     54   // to a message pipe. The error handler will be reset when this
     55   // AssociatedBinding is unbound or closed.
     56   void set_connection_error_handler(const base::Closure& error_handler);
     57 
     58   void set_connection_error_with_reason_handler(
     59       const ConnectionErrorWithReasonCallback& error_handler);
     60 
     61   // Indicates whether the associated binding has been completed.
     62   bool is_bound() const { return !!endpoint_client_; }
     63 
     64   // Sends a message on the underlying message pipe and runs the current
     65   // message loop until its response is received. This can be used in tests to
     66   // verify that no message was sent on a message pipe in response to some
     67   // stimulus.
     68   void FlushForTesting();
     69 
     70  protected:
     71   void BindImpl(ScopedInterfaceEndpointHandle handle,
     72                 MessageReceiverWithResponderStatus* receiver,
     73                 std::unique_ptr<MessageReceiver> payload_validator,
     74                 bool expect_sync_requests,
     75                 scoped_refptr<base::SingleThreadTaskRunner> runner,
     76                 uint32_t interface_version);
     77 
     78   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
     79 };
     80 
     81 // Represents the implementation side of an associated interface. It is similar
     82 // to Binding, except that it doesn't own a message pipe handle.
     83 //
     84 // When you bind this class to a request, optionally you can specify a
     85 // base::SingleThreadTaskRunner. This task runner must belong to the same
     86 // thread. It will be used to dispatch incoming method calls and connection
     87 // error notification. It is useful when you attach multiple task runners to a
     88 // single thread for the purposes of task scheduling. Please note that incoming
     89 // synchrounous method calls may not be run from this task runner, when they
     90 // reenter outgoing synchrounous calls on the same thread.
     91 template <typename Interface,
     92           typename ImplRefTraits = RawPtrImplRefTraits<Interface>>
     93 class AssociatedBinding : public AssociatedBindingBase {
     94  public:
     95   using ImplPointerType = typename ImplRefTraits::PointerType;
     96 
     97   // Constructs an incomplete associated binding that will use the
     98   // implementation |impl|. It may be completed with a subsequent call to the
     99   // |Bind| method. Does not take ownership of |impl|, which must outlive this
    100   // object.
    101   explicit AssociatedBinding(ImplPointerType impl) { stub_.set_sink(impl); }
    102 
    103   // Constructs a completed associated binding of |impl|. The output |ptr_info|
    104   // should be sent by another interface. |impl| must outlive this object.
    105   AssociatedBinding(ImplPointerType impl,
    106                     AssociatedInterfacePtrInfo<Interface>* ptr_info,
    107                     scoped_refptr<base::SingleThreadTaskRunner> runner =
    108                         base::ThreadTaskRunnerHandle::Get())
    109       : AssociatedBinding(std::move(impl)) {
    110     Bind(ptr_info, std::move(runner));
    111   }
    112 
    113   // Constructs a completed associated binding of |impl|. |impl| must outlive
    114   // the binding.
    115   AssociatedBinding(ImplPointerType impl,
    116                     AssociatedInterfaceRequest<Interface> request,
    117                     scoped_refptr<base::SingleThreadTaskRunner> runner =
    118                         base::ThreadTaskRunnerHandle::Get())
    119       : AssociatedBinding(std::move(impl)) {
    120     Bind(std::move(request), std::move(runner));
    121   }
    122 
    123   ~AssociatedBinding() {}
    124 
    125   // Creates an associated inteface and sets up this object as the
    126   // implementation side. The output |ptr_info| should be sent by another
    127   // interface.
    128   void Bind(AssociatedInterfacePtrInfo<Interface>* ptr_info,
    129             scoped_refptr<base::SingleThreadTaskRunner> runner =
    130                 base::ThreadTaskRunnerHandle::Get()) {
    131     auto request = MakeRequest(ptr_info);
    132     ptr_info->set_version(Interface::Version_);
    133     Bind(std::move(request), std::move(runner));
    134   }
    135 
    136   // Sets up this object as the implementation side of an associated interface.
    137   void Bind(AssociatedInterfaceRequest<Interface> request,
    138             scoped_refptr<base::SingleThreadTaskRunner> runner =
    139                 base::ThreadTaskRunnerHandle::Get()) {
    140     BindImpl(request.PassHandle(), &stub_,
    141              base::WrapUnique(new typename Interface::RequestValidator_()),
    142              Interface::HasSyncMethods_, std::move(runner),
    143              Interface::Version_);
    144   }
    145 
    146   // Unbinds and returns the associated interface request so it can be
    147   // used in another context, such as on another thread or with a different
    148   // implementation. Puts this object into a state where it can be rebound.
    149   AssociatedInterfaceRequest<Interface> Unbind() {
    150     DCHECK(endpoint_client_);
    151 
    152     AssociatedInterfaceRequest<Interface> request;
    153     request.Bind(endpoint_client_->PassHandle());
    154 
    155     endpoint_client_.reset();
    156 
    157     return request;
    158   }
    159 
    160   // Returns the interface implementation that was previously specified.
    161   Interface* impl() { return ImplRefTraits::GetRawPointer(&stub_.sink()); }
    162 
    163  private:
    164   typename Interface::template Stub_<ImplRefTraits> stub_;
    165 
    166   DISALLOW_COPY_AND_ASSIGN(AssociatedBinding);
    167 };
    168 
    169 }  // namespace mojo
    170 
    171 #endif  // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_BINDING_H_
    172