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