1 // Copyright 2014 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_BINDING_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_STRONG_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/binding.h"
18 #include "mojo/public/cpp/bindings/connection_error_callback.h"
19 #include "mojo/public/cpp/bindings/filter_chain.h"
20 #include "mojo/public/cpp/bindings/interface_ptr.h"
21 #include "mojo/public/cpp/bindings/interface_request.h"
22 #include "mojo/public/cpp/bindings/message_header_validator.h"
23 #include "mojo/public/cpp/system/core.h"
24
25 namespace mojo {
26
27 template <typename Interface>
28 class StrongBinding;
29
30 template <typename Interface>
31 using StrongBindingPtr = base::WeakPtr<StrongBinding<Interface>>;
32
33 // This connects an interface implementation strongly to a pipe. When a
34 // connection error is detected the implementation is deleted. If the task
35 // runner that a StrongBinding is bound on is stopped, the connection error
36 // handler will not be invoked and the implementation will not be deleted.
37 //
38 // To use, call StrongBinding<T>::Create() (see below) or the helper
39 // MakeStrongBinding function:
40 //
41 // mojo::MakeStrongBinding(std::make_unique<FooImpl>(),
42 // std::move(foo_request));
43 //
44 template <typename Interface>
45 class StrongBinding {
46 public:
47 // Create a new StrongBinding instance. The instance owns itself, cleaning up
48 // only in the event of a pipe connection error. Returns a WeakPtr to the new
49 // StrongBinding instance.
Create(std::unique_ptr<Interface> impl,InterfaceRequest<Interface> request)50 static StrongBindingPtr<Interface> Create(
51 std::unique_ptr<Interface> impl,
52 InterfaceRequest<Interface> request) {
53 StrongBinding* binding =
54 new StrongBinding(std::move(impl), std::move(request));
55 return binding->weak_factory_.GetWeakPtr();
56 }
57
58 // Note: The error handler must not delete the interface implementation.
59 //
60 // This method may only be called after this StrongBinding has been bound to a
61 // message pipe.
set_connection_error_handler(base::OnceClosure error_handler)62 void set_connection_error_handler(base::OnceClosure error_handler) {
63 DCHECK(binding_.is_bound());
64 connection_error_handler_ = std::move(error_handler);
65 connection_error_with_reason_handler_.Reset();
66 }
67
set_connection_error_with_reason_handler(ConnectionErrorWithReasonCallback error_handler)68 void set_connection_error_with_reason_handler(
69 ConnectionErrorWithReasonCallback error_handler) {
70 DCHECK(binding_.is_bound());
71 connection_error_with_reason_handler_ = std::move(error_handler);
72 connection_error_handler_.Reset();
73 }
74
75 // Stops processing incoming messages until
76 // ResumeIncomingMethodCallProcessing().
77 // Outgoing messages are still sent.
78 //
79 // No errors are detected on the message pipe while paused.
80 //
81 // This method may only be called if the object has been bound to a message
82 // pipe and there are no associated interfaces running.
PauseIncomingMethodCallProcessing()83 void PauseIncomingMethodCallProcessing() {
84 binding_.PauseIncomingMethodCallProcessing();
85 }
ResumeIncomingMethodCallProcessing()86 void ResumeIncomingMethodCallProcessing() {
87 binding_.ResumeIncomingMethodCallProcessing();
88 }
89
90 // Forces the binding to close. This destroys the StrongBinding instance.
Close()91 void Close() { delete this; }
92
impl()93 Interface* impl() { return impl_.get(); }
94
95 // Sends a message on the underlying message pipe and runs the current
96 // message loop until its response is received. This can be used in tests to
97 // verify that no message was sent on a message pipe in response to some
98 // stimulus.
FlushForTesting()99 void FlushForTesting() { binding_.FlushForTesting(); }
100
101 private:
StrongBinding(std::unique_ptr<Interface> impl,InterfaceRequest<Interface> request)102 StrongBinding(std::unique_ptr<Interface> impl,
103 InterfaceRequest<Interface> request)
104 : impl_(std::move(impl)),
105 binding_(impl_.get(), std::move(request)),
106 weak_factory_(this) {
107 binding_.set_connection_error_with_reason_handler(
108 base::Bind(&StrongBinding::OnConnectionError, base::Unretained(this)));
109 }
110
~StrongBinding()111 ~StrongBinding() {}
112
OnConnectionError(uint32_t custom_reason,const std::string & description)113 void OnConnectionError(uint32_t custom_reason,
114 const std::string& description) {
115 if (connection_error_handler_) {
116 std::move(connection_error_handler_).Run();
117 } else if (connection_error_with_reason_handler_) {
118 std::move(connection_error_with_reason_handler_)
119 .Run(custom_reason, description);
120 }
121 Close();
122 }
123
124 std::unique_ptr<Interface> impl_;
125 base::OnceClosure connection_error_handler_;
126 ConnectionErrorWithReasonCallback connection_error_with_reason_handler_;
127 Binding<Interface> binding_;
128 base::WeakPtrFactory<StrongBinding> weak_factory_;
129
130 DISALLOW_COPY_AND_ASSIGN(StrongBinding);
131 };
132
133 template <typename Interface, typename Impl>
MakeStrongBinding(std::unique_ptr<Impl> impl,InterfaceRequest<Interface> request)134 StrongBindingPtr<Interface> MakeStrongBinding(
135 std::unique_ptr<Impl> impl,
136 InterfaceRequest<Interface> request) {
137 return StrongBinding<Interface>::Create(std::move(impl), std::move(request));
138 }
139
140 } // namespace mojo
141
142 #endif // MOJO_PUBLIC_CPP_BINDINGS_STRONG_BINDING_H_
143