object_manager.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. // Copyright (c) 2013 The Chromium 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. #ifndef DBUS_OBJECT_MANAGER_H_
  5. #define DBUS_OBJECT_MANAGER_H_
  6. #include <stdint.h>
  7. #include <map>
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/memory/ref_counted.h"
  10. #include "base/memory/weak_ptr.h"
  11. #include "dbus/object_path.h"
  12. #include "dbus/property.h"
  13. // Newer D-Bus services implement the Object Manager interface to inform other
  14. // clients about the objects they export, the properties of those objects, and
  15. // notification of changes in the set of available objects:
  16. // http://dbus.freedesktop.org/doc/dbus-specification.html
  17. // #standard-interfaces-objectmanager
  18. //
  19. // This interface is very closely tied to the Properties interface, and uses
  20. // even more levels of nested dictionaries and variants. In addition to
  21. // simplifying implementation, since there tends to be a single object manager
  22. // per service, spanning the complete set of objects an interfaces available,
  23. // the classes implemented here make dealing with this interface simpler.
  24. //
  25. // Except where noted, use of this class replaces the need for the code
  26. // documented in dbus/property.h
  27. //
  28. // Client implementation classes should begin by deriving from the
  29. // dbus::ObjectManager::Interface class, and defining a Properties structure as
  30. // documented in dbus/property.h.
  31. //
  32. // Example:
  33. // class ExampleClient : public dbus::ObjectManager::Interface {
  34. // public:
  35. // struct Properties : public dbus::PropertySet {
  36. // dbus::Property<std::string> name;
  37. // dbus::Property<uint16_t> version;
  38. // dbus::Property<dbus::ObjectPath> parent;
  39. // dbus::Property<std::vector<std::string>> children;
  40. //
  41. // Properties(dbus::ObjectProxy* object_proxy,
  42. // const PropertyChangedCallback callback)
  43. // : dbus::PropertySet(object_proxy, kExampleInterface, callback) {
  44. // RegisterProperty("Name", &name);
  45. // RegisterProperty("Version", &version);
  46. // RegisterProperty("Parent", &parent);
  47. // RegisterProperty("Children", &children);
  48. // }
  49. // virtual ~Properties() {}
  50. // };
  51. //
  52. // The link between the implementation class and the object manager is set up
  53. // in the constructor and removed in the destructor; the class should maintain
  54. // a pointer to its object manager for use in other methods and establish
  55. // itself as the implementation class for its interface.
  56. //
  57. // Example:
  58. // explicit ExampleClient::ExampleClient(dbus::Bus* bus)
  59. // : bus_(bus),
  60. // weak_ptr_factory_(this) {
  61. // object_manager_ = bus_->GetObjectManager(kServiceName, kManagerPath);
  62. // object_manager_->RegisterInterface(kInterface, this);
  63. // }
  64. //
  65. // virtual ExampleClient::~ExampleClient() {
  66. // object_manager_->UnregisterInterface(kInterface);
  67. // }
  68. //
  69. // This class calls GetManagedObjects() asynchronously after the remote service
  70. // becomes available and additionally refreshes managed objects after the
  71. // service stops or restarts.
  72. //
  73. // The object manager interface class has one abstract method that must be
  74. // implemented by the class to create Properties structures on demand. As well
  75. // as implementing this, you will want to implement a public GetProperties()
  76. // method.
  77. //
  78. // Example:
  79. // dbus::PropertySet* CreateProperties(dbus::ObjectProxy* object_proxy,
  80. // const std::string& interface_name)
  81. // override {
  82. // Properties* properties = new Properties(
  83. // object_proxy, interface_name,
  84. // base::BindRepeating(&PropertyChanged,
  85. // weak_ptr_factory_.GetWeakPtr(),
  86. // object_path));
  87. // return static_cast<dbus::PropertySet*>(properties);
  88. // }
  89. //
  90. // Properties* GetProperties(const dbus::ObjectPath& object_path) {
  91. // return static_cast<Properties*>(
  92. // object_manager_->GetProperties(object_path, kInterface));
  93. // }
  94. //
  95. // Note that unlike classes that only use dbus/property.h there is no need
  96. // to connect signals or obtain the initial values of properties. The object
  97. // manager class handles that for you.
  98. //
  99. // PropertyChanged is a method of your own to notify your observers of a change
  100. // in your properties, either as a result of a signal from the Properties
  101. // interface or from the Object Manager interface. You may also wish to
  102. // implement the optional ObjectAdded and ObjectRemoved methods of the class
  103. // to likewise notify observers.
  104. //
  105. // When your class needs an object proxy for a given object path, it may
  106. // obtain it from the object manager. Unlike the equivalent method on the bus
  107. // this will return NULL if the object is not known.
  108. //
  109. // object_proxy = object_manager_->GetObjectProxy(object_path);
  110. // if (object_proxy) {
  111. // ...
  112. // }
  113. //
  114. // There is no need for code using your implementation class to be aware of the
  115. // use of object manager behind the scenes, the rules for updating properties
  116. // documented in dbus/property.h still apply.
  117. namespace dbus {
  118. const char kObjectManagerInterface[] = "org.freedesktop.DBus.ObjectManager";
  119. const char kObjectManagerGetManagedObjects[] = "GetManagedObjects";
  120. const char kObjectManagerInterfacesAdded[] = "InterfacesAdded";
  121. const char kObjectManagerInterfacesRemoved[] = "InterfacesRemoved";
  122. class Bus;
  123. class MessageReader;
  124. class ObjectProxy;
  125. class Response;
  126. class Signal;
  127. // ObjectManager implements both the D-Bus client components of the D-Bus
  128. // Object Manager interface, as internal methods, and a public API for
  129. // client classes to utilize.
  130. class CHROME_DBUS_EXPORT ObjectManager final
  131. : public base::RefCountedThreadSafe<ObjectManager> {
  132. public:
  133. // ObjectManager::Interface must be implemented by any class wishing to have
  134. // its remote objects managed by an ObjectManager.
  135. class Interface {
  136. public:
  137. virtual ~Interface() {}
  138. // Called by ObjectManager to create a Properties structure for the remote
  139. // D-Bus object identified by |object_path| and accessibile through
  140. // |object_proxy|. The D-Bus interface name |interface_name| is that passed
  141. // to RegisterInterface() by the implementation class.
  142. //
  143. // The implementation class should create and return an instance of its own
  144. // subclass of dbus::PropertySet; ObjectManager will then connect signals
  145. // and update the properties from its own internal message reader.
  146. virtual PropertySet* CreateProperties(
  147. ObjectProxy *object_proxy,
  148. const dbus::ObjectPath& object_path,
  149. const std::string& interface_name) = 0;
  150. // Called by ObjectManager to inform the implementation class that an
  151. // object has been added with the path |object_path|. The D-Bus interface
  152. // name |interface_name| is that passed to RegisterInterface() by the
  153. // implementation class.
  154. //
  155. // If a new object implements multiple interfaces, this method will be
  156. // called on each interface implementation with differing values of
  157. // |interface_name| as appropriate. An implementation class will only
  158. // receive multiple calls if it has registered for multiple interfaces.
  159. virtual void ObjectAdded(const ObjectPath& object_path,
  160. const std::string& interface_name) { }
  161. // Called by ObjectManager to inform the implementation class than an
  162. // object with the path |object_path| has been removed. Ths D-Bus interface
  163. // name |interface_name| is that passed to RegisterInterface() by the
  164. // implementation class. Multiple interfaces are handled as with
  165. // ObjectAdded().
  166. //
  167. // This method will be called before the Properties structure and the
  168. // ObjectProxy object for the given interface are cleaned up, it is safe
  169. // to retrieve them during removal to vary processing.
  170. virtual void ObjectRemoved(const ObjectPath& object_path,
  171. const std::string& interface_name) { }
  172. };
  173. // Client code should use Bus::GetObjectManager() instead of this constructor.
  174. static scoped_refptr<ObjectManager> Create(Bus* bus,
  175. const std::string& service_name,
  176. const ObjectPath& object_path);
  177. ObjectManager(const ObjectManager&) = delete;
  178. ObjectManager& operator=(const ObjectManager&) = delete;
  179. // Register a client implementation class |interface| for the given D-Bus
  180. // interface named in |interface_name|. That object's CreateProperties()
  181. // method will be used to create instances of dbus::PropertySet* when
  182. // required.
  183. void RegisterInterface(const std::string& interface_name,
  184. Interface* interface);
  185. // Unregister the implementation class for the D-Bus interface named in
  186. // |interface_name|, objects and properties of this interface will be
  187. // ignored.
  188. void UnregisterInterface(const std::string& interface_name);
  189. // Checks whether an interface is registered.
  190. bool IsInterfaceRegisteredForTesting(const std::string& interface_name) const;
  191. // Returns a list of object paths, in an undefined order, of objects known
  192. // to this manager.
  193. std::vector<ObjectPath> GetObjects();
  194. // Returns the list of object paths, in an undefined order, of objects
  195. // implementing the interface named in |interface_name| known to this manager.
  196. std::vector<ObjectPath> GetObjectsWithInterface(
  197. const std::string& interface_name);
  198. // Returns a ObjectProxy pointer for the given |object_path|. Unlike
  199. // the equivalent method on Bus this will return NULL if the object
  200. // manager has not been informed of that object's existence.
  201. ObjectProxy* GetObjectProxy(const ObjectPath& object_path);
  202. // Returns a PropertySet* pointer for the given |object_path| and
  203. // |interface_name|, or NULL if the object manager has not been informed of
  204. // that object's existence or the interface's properties. The caller should
  205. // cast the returned pointer to the appropriate type, e.g.:
  206. // static_cast<Properties*>(GetProperties(object_path, my_interface));
  207. PropertySet* GetProperties(const ObjectPath& object_path,
  208. const std::string& interface_name);
  209. // Instructs the object manager to refresh its list of managed objects;
  210. // automatically called by the D-Bus thread manager, there should never be
  211. // a need to call this manually.
  212. void GetManagedObjects();
  213. // Cleans up any match rules and filter functions added by this ObjectManager.
  214. // The Bus object will take care of this so you don't have to do it manually.
  215. //
  216. // BLOCKING CALL.
  217. void CleanUp();
  218. private:
  219. friend class base::RefCountedThreadSafe<ObjectManager>;
  220. ObjectManager(Bus* bus,
  221. const std::string& service_name,
  222. const ObjectPath& object_path);
  223. ~ObjectManager();
  224. // Called from the constructor to add a match rule for PropertiesChanged
  225. // signals on the D-Bus thread and set up a corresponding filter function.
  226. bool SetupMatchRuleAndFilter();
  227. // Called on the origin thread once the match rule and filter have been set
  228. // up. Connects the InterfacesAdded and InterfacesRemoved signals and
  229. // refreshes objects if the service is available. |success| is false if an
  230. // error occurred during setup and true otherwise.
  231. void OnSetupMatchRuleAndFilterComplete(bool success);
  232. // Called by dbus:: when a message is received. This is used to filter
  233. // PropertiesChanged signals from the correct sender and relay the event to
  234. // the correct PropertySet.
  235. static DBusHandlerResult HandleMessageThunk(DBusConnection* connection,
  236. DBusMessage* raw_message,
  237. void* user_data);
  238. DBusHandlerResult HandleMessage(DBusConnection* connection,
  239. DBusMessage* raw_message);
  240. // Called when a PropertiesChanged signal is received from the sender.
  241. // This method notifies the relevant PropertySet that it should update its
  242. // properties based on the received signal. Called from HandleMessage.
  243. void NotifyPropertiesChanged(const dbus::ObjectPath object_path,
  244. Signal* signal);
  245. void NotifyPropertiesChangedHelper(const dbus::ObjectPath object_path,
  246. Signal* signal);
  247. // Called by dbus:: in response to the GetManagedObjects() method call.
  248. void OnGetManagedObjects(Response* response);
  249. // Called by dbus:: when an InterfacesAdded signal is received and initially
  250. // connected.
  251. void InterfacesAddedReceived(Signal* signal);
  252. void InterfacesAddedConnected(const std::string& interface_name,
  253. const std::string& signal_name,
  254. bool success);
  255. // Called by dbus:: when an InterfacesRemoved signal is received and
  256. // initially connected.
  257. void InterfacesRemovedReceived(Signal* signal);
  258. void InterfacesRemovedConnected(const std::string& interface_name,
  259. const std::string& signal_name,
  260. bool success);
  261. // Updates the map entry for the object with path |object_path| using the
  262. // D-Bus message in |reader|, which should consist of an dictionary mapping
  263. // interface names to properties dictionaries as recieved by both the
  264. // GetManagedObjects() method return and the InterfacesAdded() signal.
  265. void UpdateObject(const ObjectPath& object_path, MessageReader* reader);
  266. // Updates the properties structure of the object with path |object_path|
  267. // for the interface named |interface_name| using the D-Bus message in
  268. // |reader| which should consist of the properties dictionary for that
  269. // interface.
  270. //
  271. // Called by UpdateObjects() for each interface in the dictionary; this
  272. // method takes care of both creating the entry in the ObjectMap and
  273. // ObjectProxy if required, as well as the PropertySet instance for that
  274. // interface if necessary.
  275. void AddInterface(const ObjectPath& object_path,
  276. const std::string& interface_name,
  277. MessageReader* reader);
  278. // Removes the properties structure of the object with path |object_path|
  279. // for the interfaces named |interface_name|.
  280. //
  281. // If no further interfaces remain, the entry in the ObjectMap is discarded.
  282. void RemoveInterface(const ObjectPath& object_path,
  283. const std::string& interface_name);
  284. // Removes all objects and interfaces from the object manager when
  285. // |old_owner| is not the empty string and/or re-requests the set of managed
  286. // objects when |new_owner| is not the empty string.
  287. void NameOwnerChanged(const std::string& old_owner,
  288. const std::string& new_owner);
  289. // Write |new_owner| to |service_name_owner_|. This method makes sure write
  290. // happens on the DBus thread, which is the sole writer to
  291. // |service_name_owner_|.
  292. void UpdateServiceNameOwner(const std::string& new_owner);
  293. raw_ptr<Bus> bus_;
  294. std::string service_name_;
  295. std::string service_name_owner_;
  296. std::string match_rule_;
  297. ObjectPath object_path_;
  298. raw_ptr<ObjectProxy> object_proxy_;
  299. bool setup_success_;
  300. bool cleanup_called_;
  301. // Maps the name of an interface to the implementation class used for
  302. // instantiating PropertySet structures for that interface's properties.
  303. typedef std::map<std::string, Interface*> InterfaceMap;
  304. InterfaceMap interface_map_;
  305. // Each managed object consists of a ObjectProxy used to make calls
  306. // against that object and a collection of D-Bus interface names and their
  307. // associated PropertySet structures.
  308. struct Object {
  309. Object();
  310. ~Object();
  311. raw_ptr<ObjectProxy> object_proxy;
  312. // Maps the name of an interface to the specific PropertySet structure
  313. // of that interface's properties.
  314. typedef std::map<const std::string, PropertySet*> PropertiesMap;
  315. PropertiesMap properties_map;
  316. };
  317. // Maps the object path of an object to the Object structure.
  318. typedef std::map<const ObjectPath, Object*> ObjectMap;
  319. ObjectMap object_map_;
  320. // Weak pointer factory for generating 'this' pointers that might live longer
  321. // than we do.
  322. // Note: This should remain the last member so it'll be destroyed and
  323. // invalidate its weak pointers before any other members are destroyed.
  324. base::WeakPtrFactory<ObjectManager> weak_ptr_factory_{this};
  325. };
  326. } // namespace dbus
  327. #endif // DBUS_OBJECT_MANAGER_H_