Fix XmppLoginHandler to handle destruction from delegate methods.
[chromium-blink-merge.git] / dbus / property.cc
blob66b86c0486d9f8b85b8eb7418c3d89c985eb4df0
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"
8 #include "base/bind.h"
9 #include "base/logging.h"
11 #include "dbus/message.h"
12 #include "dbus/object_path.h"
13 #include "dbus/object_proxy.h"
15 namespace dbus {
18 // PropertyBase implementation.
21 void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
22 DCHECK(!property_set_);
23 property_set_ = property_set;
24 is_valid_ = false;
25 name_ = name;
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(
53 kPropertiesInterface,
54 kPropertiesChanged,
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) {
63 DCHECK(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();
70 return;
73 if (interface != this->interface())
74 return;
76 if (!UpdatePropertiesFromReader(&reader)) {
77 LOG(WARNING) << "Property changed signal has wrong parameters: "
78 << "expected dictionary: " << signal->ToString();
81 if (!InvalidatePropertiesFromReader(&reader)) {
82 LOG(WARNING) << "Property changed signal has wrong parameters: "
83 << "expected array to invalidate: " << signal->ToString();
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.";
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());
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));
110 void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
111 Response* response) {
112 if (!response) {
113 LOG(WARNING) << property->name() << ": Get: failed.";
114 return;
117 MessageReader reader(response);
118 if (property->PopValueFromReader(&reader)) {
119 property->set_valid(true);
120 NotifyPropertyChanged(property->name());
121 } else {
122 if (property->is_valid()) {
123 property->set_valid(false);
124 NotifyPropertyChanged(property->name());
128 if (!callback.is_null())
129 callback.Run(response);
132 void PropertySet::GetAll() {
133 MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
134 MessageWriter writer(&method_call);
135 writer.AppendString(interface());
137 DCHECK(object_proxy_);
138 object_proxy_->CallMethod(&method_call,
139 ObjectProxy::TIMEOUT_USE_DEFAULT,
140 base::Bind(&PropertySet::OnGetAll,
141 weak_ptr_factory_.GetWeakPtr()));
144 void PropertySet::OnGetAll(Response* response) {
145 if (!response) {
146 LOG(WARNING) << "GetAll request failed for: " << interface_;
147 return;
150 MessageReader reader(response);
151 if (!UpdatePropertiesFromReader(&reader)) {
152 LOG(WARNING) << "GetAll response has wrong parameters: "
153 << "expected dictionary: " << response->ToString();
157 void PropertySet::Set(PropertyBase* property, SetCallback callback) {
158 MethodCall method_call(kPropertiesInterface, kPropertiesSet);
159 MessageWriter writer(&method_call);
160 writer.AppendString(interface());
161 writer.AppendString(property->name());
162 property->AppendSetValueToWriter(&writer);
164 DCHECK(object_proxy_);
165 object_proxy_->CallMethod(&method_call,
166 ObjectProxy::TIMEOUT_USE_DEFAULT,
167 base::Bind(&PropertySet::OnSet,
168 GetWeakPtr(),
169 property,
170 callback));
173 void PropertySet::OnSet(PropertyBase* property,
174 SetCallback callback,
175 Response* response) {
176 LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
177 if (!callback.is_null())
178 callback.Run(response);
181 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
182 DCHECK(reader);
183 MessageReader array_reader(NULL);
184 if (!reader->PopArray(&array_reader))
185 return false;
187 while (array_reader.HasMoreData()) {
188 MessageReader dict_entry_reader(NULL);
189 if (array_reader.PopDictEntry(&dict_entry_reader))
190 UpdatePropertyFromReader(&dict_entry_reader);
193 return true;
196 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
197 DCHECK(reader);
199 std::string name;
200 if (!reader->PopString(&name))
201 return false;
203 PropertiesMap::iterator it = properties_map_.find(name);
204 if (it == properties_map_.end())
205 return false;
207 PropertyBase* property = it->second;
208 if (property->PopValueFromReader(reader)) {
209 property->set_valid(true);
210 NotifyPropertyChanged(name);
211 return true;
212 } else {
213 if (property->is_valid()) {
214 property->set_valid(false);
215 NotifyPropertyChanged(property->name());
217 return false;
221 bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
222 DCHECK(reader);
223 MessageReader array_reader(NULL);
224 if (!reader->PopArray(&array_reader))
225 return false;
227 while (array_reader.HasMoreData()) {
228 std::string name;
229 if (!array_reader.PopString(&name))
230 return false;
232 PropertiesMap::iterator it = properties_map_.find(name);
233 if (it == properties_map_.end())
234 continue;
236 PropertyBase* property = it->second;
237 if (property->is_valid()) {
238 property->set_valid(false);
239 NotifyPropertyChanged(property->name());
243 return true;
246 void PropertySet::NotifyPropertyChanged(const std::string& name) {
247 if (!property_changed_callback_.is_null())
248 property_changed_callback_.Run(name);
252 // Property<Byte> specialization.
255 template <>
256 Property<uint8>::Property() : value_(0) {
259 template <>
260 bool Property<uint8>::PopValueFromReader(MessageReader* reader) {
261 return reader->PopVariantOfByte(&value_);
264 template <>
265 void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) {
266 writer->AppendVariantOfByte(set_value_);
270 // Property<bool> specialization.
273 template <>
274 Property<bool>::Property() : value_(false) {
277 template <>
278 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
279 return reader->PopVariantOfBool(&value_);
282 template <>
283 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
284 writer->AppendVariantOfBool(set_value_);
288 // Property<int16> specialization.
291 template <>
292 Property<int16>::Property() : value_(0) {
295 template <>
296 bool Property<int16>::PopValueFromReader(MessageReader* reader) {
297 return reader->PopVariantOfInt16(&value_);
300 template <>
301 void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) {
302 writer->AppendVariantOfInt16(set_value_);
306 // Property<uint16> specialization.
309 template <>
310 Property<uint16>::Property() : value_(0) {
313 template <>
314 bool Property<uint16>::PopValueFromReader(MessageReader* reader) {
315 return reader->PopVariantOfUint16(&value_);
318 template <>
319 void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) {
320 writer->AppendVariantOfUint16(set_value_);
324 // Property<int32> specialization.
327 template <>
328 Property<int32>::Property() : value_(0) {
331 template <>
332 bool Property<int32>::PopValueFromReader(MessageReader* reader) {
333 return reader->PopVariantOfInt32(&value_);
336 template <>
337 void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) {
338 writer->AppendVariantOfInt32(set_value_);
342 // Property<uint32> specialization.
345 template <>
346 Property<uint32>::Property() : value_(0) {
349 template <>
350 bool Property<uint32>::PopValueFromReader(MessageReader* reader) {
351 return reader->PopVariantOfUint32(&value_);
354 template <>
355 void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) {
356 writer->AppendVariantOfUint32(set_value_);
360 // Property<int64> specialization.
363 template <>
364 Property<int64>::Property() : value_(0), set_value_(0) {
367 template <>
368 bool Property<int64>::PopValueFromReader(MessageReader* reader) {
369 return reader->PopVariantOfInt64(&value_);
372 template <>
373 void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) {
374 writer->AppendVariantOfInt64(set_value_);
378 // Property<uint64> specialization.
381 template <>
382 Property<uint64>::Property() : value_(0) {
385 template <>
386 bool Property<uint64>::PopValueFromReader(MessageReader* reader) {
387 return reader->PopVariantOfUint64(&value_);
390 template <>
391 void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) {
392 writer->AppendVariantOfUint64(set_value_);
396 // Property<double> specialization.
399 template <>
400 Property<double>::Property() : value_(0.0) {
403 template <>
404 bool Property<double>::PopValueFromReader(MessageReader* reader) {
405 return reader->PopVariantOfDouble(&value_);
408 template <>
409 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
410 writer->AppendVariantOfDouble(set_value_);
414 // Property<std::string> specialization.
417 template <>
418 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
419 return reader->PopVariantOfString(&value_);
422 template <>
423 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
424 writer->AppendVariantOfString(set_value_);
428 // Property<ObjectPath> specialization.
431 template <>
432 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
433 return reader->PopVariantOfObjectPath(&value_);
436 template <>
437 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
438 writer->AppendVariantOfObjectPath(set_value_);
442 // Property<std::vector<std::string> > specialization.
445 template <>
446 bool Property<std::vector<std::string> >::PopValueFromReader(
447 MessageReader* reader) {
448 MessageReader variant_reader(NULL);
449 if (!reader->PopVariant(&variant_reader))
450 return false;
452 value_.clear();
453 return variant_reader.PopArrayOfStrings(&value_);
456 template <>
457 void Property<std::vector<std::string> >::AppendSetValueToWriter(
458 MessageWriter* writer) {
459 MessageWriter variant_writer(NULL);
460 writer->OpenVariant("as", &variant_writer);
461 variant_writer.AppendArrayOfStrings(set_value_);
462 writer->CloseContainer(&variant_writer);
466 // Property<std::vector<ObjectPath> > specialization.
469 template <>
470 bool Property<std::vector<ObjectPath> >::PopValueFromReader(
471 MessageReader* reader) {
472 MessageReader variant_reader(NULL);
473 if (!reader->PopVariant(&variant_reader))
474 return false;
476 value_.clear();
477 return variant_reader.PopArrayOfObjectPaths(&value_);
480 template <>
481 void Property<std::vector<ObjectPath> >::AppendSetValueToWriter(
482 MessageWriter* writer) {
483 MessageWriter variant_writer(NULL);
484 writer->OpenVariant("ao", &variant_writer);
485 variant_writer.AppendArrayOfObjectPaths(set_value_);
486 writer->CloseContainer(&variant_writer);
490 // Property<std::vector<uint8> > specialization.
493 template <>
494 bool Property<std::vector<uint8> >::PopValueFromReader(MessageReader* reader) {
495 MessageReader variant_reader(NULL);
496 if (!reader->PopVariant(&variant_reader))
497 return false;
499 value_.clear();
500 const uint8* bytes = NULL;
501 size_t length = 0;
502 if (!variant_reader.PopArrayOfBytes(&bytes, &length))
503 return false;
504 value_.assign(bytes, bytes + length);
505 return true;
508 template <>
509 void Property<std::vector<uint8> >::AppendSetValueToWriter(
510 MessageWriter* writer) {
511 MessageWriter variant_writer(NULL);
512 writer->OpenVariant("ay", &variant_writer);
513 variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
514 writer->CloseContainer(&variant_writer);
518 // Property<std::map<std::string, std::string>> specialization.
521 template <>
522 bool Property<std::map<std::string, std::string>>::PopValueFromReader(
523 MessageReader* reader) {
524 MessageReader variant_reader(NULL);
525 MessageReader array_reader(NULL);
526 if (!reader->PopVariant(&variant_reader) ||
527 !variant_reader.PopArray(&array_reader))
528 return false;
529 value_.clear();
530 while (array_reader.HasMoreData()) {
531 dbus::MessageReader dict_entry_reader(NULL);
532 if (!array_reader.PopDictEntry(&dict_entry_reader))
533 return false;
534 std::string key;
535 std::string value;
536 if (!dict_entry_reader.PopString(&key) ||
537 !dict_entry_reader.PopString(&value))
538 return false;
539 value_[key] = value;
541 return true;
544 template <>
545 void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
546 MessageWriter* writer) {
547 MessageWriter variant_writer(NULL);
548 MessageWriter dict_writer(NULL);
549 writer->OpenVariant("a{ss}", &variant_writer);
550 variant_writer.OpenArray("{ss}", &dict_writer);
551 for (const auto& pair : set_value_) {
552 dbus::MessageWriter entry_writer(NULL);
553 dict_writer.OpenDictEntry(&entry_writer);
554 entry_writer.AppendString(pair.first);
555 entry_writer.AppendString(pair.second);
556 dict_writer.CloseContainer(&entry_writer);
558 variant_writer.CloseContainer(&dict_writer);
559 writer->CloseContainer(&variant_writer);
563 // Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
564 // specialization.
567 template <>
568 bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
569 PopValueFromReader(MessageReader* reader) {
570 MessageReader variant_reader(NULL);
571 MessageReader array_reader(NULL);
572 if (!reader->PopVariant(&variant_reader) ||
573 !variant_reader.PopArray(&array_reader))
574 return false;
576 value_.clear();
577 while (array_reader.HasMoreData()) {
578 dbus::MessageReader struct_reader(NULL);
579 if (!array_reader.PopStruct(&struct_reader))
580 return false;
582 std::pair<std::vector<uint8_t>, uint16_t> entry;
583 const uint8* bytes = NULL;
584 size_t length = 0;
585 if (!struct_reader.PopArrayOfBytes(&bytes, &length))
586 return false;
587 entry.first.assign(bytes, bytes + length);
588 if (!struct_reader.PopUint16(&entry.second))
589 return false;
590 value_.push_back(entry);
592 return true;
595 template <>
596 void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
597 AppendSetValueToWriter(MessageWriter* writer) {
598 MessageWriter variant_writer(NULL);
599 MessageWriter array_writer(NULL);
600 writer->OpenVariant("a(ayq)", &variant_writer);
601 variant_writer.OpenArray("(ayq)", &array_writer);
602 for (const auto& pair : set_value_) {
603 dbus::MessageWriter struct_writer(nullptr);
604 array_writer.OpenStruct(&struct_writer);
605 struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
606 std::get<0>(pair).size());
607 struct_writer.AppendUint16(std::get<1>(pair));
608 array_writer.CloseContainer(&struct_writer);
610 variant_writer.CloseContainer(&array_writer);
611 writer->CloseContainer(&variant_writer);
614 template class Property<uint8>;
615 template class Property<bool>;
616 template class Property<int16>;
617 template class Property<uint16>;
618 template class Property<int32>;
619 template class Property<uint32>;
620 template class Property<int64>;
621 template class Property<uint64>;
622 template class Property<double>;
623 template class Property<std::string>;
624 template class Property<ObjectPath>;
625 template class Property<std::vector<std::string> >;
626 template class Property<std::vector<ObjectPath> >;
627 template class Property<std::vector<uint8> >;
628 template class Property<std::map<std::string, std::string>>;
629 template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
631 } // namespace dbus