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 22 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {} 23 24 PropertyBase::~PropertyBase() {} 25 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 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 46 PropertySet::~PropertySet() { 47 } 48 49 void PropertySet::RegisterProperty(const std::string& name, 50 PropertyBase* property) { 51 property->Init(this, name); 52 properties_map_[name] = property; 53 } 54 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 <> 306 Property<uint8_t>::Property() 307 : value_(0) {} 308 309 template <> 310 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) { 311 return reader->PopVariantOfByte(&value_); 312 } 313 314 template <> 315 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) { 316 writer->AppendVariantOfByte(set_value_); 317 } 318 319 // 320 // Property<bool> specialization. 321 // 322 323 template <> 324 Property<bool>::Property() : value_(false) { 325 } 326 327 template <> 328 bool Property<bool>::PopValueFromReader(MessageReader* reader) { 329 return reader->PopVariantOfBool(&value_); 330 } 331 332 template <> 333 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) { 334 writer->AppendVariantOfBool(set_value_); 335 } 336 337 // 338 // Property<int16_t> specialization. 339 // 340 341 template <> 342 Property<int16_t>::Property() 343 : value_(0) {} 344 345 template <> 346 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) { 347 return reader->PopVariantOfInt16(&value_); 348 } 349 350 template <> 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 <> 360 Property<uint16_t>::Property() 361 : value_(0) {} 362 363 template <> 364 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) { 365 return reader->PopVariantOfUint16(&value_); 366 } 367 368 template <> 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 <> 378 Property<int32_t>::Property() 379 : value_(0) {} 380 381 template <> 382 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) { 383 return reader->PopVariantOfInt32(&value_); 384 } 385 386 template <> 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 <> 396 Property<uint32_t>::Property() 397 : value_(0) {} 398 399 template <> 400 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) { 401 return reader->PopVariantOfUint32(&value_); 402 } 403 404 template <> 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 <> 414 Property<int64_t>::Property() 415 : value_(0), set_value_(0) {} 416 417 template <> 418 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) { 419 return reader->PopVariantOfInt64(&value_); 420 } 421 422 template <> 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 <> 432 Property<uint64_t>::Property() 433 : value_(0) {} 434 435 template <> 436 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) { 437 return reader->PopVariantOfUint64(&value_); 438 } 439 440 template <> 441 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) { 442 writer->AppendVariantOfUint64(set_value_); 443 } 444 445 // 446 // Property<double> specialization. 447 // 448 449 template <> 450 Property<double>::Property() : value_(0.0) { 451 } 452 453 template <> 454 bool Property<double>::PopValueFromReader(MessageReader* reader) { 455 return reader->PopVariantOfDouble(&value_); 456 } 457 458 template <> 459 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) { 460 writer->AppendVariantOfDouble(set_value_); 461 } 462 463 // 464 // Property<std::string> specialization. 465 // 466 467 template <> 468 bool Property<std::string>::PopValueFromReader(MessageReader* reader) { 469 return reader->PopVariantOfString(&value_); 470 } 471 472 template <> 473 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) { 474 writer->AppendVariantOfString(set_value_); 475 } 476 477 // 478 // Property<ObjectPath> specialization. 479 // 480 481 template <> 482 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) { 483 return reader->PopVariantOfObjectPath(&value_); 484 } 485 486 template <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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>>>:: 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>>>:: 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