1 // Copyright 2015 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_BINDING_STATE_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ 7 8 #include <memory> 9 #include <utility> 10 11 #include "base/bind.h" 12 #include "base/callback.h" 13 #include "base/logging.h" 14 #include "base/macros.h" 15 #include "base/memory/ptr_util.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/single_thread_task_runner.h" 18 #include "mojo/public/cpp/bindings/associated_group.h" 19 #include "mojo/public/cpp/bindings/interface_endpoint_client.h" 20 #include "mojo/public/cpp/bindings/interface_id.h" 21 #include "mojo/public/cpp/bindings/interface_ptr.h" 22 #include "mojo/public/cpp/bindings/interface_ptr_info.h" 23 #include "mojo/public/cpp/bindings/interface_request.h" 24 #include "mojo/public/cpp/bindings/lib/filter_chain.h" 25 #include "mojo/public/cpp/bindings/lib/multiplex_router.h" 26 #include "mojo/public/cpp/bindings/lib/router.h" 27 #include "mojo/public/cpp/bindings/message_header_validator.h" 28 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" 29 #include "mojo/public/cpp/system/core.h" 30 31 namespace mojo { 32 namespace internal { 33 34 template <typename Interface, bool use_multiplex_router> 35 class BindingState; 36 37 // Uses a single-threaded, dedicated router. If |Interface| doesn't have any 38 // methods to pass associated interface pointers or requests, there won't be 39 // multiple interfaces running on the underlying message pipe. In that case, we 40 // can use this specialization to reduce cost. 41 template <typename Interface> 42 class BindingState<Interface, false> { 43 public: BindingState(Interface * impl)44 explicit BindingState(Interface* impl) : impl_(impl) { 45 stub_.set_sink(impl_); 46 } 47 ~BindingState()48 ~BindingState() { Close(); } 49 Bind(ScopedMessagePipeHandle handle,scoped_refptr<base::SingleThreadTaskRunner> runner)50 void Bind(ScopedMessagePipeHandle handle, 51 scoped_refptr<base::SingleThreadTaskRunner> runner) { 52 DCHECK(!router_); 53 internal::FilterChain filters; 54 filters.Append<MessageHeaderValidator>(Interface::Name_); 55 filters.Append<typename Interface::RequestValidator_>(); 56 57 router_ = 58 new internal::Router(std::move(handle), std::move(filters), 59 Interface::HasSyncMethods_, std::move(runner)); 60 router_->set_incoming_receiver(&stub_); 61 router_->set_connection_error_handler( 62 base::Bind(&BindingState::RunConnectionErrorHandler, 63 base::Unretained(this))); 64 } 65 HasAssociatedInterfaces()66 bool HasAssociatedInterfaces() const { return false; } 67 PauseIncomingMethodCallProcessing()68 void PauseIncomingMethodCallProcessing() { 69 DCHECK(router_); 70 router_->PauseIncomingMethodCallProcessing(); 71 } ResumeIncomingMethodCallProcessing()72 void ResumeIncomingMethodCallProcessing() { 73 DCHECK(router_); 74 router_->ResumeIncomingMethodCallProcessing(); 75 } 76 77 bool WaitForIncomingMethodCall( 78 MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) { 79 DCHECK(router_); 80 return router_->WaitForIncomingMessage(deadline); 81 } 82 Close()83 void Close() { 84 if (!router_) 85 return; 86 87 router_->CloseMessagePipe(); 88 DestroyRouter(); 89 } 90 Unbind()91 InterfaceRequest<Interface> Unbind() { 92 InterfaceRequest<Interface> request = 93 MakeRequest<Interface>(router_->PassMessagePipe()); 94 DestroyRouter(); 95 return std::move(request); 96 } 97 set_connection_error_handler(const base::Closure & error_handler)98 void set_connection_error_handler(const base::Closure& error_handler) { 99 DCHECK(is_bound()); 100 connection_error_handler_ = error_handler; 101 } 102 impl()103 Interface* impl() { return impl_; } 104 is_bound()105 bool is_bound() const { return !!router_; } 106 handle()107 MessagePipeHandle handle() const { 108 DCHECK(is_bound()); 109 return router_->handle(); 110 } 111 associated_group()112 AssociatedGroup* associated_group() { return nullptr; } 113 EnableTestingMode()114 void EnableTestingMode() { 115 DCHECK(is_bound()); 116 router_->EnableTestingMode(); 117 } 118 119 private: DestroyRouter()120 void DestroyRouter() { 121 router_->set_connection_error_handler(base::Closure()); 122 delete router_; 123 router_ = nullptr; 124 connection_error_handler_.Reset(); 125 } 126 RunConnectionErrorHandler()127 void RunConnectionErrorHandler() { 128 if (!connection_error_handler_.is_null()) 129 connection_error_handler_.Run(); 130 } 131 132 internal::Router* router_ = nullptr; 133 typename Interface::Stub_ stub_; 134 Interface* impl_; 135 base::Closure connection_error_handler_; 136 137 DISALLOW_COPY_AND_ASSIGN(BindingState); 138 }; 139 140 // Uses a multiplexing router. If |Interface| has methods to pass associated 141 // interface pointers or requests, this specialization should be used. 142 template <typename Interface> 143 class BindingState<Interface, true> { 144 public: BindingState(Interface * impl)145 explicit BindingState(Interface* impl) : impl_(impl) { 146 stub_.set_sink(impl_); 147 } 148 ~BindingState()149 ~BindingState() { Close(); } 150 Bind(ScopedMessagePipeHandle handle,scoped_refptr<base::SingleThreadTaskRunner> runner)151 void Bind(ScopedMessagePipeHandle handle, 152 scoped_refptr<base::SingleThreadTaskRunner> runner) { 153 DCHECK(!router_); 154 155 router_ = new internal::MultiplexRouter(false, std::move(handle), runner); 156 router_->SetMasterInterfaceName(Interface::Name_); 157 stub_.serialization_context()->group_controller = router_; 158 159 endpoint_client_.reset(new InterfaceEndpointClient( 160 router_->CreateLocalEndpointHandle(kMasterInterfaceId), 161 &stub_, base::WrapUnique(new typename Interface::RequestValidator_()), 162 Interface::HasSyncMethods_, std::move(runner))); 163 164 endpoint_client_->set_connection_error_handler( 165 base::Bind(&BindingState::RunConnectionErrorHandler, 166 base::Unretained(this))); 167 } 168 HasAssociatedInterfaces()169 bool HasAssociatedInterfaces() const { 170 return router_ ? router_->HasAssociatedEndpoints() : false; 171 } 172 PauseIncomingMethodCallProcessing()173 void PauseIncomingMethodCallProcessing() { 174 DCHECK(router_); 175 router_->PauseIncomingMethodCallProcessing(); 176 } ResumeIncomingMethodCallProcessing()177 void ResumeIncomingMethodCallProcessing() { 178 DCHECK(router_); 179 router_->ResumeIncomingMethodCallProcessing(); 180 } 181 182 bool WaitForIncomingMethodCall( 183 MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) { 184 DCHECK(router_); 185 return router_->WaitForIncomingMessage(deadline); 186 } 187 Close()188 void Close() { 189 if (!router_) 190 return; 191 192 endpoint_client_.reset(); 193 router_->CloseMessagePipe(); 194 router_ = nullptr; 195 connection_error_handler_.Reset(); 196 } 197 Unbind()198 InterfaceRequest<Interface> Unbind() { 199 endpoint_client_.reset(); 200 InterfaceRequest<Interface> request = 201 MakeRequest<Interface>(router_->PassMessagePipe()); 202 router_ = nullptr; 203 connection_error_handler_.Reset(); 204 return request; 205 } 206 set_connection_error_handler(const base::Closure & error_handler)207 void set_connection_error_handler(const base::Closure& error_handler) { 208 DCHECK(is_bound()); 209 connection_error_handler_ = error_handler; 210 } 211 impl()212 Interface* impl() { return impl_; } 213 is_bound()214 bool is_bound() const { return !!router_; } 215 handle()216 MessagePipeHandle handle() const { 217 DCHECK(is_bound()); 218 return router_->handle(); 219 } 220 associated_group()221 AssociatedGroup* associated_group() { 222 return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; 223 } 224 EnableTestingMode()225 void EnableTestingMode() { 226 DCHECK(is_bound()); 227 router_->EnableTestingMode(); 228 } 229 230 private: RunConnectionErrorHandler()231 void RunConnectionErrorHandler() { 232 if (!connection_error_handler_.is_null()) 233 connection_error_handler_.Run(); 234 } 235 236 scoped_refptr<internal::MultiplexRouter> router_; 237 std::unique_ptr<InterfaceEndpointClient> endpoint_client_; 238 239 typename Interface::Stub_ stub_; 240 Interface* impl_; 241 base::Closure connection_error_handler_; 242 243 DISALLOW_COPY_AND_ASSIGN(BindingState); 244 }; 245 246 } // namesapce internal 247 } // namespace mojo 248 249 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ 250