blob: 5e4bb2696e992c96db65d5b8620bcbc389ee0815 [file] [log] [blame]
rockot85dce0862015-11-13 01:33:591// 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_BINDING_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_
7
yzshen24438d22016-09-13 17:03:538#include <string>
dchengaa6492d2015-12-26 04:46:369#include <utility>
10
rockota21316a2016-06-19 17:08:3611#include "base/callback_forward.h"
yzshen0b5628a2015-11-25 05:58:1012#include "base/macros.h"
yzshenf5d48932016-04-22 23:18:3313#include "base/memory/ref_counted.h"
14#include "base/single_thread_task_runner.h"
gab6e4c7542016-05-11 18:11:1615#include "base/threading/thread_task_runner_handle.h"
yzshen24438d22016-09-13 17:03:5316#include "mojo/public/cpp/bindings/connection_error_callback.h"
rockot85dce0862015-11-13 01:33:5917#include "mojo/public/cpp/bindings/interface_ptr.h"
18#include "mojo/public/cpp/bindings/interface_ptr_info.h"
19#include "mojo/public/cpp/bindings/interface_request.h"
yzshen0b5628a2015-11-25 05:58:1020#include "mojo/public/cpp/bindings/lib/binding_state.h"
rockot8e2a5d22016-10-10 06:38:1021#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
rockot85dce0862015-11-13 01:33:5922#include "mojo/public/cpp/system/core.h"
23
24namespace mojo {
25
rockot222e7dd2016-08-24 23:37:1126class MessageReceiver;
yzshen0b5628a2015-11-25 05:58:1027
rockot85dce0862015-11-13 01:33:5928// Represents the binding of an interface implementation to a message pipe.
29// When the |Binding| object is destroyed, the binding between the message pipe
30// and the interface is torn down and the message pipe is closed, leaving the
31// interface implementation in an unbound state.
32//
33// Example:
34//
35// #include "foo.mojom.h"
36//
37// class FooImpl : public Foo {
38// public:
39// explicit FooImpl(InterfaceRequest<Foo> request)
yzshenbeda231232016-03-04 20:15:3940// : binding_(this, std::move(request)) {}
rockot85dce0862015-11-13 01:33:5941//
42// // Foo implementation here.
43//
44// private:
45// Binding<Foo> binding_;
46// };
47//
48// class MyFooFactory : public InterfaceFactory<Foo> {
49// public:
50// void Create(..., InterfaceRequest<Foo> request) override {
yzshenbeda231232016-03-04 20:15:3951// auto f = new FooImpl(std::move(request));
rockot85dce0862015-11-13 01:33:5952// // Do something to manage the lifetime of |f|. Use StrongBinding<> to
53// // delete FooImpl on connection errors.
54// }
55// };
56//
amistry913e9f12016-01-06 22:12:0357// This class is thread hostile while bound to a message pipe. All calls to this
58// class must be from the thread that bound it. The interface implementation's
59// methods will be called from the thread that bound this. If a Binding is not
60// bound to a message pipe, it may be bound or destroyed on any thread.
yzshenf5d48932016-04-22 23:18:3361//
62// When you bind this class to a message pipe, optionally you can specify a
63// base::SingleThreadTaskRunner. This task runner must belong to the same
64// thread. It will be used to dispatch incoming method calls and connection
65// error notification. It is useful when you attach multiple task runners to a
66// single thread for the purposes of task scheduling. Please note that incoming
67// synchrounous method calls may not be run from this task runner, when they
68// reenter outgoing synchrounous calls on the same thread.
rockot8e2a5d22016-10-10 06:38:1069template <typename Interface,
70 typename ImplRefTraits = RawPtrImplRefTraits<Interface>>
rockot85dce0862015-11-13 01:33:5971class Binding {
72 public:
rockot8e2a5d22016-10-10 06:38:1073 using ImplPointerType = typename ImplRefTraits::PointerType;
74
rockot85dce0862015-11-13 01:33:5975 // Constructs an incomplete binding that will use the implementation |impl|.
76 // The binding may be completed with a subsequent call to the |Bind| method.
77 // Does not take ownership of |impl|, which must outlive the binding.
rockot8e2a5d22016-10-10 06:38:1078 explicit Binding(ImplPointerType impl) : internal_state_(std::move(impl)) {}
rockot85dce0862015-11-13 01:33:5979
rockot85dce0862015-11-13 01:33:5980 // Constructs a completed binding of |impl| to the message pipe endpoint in
81 // |request|, taking ownership of the endpoint. Does not take ownership of
yzshen076d08762016-03-02 06:57:1482 // |impl|, which must outlive the binding.
rockot8e2a5d22016-10-10 06:38:1083 Binding(ImplPointerType impl,
yzshenf5d48932016-04-22 23:18:3384 InterfaceRequest<Interface> request,
85 scoped_refptr<base::SingleThreadTaskRunner> runner =
86 base::ThreadTaskRunnerHandle::Get())
rockot8e2a5d22016-10-10 06:38:1087 : Binding(std::move(impl)) {
Ken Rockot42472452017-05-12 05:37:0388 Bind(std::move(request), std::move(runner));
rockot85dce0862015-11-13 01:33:5989 }
90
91 // Tears down the binding, closing the message pipe and leaving the interface
92 // implementation unbound.
yzshen0b5628a2015-11-25 05:58:1093 ~Binding() {}
rockot85dce0862015-11-13 01:33:5994
skyad19bf46a2016-01-21 18:59:4795 // Returns an InterfacePtr bound to one end of a pipe whose other end is
96 // bound to |this|.
yzshenf5d48932016-04-22 23:18:3397 InterfacePtr<Interface> CreateInterfacePtrAndBind(
98 scoped_refptr<base::SingleThreadTaskRunner> runner =
99 base::ThreadTaskRunnerHandle::Get()) {
skyad19bf46a2016-01-21 18:59:47100 InterfacePtr<Interface> interface_ptr;
Ken Rockot42472452017-05-12 05:37:03101 Bind(MakeRequest(&interface_ptr), std::move(runner));
skyad19bf46a2016-01-21 18:59:47102 return interface_ptr;
103 }
104
rockot85dce0862015-11-13 01:33:59105 // Completes a binding that was constructed with only an interface
rockot85dce0862015-11-13 01:33:59106 // implementation by removing the message pipe endpoint from |request| and
yzshen076d08762016-03-02 06:57:14107 // binding it to the previously specified implementation.
yzshenf5d48932016-04-22 23:18:33108 void Bind(InterfaceRequest<Interface> request,
109 scoped_refptr<base::SingleThreadTaskRunner> runner =
110 base::ThreadTaskRunnerHandle::Get()) {
Ken Rockot42472452017-05-12 05:37:03111 internal_state_.Bind(request.PassMessagePipe(), std::move(runner));
rockot85dce0862015-11-13 01:33:59112 }
113
rockot222e7dd2016-08-24 23:37:11114 // Adds a message filter to be notified of each incoming message before
115 // dispatch. If a filter returns |false| from Accept(), the message is not
116 // dispatched and the pipe is closed. Filters cannot be removed.
117 void AddFilter(std::unique_ptr<MessageReceiver> filter) {
118 DCHECK(is_bound());
119 internal_state_.AddFilter(std::move(filter));
120 }
121
yzshen1e8f6662015-12-11 01:37:50122 // Whether there are any associated interfaces running on the pipe currently.
123 bool HasAssociatedInterfaces() const {
124 return internal_state_.HasAssociatedInterfaces();
125 }
126
rockot85dce0862015-11-13 01:33:59127 // Stops processing incoming messages until
128 // ResumeIncomingMethodCallProcessing(), or WaitForIncomingMethodCall().
129 // Outgoing messages are still sent.
130 //
131 // No errors are detected on the message pipe while paused.
yzshen0b5628a2015-11-25 05:58:10132 //
yzshen1e8f6662015-12-11 01:37:50133 // This method may only be called if the object has been bound to a message
134 // pipe and there are no associated interfaces running.
rockot85dce0862015-11-13 01:33:59135 void PauseIncomingMethodCallProcessing() {
yzshen1e8f6662015-12-11 01:37:50136 CHECK(!HasAssociatedInterfaces());
yzshen0b5628a2015-11-25 05:58:10137 internal_state_.PauseIncomingMethodCallProcessing();
rockot85dce0862015-11-13 01:33:59138 }
139 void ResumeIncomingMethodCallProcessing() {
yzshen0b5628a2015-11-25 05:58:10140 internal_state_.ResumeIncomingMethodCallProcessing();
rockot85dce0862015-11-13 01:33:59141 }
142
143 // Blocks the calling thread until either a call arrives on the previously
144 // bound message pipe, the deadline is exceeded, or an error occurs. Returns
145 // true if a method was successfully read and dispatched.
yzshen0b5628a2015-11-25 05:58:10146 //
yzshen1e8f6662015-12-11 01:37:50147 // This method may only be called if the object has been bound to a message
sky66b7a5e2017-03-24 19:11:22148 // pipe. This returns once a message is received either on the master
149 // interface or any associated interfaces.
rockot85dce0862015-11-13 01:33:59150 bool WaitForIncomingMethodCall(
151 MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
yzshen0b5628a2015-11-25 05:58:10152 return internal_state_.WaitForIncomingMethodCall(deadline);
rockot85dce0862015-11-13 01:33:59153 }
154
155 // Closes the message pipe that was previously bound. Put this object into a
156 // state where it can be rebound to a new pipe.
yzshen0b5628a2015-11-25 05:58:10157 void Close() { internal_state_.Close(); }
rockot85dce0862015-11-13 01:33:59158
yzshen24438d22016-09-13 17:03:53159 // Similar to the method above, but also specifies a disconnect reason.
160 void CloseWithReason(uint32_t custom_reason, const std::string& description) {
161 internal_state_.CloseWithReason(custom_reason, description);
162 }
163
rockot85dce0862015-11-13 01:33:59164 // Unbinds the underlying pipe from this binding and returns it so it can be
165 // used in another context, such as on another thread or with a different
166 // implementation. Put this object into a state where it can be rebound to a
167 // new pipe.
yzshen1e8f6662015-12-11 01:37:50168 //
169 // This method may only be called if the object has been bound to a message
170 // pipe and there are no associated interfaces running.
171 //
172 // TODO(yzshen): For now, users need to make sure there is no one holding
173 // on to associated interface endpoint handles at both sides of the
174 // message pipe in order to call this method. We need a way to forcefully
175 // invalidate associated interface endpoint handles.
yzshenb92c3dd2016-03-08 23:48:49176 InterfaceRequest<Interface> Unbind() {
yzshen1e8f6662015-12-11 01:37:50177 CHECK(!HasAssociatedInterfaces());
178 return internal_state_.Unbind();
179 }
rockot85dce0862015-11-13 01:33:59180
181 // Sets an error handler that will be called if a connection error occurs on
182 // the bound message pipe.
amistryf70387572015-12-17 05:23:43183 //
184 // This method may only be called after this Binding has been bound to a
185 // message pipe. The error handler will be reset when this Binding is unbound
186 // or closed.
rockota21316a2016-06-19 17:08:36187 void set_connection_error_handler(const base::Closure& error_handler) {
amistryf70387572015-12-17 05:23:43188 DCHECK(is_bound());
yzshen0b5628a2015-11-25 05:58:10189 internal_state_.set_connection_error_handler(error_handler);
rockot85dce0862015-11-13 01:33:59190 }
191
yzshen24438d22016-09-13 17:03:53192 void set_connection_error_with_reason_handler(
193 const ConnectionErrorWithReasonCallback& error_handler) {
194 DCHECK(is_bound());
195 internal_state_.set_connection_error_with_reason_handler(error_handler);
196 }
197
rockot85dce0862015-11-13 01:33:59198 // Returns the interface implementation that was previously specified. Caller
199 // does not take ownership.
yzshen0b5628a2015-11-25 05:58:10200 Interface* impl() { return internal_state_.impl(); }
rockot85dce0862015-11-13 01:33:59201
202 // Indicates whether the binding has been completed (i.e., whether a message
203 // pipe has been bound to the implementation).
yzshen0b5628a2015-11-25 05:58:10204 bool is_bound() const { return internal_state_.is_bound(); }
rockot85dce0862015-11-13 01:33:59205
206 // Returns the value of the handle currently bound to this Binding which can
207 // be used to make explicit Wait/WaitMany calls. Requires that the Binding be
208 // bound. Ownership of the handle is retained by the Binding, it is not
209 // transferred to the caller.
yzshen0b5628a2015-11-25 05:58:10210 MessagePipeHandle handle() const { return internal_state_.handle(); }
211
sammc462458f2016-09-01 09:52:58212 // Sends a no-op message on the underlying message pipe and runs the current
213 // message loop until its response is received. This can be used in tests to
214 // verify that no message was sent on a message pipe in response to some
215 // stimulus.
216 void FlushForTesting() { internal_state_.FlushForTesting(); }
217
rockot85dce0862015-11-13 01:33:59218 // Exposed for testing, should not generally be used.
yzshen0b5628a2015-11-25 05:58:10219 void EnableTestingMode() { internal_state_.EnableTestingMode(); }
rockot85dce0862015-11-13 01:33:59220
221 private:
yzshena87f4ac2016-11-30 19:03:20222 internal::BindingState<Interface, ImplRefTraits> internal_state_;
rockot85dce0862015-11-13 01:33:59223
yzshen0b5628a2015-11-25 05:58:10224 DISALLOW_COPY_AND_ASSIGN(Binding);
rockot85dce0862015-11-13 01:33:59225};
226
227} // namespace mojo
228
229#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_