Chromium Code Reviews| 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. | |
|
satorux1
2013/03/21 05:45:43
Please add a pointer to the spec:
http://dbus.fre
keybuk
2013/03/21 17:50:00
Done.
| |
| 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> 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 setup | |
|
satorux1
2013/03/21 05:45:43
setup -> set up?
keybuk
2013/03/21 17:50:00
Done.
| |
| 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 // The D-Bus thread manager takes care of issuing the necessary call to | |
| 70 // GetManagedObjects() after the implementation classes have been set up. | |
| 71 // | |
| 72 // The object manager interface class has one abstract method that must be | |
| 73 // implemented by the class to create Properties structures on demand. As well | |
| 74 // as implementing this, you will want to implement a public GetProperties() | |
| 75 // method. | |
| 76 // | |
| 77 // Example: | |
| 78 // dbus::PropertySet* CreateProperties(dbus::ObjectProxy* object_proxy, | |
| 79 // const std::string& interface_name) | |
| 80 // OVERRIDE{ | |
|
satorux1
2013/03/21 05:45:43
OVERRIDE {
keybuk
2013/03/21 17:50:00
Done.
| |
| 81 // Properties* properties = new Properties( | |
| 82 // object_proxy, interface_name, | |
| 83 // base::Bind(&PropertyChanged, | |
| 84 // weak_ptr_factory_.GetWeakPtr(), | |
| 85 // object_path)); | |
| 86 // return static_cast<dbus::PropertySet*>(properties); | |
| 87 // } | |
| 88 // | |
| 89 // Properties* GetProperties(const dbus::ObjectPath& object_path) { | |
| 90 // return static_cast<Properties*>( | |
| 91 // object_manager_->GetProperties(object_path, kInterface)); | |
| 92 // } | |
| 93 // | |
| 94 // Note that unlike classes that only use dbus/property.h there is no need | |
| 95 // to connect signals or obtain the initial values of properties. The object | |
| 96 // manager class handles that for you. | |
| 97 // | |
| 98 // PropertyChanged is a method of your own to notify your observers of a change | |
| 99 // in your properties, either as a result of a signal from the Properties | |
| 100 // interface or from the Object Manager interface. You may also wish to | |
| 101 // implement the optional ObjectAdded and ObjectRemoved methods of the class | |
| 102 // to likewise notify observers. | |
| 103 // | |
| 104 // When your class needs an object proxy for a given object path, it may | |
| 105 // obtain it from the object manager. Unlike the equivalent method on the bus | |
| 106 // this will return NULL if the object is not known. | |
| 107 // | |
| 108 // object_proxy = object_manager_->GetObjectProxy(object_path); | |
| 109 // if (object_proxy) { | |
| 110 // ... | |
| 111 // } | |
| 112 // | |
| 113 // There is no need for code using your implementation class to be aware of the | |
| 114 // use of object manager behind the scenes, the rules for updating properties | |
| 115 // documented in dbus/property.h still apply. | |
|
satorux1
2013/03/21 05:45:43
Nicely documented. Thank you for writing this!
| |
| 116 | |
| 117 namespace dbus { | |
| 118 | |
| 119 const char kObjectManagerInterface[] = "org.freedesktop.DBus.ObjectManager"; | |
| 120 const char kObjectManagerGetManagedObjects[] = "GetManagedObjects"; | |
| 121 const char kObjectManagerInterfacesAdded[] = "InterfacesAdded"; | |
| 122 const char kObjectManagerInterfacesRemoved[] = "InterfacesRemoved"; | |
| 123 | |
| 124 class Bus; | |
| 125 class MessageReader; | |
| 126 class ObjectProxy; | |
| 127 class Response; | |
| 128 class Signal; | |
| 129 | |
| 130 // ObjectManager implements both the D-Bus client components of the D-Bus | |
| 131 // Object Manager interface, as internal methods, and a public API for | |
| 132 // client classes to utilize. | |
| 133 class CHROME_DBUS_EXPORT ObjectManager | |
| 134 : public base::RefCountedThreadSafe<ObjectManager> { | |
| 135 public: | |
| 136 // ObjectManager::Interface must be implemented by any class wishing to have | |
| 137 // its remote objects managed by an ObjectManager. | |
| 138 class Interface { | |
| 139 public: | |
| 140 virtual ~Interface() {} | |
| 141 | |
| 142 // Called by ObjectManager to create a Properties structure for the remote | |
| 143 // D-Bus object identified by |object_path| and accessibile through | |
| 144 // |object_proxy|. The D-Bus interface name |interface_name| is that passed | |
| 145 // to RegisterInterface() by the implementation class. | |
| 146 // | |
| 147 // The implementation class should create and return an instance of its own | |
| 148 // subclass of dbus::PropertySet; ObjectManager will then connect signals | |
| 149 // and update the properties from its own internal message reader. | |
| 150 virtual PropertySet* CreateProperties( | |
| 151 ObjectProxy *object_proxy, | |
| 152 const dbus::ObjectPath& object_path, | |
| 153 const std::string& interface_name) = 0; | |
| 154 | |
| 155 // Called by ObjectManager to inform the implementation class that an | |
| 156 // object has been added with the path |object_path|. The D-Bus interface | |
| 157 // name |interface_name| is that passed to RegisterInterface() by the | |
| 158 // implementation class. | |
| 159 // | |
| 160 // If a new object implements multiple interfaces, this method will be | |
| 161 // called on each interface implementation with differing values of | |
| 162 // |interface_name| as appropriate. An implementation class will only | |
| 163 // receive multiple calls if it has registered for multiple interfaces. | |
| 164 virtual void ObjectAdded(const ObjectPath& object_path, | |
| 165 const std::string& interface_name) { } | |
| 166 | |
| 167 // Called by ObjectManager to inform the implementation class than an | |
| 168 // object with the path |object_path| has been removed. Ths D-Bus interface | |
| 169 // name |interface_name| is that passed to RegisterInterface() by the | |
| 170 // implementation class. Multiple interfaces are handled as with | |
| 171 // ObjectAdded(). | |
| 172 // | |
| 173 // This method will be called before the Properties structure and the | |
| 174 // ObjectProxy object for the given interface are cleaned up, it is safe | |
| 175 // to retrieve them during removal to vary processing. | |
| 176 virtual void ObjectRemoved(const ObjectPath& object_path, | |
| 177 const std::string& interface_name) { } | |
| 178 }; | |
|
satorux1
2013/03/21 05:45:43
You might want to externalize this class as Object
keybuk
2013/03/21 17:50:00
You can't inherit from forward-declared classes, y
satorux1
2013/03/22 01:41:33
Sounds reasonable.
| |
| 179 | |
| 180 // Client code should use Bus::GetObjectManager() instead of this constructor. | |
| 181 ObjectManager(Bus* bus, | |
| 182 const std::string& service_name, | |
| 183 const ObjectPath& object_path); | |
| 184 virtual ~ObjectManager(); | |
| 185 | |
| 186 // Register a client implementation class |interface| for the given D-Bus | |
| 187 // interface named in |interface_name|. That object's CreateProperties() | |
| 188 // method will be used to create instances of dbus::PropertySet* when | |
| 189 // required. | |
| 190 void RegisterInterface(const std::string& interface_name, | |
| 191 Interface* interface); | |
| 192 | |
| 193 // Unregister the implementation class for the D-Bus interface named in | |
| 194 // |interface_name|, objects and properties of this interface will be | |
| 195 // ignored. | |
| 196 void UnregisterInterface(const std::string& interface_name); | |
| 197 | |
| 198 // Returns the list of object paths of objects known to this manager. | |
| 199 std::vector<ObjectPath> GetObjects(); | |
|
satorux1
2013/03/21 05:45:43
Might want to mention that the order is undefined?
keybuk
2013/03/21 17:50:00
Done.
| |
| 200 | |
| 201 // Returns the list of object paths of objects implementing the interface | |
|
satorux1
2013/03/21 05:45:43
ditto.
keybuk
2013/03/21 17:50:00
Done.
| |
| 202 // named in |interface_name| known to this manager. | |
| 203 std::vector<ObjectPath> GetObjectsWithInterface( | |
| 204 const std::string& interface_name); | |
| 205 | |
| 206 // Returns a ObjectProxy pointer for the given |object_path|. Unlike | |
| 207 // the equivalent method on Bus this will return NULL if the object | |
| 208 // manager has not been informed of that object's existance. | |
| 209 ObjectProxy* GetObjectProxy(const ObjectPath& object_path); | |
| 210 | |
| 211 // Returns a PropertySet* pointer for the given |object_path| and | |
| 212 // |interface_name|, or NULL if the object manager has not been informed of | |
| 213 // that object's existance or the interface's properties. The caller should | |
| 214 // cast the returned pointer to the appropriate type, e.g.: | |
| 215 // static_cast<Properties*>(GetProperties(object_path, my_interface)); | |
| 216 PropertySet* GetProperties(const ObjectPath& object_path, | |
| 217 const std::string& interface_name); | |
| 218 | |
| 219 // Instructs the object manager to refresh its list of managed objects; | |
| 220 // automatically called by the D-Bus thread manager, there should never be | |
| 221 // a need to call this manually. | |
| 222 void GetManagedObjects(); | |
| 223 | |
| 224 private: | |
| 225 friend class base::RefCountedThreadSafe<ObjectManager>; | |
| 226 | |
| 227 typedef std::map<std::string, Interface*> InterfaceMap; | |
|
satorux1
2013/03/21 05:45:43
Please document. Key is an interface name, right?
keybuk
2013/03/21 17:50:00
Done.
| |
| 228 InterfaceMap interface_map_; | |
| 229 | |
| 230 // Each managed object consists of a ObjectProxy used to make calls | |
| 231 // against that object and a collection of D-Bus interface names and their | |
| 232 // associated PropertySet structures. | |
| 233 struct Object { | |
| 234 ObjectProxy* object_proxy; | |
| 235 | |
| 236 typedef std::map<const std::string, PropertySet*> PropertiesMap; | |
| 237 PropertiesMap properties_map; | |
| 238 }; | |
| 239 | |
| 240 typedef std::map<const ObjectPath, Object*> ObjectMap; | |
| 241 ObjectMap object_map_; | |
|
satorux1
2013/03/21 05:45:43
Per the style guide, data members should be placed
keybuk
2013/03/21 17:50:00
Done.
| |
| 242 | |
| 243 void OnGetManagedObjects(Response* response); | |
| 244 | |
| 245 void InterfacesAddedReceived(Signal* signal); | |
| 246 void InterfacesAddedConnected(const std::string& interface_name, | |
| 247 const std::string& signal_name, | |
| 248 bool success); | |
| 249 | |
| 250 void InterfacesRemovedReceived(Signal* signal); | |
| 251 void InterfacesRemovedConnected(const std::string& interface_name, | |
| 252 const std::string& signal_name, | |
| 253 bool success); | |
| 254 | |
| 255 void UpdateObject(const ObjectPath& object_path, MessageReader* reader); | |
| 256 void AddInterface(const ObjectPath& object_path, | |
| 257 const std::string& interface_name, | |
| 258 MessageReader* reader); | |
| 259 void RemoveInterface(const ObjectPath& object_path, | |
| 260 const std::string& interface_name); | |
|
satorux1
2013/03/21 05:45:43
Could you add comments for the three non-trivial f
keybuk
2013/03/21 17:50:00
Done.
| |
| 261 | |
| 262 Bus* bus_; | |
| 263 std::string service_name_; | |
| 264 ObjectPath object_path_; | |
| 265 ObjectProxy* object_proxy_; | |
| 266 | |
| 267 // Weak pointer factory for generating 'this' pointers that might live longer | |
| 268 // than we do. | |
| 269 // Note: This should remain the last member so it'll be destroyed and | |
| 270 // invalidate its weak pointers before any other members are destroyed. | |
| 271 base::WeakPtrFactory<ObjectManager> weak_ptr_factory_; | |
| 272 | |
| 273 DISALLOW_COPY_AND_ASSIGN(ObjectManager); | |
| 274 }; | |
| 275 | |
| 276 } // namespace dbus | |
| 277 | |
| 278 #endif // DBUS_OBJECT_MANAGER_H_ | |
| OLD | NEW |