10de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
20de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
30de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// found in the LICENSE file.
40de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
50de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
60de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
70de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
80de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "mojo/public/cpp/bindings/error_handler.h"
90de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "mojo/public/cpp/bindings/interface_ptr.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/public/cpp/bindings/lib/filter_chain.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/public/cpp/bindings/lib/message_header_validator.h"
126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "mojo/public/cpp/environment/environment.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/cpp/environment/logging.h"
140de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#include "mojo/public/cpp/system/macros.h"
150de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)namespace mojo {
170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)namespace internal {
180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)template <typename Interface>
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class InterfaceImplBase : public Interface {
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~InterfaceImplBase() {}
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnConnectionEstablished() = 0;
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void OnConnectionError() = 0;
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <typename Interface>
280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)class InterfaceImplState : public ErrorHandler {
290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) public:
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  typedef typename Interface::Client Client;
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  explicit InterfaceImplState(InterfaceImplBase<Interface>* instance)
330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      : router_(NULL),
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        proxy_(NULL),
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        instance_bound_to_pipe_(false)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NDEBUG
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ,
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        deleting_instance_due_to_error_(false)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  {
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MOJO_DCHECK(instance);
420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    stub_.set_sink(instance);
430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  virtual ~InterfaceImplState() {
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NDEBUG
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MOJO_DCHECK(!instance_bound_to_pipe_ || deleting_instance_due_to_error_);
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    delete proxy_;
500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    if (router_) {
510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      router_->set_error_handler(NULL);
520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      delete router_;
530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    }
540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  void BindProxy(
570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)      InterfacePtr<Interface>* ptr,
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      bool instance_bound_to_pipe,
596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) {
600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    MessagePipe pipe;
610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    ptr->Bind(pipe.handle0.Pass(), waiter);
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Bind(pipe.handle1.Pass(), instance_bound_to_pipe, waiter);
630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  void Bind(ScopedMessagePipeHandle handle,
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            bool instance_bound_to_pipe,
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            const MojoAsyncWaiter* waiter) {
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    MOJO_CHECK(!router_);
690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    FilterChain filters;
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    filters.Append<MessageHeaderValidator>();
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    filters.Append<typename Interface::RequestValidator_>();
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    filters.Append<typename Interface::Client::ResponseValidator_>();
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    router_ = new Router(handle.Pass(), filters.Pass(), waiter);
760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    router_->set_incoming_receiver(&stub_);
770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)    router_->set_error_handler(this);
780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    proxy_ = new typename Client::Proxy_(router_);
800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    instance_bound_to_pipe_ = instance_bound_to_pipe;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    instance()->OnConnectionEstablished();
840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool WaitForIncomingMethodCall() {
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MOJO_DCHECK(router_);
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return router_->WaitForIncomingMessage();
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  Router* router() { return router_; }
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Client* client() { return proxy_; }
930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) private:
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InterfaceImplBase<Interface>* instance() {
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return static_cast<InterfaceImplBase<Interface>*>(stub_.sink());
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
990de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  virtual void OnConnectionError() MOJO_OVERRIDE {
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // If the the instance is not bound to the pipe, the instance might choose
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // to delete itself in the OnConnectionError handler, which would in turn
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // delete this.  Save the error behavior before invoking the error handler
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // so we can correctly decide what to do.
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool bound = instance_bound_to_pipe_;
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    instance()->OnConnectionError();
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!bound)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NDEBUG
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    deleting_instance_due_to_error_ = true;
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delete instance();
1120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  }
1130de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Router* router_;
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  typename Client::Proxy_* proxy_;
1160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  typename Interface::Stub_ stub_;
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool instance_bound_to_pipe_;
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifndef NDEBUG
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool deleting_instance_due_to_error_;
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
1210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceImplState);
1230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)};
1240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}  // namespace internal
1260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}  // namespace mojo
1270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
1280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_IMPL_INTERNAL_H_
129