1 // Copyright 2012 The Chromium Authors
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/functional/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 auto result = object_proxy_->CallMethodAndBlock(
141 &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT);
143 if (!result.has_value()) {
144 LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
148 MessageReader reader(result->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_);
207 ->CallMethodAndBlock(&method_call, ObjectProxy::TIMEOUT_USE_DEFAULT)
211 void PropertySet::OnSet(PropertyBase* property,
212 SetCallback callback,
213 Response* response) {
214 LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
215 if (!callback.is_null())
216 std::move(callback).Run(response);
219 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
221 MessageReader array_reader(nullptr);
222 if (!reader->PopArray(&array_reader))
225 while (array_reader.HasMoreData()) {
226 MessageReader dict_entry_reader(nullptr);
227 if (array_reader.PopDictEntry(&dict_entry_reader))
228 UpdatePropertyFromReader(&dict_entry_reader);
234 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
238 if (!reader->PopString(&name))
241 PropertiesMap::iterator it = properties_map_.find(name);
242 if (it == properties_map_.end())
245 PropertyBase* property = it->second;
246 if (property->PopValueFromReader(reader)) {
247 property->set_valid(true);
248 NotifyPropertyChanged(name);
251 if (property->is_valid()) {
252 property->set_valid(false);
253 NotifyPropertyChanged(property->name());
259 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
261 MessageReader array_reader(nullptr);
262 if (!reader->PopArray(&array_reader))
265 while (array_reader.HasMoreData()) {
267 if (!array_reader.PopString(&name))
270 PropertiesMap::iterator it = properties_map_.find(name);
271 if (it == properties_map_.end())
274 PropertyBase* property = it->second;
275 if (property->is_valid()) {
276 property->set_valid(false);
277 NotifyPropertyChanged(property->name());
284 void PropertySet::NotifyPropertyChanged(const std::string& name) {
285 if (!property_changed_callback_.is_null())
286 property_changed_callback_.Run(name);
290 // Property<Byte> specialization.
294 Property<uint8_t>::Property()
298 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
299 return reader->PopVariantOfByte(&value_);
303 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
304 writer->AppendVariantOfByte(set_value_);
308 // Property<bool> specialization.
312 Property<bool>::Property() : value_(false) {
316 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
317 return reader->PopVariantOfBool(&value_);
321 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
322 writer->AppendVariantOfBool(set_value_);
326 // Property<int16_t> specialization.
330 Property<int16_t>::Property()
334 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
335 return reader->PopVariantOfInt16(&value_);
339 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
340 writer->AppendVariantOfInt16(set_value_);
344 // Property<uint16_t> specialization.
348 Property<uint16_t>::Property()
352 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
353 return reader->PopVariantOfUint16(&value_);
357 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
358 writer->AppendVariantOfUint16(set_value_);
362 // Property<int32_t> specialization.
366 Property<int32_t>::Property()
370 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
371 return reader->PopVariantOfInt32(&value_);
375 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
376 writer->AppendVariantOfInt32(set_value_);
380 // Property<uint32_t> specialization.
384 Property<uint32_t>::Property()
388 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
389 return reader->PopVariantOfUint32(&value_);
393 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
394 writer->AppendVariantOfUint32(set_value_);
398 // Property<int64_t> specialization.
402 Property<int64_t>::Property()
403 : value_(0), set_value_(0) {}
406 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
407 return reader->PopVariantOfInt64(&value_);
411 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
412 writer->AppendVariantOfInt64(set_value_);
416 // Property<uint64_t> specialization.
420 Property<uint64_t>::Property()
424 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
425 return reader->PopVariantOfUint64(&value_);
429 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
430 writer->AppendVariantOfUint64(set_value_);
434 // Property<double> specialization.
438 Property<double>::Property() : value_(0.0) {
442 bool Property<double>::PopValueFromReader(MessageReader* reader) {
443 return reader->PopVariantOfDouble(&value_);
447 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
448 writer->AppendVariantOfDouble(set_value_);
452 // Property<std::string> specialization.
456 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
457 return reader->PopVariantOfString(&value_);
461 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
462 writer->AppendVariantOfString(set_value_);
466 // Property<ObjectPath> specialization.
470 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
471 return reader->PopVariantOfObjectPath(&value_);
475 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
476 writer->AppendVariantOfObjectPath(set_value_);
480 // Property<std::vector<std::string>> specialization.
484 bool Property<std::vector<std::string>>::PopValueFromReader(
485 MessageReader* reader) {
486 MessageReader variant_reader(nullptr);
487 if (!reader->PopVariant(&variant_reader))
491 return variant_reader.PopArrayOfStrings(&value_);
495 void Property<std::vector<std::string>>::AppendSetValueToWriter(
496 MessageWriter* writer) {
497 MessageWriter variant_writer(nullptr);
498 writer->OpenVariant("as", &variant_writer);
499 variant_writer.AppendArrayOfStrings(set_value_);
500 writer->CloseContainer(&variant_writer);
504 // Property<std::vector<ObjectPath>> specialization.
508 bool Property<std::vector<ObjectPath>>::PopValueFromReader(
509 MessageReader* reader) {
510 MessageReader variant_reader(nullptr);
511 if (!reader->PopVariant(&variant_reader))
515 return variant_reader.PopArrayOfObjectPaths(&value_);
519 void Property<std::vector<ObjectPath>>::AppendSetValueToWriter(
520 MessageWriter* writer) {
521 MessageWriter variant_writer(nullptr);
522 writer->OpenVariant("ao", &variant_writer);
523 variant_writer.AppendArrayOfObjectPaths(set_value_);
524 writer->CloseContainer(&variant_writer);
528 // Property<std::vector<uint8_t>> specialization.
532 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
533 MessageReader variant_reader(nullptr);
534 if (!reader->PopVariant(&variant_reader))
538 const uint8_t* bytes = nullptr;
540 if (!variant_reader.PopArrayOfBytes(&bytes, &length))
542 value_.assign(bytes, bytes + length);
547 void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
548 MessageWriter* writer) {
549 MessageWriter variant_writer(nullptr);
550 writer->OpenVariant("ay", &variant_writer);
551 variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
552 writer->CloseContainer(&variant_writer);
556 // Property<std::map<std::string, std::string>> specialization.
560 bool Property<std::map<std::string, std::string>>::PopValueFromReader(
561 MessageReader* reader) {
562 MessageReader variant_reader(nullptr);
563 MessageReader array_reader(nullptr);
564 if (!reader->PopVariant(&variant_reader) ||
565 !variant_reader.PopArray(&array_reader))
568 while (array_reader.HasMoreData()) {
569 dbus::MessageReader dict_entry_reader(nullptr);
570 if (!array_reader.PopDictEntry(&dict_entry_reader))
574 if (!dict_entry_reader.PopString(&key) ||
575 !dict_entry_reader.PopString(&value))
583 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
584 MessageWriter* writer) {
585 MessageWriter variant_writer(nullptr);
586 MessageWriter dict_writer(nullptr);
587 writer->OpenVariant("a{ss}", &variant_writer);
588 variant_writer.OpenArray("{ss}", &dict_writer);
589 for (const auto& pair : set_value_) {
590 dbus::MessageWriter entry_writer(nullptr);
591 dict_writer.OpenDictEntry(&entry_writer);
592 entry_writer.AppendString(pair.first);
593 entry_writer.AppendString(pair.second);
594 dict_writer.CloseContainer(&entry_writer);
596 variant_writer.CloseContainer(&dict_writer);
597 writer->CloseContainer(&variant_writer);
601 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
606 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
607 PopValueFromReader(MessageReader* reader) {
608 MessageReader variant_reader(nullptr);
609 MessageReader array_reader(nullptr);
610 if (!reader->PopVariant(&variant_reader) ||
611 !variant_reader.PopArray(&array_reader))
615 while (array_reader.HasMoreData()) {
616 dbus::MessageReader struct_reader(nullptr);
617 if (!array_reader.PopStruct(&struct_reader))
620 std::pair<std::vector<uint8_t>, uint16_t> entry;
621 const uint8_t* bytes = nullptr;
623 if (!struct_reader.PopArrayOfBytes(&bytes, &length))
625 entry.first.assign(bytes, bytes + length);
626 if (!struct_reader.PopUint16(&entry.second))
628 value_.push_back(entry);
634 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
635 AppendSetValueToWriter(MessageWriter* writer) {
636 MessageWriter variant_writer(nullptr);
637 MessageWriter array_writer(nullptr);
638 writer->OpenVariant("a(ayq)", &variant_writer);
639 variant_writer.OpenArray("(ayq)", &array_writer);
640 for (const auto& pair : set_value_) {
641 dbus::MessageWriter struct_writer(nullptr);
642 array_writer.OpenStruct(&struct_writer);
643 struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
644 std::get<0>(pair).size());
645 struct_writer.AppendUint16(std::get<1>(pair));
646 array_writer.CloseContainer(&struct_writer);
648 variant_writer.CloseContainer(&array_writer);
649 writer->CloseContainer(&variant_writer);
653 // Property<std::map<std::string, std::vector<uint8_t>>>
658 bool Property<std::map<std::string, std::vector<uint8_t>>>::PopValueFromReader(
659 MessageReader* reader) {
660 MessageReader variant_reader(nullptr);
661 MessageReader dict_reader(nullptr);
662 if (!reader->PopVariant(&variant_reader) ||
663 !variant_reader.PopArray(&dict_reader))
667 while (dict_reader.HasMoreData()) {
668 MessageReader entry_reader(nullptr);
669 if (!dict_reader.PopDictEntry(&entry_reader))
673 if (!entry_reader.PopString(&key))
676 const uint8_t* bytes = nullptr;
679 if (entry_reader.GetDataType() == Message::VARIANT) {
680 // Make BlueZ happy since it wraps the array of bytes with a variant.
681 MessageReader value_variant_reader(nullptr);
682 if (!entry_reader.PopVariant(&value_variant_reader))
684 if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
687 if (!entry_reader.PopArrayOfBytes(&bytes, &length))
691 value_[key].assign(bytes, bytes + length);
697 void Property<std::map<std::string, std::vector<uint8_t>>>::
698 AppendSetValueToWriter(MessageWriter* writer) {
699 MessageWriter variant_writer(nullptr);
700 MessageWriter dict_writer(nullptr);
702 writer->OpenVariant("a{sv}", &variant_writer);
703 variant_writer.OpenArray("{sv}", &dict_writer);
705 for (const auto& pair : set_value_) {
706 MessageWriter entry_writer(nullptr);
707 dict_writer.OpenDictEntry(&entry_writer);
709 entry_writer.AppendString(pair.first);
711 MessageWriter value_varient_writer(nullptr);
712 entry_writer.OpenVariant("ay", &value_varient_writer);
713 value_varient_writer.AppendArrayOfBytes(pair.second.data(),
715 entry_writer.CloseContainer(&value_varient_writer);
717 dict_writer.CloseContainer(&entry_writer);
720 variant_writer.CloseContainer(&dict_writer);
721 writer->CloseContainer(&variant_writer);
725 // Property<std::map<uint16_t, std::vector<uint8_t>>>
730 bool Property<std::map<uint16_t, std::vector<uint8_t>>>::PopValueFromReader(
731 MessageReader* reader) {
732 MessageReader variant_reader(nullptr);
733 MessageReader dict_reader(nullptr);
734 if (!reader->PopVariant(&variant_reader) ||
735 !variant_reader.PopArray(&dict_reader))
739 while (dict_reader.HasMoreData()) {
740 MessageReader entry_reader(nullptr);
741 if (!dict_reader.PopDictEntry(&entry_reader))
745 if (!entry_reader.PopUint16(&key))
748 const uint8_t* bytes = nullptr;
751 if (entry_reader.GetDataType() == Message::VARIANT) {
752 // Make BlueZ happy since it wraps the array of bytes with a variant.
753 MessageReader value_variant_reader(nullptr);
754 if (!entry_reader.PopVariant(&value_variant_reader))
756 if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
759 if (!entry_reader.PopArrayOfBytes(&bytes, &length))
763 value_[key].assign(bytes, bytes + length);
769 void Property<std::map<uint16_t, std::vector<uint8_t>>>::AppendSetValueToWriter(
770 MessageWriter* writer) {
771 MessageWriter variant_writer(nullptr);
772 MessageWriter dict_writer(nullptr);
774 writer->OpenVariant("a{qv}", &variant_writer);
775 variant_writer.OpenArray("{qv}", &dict_writer);
777 for (const auto& pair : set_value_) {
778 MessageWriter entry_writer(nullptr);
779 dict_writer.OpenDictEntry(&entry_writer);
781 entry_writer.AppendUint16(pair.first);
783 MessageWriter value_varient_writer(nullptr);
784 entry_writer.OpenVariant("ay", &value_varient_writer);
785 value_varient_writer.AppendArrayOfBytes(pair.second.data(),
787 entry_writer.CloseContainer(&value_varient_writer);
789 dict_writer.CloseContainer(&entry_writer);
792 variant_writer.CloseContainer(&dict_writer);
793 writer->CloseContainer(&variant_writer);
796 template class Property<uint8_t>;
797 template class Property<bool>;
798 template class Property<int16_t>;
799 template class Property<uint16_t>;
800 template class Property<int32_t>;
801 template class Property<uint32_t>;
802 template class Property<int64_t>;
803 template class Property<uint64_t>;
804 template class Property<double>;
805 template class Property<std::string>;
806 template class Property<ObjectPath>;
807 template class Property<std::vector<std::string>>;
808 template class Property<std::vector<ObjectPath>>;
809 template class Property<std::vector<uint8_t>>;
810 template class Property<std::map<std::string, std::string>>;
811 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
812 template class Property<std::map<std::string, std::vector<uint8_t>>>;
813 template class Property<std::map<uint16_t, std::vector<uint8_t>>>;