ash: Add launcher overflow bubble.
[chromium-blink-merge.git] / dbus / property.h
bloba3fb5ca76e0c5de85f1ad865615c6c1590a92975
1 // Copyright (c) 2012 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_PROPERTY_H_
6 #define DBUS_PROPERTY_H_
8 #include <map>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "dbus/message.h"
15 #include "dbus/object_proxy.h"
17 // D-Bus objects frequently provide sets of properties accessed via a
18 // standard interface of method calls and signals to obtain the current value,
19 // set a new value and be notified of changes to the value. Unfortunately this
20 // interface makes heavy use of variants and dictionaries of variants. The
21 // classes defined here make dealing with properties in a type-safe manner
22 // possible.
24 // Client implementation classes should define a Properties structure, deriving
25 // from the PropertySet class defined here. This structure should contain a
26 // member for each property defined as an instance of the Property<> class,
27 // specifying the type to the template. Finally the structure should chain up
28 // to the PropertySet constructor, and then call RegisterProperty() for each
29 // property defined to associate them with their string name.
31 // Example:
32 // class ExampleClient {
33 // public:
34 // struct Properties : public dbus::PropertySet {
35 // dbus::Property<std::string> name;
36 // dbus::Property<uint16> version;
37 // dbus::Property<dbus::ObjectPath> parent;
38 // dbus::Property<std::vector<std::string> > children;
40 // Properties(dbus::ObjectProxy* object_proxy,
41 // PropertyChangedCallback callback)
42 // : dbus::PropertySet(object_proxy, "com.example.DBus", callback) {
43 // RegisterProperty("Name", &name);
44 // RegisterProperty("Version", &version);
45 // RegisterProperty("Parent", &parent);
46 // RegisterProperty("Children", &children);
47 // }
48 // virtual ~Properties() {}
49 // };
51 // The Properties structure requires a pointer to the object proxy of the
52 // actual object to track, and after construction should have signals
53 // connected to that object and initial values set by calling ConnectSignals()
54 // and GetAll(). The structure should not outlive the object proxy, so it
55 // is recommended that the lifecycle of both be managed together.
57 // Example (continued):
59 // typedef std::map<std::pair<dbus::ObjectProxy*, Properties*> > Object;
60 // typedef std::map<dbus::ObjectPath, Object> ObjectMap;
61 // ObjectMap object_map_;
63 // dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) {
64 // return GetObject(object_path).first;
65 // }
67 // Properties* GetProperties(const dbus::ObjectPath& object_path) {
68 // return GetObject(object_path).second;
69 // }
71 // Object GetObject(const dbus::ObjectPath& object_path) {
72 // ObjectMap::iterator it = object_map_.find(object_path);
73 // if (it != object_map_.end())
74 // return it->second;
76 // dbus::ObjectProxy* object_proxy = bus->GetObjectProxy(...);
77 // // connect signals, etc.
79 // Properties* properties = new Properties(
80 // object_proxy,
81 // base::Bind(&PropertyChanged,
82 // weak_ptr_factory_.GetWeakPtr(),
83 // object_path));
84 // properties->ConnectSignals();
85 // properties->GetAll();
87 // Object object = std::make_pair(object_proxy, properties);
88 // object_map_[object_path] = object;
89 // return object;
90 // }
91 // };
93 // This now allows code using the client implementation to access properties
94 // in a type-safe manner, and assuming the PropertyChanged callback is
95 // propogated up to observers, be notified of changes. A typical access of
96 // the current value of the name property would be:
98 // ExampleClient::Properties* p = example_client->GetProperties(object_path);
99 // std::string name = p->name.value();
101 // Normally these values are updated from signals emitted by the remote object,
102 // in case an explicit round-trip is needed to obtain the current value, the
103 // Get() method can be used and indicates whether or not the value update was
104 // successful. The updated value can be obtained in the callback using the
105 // value() method.
107 // p->children.Get(base::Bind(&OnGetChildren));
109 // A new value can be set using the Set() method, the callback indicates
110 // success only; it is up to the remote object when (and indeed if) it updates
111 // the property value, and whether it emits a signal or a Get() call is
112 // required to obtain it.
114 // p->version.Set(20, base::Bind(&OnSetVersion))
116 namespace dbus {
118 // D-Bus Properties interface constants, declared here rather than
119 // in property.cc because template methods use them.
120 const char kPropertiesInterface[] = "org.freedesktop.DBus.Properties";
121 const char kPropertiesGetAll[] = "GetAll";
122 const char kPropertiesGet[] = "Get";
123 const char kPropertiesSet[] = "Set";
124 const char kPropertiesChanged[] = "PropertiesChanged";
126 class PropertySet;
128 // PropertyBase is an abstract base-class consisting of the parts of
129 // the Property<> template that are not type-specific, such as the
130 // associated PropertySet, property name, and the type-unsafe parts
131 // used by PropertySet.
132 class PropertyBase {
133 public:
134 PropertyBase() : property_set_(NULL) {}
136 // Initializes the |property_set| and property |name| so that method
137 // calls may be made from this class. This method is called by
138 // PropertySet::RegisterProperty() passing |this| for |property_set| so
139 // there should be no need to call it directly. If you do beware that
140 // no ownership or reference to |property_set| is taken so that object
141 // must outlive this one.
142 void Init(PropertySet* property_set, const std::string& name);
144 // Retrieves the name of this property, this may be useful in observers
145 // to avoid specifying the name in more than once place, e.g.
147 // void Client::PropertyChanged(const dbus::ObjectPath& object_path,
148 // const std::string &property_name) {
149 // Properties& properties = GetProperties(object_path);
150 // if (property_name == properties.version.name()) {
151 // // Handle version property changing
152 // }
153 // }
154 const std::string& name() const { return name_; }
156 // Method used by PropertySet to retrieve the value from a MessageReader,
157 // no knowledge of the contained type is required, this method returns
158 // true if its expected type was found, false if not.
159 // Implementation provided by specialization.
160 virtual bool PopValueFromReader(MessageReader*) = 0;
162 // Method used by PropertySet to append the set value to a MessageWriter,
163 // no knowledge of the contained type is required.
164 // Implementation provided by specialization.
165 virtual void AppendSetValueToWriter(MessageWriter* writer) = 0;
167 protected:
168 // Retrieves the associated property set.
169 PropertySet* property_set() { return property_set_; }
171 private:
172 // Pointer to the PropertySet instance that this instance is a member of,
173 // no ownership is taken and |property_set_| must outlive this class.
174 PropertySet* property_set_;
176 // Name of the property.
177 std::string name_;
179 DISALLOW_COPY_AND_ASSIGN(PropertyBase);
182 // PropertySet groups a collection of properties for a remote object
183 // together into a single structure, fixing their types and name such
184 // that calls made through it are type-safe.
186 // Clients always sub-class this to add the properties, and should always
187 // provide a constructor that chains up to this and then calls
188 // RegisterProperty() for each property defined.
190 // After creation, client code should call ConnectSignals() and most likely
191 // GetAll() to seed initial values and update as changes occur.
192 class PropertySet {
193 public:
194 // Callback for changes to cached values of properties, either notified
195 // via signal, or as a result of calls to Get() and GetAll(). The |name|
196 // argument specifies the name of the property changed.
197 typedef base::Callback<void(const std::string& name)> PropertyChangedCallback;
199 // Constructs a property set, where |object_proxy| specifies the proxy for
200 // the/ remote object that these properties are for, care should be taken to
201 // ensure that this object does not outlive the lifetime of the proxy;
202 // |interface| specifies the D-Bus interface of these properties, and
203 // |property_changed_callback| specifies the callback for when properties
204 // are changed, this may be a NULL callback.
205 PropertySet(ObjectProxy* object_proxy, const std::string& interface,
206 PropertyChangedCallback property_changed_callback);
208 // Destructor; we don't hold on to any references or memory that needs
209 // explicit clean-up, but clang thinks we might.
210 virtual ~PropertySet();
212 // Registers a property, generally called from the subclass constructor;
213 // pass the |name| of the property as used in method calls and signals,
214 // and the pointer to the |property| member of the structure. This will
215 // call the PropertyBase::Init method.
216 void RegisterProperty(const std::string& name, PropertyBase* property);
218 // Connects property change notification signals to the object, generally
219 // called immediately after the object is created and before calls to other
220 // methods. Sub-classes may override to use different D-Bus signals.
221 virtual void ConnectSignals();
223 // Methods connected by ConnectSignals() and called by dbus:: when
224 // a property is changed. Sub-classes may override if the property
225 // changed signal provides different arguments.
226 virtual void ChangedReceived(Signal*);
227 virtual void ChangedConnected(const std::string& interface_name,
228 const std::string& signal_name,
229 bool success);
231 // Callback for Get() method, |success| indicates whether or not the
232 // value could be retrived, if true the new value can be obtained by
233 // calling value() on the property.
234 typedef base::Callback<void(bool success)> GetCallback;
236 // Requests an updated value from the remote object for |property|
237 // incurring a round-trip. |callback| will be called when the new
238 // value is available. This may not be implemented by some interfaces,
239 // and may be overriden by sub-classes if interfaces use different
240 // method calls.
241 virtual void Get(PropertyBase* property, GetCallback callback);
242 virtual void OnGet(PropertyBase* property, GetCallback callback,
243 Response* response);
245 // Queries the remote object for values of all properties and updates
246 // initial values. Sub-classes may override to use a different D-Bus
247 // method, or if the remote object does not support retrieving all
248 // properties, either ignore or obtain each property value individually.
249 virtual void GetAll();
250 virtual void OnGetAll(Response* response);
252 // Callback for Set() method, |success| indicates whether or not the
253 // new property value was accepted by the remote object.
254 typedef base::Callback<void(bool success)> SetCallback;
256 // Requests that the remote object for |property| change the property to
257 // its new value. |callback| will be called to indicate the success or
258 // failure of the request, however the new value may not be available
259 // depending on the remote object. This method may be overridden by
260 // sub-classes if interfaces use different method calls.
261 virtual void Set(PropertyBase* property, SetCallback callback);
262 virtual void OnSet(PropertyBase* property, SetCallback callback,
263 Response* response);
265 // Update properties by reading an array of dictionary entries, each
266 // containing a string with the name and a variant with the value, from
267 // |message_reader|. Returns false if message is in incorrect format.
268 bool UpdatePropertiesFromReader(MessageReader* reader);
270 // Updates a single property by reading a string with the name and a
271 // variant with the value from |message_reader|. Returns false if message
272 // is in incorrect format, or property type doesn't match.
273 bool UpdatePropertyFromReader(MessageReader* reader);
275 // Calls the property changed callback passed to the constructor, used
276 // by sub-classes that do not call UpdatePropertiesFromReader() or
277 // UpdatePropertyFromReader(). Takes the |name| of the changed property.
278 void NotifyPropertyChanged(const std::string& name);
280 // Retrieves the object proxy this property set was initialized with,
281 // provided for sub-classes overriding methods that make D-Bus calls
282 // and for Property<>. Not permitted with const references to this class.
283 ObjectProxy* object_proxy() { return object_proxy_; }
285 // Retrieves the interface of this property set.
286 const std::string& interface() const { return interface_; }
288 protected:
289 // Get a weak pointer to this property set, provided so that sub-classes
290 // overriding methods that make D-Bus calls may use the existing (or
291 // override) callbacks without providing their own weak pointer factory.
292 base::WeakPtr<PropertySet> GetWeakPtr() {
293 return weak_ptr_factory_.GetWeakPtr();
296 private:
297 // Pointer to object proxy for making method calls, no ownership is taken
298 // so this must outlive this class.
299 ObjectProxy* object_proxy_;
301 // Interface of property, e.g. "org.chromium.ExampleService", this is
302 // distinct from the interface of the method call itself which is the
303 // general D-Bus Properties interface "org.freedesktop.DBus.Properties".
304 std::string interface_;
306 // Callback for property changes.
307 PropertyChangedCallback property_changed_callback_;
309 // Map of properties (as PropertyBase*) defined in the structure to
310 // names as used in D-Bus method calls and signals. The base pointer
311 // restricts property access via this map to type-unsafe and non-specific
312 // actions only.
313 typedef std::map<const std::string, PropertyBase*> PropertiesMap;
314 PropertiesMap properties_map_;
316 // Weak pointer factory as D-Bus callbacks may last longer than these
317 // objects.
318 base::WeakPtrFactory<PropertySet> weak_ptr_factory_;
320 DISALLOW_COPY_AND_ASSIGN(PropertySet);
323 // Property template, this defines the type-specific and type-safe methods
324 // of properties that can be accessed as members of a PropertySet structure.
326 // Properties provide a cached value that has an initial sensible default
327 // until the reply to PropertySet::GetAll() is retrieved and is updated by
328 // all calls to that method, PropertySet::Get() and property changed signals
329 // also handled by PropertySet. It can be obtained by calling value() on the
330 // property.
332 // It is recommended that this cached value be used where necessary, with
333 // code using PropertySet::PropertyChangedCallback to be notified of changes,
334 // rather than incurring a round-trip to the remote object for each property
335 // access.
337 // Where a round-trip is necessary, the Get() method is provided. And to
338 // update the remote object value, the Set() method is also provided; these
339 // both simply call methods on PropertySet.
341 // Handling of particular D-Bus types is performed via specialization,
342 // typically the PopValueFromReader() and AppendSetValueToWriter() methods
343 // will need to be provided, and in rare cases a constructor to provide a
344 // default value. Specializations for basic D-Bus types, strings, object
345 // paths and arrays are provided for you.
346 template <class T>
347 class Property : public PropertyBase {
348 public:
349 Property() {}
351 // Retrieves the cached value.
352 const T& value() const { return value_; }
354 // Requests an updated value from the remote object incurring a
355 // round-trip. |callback| will be called when the new value is available.
356 // This may not be implemented by some interfaces.
357 virtual void Get(dbus::PropertySet::GetCallback callback) {
358 property_set()->Get(this, callback);
361 // Requests that the remote object change the property value to |value|,
362 // |callback| will be called to indicate the success or failure of the
363 // request, however the new value may not be available depending on the
364 // remote object.
365 virtual void Set(const T& value, dbus::PropertySet::SetCallback callback) {
366 set_value_ = value;
367 property_set()->Set(this, callback);
370 // Method used by PropertySet to retrieve the value from a MessageReader,
371 // no knowledge of the contained type is required, this method returns
372 // true if its expected type was found, false if not.
373 virtual bool PopValueFromReader(MessageReader*);
375 // Method used by PropertySet to append the set value to a MessageWriter,
376 // no knowledge of the contained type is required.
377 // Implementation provided by specialization.
378 virtual void AppendSetValueToWriter(MessageWriter* writer);
380 private:
381 // Current cached value of the property.
382 T value_;
384 // Replacement value of the property.
385 T set_value_;
388 } // namespace dbus
390 #endif // DBUS_PROPERTY_H_