blob: 1616f33e79811fe2ec38c59601fe33afbc490fcf [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
95 // Completes a binding that was constructed with only an interface
rockot85dce0862015-11-13 01:33:5996 // implementation by removing the message pipe endpoint from |request| and
yzshen076d08762016-03-02 06:57:1497 // binding it to the previously specified implementation.
yzshenf5d48932016-04-22 23:18:3398 void Bind(InterfaceRequest<Interface> request,
99 scoped_refptr<base::SingleThreadTaskRunner> runner =
100 base::ThreadTaskRunnerHandle::Get()) {
Ken Rockot42472452017-05-12 05:37:03101 internal_state_.Bind(request.PassMessagePipe(), std::move(runner));
rockot85dce0862015-11-13 01:33:59102 }
103
rockot222e7dd2016-08-24 23:37:11104 // Adds a message filter to be notified of each incoming message before
105 // dispatch. If a filter returns |false| from Accept(), the message is not
106 // dispatched and the pipe is closed. Filters cannot be removed.
107 void AddFilter(std::unique_ptr<MessageReceiver> filter) {
108 DCHECK(is_bound());
109 internal_state_.AddFilter(std::move(filter));
110 }
111
yzshen1e8f6662015-12-11 01:37:50112 // Whether there are any associated interfaces running on the pipe currently.
113 bool HasAssociatedInterfaces() const {
114 return internal_state_.HasAssociatedInterfaces();
115 }
116
rockot85dce0862015-11-13 01:33:59117 // Stops processing incoming messages until
118 // ResumeIncomingMethodCallProcessing(), or WaitForIncomingMethodCall().
119 // Outgoing messages are still sent.
120 //
121 // No errors are detected on the message pipe while paused.
yzshen0b5628a2015-11-25 05:58:10122 //
yzshen1e8f6662015-12-11 01:37:50123 // This method may only be called if the object has been bound to a message
124 // pipe and there are no associated interfaces running.
rockot85dce0862015-11-13 01:33:59125 void PauseIncomingMethodCallProcessing() {
yzshen1e8f6662015-12-11 01:37:50126 CHECK(!HasAssociatedInterfaces());
yzshen0b5628a2015-11-25 05:58:10127 internal_state_.PauseIncomingMethodCallProcessing();
rockot85dce0862015-11-13 01:33:59128 }
129 void ResumeIncomingMethodCallProcessing() {
yzshen0b5628a2015-11-25 05:58:10130 internal_state_.ResumeIncomingMethodCallProcessing();
rockot85dce0862015-11-13 01:33:59131 }
132
133 // Blocks the calling thread until either a call arrives on the previously
134 // bound message pipe, the deadline is exceeded, or an error occurs. Returns
135 // true if a method was successfully read and dispatched.
yzshen0b5628a2015-11-25 05:58:10136 //
yzshen1e8f6662015-12-11 01:37:50137 // This method may only be called if the object has been bound to a message
sky66b7a5e2017-03-24 19:11:22138 // pipe. This returns once a message is received either on the master
139 // interface or any associated interfaces.
rockot85dce0862015-11-13 01:33:59140 bool WaitForIncomingMethodCall(
141 MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE) {
yzshen0b5628a2015-11-25 05:58:10142 return internal_state_.WaitForIncomingMethodCall(deadline);
rockot85dce0862015-11-13 01:33:59143 }
144
145 // Closes the message pipe that was previously bound. Put this object into a
146 // state where it can be rebound to a new pipe.
yzshen0b5628a2015-11-25 05:58:10147 void Close() { internal_state_.Close(); }
rockot85dce0862015-11-13 01:33:59148
yzshen24438d22016-09-13 17:03:53149 // Similar to the method above, but also specifies a disconnect reason.
150 void CloseWithReason(uint32_t custom_reason, const std::string& description) {
151 internal_state_.CloseWithReason(custom_reason, description);
152 }
153
rockot85dce0862015-11-13 01:33:59154 // Unbinds the underlying pipe from this binding and returns it so it can be
155 // used in another context, such as on another thread or with a different
156 // implementation. Put this object into a state where it can be rebound to a
157 // new pipe.
yzshen1e8f6662015-12-11 01:37:50158 //
159 // This method may only be called if the object has been bound to a message
160 // pipe and there are no associated interfaces running.
161 //
162 // TODO(yzshen): For now, users need to make sure there is no one holding
163 // on to associated interface endpoint handles at both sides of the
164 // message pipe in order to call this method. We need a way to forcefully
165 // invalidate associated interface endpoint handles.
yzshenb92c3dd2016-03-08 23:48:49166 InterfaceRequest<Interface> Unbind() {
yzshen1e8f6662015-12-11 01:37:50167 CHECK(!HasAssociatedInterfaces());
168 return internal_state_.Unbind();
169 }
rockot85dce0862015-11-13 01:33:59170
171 // Sets an error handler that will be called if a connection error occurs on
172 // the bound message pipe.
amistryf70387572015-12-17 05:23:43173 //
174 // This method may only be called after this Binding has been bound to a
175 // message pipe. The error handler will be reset when this Binding is unbound
176 // or closed.
rockota21316a2016-06-19 17:08:36177 void set_connection_error_handler(const base::Closure& error_handler) {
amistryf70387572015-12-17 05:23:43178 DCHECK(is_bound());
yzshen0b5628a2015-11-25 05:58:10179 internal_state_.set_connection_error_handler(error_handler);
rockot85dce0862015-11-13 01:33:59180 }
181
yzshen24438d22016-09-13 17:03:53182 void set_connection_error_with_reason_handler(
183 const ConnectionErrorWithReasonCallback& error_handler) {
184 DCHECK(is_bound());
185 internal_state_.set_connection_error_with_reason_handler(error_handler);
186 }
187
rockot85dce0862015-11-13 01:33:59188 // Returns the interface implementation that was previously specified. Caller
189 // does not take ownership.
yzshen0b5628a2015-11-25 05:58:10190 Interface* impl() { return internal_state_.impl(); }
rockot85dce0862015-11-13 01:33:59191
192 // Indicates whether the binding has been completed (i.e., whether a message
193 // pipe has been bound to the implementation).
yzshen0b5628a2015-11-25 05:58:10194 bool is_bound() const { return internal_state_.is_bound(); }
rockot85dce0862015-11-13 01:33:59195
196 // Returns the value of the handle currently bound to this Binding which can
197 // be used to make explicit Wait/WaitMany calls. Requires that the Binding be
198 // bound. Ownership of the handle is retained by the Binding, it is not
199 // transferred to the caller.
yzshen0b5628a2015-11-25 05:58:10200 MessagePipeHandle handle() const { return internal_state_.handle(); }
201
Marijn Kruisselbrink3325c22c2017-06-07 20:54:26202 // Reports the currently dispatching Message as bad and closes this binding.
203 // Note that this is only legal to call from directly within the stack frame
204 // of a message dispatch. If you need to do asynchronous work before you can
205 // determine the legitimacy of a message, use GetBadMessageCallback() and
206 // retain its result until you're ready to invoke or discard it.
207 void ReportBadMessage(const std::string& error) {
208 GetBadMessageCallback().Run(error);
209 }
210
211 // Acquires a callback which may be run to report the currently dispatching
212 // Message as bad and close this binding. Note that this is only legal to call
213 // from directly within the stack frame of a message dispatch, but the
214 // returned callback may be called exactly once any time thereafter to report
215 // the message as bad. This may only be called once per message. The returned
216 // callback must be called on the Binding's own thread.
217 ReportBadMessageCallback GetBadMessageCallback() {
218 return internal_state_.GetBadMessageCallback();
219 }
220
sammc462458f2016-09-01 09:52:58221 // Sends a no-op message on the underlying message pipe and runs the current
222 // message loop until its response is received. This can be used in tests to
223 // verify that no message was sent on a message pipe in response to some
224 // stimulus.
225 void FlushForTesting() { internal_state_.FlushForTesting(); }
226
rockot85dce0862015-11-13 01:33:59227 // Exposed for testing, should not generally be used.
yzshen0b5628a2015-11-25 05:58:10228 void EnableTestingMode() { internal_state_.EnableTestingMode(); }
rockot85dce0862015-11-13 01:33:59229
230 private:
yzshena87f4ac2016-11-30 19:03:20231 internal::BindingState<Interface, ImplRefTraits> internal_state_;
rockot85dce0862015-11-13 01:33:59232
yzshen0b5628a2015-11-25 05:58:10233 DISALLOW_COPY_AND_ASSIGN(Binding);
rockot85dce0862015-11-13 01:33:59234};
235
236} // namespace mojo
237
238#endif // MOJO_PUBLIC_CPP_BINDINGS_BINDING_H_