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 #include "dbus/property.h"
7 #include "base/basictypes.h"
9 #include "base/logging.h"
11 #include "dbus/message.h"
12 #include "dbus/object_path.h"
13 #include "dbus/object_proxy.h"
18 // PropertyBase implementation.
21 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {}
23 PropertyBase::~PropertyBase() {}
25 void PropertyBase::Init(PropertySet
* property_set
, const std::string
& name
) {
26 DCHECK(!property_set_
);
27 property_set_
= property_set
;
33 // PropertySet implementation.
36 PropertySet::PropertySet(
37 ObjectProxy
* object_proxy
,
38 const std::string
& interface
,
39 const PropertyChangedCallback
& property_changed_callback
)
40 : object_proxy_(object_proxy
),
41 interface_(interface
),
42 property_changed_callback_(property_changed_callback
),
43 weak_ptr_factory_(this) {}
45 PropertySet::~PropertySet() {
48 void PropertySet::RegisterProperty(const std::string
& name
,
49 PropertyBase
* property
) {
50 property
->Init(this, name
);
51 properties_map_
[name
] = property
;
54 void PropertySet::ConnectSignals() {
55 DCHECK(object_proxy_
);
56 object_proxy_
->ConnectToSignal(
59 base::Bind(&PropertySet::ChangedReceived
,
60 weak_ptr_factory_
.GetWeakPtr()),
61 base::Bind(&PropertySet::ChangedConnected
,
62 weak_ptr_factory_
.GetWeakPtr()));
66 void PropertySet::ChangedReceived(Signal
* signal
) {
68 MessageReader
reader(signal
);
70 std::string interface
;
71 if (!reader
.PopString(&interface
)) {
72 LOG(WARNING
) << "Property changed signal has wrong parameters: "
73 << "expected interface name: " << signal
->ToString();
77 if (interface
!= this->interface())
80 if (!UpdatePropertiesFromReader(&reader
)) {
81 LOG(WARNING
) << "Property changed signal has wrong parameters: "
82 << "expected dictionary: " << signal
->ToString();
85 if (!InvalidatePropertiesFromReader(&reader
)) {
86 LOG(WARNING
) << "Property changed signal has wrong parameters: "
87 << "expected array to invalidate: " << signal
->ToString();
91 void PropertySet::ChangedConnected(const std::string
& interface_name
,
92 const std::string
& signal_name
,
94 LOG_IF(WARNING
, !success
) << "Failed to connect to " << signal_name
99 void PropertySet::Get(PropertyBase
* property
, GetCallback callback
) {
100 MethodCall
method_call(kPropertiesInterface
, kPropertiesGet
);
101 MessageWriter
writer(&method_call
);
102 writer
.AppendString(interface());
103 writer
.AppendString(property
->name());
105 DCHECK(object_proxy_
);
106 object_proxy_
->CallMethod(&method_call
,
107 ObjectProxy::TIMEOUT_USE_DEFAULT
,
108 base::Bind(&PropertySet::OnGet
,
114 void PropertySet::OnGet(PropertyBase
* property
, GetCallback callback
,
115 Response
* response
) {
117 LOG(WARNING
) << property
->name() << ": Get: failed.";
121 MessageReader
reader(response
);
122 if (property
->PopValueFromReader(&reader
)) {
123 property
->set_valid(true);
124 NotifyPropertyChanged(property
->name());
126 if (property
->is_valid()) {
127 property
->set_valid(false);
128 NotifyPropertyChanged(property
->name());
132 if (!callback
.is_null())
133 callback
.Run(response
);
136 void PropertySet::GetAll() {
137 MethodCall
method_call(kPropertiesInterface
, kPropertiesGetAll
);
138 MessageWriter
writer(&method_call
);
139 writer
.AppendString(interface());
141 DCHECK(object_proxy_
);
142 object_proxy_
->CallMethod(&method_call
,
143 ObjectProxy::TIMEOUT_USE_DEFAULT
,
144 base::Bind(&PropertySet::OnGetAll
,
145 weak_ptr_factory_
.GetWeakPtr()));
148 void PropertySet::OnGetAll(Response
* response
) {
150 LOG(WARNING
) << "GetAll request failed for: " << interface_
;
154 MessageReader
reader(response
);
155 if (!UpdatePropertiesFromReader(&reader
)) {
156 LOG(WARNING
) << "GetAll response has wrong parameters: "
157 << "expected dictionary: " << response
->ToString();
161 void PropertySet::Set(PropertyBase
* property
, SetCallback callback
) {
162 MethodCall
method_call(kPropertiesInterface
, kPropertiesSet
);
163 MessageWriter
writer(&method_call
);
164 writer
.AppendString(interface());
165 writer
.AppendString(property
->name());
166 property
->AppendSetValueToWriter(&writer
);
168 DCHECK(object_proxy_
);
169 object_proxy_
->CallMethod(&method_call
,
170 ObjectProxy::TIMEOUT_USE_DEFAULT
,
171 base::Bind(&PropertySet::OnSet
,
177 void PropertySet::OnSet(PropertyBase
* property
,
178 SetCallback callback
,
179 Response
* response
) {
180 LOG_IF(WARNING
, !response
) << property
->name() << ": Set: failed.";
181 if (!callback
.is_null())
182 callback
.Run(response
);
185 bool PropertySet::UpdatePropertiesFromReader(MessageReader
* reader
) {
187 MessageReader
array_reader(NULL
);
188 if (!reader
->PopArray(&array_reader
))
191 while (array_reader
.HasMoreData()) {
192 MessageReader
dict_entry_reader(NULL
);
193 if (array_reader
.PopDictEntry(&dict_entry_reader
))
194 UpdatePropertyFromReader(&dict_entry_reader
);
200 bool PropertySet::UpdatePropertyFromReader(MessageReader
* reader
) {
204 if (!reader
->PopString(&name
))
207 PropertiesMap::iterator it
= properties_map_
.find(name
);
208 if (it
== properties_map_
.end())
211 PropertyBase
* property
= it
->second
;
212 if (property
->PopValueFromReader(reader
)) {
213 property
->set_valid(true);
214 NotifyPropertyChanged(name
);
217 if (property
->is_valid()) {
218 property
->set_valid(false);
219 NotifyPropertyChanged(property
->name());
225 bool PropertySet::InvalidatePropertiesFromReader(MessageReader
* reader
) {
227 MessageReader
array_reader(NULL
);
228 if (!reader
->PopArray(&array_reader
))
231 while (array_reader
.HasMoreData()) {
233 if (!array_reader
.PopString(&name
))
236 PropertiesMap::iterator it
= properties_map_
.find(name
);
237 if (it
== properties_map_
.end())
240 PropertyBase
* property
= it
->second
;
241 if (property
->is_valid()) {
242 property
->set_valid(false);
243 NotifyPropertyChanged(property
->name());
250 void PropertySet::NotifyPropertyChanged(const std::string
& name
) {
251 if (!property_changed_callback_
.is_null())
252 property_changed_callback_
.Run(name
);
256 // Property<Byte> specialization.
260 Property
<uint8
>::Property() : value_(0) {
264 bool Property
<uint8
>::PopValueFromReader(MessageReader
* reader
) {
265 return reader
->PopVariantOfByte(&value_
);
269 void Property
<uint8
>::AppendSetValueToWriter(MessageWriter
* writer
) {
270 writer
->AppendVariantOfByte(set_value_
);
274 // Property<bool> specialization.
278 Property
<bool>::Property() : value_(false) {
282 bool Property
<bool>::PopValueFromReader(MessageReader
* reader
) {
283 return reader
->PopVariantOfBool(&value_
);
287 void Property
<bool>::AppendSetValueToWriter(MessageWriter
* writer
) {
288 writer
->AppendVariantOfBool(set_value_
);
292 // Property<int16> specialization.
296 Property
<int16
>::Property() : value_(0) {
300 bool Property
<int16
>::PopValueFromReader(MessageReader
* reader
) {
301 return reader
->PopVariantOfInt16(&value_
);
305 void Property
<int16
>::AppendSetValueToWriter(MessageWriter
* writer
) {
306 writer
->AppendVariantOfInt16(set_value_
);
310 // Property<uint16> specialization.
314 Property
<uint16
>::Property() : value_(0) {
318 bool Property
<uint16
>::PopValueFromReader(MessageReader
* reader
) {
319 return reader
->PopVariantOfUint16(&value_
);
323 void Property
<uint16
>::AppendSetValueToWriter(MessageWriter
* writer
) {
324 writer
->AppendVariantOfUint16(set_value_
);
328 // Property<int32> specialization.
332 Property
<int32
>::Property() : value_(0) {
336 bool Property
<int32
>::PopValueFromReader(MessageReader
* reader
) {
337 return reader
->PopVariantOfInt32(&value_
);
341 void Property
<int32
>::AppendSetValueToWriter(MessageWriter
* writer
) {
342 writer
->AppendVariantOfInt32(set_value_
);
346 // Property<uint32> specialization.
350 Property
<uint32
>::Property() : value_(0) {
354 bool Property
<uint32
>::PopValueFromReader(MessageReader
* reader
) {
355 return reader
->PopVariantOfUint32(&value_
);
359 void Property
<uint32
>::AppendSetValueToWriter(MessageWriter
* writer
) {
360 writer
->AppendVariantOfUint32(set_value_
);
364 // Property<int64> specialization.
368 Property
<int64
>::Property() : value_(0), set_value_(0) {
372 bool Property
<int64
>::PopValueFromReader(MessageReader
* reader
) {
373 return reader
->PopVariantOfInt64(&value_
);
377 void Property
<int64
>::AppendSetValueToWriter(MessageWriter
* writer
) {
378 writer
->AppendVariantOfInt64(set_value_
);
382 // Property<uint64> specialization.
386 Property
<uint64
>::Property() : value_(0) {
390 bool Property
<uint64
>::PopValueFromReader(MessageReader
* reader
) {
391 return reader
->PopVariantOfUint64(&value_
);
395 void Property
<uint64
>::AppendSetValueToWriter(MessageWriter
* writer
) {
396 writer
->AppendVariantOfUint64(set_value_
);
400 // Property<double> specialization.
404 Property
<double>::Property() : value_(0.0) {
408 bool Property
<double>::PopValueFromReader(MessageReader
* reader
) {
409 return reader
->PopVariantOfDouble(&value_
);
413 void Property
<double>::AppendSetValueToWriter(MessageWriter
* writer
) {
414 writer
->AppendVariantOfDouble(set_value_
);
418 // Property<std::string> specialization.
422 bool Property
<std::string
>::PopValueFromReader(MessageReader
* reader
) {
423 return reader
->PopVariantOfString(&value_
);
427 void Property
<std::string
>::AppendSetValueToWriter(MessageWriter
* writer
) {
428 writer
->AppendVariantOfString(set_value_
);
432 // Property<ObjectPath> specialization.
436 bool Property
<ObjectPath
>::PopValueFromReader(MessageReader
* reader
) {
437 return reader
->PopVariantOfObjectPath(&value_
);
441 void Property
<ObjectPath
>::AppendSetValueToWriter(MessageWriter
* writer
) {
442 writer
->AppendVariantOfObjectPath(set_value_
);
446 // Property<std::vector<std::string> > specialization.
450 bool Property
<std::vector
<std::string
> >::PopValueFromReader(
451 MessageReader
* reader
) {
452 MessageReader
variant_reader(NULL
);
453 if (!reader
->PopVariant(&variant_reader
))
457 return variant_reader
.PopArrayOfStrings(&value_
);
461 void Property
<std::vector
<std::string
> >::AppendSetValueToWriter(
462 MessageWriter
* writer
) {
463 MessageWriter
variant_writer(NULL
);
464 writer
->OpenVariant("as", &variant_writer
);
465 variant_writer
.AppendArrayOfStrings(set_value_
);
466 writer
->CloseContainer(&variant_writer
);
470 // Property<std::vector<ObjectPath> > specialization.
474 bool Property
<std::vector
<ObjectPath
> >::PopValueFromReader(
475 MessageReader
* reader
) {
476 MessageReader
variant_reader(NULL
);
477 if (!reader
->PopVariant(&variant_reader
))
481 return variant_reader
.PopArrayOfObjectPaths(&value_
);
485 void Property
<std::vector
<ObjectPath
> >::AppendSetValueToWriter(
486 MessageWriter
* writer
) {
487 MessageWriter
variant_writer(NULL
);
488 writer
->OpenVariant("ao", &variant_writer
);
489 variant_writer
.AppendArrayOfObjectPaths(set_value_
);
490 writer
->CloseContainer(&variant_writer
);
494 // Property<std::vector<uint8> > specialization.
498 bool Property
<std::vector
<uint8
> >::PopValueFromReader(MessageReader
* reader
) {
499 MessageReader
variant_reader(NULL
);
500 if (!reader
->PopVariant(&variant_reader
))
504 const uint8
* bytes
= NULL
;
506 if (!variant_reader
.PopArrayOfBytes(&bytes
, &length
))
508 value_
.assign(bytes
, bytes
+ length
);
513 void Property
<std::vector
<uint8
> >::AppendSetValueToWriter(
514 MessageWriter
* writer
) {
515 MessageWriter
variant_writer(NULL
);
516 writer
->OpenVariant("ay", &variant_writer
);
517 variant_writer
.AppendArrayOfBytes(set_value_
.data(), set_value_
.size());
518 writer
->CloseContainer(&variant_writer
);
522 // Property<std::map<std::string, std::string>> specialization.
526 bool Property
<std::map
<std::string
, std::string
>>::PopValueFromReader(
527 MessageReader
* reader
) {
528 MessageReader
variant_reader(NULL
);
529 MessageReader
array_reader(NULL
);
530 if (!reader
->PopVariant(&variant_reader
) ||
531 !variant_reader
.PopArray(&array_reader
))
534 while (array_reader
.HasMoreData()) {
535 dbus::MessageReader
dict_entry_reader(NULL
);
536 if (!array_reader
.PopDictEntry(&dict_entry_reader
))
540 if (!dict_entry_reader
.PopString(&key
) ||
541 !dict_entry_reader
.PopString(&value
))
549 void Property
<std::map
<std::string
, std::string
>>::AppendSetValueToWriter(
550 MessageWriter
* writer
) {
551 MessageWriter
variant_writer(NULL
);
552 MessageWriter
dict_writer(NULL
);
553 writer
->OpenVariant("a{ss}", &variant_writer
);
554 variant_writer
.OpenArray("{ss}", &dict_writer
);
555 for (const auto& pair
: set_value_
) {
556 dbus::MessageWriter
entry_writer(NULL
);
557 dict_writer
.OpenDictEntry(&entry_writer
);
558 entry_writer
.AppendString(pair
.first
);
559 entry_writer
.AppendString(pair
.second
);
560 dict_writer
.CloseContainer(&entry_writer
);
562 variant_writer
.CloseContainer(&dict_writer
);
563 writer
->CloseContainer(&variant_writer
);
567 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
572 bool Property
<std::vector
<std::pair
<std::vector
<uint8_t>, uint16_t>>>::
573 PopValueFromReader(MessageReader
* reader
) {
574 MessageReader
variant_reader(NULL
);
575 MessageReader
array_reader(NULL
);
576 if (!reader
->PopVariant(&variant_reader
) ||
577 !variant_reader
.PopArray(&array_reader
))
581 while (array_reader
.HasMoreData()) {
582 dbus::MessageReader
struct_reader(NULL
);
583 if (!array_reader
.PopStruct(&struct_reader
))
586 std::pair
<std::vector
<uint8_t>, uint16_t> entry
;
587 const uint8
* bytes
= NULL
;
589 if (!struct_reader
.PopArrayOfBytes(&bytes
, &length
))
591 entry
.first
.assign(bytes
, bytes
+ length
);
592 if (!struct_reader
.PopUint16(&entry
.second
))
594 value_
.push_back(entry
);
600 void Property
<std::vector
<std::pair
<std::vector
<uint8_t>, uint16_t>>>::
601 AppendSetValueToWriter(MessageWriter
* writer
) {
602 MessageWriter
variant_writer(NULL
);
603 MessageWriter
array_writer(NULL
);
604 writer
->OpenVariant("a(ayq)", &variant_writer
);
605 variant_writer
.OpenArray("(ayq)", &array_writer
);
606 for (const auto& pair
: set_value_
) {
607 dbus::MessageWriter
struct_writer(nullptr);
608 array_writer
.OpenStruct(&struct_writer
);
609 struct_writer
.AppendArrayOfBytes(std::get
<0>(pair
).data(),
610 std::get
<0>(pair
).size());
611 struct_writer
.AppendUint16(std::get
<1>(pair
));
612 array_writer
.CloseContainer(&struct_writer
);
614 variant_writer
.CloseContainer(&array_writer
);
615 writer
->CloseContainer(&variant_writer
);
618 template class Property
<uint8
>;
619 template class Property
<bool>;
620 template class Property
<int16
>;
621 template class Property
<uint16
>;
622 template class Property
<int32
>;
623 template class Property
<uint32
>;
624 template class Property
<int64
>;
625 template class Property
<uint64
>;
626 template class Property
<double>;
627 template class Property
<std::string
>;
628 template class Property
<ObjectPath
>;
629 template class Property
<std::vector
<std::string
> >;
630 template class Property
<std::vector
<ObjectPath
> >;
631 template class Property
<std::vector
<uint8
> >;
632 template class Property
<std::map
<std::string
, std::string
>>;
633 template class Property
<std::vector
<std::pair
<std::vector
<uint8_t>, uint16_t>>>;