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_
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/weak_ptr.h"
12 #include "dbus/object_path.h"
13 #include "dbus/property.h"
15 // Newer D-Bus services implement the Object Manager interface to inform other
16 // clients about the objects they export, the properties of those objects, and
17 // notification of changes in the set of available objects:
18 // http://dbus.freedesktop.org/doc/dbus-specification.html
19 // #standard-interfaces-objectmanager
21 // This interface is very closely tied to the Properties interface, and uses
22 // even more levels of nested dictionaries and variants. In addition to
23 // simplifying implementation, since there tends to be a single object manager
24 // per service, spanning the complete set of objects an interfaces available,
25 // the classes implemented here make dealing with this interface simpler.
27 // Except where noted, use of this class replaces the need for the code
28 // documented in dbus/property.h
30 // Client implementation classes should begin by deriving from the
31 // dbus::ObjectManager::Interface class, and defining a Properties structure as
32 // documented in dbus/property.h.
35 // class ExampleClient : public dbus::ObjectManager::Interface {
37 // struct Properties : public dbus::PropertySet {
38 // dbus::Property<std::string> name;
39 // dbus::Property<uint16> version;
40 // dbus::Property<dbus::ObjectPath> parent;
41 // dbus::Property<std::vector<std::string> > children;
43 // Properties(dbus::ObjectProxy* object_proxy,
44 // const PropertyChangedCallback callback)
45 // : dbus::PropertySet(object_proxy, kExampleInterface, callback) {
46 // RegisterProperty("Name", &name);
47 // RegisterProperty("Version", &version);
48 // RegisterProperty("Parent", &parent);
49 // RegisterProperty("Children", &children);
51 // virtual ~Properties() {}
54 // The link between the implementation class and the object manager is set up
55 // in the constructor and removed in the destructor; the class should maintain
56 // a pointer to its object manager for use in other methods and establish
57 // itself as the implementation class for its interface.
60 // explicit ExampleClient::ExampleClient(dbus::Bus* bus)
62 // weak_ptr_factory_(this) {
63 // object_manager_ = bus_->GetObjectManager(kServiceName, kManagerPath);
64 // object_manager_->RegisterInterface(kInterface, this);
67 // virtual ExampleClient::~ExampleClient() {
68 // object_manager_->UnregisterInterface(kInterface);
71 // The D-Bus thread manager takes care of issuing the necessary call to
72 // GetManagedObjects() after the implementation classes have been set up.
74 // The object manager interface class has one abstract method that must be
75 // implemented by the class to create Properties structures on demand. As well
76 // as implementing this, you will want to implement a public GetProperties()
80 // dbus::PropertySet* CreateProperties(dbus::ObjectProxy* object_proxy,
81 // const std::string& interface_name)
83 // Properties* properties = new Properties(
84 // object_proxy, interface_name,
85 // base::Bind(&PropertyChanged,
86 // weak_ptr_factory_.GetWeakPtr(),
88 // return static_cast<dbus::PropertySet*>(properties);
91 // Properties* GetProperties(const dbus::ObjectPath& object_path) {
92 // return static_cast<Properties*>(
93 // object_manager_->GetProperties(object_path, kInterface));
96 // Note that unlike classes that only use dbus/property.h there is no need
97 // to connect signals or obtain the initial values of properties. The object
98 // manager class handles that for you.
100 // PropertyChanged is a method of your own to notify your observers of a change
101 // in your properties, either as a result of a signal from the Properties
102 // interface or from the Object Manager interface. You may also wish to
103 // implement the optional ObjectAdded and ObjectRemoved methods of the class
104 // to likewise notify observers.
106 // When your class needs an object proxy for a given object path, it may
107 // obtain it from the object manager. Unlike the equivalent method on the bus
108 // this will return NULL if the object is not known.
110 // object_proxy = object_manager_->GetObjectProxy(object_path);
111 // if (object_proxy) {
115 // There is no need for code using your implementation class to be aware of the
116 // use of object manager behind the scenes, the rules for updating properties
117 // documented in dbus/property.h still apply.
121 const char kObjectManagerInterface
[] = "org.freedesktop.DBus.ObjectManager";
122 const char kObjectManagerGetManagedObjects
[] = "GetManagedObjects";
123 const char kObjectManagerInterfacesAdded
[] = "InterfacesAdded";
124 const char kObjectManagerInterfacesRemoved
[] = "InterfacesRemoved";
132 // ObjectManager implements both the D-Bus client components of the D-Bus
133 // Object Manager interface, as internal methods, and a public API for
134 // client classes to utilize.
135 class CHROME_DBUS_EXPORT ObjectManager
136 : public base::RefCountedThreadSafe
<ObjectManager
> {
138 // ObjectManager::Interface must be implemented by any class wishing to have
139 // its remote objects managed by an ObjectManager.
142 virtual ~Interface() {}
144 // Called by ObjectManager to create a Properties structure for the remote
145 // D-Bus object identified by |object_path| and accessibile through
146 // |object_proxy|. The D-Bus interface name |interface_name| is that passed
147 // to RegisterInterface() by the implementation class.
149 // The implementation class should create and return an instance of its own
150 // subclass of dbus::PropertySet; ObjectManager will then connect signals
151 // and update the properties from its own internal message reader.
152 virtual PropertySet
* CreateProperties(
153 ObjectProxy
*object_proxy
,
154 const dbus::ObjectPath
& object_path
,
155 const std::string
& interface_name
) = 0;
157 // Called by ObjectManager to inform the implementation class that an
158 // object has been added with the path |object_path|. The D-Bus interface
159 // name |interface_name| is that passed to RegisterInterface() by the
160 // implementation class.
162 // If a new object implements multiple interfaces, this method will be
163 // called on each interface implementation with differing values of
164 // |interface_name| as appropriate. An implementation class will only
165 // receive multiple calls if it has registered for multiple interfaces.
166 virtual void ObjectAdded(const ObjectPath
& object_path
,
167 const std::string
& interface_name
) { }
169 // Called by ObjectManager to inform the implementation class than an
170 // object with the path |object_path| has been removed. Ths D-Bus interface
171 // name |interface_name| is that passed to RegisterInterface() by the
172 // implementation class. Multiple interfaces are handled as with
175 // This method will be called before the Properties structure and the
176 // ObjectProxy object for the given interface are cleaned up, it is safe
177 // to retrieve them during removal to vary processing.
178 virtual void ObjectRemoved(const ObjectPath
& object_path
,
179 const std::string
& interface_name
) { }
182 // Client code should use Bus::GetObjectManager() instead of this constructor.
183 ObjectManager(Bus
* bus
,
184 const std::string
& service_name
,
185 const ObjectPath
& object_path
);
187 // Register a client implementation class |interface| for the given D-Bus
188 // interface named in |interface_name|. That object's CreateProperties()
189 // method will be used to create instances of dbus::PropertySet* when
191 void RegisterInterface(const std::string
& interface_name
,
192 Interface
* interface
);
194 // Unregister the implementation class for the D-Bus interface named in
195 // |interface_name|, objects and properties of this interface will be
197 void UnregisterInterface(const std::string
& interface_name
);
199 // Returns a list of object paths, in an undefined order, of objects known
201 std::vector
<ObjectPath
> GetObjects();
203 // Returns the list of object paths, in an undefined order, of objects
204 // implementing the interface named in |interface_name| known to this manager.
205 std::vector
<ObjectPath
> GetObjectsWithInterface(
206 const std::string
& interface_name
);
208 // Returns a ObjectProxy pointer for the given |object_path|. Unlike
209 // the equivalent method on Bus this will return NULL if the object
210 // manager has not been informed of that object's existance.
211 ObjectProxy
* GetObjectProxy(const ObjectPath
& object_path
);
213 // Returns a PropertySet* pointer for the given |object_path| and
214 // |interface_name|, or NULL if the object manager has not been informed of
215 // that object's existance or the interface's properties. The caller should
216 // cast the returned pointer to the appropriate type, e.g.:
217 // static_cast<Properties*>(GetProperties(object_path, my_interface));
218 PropertySet
* GetProperties(const ObjectPath
& object_path
,
219 const std::string
& interface_name
);
221 // Instructs the object manager to refresh its list of managed objects;
222 // automatically called by the D-Bus thread manager, there should never be
223 // a need to call this manually.
224 void GetManagedObjects();
227 virtual ~ObjectManager();
230 friend class base::RefCountedThreadSafe
<ObjectManager
>;
233 // Called by dbus:: in response to the GetManagedObjects() method call.
234 void OnGetManagedObjects(Response
* response
);
236 // Called by dbus:: when an InterfacesAdded signal is received and initially
238 void InterfacesAddedReceived(Signal
* signal
);
239 void InterfacesAddedConnected(const std::string
& interface_name
,
240 const std::string
& signal_name
,
243 // Called by dbus:: when an InterfacesRemoved signal is received and
244 // initially connected.
245 void InterfacesRemovedReceived(Signal
* signal
);
246 void InterfacesRemovedConnected(const std::string
& interface_name
,
247 const std::string
& signal_name
,
250 // Updates the map entry for the object with path |object_path| using the
251 // D-Bus message in |reader|, which should consist of an dictionary mapping
252 // interface names to properties dictionaries as recieved by both the
253 // GetManagedObjects() method return and the InterfacesAdded() signal.
254 void UpdateObject(const ObjectPath
& object_path
, MessageReader
* reader
);
256 // Updates the properties structure of the object with path |object_path|
257 // for the interface named |interface_name| using the D-Bus message in
258 // |reader| which should consist of the properties dictionary for that
261 // Called by UpdateObjects() for each interface in the dictionary; this
262 // method takes care of both creating the entry in the ObjectMap and
263 // ObjectProxy if required, as well as the PropertySet instance for that
264 // interface if necessary.
265 void AddInterface(const ObjectPath
& object_path
,
266 const std::string
& interface_name
,
267 MessageReader
* reader
);
269 // Removes the properties structure of the object with path |object_path|
270 // for the interfaces named |interface_name|.
272 // If no further interfaces remain, the entry in the ObjectMap is discarded.
273 void RemoveInterface(const ObjectPath
& object_path
,
274 const std::string
& interface_name
);
277 std::string service_name_
;
278 ObjectPath object_path_
;
279 ObjectProxy
* object_proxy_
;
281 // Maps the name of an interface to the implementation class used for
282 // instantiating PropertySet structures for that interface's properties.
283 typedef std::map
<std::string
, Interface
*> InterfaceMap
;
284 InterfaceMap interface_map_
;
286 // Each managed object consists of a ObjectProxy used to make calls
287 // against that object and a collection of D-Bus interface names and their
288 // associated PropertySet structures.
293 ObjectProxy
* object_proxy
;
295 // Maps the name of an interface to the specific PropertySet structure
296 // of that interface's properties.
297 typedef std::map
<const std::string
, PropertySet
*> PropertiesMap
;
298 PropertiesMap properties_map
;
301 // Maps the object path of an object to the Object structure.
302 typedef std::map
<const ObjectPath
, Object
*> ObjectMap
;
303 ObjectMap object_map_
;
305 // Weak pointer factory for generating 'this' pointers that might live longer
307 // Note: This should remain the last member so it'll be destroyed and
308 // invalidate its weak pointers before any other members are destroyed.
309 base::WeakPtrFactory
<ObjectManager
> weak_ptr_factory_
;
311 DISALLOW_COPY_AND_ASSIGN(ObjectManager
);
316 #endif // DBUS_OBJECT_MANAGER_H_