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 <stddef.h>
      8 
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 
     12 #include "dbus/message.h"
     13 #include "dbus/object_path.h"
     14 #include "dbus/object_proxy.h"
     15 
     16 namespace dbus {
     17 
     18 //
     19 // PropertyBase implementation.
     20 //
     21 
     22 PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {}
     23 
     24 PropertyBase::~PropertyBase() {}
     25 
     26 void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
     27   DCHECK(!property_set_);
     28   property_set_ = property_set;
     29   is_valid_ = false;
     30   name_ = name;
     31 }
     32 
     33 //
     34 // PropertySet implementation.
     35 //
     36 
     37 PropertySet::PropertySet(
     38     ObjectProxy* object_proxy,
     39     const std::string& interface,
     40     const PropertyChangedCallback& property_changed_callback)
     41     : object_proxy_(object_proxy),
     42       interface_(interface),
     43       property_changed_callback_(property_changed_callback),
     44       weak_ptr_factory_(this) {}
     45 
     46 PropertySet::~PropertySet() {
     47 }
     48 
     49 void PropertySet::RegisterProperty(const std::string& name,
     50                                    PropertyBase* property) {
     51   property->Init(this, name);
     52   properties_map_[name] = property;
     53 }
     54 
     55 void PropertySet::ConnectSignals() {
     56   DCHECK(object_proxy_);
     57   object_proxy_->ConnectToSignal(
     58       kPropertiesInterface,
     59       kPropertiesChanged,
     60       base::Bind(&PropertySet::ChangedReceived,
     61                  weak_ptr_factory_.GetWeakPtr()),
     62       base::Bind(&PropertySet::ChangedConnected,
     63                  weak_ptr_factory_.GetWeakPtr()));
     64 }
     65 
     66 
     67 void PropertySet::ChangedReceived(Signal* signal) {
     68   DCHECK(signal);
     69   MessageReader reader(signal);
     70 
     71   std::string interface;
     72   if (!reader.PopString(&interface)) {
     73     LOG(WARNING) << "Property changed signal has wrong parameters: "
     74                  << "expected interface name: " << signal->ToString();
     75     return;
     76   }
     77 
     78   if (interface != this->interface())
     79     return;
     80 
     81   if (!UpdatePropertiesFromReader(&reader)) {
     82     LOG(WARNING) << "Property changed signal has wrong parameters: "
     83                  << "expected dictionary: " << signal->ToString();
     84   }
     85 
     86   if (!InvalidatePropertiesFromReader(&reader)) {
     87     LOG(WARNING) << "Property changed signal has wrong parameters: "
     88                  << "expected array to invalidate: " << signal->ToString();
     89   }
     90 }
     91 
     92 void PropertySet::ChangedConnected(const std::string& /* interface_name */,
     93                                    const std::string& signal_name,
     94                                    bool success) {
     95   LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name
     96                             << "signal.";
     97 }
     98 
     99 
    100 void PropertySet::Get(PropertyBase* property, GetCallback callback) {
    101   MethodCall method_call(kPropertiesInterface, kPropertiesGet);
    102   MessageWriter writer(&method_call);
    103   writer.AppendString(interface());
    104   writer.AppendString(property->name());
    105 
    106   DCHECK(object_proxy_);
    107   object_proxy_->CallMethod(&method_call,
    108                             ObjectProxy::TIMEOUT_USE_DEFAULT,
    109                             base::Bind(&PropertySet::OnGet,
    110                                        GetWeakPtr(),
    111                                        property,
    112                                        callback));
    113 }
    114 
    115 void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
    116                         Response* response) {
    117   if (!response) {
    118     LOG(WARNING) << property->name() << ": Get: failed.";
    119     return;
    120   }
    121 
    122   MessageReader reader(response);
    123   if (property->PopValueFromReader(&reader)) {
    124     property->set_valid(true);
    125     NotifyPropertyChanged(property->name());
    126   } else {
    127     if (property->is_valid()) {
    128       property->set_valid(false);
    129       NotifyPropertyChanged(property->name());
    130     }
    131   }
    132 
    133   if (!callback.is_null())
    134     callback.Run(response);
    135 }
    136 
    137 bool PropertySet::GetAndBlock(PropertyBase* property) {
    138   MethodCall method_call(kPropertiesInterface, kPropertiesGet);
    139   MessageWriter writer(&method_call);
    140   writer.AppendString(interface());
    141   writer.AppendString(property->name());
    142 
    143   DCHECK(object_proxy_);
    144   scoped_ptr<dbus::Response> response(
    145       object_proxy_->CallMethodAndBlock(&method_call,
    146                                         ObjectProxy::TIMEOUT_USE_DEFAULT));
    147 
    148   if (!response.get()) {
    149     LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
    150     return false;
    151   }
    152 
    153   MessageReader reader(response.get());
    154   if (property->PopValueFromReader(&reader)) {
    155     property->set_valid(true);
    156     NotifyPropertyChanged(property->name());
    157   } else {
    158     if (property->is_valid()) {
    159       property->set_valid(false);
    160       NotifyPropertyChanged(property->name());
    161     }
    162   }
    163   return true;
    164 }
    165 
    166 void PropertySet::GetAll() {
    167   MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
    168   MessageWriter writer(&method_call);
    169   writer.AppendString(interface());
    170 
    171   DCHECK(object_proxy_);
    172   object_proxy_->CallMethod(&method_call,
    173                             ObjectProxy::TIMEOUT_USE_DEFAULT,
    174                             base::Bind(&PropertySet::OnGetAll,
    175                                        weak_ptr_factory_.GetWeakPtr()));
    176 }
    177 
    178 void PropertySet::OnGetAll(Response* response) {
    179   if (!response) {
    180     LOG(WARNING) << "GetAll request failed for: " << interface_;
    181     return;
    182   }
    183 
    184   MessageReader reader(response);
    185   if (!UpdatePropertiesFromReader(&reader)) {
    186     LOG(WARNING) << "GetAll response has wrong parameters: "
    187                  << "expected dictionary: " << response->ToString();
    188   }
    189 }
    190 
    191 void PropertySet::Set(PropertyBase* property, SetCallback callback) {
    192   MethodCall method_call(kPropertiesInterface, kPropertiesSet);
    193   MessageWriter writer(&method_call);
    194   writer.AppendString(interface());
    195   writer.AppendString(property->name());
    196   property->AppendSetValueToWriter(&writer);
    197 
    198   DCHECK(object_proxy_);
    199   object_proxy_->CallMethod(&method_call,
    200                             ObjectProxy::TIMEOUT_USE_DEFAULT,
    201                             base::Bind(&PropertySet::OnSet,
    202                                        GetWeakPtr(),
    203                                        property,
    204                                        callback));
    205 }
    206 
    207 bool PropertySet::SetAndBlock(PropertyBase* property) {
    208   MethodCall method_call(kPropertiesInterface, kPropertiesSet);
    209   MessageWriter writer(&method_call);
    210   writer.AppendString(interface());
    211   writer.AppendString(property->name());
    212   property->AppendSetValueToWriter(&writer);
    213 
    214   DCHECK(object_proxy_);
    215   scoped_ptr<dbus::Response> response(
    216       object_proxy_->CallMethodAndBlock(&method_call,
    217                                         ObjectProxy::TIMEOUT_USE_DEFAULT));
    218   if (response.get())
    219     return true;
    220   return false;
    221 }
    222 
    223 void PropertySet::OnSet(PropertyBase* property,
    224                         SetCallback callback,
    225                         Response* response) {
    226   LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
    227   if (!callback.is_null())
    228     callback.Run(response);
    229 }
    230 
    231 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
    232   DCHECK(reader);
    233   MessageReader array_reader(NULL);
    234   if (!reader->PopArray(&array_reader))
    235     return false;
    236 
    237   while (array_reader.HasMoreData()) {
    238     MessageReader dict_entry_reader(NULL);
    239     if (array_reader.PopDictEntry(&dict_entry_reader))
    240       UpdatePropertyFromReader(&dict_entry_reader);
    241   }
    242 
    243   return true;
    244 }
    245 
    246 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
    247   DCHECK(reader);
    248 
    249   std::string name;
    250   if (!reader->PopString(&name))
    251     return false;
    252 
    253   PropertiesMap::iterator it = properties_map_.find(name);
    254   if (it == properties_map_.end())
    255     return false;
    256 
    257   PropertyBase* property = it->second;
    258   if (property->PopValueFromReader(reader)) {
    259     property->set_valid(true);
    260     NotifyPropertyChanged(name);
    261     return true;
    262   } else {
    263     if (property->is_valid()) {
    264       property->set_valid(false);
    265       NotifyPropertyChanged(property->name());
    266     }
    267     return false;
    268   }
    269 }
    270 
    271 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
    272   DCHECK(reader);
    273   MessageReader array_reader(NULL);
    274   if (!reader->PopArray(&array_reader))
    275     return false;
    276 
    277   while (array_reader.HasMoreData()) {
    278     std::string name;
    279     if (!array_reader.PopString(&name))
    280       return false;
    281 
    282     PropertiesMap::iterator it = properties_map_.find(name);
    283     if (it == properties_map_.end())
    284       continue;
    285 
    286     PropertyBase* property = it->second;
    287     if (property->is_valid()) {
    288       property->set_valid(false);
    289       NotifyPropertyChanged(property->name());
    290     }
    291   }
    292 
    293   return true;
    294 }
    295 
    296 void PropertySet::NotifyPropertyChanged(const std::string& name) {
    297   if (!property_changed_callback_.is_null())
    298     property_changed_callback_.Run(name);
    299 }
    300 
    301 //
    302 // Property<Byte> specialization.
    303 //
    304 
    305 template <>
    306 Property<uint8_t>::Property()
    307     : value_(0) {}
    308 
    309 template <>
    310 bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
    311   return reader->PopVariantOfByte(&value_);
    312 }
    313 
    314 template <>
    315 void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
    316   writer->AppendVariantOfByte(set_value_);
    317 }
    318 
    319 //
    320 // Property<bool> specialization.
    321 //
    322 
    323 template <>
    324 Property<bool>::Property() : value_(false) {
    325 }
    326 
    327 template <>
    328 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
    329   return reader->PopVariantOfBool(&value_);
    330 }
    331 
    332 template <>
    333 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
    334   writer->AppendVariantOfBool(set_value_);
    335 }
    336 
    337 //
    338 // Property<int16_t> specialization.
    339 //
    340 
    341 template <>
    342 Property<int16_t>::Property()
    343     : value_(0) {}
    344 
    345 template <>
    346 bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
    347   return reader->PopVariantOfInt16(&value_);
    348 }
    349 
    350 template <>
    351 void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
    352   writer->AppendVariantOfInt16(set_value_);
    353 }
    354 
    355 //
    356 // Property<uint16_t> specialization.
    357 //
    358 
    359 template <>
    360 Property<uint16_t>::Property()
    361     : value_(0) {}
    362 
    363 template <>
    364 bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
    365   return reader->PopVariantOfUint16(&value_);
    366 }
    367 
    368 template <>
    369 void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
    370   writer->AppendVariantOfUint16(set_value_);
    371 }
    372 
    373 //
    374 // Property<int32_t> specialization.
    375 //
    376 
    377 template <>
    378 Property<int32_t>::Property()
    379     : value_(0) {}
    380 
    381 template <>
    382 bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
    383   return reader->PopVariantOfInt32(&value_);
    384 }
    385 
    386 template <>
    387 void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
    388   writer->AppendVariantOfInt32(set_value_);
    389 }
    390 
    391 //
    392 // Property<uint32_t> specialization.
    393 //
    394 
    395 template <>
    396 Property<uint32_t>::Property()
    397     : value_(0) {}
    398 
    399 template <>
    400 bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
    401   return reader->PopVariantOfUint32(&value_);
    402 }
    403 
    404 template <>
    405 void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
    406   writer->AppendVariantOfUint32(set_value_);
    407 }
    408 
    409 //
    410 // Property<int64_t> specialization.
    411 //
    412 
    413 template <>
    414 Property<int64_t>::Property()
    415     : value_(0), set_value_(0) {}
    416 
    417 template <>
    418 bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
    419   return reader->PopVariantOfInt64(&value_);
    420 }
    421 
    422 template <>
    423 void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
    424   writer->AppendVariantOfInt64(set_value_);
    425 }
    426 
    427 //
    428 // Property<uint64_t> specialization.
    429 //
    430 
    431 template <>
    432 Property<uint64_t>::Property()
    433     : value_(0) {}
    434 
    435 template <>
    436 bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
    437   return reader->PopVariantOfUint64(&value_);
    438 }
    439 
    440 template <>
    441 void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
    442   writer->AppendVariantOfUint64(set_value_);
    443 }
    444 
    445 //
    446 // Property<double> specialization.
    447 //
    448 
    449 template <>
    450 Property<double>::Property() : value_(0.0) {
    451 }
    452 
    453 template <>
    454 bool Property<double>::PopValueFromReader(MessageReader* reader) {
    455   return reader->PopVariantOfDouble(&value_);
    456 }
    457 
    458 template <>
    459 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
    460   writer->AppendVariantOfDouble(set_value_);
    461 }
    462 
    463 //
    464 // Property<std::string> specialization.
    465 //
    466 
    467 template <>
    468 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
    469   return reader->PopVariantOfString(&value_);
    470 }
    471 
    472 template <>
    473 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
    474   writer->AppendVariantOfString(set_value_);
    475 }
    476 
    477 //
    478 // Property<ObjectPath> specialization.
    479 //
    480 
    481 template <>
    482 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
    483   return reader->PopVariantOfObjectPath(&value_);
    484 }
    485 
    486 template <>
    487 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
    488   writer->AppendVariantOfObjectPath(set_value_);
    489 }
    490 
    491 //
    492 // Property<std::vector<std::string> > specialization.
    493 //
    494 
    495 template <>
    496 bool Property<std::vector<std::string> >::PopValueFromReader(
    497     MessageReader* reader) {
    498   MessageReader variant_reader(NULL);
    499   if (!reader->PopVariant(&variant_reader))
    500     return false;
    501 
    502   value_.clear();
    503   return variant_reader.PopArrayOfStrings(&value_);
    504 }
    505 
    506 template <>
    507 void Property<std::vector<std::string> >::AppendSetValueToWriter(
    508     MessageWriter* writer) {
    509   MessageWriter variant_writer(NULL);
    510   writer->OpenVariant("as", &variant_writer);
    511   variant_writer.AppendArrayOfStrings(set_value_);
    512   writer->CloseContainer(&variant_writer);
    513 }
    514 
    515 //
    516 // Property<std::vector<ObjectPath> > specialization.
    517 //
    518 
    519 template <>
    520 bool Property<std::vector<ObjectPath> >::PopValueFromReader(
    521     MessageReader* reader) {
    522   MessageReader variant_reader(NULL);
    523   if (!reader->PopVariant(&variant_reader))
    524     return false;
    525 
    526   value_.clear();
    527   return variant_reader.PopArrayOfObjectPaths(&value_);
    528 }
    529 
    530 template <>
    531 void Property<std::vector<ObjectPath> >::AppendSetValueToWriter(
    532     MessageWriter* writer) {
    533   MessageWriter variant_writer(NULL);
    534   writer->OpenVariant("ao", &variant_writer);
    535   variant_writer.AppendArrayOfObjectPaths(set_value_);
    536   writer->CloseContainer(&variant_writer);
    537 }
    538 
    539 //
    540 // Property<std::vector<uint8_t> > specialization.
    541 //
    542 
    543 template <>
    544 bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
    545   MessageReader variant_reader(NULL);
    546   if (!reader->PopVariant(&variant_reader))
    547     return false;
    548 
    549   value_.clear();
    550   const uint8_t* bytes = NULL;
    551   size_t length = 0;
    552   if (!variant_reader.PopArrayOfBytes(&bytes, &length))
    553     return false;
    554   value_.assign(bytes, bytes + length);
    555   return true;
    556 }
    557 
    558 template <>
    559 void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
    560     MessageWriter* writer) {
    561   MessageWriter variant_writer(NULL);
    562   writer->OpenVariant("ay", &variant_writer);
    563   variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
    564   writer->CloseContainer(&variant_writer);
    565 }
    566 
    567 //
    568 // Property<std::map<std::string, std::string>> specialization.
    569 //
    570 
    571 template <>
    572 bool Property<std::map<std::string, std::string>>::PopValueFromReader(
    573     MessageReader* reader) {
    574   MessageReader variant_reader(NULL);
    575   MessageReader array_reader(NULL);
    576   if (!reader->PopVariant(&variant_reader) ||
    577       !variant_reader.PopArray(&array_reader))
    578     return false;
    579   value_.clear();
    580   while (array_reader.HasMoreData()) {
    581     dbus::MessageReader dict_entry_reader(NULL);
    582     if (!array_reader.PopDictEntry(&dict_entry_reader))
    583       return false;
    584     std::string key;
    585     std::string value;
    586     if (!dict_entry_reader.PopString(&key) ||
    587         !dict_entry_reader.PopString(&value))
    588       return false;
    589     value_[key] = value;
    590   }
    591   return true;
    592 }
    593 
    594 template <>
    595 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
    596     MessageWriter* writer) {
    597   MessageWriter variant_writer(NULL);
    598   MessageWriter dict_writer(NULL);
    599   writer->OpenVariant("a{ss}", &variant_writer);
    600   variant_writer.OpenArray("{ss}", &dict_writer);
    601   for (const auto& pair : set_value_) {
    602     dbus::MessageWriter entry_writer(NULL);
    603     dict_writer.OpenDictEntry(&entry_writer);
    604     entry_writer.AppendString(pair.first);
    605     entry_writer.AppendString(pair.second);
    606     dict_writer.CloseContainer(&entry_writer);
    607   }
    608   variant_writer.CloseContainer(&dict_writer);
    609   writer->CloseContainer(&variant_writer);
    610 }
    611 
    612 //
    613 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
    614 // specialization.
    615 //
    616 
    617 template <>
    618 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
    619     PopValueFromReader(MessageReader* reader) {
    620   MessageReader variant_reader(NULL);
    621   MessageReader array_reader(NULL);
    622   if (!reader->PopVariant(&variant_reader) ||
    623       !variant_reader.PopArray(&array_reader))
    624     return false;
    625 
    626   value_.clear();
    627   while (array_reader.HasMoreData()) {
    628     dbus::MessageReader struct_reader(NULL);
    629     if (!array_reader.PopStruct(&struct_reader))
    630       return false;
    631 
    632     std::pair<std::vector<uint8_t>, uint16_t> entry;
    633     const uint8_t* bytes = NULL;
    634     size_t length = 0;
    635     if (!struct_reader.PopArrayOfBytes(&bytes, &length))
    636       return false;
    637     entry.first.assign(bytes, bytes + length);
    638     if (!struct_reader.PopUint16(&entry.second))
    639       return false;
    640     value_.push_back(entry);
    641   }
    642   return true;
    643 }
    644 
    645 template <>
    646 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
    647     AppendSetValueToWriter(MessageWriter* writer) {
    648   MessageWriter variant_writer(NULL);
    649   MessageWriter array_writer(NULL);
    650   writer->OpenVariant("a(ayq)", &variant_writer);
    651   variant_writer.OpenArray("(ayq)", &array_writer);
    652   for (const auto& pair : set_value_) {
    653     dbus::MessageWriter struct_writer(nullptr);
    654     array_writer.OpenStruct(&struct_writer);
    655     struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
    656                                      std::get<0>(pair).size());
    657     struct_writer.AppendUint16(std::get<1>(pair));
    658     array_writer.CloseContainer(&struct_writer);
    659   }
    660   variant_writer.CloseContainer(&array_writer);
    661   writer->CloseContainer(&variant_writer);
    662 }
    663 
    664 template class Property<uint8_t>;
    665 template class Property<bool>;
    666 template class Property<int16_t>;
    667 template class Property<uint16_t>;
    668 template class Property<int32_t>;
    669 template class Property<uint32_t>;
    670 template class Property<int64_t>;
    671 template class Property<uint64_t>;
    672 template class Property<double>;
    673 template class Property<std::string>;
    674 template class Property<ObjectPath>;
    675 template class Property<std::vector<std::string> >;
    676 template class Property<std::vector<ObjectPath> >;
    677 template class Property<std::vector<uint8_t>>;
    678 template class Property<std::map<std::string, std::string>>;
    679 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
    680 
    681 }  // namespace dbus
    682