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