summaryrefslogtreecommitdiffstats
path: root/dbus/exported_object.h
blob: c897ea6a5e9b1de5940d17f3701591e34a243202 (plain)
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
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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 <string>
#include <utility>

#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time.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 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 a NULL Response* in the event
  // of an error that prevents the sending of a response.
  typedef base::Callback<void (Response*)> ResponseSender;

  // Called when an exported method is called. MethodCall* is the request
  // message. ResponseSender is the callback that should be used to send a
  // response.
  typedef base::Callback<void (MethodCall*, ResponseSender)> MethodCallCallback;

  // Called when method exporting is done.
  // Parameters:
  // - the interface name.
  // - the method name.
  // - whether exporting was successful or not.
  typedef base::Callback<void (const std::string&, const std::string&, bool)>
      OnExportedCallback;

  // 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).
  //
  // BLOCKING CALL.
  virtual bool ExportMethodAndBlock(const std::string& interface_name,
                                    const std::string& method_name,
                                    MethodCallCallback method_call_callback);

  // 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,
                            MethodCallCallback method_call_callback,
                            OnExportedCallback on_exported_callback);

  // Requests to send the signal from this object. The signal will be sent
  // asynchronously from the message loop in the D-Bus thread.
  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,
                            MethodCallCallback method_call_callback,
                            OnExportedCallback exported_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);

  // Helper function for SendSignal().
  void SendSignalInternal(base::TimeTicks start_time,
                          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(MethodCallCallback method_call_callback,
                 MethodCall* method_call,
                 base::TimeTicks start_time);

  // 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(base::TimeTicks start_time,
                    MethodCall* method_call,
                    Response* response);

  // Called on completion of the method run from SendResponse().
  // Takes ownership of |method_call| and |response|.
  void OnMethodCompleted(MethodCall* method_call,
                         Response* response,
                         base::TimeTicks start_time);

  // 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_