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: InterfacePtrState()23 InterfacePtrState() : proxy_(NULL), router_(NULL), waiter_(NULL) {} 24 ~InterfacePtrState()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 instance()33 Interface* instance() { 34 ConfigureProxyIfNecessary(); 35 36 // This will be NULL if the object is not bound. 37 return proxy_; 38 } 39 Swap(InterfacePtrState * other)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 Bind(ScopedMessagePipeHandle handle,const MojoAsyncWaiter * waiter)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 WaitForIncomingMethodCall()57 bool WaitForIncomingMethodCall() { 58 ConfigureProxyIfNecessary(); 59 60 MOJO_DCHECK(router_); 61 return router_->WaitForIncomingMessage(); 62 } 63 PassMessagePipe()64 ScopedMessagePipeHandle PassMessagePipe() { 65 if (router_) 66 return router_->PassMessagePipe(); 67 68 waiter_ = NULL; 69 return handle_.Pass(); 70 } 71 is_bound()72 bool is_bound() const { 73 return handle_.is_valid() || router_; 74 } 75 set_client(typename Interface::Client * client)76 void set_client(typename Interface::Client* client) { 77 ConfigureProxyIfNecessary(); 78 79 MOJO_DCHECK(proxy_); 80 proxy_->stub.set_sink(client); 81 } 82 encountered_error()83 bool encountered_error() const { 84 return router_ ? router_->encountered_error() : false; 85 } 86 set_error_handler(ErrorHandler * error_handler)87 void set_error_handler(ErrorHandler* error_handler) { 88 ConfigureProxyIfNecessary(); 89 90 MOJO_DCHECK(router_); 91 router_->set_error_handler(error_handler); 92 } 93 router_for_testing()94 Router* router_for_testing() { 95 ConfigureProxyIfNecessary(); 96 return router_; 97 } 98 99 private: 100 class ProxyWithStub : public Interface::Proxy_ { 101 public: ProxyWithStub(MessageReceiverWithResponder * receiver)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 ConfigureProxyIfNecessary()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