blob: efbad226a69d16333ea49b5911e4ef2f659aa519 [file] [log] [blame]
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +09001// 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.
4
5#ifndef DBUS_PROPERTY_H_
6#define DBUS_PROPERTY_H_
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +09007
avi0ad0ce02015-12-23 03:12:45 +09008#include <stdint.h>
9
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090010#include <map>
11#include <string>
dtapuska95f71722015-02-10 01:02:55 +090012#include <utility>
13#include <vector>
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090014
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090015#include "base/bind.h"
16#include "base/callback.h"
avi0ad0ce02015-12-23 03:12:45 +090017#include "base/macros.h"
tfarina@chromium.org7928ea22012-11-05 10:56:14 +090018#include "dbus/dbus_export.h"
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090019#include "dbus/message.h"
20#include "dbus/object_proxy.h"
21
22// D-Bus objects frequently provide sets of properties accessed via a
23// standard interface of method calls and signals to obtain the current value,
24// set a new value and be notified of changes to the value. Unfortunately this
25// interface makes heavy use of variants and dictionaries of variants. The
26// classes defined here make dealing with properties in a type-safe manner
27// possible.
28//
29// Client implementation classes should define a Properties structure, deriving
30// from the PropertySet class defined here. This structure should contain a
31// member for each property defined as an instance of the Property<> class,
32// specifying the type to the template. Finally the structure should chain up
33// to the PropertySet constructor, and then call RegisterProperty() for each
34// property defined to associate them with their string name.
35//
36// Example:
37// class ExampleClient {
38// public:
39// struct Properties : public dbus::PropertySet {
40// dbus::Property<std::string> name;
avi0ad0ce02015-12-23 03:12:45 +090041// dbus::Property<uint16_t> version;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090042// dbus::Property<dbus::ObjectPath> parent;
43// dbus::Property<std::vector<std::string> > children;
44//
45// Properties(dbus::ObjectProxy* object_proxy,
keybuk@chromium.orgb45e5292012-08-15 10:03:30 +090046// const PropertyChangedCallback callback)
keybuk@chromium.orgf63debc2012-02-18 01:50:42 +090047// : dbus::PropertySet(object_proxy, "com.example.DBus", callback) {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090048// RegisterProperty("Name", &name);
49// RegisterProperty("Version", &version);
50// RegisterProperty("Parent", &parent);
51// RegisterProperty("Children", &children);
52// }
keybuk@chromium.orgf63debc2012-02-18 01:50:42 +090053// virtual ~Properties() {}
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090054// };
55//
56// The Properties structure requires a pointer to the object proxy of the
57// actual object to track, and after construction should have signals
58// connected to that object and initial values set by calling ConnectSignals()
59// and GetAll(). The structure should not outlive the object proxy, so it
60// is recommended that the lifecycle of both be managed together.
61//
62// Example (continued):
63//
keybuk@chromium.orgf63debc2012-02-18 01:50:42 +090064// typedef std::map<std::pair<dbus::ObjectProxy*, Properties*> > Object;
65// typedef std::map<dbus::ObjectPath, Object> ObjectMap;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090066// ObjectMap object_map_;
67//
68// dbus::ObjectProxy* GetObjectProxy(const dbus::ObjectPath& object_path) {
69// return GetObject(object_path).first;
70// }
71//
72// Properties* GetProperties(const dbus::ObjectPath& object_path) {
73// return GetObject(object_path).second;
74// }
75//
76// Object GetObject(const dbus::ObjectPath& object_path) {
77// ObjectMap::iterator it = object_map_.find(object_path);
78// if (it != object_map_.end())
79// return it->second;
80//
81// dbus::ObjectProxy* object_proxy = bus->GetObjectProxy(...);
keybuk@chromium.orgf63debc2012-02-18 01:50:42 +090082// // connect signals, etc.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090083//
84// Properties* properties = new Properties(
85// object_proxy,
86// base::Bind(&PropertyChanged,
87// weak_ptr_factory_.GetWeakPtr(),
88// object_path));
89// properties->ConnectSignals();
90// properties->GetAll();
91//
keybuk@chromium.orgf63debc2012-02-18 01:50:42 +090092// Object object = std::make_pair(object_proxy, properties);
93// object_map_[object_path] = object;
94// return object;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +090095// }
96// };
97//
98// This now allows code using the client implementation to access properties
99// in a type-safe manner, and assuming the PropertyChanged callback is
100// propogated up to observers, be notified of changes. A typical access of
101// the current value of the name property would be:
102//
103// ExampleClient::Properties* p = example_client->GetProperties(object_path);
104// std::string name = p->name.value();
105//
106// Normally these values are updated from signals emitted by the remote object,
107// in case an explicit round-trip is needed to obtain the current value, the
108// Get() method can be used and indicates whether or not the value update was
109// successful. The updated value can be obtained in the callback using the
110// value() method.
111//
112// p->children.Get(base::Bind(&OnGetChildren));
113//
114// A new value can be set using the Set() method, the callback indicates
115// success only; it is up to the remote object when (and indeed if) it updates
116// the property value, and whether it emits a signal or a Get() call is
117// required to obtain it.
118//
119// p->version.Set(20, base::Bind(&OnSetVersion))
120
121namespace dbus {
122
123// D-Bus Properties interface constants, declared here rather than
124// in property.cc because template methods use them.
125const char kPropertiesInterface[] = "org.freedesktop.DBus.Properties";
126const char kPropertiesGetAll[] = "GetAll";
127const char kPropertiesGet[] = "Get";
128const char kPropertiesSet[] = "Set";
129const char kPropertiesChanged[] = "PropertiesChanged";
130
131class PropertySet;
132
133// PropertyBase is an abstract base-class consisting of the parts of
134// the Property<> template that are not type-specific, such as the
135// associated PropertySet, property name, and the type-unsafe parts
136// used by PropertySet.
derat3f868a42015-07-17 00:06:44 +0900137class CHROME_DBUS_EXPORT PropertyBase {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900138 public:
derat3f868a42015-07-17 00:06:44 +0900139 PropertyBase();
140 virtual ~PropertyBase();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900141
142 // Initializes the |property_set| and property |name| so that method
143 // calls may be made from this class. This method is called by
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900144 // PropertySet::RegisterProperty() passing |this| for |property_set| so
145 // there should be no need to call it directly. If you do beware that
146 // no ownership or reference to |property_set| is taken so that object
147 // must outlive this one.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900148 void Init(PropertySet* property_set, const std::string& name);
149
150 // Retrieves the name of this property, this may be useful in observers
151 // to avoid specifying the name in more than once place, e.g.
152 //
153 // void Client::PropertyChanged(const dbus::ObjectPath& object_path,
154 // const std::string &property_name) {
155 // Properties& properties = GetProperties(object_path);
156 // if (property_name == properties.version.name()) {
157 // // Handle version property changing
158 // }
159 // }
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900160 const std::string& name() const { return name_; }
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900161
jpawlowski77e73fc2015-05-11 20:07:04 +0900162 // Returns true if property is valid, false otherwise.
163 bool is_valid() const { return is_valid_; }
164
165 // Allows to mark Property as valid or invalid.
166 void set_valid(bool is_valid) { is_valid_ = is_valid; }
167
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900168 // Method used by PropertySet to retrieve the value from a MessageReader,
169 // no knowledge of the contained type is required, this method returns
170 // true if its expected type was found, false if not.
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900171 // Implementation provided by specialization.
dtapuska95f71722015-02-10 01:02:55 +0900172 virtual bool PopValueFromReader(MessageReader* reader) = 0;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900173
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900174 // Method used by PropertySet to append the set value to a MessageWriter,
175 // no knowledge of the contained type is required.
176 // Implementation provided by specialization.
177 virtual void AppendSetValueToWriter(MessageWriter* writer) = 0;
178
keybuk@chromium.orgb45e5292012-08-15 10:03:30 +0900179 // Method used by test and stub implementations of dbus::PropertySet::Set
180 // to replace the property value with the set value without using a
181 // dbus::MessageReader.
182 virtual void ReplaceValueWithSetValue() = 0;
183
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900184 protected:
185 // Retrieves the associated property set.
186 PropertySet* property_set() { return property_set_; }
187
188 private:
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900189 // Pointer to the PropertySet instance that this instance is a member of,
190 // no ownership is taken and |property_set_| must outlive this class.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900191 PropertySet* property_set_;
192
jpawlowski77e73fc2015-05-11 20:07:04 +0900193 bool is_valid_;
194
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900195 // Name of the property.
196 std::string name_;
197
198 DISALLOW_COPY_AND_ASSIGN(PropertyBase);
199};
200
201// PropertySet groups a collection of properties for a remote object
202// together into a single structure, fixing their types and name such
203// that calls made through it are type-safe.
204//
205// Clients always sub-class this to add the properties, and should always
206// provide a constructor that chains up to this and then calls
207// RegisterProperty() for each property defined.
208//
209// After creation, client code should call ConnectSignals() and most likely
210// GetAll() to seed initial values and update as changes occur.
tfarina@chromium.org7928ea22012-11-05 10:56:14 +0900211class CHROME_DBUS_EXPORT PropertySet {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900212 public:
213 // Callback for changes to cached values of properties, either notified
214 // via signal, or as a result of calls to Get() and GetAll(). The |name|
215 // argument specifies the name of the property changed.
216 typedef base::Callback<void(const std::string& name)> PropertyChangedCallback;
217
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900218 // Constructs a property set, where |object_proxy| specifies the proxy for
219 // the/ remote object that these properties are for, care should be taken to
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900220 // ensure that this object does not outlive the lifetime of the proxy;
221 // |interface| specifies the D-Bus interface of these properties, and
222 // |property_changed_callback| specifies the callback for when properties
223 // are changed, this may be a NULL callback.
224 PropertySet(ObjectProxy* object_proxy, const std::string& interface,
keybuk@chromium.orgb45e5292012-08-15 10:03:30 +0900225 const PropertyChangedCallback& property_changed_callback);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900226
227 // Destructor; we don't hold on to any references or memory that needs
228 // explicit clean-up, but clang thinks we might.
keybuk@chromium.org82e082a2012-02-17 10:01:18 +0900229 virtual ~PropertySet();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900230
231 // Registers a property, generally called from the subclass constructor;
232 // pass the |name| of the property as used in method calls and signals,
233 // and the pointer to the |property| member of the structure. This will
234 // call the PropertyBase::Init method.
235 void RegisterProperty(const std::string& name, PropertyBase* property);
236
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900237 // Connects property change notification signals to the object, generally
238 // called immediately after the object is created and before calls to other
239 // methods. Sub-classes may override to use different D-Bus signals.
240 virtual void ConnectSignals();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900241
242 // Methods connected by ConnectSignals() and called by dbus:: when
243 // a property is changed. Sub-classes may override if the property
244 // changed signal provides different arguments.
dtapuska95f71722015-02-10 01:02:55 +0900245 virtual void ChangedReceived(Signal* signal);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900246 virtual void ChangedConnected(const std::string& interface_name,
247 const std::string& signal_name,
248 bool success);
249
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900250 // Callback for Get() method, |success| indicates whether or not the
251 // value could be retrived, if true the new value can be obtained by
252 // calling value() on the property.
253 typedef base::Callback<void(bool success)> GetCallback;
254
255 // Requests an updated value from the remote object for |property|
256 // incurring a round-trip. |callback| will be called when the new
257 // value is available. This may not be implemented by some interfaces,
258 // and may be overriden by sub-classes if interfaces use different
259 // method calls.
260 virtual void Get(PropertyBase* property, GetCallback callback);
261 virtual void OnGet(PropertyBase* property, GetCallback callback,
262 Response* response);
263
nywang80f27162015-09-29 07:46:36 +0900264 // The synchronous version of Get().
265 // This should never be used on an interactive thread.
266 virtual bool GetAndBlock(PropertyBase* property);
267
keybuk@chromium.orgf63debc2012-02-18 01:50:42 +0900268 // Queries the remote object for values of all properties and updates
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900269 // initial values. Sub-classes may override to use a different D-Bus
270 // method, or if the remote object does not support retrieving all
271 // properties, either ignore or obtain each property value individually.
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900272 virtual void GetAll();
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900273 virtual void OnGetAll(Response* response);
274
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900275 // Callback for Set() method, |success| indicates whether or not the
276 // new property value was accepted by the remote object.
277 typedef base::Callback<void(bool success)> SetCallback;
278
279 // Requests that the remote object for |property| change the property to
280 // its new value. |callback| will be called to indicate the success or
281 // failure of the request, however the new value may not be available
282 // depending on the remote object. This method may be overridden by
283 // sub-classes if interfaces use different method calls.
284 virtual void Set(PropertyBase* property, SetCallback callback);
285 virtual void OnSet(PropertyBase* property, SetCallback callback,
286 Response* response);
287
nywang80f27162015-09-29 07:46:36 +0900288 // The synchronous version of Set().
289 // This should never be used on an interactive thread.
290 virtual bool SetAndBlock(PropertyBase* property);
291
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900292 // Update properties by reading an array of dictionary entries, each
293 // containing a string with the name and a variant with the value, from
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900294 // |message_reader|. Returns false if message is in incorrect format.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900295 bool UpdatePropertiesFromReader(MessageReader* reader);
296
297 // Updates a single property by reading a string with the name and a
298 // variant with the value from |message_reader|. Returns false if message
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900299 // is in incorrect format, or property type doesn't match.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900300 bool UpdatePropertyFromReader(MessageReader* reader);
301
302 // Calls the property changed callback passed to the constructor, used
303 // by sub-classes that do not call UpdatePropertiesFromReader() or
304 // UpdatePropertyFromReader(). Takes the |name| of the changed property.
305 void NotifyPropertyChanged(const std::string& name);
306
307 // Retrieves the object proxy this property set was initialized with,
308 // provided for sub-classes overriding methods that make D-Bus calls
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900309 // and for Property<>. Not permitted with const references to this class.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900310 ObjectProxy* object_proxy() { return object_proxy_; }
311
312 // Retrieves the interface of this property set.
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900313 const std::string& interface() const { return interface_; }
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900314
315 protected:
316 // Get a weak pointer to this property set, provided so that sub-classes
317 // overriding methods that make D-Bus calls may use the existing (or
318 // override) callbacks without providing their own weak pointer factory.
319 base::WeakPtr<PropertySet> GetWeakPtr() {
320 return weak_ptr_factory_.GetWeakPtr();
321 }
322
323 private:
jpawlowski77e73fc2015-05-11 20:07:04 +0900324 // Invalidates properties by reading an array of names, from
325 // |message_reader|. Returns false if message is in incorrect format.
326 bool InvalidatePropertiesFromReader(MessageReader* reader);
327
keybuk@chromium.org683dd8c2012-03-23 05:34:05 +0900328 // Pointer to object proxy for making method calls, no ownership is taken
329 // so this must outlive this class.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900330 ObjectProxy* object_proxy_;
331
332 // Interface of property, e.g. "org.chromium.ExampleService", this is
333 // distinct from the interface of the method call itself which is the
334 // general D-Bus Properties interface "org.freedesktop.DBus.Properties".
335 std::string interface_;
336
337 // Callback for property changes.
338 PropertyChangedCallback property_changed_callback_;
339
340 // Map of properties (as PropertyBase*) defined in the structure to
341 // names as used in D-Bus method calls and signals. The base pointer
342 // restricts property access via this map to type-unsafe and non-specific
343 // actions only.
344 typedef std::map<const std::string, PropertyBase*> PropertiesMap;
345 PropertiesMap properties_map_;
346
347 // Weak pointer factory as D-Bus callbacks may last longer than these
348 // objects.
349 base::WeakPtrFactory<PropertySet> weak_ptr_factory_;
350
351 DISALLOW_COPY_AND_ASSIGN(PropertySet);
352};
353
354// Property template, this defines the type-specific and type-safe methods
355// of properties that can be accessed as members of a PropertySet structure.
356//
357// Properties provide a cached value that has an initial sensible default
358// until the reply to PropertySet::GetAll() is retrieved and is updated by
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900359// all calls to that method, PropertySet::Get() and property changed signals
360// also handled by PropertySet. It can be obtained by calling value() on the
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900361// property.
362//
363// It is recommended that this cached value be used where necessary, with
364// code using PropertySet::PropertyChangedCallback to be notified of changes,
365// rather than incurring a round-trip to the remote object for each property
366// access.
367//
368// Where a round-trip is necessary, the Get() method is provided. And to
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900369// update the remote object value, the Set() method is also provided; these
370// both simply call methods on PropertySet.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900371//
372// Handling of particular D-Bus types is performed via specialization,
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900373// typically the PopValueFromReader() and AppendSetValueToWriter() methods
374// will need to be provided, and in rare cases a constructor to provide a
375// default value. Specializations for basic D-Bus types, strings, object
376// paths and arrays are provided for you.
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900377template <class T>
tzik@chromium.org57fd8b12014-06-27 17:10:43 +0900378class CHROME_DBUS_EXPORT Property : public PropertyBase {
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900379 public:
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900380 Property() {}
derat3f868a42015-07-17 00:06:44 +0900381 ~Property() override {}
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900382
383 // Retrieves the cached value.
keybuk@chromium.org5b48ae42012-02-17 16:46:34 +0900384 const T& value() const { return value_; }
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900385
386 // Requests an updated value from the remote object incurring a
387 // round-trip. |callback| will be called when the new value is available.
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900388 // This may not be implemented by some interfaces.
389 virtual void Get(dbus::PropertySet::GetCallback callback) {
390 property_set()->Get(this, callback);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900391 }
392
nywang80f27162015-09-29 07:46:36 +0900393 // The synchronous version of Get().
394 // This should never be used on an interactive thread.
395 virtual bool GetAndBlock() {
396 return property_set()->GetAndBlock(this);
397 }
398
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900399 // Requests that the remote object change the property value to |value|,
400 // |callback| will be called to indicate the success or failure of the
401 // request, however the new value may not be available depending on the
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900402 // remote object.
403 virtual void Set(const T& value, dbus::PropertySet::SetCallback callback) {
404 set_value_ = value;
405 property_set()->Set(this, callback);
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900406 }
407
nywang80f27162015-09-29 07:46:36 +0900408 // The synchronous version of Set().
409 // This should never be used on an interactive thread.
nywangf1196812015-09-23 09:06:40 +0900410 virtual bool SetAndBlock(const T& value) {
411 set_value_ = value;
412 return property_set()->SetAndBlock(this);
413 }
414
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900415 // Method used by PropertySet to retrieve the value from a MessageReader,
416 // no knowledge of the contained type is required, this method returns
417 // true if its expected type was found, false if not.
dtapuska95f71722015-02-10 01:02:55 +0900418 bool PopValueFromReader(MessageReader* reader) override;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900419
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900420 // Method used by PropertySet to append the set value to a MessageWriter,
421 // no knowledge of the contained type is required.
keybuk@google.comf056b962012-03-22 08:43:45 +0900422 // Implementation provided by specialization.
dmichaelbc06db42014-12-20 05:52:31 +0900423 void AppendSetValueToWriter(MessageWriter* writer) override;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900424
keybuk@chromium.orgb45e5292012-08-15 10:03:30 +0900425 // Method used by test and stub implementations of dbus::PropertySet::Set
426 // to replace the property value with the set value without using a
427 // dbus::MessageReader.
dmichaelbc06db42014-12-20 05:52:31 +0900428 void ReplaceValueWithSetValue() override {
keybuk@chromium.orgc1944c62013-04-24 10:41:54 +0900429 value_ = set_value_;
430 property_set()->NotifyPropertyChanged(name());
431 }
keybuk@chromium.orgb45e5292012-08-15 10:03:30 +0900432
433 // Method used by test and stub implementations to directly set the
434 // value of a property.
keybuk@chromium.orgc1944c62013-04-24 10:41:54 +0900435 void ReplaceValue(const T& value) {
436 value_ = value;
437 property_set()->NotifyPropertyChanged(name());
438 }
keybuk@chromium.orgb45e5292012-08-15 10:03:30 +0900439
dtapuska95f71722015-02-10 01:02:55 +0900440 // Method used by test and stub implementations to directly set the
441 // |set_value_| of a property.
442 void ReplaceSetValueForTesting(const T& value) { set_value_ = value; }
443
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900444 private:
445 // Current cached value of the property.
446 T value_;
447
keybuk@chromium.org56028ac2012-06-29 03:43:30 +0900448 // Replacement value of the property.
449 T set_value_;
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900450};
451
dcheng52b30722015-09-19 03:29:06 +0900452// Clang and GCC don't agree on how attributes should work for explicitly
453// instantiated templates. GCC ignores attributes on explicit instantiations
454// (and emits a warning) while Clang requires the visiblity attribute on the
455// explicit instantiations for them to be visible to other compilation units.
456// Hopefully clang and GCC agree one day, and this can be cleaned up:
457// https://llvm.org/bugs/show_bug.cgi?id=24815
458#pragma GCC diagnostic push
459#pragma GCC diagnostic ignored "-Wattributes"
spangcff38832015-09-15 02:49:40 +0900460
dtapuska95f71722015-02-10 01:02:55 +0900461template <>
avi0ad0ce02015-12-23 03:12:45 +0900462CHROME_DBUS_EXPORT Property<uint8_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900463template <>
avi0ad0ce02015-12-23 03:12:45 +0900464CHROME_DBUS_EXPORT bool Property<uint8_t>::PopValueFromReader(
dtapuska95f71722015-02-10 01:02:55 +0900465 MessageReader* reader);
466template <>
avi0ad0ce02015-12-23 03:12:45 +0900467CHROME_DBUS_EXPORT void Property<uint8_t>::AppendSetValueToWriter(
dtapuska95f71722015-02-10 01:02:55 +0900468 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900469extern template class CHROME_DBUS_EXPORT Property<uint8_t>;
dtapuska95f71722015-02-10 01:02:55 +0900470
471template <>
dcheng52b30722015-09-19 03:29:06 +0900472CHROME_DBUS_EXPORT Property<bool>::Property();
473template <>
474CHROME_DBUS_EXPORT bool Property<bool>::PopValueFromReader(
475 MessageReader* reader);
476template <>
477CHROME_DBUS_EXPORT void Property<bool>::AppendSetValueToWriter(
478 MessageWriter* writer);
479extern template class CHROME_DBUS_EXPORT Property<bool>;
480
481template <>
avi0ad0ce02015-12-23 03:12:45 +0900482CHROME_DBUS_EXPORT Property<int16_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900483template <>
avi0ad0ce02015-12-23 03:12:45 +0900484CHROME_DBUS_EXPORT bool Property<int16_t>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900485 MessageReader* reader);
486template <>
avi0ad0ce02015-12-23 03:12:45 +0900487CHROME_DBUS_EXPORT void Property<int16_t>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900488 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900489extern template class CHROME_DBUS_EXPORT Property<int16_t>;
dcheng52b30722015-09-19 03:29:06 +0900490
491template <>
avi0ad0ce02015-12-23 03:12:45 +0900492CHROME_DBUS_EXPORT Property<uint16_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900493template <>
avi0ad0ce02015-12-23 03:12:45 +0900494CHROME_DBUS_EXPORT bool Property<uint16_t>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900495 MessageReader* reader);
496template <>
avi0ad0ce02015-12-23 03:12:45 +0900497CHROME_DBUS_EXPORT void Property<uint16_t>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900498 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900499extern template class CHROME_DBUS_EXPORT Property<uint16_t>;
dcheng52b30722015-09-19 03:29:06 +0900500
501template <>
avi0ad0ce02015-12-23 03:12:45 +0900502CHROME_DBUS_EXPORT Property<int32_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900503template <>
avi0ad0ce02015-12-23 03:12:45 +0900504CHROME_DBUS_EXPORT bool Property<int32_t>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900505 MessageReader* reader);
506template <>
avi0ad0ce02015-12-23 03:12:45 +0900507CHROME_DBUS_EXPORT void Property<int32_t>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900508 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900509extern template class CHROME_DBUS_EXPORT Property<int32_t>;
dcheng52b30722015-09-19 03:29:06 +0900510
511template <>
avi0ad0ce02015-12-23 03:12:45 +0900512CHROME_DBUS_EXPORT Property<uint32_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900513template <>
avi0ad0ce02015-12-23 03:12:45 +0900514CHROME_DBUS_EXPORT bool Property<uint32_t>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900515 MessageReader* reader);
516template <>
avi0ad0ce02015-12-23 03:12:45 +0900517CHROME_DBUS_EXPORT void Property<uint32_t>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900518 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900519extern template class CHROME_DBUS_EXPORT Property<uint32_t>;
dcheng52b30722015-09-19 03:29:06 +0900520
521template <>
avi0ad0ce02015-12-23 03:12:45 +0900522CHROME_DBUS_EXPORT Property<int64_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900523template <>
avi0ad0ce02015-12-23 03:12:45 +0900524CHROME_DBUS_EXPORT bool Property<int64_t>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900525 MessageReader* reader);
526template <>
avi0ad0ce02015-12-23 03:12:45 +0900527CHROME_DBUS_EXPORT void Property<int64_t>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900528 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900529extern template class CHROME_DBUS_EXPORT Property<int64_t>;
dcheng52b30722015-09-19 03:29:06 +0900530
531template <>
avi0ad0ce02015-12-23 03:12:45 +0900532CHROME_DBUS_EXPORT Property<uint64_t>::Property();
dcheng52b30722015-09-19 03:29:06 +0900533template <>
avi0ad0ce02015-12-23 03:12:45 +0900534CHROME_DBUS_EXPORT bool Property<uint64_t>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900535 MessageReader* reader);
536template <>
avi0ad0ce02015-12-23 03:12:45 +0900537CHROME_DBUS_EXPORT void Property<uint64_t>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900538 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900539extern template class CHROME_DBUS_EXPORT Property<uint64_t>;
dcheng52b30722015-09-19 03:29:06 +0900540
541template <>
542CHROME_DBUS_EXPORT Property<double>::Property();
543template <>
544CHROME_DBUS_EXPORT bool Property<double>::PopValueFromReader(
545 MessageReader* reader);
546template <>
547CHROME_DBUS_EXPORT void Property<double>::AppendSetValueToWriter(
548 MessageWriter* writer);
549extern template class CHROME_DBUS_EXPORT Property<double>;
550
551template <>
552CHROME_DBUS_EXPORT bool Property<std::string>::PopValueFromReader(
553 MessageReader* reader);
554template <>
555CHROME_DBUS_EXPORT void Property<std::string>::AppendSetValueToWriter(
556 MessageWriter* writer);
557extern template class CHROME_DBUS_EXPORT Property<std::string>;
558
559template <>
560CHROME_DBUS_EXPORT bool Property<ObjectPath>::PopValueFromReader(
561 MessageReader* reader);
562template <>
563CHROME_DBUS_EXPORT void Property<ObjectPath>::AppendSetValueToWriter(
564 MessageWriter* writer);
565extern template class CHROME_DBUS_EXPORT Property<ObjectPath>;
566
567template <>
568CHROME_DBUS_EXPORT bool Property<std::vector<std::string>>::PopValueFromReader(
569 MessageReader* reader);
570template <>
571CHROME_DBUS_EXPORT void Property<
572 std::vector<std::string>>::AppendSetValueToWriter(MessageWriter* writer);
573extern template class CHROME_DBUS_EXPORT Property<std::vector<std::string>>;
574
575template <>
576CHROME_DBUS_EXPORT bool Property<std::vector<ObjectPath>>::PopValueFromReader(
577 MessageReader* reader);
578template <>
579CHROME_DBUS_EXPORT void Property<
580 std::vector<ObjectPath>>::AppendSetValueToWriter(MessageWriter* writer);
581extern template class CHROME_DBUS_EXPORT Property<std::vector<ObjectPath>>;
582
583template <>
avi0ad0ce02015-12-23 03:12:45 +0900584CHROME_DBUS_EXPORT bool Property<std::vector<uint8_t>>::PopValueFromReader(
dcheng52b30722015-09-19 03:29:06 +0900585 MessageReader* reader);
586template <>
avi0ad0ce02015-12-23 03:12:45 +0900587CHROME_DBUS_EXPORT void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
dcheng52b30722015-09-19 03:29:06 +0900588 MessageWriter* writer);
avi0ad0ce02015-12-23 03:12:45 +0900589extern template class CHROME_DBUS_EXPORT Property<std::vector<uint8_t>>;
dcheng52b30722015-09-19 03:29:06 +0900590
591template <>
592CHROME_DBUS_EXPORT bool
593Property<std::map<std::string, std::string>>::PopValueFromReader(
594 MessageReader* reader);
595template <>
596CHROME_DBUS_EXPORT void
597Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
598 MessageWriter* writer);
599extern template class CHROME_DBUS_EXPORT
600 Property<std::map<std::string, std::string>>;
601
602template <>
603CHROME_DBUS_EXPORT bool
604Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
dtapuska95f71722015-02-10 01:02:55 +0900605 PopValueFromReader(MessageReader* reader);
606template <>
dcheng52b30722015-09-19 03:29:06 +0900607CHROME_DBUS_EXPORT void
608Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
dtapuska95f71722015-02-10 01:02:55 +0900609 AppendSetValueToWriter(MessageWriter* writer);
dcheng52b30722015-09-19 03:29:06 +0900610extern template class CHROME_DBUS_EXPORT
611 Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
612
613#pragma GCC diagnostic pop
dtapuska95f71722015-02-10 01:02:55 +0900614
keybuk@chromium.org7e0c4932012-02-15 13:21:08 +0900615} // namespace dbus
616
617#endif // DBUS_PROPERTY_H_