OLD | NEW |
---|---|
(Empty) | |
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 | |
5 #ifndef DBUS_OBJECT_MANAGER_H_ | |
6 #define DBUS_OBJECT_MANAGER_H_ | |
7 | |
8 #include <map> | |
9 | |
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" | |
14 | |
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 | |
20 // | |
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. | |
26 // | |
27 // Except where noted, use of this class replaces the need for the code | |
28 // documented in dbus/property.h | |
29 // | |
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. | |
33 // | |
34 // Example: | |
35 // class ExampleClient : public dbus::ObjectManager::Interface { | |
36 // public: | |
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; | |
42 // | |
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); | |
50 // } | |
51 // virtual ~Properties() {} | |
52 // }; | |
53 // | |
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. | |
58 // | |
59 // Example: | |
60 // explicit ExampleClient::ExampleClient(dbus::Bus* bus) | |
61 // : bus_(bus), | |
62 // weak_ptr_factory_(this) { | |
63 // object_manager_ = bus_->GetObjectManager(kServiceName, kManagerPath); | |
64 // object_manager_->RegisterInterface(kInterface, this); | |
65 // } | |
66 // | |
67 // virtual ExampleClient::~ExampleClient() { | |
68 // object_manager_->UnregisterInterface(kInterface); | |
69 // } | |
70 // | |
71 // The D-Bus thread manager takes care of issuing the necessary call to | |
72 // GetManagedObjects() after the implementation classes have been set up. | |
73 // | |
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() | |
77 // method. | |
78 // | |
79 // Example: | |
80 // dbus::PropertySet* CreateProperties(dbus::ObjectProxy* object_proxy, | |
81 // const std::string& interface_name) | |
82 // OVERRIDE { | |
83 // Properties* properties = new Properties( | |
84 // object_proxy, interface_name, | |
85 // base::Bind(&PropertyChanged, | |
86 // weak_ptr_factory_.GetWeakPtr(), | |
87 // object_path)); | |
88 // return static_cast<dbus::PropertySet*>(properties); | |
89 // } | |
90 // | |
91 // Properties* GetProperties(const dbus::ObjectPath& object_path) { | |
92 // return static_cast<Properties*>( | |
93 // object_manager_->GetProperties(object_path, kInterface)); | |
94 // } | |
95 // | |
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. | |
99 // | |
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. | |
105 // | |
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. | |
109 // | |
110 // object_proxy = object_manager_->GetObjectProxy(object_path); | |
111 // if (object_proxy) { | |
112 // ... | |
113 // } | |
114 // | |
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. | |
118 | |
119 namespace dbus { | |
120 | |
121 const char kObjectManagerInterface[] = "org.freedesktop.DBus.ObjectManager"; | |
122 const char kObjectManagerGetManagedObjects[] = "GetManagedObjects"; | |
123 const char kObjectManagerInterfacesAdded[] = "InterfacesAdded"; | |
124 const char kObjectManagerInterfacesRemoved[] = "InterfacesRemoved"; | |
125 | |
126 class Bus; | |
127 class MessageReader; | |
128 class ObjectProxy; | |
129 class Response; | |
130 class Signal; | |
131 | |
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> { | |
137 public: | |
138 // ObjectManager::Interface must be implemented by any class wishing to have | |
139 // its remote objects managed by an ObjectManager. | |
140 class Interface { | |
141 public: | |
142 virtual ~Interface() {} | |
143 | |
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. | |
148 // | |
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; | |
156 | |
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. | |
161 // | |
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) { } | |
168 | |
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 | |
173 // ObjectAdded(). | |
174 // | |
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) { } | |
satorux1
2013/03/22 01:56:27
Looking at the other patch, ObjectAdded() and Obje
keybuk
2013/03/25 16:00:10
I didn't feel it should be mandatory, it just happ
| |
180 }; | |
181 | |
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); | |
186 virtual ~ObjectManager(); | |
187 | |
188 // Register a client implementation class |interface| for the given D-Bus | |
189 // interface named in |interface_name|. That object's CreateProperties() | |
190 // method will be used to create instances of dbus::PropertySet* when | |
191 // required. | |
192 void RegisterInterface(const std::string& interface_name, | |
193 Interface* interface); | |
194 | |
195 // Unregister the implementation class for the D-Bus interface named in | |
196 // |interface_name|, objects and properties of this interface will be | |
197 // ignored. | |
198 void UnregisterInterface(const std::string& interface_name); | |
199 | |
200 // Returns a list of object paths, in an undefined order, of objects known | |
201 // to this manager. | |
202 std::vector<ObjectPath> GetObjects(); | |
203 | |
204 // Returns the list of object paths, in an undefined order, of objects | |
205 // implementing the interface named in |interface_name| known to this manager. | |
206 std::vector<ObjectPath> GetObjectsWithInterface( | |
207 const std::string& interface_name); | |
208 | |
209 // Returns a ObjectProxy pointer for the given |object_path|. Unlike | |
210 // the equivalent method on Bus this will return NULL if the object | |
211 // manager has not been informed of that object's existance. | |
212 ObjectProxy* GetObjectProxy(const ObjectPath& object_path); | |
213 | |
214 // Returns a PropertySet* pointer for the given |object_path| and | |
215 // |interface_name|, or NULL if the object manager has not been informed of | |
216 // that object's existance or the interface's properties. The caller should | |
217 // cast the returned pointer to the appropriate type, e.g.: | |
218 // static_cast<Properties*>(GetProperties(object_path, my_interface)); | |
219 PropertySet* GetProperties(const ObjectPath& object_path, | |
220 const std::string& interface_name); | |
221 | |
222 // Instructs the object manager to refresh its list of managed objects; | |
223 // automatically called by the D-Bus thread manager, there should never be | |
224 // a need to call this manually. | |
225 void GetManagedObjects(); | |
satorux1
2013/03/22 01:41:33
The message (list of list of dictionaries) we'll r
| |
226 | |
227 private: | |
228 friend class base::RefCountedThreadSafe<ObjectManager>; | |
229 | |
230 // Called by dbus:: in response to the GetManagedObjects() method call. | |
231 void OnGetManagedObjects(Response* response); | |
232 | |
233 // Called by dbus:: when an InterfacesAdded signal is received and initially | |
234 // connected. | |
235 void InterfacesAddedReceived(Signal* signal); | |
236 void InterfacesAddedConnected(const std::string& interface_name, | |
237 const std::string& signal_name, | |
238 bool success); | |
239 | |
240 // Called by dbus:: when an InterfacesRemoved signal is received and | |
241 // initially connected. | |
242 void InterfacesRemovedReceived(Signal* signal); | |
243 void InterfacesRemovedConnected(const std::string& interface_name, | |
244 const std::string& signal_name, | |
245 bool success); | |
246 | |
247 // Updates the map entry for the object with path |object_path| using the | |
248 // D-Bus message in |reader|, which should consist of an dictionary mapping | |
249 // interface names to properties dictionaries as recieved by both the | |
250 // GetManagedObjects() method return and the InterfacesAdded() signal. | |
satorux1
2013/03/22 01:41:33
Likewise, having some example of the input message
| |
251 void UpdateObject(const ObjectPath& object_path, MessageReader* reader); | |
252 | |
253 // Updates the properties structure of the object with path |object_path| | |
254 // for the interface named |interface_name| using the D-Bus message in | |
255 // |reader| which should consist of the properties dictionary for that | |
256 // interface. | |
257 // | |
258 // Called by UpdateObjects() for each interface in the dictionary; this | |
259 // method takes care of both creating the entry in the ObjectMap and | |
260 // ObjectProxy if required, as well as the PropertySet instance for that | |
261 // interface if necessary. | |
262 void AddInterface(const ObjectPath& object_path, | |
263 const std::string& interface_name, | |
264 MessageReader* reader); | |
265 | |
266 // Removes the properties structure of the object with path |object_path| | |
267 // for the interfaces named |interface_name|. | |
268 // | |
269 // If no further interfaces remain, the entry in the ObjectMap is discarded. | |
270 void RemoveInterface(const ObjectPath& object_path, | |
271 const std::string& interface_name); | |
272 | |
273 Bus* bus_; | |
satorux1
2013/03/22 01:41:33
Maybe add a comment about the ownership:
Bus* bus
| |
274 std::string service_name_; | |
275 ObjectPath object_path_; | |
276 ObjectProxy* object_proxy_; | |
satorux1
2013/03/22 01:41:33
ditto
| |
277 | |
278 // Maps the name of an interface to the implementation class used for | |
279 // instantiating PropertySet structures for that interface's properties. | |
280 typedef std::map<std::string, Interface*> InterfaceMap; | |
281 InterfaceMap interface_map_; | |
282 | |
283 // Each managed object consists of a ObjectProxy used to make calls | |
284 // against that object and a collection of D-Bus interface names and their | |
285 // associated PropertySet structures. | |
286 struct Object { | |
287 ObjectProxy* object_proxy; | |
288 | |
289 // Maps the name of an interface to the specific PropertySet structure | |
290 // of that interface's properties. | |
291 typedef std::map<const std::string, PropertySet*> PropertiesMap; | |
292 PropertiesMap properties_map; | |
293 }; | |
294 | |
295 // Maps the object path of an object to the Object structure. | |
296 typedef std::map<const ObjectPath, Object*> ObjectMap; | |
297 ObjectMap object_map_; | |
298 | |
299 // Weak pointer factory for generating 'this' pointers that might live longer | |
300 // than we do. | |
301 // Note: This should remain the last member so it'll be destroyed and | |
302 // invalidate its weak pointers before any other members are destroyed. | |
303 base::WeakPtrFactory<ObjectManager> weak_ptr_factory_; | |
304 | |
305 DISALLOW_COPY_AND_ASSIGN(ObjectManager); | |
306 }; | |
307 | |
308 } // namespace dbus | |
309 | |
310 #endif // DBUS_OBJECT_MANAGER_H_ | |
OLD | NEW |