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."; 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, SetCallback callback, 167 Response* response) { 168 LOG_IF(WARNING, !response) << property->name() << ": Set: failed."; 169 if (!callback.is_null()) 170 callback.Run(response); 171 } 172 173 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) { 174 DCHECK(reader); 175 MessageReader array_reader(NULL); 176 if (!reader->PopArray(&array_reader)) 177 return false; 178 179 while (array_reader.HasMoreData()) { 180 MessageReader dict_entry_reader(NULL); 181 if (array_reader.PopDictEntry(&dict_entry_reader)) 182 UpdatePropertyFromReader(&dict_entry_reader); 183 } 184 185 return true; 186 } 187 188 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) { 189 DCHECK(reader); 190 191 std::string name; 192 if (!reader->PopString(&name)) 193 return false; 194 195 PropertiesMap::iterator it = properties_map_.find(name); 196 if (it == properties_map_.end()) 197 return false; 198 199 PropertyBase* property = it->second; 200 if (property->PopValueFromReader(reader)) { 201 NotifyPropertyChanged(name); 202 return true; 203 } else { 204 return false; 205 } 206 } 207 208 209 void PropertySet::NotifyPropertyChanged(const std::string& name) { 210 if (!property_changed_callback_.is_null()) 211 property_changed_callback_.Run(name); 212 } 213 214 // 215 // Property<Byte> specialization. 216 // 217 218 template <> 219 Property<uint8>::Property() : value_(0) { 220 } 221 222 template <> 223 bool Property<uint8>::PopValueFromReader(MessageReader* reader) { 224 return reader->PopVariantOfByte(&value_); 225 } 226 227 template <> 228 void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) { 229 writer->AppendVariantOfByte(set_value_); 230 } 231 232 // 233 // Property<bool> specialization. 234 // 235 236 template <> 237 Property<bool>::Property() : value_(false) { 238 } 239 240 template <> 241 bool Property<bool>::PopValueFromReader(MessageReader* reader) { 242 return reader->PopVariantOfBool(&value_); 243 } 244 245 template <> 246 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) { 247 writer->AppendVariantOfBool(set_value_); 248 } 249 250 // 251 // Property<int16> specialization. 252 // 253 254 template <> 255 Property<int16>::Property() : value_(0) { 256 } 257 258 template <> 259 bool Property<int16>::PopValueFromReader(MessageReader* reader) { 260 return reader->PopVariantOfInt16(&value_); 261 } 262 263 template <> 264 void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) { 265 writer->AppendVariantOfInt16(set_value_); 266 } 267 268 // 269 // Property<uint16> specialization. 270 // 271 272 template <> 273 Property<uint16>::Property() : value_(0) { 274 } 275 276 template <> 277 bool Property<uint16>::PopValueFromReader(MessageReader* reader) { 278 return reader->PopVariantOfUint16(&value_); 279 } 280 281 template <> 282 void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) { 283 writer->AppendVariantOfUint16(set_value_); 284 } 285 286 // 287 // Property<int32> specialization. 288 // 289 290 template <> 291 Property<int32>::Property() : value_(0) { 292 } 293 294 template <> 295 bool Property<int32>::PopValueFromReader(MessageReader* reader) { 296 return reader->PopVariantOfInt32(&value_); 297 } 298 299 template <> 300 void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) { 301 writer->AppendVariantOfInt32(set_value_); 302 } 303 304 // 305 // Property<uint32> specialization. 306 // 307 308 template <> 309 Property<uint32>::Property() : value_(0) { 310 } 311 312 template <> 313 bool Property<uint32>::PopValueFromReader(MessageReader* reader) { 314 return reader->PopVariantOfUint32(&value_); 315 } 316 317 template <> 318 void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) { 319 writer->AppendVariantOfUint32(set_value_); 320 } 321 322 // 323 // Property<int64> specialization. 324 // 325 326 template <> 327 Property<int64>::Property() : value_(0), set_value_(0) { 328 } 329 330 template <> 331 bool Property<int64>::PopValueFromReader(MessageReader* reader) { 332 return reader->PopVariantOfInt64(&value_); 333 } 334 335 template <> 336 void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) { 337 writer->AppendVariantOfInt64(set_value_); 338 } 339 340 // 341 // Property<uint64> specialization. 342 // 343 344 template <> 345 Property<uint64>::Property() : value_(0) { 346 } 347 348 template <> 349 bool Property<uint64>::PopValueFromReader(MessageReader* reader) { 350 return reader->PopVariantOfUint64(&value_); 351 } 352 353 template <> 354 void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) { 355 writer->AppendVariantOfUint64(set_value_); 356 } 357 358 // 359 // Property<double> specialization. 360 // 361 362 template <> 363 Property<double>::Property() : value_(0.0) { 364 } 365 366 template <> 367 bool Property<double>::PopValueFromReader(MessageReader* reader) { 368 return reader->PopVariantOfDouble(&value_); 369 } 370 371 template <> 372 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) { 373 writer->AppendVariantOfDouble(set_value_); 374 } 375 376 // 377 // Property<std::string> specialization. 378 // 379 380 template <> 381 bool Property<std::string>::PopValueFromReader(MessageReader* reader) { 382 return reader->PopVariantOfString(&value_); 383 } 384 385 template <> 386 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) { 387 writer->AppendVariantOfString(set_value_); 388 } 389 390 // 391 // Property<ObjectPath> specialization. 392 // 393 394 template <> 395 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) { 396 return reader->PopVariantOfObjectPath(&value_); 397 } 398 399 template <> 400 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) { 401 writer->AppendVariantOfObjectPath(set_value_); 402 } 403 404 // 405 // Property<std::vector<std::string> > specialization. 406 // 407 408 template <> 409 bool Property<std::vector<std::string> >::PopValueFromReader( 410 MessageReader* reader) { 411 MessageReader variant_reader(NULL); 412 if (!reader->PopVariant(&variant_reader)) 413 return false; 414 415 value_.clear(); 416 return variant_reader.PopArrayOfStrings(&value_); 417 } 418 419 template <> 420 void Property<std::vector<std::string> >::AppendSetValueToWriter( 421 MessageWriter* writer) { 422 MessageWriter variant_writer(NULL); 423 writer->OpenVariant("as", &variant_writer); 424 variant_writer.AppendArrayOfStrings(set_value_); 425 writer->CloseContainer(&variant_writer); 426 } 427 428 // 429 // Property<std::vector<ObjectPath> > specialization. 430 // 431 432 template <> 433 bool Property<std::vector<ObjectPath> >::PopValueFromReader( 434 MessageReader* reader) { 435 MessageReader variant_reader(NULL); 436 if (!reader->PopVariant(&variant_reader)) 437 return false; 438 439 value_.clear(); 440 return variant_reader.PopArrayOfObjectPaths(&value_); 441 } 442 443 template <> 444 void Property<std::vector<ObjectPath> >::AppendSetValueToWriter( 445 MessageWriter* writer) { 446 MessageWriter variant_writer(NULL); 447 writer->OpenVariant("ao", &variant_writer); 448 variant_writer.AppendArrayOfObjectPaths(set_value_); 449 writer->CloseContainer(&variant_writer); 450 } 451 452 } // namespace dbus 453