136 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Copyright 2016 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_ASSOCIATED_BINDING_H_
 | |
| #define MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_
 | |
| 
 | |
| #include <memory>
 | |
| #include <string>
 | |
| #include <utility>
 | |
| 
 | |
| #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/associated_binding.h"
 | |
| #include "mojo/public/cpp/bindings/associated_interface_request.h"
 | |
| #include "mojo/public/cpp/bindings/connection_error_callback.h"
 | |
| #include "mojo/public/cpp/system/core.h"
 | |
| 
 | |
| namespace mojo {
 | |
| 
 | |
| template <typename Interface>
 | |
| class StrongAssociatedBinding;
 | |
| 
 | |
| template <typename Interface>
 | |
| using StrongAssociatedBindingPtr =
 | |
|     base::WeakPtr<StrongAssociatedBinding<Interface>>;
 | |
| 
 | |
| // This connects an interface implementation strongly to an associated pipe.
 | |
| // When a connection error is detected the implementation is deleted. If the
 | |
| // task runner that a StrongAssociatedBinding is bound on is stopped, the
 | |
| // connection error handler will not be invoked and the implementation will not
 | |
| // be deleted.
 | |
| //
 | |
| // To use, call StrongAssociatedBinding<T>::Create() (see below) or the helper
 | |
| // MakeStrongAssociatedBinding function:
 | |
| //
 | |
| //   mojo::MakeStrongAssociatedBinding(std::make_unique<FooImpl>(),
 | |
| //                                     std::move(foo_request));
 | |
| //
 | |
| template <typename Interface>
 | |
| class StrongAssociatedBinding {
 | |
|  public:
 | |
|   using ImplPointerType =
 | |
|       typename AssociatedBinding<Interface>::ImplPointerType;
 | |
| 
 | |
|   // Create a new StrongAssociatedBinding instance. The instance owns itself,
 | |
|   // cleaning up only in the event of a pipe connection error. Returns a WeakPtr
 | |
|   // to the new StrongAssociatedBinding instance.
 | |
|   static StrongAssociatedBindingPtr<Interface> Create(
 | |
|       std::unique_ptr<Interface> impl,
 | |
|       AssociatedInterfaceRequest<Interface> request) {
 | |
|     StrongAssociatedBinding* binding =
 | |
|         new StrongAssociatedBinding(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 StrongAssociatedBinding 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();
 | |
|   }
 | |
| 
 | |
|   // 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(); }
 | |
| 
 | |
|   // Allows test code to swap the interface implementation.
 | |
|   ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
 | |
|     return binding_.SwapImplForTesting(new_impl);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   StrongAssociatedBinding(std::unique_ptr<Interface> impl,
 | |
|                           AssociatedInterfaceRequest<Interface> request)
 | |
|       : impl_(std::move(impl)),
 | |
|         binding_(impl_.get(), std::move(request)),
 | |
|         weak_factory_(this) {
 | |
|     binding_.set_connection_error_with_reason_handler(base::Bind(
 | |
|         &StrongAssociatedBinding::OnConnectionError, base::Unretained(this)));
 | |
|   }
 | |
| 
 | |
|   ~StrongAssociatedBinding() {}
 | |
| 
 | |
|   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<Interface> impl_;
 | |
|   base::OnceClosure connection_error_handler_;
 | |
|   ConnectionErrorWithReasonCallback connection_error_with_reason_handler_;
 | |
|   AssociatedBinding<Interface> binding_;
 | |
|   base::WeakPtrFactory<StrongAssociatedBinding> weak_factory_;
 | |
| 
 | |
|   DISALLOW_COPY_AND_ASSIGN(StrongAssociatedBinding);
 | |
| };
 | |
| 
 | |
| template <typename Interface, typename Impl>
 | |
| StrongAssociatedBindingPtr<Interface> MakeStrongAssociatedBinding(
 | |
|     std::unique_ptr<Impl> impl,
 | |
|     AssociatedInterfaceRequest<Interface> request) {
 | |
|   return StrongAssociatedBinding<Interface>::Create(std::move(impl),
 | |
|                                                     std::move(request));
 | |
| }
 | |
| 
 | |
| }  // namespace mojo
 | |
| 
 | |
| #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_
 |