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