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