• 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   // Registers a D-Bus signal that has a specified number and types (|Args|) of
376   // arguments. Returns a weak pointer to the DBusSignal object which can be
377   // used to send the signal on this interface when needed:
378   /*
379     DBusInterface* itf = dbus_object->AddOrGetInterface("Interface");
380     auto signal = itf->RegisterSignal<int, bool>("MySignal");
381     ...
382     // Send the Interface.MySig(12, true) signal.
383     if (signal.lock()->Send(12, true)) { ... }
384   */
385   // Or if the signal signature is long or complex, you can alias the
386   // DBusSignal<Args...> signal type and use RegisterSignalOfType method
387   // instead:
388   /*
389     DBusInterface* itf = dbus_object->AddOrGetInterface("Interface");
390     using MySignal = DBusSignal<int, bool>;
391     auto signal = itf->RegisterSignalOfType<MySignal>("MySignal");
392     ...
393     // Send the Interface.MySig(12, true) signal.
394     if (signal.lock()->Send(12, true)) { ... }
395   */
396   // If the signal with the given name was already registered, the existing
397   // copy of the signal proxy object is returned as long as the method signature
398   // of the original signal matches the current call. If it doesn't, the method
399   // aborts.
400 
401   // RegisterSignalOfType can be used to create a signal if the type of the
402   // complete DBusSignal<Args...> class which is pre-defined/aliased earlier.
403   template<typename DBusSignalType>
RegisterSignalOfType(const std::string & signal_name)404   inline std::weak_ptr<DBusSignalType> RegisterSignalOfType(
405       const std::string& signal_name) {
406     auto signal = std::make_shared<DBusSignalType>(
407         dbus_object_, interface_name_, signal_name);
408     AddSignalImpl(signal_name, signal);
409     return signal;
410   }
411 
412   // For simple signal arguments, you can specify their types directly in
413   // RegisterSignal<t1, t2, ...>():
414   //  auto signal = itf->RegisterSignal<int>("SignalName");
415   // This will create a callback signal object that expects one int argument.
416   template<typename... Args>
RegisterSignal(const std::string & signal_name)417   inline std::weak_ptr<DBusSignal<Args...>> RegisterSignal(
418       const std::string& signal_name) {
419     return RegisterSignalOfType<DBusSignal<Args...>>(signal_name);
420   }
421 
422  private:
423   // Helper to create an instance of DBusInterfaceMethodHandlerInterface-derived
424   // handler and add it to the method handler map of the interface.
425   // This makes the actual AddXXXMethodHandler() methods very light-weight and
426   // easier to provide different overloads for various method handler kinds.
427   // Using struct here to allow partial specialization on HandlerType while
428   // letting the compiler to deduce the type of the callback without explicitly
429   // specifying it.
430   template<typename HandlerType>
431   struct Handler {
432     template<typename CallbackType>
AddHandler433     inline static void Add(DBusInterface* self,
434                            const std::string& method_name,
435                            const CallbackType& callback) {
436       std::unique_ptr<DBusInterfaceMethodHandlerInterface> sync_method_handler(
437           new HandlerType(callback));
438       self->AddHandlerImpl(method_name, std::move(sync_method_handler));
439     }
440   };
441   // A generic D-Bus method handler for the interface. It extracts the method
442   // name from |method_call|, looks up a registered handler from |handlers_|
443   // map and dispatched the call to that handler.
444   void HandleMethodCall(dbus::MethodCall* method_call, ResponseSender sender);
445   // Helper to add a handler for method |method_name| to the |handlers_| map.
446   // Not marked BRILLO_PRIVATE because it needs to be called by the inline
447   // template functions AddMethodHandler(...)
448   void AddHandlerImpl(
449       const std::string& method_name,
450       std::unique_ptr<DBusInterfaceMethodHandlerInterface> handler);
451   // Helper to add a signal object to the |signals_| map.
452   // Not marked BRILLO_PRIVATE because it needs to be called by the inline
453   // template function RegisterSignalOfType(...)
454   void AddSignalImpl(const std::string& signal_name,
455                      const std::shared_ptr<DBusSignalBase>& signal);
456   // Exports all the methods and properties of this interface and claims the
457   // D-Bus interface.
458   // object_manager - ExportedObjectManager instance that notifies D-Bus
459   //                  listeners of a new interface being claimed.
460   // exported_object - instance of D-Bus object the interface is being added to.
461   // object_path - D-Bus object path for the object instance.
462   // interface_name - name of interface being registered.
463   // completion_callback - a callback to be called when the asynchronous
464   //                       registration operation is completed.
465   BRILLO_PRIVATE void ExportAsync(
466       ExportedObjectManager* object_manager,
467       dbus::Bus* bus,
468       dbus::ExportedObject* exported_object,
469       const dbus::ObjectPath& object_path,
470       const AsyncEventSequencer::CompletionAction& completion_callback);
471   // Exports all the methods and properties of this interface and claims the
472   // D-Bus interface synchronously.
473   // object_manager - ExportedObjectManager instance that notifies D-Bus
474   //                  listeners of a new interface being claimed.
475   // exported_object - instance of D-Bus object the interface is being added to.
476   // object_path - D-Bus object path for the object instance.
477   // interface_name - name of interface being registered.
478   BRILLO_PRIVATE void ExportAndBlock(
479       ExportedObjectManager* object_manager,
480       dbus::Bus* bus,
481       dbus::ExportedObject* exported_object,
482       const dbus::ObjectPath& object_path);
483 
484   BRILLO_PRIVATE void ClaimInterface(
485       base::WeakPtr<ExportedObjectManager> object_manager,
486       const dbus::ObjectPath& object_path,
487       const ExportedPropertySet::PropertyWriter& writer,
488       bool all_succeeded);
489 
490   // Method registration map.
491   std::map<std::string, std::unique_ptr<DBusInterfaceMethodHandlerInterface>>
492       handlers_;
493   // Signal registration map.
494   std::map<std::string, std::shared_ptr<DBusSignalBase>> signals_;
495 
496   friend class DBusObject;
497   friend class DBusInterfaceTestHelper;
498   DBusObject* dbus_object_;
499   std::string interface_name_;
500   base::ScopedClosureRunner release_interface_cb_;
501 
502   base::WeakPtrFactory<DBusInterface> weak_factory_{this};
503   DISALLOW_COPY_AND_ASSIGN(DBusInterface);
504 };
505 
506 // A D-Bus object implementation class. Manages the interfaces implemented
507 // by this object.
508 class BRILLO_EXPORT DBusObject {
509  public:
510   // object_manager - ExportedObjectManager instance that notifies D-Bus
511   //                  listeners of a new interface being claimed and property
512   //                  changes on those interfaces.
513   // object_path - D-Bus object path for the object instance.
514   DBusObject(ExportedObjectManager* object_manager,
515              const scoped_refptr<dbus::Bus>& bus,
516              const dbus::ObjectPath& object_path);
517   virtual ~DBusObject();
518 
519   // Returns an proxy handler for the interface |interface_name|. If the
520   // interface proxy does not exist yet, it will be automatically created.
521   DBusInterface* AddOrGetInterface(const std::string& interface_name);
522 
523   // Finds an interface with the given name. Returns nullptr if there is no
524   // interface registered by this name.
525   DBusInterface* FindInterface(const std::string& interface_name) const;
526 
527   // Registers the object instance with D-Bus. This is an asynchronous call
528   // that will call |completion_callback| when the object and all of its
529   // interfaces are registered.
530   virtual void RegisterAsync(
531       const AsyncEventSequencer::CompletionAction& completion_callback);
532 
533   // Registers the object instance with D-Bus. This is call is synchronous and
534   // will block until the object and all of its interfaces are registered.
535   virtual void RegisterAndBlock();
536 
537   // Unregister the object instance with D-Bus.  This will unregister the
538   // |exported_object_| and its path from the bus.  The destruction of
539   // |exported_object_| will be deferred in an async task posted by the bus.
540   // It is guarantee that upon return from this call a new DBusObject with the
541   // same object path can be created/registered.
542   virtual void UnregisterAsync();
543 
544   // Returns the ExportedObjectManager proxy, if any. If DBusObject has been
545   // constructed without an object manager, this method returns an empty
546   // smart pointer (containing nullptr).
GetObjectManager()547   const base::WeakPtr<ExportedObjectManager>& GetObjectManager() const {
548     return object_manager_;
549   }
550 
551   // Sends a signal from the exported D-Bus object.
552   bool SendSignal(dbus::Signal* signal);
553 
554   // Returns the reference to dbus::Bus this object is associated with.
GetBus()555   scoped_refptr<dbus::Bus> GetBus() { return bus_; }
556 
557  private:
558   // A map of all the interfaces added to this object.
559   std::map<std::string, std::unique_ptr<DBusInterface>> interfaces_;
560   // Exported property set for properties registered with the interfaces
561   // implemented by this D-Bus object.
562   ExportedPropertySet property_set_;
563   // Delegate object implementing org.freedesktop.DBus.ObjectManager interface.
564   base::WeakPtr<ExportedObjectManager> object_manager_;
565   // D-Bus bus object.
566   scoped_refptr<dbus::Bus> bus_;
567   // D-Bus object path for this object.
568   dbus::ObjectPath object_path_;
569   // D-Bus object instance once this object is successfully exported.
570   dbus::ExportedObject* exported_object_ = nullptr;  // weak; owned by |bus_|.
571 
572   friend class DBusInterface;
573   DISALLOW_COPY_AND_ASSIGN(DBusObject);
574 };
575 
576 }  // namespace dbus_utils
577 }  // namespace brillo
578 
579 #endif  // LIBBRILLO_BRILLO_DBUS_DBUS_OBJECT_H_
580