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