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 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 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 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 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 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 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 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 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 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 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 <> 304 Property<uint8_t>::Property() 305 : value_(0) {} 306 307 template <> 308 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) { 309 return reader->PopVariantOfByte(&value_); 310 } 311 312 template <> 313 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) { 314 writer->AppendVariantOfByte(set_value_); 315 } 316 317 // 318 // Property<bool> specialization. 319 // 320 321 template <> 322 Property<bool>::Property() : value_(false) { 323 } 324 325 template <> 326 bool Property<bool>::PopValueFromReader(MessageReader* reader) { 327 return reader->PopVariantOfBool(&value_); 328 } 329 330 template <> 331 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) { 332 writer->AppendVariantOfBool(set_value_); 333 } 334 335 // 336 // Property<int16_t> specialization. 337 // 338 339 template <> 340 Property<int16_t>::Property() 341 : value_(0) {} 342 343 template <> 344 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) { 345 return reader->PopVariantOfInt16(&value_); 346 } 347 348 template <> 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 <> 358 Property<uint16_t>::Property() 359 : value_(0) {} 360 361 template <> 362 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) { 363 return reader->PopVariantOfUint16(&value_); 364 } 365 366 template <> 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 <> 376 Property<int32_t>::Property() 377 : value_(0) {} 378 379 template <> 380 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) { 381 return reader->PopVariantOfInt32(&value_); 382 } 383 384 template <> 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 <> 394 Property<uint32_t>::Property() 395 : value_(0) {} 396 397 template <> 398 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) { 399 return reader->PopVariantOfUint32(&value_); 400 } 401 402 template <> 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 <> 412 Property<int64_t>::Property() 413 : value_(0), set_value_(0) {} 414 415 template <> 416 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) { 417 return reader->PopVariantOfInt64(&value_); 418 } 419 420 template <> 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 <> 430 Property<uint64_t>::Property() 431 : value_(0) {} 432 433 template <> 434 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) { 435 return reader->PopVariantOfUint64(&value_); 436 } 437 438 template <> 439 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) { 440 writer->AppendVariantOfUint64(set_value_); 441 } 442 443 // 444 // Property<double> specialization. 445 // 446 447 template <> 448 Property<double>::Property() : value_(0.0) { 449 } 450 451 template <> 452 bool Property<double>::PopValueFromReader(MessageReader* reader) { 453 return reader->PopVariantOfDouble(&value_); 454 } 455 456 template <> 457 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) { 458 writer->AppendVariantOfDouble(set_value_); 459 } 460 461 // 462 // Property<std::string> specialization. 463 // 464 465 template <> 466 bool Property<std::string>::PopValueFromReader(MessageReader* reader) { 467 return reader->PopVariantOfString(&value_); 468 } 469 470 template <> 471 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) { 472 writer->AppendVariantOfString(set_value_); 473 } 474 475 // 476 // Property<ObjectPath> specialization. 477 // 478 479 template <> 480 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) { 481 return reader->PopVariantOfObjectPath(&value_); 482 } 483 484 template <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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>>>:: 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>>>:: 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