23a88cdc893ed871845a16f5c89b73f7d1302c28
[platform/framework/web/crosswalk.git] / src / dbus / object_manager.h
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) { }
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
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
190   // required.
191   void RegisterInterface(const std::string& interface_name,
192                          Interface* interface);
193
194   // Unregister the implementation class for the D-Bus interface named in
195   // |interface_name|, objects and properties of this interface will be
196   // ignored.
197   void UnregisterInterface(const std::string& interface_name);
198
199   // Returns a list of object paths, in an undefined order, of objects known
200   // to this manager.
201   std::vector<ObjectPath> GetObjects();
202
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);
207
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);
212
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);
220
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();
225
226   // Cleans up any match rules and filter functions added by this ObjectManager.
227   // The Bus object will take care of this so you don't have to do it manually.
228   //
229   // BLOCKING CALL.
230   void CleanUp();
231
232  protected:
233   virtual ~ObjectManager();
234
235  private:
236   friend class base::RefCountedThreadSafe<ObjectManager>;
237
238   // Connects the InterfacesAdded and InterfacesRemoved signals and calls
239   // GetManagedObjects. Called from OnSetupMatchRuleAndFilterComplete.
240   void InitializeObjects();
241
242   // Called from the constructor to add a match rule for PropertiesChanged
243   // signals on the DBus thread and set up a corresponding filter function.
244   bool SetupMatchRuleAndFilter();
245
246   // Called on the origin thread once the match rule and filter have been set
247   // up. |success| is false, if an error occurred during set up; it's true
248   // otherwise.
249   void OnSetupMatchRuleAndFilterComplete(bool success);
250
251   // Called by dbus:: when a message is received. This is used to filter
252   // PropertiesChanged signals from the correct sender and relay the event to
253   // the correct PropertySet.
254   static DBusHandlerResult HandleMessageThunk(DBusConnection* connection,
255                                               DBusMessage* raw_message,
256                                               void* user_data);
257   DBusHandlerResult HandleMessage(DBusConnection* connection,
258                                   DBusMessage* raw_message);
259
260   // Called when a PropertiesChanged signal is received from the sender.
261   // This method notifies the relevant PropertySet that it should update its
262   // properties based on the received signal. Called from HandleMessage.
263   void NotifyPropertiesChanged(const dbus::ObjectPath object_path,
264                                Signal* signal);
265   void NotifyPropertiesChangedHelper(const dbus::ObjectPath object_path,
266                                      Signal* signal);
267
268   // Called by dbus:: in response to the GetManagedObjects() method call.
269   void OnGetManagedObjects(Response* response);
270
271   // Called by dbus:: when an InterfacesAdded signal is received and initially
272   // connected.
273   void InterfacesAddedReceived(Signal* signal);
274   void InterfacesAddedConnected(const std::string& interface_name,
275                                 const std::string& signal_name,
276                                 bool success);
277
278   // Called by dbus:: when an InterfacesRemoved signal is received and
279   // initially connected.
280   void InterfacesRemovedReceived(Signal* signal);
281   void InterfacesRemovedConnected(const std::string& interface_name,
282                                   const std::string& signal_name,
283                                   bool success);
284
285   // Updates the map entry for the object with path |object_path| using the
286   // D-Bus message in |reader|, which should consist of an dictionary mapping
287   // interface names to properties dictionaries as recieved by both the
288   // GetManagedObjects() method return and the InterfacesAdded() signal.
289   void UpdateObject(const ObjectPath& object_path, MessageReader* reader);
290
291   // Updates the properties structure of the object with path |object_path|
292   // for the interface named |interface_name| using the D-Bus message in
293   // |reader| which should consist of the properties dictionary for that
294   // interface.
295   //
296   // Called by UpdateObjects() for each interface in the dictionary; this
297   // method takes care of both creating the entry in the ObjectMap and
298   // ObjectProxy if required, as well as the PropertySet instance for that
299   // interface if necessary.
300   void AddInterface(const ObjectPath& object_path,
301                     const std::string& interface_name,
302                     MessageReader* reader);
303
304   // Removes the properties structure of the object with path |object_path|
305   // for the interfaces named |interface_name|.
306   //
307   // If no further interfaces remain, the entry in the ObjectMap is discarded.
308   void RemoveInterface(const ObjectPath& object_path,
309                        const std::string& interface_name);
310
311   // Removes all objects and interfaces from the object manager when
312   // |old_owner| is not the empty string and/or re-requests the set of managed
313   // objects when |new_owner| is not the empty string.
314   void NameOwnerChanged(const std::string& old_owner,
315                         const std::string& new_owner);
316
317   Bus* bus_;
318   std::string service_name_;
319   std::string service_name_owner_;
320   std::string match_rule_;
321   ObjectPath object_path_;
322   ObjectProxy* object_proxy_;
323   bool setup_success_;
324   bool cleanup_called_;
325
326   // Maps the name of an interface to the implementation class used for
327   // instantiating PropertySet structures for that interface's properties.
328   typedef std::map<std::string, Interface*> InterfaceMap;
329   InterfaceMap interface_map_;
330
331   // Each managed object consists of a ObjectProxy used to make calls
332   // against that object and a collection of D-Bus interface names and their
333   // associated PropertySet structures.
334   struct Object {
335     Object();
336     ~Object();
337
338     ObjectProxy* object_proxy;
339
340     // Maps the name of an interface to the specific PropertySet structure
341     // of that interface's properties.
342     typedef std::map<const std::string, PropertySet*> PropertiesMap;
343     PropertiesMap properties_map;
344   };
345
346   // Maps the object path of an object to the Object structure.
347   typedef std::map<const ObjectPath, Object*> ObjectMap;
348   ObjectMap object_map_;
349
350   // Weak pointer factory for generating 'this' pointers that might live longer
351   // than we do.
352   // Note: This should remain the last member so it'll be destroyed and
353   // invalidate its weak pointers before any other members are destroyed.
354   base::WeakPtrFactory<ObjectManager> weak_ptr_factory_;
355
356   DISALLOW_COPY_AND_ASSIGN(ObjectManager);
357 };
358
359 }  // namespace dbus
360
361 #endif  // DBUS_OBJECT_MANAGER_H_