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