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 "base/basictypes.h" 8#include "base/bind.h" 9#include "base/logging.h" 10 11#include "dbus/message.h" 12#include "dbus/object_path.h" 13#include "dbus/object_proxy.h" 14 15namespace dbus { 16 17// 18// PropertyBase implementation. 19// 20 21void PropertyBase::Init(PropertySet* property_set, const std::string& name) { 22 DCHECK(!property_set_); 23 property_set_ = property_set; 24 name_ = name; 25} 26 27 28// 29// PropertySet implementation. 30// 31 32PropertySet::PropertySet( 33 ObjectProxy* object_proxy, 34 const std::string& interface, 35 const PropertyChangedCallback& property_changed_callback) 36 : object_proxy_(object_proxy), 37 interface_(interface), 38 property_changed_callback_(property_changed_callback), 39 weak_ptr_factory_(this) {} 40 41PropertySet::~PropertySet() { 42} 43 44void PropertySet::RegisterProperty(const std::string& name, 45 PropertyBase* property) { 46 property->Init(this, name); 47 properties_map_[name] = property; 48} 49 50void PropertySet::ConnectSignals() { 51 DCHECK(object_proxy_); 52 object_proxy_->ConnectToSignal( 53 kPropertiesInterface, 54 kPropertiesChanged, 55 base::Bind(&PropertySet::ChangedReceived, 56 weak_ptr_factory_.GetWeakPtr()), 57 base::Bind(&PropertySet::ChangedConnected, 58 weak_ptr_factory_.GetWeakPtr())); 59} 60 61 62void PropertySet::ChangedReceived(Signal* signal) { 63 DCHECK(signal); 64 MessageReader reader(signal); 65 66 std::string interface; 67 if (!reader.PopString(&interface)) { 68 LOG(WARNING) << "Property changed signal has wrong parameters: " 69 << "expected interface name: " << signal->ToString(); 70 return; 71 } 72 73 if (interface != this->interface()) 74 return; 75 76 if (!UpdatePropertiesFromReader(&reader)) { 77 LOG(WARNING) << "Property changed signal has wrong parameters: " 78 << "expected dictionary: " << signal->ToString(); 79 } 80 81 // TODO(keybuk): dbus properties api has invalidated properties array 82 // on the end, we don't handle this right now because I don't know of 83 // any service that sends it - or what they expect us to do with it. 84 // Add later when we need it. 85} 86 87void PropertySet::ChangedConnected(const std::string& interface_name, 88 const std::string& signal_name, 89 bool success) { 90 LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name 91 << "signal."; 92} 93 94 95void PropertySet::Get(PropertyBase* property, GetCallback callback) { 96 MethodCall method_call(kPropertiesInterface, kPropertiesGet); 97 MessageWriter writer(&method_call); 98 writer.AppendString(interface()); 99 writer.AppendString(property->name()); 100 101 DCHECK(object_proxy_); 102 object_proxy_->CallMethod(&method_call, 103 ObjectProxy::TIMEOUT_USE_DEFAULT, 104 base::Bind(&PropertySet::OnGet, 105 GetWeakPtr(), 106 property, 107 callback)); 108} 109 110void PropertySet::OnGet(PropertyBase* property, GetCallback callback, 111 Response* response) { 112 if (!response) { 113 LOG(WARNING) << property->name() << ": Get: failed."; 114 return; 115 } 116 117 MessageReader reader(response); 118 if (property->PopValueFromReader(&reader)) 119 NotifyPropertyChanged(property->name()); 120 121 if (!callback.is_null()) 122 callback.Run(response); 123} 124 125void PropertySet::GetAll() { 126 MethodCall method_call(kPropertiesInterface, kPropertiesGetAll); 127 MessageWriter writer(&method_call); 128 writer.AppendString(interface()); 129 130 DCHECK(object_proxy_); 131 object_proxy_->CallMethod(&method_call, 132 ObjectProxy::TIMEOUT_USE_DEFAULT, 133 base::Bind(&PropertySet::OnGetAll, 134 weak_ptr_factory_.GetWeakPtr())); 135} 136 137void PropertySet::OnGetAll(Response* response) { 138 if (!response) { 139 LOG(WARNING) << "GetAll request failed for: " << interface_; 140 return; 141 } 142 143 MessageReader reader(response); 144 if (!UpdatePropertiesFromReader(&reader)) { 145 LOG(WARNING) << "GetAll response has wrong parameters: " 146 << "expected dictionary: " << response->ToString(); 147 } 148} 149 150void PropertySet::Set(PropertyBase* property, SetCallback callback) { 151 MethodCall method_call(kPropertiesInterface, kPropertiesSet); 152 MessageWriter writer(&method_call); 153 writer.AppendString(interface()); 154 writer.AppendString(property->name()); 155 property->AppendSetValueToWriter(&writer); 156 157 DCHECK(object_proxy_); 158 object_proxy_->CallMethod(&method_call, 159 ObjectProxy::TIMEOUT_USE_DEFAULT, 160 base::Bind(&PropertySet::OnSet, 161 GetWeakPtr(), 162 property, 163 callback)); 164} 165 166void PropertySet::OnSet(PropertyBase* property, 167 SetCallback callback, 168 Response* response) { 169 LOG_IF(WARNING, !response) << property->name() << ": Set: failed."; 170 if (!callback.is_null()) 171 callback.Run(response); 172} 173 174bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) { 175 DCHECK(reader); 176 MessageReader array_reader(NULL); 177 if (!reader->PopArray(&array_reader)) 178 return false; 179 180 while (array_reader.HasMoreData()) { 181 MessageReader dict_entry_reader(NULL); 182 if (array_reader.PopDictEntry(&dict_entry_reader)) 183 UpdatePropertyFromReader(&dict_entry_reader); 184 } 185 186 return true; 187} 188 189bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) { 190 DCHECK(reader); 191 192 std::string name; 193 if (!reader->PopString(&name)) 194 return false; 195 196 PropertiesMap::iterator it = properties_map_.find(name); 197 if (it == properties_map_.end()) 198 return false; 199 200 PropertyBase* property = it->second; 201 if (property->PopValueFromReader(reader)) { 202 NotifyPropertyChanged(name); 203 return true; 204 } else { 205 return false; 206 } 207} 208 209 210void PropertySet::NotifyPropertyChanged(const std::string& name) { 211 if (!property_changed_callback_.is_null()) 212 property_changed_callback_.Run(name); 213} 214 215// 216// Property<Byte> specialization. 217// 218 219template <> 220Property<uint8>::Property() : value_(0) { 221} 222 223template <> 224bool Property<uint8>::PopValueFromReader(MessageReader* reader) { 225 return reader->PopVariantOfByte(&value_); 226} 227 228template <> 229void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) { 230 writer->AppendVariantOfByte(set_value_); 231} 232 233// 234// Property<bool> specialization. 235// 236 237template <> 238Property<bool>::Property() : value_(false) { 239} 240 241template <> 242bool Property<bool>::PopValueFromReader(MessageReader* reader) { 243 return reader->PopVariantOfBool(&value_); 244} 245 246template <> 247void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) { 248 writer->AppendVariantOfBool(set_value_); 249} 250 251// 252// Property<int16> specialization. 253// 254 255template <> 256Property<int16>::Property() : value_(0) { 257} 258 259template <> 260bool Property<int16>::PopValueFromReader(MessageReader* reader) { 261 return reader->PopVariantOfInt16(&value_); 262} 263 264template <> 265void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) { 266 writer->AppendVariantOfInt16(set_value_); 267} 268 269// 270// Property<uint16> specialization. 271// 272 273template <> 274Property<uint16>::Property() : value_(0) { 275} 276 277template <> 278bool Property<uint16>::PopValueFromReader(MessageReader* reader) { 279 return reader->PopVariantOfUint16(&value_); 280} 281 282template <> 283void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) { 284 writer->AppendVariantOfUint16(set_value_); 285} 286 287// 288// Property<int32> specialization. 289// 290 291template <> 292Property<int32>::Property() : value_(0) { 293} 294 295template <> 296bool Property<int32>::PopValueFromReader(MessageReader* reader) { 297 return reader->PopVariantOfInt32(&value_); 298} 299 300template <> 301void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) { 302 writer->AppendVariantOfInt32(set_value_); 303} 304 305// 306// Property<uint32> specialization. 307// 308 309template <> 310Property<uint32>::Property() : value_(0) { 311} 312 313template <> 314bool Property<uint32>::PopValueFromReader(MessageReader* reader) { 315 return reader->PopVariantOfUint32(&value_); 316} 317 318template <> 319void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) { 320 writer->AppendVariantOfUint32(set_value_); 321} 322 323// 324// Property<int64> specialization. 325// 326 327template <> 328Property<int64>::Property() : value_(0), set_value_(0) { 329} 330 331template <> 332bool Property<int64>::PopValueFromReader(MessageReader* reader) { 333 return reader->PopVariantOfInt64(&value_); 334} 335 336template <> 337void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) { 338 writer->AppendVariantOfInt64(set_value_); 339} 340 341// 342// Property<uint64> specialization. 343// 344 345template <> 346Property<uint64>::Property() : value_(0) { 347} 348 349template <> 350bool Property<uint64>::PopValueFromReader(MessageReader* reader) { 351 return reader->PopVariantOfUint64(&value_); 352} 353 354template <> 355void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) { 356 writer->AppendVariantOfUint64(set_value_); 357} 358 359// 360// Property<double> specialization. 361// 362 363template <> 364Property<double>::Property() : value_(0.0) { 365} 366 367template <> 368bool Property<double>::PopValueFromReader(MessageReader* reader) { 369 return reader->PopVariantOfDouble(&value_); 370} 371 372template <> 373void Property<double>::AppendSetValueToWriter(MessageWriter* writer) { 374 writer->AppendVariantOfDouble(set_value_); 375} 376 377// 378// Property<std::string> specialization. 379// 380 381template <> 382bool Property<std::string>::PopValueFromReader(MessageReader* reader) { 383 return reader->PopVariantOfString(&value_); 384} 385 386template <> 387void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) { 388 writer->AppendVariantOfString(set_value_); 389} 390 391// 392// Property<ObjectPath> specialization. 393// 394 395template <> 396bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) { 397 return reader->PopVariantOfObjectPath(&value_); 398} 399 400template <> 401void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) { 402 writer->AppendVariantOfObjectPath(set_value_); 403} 404 405// 406// Property<std::vector<std::string> > specialization. 407// 408 409template <> 410bool Property<std::vector<std::string> >::PopValueFromReader( 411 MessageReader* reader) { 412 MessageReader variant_reader(NULL); 413 if (!reader->PopVariant(&variant_reader)) 414 return false; 415 416 value_.clear(); 417 return variant_reader.PopArrayOfStrings(&value_); 418} 419 420template <> 421void Property<std::vector<std::string> >::AppendSetValueToWriter( 422 MessageWriter* writer) { 423 MessageWriter variant_writer(NULL); 424 writer->OpenVariant("as", &variant_writer); 425 variant_writer.AppendArrayOfStrings(set_value_); 426 writer->CloseContainer(&variant_writer); 427} 428 429// 430// Property<std::vector<ObjectPath> > specialization. 431// 432 433template <> 434bool Property<std::vector<ObjectPath> >::PopValueFromReader( 435 MessageReader* reader) { 436 MessageReader variant_reader(NULL); 437 if (!reader->PopVariant(&variant_reader)) 438 return false; 439 440 value_.clear(); 441 return variant_reader.PopArrayOfObjectPaths(&value_); 442} 443 444template <> 445void Property<std::vector<ObjectPath> >::AppendSetValueToWriter( 446 MessageWriter* writer) { 447 MessageWriter variant_writer(NULL); 448 writer->OpenVariant("ao", &variant_writer); 449 variant_writer.AppendArrayOfObjectPaths(set_value_); 450 writer->CloseContainer(&variant_writer); 451} 452 453// 454// Property<std::vector<uint8> > specialization. 455// 456 457template <> 458bool Property<std::vector<uint8> >::PopValueFromReader(MessageReader* reader) { 459 MessageReader variant_reader(NULL); 460 if (!reader->PopVariant(&variant_reader)) 461 return false; 462 463 value_.clear(); 464 const uint8* bytes = NULL; 465 size_t length = 0; 466 if (!variant_reader.PopArrayOfBytes(&bytes, &length)) 467 return false; 468 value_.assign(bytes, bytes + length); 469 return true; 470} 471 472template <> 473void Property<std::vector<uint8> >::AppendSetValueToWriter( 474 MessageWriter* writer) { 475 MessageWriter variant_writer(NULL); 476 writer->OpenVariant("ay", &variant_writer); 477 variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size()); 478 writer->CloseContainer(&variant_writer); 479} 480 481template class Property<uint8>; 482template class Property<bool>; 483template class Property<int16>; 484template class Property<uint16>; 485template class Property<int32>; 486template class Property<uint32>; 487template class Property<int64>; 488template class Property<uint64>; 489template class Property<double>; 490template class Property<std::string>; 491template class Property<ObjectPath>; 492template class Property<std::vector<std::string> >; 493template class Property<std::vector<ObjectPath> >; 494template class Property<std::vector<uint8> >; 495 496} // namespace dbus 497