Home | History | Annotate | Download | only in dbus
      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 //
    453 // Property<std::vector<uint8> > specialization.
    454 //
    455 
    456 template <>
    457 bool Property<std::vector<uint8> >::PopValueFromReader(MessageReader* reader) {
    458   MessageReader variant_reader(NULL);
    459   if (!reader->PopVariant(&variant_reader))
    460     return false;
    461 
    462   value_.clear();
    463   const uint8* bytes = NULL;
    464   size_t length = 0;
    465   if (!variant_reader.PopArrayOfBytes(&bytes, &length))
    466     return false;
    467   value_.assign(bytes, bytes + length);
    468   return true;
    469 }
    470 
    471 template <>
    472 void Property<std::vector<uint8> >::AppendSetValueToWriter(
    473     MessageWriter* writer) {
    474   MessageWriter variant_writer(NULL);
    475   writer->OpenVariant("ay", &variant_writer);
    476   variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
    477   writer->CloseContainer(&variant_writer);
    478 }
    479 
    480 }  // namespace dbus
    481