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 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