• 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   scoped_ptr<dbus::Response> response(
145       object_proxy_->CallMethodAndBlock(&method_call,
146                                         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   scoped_ptr<dbus::Response> response(
216       object_proxy_->CallMethodAndBlock(&method_call,
217                                         ObjectProxy::TIMEOUT_USE_DEFAULT));
218   if (response.get())
219     return true;
220   return false;
221 }
222 
OnSet(PropertyBase * property,SetCallback callback,Response * response)223 void PropertySet::OnSet(PropertyBase* property,
224                         SetCallback callback,
225                         Response* response) {
226   LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
227   if (!callback.is_null())
228     callback.Run(response);
229 }
230 
UpdatePropertiesFromReader(MessageReader * reader)231 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
232   DCHECK(reader);
233   MessageReader array_reader(NULL);
234   if (!reader->PopArray(&array_reader))
235     return false;
236 
237   while (array_reader.HasMoreData()) {
238     MessageReader dict_entry_reader(NULL);
239     if (array_reader.PopDictEntry(&dict_entry_reader))
240       UpdatePropertyFromReader(&dict_entry_reader);
241   }
242 
243   return true;
244 }
245 
UpdatePropertyFromReader(MessageReader * reader)246 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
247   DCHECK(reader);
248 
249   std::string name;
250   if (!reader->PopString(&name))
251     return false;
252 
253   PropertiesMap::iterator it = properties_map_.find(name);
254   if (it == properties_map_.end())
255     return false;
256 
257   PropertyBase* property = it->second;
258   if (property->PopValueFromReader(reader)) {
259     property->set_valid(true);
260     NotifyPropertyChanged(name);
261     return true;
262   } else {
263     if (property->is_valid()) {
264       property->set_valid(false);
265       NotifyPropertyChanged(property->name());
266     }
267     return false;
268   }
269 }
270 
InvalidatePropertiesFromReader(MessageReader * reader)271 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
272   DCHECK(reader);
273   MessageReader array_reader(NULL);
274   if (!reader->PopArray(&array_reader))
275     return false;
276 
277   while (array_reader.HasMoreData()) {
278     std::string name;
279     if (!array_reader.PopString(&name))
280       return false;
281 
282     PropertiesMap::iterator it = properties_map_.find(name);
283     if (it == properties_map_.end())
284       continue;
285 
286     PropertyBase* property = it->second;
287     if (property->is_valid()) {
288       property->set_valid(false);
289       NotifyPropertyChanged(property->name());
290     }
291   }
292 
293   return true;
294 }
295 
NotifyPropertyChanged(const std::string & name)296 void PropertySet::NotifyPropertyChanged(const std::string& name) {
297   if (!property_changed_callback_.is_null())
298     property_changed_callback_.Run(name);
299 }
300 
301 //
302 // Property<Byte> specialization.
303 //
304 
305 template <>
Property()306 Property<uint8_t>::Property()
307     : value_(0) {}
308 
309 template <>
PopValueFromReader(MessageReader * reader)310 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
311   return reader->PopVariantOfByte(&value_);
312 }
313 
314 template <>
AppendSetValueToWriter(MessageWriter * writer)315 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
316   writer->AppendVariantOfByte(set_value_);
317 }
318 
319 //
320 // Property<bool> specialization.
321 //
322 
323 template <>
Property()324 Property<bool>::Property() : value_(false) {
325 }
326 
327 template <>
PopValueFromReader(MessageReader * reader)328 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
329   return reader->PopVariantOfBool(&value_);
330 }
331 
332 template <>
AppendSetValueToWriter(MessageWriter * writer)333 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
334   writer->AppendVariantOfBool(set_value_);
335 }
336 
337 //
338 // Property<int16_t> specialization.
339 //
340 
341 template <>
Property()342 Property<int16_t>::Property()
343     : value_(0) {}
344 
345 template <>
PopValueFromReader(MessageReader * reader)346 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
347   return reader->PopVariantOfInt16(&value_);
348 }
349 
350 template <>
AppendSetValueToWriter(MessageWriter * writer)351 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
352   writer->AppendVariantOfInt16(set_value_);
353 }
354 
355 //
356 // Property<uint16_t> specialization.
357 //
358 
359 template <>
Property()360 Property<uint16_t>::Property()
361     : value_(0) {}
362 
363 template <>
PopValueFromReader(MessageReader * reader)364 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
365   return reader->PopVariantOfUint16(&value_);
366 }
367 
368 template <>
AppendSetValueToWriter(MessageWriter * writer)369 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
370   writer->AppendVariantOfUint16(set_value_);
371 }
372 
373 //
374 // Property<int32_t> specialization.
375 //
376 
377 template <>
Property()378 Property<int32_t>::Property()
379     : value_(0) {}
380 
381 template <>
PopValueFromReader(MessageReader * reader)382 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
383   return reader->PopVariantOfInt32(&value_);
384 }
385 
386 template <>
AppendSetValueToWriter(MessageWriter * writer)387 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
388   writer->AppendVariantOfInt32(set_value_);
389 }
390 
391 //
392 // Property<uint32_t> specialization.
393 //
394 
395 template <>
Property()396 Property<uint32_t>::Property()
397     : value_(0) {}
398 
399 template <>
PopValueFromReader(MessageReader * reader)400 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
401   return reader->PopVariantOfUint32(&value_);
402 }
403 
404 template <>
AppendSetValueToWriter(MessageWriter * writer)405 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
406   writer->AppendVariantOfUint32(set_value_);
407 }
408 
409 //
410 // Property<int64_t> specialization.
411 //
412 
413 template <>
Property()414 Property<int64_t>::Property()
415     : value_(0), set_value_(0) {}
416 
417 template <>
PopValueFromReader(MessageReader * reader)418 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
419   return reader->PopVariantOfInt64(&value_);
420 }
421 
422 template <>
AppendSetValueToWriter(MessageWriter * writer)423 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
424   writer->AppendVariantOfInt64(set_value_);
425 }
426 
427 //
428 // Property<uint64_t> specialization.
429 //
430 
431 template <>
Property()432 Property<uint64_t>::Property()
433     : value_(0) {}
434 
435 template <>
PopValueFromReader(MessageReader * reader)436 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
437   return reader->PopVariantOfUint64(&value_);
438 }
439 
440 template <>
AppendSetValueToWriter(MessageWriter * writer)441 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
442   writer->AppendVariantOfUint64(set_value_);
443 }
444 
445 //
446 // Property<double> specialization.
447 //
448 
449 template <>
Property()450 Property<double>::Property() : value_(0.0) {
451 }
452 
453 template <>
PopValueFromReader(MessageReader * reader)454 bool Property<double>::PopValueFromReader(MessageReader* reader) {
455   return reader->PopVariantOfDouble(&value_);
456 }
457 
458 template <>
AppendSetValueToWriter(MessageWriter * writer)459 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
460   writer->AppendVariantOfDouble(set_value_);
461 }
462 
463 //
464 // Property<std::string> specialization.
465 //
466 
467 template <>
PopValueFromReader(MessageReader * reader)468 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
469   return reader->PopVariantOfString(&value_);
470 }
471 
472 template <>
AppendSetValueToWriter(MessageWriter * writer)473 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
474   writer->AppendVariantOfString(set_value_);
475 }
476 
477 //
478 // Property<ObjectPath> specialization.
479 //
480 
481 template <>
PopValueFromReader(MessageReader * reader)482 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
483   return reader->PopVariantOfObjectPath(&value_);
484 }
485 
486 template <>
AppendSetValueToWriter(MessageWriter * writer)487 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
488   writer->AppendVariantOfObjectPath(set_value_);
489 }
490 
491 //
492 // Property<std::vector<std::string> > specialization.
493 //
494 
495 template <>
PopValueFromReader(MessageReader * reader)496 bool Property<std::vector<std::string> >::PopValueFromReader(
497     MessageReader* reader) {
498   MessageReader variant_reader(NULL);
499   if (!reader->PopVariant(&variant_reader))
500     return false;
501 
502   value_.clear();
503   return variant_reader.PopArrayOfStrings(&value_);
504 }
505 
506 template <>
AppendSetValueToWriter(MessageWriter * writer)507 void Property<std::vector<std::string> >::AppendSetValueToWriter(
508     MessageWriter* writer) {
509   MessageWriter variant_writer(NULL);
510   writer->OpenVariant("as", &variant_writer);
511   variant_writer.AppendArrayOfStrings(set_value_);
512   writer->CloseContainer(&variant_writer);
513 }
514 
515 //
516 // Property<std::vector<ObjectPath> > specialization.
517 //
518 
519 template <>
PopValueFromReader(MessageReader * reader)520 bool Property<std::vector<ObjectPath> >::PopValueFromReader(
521     MessageReader* reader) {
522   MessageReader variant_reader(NULL);
523   if (!reader->PopVariant(&variant_reader))
524     return false;
525 
526   value_.clear();
527   return variant_reader.PopArrayOfObjectPaths(&value_);
528 }
529 
530 template <>
AppendSetValueToWriter(MessageWriter * writer)531 void Property<std::vector<ObjectPath> >::AppendSetValueToWriter(
532     MessageWriter* writer) {
533   MessageWriter variant_writer(NULL);
534   writer->OpenVariant("ao", &variant_writer);
535   variant_writer.AppendArrayOfObjectPaths(set_value_);
536   writer->CloseContainer(&variant_writer);
537 }
538 
539 //
540 // Property<std::vector<uint8_t> > specialization.
541 //
542 
543 template <>
PopValueFromReader(MessageReader * reader)544 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
545   MessageReader variant_reader(NULL);
546   if (!reader->PopVariant(&variant_reader))
547     return false;
548 
549   value_.clear();
550   const uint8_t* bytes = NULL;
551   size_t length = 0;
552   if (!variant_reader.PopArrayOfBytes(&bytes, &length))
553     return false;
554   value_.assign(bytes, bytes + length);
555   return true;
556 }
557 
558 template <>
AppendSetValueToWriter(MessageWriter * writer)559 void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
560     MessageWriter* writer) {
561   MessageWriter variant_writer(NULL);
562   writer->OpenVariant("ay", &variant_writer);
563   variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
564   writer->CloseContainer(&variant_writer);
565 }
566 
567 //
568 // Property<std::map<std::string, std::string>> specialization.
569 //
570 
571 template <>
PopValueFromReader(MessageReader * reader)572 bool Property<std::map<std::string, std::string>>::PopValueFromReader(
573     MessageReader* reader) {
574   MessageReader variant_reader(NULL);
575   MessageReader array_reader(NULL);
576   if (!reader->PopVariant(&variant_reader) ||
577       !variant_reader.PopArray(&array_reader))
578     return false;
579   value_.clear();
580   while (array_reader.HasMoreData()) {
581     dbus::MessageReader dict_entry_reader(NULL);
582     if (!array_reader.PopDictEntry(&dict_entry_reader))
583       return false;
584     std::string key;
585     std::string value;
586     if (!dict_entry_reader.PopString(&key) ||
587         !dict_entry_reader.PopString(&value))
588       return false;
589     value_[key] = value;
590   }
591   return true;
592 }
593 
594 template <>
AppendSetValueToWriter(MessageWriter * writer)595 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
596     MessageWriter* writer) {
597   MessageWriter variant_writer(NULL);
598   MessageWriter dict_writer(NULL);
599   writer->OpenVariant("a{ss}", &variant_writer);
600   variant_writer.OpenArray("{ss}", &dict_writer);
601   for (const auto& pair : set_value_) {
602     dbus::MessageWriter entry_writer(NULL);
603     dict_writer.OpenDictEntry(&entry_writer);
604     entry_writer.AppendString(pair.first);
605     entry_writer.AppendString(pair.second);
606     dict_writer.CloseContainer(&entry_writer);
607   }
608   variant_writer.CloseContainer(&dict_writer);
609   writer->CloseContainer(&variant_writer);
610 }
611 
612 //
613 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
614 // specialization.
615 //
616 
617 template <>
618 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
PopValueFromReader(MessageReader * reader)619     PopValueFromReader(MessageReader* reader) {
620   MessageReader variant_reader(NULL);
621   MessageReader array_reader(NULL);
622   if (!reader->PopVariant(&variant_reader) ||
623       !variant_reader.PopArray(&array_reader))
624     return false;
625 
626   value_.clear();
627   while (array_reader.HasMoreData()) {
628     dbus::MessageReader struct_reader(NULL);
629     if (!array_reader.PopStruct(&struct_reader))
630       return false;
631 
632     std::pair<std::vector<uint8_t>, uint16_t> entry;
633     const uint8_t* bytes = NULL;
634     size_t length = 0;
635     if (!struct_reader.PopArrayOfBytes(&bytes, &length))
636       return false;
637     entry.first.assign(bytes, bytes + length);
638     if (!struct_reader.PopUint16(&entry.second))
639       return false;
640     value_.push_back(entry);
641   }
642   return true;
643 }
644 
645 template <>
646 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
AppendSetValueToWriter(MessageWriter * writer)647     AppendSetValueToWriter(MessageWriter* writer) {
648   MessageWriter variant_writer(NULL);
649   MessageWriter array_writer(NULL);
650   writer->OpenVariant("a(ayq)", &variant_writer);
651   variant_writer.OpenArray("(ayq)", &array_writer);
652   for (const auto& pair : set_value_) {
653     dbus::MessageWriter struct_writer(nullptr);
654     array_writer.OpenStruct(&struct_writer);
655     struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
656                                      std::get<0>(pair).size());
657     struct_writer.AppendUint16(std::get<1>(pair));
658     array_writer.CloseContainer(&struct_writer);
659   }
660   variant_writer.CloseContainer(&array_writer);
661   writer->CloseContainer(&variant_writer);
662 }
663 
664 template class Property<uint8_t>;
665 template class Property<bool>;
666 template class Property<int16_t>;
667 template class Property<uint16_t>;
668 template class Property<int32_t>;
669 template class Property<uint32_t>;
670 template class Property<int64_t>;
671 template class Property<uint64_t>;
672 template class Property<double>;
673 template class Property<std::string>;
674 template class Property<ObjectPath>;
675 template class Property<std::vector<std::string> >;
676 template class Property<std::vector<ObjectPath> >;
677 template class Property<std::vector<uint8_t>>;
678 template class Property<std::map<std::string, std::string>>;
679 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
680 
681 }  // namespace dbus
682