fixup! Upload upstream chromium 85.0.4183.93
[platform/framework/web/chromium-efl.git] / dbus / property.cc
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.
4
5 #include "dbus/property.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10
11 #include "base/bind.h"
12 #include "base/logging.h"
13
14 #include "dbus/message.h"
15 #include "dbus/object_path.h"
16 #include "dbus/object_proxy.h"
17
18 namespace dbus {
19
20 //
21 // PropertyBase implementation.
22 //
23
24 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {}
25
26 PropertyBase::~PropertyBase() = default;
27
28 void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
29   DCHECK(!property_set_);
30   property_set_ = property_set;
31   is_valid_ = false;
32   name_ = name;
33 }
34
35 //
36 // PropertySet implementation.
37 //
38
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) {}
46
47 PropertySet::~PropertySet() = default;
48
49 void PropertySet::RegisterProperty(const std::string& name,
50                                    PropertyBase* property) {
51   property->Init(this, name);
52   properties_map_[name] = property;
53 }
54
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()));
63 }
64
65
66 void PropertySet::ChangedReceived(Signal* signal) {
67   DCHECK(signal);
68   MessageReader reader(signal);
69
70   std::string interface;
71   if (!reader.PopString(&interface)) {
72     LOG(WARNING) << "Property changed signal has wrong parameters: "
73                  << "expected interface name: " << signal->ToString();
74     return;
75   }
76
77   if (interface != this->interface())
78     return;
79
80   if (!UpdatePropertiesFromReader(&reader)) {
81     LOG(WARNING) << "Property changed signal has wrong parameters: "
82                  << "expected dictionary: " << signal->ToString();
83   }
84
85   if (!InvalidatePropertiesFromReader(&reader)) {
86     LOG(WARNING) << "Property changed signal has wrong parameters: "
87                  << "expected array to invalidate: " << signal->ToString();
88   }
89 }
90
91 void PropertySet::ChangedConnected(const std::string& interface_name,
92                                    const std::string& signal_name,
93                                    bool success) {
94   LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name
95                             << "signal.";
96 }
97
98
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());
104
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)));
109 }
110
111 void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
112                         Response* response) {
113   if (!response) {
114     LOG(WARNING) << property->name() << ": Get: failed.";
115     return;
116   }
117
118   MessageReader reader(response);
119   if (property->PopValueFromReader(&reader)) {
120     property->set_valid(true);
121     NotifyPropertyChanged(property->name());
122   } else {
123     if (property->is_valid()) {
124       property->set_valid(false);
125       NotifyPropertyChanged(property->name());
126     }
127   }
128
129   if (!callback.is_null())
130     std::move(callback).Run(response);
131 }
132
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());
138
139   DCHECK(object_proxy_);
140   std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
141       &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
142
143   if (!response.get()) {
144     LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
145     return false;
146   }
147
148   MessageReader reader(response.get());
149   if (property->PopValueFromReader(&reader)) {
150     property->set_valid(true);
151     NotifyPropertyChanged(property->name());
152   } else {
153     if (property->is_valid()) {
154       property->set_valid(false);
155       NotifyPropertyChanged(property->name());
156     }
157   }
158   return true;
159 }
160
161 void PropertySet::GetAll() {
162   MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
163   MessageWriter writer(&method_call);
164   writer.AppendString(interface());
165
166   DCHECK(object_proxy_);
167   object_proxy_->CallMethod(
168       &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
169       base::BindOnce(&PropertySet::OnGetAll, weak_ptr_factory_.GetWeakPtr()));
170 }
171
172 void PropertySet::OnGetAll(Response* response) {
173   if (!response) {
174     LOG(WARNING) << "GetAll request failed for: " << interface_;
175     return;
176   }
177
178   MessageReader reader(response);
179   if (!UpdatePropertiesFromReader(&reader)) {
180     LOG(WARNING) << "GetAll response has wrong parameters: "
181                  << "expected dictionary: " << response->ToString();
182   }
183 }
184
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);
191
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)));
196 }
197
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);
204
205   DCHECK(object_proxy_);
206   std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
207       &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
208   if (response.get())
209     return true;
210   return false;
211 }
212
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);
219 }
220
221 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
222   DCHECK(reader);
223   MessageReader array_reader(nullptr);
224   if (!reader->PopArray(&array_reader))
225     return false;
226
227   while (array_reader.HasMoreData()) {
228     MessageReader dict_entry_reader(nullptr);
229     if (array_reader.PopDictEntry(&dict_entry_reader))
230       UpdatePropertyFromReader(&dict_entry_reader);
231   }
232
233   return true;
234 }
235
236 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
237   DCHECK(reader);
238
239   std::string name;
240   if (!reader->PopString(&name))
241     return false;
242
243   PropertiesMap::iterator it = properties_map_.find(name);
244   if (it == properties_map_.end())
245     return false;
246
247   PropertyBase* property = it->second;
248   if (property->PopValueFromReader(reader)) {
249     property->set_valid(true);
250     NotifyPropertyChanged(name);
251     return true;
252   } else {
253     if (property->is_valid()) {
254       property->set_valid(false);
255       NotifyPropertyChanged(property->name());
256     }
257     return false;
258   }
259 }
260
261 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
262   DCHECK(reader);
263   MessageReader array_reader(nullptr);
264   if (!reader->PopArray(&array_reader))
265     return false;
266
267   while (array_reader.HasMoreData()) {
268     std::string name;
269     if (!array_reader.PopString(&name))
270       return false;
271
272     PropertiesMap::iterator it = properties_map_.find(name);
273     if (it == properties_map_.end())
274       continue;
275
276     PropertyBase* property = it->second;
277     if (property->is_valid()) {
278       property->set_valid(false);
279       NotifyPropertyChanged(property->name());
280     }
281   }
282
283   return true;
284 }
285
286 void PropertySet::NotifyPropertyChanged(const std::string& name) {
287   if (!property_changed_callback_.is_null())
288     property_changed_callback_.Run(name);
289 }
290
291 //
292 // Property<Byte> specialization.
293 //
294
295 template <>
296 Property<uint8_t>::Property()
297     : value_(0) {}
298
299 template <>
300 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
301   return reader->PopVariantOfByte(&value_);
302 }
303
304 template <>
305 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
306   writer->AppendVariantOfByte(set_value_);
307 }
308
309 //
310 // Property<bool> specialization.
311 //
312
313 template <>
314 Property<bool>::Property() : value_(false) {
315 }
316
317 template <>
318 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
319   return reader->PopVariantOfBool(&value_);
320 }
321
322 template <>
323 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
324   writer->AppendVariantOfBool(set_value_);
325 }
326
327 //
328 // Property<int16_t> specialization.
329 //
330
331 template <>
332 Property<int16_t>::Property()
333     : value_(0) {}
334
335 template <>
336 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
337   return reader->PopVariantOfInt16(&value_);
338 }
339
340 template <>
341 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
342   writer->AppendVariantOfInt16(set_value_);
343 }
344
345 //
346 // Property<uint16_t> specialization.
347 //
348
349 template <>
350 Property<uint16_t>::Property()
351     : value_(0) {}
352
353 template <>
354 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
355   return reader->PopVariantOfUint16(&value_);
356 }
357
358 template <>
359 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
360   writer->AppendVariantOfUint16(set_value_);
361 }
362
363 //
364 // Property<int32_t> specialization.
365 //
366
367 template <>
368 Property<int32_t>::Property()
369     : value_(0) {}
370
371 template <>
372 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
373   return reader->PopVariantOfInt32(&value_);
374 }
375
376 template <>
377 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
378   writer->AppendVariantOfInt32(set_value_);
379 }
380
381 //
382 // Property<uint32_t> specialization.
383 //
384
385 template <>
386 Property<uint32_t>::Property()
387     : value_(0) {}
388
389 template <>
390 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
391   return reader->PopVariantOfUint32(&value_);
392 }
393
394 template <>
395 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
396   writer->AppendVariantOfUint32(set_value_);
397 }
398
399 //
400 // Property<int64_t> specialization.
401 //
402
403 template <>
404 Property<int64_t>::Property()
405     : value_(0), set_value_(0) {}
406
407 template <>
408 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
409   return reader->PopVariantOfInt64(&value_);
410 }
411
412 template <>
413 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
414   writer->AppendVariantOfInt64(set_value_);
415 }
416
417 //
418 // Property<uint64_t> specialization.
419 //
420
421 template <>
422 Property<uint64_t>::Property()
423     : value_(0) {}
424
425 template <>
426 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
427   return reader->PopVariantOfUint64(&value_);
428 }
429
430 template <>
431 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
432   writer->AppendVariantOfUint64(set_value_);
433 }
434
435 //
436 // Property<double> specialization.
437 //
438
439 template <>
440 Property<double>::Property() : value_(0.0) {
441 }
442
443 template <>
444 bool Property<double>::PopValueFromReader(MessageReader* reader) {
445   return reader->PopVariantOfDouble(&value_);
446 }
447
448 template <>
449 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
450   writer->AppendVariantOfDouble(set_value_);
451 }
452
453 //
454 // Property<std::string> specialization.
455 //
456
457 template <>
458 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
459   return reader->PopVariantOfString(&value_);
460 }
461
462 template <>
463 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
464   writer->AppendVariantOfString(set_value_);
465 }
466
467 //
468 // Property<ObjectPath> specialization.
469 //
470
471 template <>
472 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
473   return reader->PopVariantOfObjectPath(&value_);
474 }
475
476 template <>
477 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
478   writer->AppendVariantOfObjectPath(set_value_);
479 }
480
481 //
482 // Property<std::vector<std::string>> specialization.
483 //
484
485 template <>
486 bool Property<std::vector<std::string>>::PopValueFromReader(
487     MessageReader* reader) {
488   MessageReader variant_reader(nullptr);
489   if (!reader->PopVariant(&variant_reader))
490     return false;
491
492   value_.clear();
493   return variant_reader.PopArrayOfStrings(&value_);
494 }
495
496 template <>
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);
503 }
504
505 //
506 // Property<std::vector<ObjectPath>> specialization.
507 //
508
509 template <>
510 bool Property<std::vector<ObjectPath>>::PopValueFromReader(
511     MessageReader* reader) {
512   MessageReader variant_reader(nullptr);
513   if (!reader->PopVariant(&variant_reader))
514     return false;
515
516   value_.clear();
517   return variant_reader.PopArrayOfObjectPaths(&value_);
518 }
519
520 template <>
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);
527 }
528
529 //
530 // Property<std::vector<uint8_t>> specialization.
531 //
532
533 template <>
534 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
535   MessageReader variant_reader(nullptr);
536   if (!reader->PopVariant(&variant_reader))
537     return false;
538
539   value_.clear();
540   const uint8_t* bytes = nullptr;
541   size_t length = 0;
542   if (!variant_reader.PopArrayOfBytes(&bytes, &length))
543     return false;
544   value_.assign(bytes, bytes + length);
545   return true;
546 }
547
548 template <>
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);
555 }
556
557 //
558 // Property<std::map<std::string, std::string>> specialization.
559 //
560
561 template <>
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))
568     return false;
569   value_.clear();
570   while (array_reader.HasMoreData()) {
571     dbus::MessageReader dict_entry_reader(nullptr);
572     if (!array_reader.PopDictEntry(&dict_entry_reader))
573       return false;
574     std::string key;
575     std::string value;
576     if (!dict_entry_reader.PopString(&key) ||
577         !dict_entry_reader.PopString(&value))
578       return false;
579     value_[key] = value;
580   }
581   return true;
582 }
583
584 template <>
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);
597   }
598   variant_writer.CloseContainer(&dict_writer);
599   writer->CloseContainer(&variant_writer);
600 }
601
602 //
603 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
604 // specialization.
605 //
606
607 template <>
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))
614     return false;
615
616   value_.clear();
617   while (array_reader.HasMoreData()) {
618     dbus::MessageReader struct_reader(nullptr);
619     if (!array_reader.PopStruct(&struct_reader))
620       return false;
621
622     std::pair<std::vector<uint8_t>, uint16_t> entry;
623     const uint8_t* bytes = nullptr;
624     size_t length = 0;
625     if (!struct_reader.PopArrayOfBytes(&bytes, &length))
626       return false;
627     entry.first.assign(bytes, bytes + length);
628     if (!struct_reader.PopUint16(&entry.second))
629       return false;
630     value_.push_back(entry);
631   }
632   return true;
633 }
634
635 template <>
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);
649   }
650   variant_writer.CloseContainer(&array_writer);
651   writer->CloseContainer(&variant_writer);
652 }
653
654 //
655 // Property<std::map<std::string, std::vector<uint8_t>>>
656 // specialization.
657 //
658
659 template <>
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))
666     return false;
667
668   value_.clear();
669   while (dict_reader.HasMoreData()) {
670     MessageReader entry_reader(nullptr);
671     if (!dict_reader.PopDictEntry(&entry_reader))
672       return false;
673
674     std::string key;
675     if (!entry_reader.PopString(&key))
676       return false;
677
678     const uint8_t* bytes = nullptr;
679     size_t length = 0;
680
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))
685         return false;
686       if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
687         return false;
688     } else {
689       if (!entry_reader.PopArrayOfBytes(&bytes, &length))
690         return false;
691     }
692
693     value_[key].assign(bytes, bytes + length);
694   }
695   return true;
696 }
697
698 template <>
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);
703
704   writer->OpenVariant("a{sv}", &variant_writer);
705   variant_writer.OpenArray("{sv}", &dict_writer);
706
707   for (const auto& pair : set_value_) {
708     MessageWriter entry_writer(nullptr);
709     dict_writer.OpenDictEntry(&entry_writer);
710
711     entry_writer.AppendString(pair.first);
712
713     MessageWriter value_varient_writer(nullptr);
714     entry_writer.OpenVariant("ay", &value_varient_writer);
715     value_varient_writer.AppendArrayOfBytes(pair.second.data(),
716                                             pair.second.size());
717     entry_writer.CloseContainer(&value_varient_writer);
718
719     dict_writer.CloseContainer(&entry_writer);
720   }
721
722   variant_writer.CloseContainer(&dict_writer);
723   writer->CloseContainer(&variant_writer);
724 }
725
726 //
727 // Property<std::map<uint16_t, std::vector<uint8_t>>>
728 // specialization.
729 //
730
731 template <>
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))
738     return false;
739
740   value_.clear();
741   while (dict_reader.HasMoreData()) {
742     MessageReader entry_reader(nullptr);
743     if (!dict_reader.PopDictEntry(&entry_reader))
744       return false;
745
746     uint16_t key;
747     if (!entry_reader.PopUint16(&key))
748       return false;
749
750     const uint8_t* bytes = nullptr;
751     size_t length = 0;
752
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))
757         return false;
758       if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
759         return false;
760     } else {
761       if (!entry_reader.PopArrayOfBytes(&bytes, &length))
762         return false;
763     }
764
765     value_[key].assign(bytes, bytes + length);
766   }
767   return true;
768 }
769
770 template <>
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);
775
776   writer->OpenVariant("a{qv}", &variant_writer);
777   variant_writer.OpenArray("{qv}", &dict_writer);
778
779   for (const auto& pair : set_value_) {
780     MessageWriter entry_writer(nullptr);
781     dict_writer.OpenDictEntry(&entry_writer);
782
783     entry_writer.AppendUint16(pair.first);
784
785     MessageWriter value_varient_writer(nullptr);
786     entry_writer.OpenVariant("ay", &value_varient_writer);
787     value_varient_writer.AppendArrayOfBytes(pair.second.data(),
788                                             pair.second.size());
789     entry_writer.CloseContainer(&value_varient_writer);
790
791     dict_writer.CloseContainer(&entry_writer);
792   }
793
794   variant_writer.CloseContainer(&dict_writer);
795   writer->CloseContainer(&variant_writer);
796 }
797
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>>>;
816
817 }  // namespace dbus