Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / dbus / property.cc
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 "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
15 namespace dbus {
16
17 //
18 // PropertyBase implementation.
19 //
20
21 void 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
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) {}
40
41 PropertySet::~PropertySet() {
42 }
43
44 void PropertySet::RegisterProperty(const std::string& name,
45                                    PropertyBase* property) {
46   property->Init(this, name);
47   properties_map_[name] = property;
48 }
49
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()));
59 }
60
61
62 void 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
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.";
92
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).
96   GetAll();
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     NotifyPropertyChanged(property->name());
125
126   if (!callback.is_null())
127     callback.Run(response);
128 }
129
130 void PropertySet::GetAll() {
131   MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
132   MessageWriter writer(&method_call);
133   writer.AppendString(interface());
134
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()));
140 }
141
142 void PropertySet::OnGetAll(Response* response) {
143   if (!response) {
144     LOG(WARNING) << "GetAll request failed for: " << interface_;
145     return;
146   }
147
148   MessageReader reader(response);
149   if (!UpdatePropertiesFromReader(&reader)) {
150     LOG(WARNING) << "GetAll response has wrong parameters: "
151                  << "expected dictionary: " << response->ToString();
152   }
153 }
154
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);
161
162   DCHECK(object_proxy_);
163   object_proxy_->CallMethod(&method_call,
164                             ObjectProxy::TIMEOUT_USE_DEFAULT,
165                             base::Bind(&PropertySet::OnSet,
166                                        GetWeakPtr(),
167                                        property,
168                                        callback));
169 }
170
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);
177 }
178
179 bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
180   DCHECK(reader);
181   MessageReader array_reader(NULL);
182   if (!reader->PopArray(&array_reader))
183     return false;
184
185   while (array_reader.HasMoreData()) {
186     MessageReader dict_entry_reader(NULL);
187     if (array_reader.PopDictEntry(&dict_entry_reader))
188       UpdatePropertyFromReader(&dict_entry_reader);
189   }
190
191   return true;
192 }
193
194 bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
195   DCHECK(reader);
196
197   std::string name;
198   if (!reader->PopString(&name))
199     return false;
200
201   PropertiesMap::iterator it = properties_map_.find(name);
202   if (it == properties_map_.end())
203     return false;
204
205   PropertyBase* property = it->second;
206   if (property->PopValueFromReader(reader)) {
207     NotifyPropertyChanged(name);
208     return true;
209   } else {
210     return false;
211   }
212 }
213
214
215 void PropertySet::NotifyPropertyChanged(const std::string& name) {
216   if (!property_changed_callback_.is_null())
217     property_changed_callback_.Run(name);
218 }
219
220 //
221 // Property<Byte> specialization.
222 //
223
224 template <>
225 Property<uint8>::Property() : value_(0) {
226 }
227
228 template <>
229 bool Property<uint8>::PopValueFromReader(MessageReader* reader) {
230   return reader->PopVariantOfByte(&value_);
231 }
232
233 template <>
234 void Property<uint8>::AppendSetValueToWriter(MessageWriter* writer) {
235   writer->AppendVariantOfByte(set_value_);
236 }
237
238 //
239 // Property<bool> specialization.
240 //
241
242 template <>
243 Property<bool>::Property() : value_(false) {
244 }
245
246 template <>
247 bool Property<bool>::PopValueFromReader(MessageReader* reader) {
248   return reader->PopVariantOfBool(&value_);
249 }
250
251 template <>
252 void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
253   writer->AppendVariantOfBool(set_value_);
254 }
255
256 //
257 // Property<int16> specialization.
258 //
259
260 template <>
261 Property<int16>::Property() : value_(0) {
262 }
263
264 template <>
265 bool Property<int16>::PopValueFromReader(MessageReader* reader) {
266   return reader->PopVariantOfInt16(&value_);
267 }
268
269 template <>
270 void Property<int16>::AppendSetValueToWriter(MessageWriter* writer) {
271   writer->AppendVariantOfInt16(set_value_);
272 }
273
274 //
275 // Property<uint16> specialization.
276 //
277
278 template <>
279 Property<uint16>::Property() : value_(0) {
280 }
281
282 template <>
283 bool Property<uint16>::PopValueFromReader(MessageReader* reader) {
284   return reader->PopVariantOfUint16(&value_);
285 }
286
287 template <>
288 void Property<uint16>::AppendSetValueToWriter(MessageWriter* writer) {
289   writer->AppendVariantOfUint16(set_value_);
290 }
291
292 //
293 // Property<int32> specialization.
294 //
295
296 template <>
297 Property<int32>::Property() : value_(0) {
298 }
299
300 template <>
301 bool Property<int32>::PopValueFromReader(MessageReader* reader) {
302   return reader->PopVariantOfInt32(&value_);
303 }
304
305 template <>
306 void Property<int32>::AppendSetValueToWriter(MessageWriter* writer) {
307   writer->AppendVariantOfInt32(set_value_);
308 }
309
310 //
311 // Property<uint32> specialization.
312 //
313
314 template <>
315 Property<uint32>::Property() : value_(0) {
316 }
317
318 template <>
319 bool Property<uint32>::PopValueFromReader(MessageReader* reader) {
320   return reader->PopVariantOfUint32(&value_);
321 }
322
323 template <>
324 void Property<uint32>::AppendSetValueToWriter(MessageWriter* writer) {
325   writer->AppendVariantOfUint32(set_value_);
326 }
327
328 //
329 // Property<int64> specialization.
330 //
331
332 template <>
333 Property<int64>::Property() : value_(0), set_value_(0) {
334 }
335
336 template <>
337 bool Property<int64>::PopValueFromReader(MessageReader* reader) {
338   return reader->PopVariantOfInt64(&value_);
339 }
340
341 template <>
342 void Property<int64>::AppendSetValueToWriter(MessageWriter* writer) {
343   writer->AppendVariantOfInt64(set_value_);
344 }
345
346 //
347 // Property<uint64> specialization.
348 //
349
350 template <>
351 Property<uint64>::Property() : value_(0) {
352 }
353
354 template <>
355 bool Property<uint64>::PopValueFromReader(MessageReader* reader) {
356   return reader->PopVariantOfUint64(&value_);
357 }
358
359 template <>
360 void Property<uint64>::AppendSetValueToWriter(MessageWriter* writer) {
361   writer->AppendVariantOfUint64(set_value_);
362 }
363
364 //
365 // Property<double> specialization.
366 //
367
368 template <>
369 Property<double>::Property() : value_(0.0) {
370 }
371
372 template <>
373 bool Property<double>::PopValueFromReader(MessageReader* reader) {
374   return reader->PopVariantOfDouble(&value_);
375 }
376
377 template <>
378 void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
379   writer->AppendVariantOfDouble(set_value_);
380 }
381
382 //
383 // Property<std::string> specialization.
384 //
385
386 template <>
387 bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
388   return reader->PopVariantOfString(&value_);
389 }
390
391 template <>
392 void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
393   writer->AppendVariantOfString(set_value_);
394 }
395
396 //
397 // Property<ObjectPath> specialization.
398 //
399
400 template <>
401 bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
402   return reader->PopVariantOfObjectPath(&value_);
403 }
404
405 template <>
406 void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
407   writer->AppendVariantOfObjectPath(set_value_);
408 }
409
410 //
411 // Property<std::vector<std::string> > specialization.
412 //
413
414 template <>
415 bool Property<std::vector<std::string> >::PopValueFromReader(
416     MessageReader* reader) {
417   MessageReader variant_reader(NULL);
418   if (!reader->PopVariant(&variant_reader))
419     return false;
420
421   value_.clear();
422   return variant_reader.PopArrayOfStrings(&value_);
423 }
424
425 template <>
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);
432 }
433
434 //
435 // Property<std::vector<ObjectPath> > specialization.
436 //
437
438 template <>
439 bool Property<std::vector<ObjectPath> >::PopValueFromReader(
440     MessageReader* reader) {
441   MessageReader variant_reader(NULL);
442   if (!reader->PopVariant(&variant_reader))
443     return false;
444
445   value_.clear();
446   return variant_reader.PopArrayOfObjectPaths(&value_);
447 }
448
449 template <>
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);
456 }
457
458 //
459 // Property<std::vector<uint8> > specialization.
460 //
461
462 template <>
463 bool Property<std::vector<uint8> >::PopValueFromReader(MessageReader* reader) {
464   MessageReader variant_reader(NULL);
465   if (!reader->PopVariant(&variant_reader))
466     return false;
467
468   value_.clear();
469   const uint8* bytes = NULL;
470   size_t length = 0;
471   if (!variant_reader.PopArrayOfBytes(&bytes, &length))
472     return false;
473   value_.assign(bytes, bytes + length);
474   return true;
475 }
476
477 template <>
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);
484 }
485
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> >;
500
501 }  // namespace dbus