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"
11 #include "base/bind.h"
12 #include "base/logging.h"
14 #include "dbus/message.h"
15 #include "dbus/object_path.h"
16 #include "dbus/object_proxy.h"
21 // PropertyBase implementation.
24 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {}
26 PropertyBase::~PropertyBase() = default;
28 void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
29 DCHECK(!property_set_);
30 property_set_ = property_set;
36 // PropertySet implementation.
39 PropertySet::PropertySet(
40 ObjectProxy* object_proxy,
41 const std::string& interface,
42 const PropertyChangedCallback& property_changed_callback)
43 : object_proxy_(object_proxy),
44 interface_(interface),
45 property_changed_callback_(property_changed_callback) {}
47 PropertySet::~PropertySet() = default;
49 void PropertySet::RegisterProperty(const std::string& name,
50 PropertyBase* property) {
51 property->Init(this, name);
52 properties_map_[name] = property;
55 void PropertySet::ConnectSignals() {
56 DCHECK(object_proxy_);
57 object_proxy_->ConnectToSignal(
58 kPropertiesInterface, kPropertiesChanged,
59 base::BindRepeating(&PropertySet::ChangedReceived,
60 weak_ptr_factory_.GetWeakPtr()),
61 base::BindOnce(&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, ObjectProxy::TIMEOUT_USE_DEFAULT,
107 base::BindOnce(&PropertySet::OnGet, GetWeakPtr(),
108 property, std::move(callback)));
111 void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
112 Response* response) {
114 LOG(WARNING) << property->name() << ": Get: failed.";
118 MessageReader reader(response);
119 if (property->PopValueFromReader(&reader)) {
120 property->set_valid(true);
121 NotifyPropertyChanged(property->name());
123 if (property->is_valid()) {
124 property->set_valid(false);
125 NotifyPropertyChanged(property->name());
129 if (!callback.is_null())
130 std::move(callback).Run(response);
133 bool PropertySet::GetAndBlock(PropertyBase* property) {
134 MethodCall method_call(kPropertiesInterface, kPropertiesGet);
135 MessageWriter writer(&method_call);
136 writer.AppendString(interface());
137 writer.AppendString(property->name());
139 DCHECK(object_proxy_);
140 std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
141 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
143 if (!response.get()) {
144 LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
148 MessageReader reader(response.get());
149 if (property->PopValueFromReader(&reader)) {
150 property->set_valid(true);
151 NotifyPropertyChanged(property->name());
153 if (property->is_valid()) {
154 property->set_valid(false);
155 NotifyPropertyChanged(property->name());
161 void PropertySet::GetAll() {
162 MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
163 MessageWriter writer(&method_call);
164 writer.AppendString(interface());
166 DCHECK(object_proxy_);
167 object_proxy_->CallMethod(
168 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
169 base::BindOnce(&PropertySet::OnGetAll, weak_ptr_factory_.GetWeakPtr()));
172 void PropertySet::OnGetAll(Response* response) {
174 LOG(WARNING) << "GetAll request failed for: " << interface_;
178 MessageReader reader(response);
179 if (!UpdatePropertiesFromReader(&reader)) {
180 LOG(WARNING) << "GetAll response has wrong parameters: "
181 << "expected dictionary: " << response->ToString();
185 void PropertySet::Set(PropertyBase* property, SetCallback callback) {
186 MethodCall method_call(kPropertiesInterface, kPropertiesSet);
187 MessageWriter writer(&method_call);
188 writer.AppendString(interface());
189 writer.AppendString(property->name());
190 property->AppendSetValueToWriter(&writer);
192 DCHECK(object_proxy_);
193 object_proxy_->CallMethod(&method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
194 base::BindOnce(&PropertySet::OnSet, GetWeakPtr(),
195 property, std::move(callback)));
198 bool PropertySet::SetAndBlock(PropertyBase* property) {
199 MethodCall method_call(kPropertiesInterface, kPropertiesSet);
200 MessageWriter writer(&method_call);
201 writer.AppendString(interface());
202 writer.AppendString(property->name());
203 property->AppendSetValueToWriter(&writer);
205 DCHECK(object_proxy_);
206 std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
207 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
213 void PropertySet::OnSet(PropertyBase* property,
214 SetCallback callback,
215 Response* response) {
216 LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
217 if (!callback.is_null())
218 std::move(callback).Run(response);
221 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
223 MessageReader array_reader(nullptr);
224 if (!reader->PopArray(&array_reader))
227 while (array_reader.HasMoreData()) {
228 MessageReader dict_entry_reader(nullptr);
229 if (array_reader.PopDictEntry(&dict_entry_reader))
230 UpdatePropertyFromReader(&dict_entry_reader);
236 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
240 if (!reader->PopString(&name))
243 PropertiesMap::iterator it = properties_map_.find(name);
244 if (it == properties_map_.end())
247 PropertyBase* property = it->second;
248 if (property->PopValueFromReader(reader)) {
249 property->set_valid(true);
250 NotifyPropertyChanged(name);
253 if (property->is_valid()) {
254 property->set_valid(false);
255 NotifyPropertyChanged(property->name());
261 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
263 MessageReader array_reader(nullptr);
264 if (!reader->PopArray(&array_reader))
267 while (array_reader.HasMoreData()) {
269 if (!array_reader.PopString(&name))
272 PropertiesMap::iterator it = properties_map_.find(name);
273 if (it == properties_map_.end())
276 PropertyBase* property = it->second;
277 if (property->is_valid()) {
278 property->set_valid(false);
279 NotifyPropertyChanged(property->name());
286 void PropertySet::NotifyPropertyChanged(const std::string& name) {
287 if (!property_changed_callback_.is_null())
288 property_changed_callback_.Run(name);
292 // Property<Byte> specialization.
296 Property<uint8_t>::Property()
300 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
301 return reader->PopVariantOfByte(&value_);
305 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
306 writer->AppendVariantOfByte(set_value_);
310 // Property<bool> specialization.
314 Property<bool>::Property() : value_(false) {
318 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
319 return reader->PopVariantOfBool(&value_);
323 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
324 writer->AppendVariantOfBool(set_value_);
328 // Property<int16_t> specialization.
332 Property<int16_t>::Property()
336 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
337 return reader->PopVariantOfInt16(&value_);
341 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
342 writer->AppendVariantOfInt16(set_value_);
346 // Property<uint16_t> specialization.
350 Property<uint16_t>::Property()
354 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
355 return reader->PopVariantOfUint16(&value_);
359 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
360 writer->AppendVariantOfUint16(set_value_);
364 // Property<int32_t> specialization.
368 Property<int32_t>::Property()
372 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
373 return reader->PopVariantOfInt32(&value_);
377 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
378 writer->AppendVariantOfInt32(set_value_);
382 // Property<uint32_t> specialization.
386 Property<uint32_t>::Property()
390 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
391 return reader->PopVariantOfUint32(&value_);
395 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
396 writer->AppendVariantOfUint32(set_value_);
400 // Property<int64_t> specialization.
404 Property<int64_t>::Property()
405 : value_(0), set_value_(0) {}
408 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
409 return reader->PopVariantOfInt64(&value_);
413 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
414 writer->AppendVariantOfInt64(set_value_);
418 // Property<uint64_t> specialization.
422 Property<uint64_t>::Property()
426 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
427 return reader->PopVariantOfUint64(&value_);
431 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
432 writer->AppendVariantOfUint64(set_value_);
436 // Property<double> specialization.
440 Property<double>::Property() : value_(0.0) {
444 bool Property<double>::PopValueFromReader(MessageReader* reader) {
445 return reader->PopVariantOfDouble(&value_);
449 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
450 writer->AppendVariantOfDouble(set_value_);
454 // Property<std::string> specialization.
458 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
459 return reader->PopVariantOfString(&value_);
463 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
464 writer->AppendVariantOfString(set_value_);
468 // Property<ObjectPath> specialization.
472 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
473 return reader->PopVariantOfObjectPath(&value_);
477 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
478 writer->AppendVariantOfObjectPath(set_value_);
482 // Property<std::vector<std::string>> specialization.
486 bool Property<std::vector<std::string>>::PopValueFromReader(
487 MessageReader* reader) {
488 MessageReader variant_reader(nullptr);
489 if (!reader->PopVariant(&variant_reader))
493 return variant_reader.PopArrayOfStrings(&value_);
497 void Property<std::vector<std::string>>::AppendSetValueToWriter(
498 MessageWriter* writer) {
499 MessageWriter variant_writer(nullptr);
500 writer->OpenVariant("as", &variant_writer);
501 variant_writer.AppendArrayOfStrings(set_value_);
502 writer->CloseContainer(&variant_writer);
506 // Property<std::vector<ObjectPath>> specialization.
510 bool Property<std::vector<ObjectPath>>::PopValueFromReader(
511 MessageReader* reader) {
512 MessageReader variant_reader(nullptr);
513 if (!reader->PopVariant(&variant_reader))
517 return variant_reader.PopArrayOfObjectPaths(&value_);
521 void Property<std::vector<ObjectPath>>::AppendSetValueToWriter(
522 MessageWriter* writer) {
523 MessageWriter variant_writer(nullptr);
524 writer->OpenVariant("ao", &variant_writer);
525 variant_writer.AppendArrayOfObjectPaths(set_value_);
526 writer->CloseContainer(&variant_writer);
530 // Property<std::vector<uint8_t>> specialization.
534 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
535 MessageReader variant_reader(nullptr);
536 if (!reader->PopVariant(&variant_reader))
540 const uint8_t* bytes = nullptr;
542 if (!variant_reader.PopArrayOfBytes(&bytes, &length))
544 value_.assign(bytes, bytes + length);
549 void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
550 MessageWriter* writer) {
551 MessageWriter variant_writer(nullptr);
552 writer->OpenVariant("ay", &variant_writer);
553 variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
554 writer->CloseContainer(&variant_writer);
558 // Property<std::map<std::string, std::string>> specialization.
562 bool Property<std::map<std::string, std::string>>::PopValueFromReader(
563 MessageReader* reader) {
564 MessageReader variant_reader(nullptr);
565 MessageReader array_reader(nullptr);
566 if (!reader->PopVariant(&variant_reader) ||
567 !variant_reader.PopArray(&array_reader))
570 while (array_reader.HasMoreData()) {
571 dbus::MessageReader dict_entry_reader(nullptr);
572 if (!array_reader.PopDictEntry(&dict_entry_reader))
576 if (!dict_entry_reader.PopString(&key) ||
577 !dict_entry_reader.PopString(&value))
585 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
586 MessageWriter* writer) {
587 MessageWriter variant_writer(nullptr);
588 MessageWriter dict_writer(nullptr);
589 writer->OpenVariant("a{ss}", &variant_writer);
590 variant_writer.OpenArray("{ss}", &dict_writer);
591 for (const auto& pair : set_value_) {
592 dbus::MessageWriter entry_writer(nullptr);
593 dict_writer.OpenDictEntry(&entry_writer);
594 entry_writer.AppendString(pair.first);
595 entry_writer.AppendString(pair.second);
596 dict_writer.CloseContainer(&entry_writer);
598 variant_writer.CloseContainer(&dict_writer);
599 writer->CloseContainer(&variant_writer);
603 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
608 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
609 PopValueFromReader(MessageReader* reader) {
610 MessageReader variant_reader(nullptr);
611 MessageReader array_reader(nullptr);
612 if (!reader->PopVariant(&variant_reader) ||
613 !variant_reader.PopArray(&array_reader))
617 while (array_reader.HasMoreData()) {
618 dbus::MessageReader struct_reader(nullptr);
619 if (!array_reader.PopStruct(&struct_reader))
622 std::pair<std::vector<uint8_t>, uint16_t> entry;
623 const uint8_t* bytes = nullptr;
625 if (!struct_reader.PopArrayOfBytes(&bytes, &length))
627 entry.first.assign(bytes, bytes + length);
628 if (!struct_reader.PopUint16(&entry.second))
630 value_.push_back(entry);
636 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
637 AppendSetValueToWriter(MessageWriter* writer) {
638 MessageWriter variant_writer(nullptr);
639 MessageWriter array_writer(nullptr);
640 writer->OpenVariant("a(ayq)", &variant_writer);
641 variant_writer.OpenArray("(ayq)", &array_writer);
642 for (const auto& pair : set_value_) {
643 dbus::MessageWriter struct_writer(nullptr);
644 array_writer.OpenStruct(&struct_writer);
645 struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
646 std::get<0>(pair).size());
647 struct_writer.AppendUint16(std::get<1>(pair));
648 array_writer.CloseContainer(&struct_writer);
650 variant_writer.CloseContainer(&array_writer);
651 writer->CloseContainer(&variant_writer);
655 // Property<std::map<std::string, std::vector<uint8_t>>>
660 bool Property<std::map<std::string, std::vector<uint8_t>>>::PopValueFromReader(
661 MessageReader* reader) {
662 MessageReader variant_reader(nullptr);
663 MessageReader dict_reader(nullptr);
664 if (!reader->PopVariant(&variant_reader) ||
665 !variant_reader.PopArray(&dict_reader))
669 while (dict_reader.HasMoreData()) {
670 MessageReader entry_reader(nullptr);
671 if (!dict_reader.PopDictEntry(&entry_reader))
675 if (!entry_reader.PopString(&key))
678 const uint8_t* bytes = nullptr;
681 if (entry_reader.GetDataType() == Message::VARIANT) {
682 // Make BlueZ happy since it wraps the array of bytes with a variant.
683 MessageReader value_variant_reader(nullptr);
684 if (!entry_reader.PopVariant(&value_variant_reader))
686 if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
689 if (!entry_reader.PopArrayOfBytes(&bytes, &length))
693 value_[key].assign(bytes, bytes + length);
699 void Property<std::map<std::string, std::vector<uint8_t>>>::
700 AppendSetValueToWriter(MessageWriter* writer) {
701 MessageWriter variant_writer(nullptr);
702 MessageWriter dict_writer(nullptr);
704 writer->OpenVariant("a{sv}", &variant_writer);
705 variant_writer.OpenArray("{sv}", &dict_writer);
707 for (const auto& pair : set_value_) {
708 MessageWriter entry_writer(nullptr);
709 dict_writer.OpenDictEntry(&entry_writer);
711 entry_writer.AppendString(pair.first);
713 MessageWriter value_varient_writer(nullptr);
714 entry_writer.OpenVariant("ay", &value_varient_writer);
715 value_varient_writer.AppendArrayOfBytes(pair.second.data(),
717 entry_writer.CloseContainer(&value_varient_writer);
719 dict_writer.CloseContainer(&entry_writer);
722 variant_writer.CloseContainer(&dict_writer);
723 writer->CloseContainer(&variant_writer);
727 // Property<std::map<uint16_t, std::vector<uint8_t>>>
732 bool Property<std::map<uint16_t, std::vector<uint8_t>>>::PopValueFromReader(
733 MessageReader* reader) {
734 MessageReader variant_reader(nullptr);
735 MessageReader dict_reader(nullptr);
736 if (!reader->PopVariant(&variant_reader) ||
737 !variant_reader.PopArray(&dict_reader))
741 while (dict_reader.HasMoreData()) {
742 MessageReader entry_reader(nullptr);
743 if (!dict_reader.PopDictEntry(&entry_reader))
747 if (!entry_reader.PopUint16(&key))
750 const uint8_t* bytes = nullptr;
753 if (entry_reader.GetDataType() == Message::VARIANT) {
754 // Make BlueZ happy since it wraps the array of bytes with a variant.
755 MessageReader value_variant_reader(nullptr);
756 if (!entry_reader.PopVariant(&value_variant_reader))
758 if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
761 if (!entry_reader.PopArrayOfBytes(&bytes, &length))
765 value_[key].assign(bytes, bytes + length);
771 void Property<std::map<uint16_t, std::vector<uint8_t>>>::AppendSetValueToWriter(
772 MessageWriter* writer) {
773 MessageWriter variant_writer(nullptr);
774 MessageWriter dict_writer(nullptr);
776 writer->OpenVariant("a{qv}", &variant_writer);
777 variant_writer.OpenArray("{qv}", &dict_writer);
779 for (const auto& pair : set_value_) {
780 MessageWriter entry_writer(nullptr);
781 dict_writer.OpenDictEntry(&entry_writer);
783 entry_writer.AppendUint16(pair.first);
785 MessageWriter value_varient_writer(nullptr);
786 entry_writer.OpenVariant("ay", &value_varient_writer);
787 value_varient_writer.AppendArrayOfBytes(pair.second.data(),
789 entry_writer.CloseContainer(&value_varient_writer);
791 dict_writer.CloseContainer(&entry_writer);
794 variant_writer.CloseContainer(&dict_writer);
795 writer->CloseContainer(&variant_writer);
798 template class Property<uint8_t>;
799 template class Property<bool>;
800 template class Property<int16_t>;
801 template class Property<uint16_t>;
802 template class Property<int32_t>;
803 template class Property<uint32_t>;
804 template class Property<int64_t>;
805 template class Property<uint64_t>;
806 template class Property<double>;
807 template class Property<std::string>;
808 template class Property<ObjectPath>;
809 template class Property<std::vector<std::string>>;
810 template class Property<std::vector<ObjectPath>>;
811 template class Property<std::vector<uint8_t>>;
812 template class Property<std::map<std::string, std::string>>;
813 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
814 template class Property<std::map<std::string, std::vector<uint8_t>>>;
815 template class Property<std::map<uint16_t, std::vector<uint8_t>>>;