1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
dbus / exported_object.h [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DBUS_EXPORTED_OBJECT_H_
#define DBUS_EXPORTED_OBJECT_H_
#include <dbus/dbus.h>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "dbus/dbus_export.h"
#include "dbus/object_path.h"
namespace dbus {
class Bus;
class MethodCall;
class Response;
class Signal;
// ExportedObject is used to export objects and methods to other D-Bus
// clients.
//
// ExportedObject is a ref counted object, to ensure that |this| of the
// object is alive when callbacks referencing |this| are called.
class CHROME_DBUS_EXPORT ExportedObject
: public base::RefCountedThreadSafe<ExportedObject> {
public:
// Client code should use Bus::GetExportedObject() instead of this
// constructor.
ExportedObject(Bus* bus, const ObjectPath& object_path);
// Called to send a response from an exported method. |response| is the
// response message. Callers should pass nullptr in the event of an error that
// prevents the sending of a response.
using ResponseSender =
base::OnceCallback<void(std::unique_ptr<Response> response)>;
// Called when an exported method is called. |method_call| is the request
// message. |sender| is the callback that's used to send a response.
//
// |method_call| is owned by ExportedObject, hence client code should not
// delete |method_call|.
using MethodCallCallback =
base::RepeatingCallback<void(MethodCall* method_call,
ResponseSender sender)>;
// Called when method exporting is done.
// |success| indicates whether exporting was successful or not.
using OnExportedCallback =
base::OnceCallback<void(const std::string& interface_name,
const std::string& method_name,
bool success)>;
// Called when method unexporting is done.
// |success| indicates whether unexporting was successful or not.
using OnUnexportedCallback =
base::OnceCallback<void(const std::string& interface_name,
const std::string& method_name,
bool success)>;
// Exports the method specified by |interface_name| and |method_name|,
// and blocks until exporting is done. Returns true on success.
//
// |method_call_callback| will be called in the origin thread, when the
// exported method is called. As it's called in the origin thread,
// |method_callback| can safely reference objects in the origin thread
// (i.e. UI thread in most cases).
//
// IMPORTANT NOTE: You should export all methods before requesting a
// service name by Bus::RequestOwnership/AndBlock(). If you do it in the
// wrong order (i.e. request a service name then export methods), there
// will be a short time period where your service is unable to respond to
// method calls because these methods aren't yet exposed. This race is a
// real problem as clients may start calling methods of your service as
// soon as you acquire a service name, by watching the name owner change.
//
// BLOCKING CALL.
virtual bool ExportMethodAndBlock(
const std::string& interface_name,
const std::string& method_name,
const MethodCallCallback& method_call_callback);
// Unexports the method specified by |interface_name| and |method_name|,
// and blocks until unexporting is done. Returns true on success.
virtual bool UnexportMethodAndBlock(const std::string& interface_name,
const std::string& method_name);
// Requests to export the method specified by |interface_name| and
// |method_name|. See Also ExportMethodAndBlock().
//
// |on_exported_callback| is called when the method is exported or
// failed to be exported, in the origin thread.
//
// Must be called in the origin thread.
virtual void ExportMethod(const std::string& interface_name,
const std::string& method_name,
const MethodCallCallback& method_call_callback,
OnExportedCallback on_exported_callback);
// Requests to unexport the method specified by |interface_name| and
// |method_name|. See also UnexportMethodAndBlock().
//
// |on_unexported_callback| is called when the method is unexported or
// failed to be unexported, in the origin thread.
//
// Must be called in the origin thread.
virtual void UnexportMethod(const std::string& interface_name,
const std::string& method_name,
OnUnexportedCallback on_unexported_callback);
// Requests to send the signal from this object. The signal will be sent
// synchronously if this method is called from the message loop in the D-Bus
// thread and asynchronously otherwise.
virtual void SendSignal(Signal* signal);
// Unregisters the object from the bus. The Bus object will take care of
// unregistering so you don't have to do this manually.
//
// BLOCKING CALL.
virtual void Unregister();
protected:
// This is protected, so we can define sub classes.
virtual ~ExportedObject();
private:
friend class base::RefCountedThreadSafe<ExportedObject>;
// Helper function for ExportMethod().
void ExportMethodInternal(const std::string& interface_name,
const std::string& method_name,
const MethodCallCallback& method_call_callback,
OnExportedCallback exported_callback);
// Helper function for UnexportMethod().
void UnexportMethodInternal(const std::string& interface_name,
const std::string& method_name,
OnUnexportedCallback unexported_callback);
// Called when the object is exported.
void OnExported(OnExportedCallback on_exported_callback,
const std::string& interface_name,
const std::string& method_name,
bool success);
// Called when a method is unexported.
void OnUnexported(OnExportedCallback on_unexported_callback,
const std::string& interface_name,
const std::string& method_name,
bool success);
// Helper function for SendSignal().
void SendSignalInternal(DBusMessage* signal_message);
// Registers this object to the bus.
// Returns true on success, or the object is already registered.
//
// BLOCKING CALL.
bool Register();
// Handles the incoming request messages and dispatches to the exported
// methods.
DBusHandlerResult HandleMessage(DBusConnection* connection,
DBusMessage* raw_message);
// Runs the method. Helper function for HandleMessage().
void RunMethod(const MethodCallCallback& method_call_callback,
std::unique_ptr<MethodCall> method_call);
// Callback invoked by service provider to send a response to a method call.
// Can be called immediately from a MethodCallCallback to implement a
// synchronous service or called later to implement an asynchronous service.
void SendResponse(std::unique_ptr<MethodCall> method_call,
std::unique_ptr<Response> response);
// Called on completion of the method run from SendResponse().
// Takes ownership of |method_call| and |response|.
void OnMethodCompleted(std::unique_ptr<MethodCall> method_call,
std::unique_ptr<Response> response);
// Called when the object is unregistered.
void OnUnregistered(DBusConnection* connection);
// Redirects the function call to HandleMessage().
static DBusHandlerResult HandleMessageThunk(DBusConnection* connection,
DBusMessage* raw_message,
void* user_data);
// Redirects the function call to OnUnregistered().
static void OnUnregisteredThunk(DBusConnection* connection,
void* user_data);
scoped_refptr<Bus> bus_;
ObjectPath object_path_;
bool object_is_registered_;
// The method table where keys are absolute method names (i.e. interface
// name + method name), and values are the corresponding callbacks.
typedef std::map<std::string, MethodCallCallback> MethodTable;
MethodTable method_table_;
};
} // namespace dbus
#endif // DBUS_EXPORTED_OBJECT_H_