• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium OS 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 // DBusObject is a special helper class that simplifies the implementation of
6 // D-Bus objects in C++. It provides an easy way to define interfaces with
7 // methods and properties and offloads a lot of work to register the object and
8 // all of its interfaces, to marshal method calls (by converting D-Bus method
9 // parameters to native C++ types and invoking native method handlers), etc.
10 
11 // The basic usage pattern of this class is as follows:
12 /*
13 class MyDbusObject {
14  public:
15   MyDbusObject(ExportedObjectManager* object_manager,
16                const scoped_refptr<dbus::Bus>& bus)
17       : dbus_object_(object_manager, bus,
18                      dbus::ObjectPath("/org/chromium/my_obj")) {}
19 
20   void Init(const AsyncEventSequencer::CompletionAction& callback) {
21     DBusInterface* my_interface =
22         dbus_object_.AddOrGetInterface("org.chromium.MyInterface");
23     my_interface->AddSimpleMethodHandler("Method1", this,
24                                          &MyDbusObject::Method1);
25     my_interface->AddSimpleMethodHandlerWithError("Method2", this,
26                                                   &MyDbusObject::Method2);
27     my_interface->AddMethodHandler("Method3", this, &MyDbusObject::Method3);
28     my_interface->AddProperty("Property1", &prop1_);
29     my_interface->AddProperty("Property2", &prop2_);
30     prop1_.SetValue("prop1_value");
31     prop2_.SetValue(50);
32     // Register the object by exporting its methods and properties and
33     // exposing them to D-Bus clients.
34     dbus_object_.RegisterAsync(callback);
35   }
36 
37  private:
38   DBusObject dbus_object_;
39 
40   // Make sure the properties outlive the DBusObject they are registered with.
41   brillo::dbus_utils::ExportedProperty<std::string> prop1_;
42   brillo::dbus_utils::ExportedProperty<int> prop2_;
43   int Method1() { return 5; }
44   bool Method2(brillo::ErrorPtr* error, const std::string& message);
45   void Method3(std::unique_ptr<DBusMethodResponse<int_32>> response,
46                const std::string& message) {
47     if (message.empty()) {
48        response->ReplyWithError(brillo::errors::dbus::kDomain,
49                                 DBUS_ERROR_INVALID_ARGS,
50                                 "Message string cannot be empty");
51        return;
52     }
53     int32_t message_len = message.length();
54     response->Return(message_len);
55   }
56 
57   DISALLOW_COPY_AND_ASSIGN(MyDbusObject);
58 };
59 */
60 
61 #ifndef LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_H_
62 #define LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_H_
63 
64 #include <map>
65 #include <string>
66 
67 #include <base/bind.h>
68 #include <base/callback_helpers.h>
69 #include <base/macros.h>
70 #include <base/memory/weak_ptr.h>
71 #include <brillo/brillo_export.h>
72 #include <brillo/dbus/async_event_sequencer.h>
73 #include <brillo/dbus/dbus_object_internal_impl.h>
74 #include <brillo/dbus/dbus_signal.h>
75 #include <brillo/dbus/exported_property_set.h>
76 #include <brillo/errors/error.h>
77 #include <dbus/bus.h>
78 #include <dbus/exported_object.h>
79 #include <dbus/message.h>
80 #include <dbus/object_path.h>
81 
82 namespace brillo {
83 namespace dbus_utils {
84 
85 class ExportedObjectManager;
86 class ExportedPropertyBase;
87 class DBusObject;
88 
89 // This is an implementation proxy class for a D-Bus interface of an object.
90 // The important functionality for the users is the ability to add D-Bus method
91 // handlers and define D-Bus object properties. This is achieved by using one
92 // of the overload of AddSimpleMethodHandler()/AddMethodHandler() and
93 // AddProperty() respectively.
94 // There are three overloads for DBusInterface::AddSimpleMethodHandler() and
95 // AddMethodHandler() each:
96 //  1. That takes a handler as base::Callback
97 //  2. That takes a static function
98 //  3. That takes a class instance pointer and a class member function
99 // The signature of the handler for AddSimpleMethodHandler must be one of:
100 //    R(Args... args)                     [IN only]
101 //    void(Args... args)                  [IN/OUT]
102 // The signature of the handler for AddSimpleMethodHandlerWithError must be:
103 //    bool(ErrorPtr* error, Args... args) [IN/OUT]
104 // The signature of the handler for AddSimpleMethodHandlerWithErrorAndMessage:
105 //    bool(ErrorPtr* error, dbus::Message* msg, Args... args) [IN/OUT]
106 // The signature of the handler for AddMethodHandler must be:
107 //    void(std::unique_ptr<DBusMethodResponse<T...>> response,
108 //         Args... args) [IN]
109 // The signature of the handler for AddMethodHandlerWithMessage must be:
110 //    void(std::unique_ptr<DBusMethodResponse<T...>> response,
111 //         dbus::Message* msg, Args... args) [IN]
112 // There is also an AddRawMethodHandler() call that lets provide a custom
113 // handler that can parse its own input parameter and construct a custom
114 // response.
115 // The signature of the handler for AddRawMethodHandler must be:
116 //    void(dbus::MethodCall* method_call, ResponseSender sender)
117 class BRILLO_EXPORT DBusInterface final {
118  public:
119   DBusInterface(DBusObject* dbus_object, const std::string& interface_name);
120 
121   // Register sync DBus method handler for |method_name| as base::Callback.
122   template<typename R, typename... Args>
AddSimpleMethodHandler(const std::string & method_name,const base::Callback<R (Args...)> & handler)123   inline void AddSimpleMethodHandler(
124       const std::string& method_name,
125       const base::Callback<R(Args...)>& handler) {
126     Handler<SimpleDBusInterfaceMethodHandler<R, Args...>>::Add(
127         this, method_name, handler);
128   }
129 
130   // Register sync D-Bus method handler for |method_name| as a static
131   // function.
132   template<typename R, typename... Args>
AddSimpleMethodHandler(const std::string & method_name,R (* handler)(Args...))133   inline void AddSimpleMethodHandler(const std::string& method_name,
134                                      R(*handler)(Args...)) {
135     Handler<SimpleDBusInterfaceMethodHandler<R, Args...>>::Add(
136         this, method_name, base::Bind(handler));
137   }
138 
139   // Register sync D-Bus method handler for |method_name| as a class member
140   // function.
141   template<typename Instance, typename Class, typename R, typename... Args>
AddSimpleMethodHandler(const std::string & method_name,Instance instance,R (Class::* handler)(Args...))142   inline void AddSimpleMethodHandler(const std::string& method_name,
143                                      Instance instance,
144                                      R(Class::*handler)(Args...)) {
145     Handler<SimpleDBusInterfaceMethodHandler<R, Args...>>::Add(
146         this, method_name, base::Bind(handler, instance));
147   }
148 
149   // Same as above but for const-method of a class.
150   template<typename Instance, typename Class, typename R, typename... Args>
AddSimpleMethodHandler(const std::string & method_name,Instance instance,R (Class::* handler)(Args...)const)151   inline void AddSimpleMethodHandler(const std::string& method_name,
152                                      Instance instance,
153                                      R(Class::*handler)(Args...) const) {
154     Handler<SimpleDBusInterfaceMethodHandler<R, Args...>>::Add(
155         this, method_name, base::Bind(handler, instance));
156   }
157 
158   // Register sync DBus method handler for |method_name| as base::Callback.
159   template<typename... Args>
AddSimpleMethodHandlerWithError(const std::string & method_name,const base::Callback<bool (ErrorPtr *,Args...)> & handler)160   inline void AddSimpleMethodHandlerWithError(
161       const std::string& method_name,
162       const base::Callback<bool(ErrorPtr*, Args...)>& handler) {
163     Handler<SimpleDBusInterfaceMethodHandlerWithError<Args...>>::Add(
164         this, method_name, handler);
165   }
166 
167   // Register sync D-Bus method handler for |method_name| as a static
168   // function.
169   template<typename... Args>
AddSimpleMethodHandlerWithError(const std::string & method_name,bool (* handler)(ErrorPtr *,Args...))170   inline void AddSimpleMethodHandlerWithError(
171       const std::string& method_name,
172       bool(*handler)(ErrorPtr*, Args...)) {
173     Handler<SimpleDBusInterfaceMethodHandlerWithError<Args...>>::Add(
174         this, method_name, base::Bind(handler));
175   }
176 
177   // Register sync D-Bus method handler for |method_name| as a class member
178   // function.
179   template<typename Instance, typename Class, typename... Args>
AddSimpleMethodHandlerWithError(const std::string & method_name,Instance instance,bool (Class::* handler)(ErrorPtr *,Args...))180   inline void AddSimpleMethodHandlerWithError(
181       const std::string& method_name,
182       Instance instance,
183       bool(Class::*handler)(ErrorPtr*, Args...)) {
184     Handler<SimpleDBusInterfaceMethodHandlerWithError<Args...>>::Add(
185         this, method_name, base::Bind(handler, instance));
186   }
187 
188   // Same as above but for const-method of a class.
189   template<typename Instance, typename Class, typename... Args>
AddSimpleMethodHandlerWithError(const std::string & method_name,Instance instance,bool (Class::* handler)(ErrorPtr *,Args...)const)190   inline void AddSimpleMethodHandlerWithError(
191       const std::string& method_name,
192       Instance instance,
193       bool(Class::*handler)(ErrorPtr*, Args...) const) {
194     Handler<SimpleDBusInterfaceMethodHandlerWithError<Args...>>::Add(
195         this, method_name, base::Bind(handler, instance));
196   }
197 
198   // Register sync DBus method handler for |method_name| as base::Callback.
199   // Passing the method sender as a first parameter to the callback.
200   template<typename... Args>
AddSimpleMethodHandlerWithErrorAndMessage(const std::string & method_name,const base::Callback<bool (ErrorPtr *,dbus::Message *,Args...)> & handler)201   inline void AddSimpleMethodHandlerWithErrorAndMessage(
202       const std::string& method_name,
203       const base::Callback<bool(ErrorPtr*, dbus::Message*, Args...)>&
204           handler) {
205     Handler<SimpleDBusInterfaceMethodHandlerWithErrorAndMessage<Args...>>::Add(
206         this, method_name, handler);
207   }
208 
209   // Register sync D-Bus method handler for |method_name| as a static
210   // function. Passing the method D-Bus message as the second parameter to the
211   // callback.
212   template<typename... Args>
AddSimpleMethodHandlerWithErrorAndMessage(const std::string & method_name,bool (* handler)(ErrorPtr *,dbus::Message *,Args...))213   inline void AddSimpleMethodHandlerWithErrorAndMessage(
214       const std::string& method_name,
215       bool(*handler)(ErrorPtr*, dbus::Message*, Args...)) {
216     Handler<SimpleDBusInterfaceMethodHandlerWithErrorAndMessage<Args...>>::Add(
217         this, method_name, base::Bind(handler));
218   }
219 
220   // Register sync D-Bus method handler for |method_name| as a class member
221   // function. Passing the method D-Bus message as the second parameter to the
222   // callback.
223   template<typename Instance, typename Class, typename... Args>
AddSimpleMethodHandlerWithErrorAndMessage(const std::string & method_name,Instance instance,bool (Class::* handler)(ErrorPtr *,dbus::Message *,Args...))224   inline void AddSimpleMethodHandlerWithErrorAndMessage(
225       const std::string& method_name,
226       Instance instance,
227       bool(Class::*handler)(ErrorPtr*, dbus::Message*, Args...)) {
228     Handler<SimpleDBusInterfaceMethodHandlerWithErrorAndMessage<Args...>>::Add(
229         this, method_name, base::Bind(handler, instance));
230   }
231 
232   // Same as above but for const-method of a class.
233   template<typename Instance, typename Class, typename... Args>
AddSimpleMethodHandlerWithErrorAndMessage(const std::string & method_name,Instance instance,bool (Class::* handler)(ErrorPtr *,dbus::Message *,Args...)const)234   inline void AddSimpleMethodHandlerWithErrorAndMessage(
235       const std::string& method_name,
236       Instance instance,
237       bool(Class::*handler)(ErrorPtr*, dbus::Message*, Args...) const) {
238     Handler<SimpleDBusInterfaceMethodHandlerWithErrorAndMessage<Args...>>::Add(
239         this, method_name, base::Bind(handler, instance));
240   }
241 
242   // Register an async DBus method handler for |method_name| as base::Callback.
243   template<typename Response, typename... Args>
AddMethodHandler(const std::string & method_name,const base::Callback<void (std::unique_ptr<Response>,Args...)> & handler)244   inline void AddMethodHandler(
245       const std::string& method_name,
246       const base::Callback<void(std::unique_ptr<Response>, Args...)>& handler) {
247     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
248                   "Response must be DBusMethodResponse<T...>");
249     Handler<DBusInterfaceMethodHandler<Response, Args...>>::Add(
250         this, method_name, handler);
251   }
252 
253   // Register an async D-Bus method handler for |method_name| as a static
254   // function.
255   template<typename Response, typename... Args>
AddMethodHandler(const std::string & method_name,void (* handler)(std::unique_ptr<Response>,Args...))256   inline void AddMethodHandler(
257       const std::string& method_name,
258       void (*handler)(std::unique_ptr<Response>, Args...)) {
259     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
260                   "Response must be DBusMethodResponse<T...>");
261     Handler<DBusInterfaceMethodHandler<Response, Args...>>::Add(
262         this, method_name, base::Bind(handler));
263   }
264 
265   // Register an async D-Bus method handler for |method_name| as a class member
266   // function.
267   template<typename Response,
268            typename Instance,
269            typename Class,
270            typename... Args>
AddMethodHandler(const std::string & method_name,Instance instance,void (Class::* handler)(std::unique_ptr<Response>,Args...))271   inline void AddMethodHandler(
272       const std::string& method_name,
273       Instance instance,
274       void(Class::*handler)(std::unique_ptr<Response>, Args...)) {
275     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
276                   "Response must be DBusMethodResponse<T...>");
277     Handler<DBusInterfaceMethodHandler<Response, Args...>>::Add(
278         this, method_name, base::Bind(handler, instance));
279   }
280 
281   // Same as above but for const-method of a class.
282   template<typename Response,
283            typename Instance,
284            typename Class,
285            typename... Args>
AddMethodHandler(const std::string & method_name,Instance instance,void (Class::* handler)(std::unique_ptr<Response>,Args...)const)286   inline void AddMethodHandler(
287       const std::string& method_name,
288       Instance instance,
289       void(Class::*handler)(std::unique_ptr<Response>, Args...) const) {
290     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
291                   "Response must be DBusMethodResponse<T...>");
292     Handler<DBusInterfaceMethodHandler<Response, Args...>>::Add(
293         this, method_name, base::Bind(handler, instance));
294   }
295 
296   // Register an async DBus method handler for |method_name| as base::Callback.
297   template<typename Response, typename... Args>
AddMethodHandlerWithMessage(const std::string & method_name,const base::Callback<void (std::unique_ptr<Response>,dbus::Message *,Args...)> & handler)298   inline void AddMethodHandlerWithMessage(
299       const std::string& method_name,
300       const base::Callback<void(std::unique_ptr<Response>, dbus::Message*,
301                                 Args...)>& handler) {
302     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
303                   "Response must be DBusMethodResponse<T...>");
304     Handler<DBusInterfaceMethodHandlerWithMessage<Response, Args...>>::Add(
305         this, method_name, handler);
306   }
307 
308   // Register an async D-Bus method handler for |method_name| as a static
309   // function.
310   template<typename Response, typename... Args>
AddMethodHandlerWithMessage(const std::string & method_name,void (* handler)(std::unique_ptr<Response>,dbus::Message *,Args...))311   inline void AddMethodHandlerWithMessage(
312       const std::string& method_name,
313       void (*handler)(std::unique_ptr<Response>, dbus::Message*, Args...)) {
314     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
315                   "Response must be DBusMethodResponse<T...>");
316     Handler<DBusInterfaceMethodHandlerWithMessage<Response, Args...>>::Add(
317         this, method_name, base::Bind(handler));
318   }
319 
320   // Register an async D-Bus method handler for |method_name| as a class member
321   // function.
322   template<typename Response,
323            typename Instance,
324            typename Class,
325            typename... Args>
AddMethodHandlerWithMessage(const std::string & method_name,Instance instance,void (Class::* handler)(std::unique_ptr<Response>,dbus::Message *,Args...))326   inline void AddMethodHandlerWithMessage(
327       const std::string& method_name,
328       Instance instance,
329       void(Class::*handler)(std::unique_ptr<Response>,
330                             dbus::Message*, Args...)) {
331     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
332                   "Response must be DBusMethodResponse<T...>");
333     Handler<DBusInterfaceMethodHandlerWithMessage<Response, Args...>>::Add(
334         this, method_name, base::Bind(handler, instance));
335   }
336 
337   // Same as above but for const-method of a class.
338   template<typename Response,
339            typename Instance,
340            typename Class,
341            typename... Args>
AddMethodHandlerWithMessage(const std::string & method_name,Instance instance,void (Class::* handler)(std::unique_ptr<Response>,dbus::Message *,Args...)const)342   inline void AddMethodHandlerWithMessage(
343       const std::string& method_name,
344       Instance instance,
345       void(Class::*handler)(std::unique_ptr<Response>, dbus::Message*,
346                             Args...) const) {
347     static_assert(std::is_base_of<DBusMethodResponseBase, Response>::value,
348                   "Response must be DBusMethodResponse<T...>");
349     Handler<DBusInterfaceMethodHandlerWithMessage<Response, Args...>>::Add(
350         this, method_name, base::Bind(handler, instance));
351   }
352 
353   // Register a raw D-Bus method handler for |method_name| as base::Callback.
AddRawMethodHandler(const std::string & method_name,const base::Callback<void (dbus::MethodCall *,ResponseSender)> & handler)354   inline void AddRawMethodHandler(
355       const std::string& method_name,
356       const base::Callback<void(dbus::MethodCall*, ResponseSender)>& handler) {
357     Handler<RawDBusInterfaceMethodHandler>::Add(this, method_name, handler);
358   }
359 
360   // Register a raw D-Bus method handler for |method_name| as a class member
361   // function.
362   template<typename Instance, typename Class>
AddRawMethodHandler(const std::string & method_name,Instance instance,void (Class::* handler)(dbus::MethodCall *,ResponseSender))363   inline void AddRawMethodHandler(
364       const std::string& method_name,
365       Instance instance,
366       void(Class::*handler)(dbus::MethodCall*, ResponseSender)) {
367     Handler<RawDBusInterfaceMethodHandler>::Add(
368         this, method_name, base::Bind(handler, instance));
369   }
370 
371   // Register a D-Bus property.
372   void AddProperty(const std::string& property_name,
373                    ExportedPropertyBase* prop_base);
374 
375   // Unregisters a D-Bus property.
376   void RemoveProperty(const std::string& property_name);
377 
378   // Registers a D-Bus signal that has a specified number and types (|Args|) of
379   // arguments. Returns a weak pointer to the DBusSignal object which can be
380   // used to send the signal on this interface when needed:
381   /*
382     DBusInterface* itf = dbus_object->AddOrGetInterface("Interface");
383     auto signal = itf->RegisterSignal<int, bool>("MySignal");
384     ...
385     // Send the Interface.MySig(12, true) signal.
386     if (signal.lock()->Send(12, true)) { ... }
387   */
388   // Or if the signal signature is long or complex, you can alias the
389   // DBusSignal<Args...> signal type and use RegisterSignalOfType method
390   // instead:
391   /*
392     DBusInterface* itf = dbus_object->AddOrGetInterface("Interface");
393     using MySignal = DBusSignal<int, bool>;
394     auto signal = itf->RegisterSignalOfType<MySignal>("MySignal");
395     ...
396     // Send the Interface.MySig(12, true) signal.
397     if (signal.lock()->Send(12, true)) { ... }
398   */
399   // If the signal with the given name was already registered, the existing
400   // copy of the signal proxy object is returned as long as the method signature
401   // of the original signal matches the current call. If it doesn't, the method
402   // aborts.
403 
404   // RegisterSignalOfType can be used to create a signal if the type of the
405   // complete DBusSignal<Args...> class which is pre-defined/aliased earlier.
406   template<typename DBusSignalType>
RegisterSignalOfType(const std::string & signal_name)407   inline std::weak_ptr<DBusSignalType> RegisterSignalOfType(
408       const std::string& signal_name) {
409     auto signal = std::make_shared<DBusSignalType>(
410         dbus_object_, interface_name_, signal_name);
411     AddSignalImpl(signal_name, signal);
412     return signal;
413   }
414 
415   // For simple signal arguments, you can specify their types directly in
416   // RegisterSignal<t1, t2, ...>():
417   //  auto signal = itf->RegisterSignal<int>("SignalName");
418   // This will create a callback signal object that expects one int argument.
419   template<typename... Args>
RegisterSignal(const std::string & signal_name)420   inline std::weak_ptr<DBusSignal<Args...>> RegisterSignal(
421       const std::string& signal_name) {
422     return RegisterSignalOfType<DBusSignal<Args...>>(signal_name);
423   }
424 
425  private:
426   // Helper to create an instance of DBusInterfaceMethodHandlerInterface-derived
427   // handler and add it to the method handler map of the interface.
428   // This makes the actual AddXXXMethodHandler() methods very light-weight and
429   // easier to provide different overloads for various method handler kinds.
430   // Using struct here to allow partial specialization on HandlerType while
431   // letting the compiler to deduce the type of the callback without explicitly
432   // specifying it.
433   template<typename HandlerType>
434   struct Handler {
435     template<typename CallbackType>
AddHandler436     inline static void Add(DBusInterface* self,
437                            const std::string& method_name,
438                            const CallbackType& callback) {
439       std::unique_ptr<DBusInterfaceMethodHandlerInterface> sync_method_handler(
440           new HandlerType(callback));
441       self->AddHandlerImpl(method_name, std::move(sync_method_handler));
442     }
443   };
444   // A generic D-Bus method handler for the interface. It extracts the method
445   // name from |method_call|, looks up a registered handler from |handlers_|
446   // map and dispatched the call to that handler.
447   void HandleMethodCall(dbus::MethodCall* method_call, ResponseSender sender);
448   // Helper to add a handler for method |method_name| to the |handlers_| map.
449   // Not marked BRILLO_PRIVATE because it needs to be called by the inline
450   // template functions AddMethodHandler(...)
451   void AddHandlerImpl(
452       const std::string& method_name,
453       std::unique_ptr<DBusInterfaceMethodHandlerInterface> handler);
454   // Helper to add a signal object to the |signals_| map.
455   // Not marked BRILLO_PRIVATE because it needs to be called by the inline
456   // template function RegisterSignalOfType(...)
457   void AddSignalImpl(const std::string& signal_name,
458                      const std::shared_ptr<DBusSignalBase>& signal);
459   // Exports all the methods and properties of this interface and claims the
460   // D-Bus interface.
461   // object_manager - ExportedObjectManager instance that notifies D-Bus
462   //                  listeners of a new interface being claimed.
463   // exported_object - instance of D-Bus object the interface is being added to.
464   // object_path - D-Bus object path for the object instance.
465   // interface_name - name of interface being registered.
466   // completion_callback - a callback to be called when the asynchronous
467   //                       registration operation is completed.
468   BRILLO_PRIVATE void ExportAsync(
469       ExportedObjectManager* object_manager,
470       dbus::Bus* bus,
471       dbus::ExportedObject* exported_object,
472       const dbus::ObjectPath& object_path,
473       const AsyncEventSequencer::CompletionAction& completion_callback);
474   // Exports all the methods and properties of this interface and claims the
475   // D-Bus interface synchronously.
476   // object_manager - ExportedObjectManager instance that notifies D-Bus
477   //                  listeners of a new interface being claimed.
478   // exported_object - instance of D-Bus object the interface is being added to.
479   // object_path - D-Bus object path for the object instance.
480   // interface_name - name of interface being registered.
481   BRILLO_PRIVATE void ExportAndBlock(
482       ExportedObjectManager* object_manager,
483       dbus::Bus* bus,
484       dbus::ExportedObject* exported_object,
485       const dbus::ObjectPath& object_path);
486 
487   BRILLO_PRIVATE void ClaimInterface(
488       base::WeakPtr<ExportedObjectManager> object_manager,
489       const dbus::ObjectPath& object_path,
490       const ExportedPropertySet::PropertyWriter& writer,
491       bool all_succeeded);
492 
493   // Method registration map.
494   std::map<std::string, std::unique_ptr<DBusInterfaceMethodHandlerInterface>>
495       handlers_;
496   // Signal registration map.
497   std::map<std::string, std::shared_ptr<DBusSignalBase>> signals_;
498 
499   friend class DBusObject;
500   friend class DBusInterfaceTestHelper;
501   DBusObject* dbus_object_;
502   std::string interface_name_;
503   base::ScopedClosureRunner release_interface_cb_;
504 
505   base::WeakPtrFactory<DBusInterface> weak_factory_{this};
506   DISALLOW_COPY_AND_ASSIGN(DBusInterface);
507 };
508 
509 // A D-Bus object implementation class. Manages the interfaces implemented
510 // by this object.
511 class BRILLO_EXPORT DBusObject {
512  public:
513   using PropertyHandlerSetupCallback = base::Callback<void(
514       DBusInterface* prop_interface, ExportedPropertySet* property_set)>;
515 
516   // object_manager - ExportedObjectManager instance that notifies D-Bus
517   //                  listeners of a new interface being claimed and property
518   //                  changes on those interfaces.
519   // object_path - D-Bus object path for the object instance.
520   DBusObject(ExportedObjectManager* object_manager,
521              const scoped_refptr<dbus::Bus>& bus,
522              const dbus::ObjectPath& object_path);
523 
524   // property_handler_setup_callback - To be called when setting up property
525   //                                   method handlers. Clients can register
526   //                                   their own custom property method handlers
527   //                                   (GetAll/Get/Set) by passing in this
528   //                                   callback.
529   DBusObject(ExportedObjectManager* object_manager,
530              const scoped_refptr<dbus::Bus>& bus,
531              const dbus::ObjectPath& object_path,
532              PropertyHandlerSetupCallback property_handler_setup_callback);
533 
534   virtual ~DBusObject();
535 
536   // Returns an proxy handler for the interface |interface_name|. If the
537   // interface proxy does not exist yet, it will be automatically created.
538   DBusInterface* AddOrGetInterface(const std::string& interface_name);
539 
540   // Finds an interface with the given name. Returns nullptr if there is no
541   // interface registered by this name.
542   DBusInterface* FindInterface(const std::string& interface_name) const;
543 
544   // Removes the previously added proxy handler for the interface
545   // |interface_name|.
546   void RemoveInterface(const std::string& interface_name);
547 
548   // Exports a proxy handler for the interface |interface_name|. If the
549   // interface proxy does not exist yet, it will be automatically created.
550   void ExportInterfaceAsync(
551       const std::string& interface_name,
552       const AsyncEventSequencer::CompletionAction& completion_callback);
553 
554   // Registers the object instance with D-Bus. This is an asynchronous call
555   // that will call |completion_callback| when the object and all of its
556   // interfaces are registered.
557   virtual void RegisterAsync(
558       const AsyncEventSequencer::CompletionAction& completion_callback);
559 
560   // Registers the object instance with D-Bus. This is call is synchronous and
561   // will block until the object and all of its interfaces are registered.
562   virtual void RegisterAndBlock();
563 
564   // Unregister the object instance with D-Bus.  This will unregister the
565   // |exported_object_| and its path from the bus.  The destruction of
566   // |exported_object_| will be deferred in an async task posted by the bus.
567   // It is guarantee that upon return from this call a new DBusObject with the
568   // same object path can be created/registered.
569   virtual void UnregisterAsync();
570 
571   // Returns the ExportedObjectManager proxy, if any. If DBusObject has been
572   // constructed without an object manager, this method returns an empty
573   // smart pointer (containing nullptr).
GetObjectManager()574   const base::WeakPtr<ExportedObjectManager>& GetObjectManager() const {
575     return object_manager_;
576   }
577 
578   // Sends a signal from the exported D-Bus object.
579   bool SendSignal(dbus::Signal* signal);
580 
581   // Returns the reference to dbus::Bus this object is associated with.
GetBus()582   scoped_refptr<dbus::Bus> GetBus() { return bus_; }
583 
584  private:
585   // Add the org.freedesktop.DBus.Properties interface to the object.
586   void RegisterPropertiesInterface();
587 
588   // A map of all the interfaces added to this object.
589   std::map<std::string, std::unique_ptr<DBusInterface>> interfaces_;
590   // Exported property set for properties registered with the interfaces
591   // implemented by this D-Bus object.
592   ExportedPropertySet property_set_;
593   // Delegate object implementing org.freedesktop.DBus.ObjectManager interface.
594   base::WeakPtr<ExportedObjectManager> object_manager_;
595   // D-Bus bus object.
596   scoped_refptr<dbus::Bus> bus_;
597   // D-Bus object path for this object.
598   dbus::ObjectPath object_path_;
599   // D-Bus object instance once this object is successfully exported.
600   dbus::ExportedObject* exported_object_ = nullptr;  // weak; owned by |bus_|.
601   // Sets up property method handlers.
602   PropertyHandlerSetupCallback property_handler_setup_callback_;
603 
604   friend class DBusInterface;
605   DISALLOW_COPY_AND_ASSIGN(DBusObject);
606 };
607 
608 }  // namespace dbus_utils
609 }  // namespace brillo
610 
611 #endif  // LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_H_
612