blob: fffdeb4d620ba1c40d46fcc09ea7eae6ff964944 [file] [log] [blame]
reillyg627e7f72016-10-20 05:12:431// Copyright 2016 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_STRONG_ASSOCIATED_BINDING_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_
7
8#include <memory>
9#include <string>
10#include <utility>
11
12#include "base/bind.h"
13#include "base/callback.h"
14#include "base/logging.h"
15#include "base/macros.h"
16#include "base/memory/weak_ptr.h"
17#include "mojo/public/cpp/bindings/associated_binding.h"
18#include "mojo/public/cpp/bindings/associated_interface_request.h"
19#include "mojo/public/cpp/bindings/connection_error_callback.h"
20#include "mojo/public/cpp/system/core.h"
21
22namespace mojo {
23
24template <typename Interface>
25class StrongAssociatedBinding;
26
27template <typename Interface>
28using StrongAssociatedBindingPtr =
29 base::WeakPtr<StrongAssociatedBinding<Interface>>;
30
31// This connects an interface implementation strongly to an associated pipe.
sammc14e09ca2017-01-30 22:07:3332// When a connection error is detected the implementation is deleted. If the
33// task runner that a StrongAssociatedBinding is bound on is stopped, the
34// connection error handler will not be invoked and the implementation will not
35// be deleted.
reillyg627e7f72016-10-20 05:12:4336//
37// To use, call StrongAssociatedBinding<T>::Create() (see below) or the helper
38// MakeStrongAssociatedBinding function:
39//
Jeremy Romancf9ae2f2017-08-24 17:06:3740// mojo::MakeStrongAssociatedBinding(std::make_unique<FooImpl>(),
reillyg627e7f72016-10-20 05:12:4341// std::move(foo_request));
42//
43template <typename Interface>
44class StrongAssociatedBinding {
45 public:
Marijn Kruisselbrink8f1b1a72018-01-26 18:09:5646 using ImplPointerType =
47 typename AssociatedBinding<Interface>::ImplPointerType;
48
reillyg627e7f72016-10-20 05:12:4349 // Create a new StrongAssociatedBinding instance. The instance owns itself,
50 // cleaning up only in the event of a pipe connection error. Returns a WeakPtr
51 // to the new StrongAssociatedBinding instance.
52 static StrongAssociatedBindingPtr<Interface> Create(
53 std::unique_ptr<Interface> impl,
54 AssociatedInterfaceRequest<Interface> request) {
55 StrongAssociatedBinding* binding =
56 new StrongAssociatedBinding(std::move(impl), std::move(request));
57 return binding->weak_factory_.GetWeakPtr();
58 }
59
60 // Note: The error handler must not delete the interface implementation.
61 //
62 // This method may only be called after this StrongAssociatedBinding has been
63 // bound to a message pipe.
jameswest14ae0132017-06-12 22:52:0064 void set_connection_error_handler(base::OnceClosure error_handler) {
reillyg627e7f72016-10-20 05:12:4365 DCHECK(binding_.is_bound());
jameswest14ae0132017-06-12 22:52:0066 connection_error_handler_ = std::move(error_handler);
reillyg627e7f72016-10-20 05:12:4367 connection_error_with_reason_handler_.Reset();
68 }
69
70 void set_connection_error_with_reason_handler(
jameswest14ae0132017-06-12 22:52:0071 ConnectionErrorWithReasonCallback error_handler) {
reillyg627e7f72016-10-20 05:12:4372 DCHECK(binding_.is_bound());
jameswest14ae0132017-06-12 22:52:0073 connection_error_with_reason_handler_ = std::move(error_handler);
reillyg627e7f72016-10-20 05:12:4374 connection_error_handler_.Reset();
75 }
76
77 // Forces the binding to close. This destroys the StrongBinding instance.
78 void Close() { delete this; }
79
80 Interface* impl() { return impl_.get(); }
81
82 // Sends a message on the underlying message pipe and runs the current
83 // message loop until its response is received. This can be used in tests to
84 // verify that no message was sent on a message pipe in response to some
85 // stimulus.
86 void FlushForTesting() { binding_.FlushForTesting(); }
87
Marijn Kruisselbrink8f1b1a72018-01-26 18:09:5688 // Allows test code to swap the interface implementation.
89 ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
90 return binding_.SwapImplForTesting(new_impl);
91 }
92
reillyg627e7f72016-10-20 05:12:4393 private:
94 StrongAssociatedBinding(std::unique_ptr<Interface> impl,
95 AssociatedInterfaceRequest<Interface> request)
96 : impl_(std::move(impl)),
97 binding_(impl_.get(), std::move(request)),
98 weak_factory_(this) {
99 binding_.set_connection_error_with_reason_handler(base::Bind(
100 &StrongAssociatedBinding::OnConnectionError, base::Unretained(this)));
101 }
102
103 ~StrongAssociatedBinding() {}
104
105 void OnConnectionError(uint32_t custom_reason,
106 const std::string& description) {
jameswest14ae0132017-06-12 22:52:00107 if (connection_error_handler_) {
108 std::move(connection_error_handler_).Run();
109 } else if (connection_error_with_reason_handler_) {
110 std::move(connection_error_with_reason_handler_)
111 .Run(custom_reason, description);
112 }
reillyg627e7f72016-10-20 05:12:43113 Close();
114 }
115
116 std::unique_ptr<Interface> impl_;
jameswest14ae0132017-06-12 22:52:00117 base::OnceClosure connection_error_handler_;
reillyg627e7f72016-10-20 05:12:43118 ConnectionErrorWithReasonCallback connection_error_with_reason_handler_;
119 AssociatedBinding<Interface> binding_;
120 base::WeakPtrFactory<StrongAssociatedBinding> weak_factory_;
121
122 DISALLOW_COPY_AND_ASSIGN(StrongAssociatedBinding);
123};
124
125template <typename Interface, typename Impl>
126StrongAssociatedBindingPtr<Interface> MakeStrongAssociatedBinding(
127 std::unique_ptr<Impl> impl,
128 AssociatedInterfaceRequest<Interface> request) {
129 return StrongAssociatedBinding<Interface>::Create(std::move(impl),
130 std::move(request));
131}
132
133} // namespace mojo
134
135#endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_ASSOCIATED_BINDING_H_