Index: dbus/object_manager.h |
diff --git a/dbus/object_manager.h b/dbus/object_manager.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..42ff9eca65197a8290c2753d0b824869fd512e7e |
--- /dev/null |
+++ b/dbus/object_manager.h |
@@ -0,0 +1,310 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef DBUS_OBJECT_MANAGER_H_ |
+#define DBUS_OBJECT_MANAGER_H_ |
+ |
+#include <map> |
+ |
+#include "base/memory/ref_counted.h" |
+#include "base/memory/weak_ptr.h" |
+#include "dbus/object_path.h" |
+#include "dbus/property.h" |
+ |
+// Newer D-Bus services implement the Object Manager interface to inform other |
+// clients about the objects they export, the properties of those objects, and |
+// notification of changes in the set of available objects: |
+// http://dbus.freedesktop.org/doc/dbus-specification.html |
+// #standard-interfaces-objectmanager |
+// |
+// This interface is very closely tied to the Properties interface, and uses |
+// even more levels of nested dictionaries and variants. In addition to |
+// simplifying implementation, since there tends to be a single object manager |
+// per service, spanning the complete set of objects an interfaces available, |
+// the classes implemented here make dealing with this interface simpler. |
+// |
+// Except where noted, use of this class replaces the need for the code |
+// documented in dbus/property.h |
+// |
+// Client implementation classes should begin by deriving from the |
+// dbus::ObjectManager::Interface class, and defining a Properties structure as |
+// documented in dbus/property.h. |
+// |
+// Example: |
+// class ExampleClient : public dbus::ObjectManager::Interface { |
+// public: |
+// struct Properties : public dbus::PropertySet { |
+// dbus::Property<std::string> name; |
+// dbus::Property<uint16> version; |
+// dbus::Property<dbus::ObjectPath> parent; |
+// dbus::Property<std::vector<std::string> > children; |
+// |
+// Properties(dbus::ObjectProxy* object_proxy, |
+// const PropertyChangedCallback callback) |
+// : dbus::PropertySet(object_proxy, kExampleInterface, callback) { |
+// RegisterProperty("Name", &name); |
+// RegisterProperty("Version", &version); |
+// RegisterProperty("Parent", &parent); |
+// RegisterProperty("Children", &children); |
+// } |
+// virtual ~Properties() {} |
+// }; |
+// |
+// The link between the implementation class and the object manager is set up |
+// in the constructor and removed in the destructor; the class should maintain |
+// a pointer to its object manager for use in other methods and establish |
+// itself as the implementation class for its interface. |
+// |
+// Example: |
+// explicit ExampleClient::ExampleClient(dbus::Bus* bus) |
+// : bus_(bus), |
+// weak_ptr_factory_(this) { |
+// object_manager_ = bus_->GetObjectManager(kServiceName, kManagerPath); |
+// object_manager_->RegisterInterface(kInterface, this); |
+// } |
+// |
+// virtual ExampleClient::~ExampleClient() { |
+// object_manager_->UnregisterInterface(kInterface); |
+// } |
+// |
+// The D-Bus thread manager takes care of issuing the necessary call to |
+// GetManagedObjects() after the implementation classes have been set up. |
+// |
+// The object manager interface class has one abstract method that must be |
+// implemented by the class to create Properties structures on demand. As well |
+// as implementing this, you will want to implement a public GetProperties() |
+// method. |
+// |
+// Example: |
+// dbus::PropertySet* CreateProperties(dbus::ObjectProxy* object_proxy, |
+// const std::string& interface_name) |
+// OVERRIDE { |
+// Properties* properties = new Properties( |
+// object_proxy, interface_name, |
+// base::Bind(&PropertyChanged, |
+// weak_ptr_factory_.GetWeakPtr(), |
+// object_path)); |
+// return static_cast<dbus::PropertySet*>(properties); |
+// } |
+// |
+// Properties* GetProperties(const dbus::ObjectPath& object_path) { |
+// return static_cast<Properties*>( |
+// object_manager_->GetProperties(object_path, kInterface)); |
+// } |
+// |
+// Note that unlike classes that only use dbus/property.h there is no need |
+// to connect signals or obtain the initial values of properties. The object |
+// manager class handles that for you. |
+// |
+// PropertyChanged is a method of your own to notify your observers of a change |
+// in your properties, either as a result of a signal from the Properties |
+// interface or from the Object Manager interface. You may also wish to |
+// implement the optional ObjectAdded and ObjectRemoved methods of the class |
+// to likewise notify observers. |
+// |
+// When your class needs an object proxy for a given object path, it may |
+// obtain it from the object manager. Unlike the equivalent method on the bus |
+// this will return NULL if the object is not known. |
+// |
+// object_proxy = object_manager_->GetObjectProxy(object_path); |
+// if (object_proxy) { |
+// ... |
+// } |
+// |
+// There is no need for code using your implementation class to be aware of the |
+// use of object manager behind the scenes, the rules for updating properties |
+// documented in dbus/property.h still apply. |
+ |
+namespace dbus { |
+ |
+const char kObjectManagerInterface[] = "org.freedesktop.DBus.ObjectManager"; |
+const char kObjectManagerGetManagedObjects[] = "GetManagedObjects"; |
+const char kObjectManagerInterfacesAdded[] = "InterfacesAdded"; |
+const char kObjectManagerInterfacesRemoved[] = "InterfacesRemoved"; |
+ |
+class Bus; |
+class MessageReader; |
+class ObjectProxy; |
+class Response; |
+class Signal; |
+ |
+// ObjectManager implements both the D-Bus client components of the D-Bus |
+// Object Manager interface, as internal methods, and a public API for |
+// client classes to utilize. |
+class CHROME_DBUS_EXPORT ObjectManager |
+ : public base::RefCountedThreadSafe<ObjectManager> { |
+public: |
+ // ObjectManager::Interface must be implemented by any class wishing to have |
+ // its remote objects managed by an ObjectManager. |
+ class Interface { |
+ public: |
+ virtual ~Interface() {} |
+ |
+ // Called by ObjectManager to create a Properties structure for the remote |
+ // D-Bus object identified by |object_path| and accessibile through |
+ // |object_proxy|. The D-Bus interface name |interface_name| is that passed |
+ // to RegisterInterface() by the implementation class. |
+ // |
+ // The implementation class should create and return an instance of its own |
+ // subclass of dbus::PropertySet; ObjectManager will then connect signals |
+ // and update the properties from its own internal message reader. |
+ virtual PropertySet* CreateProperties( |
+ ObjectProxy *object_proxy, |
+ const dbus::ObjectPath& object_path, |
+ const std::string& interface_name) = 0; |
+ |
+ // Called by ObjectManager to inform the implementation class that an |
+ // object has been added with the path |object_path|. The D-Bus interface |
+ // name |interface_name| is that passed to RegisterInterface() by the |
+ // implementation class. |
+ // |
+ // If a new object implements multiple interfaces, this method will be |
+ // called on each interface implementation with differing values of |
+ // |interface_name| as appropriate. An implementation class will only |
+ // receive multiple calls if it has registered for multiple interfaces. |
+ virtual void ObjectAdded(const ObjectPath& object_path, |
+ const std::string& interface_name) { } |
+ |
+ // Called by ObjectManager to inform the implementation class than an |
+ // object with the path |object_path| has been removed. Ths D-Bus interface |
+ // name |interface_name| is that passed to RegisterInterface() by the |
+ // implementation class. Multiple interfaces are handled as with |
+ // ObjectAdded(). |
+ // |
+ // This method will be called before the Properties structure and the |
+ // ObjectProxy object for the given interface are cleaned up, it is safe |
+ // to retrieve them during removal to vary processing. |
+ virtual void ObjectRemoved(const ObjectPath& object_path, |
+ 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
|
+ }; |
+ |
+ // Client code should use Bus::GetObjectManager() instead of this constructor. |
+ ObjectManager(Bus* bus, |
+ const std::string& service_name, |
+ const ObjectPath& object_path); |
+ virtual ~ObjectManager(); |
+ |
+ // Register a client implementation class |interface| for the given D-Bus |
+ // interface named in |interface_name|. That object's CreateProperties() |
+ // method will be used to create instances of dbus::PropertySet* when |
+ // required. |
+ void RegisterInterface(const std::string& interface_name, |
+ Interface* interface); |
+ |
+ // Unregister the implementation class for the D-Bus interface named in |
+ // |interface_name|, objects and properties of this interface will be |
+ // ignored. |
+ void UnregisterInterface(const std::string& interface_name); |
+ |
+ // Returns a list of object paths, in an undefined order, of objects known |
+ // to this manager. |
+ std::vector<ObjectPath> GetObjects(); |
+ |
+ // Returns the list of object paths, in an undefined order, of objects |
+ // implementing the interface named in |interface_name| known to this manager. |
+ std::vector<ObjectPath> GetObjectsWithInterface( |
+ const std::string& interface_name); |
+ |
+ // Returns a ObjectProxy pointer for the given |object_path|. Unlike |
+ // the equivalent method on Bus this will return NULL if the object |
+ // manager has not been informed of that object's existance. |
+ ObjectProxy* GetObjectProxy(const ObjectPath& object_path); |
+ |
+ // Returns a PropertySet* pointer for the given |object_path| and |
+ // |interface_name|, or NULL if the object manager has not been informed of |
+ // that object's existance or the interface's properties. The caller should |
+ // cast the returned pointer to the appropriate type, e.g.: |
+ // static_cast<Properties*>(GetProperties(object_path, my_interface)); |
+ PropertySet* GetProperties(const ObjectPath& object_path, |
+ const std::string& interface_name); |
+ |
+ // Instructs the object manager to refresh its list of managed objects; |
+ // automatically called by the D-Bus thread manager, there should never be |
+ // a need to call this manually. |
+ void GetManagedObjects(); |
satorux1
2013/03/22 01:41:33
The message (list of list of dictionaries) we'll r
|
+ |
+ private: |
+ friend class base::RefCountedThreadSafe<ObjectManager>; |
+ |
+ // Called by dbus:: in response to the GetManagedObjects() method call. |
+ void OnGetManagedObjects(Response* response); |
+ |
+ // Called by dbus:: when an InterfacesAdded signal is received and initially |
+ // connected. |
+ void InterfacesAddedReceived(Signal* signal); |
+ void InterfacesAddedConnected(const std::string& interface_name, |
+ const std::string& signal_name, |
+ bool success); |
+ |
+ // Called by dbus:: when an InterfacesRemoved signal is received and |
+ // initially connected. |
+ void InterfacesRemovedReceived(Signal* signal); |
+ void InterfacesRemovedConnected(const std::string& interface_name, |
+ const std::string& signal_name, |
+ bool success); |
+ |
+ // Updates the map entry for the object with path |object_path| using the |
+ // D-Bus message in |reader|, which should consist of an dictionary mapping |
+ // interface names to properties dictionaries as recieved by both the |
+ // GetManagedObjects() method return and the InterfacesAdded() signal. |
satorux1
2013/03/22 01:41:33
Likewise, having some example of the input message
|
+ void UpdateObject(const ObjectPath& object_path, MessageReader* reader); |
+ |
+ // Updates the properties structure of the object with path |object_path| |
+ // for the interface named |interface_name| using the D-Bus message in |
+ // |reader| which should consist of the properties dictionary for that |
+ // interface. |
+ // |
+ // Called by UpdateObjects() for each interface in the dictionary; this |
+ // method takes care of both creating the entry in the ObjectMap and |
+ // ObjectProxy if required, as well as the PropertySet instance for that |
+ // interface if necessary. |
+ void AddInterface(const ObjectPath& object_path, |
+ const std::string& interface_name, |
+ MessageReader* reader); |
+ |
+ // Removes the properties structure of the object with path |object_path| |
+ // for the interfaces named |interface_name|. |
+ // |
+ // If no further interfaces remain, the entry in the ObjectMap is discarded. |
+ void RemoveInterface(const ObjectPath& object_path, |
+ const std::string& interface_name); |
+ |
+ Bus* bus_; |
satorux1
2013/03/22 01:41:33
Maybe add a comment about the ownership:
Bus* bus
|
+ std::string service_name_; |
+ ObjectPath object_path_; |
+ ObjectProxy* object_proxy_; |
satorux1
2013/03/22 01:41:33
ditto
|
+ |
+ // Maps the name of an interface to the implementation class used for |
+ // instantiating PropertySet structures for that interface's properties. |
+ typedef std::map<std::string, Interface*> InterfaceMap; |
+ InterfaceMap interface_map_; |
+ |
+ // Each managed object consists of a ObjectProxy used to make calls |
+ // against that object and a collection of D-Bus interface names and their |
+ // associated PropertySet structures. |
+ struct Object { |
+ ObjectProxy* object_proxy; |
+ |
+ // Maps the name of an interface to the specific PropertySet structure |
+ // of that interface's properties. |
+ typedef std::map<const std::string, PropertySet*> PropertiesMap; |
+ PropertiesMap properties_map; |
+ }; |
+ |
+ // Maps the object path of an object to the Object structure. |
+ typedef std::map<const ObjectPath, Object*> ObjectMap; |
+ ObjectMap object_map_; |
+ |
+ // Weak pointer factory for generating 'this' pointers that might live longer |
+ // than we do. |
+ // Note: This should remain the last member so it'll be destroyed and |
+ // invalidate its weak pointers before any other members are destroyed. |
+ base::WeakPtrFactory<ObjectManager> weak_ptr_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ObjectManager); |
+}; |
+ |
+} // namespace dbus |
+ |
+#endif // DBUS_OBJECT_MANAGER_H_ |