// Copyright 2014 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_STRONG_BINDING_H_ #define MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_ #include #include #include #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/connection_error_callback.h" #include "mojo/public/cpp/bindings/filter_chain.h" #include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/message_header_validator.h" #include "mojo/public/cpp/system/core.h" namespace mojo { template class StrongBinding; template using StrongBindingPtr = base::WeakPtr>; // This connects an interface implementation strongly to a pipe. When a // connection error is detected the implementation is deleted. If the task // runner that a StrongBinding is bound on is stopped, the connection error // handler will not be invoked and the implementation will not be deleted. // // To use, call StrongBinding::Create() (see below) or the helper // MakeStrongBinding function: // // mojo::MakeStrongBinding(std::make_unique(), // std::move(foo_request)); // template class StrongBinding { public: // Create a new StrongBinding instance. The instance owns itself, cleaning up // only in the event of a pipe connection error. Returns a WeakPtr to the new // StrongBinding instance. static StrongBindingPtr Create( std::unique_ptr impl, InterfaceRequest request) { StrongBinding* binding = new StrongBinding(std::move(impl), std::move(request)); return binding->weak_factory_.GetWeakPtr(); } // Note: The error handler must not delete the interface implementation. // // This method may only be called after this StrongBinding has been bound to a // message pipe. void set_connection_error_handler(base::OnceClosure error_handler) { DCHECK(binding_.is_bound()); connection_error_handler_ = std::move(error_handler); connection_error_with_reason_handler_.Reset(); } void set_connection_error_with_reason_handler( ConnectionErrorWithReasonCallback error_handler) { DCHECK(binding_.is_bound()); connection_error_with_reason_handler_ = std::move(error_handler); connection_error_handler_.Reset(); } // Stops processing incoming messages until // ResumeIncomingMethodCallProcessing(). // Outgoing messages are still sent. // // No errors are detected on the message pipe while paused. // // This method may only be called if the object has been bound to a message // pipe and there are no associated interfaces running. void PauseIncomingMethodCallProcessing() { binding_.PauseIncomingMethodCallProcessing(); } void ResumeIncomingMethodCallProcessing() { binding_.ResumeIncomingMethodCallProcessing(); } // Forces the binding to close. This destroys the StrongBinding instance. void Close() { delete this; } Interface* impl() { return impl_.get(); } // Sends a message on the underlying message pipe and runs the current // message loop until its response is received. This can be used in tests to // verify that no message was sent on a message pipe in response to some // stimulus. void FlushForTesting() { binding_.FlushForTesting(); } private: StrongBinding(std::unique_ptr impl, InterfaceRequest request) : impl_(std::move(impl)), binding_(impl_.get(), std::move(request)), weak_factory_(this) { binding_.set_connection_error_with_reason_handler( base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this))); } ~StrongBinding() {} void OnConnectionError(uint32_t custom_reason, const std::string& description) { if (connection_error_handler_) { std::move(connection_error_handler_).Run(); } else if (connection_error_with_reason_handler_) { std::move(connection_error_with_reason_handler_) .Run(custom_reason, description); } Close(); } std::unique_ptr impl_; base::OnceClosure connection_error_handler_; ConnectionErrorWithReasonCallback connection_error_with_reason_handler_; Binding binding_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(StrongBinding); }; template StrongBindingPtr MakeStrongBinding( std::unique_ptr impl, InterfaceRequest request) { return StrongBinding::Create(std::move(impl), std::move(request)); } } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_