Chromium Code Reviews| Index: mojo/public/cpp/bindings/lib/binding_state.h |
| diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..905df4dd8369c542bacf437280bc53c6e1cb1e18 |
| --- /dev/null |
| +++ b/mojo/public/cpp/bindings/lib/binding_state.h |
| @@ -0,0 +1,209 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ |
| +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ |
| + |
| +#include "base/logging.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "mojo/public/c/environment/async_waiter.h" |
| +#include "mojo/public/cpp/bindings/associated_group.h" |
| +#include "mojo/public/cpp/bindings/callback.h" |
| +#include "mojo/public/cpp/bindings/interface_ptr.h" |
| +#include "mojo/public/cpp/bindings/interface_ptr_info.h" |
| +#include "mojo/public/cpp/bindings/interface_request.h" |
| +#include "mojo/public/cpp/bindings/lib/filter_chain.h" |
| +#include "mojo/public/cpp/bindings/lib/interface_endpoint_client.h" |
| +#include "mojo/public/cpp/bindings/lib/interface_id.h" |
| +#include "mojo/public/cpp/bindings/lib/message_header_validator.h" |
| +#include "mojo/public/cpp/bindings/lib/multiplex_router.h" |
| +#include "mojo/public/cpp/bindings/lib/router.h" |
| +#include "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.h" |
| +#include "mojo/public/cpp/system/core.h" |
| + |
| +namespace mojo { |
| +namespace internal { |
| + |
| +template <typename Interface, bool kUsesMultiplexRouter> |
|
sky
2015/11/24 22:20:45
kUsesMultiplexRouter isn't a constant. use_multipl
yzshen1
2015/11/25 00:26:36
Done.
|
| +class BindingState; |
| + |
| +template <typename Interface> |
| +class BindingState<Interface, false> { |
|
sky
2015/11/24 22:20:45
Add a description.
yzshen1
2015/11/25 00:26:36
Done.
|
| + public: |
| + explicit BindingState(Interface* impl) : impl_(impl) { |
| + stub_.set_sink(impl_); |
| + } |
| + |
| + ~BindingState() { |
| + if (router_) |
| + Close(); |
| + } |
| + |
| + void Bind(ScopedMessagePipeHandle handle, const MojoAsyncWaiter* waiter) { |
| + DCHECK(!router_); |
| + internal::FilterChain filters; |
| + filters.Append<internal::MessageHeaderValidator>(); |
| + filters.Append<typename Interface::RequestValidator_>(); |
| + |
| + router_ = new internal::Router(handle.Pass(), filters.Pass(), waiter); |
| + router_->set_incoming_receiver(&stub_); |
| + router_->set_connection_error_handler( |
| + [this]() { connection_error_handler_.Run(); }); |
| + } |
| + |
| + void PauseIncomingMethodCallProcessing() { |
|
sky
2015/11/24 22:20:45
What will the semantics of pausing/resuming be wit
yzshen1
2015/11/25 00:26:36
Documented in binding.h and also interface_ptr.h t
|
| + DCHECK(router_); |
| + router_->PauseIncomingMethodCallProcessing(); |
| + } |
| + void ResumeIncomingMethodCallProcessing() { |
| + DCHECK(router_); |
| + router_->ResumeIncomingMethodCallProcessing(); |
| + } |
| + |
| + bool WaitForIncomingMethodCall( |
| + MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) { |
| + DCHECK(router_); |
| + return router_->WaitForIncomingMessage(deadline); |
| + } |
| + |
| + void Close() { |
| + DCHECK(router_); |
| + router_->CloseMessagePipe(); |
| + DestroyRouter(); |
| + } |
| + |
| + InterfaceRequest<Interface> Unbind() { |
| + InterfaceRequest<Interface> request = |
| + MakeRequest<Interface>(router_->PassMessagePipe()); |
| + DestroyRouter(); |
| + return request.Pass(); |
| + } |
| + |
| + void set_connection_error_handler(const Closure& error_handler) { |
| + connection_error_handler_ = error_handler; |
| + } |
| + |
| + Interface* impl() { return impl_; } |
| + |
| + bool is_bound() const { return !!router_; } |
| + |
| + MessagePipeHandle handle() const { |
| + DCHECK(is_bound()); |
| + return router_->handle(); |
| + } |
| + |
| + AssociatedGroup* associated_group() { return nullptr; } |
| + |
| + void EnableTestingMode() { |
| + DCHECK(is_bound()); |
| + router_->EnableTestingMode(); |
| + } |
| + |
| + private: |
| + void DestroyRouter() { |
| + router_->set_connection_error_handler(Closure()); |
| + delete router_; |
| + router_ = nullptr; |
| + } |
| + |
| + internal::Router* router_ = nullptr; |
| + typename Interface::Stub_ stub_; |
| + Interface* impl_; |
| + Closure connection_error_handler_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BindingState); |
| +}; |
| + |
| +template <typename Interface> |
| +class BindingState<Interface, true> { |
| + public: |
| + explicit BindingState(Interface* impl) : impl_(impl) { |
| + stub_.set_sink(impl_); |
| + } |
| + |
| + ~BindingState() { |
| + if (router_) |
| + Close(); |
| + } |
| + |
| + void Bind(ScopedMessagePipeHandle handle, const MojoAsyncWaiter* waiter) { |
| + DCHECK(!router_); |
| + |
| + router_ = new internal::MultiplexRouter(false, handle.Pass(), waiter); |
| + endpoint_client_.reset(new internal::InterfaceEndpointClient( |
| + router_->CreateLocalEndpointHandle(internal::kMasterInterfaceId), |
| + &stub_, make_scoped_ptr(new typename Interface::RequestValidator_()))); |
| + |
| + endpoint_client_->set_connection_error_handler( |
| + [this]() { connection_error_handler_.Run(); }); |
| + } |
| + |
| + void PauseIncomingMethodCallProcessing() { |
| + DCHECK(router_); |
| + router_->PauseIncomingMethodCallProcessing(); |
| + } |
| + void ResumeIncomingMethodCallProcessing() { |
| + DCHECK(router_); |
| + router_->ResumeIncomingMethodCallProcessing(); |
| + } |
| + |
| + bool WaitForIncomingMethodCall(MojoDeadline deadline) { |
| + DCHECK(router_); |
| + return router_->WaitForIncomingMessage(deadline); |
| + } |
| + |
| + void Close() { |
| + DCHECK(router_); |
| + endpoint_client_.reset(); |
| + router_->CloseMessagePipe(); |
| + router_ = nullptr; |
| + } |
| + |
| + InterfaceRequest<Interface> Unbind() { |
| + endpoint_client_.reset(); |
| + InterfaceRequest<Interface> request = |
| + MakeRequest<Interface>(router_->PassMessagePipe()); |
| + router_ = nullptr; |
| + return request.Pass(); |
| + } |
| + |
| + void set_connection_error_handler(const Closure& error_handler) { |
| + connection_error_handler_ = error_handler; |
| + } |
| + |
| + Interface* impl() { return impl_; } |
| + |
| + bool is_bound() const { return !!router_; } |
| + |
| + MessagePipeHandle handle() const { |
| + DCHECK(is_bound()); |
| + return router_->handle(); |
| + } |
| + |
| + AssociatedGroup* associated_group() { |
| + return endpoint_client_ ? endpoint_client_->associated_group() : nullptr; |
| + } |
| + |
| + void EnableTestingMode() { |
| + DCHECK(is_bound()); |
| + router_->EnableTestingMode(); |
| + } |
| + |
| + private: |
| + scoped_refptr<internal::MultiplexRouter> router_; |
| + scoped_ptr<internal::InterfaceEndpointClient> endpoint_client_; |
| + |
| + typename Interface::Stub_ stub_; |
| + Interface* impl_; |
| + Closure connection_error_handler_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BindingState); |
| +}; |
| + |
| +} // namesapce internal |
| +} // namespace mojo |
| + |
| +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_ |