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_INTERNAL_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
      7 
      8 #include <algorithm>  // For |std::swap()|.
      9 
     10 #include "mojo/public/cpp/bindings/lib/filter_chain.h"
     11 #include "mojo/public/cpp/bindings/lib/message_header_validator.h"
     12 #include "mojo/public/cpp/bindings/lib/router.h"
     13 #include "mojo/public/cpp/environment/logging.h"
     14 
     15 struct MojoAsyncWaiter;
     16 
     17 namespace mojo {
     18 namespace internal {
     19 
     20 template <typename Interface>
     21 class InterfacePtrState {
     22  public:
     23   InterfacePtrState() : proxy_(NULL), router_(NULL), waiter_(NULL) {}
     24 
     25   ~InterfacePtrState() {
     26     // Destruction order matters here. We delete |proxy_| first, even though
     27     // |router_| may have a reference to it, so that |~Interface| may have a
     28     // shot at generating new outbound messages (ie, invoking client methods).
     29     delete proxy_;
     30     delete router_;
     31   }
     32 
     33   Interface* instance() {
     34     ConfigureProxyIfNecessary();
     35 
     36     // This will be NULL if the object is not bound.
     37     return proxy_;
     38   }
     39 
     40   void Swap(InterfacePtrState* other) {
     41     std::swap(other->proxy_, proxy_);
     42     std::swap(other->router_, router_);
     43     handle_.swap(other->handle_);
     44     std::swap(other->waiter_, waiter_);
     45   }
     46 
     47   void Bind(ScopedMessagePipeHandle handle, const MojoAsyncWaiter* waiter) {
     48     MOJO_DCHECK(!proxy_);
     49     MOJO_DCHECK(!router_);
     50     MOJO_DCHECK(!handle_.is_valid());
     51     MOJO_DCHECK(!waiter_);
     52 
     53     handle_ = handle.Pass();
     54     waiter_ = waiter;
     55   }
     56 
     57   bool WaitForIncomingMethodCall() {
     58     ConfigureProxyIfNecessary();
     59 
     60     MOJO_DCHECK(router_);
     61     return router_->WaitForIncomingMessage();
     62   }
     63 
     64   ScopedMessagePipeHandle PassMessagePipe() {
     65     if (router_)
     66       return router_->PassMessagePipe();
     67 
     68     waiter_ = NULL;
     69     return handle_.Pass();
     70   }
     71 
     72   bool is_bound() const {
     73     return handle_.is_valid() || router_;
     74   }
     75 
     76   void set_client(typename Interface::Client* client) {
     77     ConfigureProxyIfNecessary();
     78 
     79     MOJO_DCHECK(proxy_);
     80     proxy_->stub.set_sink(client);
     81   }
     82 
     83   bool encountered_error() const {
     84     return router_ ? router_->encountered_error() : false;
     85   }
     86 
     87   void set_error_handler(ErrorHandler* error_handler) {
     88     ConfigureProxyIfNecessary();
     89 
     90     MOJO_DCHECK(router_);
     91     router_->set_error_handler(error_handler);
     92   }
     93 
     94   Router* router_for_testing() {
     95     ConfigureProxyIfNecessary();
     96     return router_;
     97   }
     98 
     99  private:
    100   class ProxyWithStub : public Interface::Proxy_ {
    101    public:
    102     explicit ProxyWithStub(MessageReceiverWithResponder* receiver)
    103         : Interface::Proxy_(receiver) {
    104     }
    105     typename Interface::Client::Stub_ stub;
    106    private:
    107     MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub);
    108   };
    109 
    110   void ConfigureProxyIfNecessary() {
    111     // The proxy has been configured.
    112     if (proxy_) {
    113       MOJO_DCHECK(router_);
    114       return;
    115     }
    116     // The object hasn't been bound.
    117     if (!waiter_) {
    118       MOJO_DCHECK(!handle_.is_valid());
    119       return;
    120     }
    121 
    122     FilterChain filters;
    123     filters.Append<MessageHeaderValidator>();
    124     filters.Append<typename Interface::Client::RequestValidator_>();
    125     filters.Append<typename Interface::ResponseValidator_>();
    126 
    127     router_ = new Router(handle_.Pass(), filters.Pass(), waiter_);
    128     waiter_ = NULL;
    129 
    130     ProxyWithStub* proxy = new ProxyWithStub(router_);
    131     router_->set_incoming_receiver(&proxy->stub);
    132 
    133     proxy_ = proxy;
    134   }
    135 
    136   ProxyWithStub* proxy_;
    137   Router* router_;
    138 
    139   // |proxy_| and |router_| are not initialized until read/write with the
    140   // message pipe handle is needed. Before that, |handle_| and |waiter_| store
    141   // the arguments of Bind().
    142   ScopedMessagePipeHandle handle_;
    143   const MojoAsyncWaiter* waiter_;
    144 
    145   MOJO_DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
    146 };
    147 
    148 }  // namespace internal
    149 }  // namespace mojo
    150 
    151 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
    152