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_IMPL_INTERNAL_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
      7 
      8 #include "mojo/public/cpp/bindings/error_handler.h"
      9 #include "mojo/public/cpp/bindings/interface_ptr.h"
     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/environment/environment.h"
     13 #include "mojo/public/cpp/environment/logging.h"
     14 #include "mojo/public/cpp/system/macros.h"
     15 
     16 namespace mojo {
     17 namespace internal {
     18 
     19 template <typename Interface>
     20 class InterfaceImplBase : public Interface {
     21  public:
     22   virtual ~InterfaceImplBase() {}
     23   virtual void OnConnectionEstablished() = 0;
     24   virtual void OnConnectionError() = 0;
     25 };
     26 
     27 template <typename Interface>
     28 class InterfaceImplState : public ErrorHandler {
     29  public:
     30   typedef typename Interface::Client Client;
     31 
     32   explicit InterfaceImplState(InterfaceImplBase<Interface>* instance)
     33       : router_(NULL),
     34         proxy_(NULL),
     35         instance_bound_to_pipe_(false)
     36 #ifndef NDEBUG
     37         ,
     38         deleting_instance_due_to_error_(false)
     39 #endif
     40   {
     41     MOJO_DCHECK(instance);
     42     stub_.set_sink(instance);
     43   }
     44 
     45   virtual ~InterfaceImplState() {
     46 #ifndef NDEBUG
     47     MOJO_DCHECK(!instance_bound_to_pipe_ || deleting_instance_due_to_error_);
     48 #endif
     49     delete proxy_;
     50     if (router_) {
     51       router_->set_error_handler(NULL);
     52       delete router_;
     53     }
     54   }
     55 
     56   void BindProxy(
     57       InterfacePtr<Interface>* ptr,
     58       bool instance_bound_to_pipe,
     59       const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
     60     MessagePipe pipe;
     61     ptr->Bind(pipe.handle0.Pass(), waiter);
     62     Bind(pipe.handle1.Pass(), instance_bound_to_pipe, waiter);
     63   }
     64 
     65   void Bind(ScopedMessagePipeHandle handle,
     66             bool instance_bound_to_pipe,
     67             const MojoAsyncWaiter* waiter) {
     68     MOJO_CHECK(!router_);
     69 
     70     FilterChain filters;
     71     filters.Append<MessageHeaderValidator>();
     72     filters.Append<typename Interface::RequestValidator_>();
     73     filters.Append<typename Interface::Client::ResponseValidator_>();
     74 
     75     router_ = new Router(handle.Pass(), filters.Pass(), waiter);
     76     router_->set_incoming_receiver(&stub_);
     77     router_->set_error_handler(this);
     78 
     79     proxy_ = new typename Client::Proxy_(router_);
     80 
     81     instance_bound_to_pipe_ = instance_bound_to_pipe;
     82 
     83     instance()->OnConnectionEstablished();
     84   }
     85 
     86   bool WaitForIncomingMethodCall() {
     87     MOJO_DCHECK(router_);
     88     return router_->WaitForIncomingMessage();
     89   }
     90 
     91   Router* router() { return router_; }
     92   Client* client() { return proxy_; }
     93 
     94  private:
     95   InterfaceImplBase<Interface>* instance() {
     96     return static_cast<InterfaceImplBase<Interface>*>(stub_.sink());
     97   }
     98 
     99   virtual void OnConnectionError() MOJO_OVERRIDE {
    100     // If the the instance is not bound to the pipe, the instance might choose
    101     // to delete itself in the OnConnectionError handler, which would in turn
    102     // delete this.  Save the error behavior before invoking the error handler
    103     // so we can correctly decide what to do.
    104     bool bound = instance_bound_to_pipe_;
    105     instance()->OnConnectionError();
    106     if (!bound)
    107       return;
    108 #ifndef NDEBUG
    109     deleting_instance_due_to_error_ = true;
    110 #endif
    111     delete instance();
    112   }
    113 
    114   Router* router_;
    115   typename Client::Proxy_* proxy_;
    116   typename Interface::Stub_ stub_;
    117   bool instance_bound_to_pipe_;
    118 #ifndef NDEBUG
    119   bool deleting_instance_due_to_error_;
    120 #endif
    121 
    122   MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceImplState);
    123 };
    124 
    125 }  // namespace internal
    126 }  // namespace mojo
    127 
    128 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
    129