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