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_EXPORTED_OBJECT_H_
6#define DBUS_EXPORTED_OBJECT_H_
7
8#include <dbus/dbus.h>
9
10#include <map>
11#include <string>
12#include <utility>
13
14#include "base/callback.h"
15#include "base/memory/ref_counted.h"
16#include "base/synchronization/waitable_event.h"
17#include "base/threading/platform_thread.h"
18#include "base/time/time.h"
19#include "dbus/dbus_export.h"
20#include "dbus/object_path.h"
21
22namespace dbus {
23
24class Bus;
25class MethodCall;
26class Response;
27class Signal;
28
29// ExportedObject is used to export objects and methods to other D-Bus
30// clients.
31//
32// ExportedObject is a ref counted object, to ensure that |this| of the
33// object is alive when callbacks referencing |this| are called.
34class CHROME_DBUS_EXPORT ExportedObject
35    : public base::RefCountedThreadSafe<ExportedObject> {
36 public:
37  // Client code should use Bus::GetExportedObject() instead of this
38  // constructor.
39  ExportedObject(Bus* bus, const ObjectPath& object_path);
40
41  // Called to send a response from an exported method. |response| is the
42  // response message. Callers should pass NULL in the event of an error that
43  // prevents the sending of a response.
44  typedef base::Callback<void (scoped_ptr<Response> response)> ResponseSender;
45
46  // Called when an exported method is called. |method_call| is the request
47  // message. |sender| is the callback that's used to send a response.
48  //
49  // |method_call| is owned by ExportedObject, hence client code should not
50  // delete |method_call|.
51  typedef base::Callback<void (MethodCall* method_call, ResponseSender sender)>
52      MethodCallCallback;
53
54  // Called when method exporting is done.
55  // |success| indicates whether exporting was successful or not.
56  typedef base::Callback<void (const std::string& interface_name,
57                               const std::string& method_name,
58                               bool success)>
59      OnExportedCallback;
60
61  // Exports the method specified by |interface_name| and |method_name|,
62  // and blocks until exporting is done. Returns true on success.
63  //
64  // |method_call_callback| will be called in the origin thread, when the
65  // exported method is called. As it's called in the origin thread,
66  // |method_callback| can safely reference objects in the origin thread
67  // (i.e. UI thread in most cases).
68  //
69  // BLOCKING CALL.
70  virtual bool ExportMethodAndBlock(const std::string& interface_name,
71                                    const std::string& method_name,
72                                    MethodCallCallback method_call_callback);
73
74  // Requests to export the method specified by |interface_name| and
75  // |method_name|. See Also ExportMethodAndBlock().
76  //
77  // |on_exported_callback| is called when the method is exported or
78  // failed to be exported, in the origin thread.
79  //
80  // Must be called in the origin thread.
81  virtual void ExportMethod(const std::string& interface_name,
82                            const std::string& method_name,
83                            MethodCallCallback method_call_callback,
84                            OnExportedCallback on_exported_callback);
85
86  // Requests to send the signal from this object. The signal will be sent
87  // asynchronously from the message loop in the D-Bus thread.
88  virtual void SendSignal(Signal* signal);
89
90  // Unregisters the object from the bus. The Bus object will take care of
91  // unregistering so you don't have to do this manually.
92  //
93  // BLOCKING CALL.
94  virtual void Unregister();
95
96 protected:
97  // This is protected, so we can define sub classes.
98  virtual ~ExportedObject();
99
100 private:
101  friend class base::RefCountedThreadSafe<ExportedObject>;
102
103  // Helper function for ExportMethod().
104  void ExportMethodInternal(const std::string& interface_name,
105                            const std::string& method_name,
106                            MethodCallCallback method_call_callback,
107                            OnExportedCallback exported_callback);
108
109  // Called when the object is exported.
110  void OnExported(OnExportedCallback on_exported_callback,
111                  const std::string& interface_name,
112                  const std::string& method_name,
113                  bool success);
114
115  // Helper function for SendSignal().
116  void SendSignalInternal(base::TimeTicks start_time,
117                          DBusMessage* signal_message);
118
119  // Registers this object to the bus.
120  // Returns true on success, or the object is already registered.
121  //
122  // BLOCKING CALL.
123  bool Register();
124
125  // Handles the incoming request messages and dispatches to the exported
126  // methods.
127  DBusHandlerResult HandleMessage(DBusConnection* connection,
128                                  DBusMessage* raw_message);
129
130  // Runs the method. Helper function for HandleMessage().
131  void RunMethod(MethodCallCallback method_call_callback,
132                 scoped_ptr<MethodCall> method_call,
133                 base::TimeTicks start_time);
134
135  // Callback invoked by service provider to send a response to a method call.
136  // Can be called immediately from a MethodCallCallback to implement a
137  // synchronous service or called later to implement an asynchronous service.
138  void SendResponse(base::TimeTicks start_time,
139                    scoped_ptr<MethodCall> method_call,
140                    scoped_ptr<Response> response);
141
142  // Called on completion of the method run from SendResponse().
143  // Takes ownership of |method_call| and |response|.
144  void OnMethodCompleted(scoped_ptr<MethodCall> method_call,
145                         scoped_ptr<Response> response,
146                         base::TimeTicks start_time);
147
148  // Called when the object is unregistered.
149  void OnUnregistered(DBusConnection* connection);
150
151  // Redirects the function call to HandleMessage().
152  static DBusHandlerResult HandleMessageThunk(DBusConnection* connection,
153                                              DBusMessage* raw_message,
154                                              void* user_data);
155
156  // Redirects the function call to OnUnregistered().
157  static void OnUnregisteredThunk(DBusConnection* connection,
158                                  void* user_data);
159
160  scoped_refptr<Bus> bus_;
161  ObjectPath object_path_;
162  bool object_is_registered_;
163
164  // The method table where keys are absolute method names (i.e. interface
165  // name + method name), and values are the corresponding callbacks.
166  typedef std::map<std::string, MethodCallCallback> MethodTable;
167  MethodTable method_table_;
168};
169
170}  // namespace dbus
171
172#endif  // DBUS_EXPORTED_OBJECT_H_
173