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 void PropertyBase::Init(PropertySet
* property_set
, const std::string
& name
) {
22 DCHECK(!property_set_
);
23 property_set_
= property_set
;
29 // PropertySet implementation.
32 PropertySet::PropertySet(
33 ObjectProxy
* object_proxy
,
34 const std::string
& interface
,
35 const PropertyChangedCallback
& property_changed_callback
)
36 : object_proxy_(object_proxy
),
37 interface_(interface
),
38 property_changed_callback_(property_changed_callback
),
39 weak_ptr_factory_(this) {}
41 PropertySet::~PropertySet() {
44 void PropertySet::RegisterProperty(const std::string
& name
,
45 PropertyBase
* property
) {
46 property
->Init(this, name
);
47 properties_map_
[name
] = property
;
50 void PropertySet::ConnectSignals() {
51 DCHECK(object_proxy_
);
52 object_proxy_
->ConnectToSignal(
55 base::Bind(&PropertySet::ChangedReceived
,
56 weak_ptr_factory_
.GetWeakPtr()),
57 base::Bind(&PropertySet::ChangedConnected
,
58 weak_ptr_factory_
.GetWeakPtr()));
62 void PropertySet::ChangedReceived(Signal
* signal
) {
64 MessageReader
reader(signal
);
66 std::string interface
;
67 if (!reader
.PopString(&interface
)) {
68 LOG(WARNING
) << "Property changed signal has wrong parameters: "
69 << "expected interface name: " << signal
->ToString();
73 if (interface
!= this->interface())
76 if (!UpdatePropertiesFromReader(&reader
)) {
77 LOG(WARNING
) << "Property changed signal has wrong parameters: "
78 << "expected dictionary: " << signal
->ToString();
81 // TODO(keybuk): dbus properties api has invalidated properties array
82 // on the end, we don't handle this right now because I don't know of
83 // any service that sends it - or what they expect us to do with it.
84 // Add later when we need it.
87 void PropertySet::ChangedConnected(const std::string
& interface_name
,
88 const std::string
& signal_name
,
90 LOG_IF(WARNING
, !success
) << "Failed to connect to " << signal_name
95 void PropertySet::Get(PropertyBase
* property
, GetCallback callback
) {
96 MethodCall
method_call(kPropertiesInterface
, kPropertiesGet
);
97 MessageWriter
writer(&method_call
);
98 writer
.AppendString(interface());
99 writer
.AppendString(property
->name());
101 DCHECK(object_proxy_
);
102 object_proxy_
->CallMethod(&method_call
,
103 ObjectProxy::TIMEOUT_USE_DEFAULT
,
104 base::Bind(&PropertySet::OnGet
,
110 void PropertySet::OnGet(PropertyBase
* property
, GetCallback callback
,
111 Response
* response
) {
113 LOG(WARNING
) << property
->name() << ": Get: failed.";
117 MessageReader
reader(response
);
118 if (property
->PopValueFromReader(&reader
))
119 NotifyPropertyChanged(property
->name());
121 if (!callback
.is_null())
122 callback
.Run(response
);
125 void PropertySet::GetAll() {
126 MethodCall
method_call(kPropertiesInterface
, kPropertiesGetAll
);
127 MessageWriter
writer(&method_call
);
128 writer
.AppendString(interface());
130 DCHECK(object_proxy_
);
131 object_proxy_
->CallMethod(&method_call
,
132 ObjectProxy::TIMEOUT_USE_DEFAULT
,
133 base::Bind(&PropertySet::OnGetAll
,
134 weak_ptr_factory_
.GetWeakPtr()));
137 void PropertySet::OnGetAll(Response
* response
) {
139 LOG(WARNING
) << "GetAll request failed for: " << interface_
;
143 MessageReader
reader(response
);
144 if (!UpdatePropertiesFromReader(&reader
)) {
145 LOG(WARNING
) << "GetAll response has wrong parameters: "
146 << "expected dictionary: " << response
->ToString();
150 void PropertySet::Set(PropertyBase
* property
, SetCallback callback
) {
151 MethodCall
method_call(kPropertiesInterface
, kPropertiesSet
);
152 MessageWriter
writer(&method_call
);
153 writer
.AppendString(interface());
154 writer
.AppendString(property
->name());
155 property
->AppendSetValueToWriter(&writer
);
157 DCHECK(object_proxy_
);
158 object_proxy_
->CallMethod(&method_call
,
159 ObjectProxy::TIMEOUT_USE_DEFAULT
,
160 base::Bind(&PropertySet::OnSet
,
166 void PropertySet::OnSet(PropertyBase
* property
,
167 SetCallback callback
,
168 Response
* response
) {
169 LOG_IF(WARNING
, !response
) << property
->name() << ": Set: failed.";
170 if (!callback
.is_null())
171 callback
.Run(response
);
174 bool PropertySet::UpdatePropertiesFromReader(MessageReader
* reader
) {
176 MessageReader
array_reader(NULL
);
177 if (!reader
->PopArray(&array_reader
))
180 while (array_reader
.HasMoreData()) {
181 MessageReader
dict_entry_reader(NULL
);
182 if (array_reader
.PopDictEntry(&dict_entry_reader
))
183 UpdatePropertyFromReader(&dict_entry_reader
);
189 bool PropertySet::UpdatePropertyFromReader(MessageReader
* reader
) {
193 if (!reader
->PopString(&name
))
196 PropertiesMap::iterator it
= properties_map_
.find(name
);
197 if (it
== properties_map_
.end())
200 PropertyBase
* property
= it
->second
;
201 if (property
->PopValueFromReader(reader
)) {
202 NotifyPropertyChanged(name
);
210 void PropertySet::NotifyPropertyChanged(const std::string
& name
) {
211 if (!property_changed_callback_
.is_null())
212 property_changed_callback_
.Run(name
);
216 // Property<Byte> specialization.
220 Property
<uint8
>::Property() : value_(0) {
224 bool Property
<uint8
>::PopValueFromReader(MessageReader
* reader
) {
225 return reader
->PopVariantOfByte(&value_
);
229 void Property
<uint8
>::AppendSetValueToWriter(MessageWriter
* writer
) {
230 writer
->AppendVariantOfByte(set_value_
);
234 // Property<bool> specialization.
238 Property
<bool>::Property() : value_(false) {
242 bool Property
<bool>::PopValueFromReader(MessageReader
* reader
) {
243 return reader
->PopVariantOfBool(&value_
);
247 void Property
<bool>::AppendSetValueToWriter(MessageWriter
* writer
) {
248 writer
->AppendVariantOfBool(set_value_
);
252 // Property<int16> specialization.
256 Property
<int16
>::Property() : value_(0) {
260 bool Property
<int16
>::PopValueFromReader(MessageReader
* reader
) {
261 return reader
->PopVariantOfInt16(&value_
);
265 void Property
<int16
>::AppendSetValueToWriter(MessageWriter
* writer
) {
266 writer
->AppendVariantOfInt16(set_value_
);
270 // Property<uint16> specialization.
274 Property
<uint16
>::Property() : value_(0) {
278 bool Property
<uint16
>::PopValueFromReader(MessageReader
* reader
) {
279 return reader
->PopVariantOfUint16(&value_
);
283 void Property
<uint16
>::AppendSetValueToWriter(MessageWriter
* writer
) {
284 writer
->AppendVariantOfUint16(set_value_
);
288 // Property<int32> specialization.
292 Property
<int32
>::Property() : value_(0) {
296 bool Property
<int32
>::PopValueFromReader(MessageReader
* reader
) {
297 return reader
->PopVariantOfInt32(&value_
);
301 void Property
<int32
>::AppendSetValueToWriter(MessageWriter
* writer
) {
302 writer
->AppendVariantOfInt32(set_value_
);
306 // Property<uint32> specialization.
310 Property
<uint32
>::Property() : value_(0) {
314 bool Property
<uint32
>::PopValueFromReader(MessageReader
* reader
) {
315 return reader
->PopVariantOfUint32(&value_
);
319 void Property
<uint32
>::AppendSetValueToWriter(MessageWriter
* writer
) {
320 writer
->AppendVariantOfUint32(set_value_
);
324 // Property<int64> specialization.
328 Property
<int64
>::Property() : value_(0), set_value_(0) {
332 bool Property
<int64
>::PopValueFromReader(MessageReader
* reader
) {
333 return reader
->PopVariantOfInt64(&value_
);
337 void Property
<int64
>::AppendSetValueToWriter(MessageWriter
* writer
) {
338 writer
->AppendVariantOfInt64(set_value_
);
342 // Property<uint64> specialization.
346 Property
<uint64
>::Property() : value_(0) {
350 bool Property
<uint64
>::PopValueFromReader(MessageReader
* reader
) {
351 return reader
->PopVariantOfUint64(&value_
);
355 void Property
<uint64
>::AppendSetValueToWriter(MessageWriter
* writer
) {
356 writer
->AppendVariantOfUint64(set_value_
);
360 // Property<double> specialization.
364 Property
<double>::Property() : value_(0.0) {
368 bool Property
<double>::PopValueFromReader(MessageReader
* reader
) {
369 return reader
->PopVariantOfDouble(&value_
);
373 void Property
<double>::AppendSetValueToWriter(MessageWriter
* writer
) {
374 writer
->AppendVariantOfDouble(set_value_
);
378 // Property<std::string> specialization.
382 bool Property
<std::string
>::PopValueFromReader(MessageReader
* reader
) {
383 return reader
->PopVariantOfString(&value_
);
387 void Property
<std::string
>::AppendSetValueToWriter(MessageWriter
* writer
) {
388 writer
->AppendVariantOfString(set_value_
);
392 // Property<ObjectPath> specialization.
396 bool Property
<ObjectPath
>::PopValueFromReader(MessageReader
* reader
) {
397 return reader
->PopVariantOfObjectPath(&value_
);
401 void Property
<ObjectPath
>::AppendSetValueToWriter(MessageWriter
* writer
) {
402 writer
->AppendVariantOfObjectPath(set_value_
);
406 // Property<std::vector<std::string> > specialization.
410 bool Property
<std::vector
<std::string
> >::PopValueFromReader(
411 MessageReader
* reader
) {
412 MessageReader
variant_reader(NULL
);
413 if (!reader
->PopVariant(&variant_reader
))
417 return variant_reader
.PopArrayOfStrings(&value_
);
421 void Property
<std::vector
<std::string
> >::AppendSetValueToWriter(
422 MessageWriter
* writer
) {
423 MessageWriter
variant_writer(NULL
);
424 writer
->OpenVariant("as", &variant_writer
);
425 variant_writer
.AppendArrayOfStrings(set_value_
);
426 writer
->CloseContainer(&variant_writer
);
430 // Property<std::vector<ObjectPath> > specialization.
434 bool Property
<std::vector
<ObjectPath
> >::PopValueFromReader(
435 MessageReader
* reader
) {
436 MessageReader
variant_reader(NULL
);
437 if (!reader
->PopVariant(&variant_reader
))
441 return variant_reader
.PopArrayOfObjectPaths(&value_
);
445 void Property
<std::vector
<ObjectPath
> >::AppendSetValueToWriter(
446 MessageWriter
* writer
) {
447 MessageWriter
variant_writer(NULL
);
448 writer
->OpenVariant("ao", &variant_writer
);
449 variant_writer
.AppendArrayOfObjectPaths(set_value_
);
450 writer
->CloseContainer(&variant_writer
);
454 // Property<std::vector<uint8> > specialization.
458 bool Property
<std::vector
<uint8
> >::PopValueFromReader(MessageReader
* reader
) {
459 MessageReader
variant_reader(NULL
);
460 if (!reader
->PopVariant(&variant_reader
))
464 const uint8
* bytes
= NULL
;
466 if (!variant_reader
.PopArrayOfBytes(&bytes
, &length
))
468 value_
.assign(bytes
, bytes
+ length
);
473 void Property
<std::vector
<uint8
> >::AppendSetValueToWriter(
474 MessageWriter
* writer
) {
475 MessageWriter
variant_writer(NULL
);
476 writer
->OpenVariant("ay", &variant_writer
);
477 variant_writer
.AppendArrayOfBytes(set_value_
.data(), set_value_
.size());
478 writer
->CloseContainer(&variant_writer
);
482 // Property<std::map<std::string, std::string>> specialization.
486 bool Property
<std::map
<std::string
, std::string
>>::PopValueFromReader(
487 MessageReader
* reader
) {
488 MessageReader
variant_reader(NULL
);
489 MessageReader
array_reader(NULL
);
490 if (!reader
->PopVariant(&variant_reader
) ||
491 !variant_reader
.PopArray(&array_reader
))
494 while (array_reader
.HasMoreData()) {
495 dbus::MessageReader
dict_entry_reader(NULL
);
496 if (!array_reader
.PopDictEntry(&dict_entry_reader
))
500 if (!dict_entry_reader
.PopString(&key
) ||
501 !dict_entry_reader
.PopString(&value
))
509 void Property
<std::map
<std::string
, std::string
>>::AppendSetValueToWriter(
510 MessageWriter
* writer
) {
511 MessageWriter
variant_writer(NULL
);
512 MessageWriter
dict_writer(NULL
);
513 writer
->OpenVariant("a{ss}", &variant_writer
);
514 variant_writer
.OpenArray("{ss}", &dict_writer
);
515 for (const auto& pair
: set_value_
) {
516 dbus::MessageWriter
entry_writer(NULL
);
517 dict_writer
.OpenDictEntry(&entry_writer
);
518 entry_writer
.AppendString(pair
.first
);
519 entry_writer
.AppendString(pair
.second
);
520 dict_writer
.CloseContainer(&entry_writer
);
522 variant_writer
.CloseContainer(&dict_writer
);
523 writer
->CloseContainer(&variant_writer
);
527 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
532 bool Property
<std::vector
<std::pair
<std::vector
<uint8_t>, uint16_t>>>::
533 PopValueFromReader(MessageReader
* reader
) {
534 MessageReader
variant_reader(NULL
);
535 MessageReader
array_reader(NULL
);
536 if (!reader
->PopVariant(&variant_reader
) ||
537 !variant_reader
.PopArray(&array_reader
))
541 while (array_reader
.HasMoreData()) {
542 dbus::MessageReader
struct_reader(NULL
);
543 if (!array_reader
.PopStruct(&struct_reader
))
546 std::pair
<std::vector
<uint8_t>, uint16_t> entry
;
547 const uint8
* bytes
= NULL
;
549 if (!struct_reader
.PopArrayOfBytes(&bytes
, &length
))
551 entry
.first
.assign(bytes
, bytes
+ length
);
552 if (!struct_reader
.PopUint16(&entry
.second
))
554 value_
.push_back(entry
);
560 void Property
<std::vector
<std::pair
<std::vector
<uint8_t>, uint16_t>>>::
561 AppendSetValueToWriter(MessageWriter
* writer
) {
562 MessageWriter
variant_writer(NULL
);
563 MessageWriter
array_writer(NULL
);
564 writer
->OpenVariant("a(ayq)", &variant_writer
);
565 variant_writer
.OpenArray("(ayq)", &array_writer
);
566 for (const auto& pair
: set_value_
) {
567 dbus::MessageWriter
struct_writer(nullptr);
568 array_writer
.OpenStruct(&struct_writer
);
569 struct_writer
.AppendArrayOfBytes(std::get
<0>(pair
).data(),
570 std::get
<0>(pair
).size());
571 struct_writer
.AppendUint16(std::get
<1>(pair
));
572 array_writer
.CloseContainer(&struct_writer
);
574 variant_writer
.CloseContainer(&array_writer
);
575 writer
->CloseContainer(&variant_writer
);
578 template class Property
<uint8
>;
579 template class Property
<bool>;
580 template class Property
<int16
>;
581 template class Property
<uint16
>;
582 template class Property
<int32
>;
583 template class Property
<uint32
>;
584 template class Property
<int64
>;
585 template class Property
<uint64
>;
586 template class Property
<double>;
587 template class Property
<std::string
>;
588 template class Property
<ObjectPath
>;
589 template class Property
<std::vector
<std::string
> >;
590 template class Property
<std::vector
<ObjectPath
> >;
591 template class Property
<std::vector
<uint8
> >;
592 template class Property
<std::map
<std::string
, std::string
>>;
593 template class Property
<std::vector
<std::pair
<std::vector
<uint8_t>, uint16_t>>>;