blob: 9289c8614a62d8ea198c7bd5c93d0ca541ddd228 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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
15namespace dbus {
16
17//
18// PropertyBase implementation.
19//
20
21void 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
32PropertySet::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
41PropertySet::~PropertySet() {
42}
43
44void PropertySet::RegisterProperty(const std::string& name,
45 PropertyBase* property) {
46 property->Init(this, name);
47 properties_map_[name] = property;
48}
49
50void 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
62void 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
87void 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
95void 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
110void 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
125void 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
137void PropertySet::OnGetAll(Response* response) {
138 if (!response) {
139 LOG(WARNING) << "GetAll request failed.";
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
150void 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
166void PropertySet::OnSet(PropertyBase* property, SetCallback callback,
167 Response* response) {
168 LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
169 if (!callback.is_null())
170 callback.Run(response);
171}
172
173bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
174 DCHECK(reader);
175 MessageReader array_reader(NULL);
176 if (!reader->PopArray(&array_reader))
177 return false;
178
179 while (array_reader.HasMoreData()) {
180 MessageReader dict_entry_reader(NULL);
181 if (array_reader.PopDictEntry(&dict_entry_reader))
182 UpdatePropertyFromReader(&dict_entry_reader);
183 }
184
185 return true;
186}
187
188bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
189 DCHECK(reader);
190
191 std::string name;
192 if (!reader->PopString(&name))
193 return false;
194
195 PropertiesMap::iterator it = properties_map_.find(name);
196 if (it == properties_map_.end())
197 return false;
198
199 PropertyBase* property = it->second;
200 if (property->PopValueFromReader(reader)) {
201 NotifyPropertyChanged(name);
202 return true;
203 } else {
204 return false;
205 }
206}
207
208
209void PropertySet::NotifyPropertyChanged(const std::string& name) {
210 if (!property_changed_callback_.is_null())
211 property_changed_callback_.Run(name);
212}
213
214//
215// Property<Byte> specialization.
216//
217
218template <>
219Property<uint8>::Property() : value_(0) {
220}
221
222template <>
223bool Property<uint8>::PopValueFromReader(MessageReader* reader) {
224 return reader->PopVariantOfByte(&value_);
225}
226
227template <>
228void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) {
229 writer->AppendVariantOfByte(set_value_);
230}
231
232//
233// Property<bool> specialization.
234//
235
236template <>
237Property<bool>::Property() : value_(false) {
238}
239
240template <>
241bool Property<bool>::PopValueFromReader(MessageReader* reader) {
242 return reader->PopVariantOfBool(&value_);
243}
244
245template <>
246void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
247 writer->AppendVariantOfBool(set_value_);
248}
249
250//
251// Property<int16> specialization.
252//
253
254template <>
255Property<int16>::Property() : value_(0) {
256}
257
258template <>
259bool Property<int16>::PopValueFromReader(MessageReader* reader) {
260 return reader->PopVariantOfInt16(&value_);
261}
262
263template <>
264void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) {
265 writer->AppendVariantOfInt16(set_value_);
266}
267
268//
269// Property<uint16> specialization.
270//
271
272template <>
273Property<uint16>::Property() : value_(0) {
274}
275
276template <>
277bool Property<uint16>::PopValueFromReader(MessageReader* reader) {
278 return reader->PopVariantOfUint16(&value_);
279}
280
281template <>
282void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) {
283 writer->AppendVariantOfUint16(set_value_);
284}
285
286//
287// Property<int32> specialization.
288//
289
290template <>
291Property<int32>::Property() : value_(0) {
292}
293
294template <>
295bool Property<int32>::PopValueFromReader(MessageReader* reader) {
296 return reader->PopVariantOfInt32(&value_);
297}
298
299template <>
300void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) {
301 writer->AppendVariantOfInt32(set_value_);
302}
303
304//
305// Property<uint32> specialization.
306//
307
308template <>
309Property<uint32>::Property() : value_(0) {
310}
311
312template <>
313bool Property<uint32>::PopValueFromReader(MessageReader* reader) {
314 return reader->PopVariantOfUint32(&value_);
315}
316
317template <>
318void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) {
319 writer->AppendVariantOfUint32(set_value_);
320}
321
322//
323// Property<int64> specialization.
324//
325
326template <>
327Property<int64>::Property() : value_(0), set_value_(0) {
328}
329
330template <>
331bool Property<int64>::PopValueFromReader(MessageReader* reader) {
332 return reader->PopVariantOfInt64(&value_);
333}
334
335template <>
336void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) {
337 writer->AppendVariantOfInt64(set_value_);
338}
339
340//
341// Property<uint64> specialization.
342//
343
344template <>
345Property<uint64>::Property() : value_(0) {
346}
347
348template <>
349bool Property<uint64>::PopValueFromReader(MessageReader* reader) {
350 return reader->PopVariantOfUint64(&value_);
351}
352
353template <>
354void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) {
355 writer->AppendVariantOfUint64(set_value_);
356}
357
358//
359// Property<double> specialization.
360//
361
362template <>
363Property<double>::Property() : value_(0.0) {
364}
365
366template <>
367bool Property<double>::PopValueFromReader(MessageReader* reader) {
368 return reader->PopVariantOfDouble(&value_);
369}
370
371template <>
372void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
373 writer->AppendVariantOfDouble(set_value_);
374}
375
376//
377// Property<std::string> specialization.
378//
379
380template <>
381bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
382 return reader->PopVariantOfString(&value_);
383}
384
385template <>
386void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
387 writer->AppendVariantOfString(set_value_);
388}
389
390//
391// Property<ObjectPath> specialization.
392//
393
394template <>
395bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
396 return reader->PopVariantOfObjectPath(&value_);
397}
398
399template <>
400void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
401 writer->AppendVariantOfObjectPath(set_value_);
402}
403
404//
405// Property<std::vector<std::string> > specialization.
406//
407
408template <>
409bool Property<std::vector<std::string> >::PopValueFromReader(
410 MessageReader* reader) {
411 MessageReader variant_reader(NULL);
412 if (!reader->PopVariant(&variant_reader))
413 return false;
414
415 value_.clear();
416 return variant_reader.PopArrayOfStrings(&value_);
417}
418
419template <>
420void Property<std::vector<std::string> >::AppendSetValueToWriter(
421 MessageWriter* writer) {
422 MessageWriter variant_writer(NULL);
423 writer->OpenVariant("as", &variant_writer);
424 variant_writer.AppendArrayOfStrings(set_value_);
425 writer->CloseContainer(&variant_writer);
426}
427
428//
429// Property<std::vector<ObjectPath> > specialization.
430//
431
432template <>
433bool Property<std::vector<ObjectPath> >::PopValueFromReader(
434 MessageReader* reader) {
435 MessageReader variant_reader(NULL);
436 if (!reader->PopVariant(&variant_reader))
437 return false;
438
439 value_.clear();
440 return variant_reader.PopArrayOfObjectPaths(&value_);
441}
442
443template <>
444void Property<std::vector<ObjectPath> >::AppendSetValueToWriter(
445 MessageWriter* writer) {
446 MessageWriter variant_writer(NULL);
447 writer->OpenVariant("ao", &variant_writer);
448 variant_writer.AppendArrayOfObjectPaths(set_value_);
449 writer->CloseContainer(&variant_writer);
450}
451
452} // namespace dbus