1// Copyright (c) 2012 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 DBUS_OBJECT_PROXY_H_
6#define DBUS_OBJECT_PROXY_H_
7
8#include <dbus/dbus.h>
9
10#include <map>
11#include <set>
12#include <string>
13#include <vector>
14
15#include "base/callback.h"
16#include "base/macros.h"
17#include "base/memory/ref_counted.h"
18#include "base/strings/string_piece.h"
19#include "base/time/time.h"
20#include "dbus/dbus_export.h"
21#include "dbus/object_path.h"
22
23namespace dbus {
24
25class Bus;
26class ErrorResponse;
27class MethodCall;
28class Response;
29class ScopedDBusError;
30class Signal;
31
32// ObjectProxy is used to communicate with remote objects, mainly for
33// calling methods of these objects.
34//
35// ObjectProxy is a ref counted object, to ensure that |this| of the
36// object is alive when callbacks referencing |this| are called; the
37// bus always holds at least one of those references so object proxies
38// always last as long as the bus that created them.
39class CHROME_DBUS_EXPORT ObjectProxy
40    : public base::RefCountedThreadSafe<ObjectProxy> {
41 public:
42  // Client code should use Bus::GetObjectProxy() or
43  // Bus::GetObjectProxyWithOptions() instead of this constructor.
44  ObjectProxy(Bus* bus,
45              const std::string& service_name,
46              const ObjectPath& object_path,
47              int options);
48
49  // Options to be OR-ed together when calling Bus::GetObjectProxyWithOptions().
50  // Set the IGNORE_SERVICE_UNKNOWN_ERRORS option to silence logging of
51  // org.freedesktop.DBus.Error.ServiceUnknown errors and
52  // org.freedesktop.DBus.Error.ObjectUnknown errors.
53  enum Options {
54    DEFAULT_OPTIONS = 0,
55    IGNORE_SERVICE_UNKNOWN_ERRORS = 1 << 0
56  };
57
58  // Special timeout constants.
59  //
60  // The constants correspond to DBUS_TIMEOUT_USE_DEFAULT and
61  // DBUS_TIMEOUT_INFINITE. Here we use literal numbers instead of these
62  // macros as these aren't defined with D-Bus earlier than 1.4.12.
63  enum {
64    TIMEOUT_USE_DEFAULT = -1,
65    TIMEOUT_INFINITE = 0x7fffffff,
66  };
67
68  // Called when an error response is returned or no response is returned.
69  // Used for CallMethodWithErrorCallback().
70  typedef base::Callback<void(ErrorResponse*)> ErrorCallback;
71
72  // Called when the response is returned. Used for CallMethod().
73  typedef base::Callback<void(Response*)> ResponseCallback;
74
75  // Called when a signal is received. Signal* is the incoming signal.
76  typedef base::Callback<void (Signal*)> SignalCallback;
77
78  // Called when NameOwnerChanged signal is received.
79  typedef base::Callback<void(
80      const std::string& old_owner,
81      const std::string& new_owner)> NameOwnerChangedCallback;
82
83  // Called when the service becomes available.
84  typedef base::Callback<void(
85      bool service_is_available)> WaitForServiceToBeAvailableCallback;
86
87  // Called when the object proxy is connected to the signal.
88  // Parameters:
89  // - the interface name.
90  // - the signal name.
91  // - whether it was successful or not.
92  typedef base::Callback<void (const std::string&, const std::string&, bool)>
93      OnConnectedCallback;
94
95  // Calls the method of the remote object and blocks until the response
96  // is returned. Returns NULL on error with the error details specified
97  // in the |error| object.
98  //
99  // BLOCKING CALL.
100  virtual scoped_ptr<Response> CallMethodAndBlockWithErrorDetails(
101      MethodCall* method_call,
102      int timeout_ms,
103      ScopedDBusError* error);
104
105  // Calls the method of the remote object and blocks until the response
106  // is returned. Returns NULL on error.
107  //
108  // BLOCKING CALL.
109  virtual scoped_ptr<Response> CallMethodAndBlock(MethodCall* method_call,
110                                                  int timeout_ms);
111
112  // Requests to call the method of the remote object.
113  //
114  // |callback| will be called in the origin thread, once the method call
115  // is complete. As it's called in the origin thread, |callback| can
116  // safely reference objects in the origin thread (i.e. UI thread in most
117  // cases). If the caller is not interested in the response from the
118  // method (i.e. calling a method that does not return a value),
119  // EmptyResponseCallback() can be passed to the |callback| parameter.
120  //
121  // If the method call is successful, a pointer to Response object will
122  // be passed to the callback. If unsuccessful, NULL will be passed to
123  // the callback.
124  //
125  // Must be called in the origin thread.
126  virtual void CallMethod(MethodCall* method_call,
127                          int timeout_ms,
128                          ResponseCallback callback);
129
130  // Requests to call the method of the remote object.
131  //
132  // |callback| and |error_callback| will be called in the origin thread, once
133  // the method call is complete. As it's called in the origin thread,
134  // |callback| can safely reference objects in the origin thread (i.e.
135  // UI thread in most cases). If the caller is not interested in the response
136  // from the method (i.e. calling a method that does not return a value),
137  // EmptyResponseCallback() can be passed to the |callback| parameter.
138  //
139  // If the method call is successful, a pointer to Response object will
140  // be passed to the callback. If unsuccessful, the error callback will be
141  // called and a pointer to ErrorResponse object will be passed to the error
142  // callback if available, otherwise NULL will be passed.
143  //
144  // Must be called in the origin thread.
145  virtual void CallMethodWithErrorCallback(MethodCall* method_call,
146                                           int timeout_ms,
147                                           ResponseCallback callback,
148                                           ErrorCallback error_callback);
149
150  // Requests to connect to the signal from the remote object.
151  //
152  // |signal_callback| will be called in the origin thread, when the
153  // signal is received from the remote object. As it's called in the
154  // origin thread, |signal_callback| can safely reference objects in the
155  // origin thread (i.e. UI thread in most cases).
156  //
157  // |on_connected_callback| is called when the object proxy is connected
158  // to the signal, or failed to be connected, in the origin thread.
159  //
160  // If a SignalCallback has already been registered for the given
161  // |interface_name| and |signal_name|, |signal_callback| will be
162  // added to the list of callbacks for |interface_name| and
163  // |signal_name|.
164  //
165  // Must be called in the origin thread.
166  virtual void ConnectToSignal(const std::string& interface_name,
167                               const std::string& signal_name,
168                               SignalCallback signal_callback,
169                               OnConnectedCallback on_connected_callback);
170
171  // Sets a callback for "NameOwnerChanged" signal. The callback is called on
172  // the origin thread when D-Bus system sends "NameOwnerChanged" for the name
173  // represented by |service_name_|.
174  virtual void SetNameOwnerChangedCallback(NameOwnerChangedCallback callback);
175
176  // Runs the callback as soon as the service becomes available.
177  virtual void WaitForServiceToBeAvailable(
178      WaitForServiceToBeAvailableCallback callback);
179
180  // Detaches from the remote object. The Bus object will take care of
181  // detaching so you don't have to do this manually.
182  //
183  // BLOCKING CALL.
184  virtual void Detach();
185
186  const ObjectPath& object_path() const { return object_path_; }
187
188  // Returns an empty callback that does nothing. Can be used for
189  // CallMethod().
190  static ResponseCallback EmptyResponseCallback();
191
192 protected:
193  // This is protected, so we can define sub classes.
194  virtual ~ObjectProxy();
195
196 private:
197  friend class base::RefCountedThreadSafe<ObjectProxy>;
198
199  // Struct of data we'll be passing from StartAsyncMethodCall() to
200  // OnPendingCallIsCompleteThunk().
201  struct OnPendingCallIsCompleteData {
202    OnPendingCallIsCompleteData(ObjectProxy* in_object_proxy,
203                                ResponseCallback in_response_callback,
204                                ErrorCallback error_callback,
205                                base::TimeTicks start_time);
206    ~OnPendingCallIsCompleteData();
207
208    ObjectProxy* object_proxy;
209    ResponseCallback response_callback;
210    ErrorCallback error_callback;
211    base::TimeTicks start_time;
212  };
213
214  // Starts the async method call. This is a helper function to implement
215  // CallMethod().
216  void StartAsyncMethodCall(int timeout_ms,
217                            DBusMessage* request_message,
218                            ResponseCallback response_callback,
219                            ErrorCallback error_callback,
220                            base::TimeTicks start_time);
221
222  // Called when the pending call is complete.
223  void OnPendingCallIsComplete(DBusPendingCall* pending_call,
224                               ResponseCallback response_callback,
225                               ErrorCallback error_callback,
226                               base::TimeTicks start_time);
227
228  // Runs the response callback with the given response object.
229  void RunResponseCallback(ResponseCallback response_callback,
230                           ErrorCallback error_callback,
231                           base::TimeTicks start_time,
232                           DBusMessage* response_message);
233
234  // Redirects the function call to OnPendingCallIsComplete().
235  static void OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call,
236                                           void* user_data);
237
238  // Connects to NameOwnerChanged signal.
239  bool ConnectToNameOwnerChangedSignal();
240
241  // Helper function for ConnectToSignal().
242  bool ConnectToSignalInternal(const std::string& interface_name,
243                               const std::string& signal_name,
244                               SignalCallback signal_callback);
245
246  // Helper function for WaitForServiceToBeAvailable().
247  void WaitForServiceToBeAvailableInternal();
248
249  // Handles the incoming request messages and dispatches to the signal
250  // callbacks.
251  DBusHandlerResult HandleMessage(DBusConnection* connection,
252                                  DBusMessage* raw_message);
253
254  // Runs the method. Helper function for HandleMessage().
255  void RunMethod(base::TimeTicks start_time,
256                 std::vector<SignalCallback> signal_callbacks,
257                 Signal* signal);
258
259  // Redirects the function call to HandleMessage().
260  static DBusHandlerResult HandleMessageThunk(DBusConnection* connection,
261                                              DBusMessage* raw_message,
262                                              void* user_data);
263
264  // Helper method for logging response errors appropriately.
265  void LogMethodCallFailure(const base::StringPiece& interface_name,
266                            const base::StringPiece& method_name,
267                            const base::StringPiece& error_name,
268                            const base::StringPiece& error_message) const;
269
270  // Used as ErrorCallback by CallMethod().
271  void OnCallMethodError(const std::string& interface_name,
272                         const std::string& method_name,
273                         ResponseCallback response_callback,
274                         ErrorResponse* error_response);
275
276  // Adds the match rule to the bus and associate the callback with the signal.
277  bool AddMatchRuleWithCallback(const std::string& match_rule,
278                                const std::string& absolute_signal_name,
279                                SignalCallback signal_callback);
280
281  // Adds the match rule to the bus so that HandleMessage can see the signal.
282  bool AddMatchRuleWithoutCallback(const std::string& match_rule,
283                                   const std::string& absolute_signal_name);
284
285  // Calls D-Bus's GetNameOwner method synchronously to update
286  // |service_name_owner_| with the current owner of |service_name_|.
287  //
288  // BLOCKING CALL.
289  void UpdateNameOwnerAndBlock();
290
291  // Handles NameOwnerChanged signal from D-Bus's special message bus.
292  DBusHandlerResult HandleNameOwnerChanged(scoped_ptr<dbus::Signal> signal);
293
294  // Runs |name_owner_changed_callback_|.
295  void RunNameOwnerChangedCallback(const std::string& old_owner,
296                                   const std::string& new_owner);
297
298  // Runs |wait_for_service_to_be_available_callbacks_|.
299  void RunWaitForServiceToBeAvailableCallbacks(bool service_is_available);
300
301  scoped_refptr<Bus> bus_;
302  std::string service_name_;
303  ObjectPath object_path_;
304
305  // The method table where keys are absolute signal names (i.e. interface
306  // name + signal name), and values are lists of the corresponding callbacks.
307  typedef std::map<std::string, std::vector<SignalCallback> > MethodTable;
308  MethodTable method_table_;
309
310  // The callback called when NameOwnerChanged signal is received.
311  NameOwnerChangedCallback name_owner_changed_callback_;
312
313  // Called when the service becomes available.
314  std::vector<WaitForServiceToBeAvailableCallback>
315      wait_for_service_to_be_available_callbacks_;
316
317  std::set<std::string> match_rules_;
318
319  const bool ignore_service_unknown_errors_;
320
321  // Known name owner of the well-known bus name represented by |service_name_|.
322  std::string service_name_owner_;
323
324  std::set<DBusPendingCall*> pending_calls_;
325
326  DISALLOW_COPY_AND_ASSIGN(ObjectProxy);
327};
328
329}  // namespace dbus
330
331#endif  // DBUS_OBJECT_PROXY_H_
332