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 15 namespace dbus { 16 17 // 18 // PropertyBase implementation. 19 // 20 21 void 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 32 PropertySet::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 41 PropertySet::~PropertySet() { 42 } 43 44 void PropertySet::RegisterProperty(const std::string& name, 45 PropertyBase* property) { 46 property->Init(this, name); 47 properties_map_[name] = property; 48 } 49 50 void 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 62 void 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 87 void 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 95 void 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 110 void 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 125 void 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 137 void 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 150 void 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 166 void 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 174 bool 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 189 bool 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 210 void 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 219 template <> 220 Property<uint8>::Property() : value_(0) { 221 } 222 223 template <> 224 bool Property<uint8>::PopValueFromReader(MessageReader* reader) { 225 return reader->PopVariantOfByte(&value_); 226 } 227 228 template <> 229 void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) { 230 writer->AppendVariantOfByte(set_value_); 231 } 232 233 // 234 // Property<bool> specialization. 235 // 236 237 template <> 238 Property<bool>::Property() : value_(false) { 239 } 240 241 template <> 242 bool Property<bool>::PopValueFromReader(MessageReader* reader) { 243 return reader->PopVariantOfBool(&value_); 244 } 245 246 template <> 247 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) { 248 writer->AppendVariantOfBool(set_value_); 249 } 250 251 // 252 // Property<int16> specialization. 253 // 254 255 template <> 256 Property<int16>::Property() : value_(0) { 257 } 258 259 template <> 260 bool Property<int16>::PopValueFromReader(MessageReader* reader) { 261 return reader->PopVariantOfInt16(&value_); 262 } 263 264 template <> 265 void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) { 266 writer->AppendVariantOfInt16(set_value_); 267 } 268 269 // 270 // Property<uint16> specialization. 271 // 272 273 template <> 274 Property<uint16>::Property() : value_(0) { 275 } 276 277 template <> 278 bool Property<uint16>::PopValueFromReader(MessageReader* reader) { 279 return reader->PopVariantOfUint16(&value_); 280 } 281 282 template <> 283 void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) { 284 writer->AppendVariantOfUint16(set_value_); 285 } 286 287 // 288 // Property<int32> specialization. 289 // 290 291 template <> 292 Property<int32>::Property() : value_(0) { 293 } 294 295 template <> 296 bool Property<int32>::PopValueFromReader(MessageReader* reader) { 297 return reader->PopVariantOfInt32(&value_); 298 } 299 300 template <> 301 void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) { 302 writer->AppendVariantOfInt32(set_value_); 303 } 304 305 // 306 // Property<uint32> specialization. 307 // 308 309 template <> 310 Property<uint32>::Property() : value_(0) { 311 } 312 313 template <> 314 bool Property<uint32>::PopValueFromReader(MessageReader* reader) { 315 return reader->PopVariantOfUint32(&value_); 316 } 317 318 template <> 319 void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) { 320 writer->AppendVariantOfUint32(set_value_); 321 } 322 323 // 324 // Property<int64> specialization. 325 // 326 327 template <> 328 Property<int64>::Property() : value_(0), set_value_(0) { 329 } 330 331 template <> 332 bool Property<int64>::PopValueFromReader(MessageReader* reader) { 333 return reader->PopVariantOfInt64(&value_); 334 } 335 336 template <> 337 void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) { 338 writer->AppendVariantOfInt64(set_value_); 339 } 340 341 // 342 // Property<uint64> specialization. 343 // 344 345 template <> 346 Property<uint64>::Property() : value_(0) { 347 } 348 349 template <> 350 bool Property<uint64>::PopValueFromReader(MessageReader* reader) { 351 return reader->PopVariantOfUint64(&value_); 352 } 353 354 template <> 355 void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) { 356 writer->AppendVariantOfUint64(set_value_); 357 } 358 359 // 360 // Property<double> specialization. 361 // 362 363 template <> 364 Property<double>::Property() : value_(0.0) { 365 } 366 367 template <> 368 bool Property<double>::PopValueFromReader(MessageReader* reader) { 369 return reader->PopVariantOfDouble(&value_); 370 } 371 372 template <> 373 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) { 374 writer->AppendVariantOfDouble(set_value_); 375 } 376 377 // 378 // Property<std::string> specialization. 379 // 380 381 template <> 382 bool Property<std::string>::PopValueFromReader(MessageReader* reader) { 383 return reader->PopVariantOfString(&value_); 384 } 385 386 template <> 387 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) { 388 writer->AppendVariantOfString(set_value_); 389 } 390 391 // 392 // Property<ObjectPath> specialization. 393 // 394 395 template <> 396 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) { 397 return reader->PopVariantOfObjectPath(&value_); 398 } 399 400 template <> 401 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) { 402 writer->AppendVariantOfObjectPath(set_value_); 403 } 404 405 // 406 // Property<std::vector<std::string> > specialization. 407 // 408 409 template <> 410 bool 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 420 template <> 421 void 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 433 template <> 434 bool 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 444 template <> 445 void 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 457 template <> 458 bool 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 472 template <> 473 void 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 481 template class Property<uint8>; 482 template class Property<bool>; 483 template class Property<int16>; 484 template class Property<uint16>; 485 template class Property<int32>; 486 template class Property<uint32>; 487 template class Property<int64>; 488 template class Property<uint64>; 489 template class Property<double>; 490 template class Property<std::string>; 491 template class Property<ObjectPath>; 492 template class Property<std::vector<std::string> >; 493 template class Property<std::vector<ObjectPath> >; 494 template class Property<std::vector<uint8> >; 495 496 } // namespace dbus 497