Home | History | Annotate | Download | only in lib
      1 // Copyright 2014 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_LIB_INTERFACE_PTR_STATE_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include <algorithm>  // For |std::swap()|.
     11 #include <memory>
     12 #include <string>
     13 #include <utility>
     14 
     15 #include "base/bind.h"
     16 #include "base/callback_forward.h"
     17 #include "base/logging.h"
     18 #include "base/macros.h"
     19 #include "base/memory/ptr_util.h"
     20 #include "base/memory/ref_counted.h"
     21 #include "base/sequenced_task_runner.h"
     22 #include "mojo/public/cpp/bindings/associated_group.h"
     23 #include "mojo/public/cpp/bindings/bindings_export.h"
     24 #include "mojo/public/cpp/bindings/connection_error_callback.h"
     25 #include "mojo/public/cpp/bindings/filter_chain.h"
     26 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
     27 #include "mojo/public/cpp/bindings/interface_id.h"
     28 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
     29 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
     30 #include "mojo/public/cpp/bindings/message_header_validator.h"
     31 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
     32 
     33 namespace mojo {
     34 namespace internal {
     35 
     36 class MOJO_CPP_BINDINGS_EXPORT InterfacePtrStateBase {
     37  public:
     38   InterfacePtrStateBase();
     39   ~InterfacePtrStateBase();
     40 
     41   MessagePipeHandle handle() const {
     42     return router_ ? router_->handle() : handle_.get();
     43   }
     44 
     45   uint32_t version() const { return version_; }
     46 
     47   bool is_bound() const { return handle_.is_valid() || endpoint_client_; }
     48 
     49   bool encountered_error() const {
     50     return endpoint_client_ ? endpoint_client_->encountered_error() : false;
     51   }
     52 
     53   bool HasAssociatedInterfaces() const {
     54     return router_ ? router_->HasAssociatedEndpoints() : false;
     55   }
     56 
     57   // Returns true if bound and awaiting a response to a message.
     58   bool has_pending_callbacks() const {
     59     return endpoint_client_ && endpoint_client_->has_pending_responders();
     60   }
     61 
     62  protected:
     63   InterfaceEndpointClient* endpoint_client() const {
     64     return endpoint_client_.get();
     65   }
     66   MultiplexRouter* router() const { return router_.get(); }
     67 
     68   void QueryVersion(const base::Callback<void(uint32_t)>& callback);
     69   void RequireVersion(uint32_t version);
     70   void Swap(InterfacePtrStateBase* other);
     71   void Bind(ScopedMessagePipeHandle handle,
     72             uint32_t version,
     73             scoped_refptr<base::SequencedTaskRunner> task_runner);
     74 
     75   ScopedMessagePipeHandle PassMessagePipe() {
     76     endpoint_client_.reset();
     77     return router_ ? router_->PassMessagePipe() : std::move(handle_);
     78   }
     79 
     80   bool InitializeEndpointClient(
     81       bool passes_associated_kinds,
     82       bool has_sync_methods,
     83       std::unique_ptr<MessageReceiver> payload_validator);
     84 
     85  private:
     86   void OnQueryVersion(const base::Callback<void(uint32_t)>& callback,
     87                       uint32_t version);
     88 
     89   scoped_refptr<MultiplexRouter> router_;
     90 
     91   std::unique_ptr<InterfaceEndpointClient> endpoint_client_;
     92 
     93   // |router_| (as well as other members above) is not initialized until
     94   // read/write with the message pipe handle is needed. |handle_| is valid
     95   // between the Bind() call and the initialization of |router_|.
     96   ScopedMessagePipeHandle handle_;
     97   scoped_refptr<base::SequencedTaskRunner> runner_;
     98 
     99   uint32_t version_ = 0;
    100 
    101   DISALLOW_COPY_AND_ASSIGN(InterfacePtrStateBase);
    102 };
    103 
    104 template <typename Interface>
    105 class InterfacePtrState : public InterfacePtrStateBase {
    106  public:
    107   using Proxy = typename Interface::Proxy_;
    108 
    109   InterfacePtrState() = default;
    110   ~InterfacePtrState() = default;
    111 
    112   Proxy* instance() {
    113     ConfigureProxyIfNecessary();
    114 
    115     // This will be null if the object is not bound.
    116     return proxy_.get();
    117   }
    118 
    119   void QueryVersion(const base::Callback<void(uint32_t)>& callback) {
    120     ConfigureProxyIfNecessary();
    121     InterfacePtrStateBase::QueryVersion(callback);
    122   }
    123 
    124   void RequireVersion(uint32_t version) {
    125     ConfigureProxyIfNecessary();
    126     InterfacePtrStateBase::RequireVersion(version);
    127   }
    128 
    129   void FlushForTesting() {
    130     ConfigureProxyIfNecessary();
    131     endpoint_client()->FlushForTesting();
    132   }
    133 
    134   void CloseWithReason(uint32_t custom_reason, const std::string& description) {
    135     ConfigureProxyIfNecessary();
    136     endpoint_client()->CloseWithReason(custom_reason, description);
    137   }
    138 
    139   void Swap(InterfacePtrState* other) {
    140     using std::swap;
    141     swap(other->proxy_, proxy_);
    142     InterfacePtrStateBase::Swap(other);
    143   }
    144 
    145   void Bind(InterfacePtrInfo<Interface> info,
    146             scoped_refptr<base::SequencedTaskRunner> runner) {
    147     DCHECK(!proxy_);
    148     InterfacePtrStateBase::Bind(info.PassHandle(), info.version(),
    149                                 std::move(runner));
    150   }
    151 
    152   // After this method is called, the object is in an invalid state and
    153   // shouldn't be reused.
    154   InterfacePtrInfo<Interface> PassInterface() {
    155     proxy_.reset();
    156     return InterfacePtrInfo<Interface>(PassMessagePipe(), version());
    157   }
    158 
    159   void set_connection_error_handler(base::OnceClosure error_handler) {
    160     ConfigureProxyIfNecessary();
    161 
    162     DCHECK(endpoint_client());
    163     endpoint_client()->set_connection_error_handler(std::move(error_handler));
    164   }
    165 
    166   void set_connection_error_with_reason_handler(
    167       ConnectionErrorWithReasonCallback error_handler) {
    168     ConfigureProxyIfNecessary();
    169 
    170     DCHECK(endpoint_client());
    171     endpoint_client()->set_connection_error_with_reason_handler(
    172         std::move(error_handler));
    173   }
    174 
    175   AssociatedGroup* associated_group() {
    176     ConfigureProxyIfNecessary();
    177     return endpoint_client()->associated_group();
    178   }
    179 
    180   void EnableTestingMode() {
    181     ConfigureProxyIfNecessary();
    182     router()->EnableTestingMode();
    183   }
    184 
    185   void ForwardMessage(Message message) {
    186     ConfigureProxyIfNecessary();
    187     endpoint_client()->Accept(&message);
    188   }
    189 
    190   void ForwardMessageWithResponder(Message message,
    191                                    std::unique_ptr<MessageReceiver> responder) {
    192     ConfigureProxyIfNecessary();
    193     endpoint_client()->AcceptWithResponder(&message, std::move(responder));
    194   }
    195 
    196   void RaiseError() {
    197     ConfigureProxyIfNecessary();
    198     endpoint_client()->RaiseError();
    199   }
    200 
    201  private:
    202   void ConfigureProxyIfNecessary() {
    203     // The proxy has been configured.
    204     if (proxy_) {
    205       DCHECK(router());
    206       DCHECK(endpoint_client());
    207       return;
    208     }
    209 
    210     if (InitializeEndpointClient(
    211             Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_,
    212             std::make_unique<typename Interface::ResponseValidator_>())) {
    213       router()->SetMasterInterfaceName(Interface::Name_);
    214       proxy_ = std::make_unique<Proxy>(endpoint_client());
    215     }
    216   }
    217 
    218   std::unique_ptr<Proxy> proxy_;
    219 
    220   DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
    221 };
    222 
    223 }  // namespace internal
    224 }  // namespace mojo
    225 
    226 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_STATE_H_
    227