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.
5 #include "dbus/property.h"
7 #include "base/basictypes.h"
9 #include "base/logging.h"
11 #include "dbus/message.h"
12 #include "dbus/object_path.h"
13 #include "dbus/object_proxy.h"
18 // PropertyBase implementation.
21 void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
22 DCHECK(!property_set_);
23 property_set_ = property_set;
29 // PropertySet implementation.
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) {}
41 PropertySet::~PropertySet() {
44 void PropertySet::RegisterProperty(const std::string& name,
45 PropertyBase* property) {
46 property->Init(this, name);
47 properties_map_[name] = property;
50 void PropertySet::ConnectSignals() {
51 DCHECK(object_proxy_);
52 object_proxy_->ConnectToSignal(
55 base::Bind(&PropertySet::ChangedReceived,
56 weak_ptr_factory_.GetWeakPtr()),
57 base::Bind(&PropertySet::ChangedConnected,
58 weak_ptr_factory_.GetWeakPtr()));
62 void PropertySet::ChangedReceived(Signal* signal) {
64 MessageReader reader(signal);
66 std::string interface;
67 if (!reader.PopString(&interface)) {
68 LOG(WARNING) << "Property changed signal has wrong parameters: "
69 << "expected interface name: " << signal->ToString();
73 if (interface != this->interface())
76 if (!UpdatePropertiesFromReader(&reader)) {
77 LOG(WARNING) << "Property changed signal has wrong parameters: "
78 << "expected dictionary: " << signal->ToString();
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.
87 void PropertySet::ChangedConnected(const std::string& interface_name,
88 const std::string& signal_name,
90 LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name
93 // This is a simple workaround for crbug.com/407109, which causes signals to
94 // be missed if they are received before a match rule is added for them. This
95 // is a branch-only workaround that is only present in 2125 (38).
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());
106 DCHECK(object_proxy_);
107 object_proxy_->CallMethod(&method_call,
108 ObjectProxy::TIMEOUT_USE_DEFAULT,
109 base::Bind(&PropertySet::OnGet,
115 void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
116 Response* response) {
118 LOG(WARNING) << property->name() << ": Get: failed.";
122 MessageReader reader(response);
123 if (property->PopValueFromReader(&reader))
124 NotifyPropertyChanged(property->name());
126 if (!callback.is_null())
127 callback.Run(response);
130 void PropertySet::GetAll() {
131 MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
132 MessageWriter writer(&method_call);
133 writer.AppendString(interface());
135 DCHECK(object_proxy_);
136 object_proxy_->CallMethod(&method_call,
137 ObjectProxy::TIMEOUT_USE_DEFAULT,
138 base::Bind(&PropertySet::OnGetAll,
139 weak_ptr_factory_.GetWeakPtr()));
142 void PropertySet::OnGetAll(Response* response) {
144 LOG(WARNING) << "GetAll request failed for: " << interface_;
148 MessageReader reader(response);
149 if (!UpdatePropertiesFromReader(&reader)) {
150 LOG(WARNING) << "GetAll response has wrong parameters: "
151 << "expected dictionary: " << response->ToString();
155 void PropertySet::Set(PropertyBase* property, SetCallback callback) {
156 MethodCall method_call(kPropertiesInterface, kPropertiesSet);
157 MessageWriter writer(&method_call);
158 writer.AppendString(interface());
159 writer.AppendString(property->name());
160 property->AppendSetValueToWriter(&writer);
162 DCHECK(object_proxy_);
163 object_proxy_->CallMethod(&method_call,
164 ObjectProxy::TIMEOUT_USE_DEFAULT,
165 base::Bind(&PropertySet::OnSet,
171 void PropertySet::OnSet(PropertyBase* property,
172 SetCallback callback,
173 Response* response) {
174 LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
175 if (!callback.is_null())
176 callback.Run(response);
179 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
181 MessageReader array_reader(NULL);
182 if (!reader->PopArray(&array_reader))
185 while (array_reader.HasMoreData()) {
186 MessageReader dict_entry_reader(NULL);
187 if (array_reader.PopDictEntry(&dict_entry_reader))
188 UpdatePropertyFromReader(&dict_entry_reader);
194 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
198 if (!reader->PopString(&name))
201 PropertiesMap::iterator it = properties_map_.find(name);
202 if (it == properties_map_.end())
205 PropertyBase* property = it->second;
206 if (property->PopValueFromReader(reader)) {
207 NotifyPropertyChanged(name);
215 void PropertySet::NotifyPropertyChanged(const std::string& name) {
216 if (!property_changed_callback_.is_null())
217 property_changed_callback_.Run(name);
221 // Property<Byte> specialization.
225 Property<uint8>::Property() : value_(0) {
229 bool Property<uint8>::PopValueFromReader(MessageReader* reader) {
230 return reader->PopVariantOfByte(&value_);
234 void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) {
235 writer->AppendVariantOfByte(set_value_);
239 // Property<bool> specialization.
243 Property<bool>::Property() : value_(false) {
247 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
248 return reader->PopVariantOfBool(&value_);
252 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
253 writer->AppendVariantOfBool(set_value_);
257 // Property<int16> specialization.
261 Property<int16>::Property() : value_(0) {
265 bool Property<int16>::PopValueFromReader(MessageReader* reader) {
266 return reader->PopVariantOfInt16(&value_);
270 void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) {
271 writer->AppendVariantOfInt16(set_value_);
275 // Property<uint16> specialization.
279 Property<uint16>::Property() : value_(0) {
283 bool Property<uint16>::PopValueFromReader(MessageReader* reader) {
284 return reader->PopVariantOfUint16(&value_);
288 void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) {
289 writer->AppendVariantOfUint16(set_value_);
293 // Property<int32> specialization.
297 Property<int32>::Property() : value_(0) {
301 bool Property<int32>::PopValueFromReader(MessageReader* reader) {
302 return reader->PopVariantOfInt32(&value_);
306 void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) {
307 writer->AppendVariantOfInt32(set_value_);
311 // Property<uint32> specialization.
315 Property<uint32>::Property() : value_(0) {
319 bool Property<uint32>::PopValueFromReader(MessageReader* reader) {
320 return reader->PopVariantOfUint32(&value_);
324 void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) {
325 writer->AppendVariantOfUint32(set_value_);
329 // Property<int64> specialization.
333 Property<int64>::Property() : value_(0), set_value_(0) {
337 bool Property<int64>::PopValueFromReader(MessageReader* reader) {
338 return reader->PopVariantOfInt64(&value_);
342 void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) {
343 writer->AppendVariantOfInt64(set_value_);
347 // Property<uint64> specialization.
351 Property<uint64>::Property() : value_(0) {
355 bool Property<uint64>::PopValueFromReader(MessageReader* reader) {
356 return reader->PopVariantOfUint64(&value_);
360 void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) {
361 writer->AppendVariantOfUint64(set_value_);
365 // Property<double> specialization.
369 Property<double>::Property() : value_(0.0) {
373 bool Property<double>::PopValueFromReader(MessageReader* reader) {
374 return reader->PopVariantOfDouble(&value_);
378 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
379 writer->AppendVariantOfDouble(set_value_);
383 // Property<std::string> specialization.
387 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
388 return reader->PopVariantOfString(&value_);
392 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
393 writer->AppendVariantOfString(set_value_);
397 // Property<ObjectPath> specialization.
401 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
402 return reader->PopVariantOfObjectPath(&value_);
406 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
407 writer->AppendVariantOfObjectPath(set_value_);
411 // Property<std::vector<std::string> > specialization.
415 bool Property<std::vector<std::string> >::PopValueFromReader(
416 MessageReader* reader) {
417 MessageReader variant_reader(NULL);
418 if (!reader->PopVariant(&variant_reader))
422 return variant_reader.PopArrayOfStrings(&value_);
426 void Property<std::vector<std::string> >::AppendSetValueToWriter(
427 MessageWriter* writer) {
428 MessageWriter variant_writer(NULL);
429 writer->OpenVariant("as", &variant_writer);
430 variant_writer.AppendArrayOfStrings(set_value_);
431 writer->CloseContainer(&variant_writer);
435 // Property<std::vector<ObjectPath> > specialization.
439 bool Property<std::vector<ObjectPath> >::PopValueFromReader(
440 MessageReader* reader) {
441 MessageReader variant_reader(NULL);
442 if (!reader->PopVariant(&variant_reader))
446 return variant_reader.PopArrayOfObjectPaths(&value_);
450 void Property<std::vector<ObjectPath> >::AppendSetValueToWriter(
451 MessageWriter* writer) {
452 MessageWriter variant_writer(NULL);
453 writer->OpenVariant("ao", &variant_writer);
454 variant_writer.AppendArrayOfObjectPaths(set_value_);
455 writer->CloseContainer(&variant_writer);
459 // Property<std::vector<uint8> > specialization.
463 bool Property<std::vector<uint8> >::PopValueFromReader(MessageReader* reader) {
464 MessageReader variant_reader(NULL);
465 if (!reader->PopVariant(&variant_reader))
469 const uint8* bytes = NULL;
471 if (!variant_reader.PopArrayOfBytes(&bytes, &length))
473 value_.assign(bytes, bytes + length);
478 void Property<std::vector<uint8> >::AppendSetValueToWriter(
479 MessageWriter* writer) {
480 MessageWriter variant_writer(NULL);
481 writer->OpenVariant("ay", &variant_writer);
482 variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
483 writer->CloseContainer(&variant_writer);
486 template class Property<uint8>;
487 template class Property<bool>;
488 template class Property<int16>;
489 template class Property<uint16>;
490 template class Property<int32>;
491 template class Property<uint32>;
492 template class Property<int64>;
493 template class Property<uint64>;
494 template class Property<double>;
495 template class Property<std::string>;
496 template class Property<ObjectPath>;
497 template class Property<std::vector<std::string> >;
498 template class Property<std::vector<ObjectPath> >;
499 template class Property<std::vector<uint8> >;