• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PropertyBase()24 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {}
25 
26 PropertyBase::~PropertyBase() = default;
27 
Init(PropertySet * property_set,const std::string & name)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 
PropertySet(ObjectProxy * object_proxy,const std::string & interface,const PropertyChangedCallback & property_changed_callback)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       weak_ptr_factory_(this) {}
47 
48 PropertySet::~PropertySet() = default;
49 
RegisterProperty(const std::string & name,PropertyBase * property)50 void PropertySet::RegisterProperty(const std::string& name,
51                                    PropertyBase* property) {
52   property->Init(this, name);
53   properties_map_[name] = property;
54 }
55 
ConnectSignals()56 void PropertySet::ConnectSignals() {
57   DCHECK(object_proxy_);
58   object_proxy_->ConnectToSignal(
59       kPropertiesInterface,
60       kPropertiesChanged,
61       base::Bind(&PropertySet::ChangedReceived,
62                  weak_ptr_factory_.GetWeakPtr()),
63       base::Bind(&PropertySet::ChangedConnected,
64                  weak_ptr_factory_.GetWeakPtr()));
65 }
66 
67 
ChangedReceived(Signal * signal)68 void PropertySet::ChangedReceived(Signal* signal) {
69   DCHECK(signal);
70   MessageReader reader(signal);
71 
72   std::string interface;
73   if (!reader.PopString(&interface)) {
74     LOG(WARNING) << "Property changed signal has wrong parameters: "
75                  << "expected interface name: " << signal->ToString();
76     return;
77   }
78 
79   if (interface != this->interface())
80     return;
81 
82   if (!UpdatePropertiesFromReader(&reader)) {
83     LOG(WARNING) << "Property changed signal has wrong parameters: "
84                  << "expected dictionary: " << signal->ToString();
85   }
86 
87   if (!InvalidatePropertiesFromReader(&reader)) {
88     LOG(WARNING) << "Property changed signal has wrong parameters: "
89                  << "expected array to invalidate: " << signal->ToString();
90   }
91 }
92 
ChangedConnected(const std::string & interface_name,const std::string & signal_name,bool success)93 void PropertySet::ChangedConnected(const std::string& interface_name,
94                                    const std::string& signal_name,
95                                    bool success) {
96   LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name
97                             << "signal.";
98 }
99 
100 
Get(PropertyBase * property,GetCallback callback)101 void PropertySet::Get(PropertyBase* property, GetCallback callback) {
102   MethodCall method_call(kPropertiesInterface, kPropertiesGet);
103   MessageWriter writer(&method_call);
104   writer.AppendString(interface());
105   writer.AppendString(property->name());
106 
107   DCHECK(object_proxy_);
108   object_proxy_->CallMethod(&method_call,
109                             ObjectProxy::TIMEOUT_USE_DEFAULT,
110                             base::Bind(&PropertySet::OnGet,
111                                        GetWeakPtr(),
112                                        property,
113                                        callback));
114 }
115 
OnGet(PropertyBase * property,GetCallback callback,Response * response)116 void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
117                         Response* response) {
118   if (!response) {
119     LOG(WARNING) << property->name() << ": Get: failed.";
120     return;
121   }
122 
123   MessageReader reader(response);
124   if (property->PopValueFromReader(&reader)) {
125     property->set_valid(true);
126     NotifyPropertyChanged(property->name());
127   } else {
128     if (property->is_valid()) {
129       property->set_valid(false);
130       NotifyPropertyChanged(property->name());
131     }
132   }
133 
134   if (!callback.is_null())
135     callback.Run(response);
136 }
137 
GetAndBlock(PropertyBase * property)138 bool PropertySet::GetAndBlock(PropertyBase* property) {
139   MethodCall method_call(kPropertiesInterface, kPropertiesGet);
140   MessageWriter writer(&method_call);
141   writer.AppendString(interface());
142   writer.AppendString(property->name());
143 
144   DCHECK(object_proxy_);
145   std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
146       &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
147 
148   if (!response.get()) {
149     LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
150     return false;
151   }
152 
153   MessageReader reader(response.get());
154   if (property->PopValueFromReader(&reader)) {
155     property->set_valid(true);
156     NotifyPropertyChanged(property->name());
157   } else {
158     if (property->is_valid()) {
159       property->set_valid(false);
160       NotifyPropertyChanged(property->name());
161     }
162   }
163   return true;
164 }
165 
GetAll()166 void PropertySet::GetAll() {
167   MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
168   MessageWriter writer(&method_call);
169   writer.AppendString(interface());
170 
171   DCHECK(object_proxy_);
172   object_proxy_->CallMethod(&method_call,
173                             ObjectProxy::TIMEOUT_USE_DEFAULT,
174                             base::Bind(&PropertySet::OnGetAll,
175                                        weak_ptr_factory_.GetWeakPtr()));
176 }
177 
OnGetAll(Response * response)178 void PropertySet::OnGetAll(Response* response) {
179   if (!response) {
180     LOG(WARNING) << "GetAll request failed for: " << interface_;
181     return;
182   }
183 
184   MessageReader reader(response);
185   if (!UpdatePropertiesFromReader(&reader)) {
186     LOG(WARNING) << "GetAll response has wrong parameters: "
187                  << "expected dictionary: " << response->ToString();
188   }
189 }
190 
Set(PropertyBase * property,SetCallback callback)191 void PropertySet::Set(PropertyBase* property, SetCallback callback) {
192   MethodCall method_call(kPropertiesInterface, kPropertiesSet);
193   MessageWriter writer(&method_call);
194   writer.AppendString(interface());
195   writer.AppendString(property->name());
196   property->AppendSetValueToWriter(&writer);
197 
198   DCHECK(object_proxy_);
199   object_proxy_->CallMethod(&method_call,
200                             ObjectProxy::TIMEOUT_USE_DEFAULT,
201                             base::Bind(&PropertySet::OnSet,
202                                        GetWeakPtr(),
203                                        property,
204                                        callback));
205 }
206 
SetAndBlock(PropertyBase * property)207 bool PropertySet::SetAndBlock(PropertyBase* property) {
208   MethodCall method_call(kPropertiesInterface, kPropertiesSet);
209   MessageWriter writer(&method_call);
210   writer.AppendString(interface());
211   writer.AppendString(property->name());
212   property->AppendSetValueToWriter(&writer);
213 
214   DCHECK(object_proxy_);
215   std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
216       &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
217   if (response.get())
218     return true;
219   return false;
220 }
221 
OnSet(PropertyBase * property,SetCallback callback,Response * response)222 void PropertySet::OnSet(PropertyBase* property,
223                         SetCallback callback,
224                         Response* response) {
225   LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
226   if (!callback.is_null())
227     callback.Run(response);
228 }
229 
UpdatePropertiesFromReader(MessageReader * reader)230 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
231   DCHECK(reader);
232   MessageReader array_reader(nullptr);
233   if (!reader->PopArray(&array_reader))
234     return false;
235 
236   while (array_reader.HasMoreData()) {
237     MessageReader dict_entry_reader(nullptr);
238     if (array_reader.PopDictEntry(&dict_entry_reader))
239       UpdatePropertyFromReader(&dict_entry_reader);
240   }
241 
242   return true;
243 }
244 
UpdatePropertyFromReader(MessageReader * reader)245 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
246   DCHECK(reader);
247 
248   std::string name;
249   if (!reader->PopString(&name))
250     return false;
251 
252   PropertiesMap::iterator it = properties_map_.find(name);
253   if (it == properties_map_.end())
254     return false;
255 
256   PropertyBase* property = it->second;
257   if (property->PopValueFromReader(reader)) {
258     property->set_valid(true);
259     NotifyPropertyChanged(name);
260     return true;
261   } else {
262     if (property->is_valid()) {
263       property->set_valid(false);
264       NotifyPropertyChanged(property->name());
265     }
266     return false;
267   }
268 }
269 
InvalidatePropertiesFromReader(MessageReader * reader)270 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
271   DCHECK(reader);
272   MessageReader array_reader(nullptr);
273   if (!reader->PopArray(&array_reader))
274     return false;
275 
276   while (array_reader.HasMoreData()) {
277     std::string name;
278     if (!array_reader.PopString(&name))
279       return false;
280 
281     PropertiesMap::iterator it = properties_map_.find(name);
282     if (it == properties_map_.end())
283       continue;
284 
285     PropertyBase* property = it->second;
286     if (property->is_valid()) {
287       property->set_valid(false);
288       NotifyPropertyChanged(property->name());
289     }
290   }
291 
292   return true;
293 }
294 
NotifyPropertyChanged(const std::string & name)295 void PropertySet::NotifyPropertyChanged(const std::string& name) {
296   if (!property_changed_callback_.is_null())
297     property_changed_callback_.Run(name);
298 }
299 
300 //
301 // Property<Byte> specialization.
302 //
303 
304 template <>
Property()305 Property<uint8_t>::Property()
306     : value_(0) {}
307 
308 template <>
PopValueFromReader(MessageReader * reader)309 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
310   return reader->PopVariantOfByte(&value_);
311 }
312 
313 template <>
AppendSetValueToWriter(MessageWriter * writer)314 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
315   writer->AppendVariantOfByte(set_value_);
316 }
317 
318 //
319 // Property<bool> specialization.
320 //
321 
322 template <>
Property()323 Property<bool>::Property() : value_(false) {
324 }
325 
326 template <>
PopValueFromReader(MessageReader * reader)327 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
328   return reader->PopVariantOfBool(&value_);
329 }
330 
331 template <>
AppendSetValueToWriter(MessageWriter * writer)332 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
333   writer->AppendVariantOfBool(set_value_);
334 }
335 
336 //
337 // Property<int16_t> specialization.
338 //
339 
340 template <>
Property()341 Property<int16_t>::Property()
342     : value_(0) {}
343 
344 template <>
PopValueFromReader(MessageReader * reader)345 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
346   return reader->PopVariantOfInt16(&value_);
347 }
348 
349 template <>
AppendSetValueToWriter(MessageWriter * writer)350 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
351   writer->AppendVariantOfInt16(set_value_);
352 }
353 
354 //
355 // Property<uint16_t> specialization.
356 //
357 
358 template <>
Property()359 Property<uint16_t>::Property()
360     : value_(0) {}
361 
362 template <>
PopValueFromReader(MessageReader * reader)363 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
364   return reader->PopVariantOfUint16(&value_);
365 }
366 
367 template <>
AppendSetValueToWriter(MessageWriter * writer)368 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
369   writer->AppendVariantOfUint16(set_value_);
370 }
371 
372 //
373 // Property<int32_t> specialization.
374 //
375 
376 template <>
Property()377 Property<int32_t>::Property()
378     : value_(0) {}
379 
380 template <>
PopValueFromReader(MessageReader * reader)381 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
382   return reader->PopVariantOfInt32(&value_);
383 }
384 
385 template <>
AppendSetValueToWriter(MessageWriter * writer)386 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
387   writer->AppendVariantOfInt32(set_value_);
388 }
389 
390 //
391 // Property<uint32_t> specialization.
392 //
393 
394 template <>
Property()395 Property<uint32_t>::Property()
396     : value_(0) {}
397 
398 template <>
PopValueFromReader(MessageReader * reader)399 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
400   return reader->PopVariantOfUint32(&value_);
401 }
402 
403 template <>
AppendSetValueToWriter(MessageWriter * writer)404 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
405   writer->AppendVariantOfUint32(set_value_);
406 }
407 
408 //
409 // Property<int64_t> specialization.
410 //
411 
412 template <>
Property()413 Property<int64_t>::Property()
414     : value_(0), set_value_(0) {}
415 
416 template <>
PopValueFromReader(MessageReader * reader)417 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
418   return reader->PopVariantOfInt64(&value_);
419 }
420 
421 template <>
AppendSetValueToWriter(MessageWriter * writer)422 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
423   writer->AppendVariantOfInt64(set_value_);
424 }
425 
426 //
427 // Property<uint64_t> specialization.
428 //
429 
430 template <>
Property()431 Property<uint64_t>::Property()
432     : value_(0) {}
433 
434 template <>
PopValueFromReader(MessageReader * reader)435 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
436   return reader->PopVariantOfUint64(&value_);
437 }
438 
439 template <>
AppendSetValueToWriter(MessageWriter * writer)440 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
441   writer->AppendVariantOfUint64(set_value_);
442 }
443 
444 //
445 // Property<double> specialization.
446 //
447 
448 template <>
Property()449 Property<double>::Property() : value_(0.0) {
450 }
451 
452 template <>
PopValueFromReader(MessageReader * reader)453 bool Property<double>::PopValueFromReader(MessageReader* reader) {
454   return reader->PopVariantOfDouble(&value_);
455 }
456 
457 template <>
AppendSetValueToWriter(MessageWriter * writer)458 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
459   writer->AppendVariantOfDouble(set_value_);
460 }
461 
462 //
463 // Property<std::string> specialization.
464 //
465 
466 template <>
PopValueFromReader(MessageReader * reader)467 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
468   return reader->PopVariantOfString(&value_);
469 }
470 
471 template <>
AppendSetValueToWriter(MessageWriter * writer)472 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
473   writer->AppendVariantOfString(set_value_);
474 }
475 
476 //
477 // Property<ObjectPath> specialization.
478 //
479 
480 template <>
PopValueFromReader(MessageReader * reader)481 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
482   return reader->PopVariantOfObjectPath(&value_);
483 }
484 
485 template <>
AppendSetValueToWriter(MessageWriter * writer)486 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
487   writer->AppendVariantOfObjectPath(set_value_);
488 }
489 
490 //
491 // Property<std::vector<std::string>> specialization.
492 //
493 
494 template <>
PopValueFromReader(MessageReader * reader)495 bool Property<std::vector<std::string>>::PopValueFromReader(
496     MessageReader* reader) {
497   MessageReader variant_reader(nullptr);
498   if (!reader->PopVariant(&variant_reader))
499     return false;
500 
501   value_.clear();
502   return variant_reader.PopArrayOfStrings(&value_);
503 }
504 
505 template <>
AppendSetValueToWriter(MessageWriter * writer)506 void Property<std::vector<std::string>>::AppendSetValueToWriter(
507     MessageWriter* writer) {
508   MessageWriter variant_writer(nullptr);
509   writer->OpenVariant("as", &variant_writer);
510   variant_writer.AppendArrayOfStrings(set_value_);
511   writer->CloseContainer(&variant_writer);
512 }
513 
514 //
515 // Property<std::vector<ObjectPath>> specialization.
516 //
517 
518 template <>
PopValueFromReader(MessageReader * reader)519 bool Property<std::vector<ObjectPath>>::PopValueFromReader(
520     MessageReader* reader) {
521   MessageReader variant_reader(nullptr);
522   if (!reader->PopVariant(&variant_reader))
523     return false;
524 
525   value_.clear();
526   return variant_reader.PopArrayOfObjectPaths(&value_);
527 }
528 
529 template <>
AppendSetValueToWriter(MessageWriter * writer)530 void Property<std::vector<ObjectPath>>::AppendSetValueToWriter(
531     MessageWriter* writer) {
532   MessageWriter variant_writer(nullptr);
533   writer->OpenVariant("ao", &variant_writer);
534   variant_writer.AppendArrayOfObjectPaths(set_value_);
535   writer->CloseContainer(&variant_writer);
536 }
537 
538 //
539 // Property<std::vector<uint8_t>> specialization.
540 //
541 
542 template <>
PopValueFromReader(MessageReader * reader)543 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
544   MessageReader variant_reader(nullptr);
545   if (!reader->PopVariant(&variant_reader))
546     return false;
547 
548   value_.clear();
549   const uint8_t* bytes = nullptr;
550   size_t length = 0;
551   if (!variant_reader.PopArrayOfBytes(&bytes, &length))
552     return false;
553   value_.assign(bytes, bytes + length);
554   return true;
555 }
556 
557 template <>
AppendSetValueToWriter(MessageWriter * writer)558 void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
559     MessageWriter* writer) {
560   MessageWriter variant_writer(nullptr);
561   writer->OpenVariant("ay", &variant_writer);
562   variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
563   writer->CloseContainer(&variant_writer);
564 }
565 
566 //
567 // Property<std::map<std::string, std::string>> specialization.
568 //
569 
570 template <>
PopValueFromReader(MessageReader * reader)571 bool Property<std::map<std::string, std::string>>::PopValueFromReader(
572     MessageReader* reader) {
573   MessageReader variant_reader(nullptr);
574   MessageReader array_reader(nullptr);
575   if (!reader->PopVariant(&variant_reader) ||
576       !variant_reader.PopArray(&array_reader))
577     return false;
578   value_.clear();
579   while (array_reader.HasMoreData()) {
580     dbus::MessageReader dict_entry_reader(nullptr);
581     if (!array_reader.PopDictEntry(&dict_entry_reader))
582       return false;
583     std::string key;
584     std::string value;
585     if (!dict_entry_reader.PopString(&key) ||
586         !dict_entry_reader.PopString(&value))
587       return false;
588     value_[key] = value;
589   }
590   return true;
591 }
592 
593 template <>
AppendSetValueToWriter(MessageWriter * writer)594 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
595     MessageWriter* writer) {
596   MessageWriter variant_writer(nullptr);
597   MessageWriter dict_writer(nullptr);
598   writer->OpenVariant("a{ss}", &variant_writer);
599   variant_writer.OpenArray("{ss}", &dict_writer);
600   for (const auto& pair : set_value_) {
601     dbus::MessageWriter entry_writer(nullptr);
602     dict_writer.OpenDictEntry(&entry_writer);
603     entry_writer.AppendString(pair.first);
604     entry_writer.AppendString(pair.second);
605     dict_writer.CloseContainer(&entry_writer);
606   }
607   variant_writer.CloseContainer(&dict_writer);
608   writer->CloseContainer(&variant_writer);
609 }
610 
611 //
612 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
613 // specialization.
614 //
615 
616 template <>
617 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
PopValueFromReader(MessageReader * reader)618     PopValueFromReader(MessageReader* reader) {
619   MessageReader variant_reader(nullptr);
620   MessageReader array_reader(nullptr);
621   if (!reader->PopVariant(&variant_reader) ||
622       !variant_reader.PopArray(&array_reader))
623     return false;
624 
625   value_.clear();
626   while (array_reader.HasMoreData()) {
627     dbus::MessageReader struct_reader(nullptr);
628     if (!array_reader.PopStruct(&struct_reader))
629       return false;
630 
631     std::pair<std::vector<uint8_t>, uint16_t> entry;
632     const uint8_t* bytes = nullptr;
633     size_t length = 0;
634     if (!struct_reader.PopArrayOfBytes(&bytes, &length))
635       return false;
636     entry.first.assign(bytes, bytes + length);
637     if (!struct_reader.PopUint16(&entry.second))
638       return false;
639     value_.push_back(entry);
640   }
641   return true;
642 }
643 
644 template <>
645 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
AppendSetValueToWriter(MessageWriter * writer)646     AppendSetValueToWriter(MessageWriter* writer) {
647   MessageWriter variant_writer(nullptr);
648   MessageWriter array_writer(nullptr);
649   writer->OpenVariant("a(ayq)", &variant_writer);
650   variant_writer.OpenArray("(ayq)", &array_writer);
651   for (const auto& pair : set_value_) {
652     dbus::MessageWriter struct_writer(nullptr);
653     array_writer.OpenStruct(&struct_writer);
654     struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
655                                      std::get<0>(pair).size());
656     struct_writer.AppendUint16(std::get<1>(pair));
657     array_writer.CloseContainer(&struct_writer);
658   }
659   variant_writer.CloseContainer(&array_writer);
660   writer->CloseContainer(&variant_writer);
661 }
662 
663 //
664 // Property<std::map<std::string, std::vector<uint8_t>>>
665 // specialization.
666 //
667 
668 template <>
PopValueFromReader(MessageReader * reader)669 bool Property<std::map<std::string, std::vector<uint8_t>>>::PopValueFromReader(
670     MessageReader* reader) {
671   MessageReader variant_reader(nullptr);
672   MessageReader dict_reader(nullptr);
673   if (!reader->PopVariant(&variant_reader) ||
674       !variant_reader.PopArray(&dict_reader))
675     return false;
676 
677   value_.clear();
678   while (dict_reader.HasMoreData()) {
679     MessageReader entry_reader(nullptr);
680     if (!dict_reader.PopDictEntry(&entry_reader))
681       return false;
682 
683     std::string key;
684     MessageReader value_varient_reader(nullptr);
685     if (!entry_reader.PopString(&key) ||
686         !entry_reader.PopVariant(&value_varient_reader))
687       return false;
688 
689     const uint8_t* bytes = nullptr;
690     size_t length = 0;
691     if (!value_varient_reader.PopArrayOfBytes(&bytes, &length))
692       return false;
693 
694     value_[key].assign(bytes, bytes + length);
695   }
696   return true;
697 }
698 
699 template <>
700 void Property<std::map<std::string, std::vector<uint8_t>>>::
AppendSetValueToWriter(MessageWriter * writer)701     AppendSetValueToWriter(MessageWriter* writer) {
702   MessageWriter variant_writer(nullptr);
703   MessageWriter dict_writer(nullptr);
704 
705   writer->OpenVariant("a{sv}", &variant_writer);
706   variant_writer.OpenArray("{sv}", &dict_writer);
707 
708   for (const auto& pair : set_value_) {
709     MessageWriter entry_writer(nullptr);
710     dict_writer.OpenDictEntry(&entry_writer);
711 
712     entry_writer.AppendString(pair.first);
713 
714     MessageWriter value_varient_writer(nullptr);
715     entry_writer.OpenVariant("ay", &value_varient_writer);
716     value_varient_writer.AppendArrayOfBytes(pair.second.data(),
717                                             pair.second.size());
718     entry_writer.CloseContainer(&value_varient_writer);
719 
720     dict_writer.CloseContainer(&entry_writer);
721   }
722 
723   variant_writer.CloseContainer(&dict_writer);
724   writer->CloseContainer(&variant_writer);
725 }
726 
727 //
728 // Property<std::map<uint16_t, std::vector<uint8_t>>>
729 // specialization.
730 //
731 
732 template <>
PopValueFromReader(MessageReader * reader)733 bool Property<std::map<uint16_t, std::vector<uint8_t>>>::PopValueFromReader(
734     MessageReader* reader) {
735   MessageReader variant_reader(nullptr);
736   MessageReader dict_reader(nullptr);
737   if (!reader->PopVariant(&variant_reader) ||
738       !variant_reader.PopArray(&dict_reader))
739     return false;
740 
741   value_.clear();
742   while (dict_reader.HasMoreData()) {
743     MessageReader entry_reader(nullptr);
744     if (!dict_reader.PopDictEntry(&entry_reader))
745       return false;
746 
747     uint16_t key;
748     MessageReader value_varient_reader(nullptr);
749     if (!entry_reader.PopUint16(&key) ||
750         !entry_reader.PopVariant(&value_varient_reader))
751       return false;
752 
753     const uint8_t* bytes = nullptr;
754     size_t length = 0;
755     if (!value_varient_reader.PopArrayOfBytes(&bytes, &length))
756       return false;
757 
758     value_[key].assign(bytes, bytes + length);
759   }
760   return true;
761 }
762 
763 template <>
AppendSetValueToWriter(MessageWriter * writer)764 void Property<std::map<uint16_t, std::vector<uint8_t>>>::AppendSetValueToWriter(
765     MessageWriter* writer) {
766   MessageWriter variant_writer(nullptr);
767   MessageWriter dict_writer(nullptr);
768 
769   writer->OpenVariant("a{qv}", &variant_writer);
770   variant_writer.OpenArray("{qv}", &dict_writer);
771 
772   for (const auto& pair : set_value_) {
773     MessageWriter entry_writer(nullptr);
774     dict_writer.OpenDictEntry(&entry_writer);
775 
776     entry_writer.AppendUint16(pair.first);
777 
778     MessageWriter value_varient_writer(nullptr);
779     entry_writer.OpenVariant("ay", &value_varient_writer);
780     value_varient_writer.AppendArrayOfBytes(pair.second.data(),
781                                             pair.second.size());
782     entry_writer.CloseContainer(&value_varient_writer);
783 
784     dict_writer.CloseContainer(&entry_writer);
785   }
786 
787   variant_writer.CloseContainer(&dict_writer);
788   writer->CloseContainer(&variant_writer);
789 }
790 
791 template class Property<uint8_t>;
792 template class Property<bool>;
793 template class Property<int16_t>;
794 template class Property<uint16_t>;
795 template class Property<int32_t>;
796 template class Property<uint32_t>;
797 template class Property<int64_t>;
798 template class Property<uint64_t>;
799 template class Property<double>;
800 template class Property<std::string>;
801 template class Property<ObjectPath>;
802 template class Property<std::vector<std::string>>;
803 template class Property<std::vector<ObjectPath>>;
804 template class Property<std::vector<uint8_t>>;
805 template class Property<std::map<std::string, std::string>>;
806 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
807 template class Property<std::map<std::string, std::vector<uint8_t>>>;
808 template class Property<std::map<uint16_t, std::vector<uint8_t>>>;
809 
810 }  // namespace dbus
811