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