Fix a type mismatch on Windows caused by r201738.
[chromium-blink-merge.git] / chromeos / dbus / shill_client_helper.cc
blobed9c994c6d604ed5a0a9d7e550b9254713ecd64a
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 "chromeos/dbus/shill_client_helper.h"
7 #include "base/bind.h"
8 #include "base/values.h"
9 #include "chromeos/dbus/blocking_method_caller.h"
10 #include "dbus/message.h"
11 #include "dbus/object_proxy.h"
12 #include "dbus/values_util.h"
13 #include "third_party/cros_system_api/dbus/service_constants.h"
15 namespace chromeos {
17 namespace {
19 const char kInvalidResponseErrorName[] = ""; // No error name.
20 const char kInvalidResponseErrorMessage[] = "Invalid response.";
22 void OnBooleanMethodWithErrorCallback(
23 const ShillClientHelper::BooleanCallback& callback,
24 const ShillClientHelper::ErrorCallback& error_callback,
25 dbus::Response* response) {
26 if (!response) {
27 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
28 return;
30 dbus::MessageReader reader(response);
31 bool result;
32 if (!reader.PopBool(&result)) {
33 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
34 return;
36 callback.Run(result);
39 void OnStringMethodWithErrorCallback(
40 const ShillClientHelper::StringCallback& callback,
41 const ShillClientHelper::ErrorCallback& error_callback,
42 dbus::Response* response) {
43 if (!response) {
44 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
45 return;
47 dbus::MessageReader reader(response);
48 std::string result;
49 if (!reader.PopString(&result)) {
50 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
51 return;
53 callback.Run(result);
56 // Handles responses for methods without results.
57 void OnVoidMethod(const VoidDBusMethodCallback& callback,
58 dbus::Response* response) {
59 if (!response) {
60 callback.Run(DBUS_METHOD_CALL_FAILURE);
61 return;
63 callback.Run(DBUS_METHOD_CALL_SUCCESS);
66 // Handles responses for methods with ObjectPath results.
67 void OnObjectPathMethod(
68 const ObjectPathDBusMethodCallback& callback,
69 dbus::Response* response) {
70 if (!response) {
71 callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath());
72 return;
74 dbus::MessageReader reader(response);
75 dbus::ObjectPath result;
76 if (!reader.PopObjectPath(&result)) {
77 callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath());
78 return;
80 callback.Run(DBUS_METHOD_CALL_SUCCESS, result);
83 // Handles responses for methods with ObjectPath results and no status.
84 void OnObjectPathMethodWithoutStatus(
85 const ObjectPathCallback& callback,
86 const ShillClientHelper::ErrorCallback& error_callback,
87 dbus::Response* response) {
88 if (!response) {
89 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
90 return;
92 dbus::MessageReader reader(response);
93 dbus::ObjectPath result;
94 if (!reader.PopObjectPath(&result)) {
95 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
96 return;
98 callback.Run(result);
101 // Handles responses for methods with DictionaryValue results.
102 void OnDictionaryValueMethod(
103 const ShillClientHelper::DictionaryValueCallback& callback,
104 dbus::Response* response) {
105 if (!response) {
106 base::DictionaryValue result;
107 callback.Run(DBUS_METHOD_CALL_FAILURE, result);
108 return;
110 dbus::MessageReader reader(response);
111 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
112 base::DictionaryValue* result = NULL;
113 if (!value.get() || !value->GetAsDictionary(&result)) {
114 base::DictionaryValue result;
115 callback.Run(DBUS_METHOD_CALL_FAILURE, result);
116 return;
118 callback.Run(DBUS_METHOD_CALL_SUCCESS, *result);
121 // Handles responses for methods without results.
122 void OnVoidMethodWithErrorCallback(
123 const base::Closure& callback,
124 dbus::Response* response) {
125 callback.Run();
128 // Handles responses for methods with DictionaryValue results.
129 // Used by CallDictionaryValueMethodWithErrorCallback().
130 void OnDictionaryValueMethodWithErrorCallback(
131 const ShillClientHelper::DictionaryValueCallbackWithoutStatus& callback,
132 const ShillClientHelper::ErrorCallback& error_callback,
133 dbus::Response* response) {
134 dbus::MessageReader reader(response);
135 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
136 base::DictionaryValue* result = NULL;
137 if (!value.get() || !value->GetAsDictionary(&result)) {
138 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
139 return;
141 callback.Run(*result);
144 // Handles responses for methods with ListValue results.
145 void OnListValueMethodWithErrorCallback(
146 const ShillClientHelper::ListValueCallback& callback,
147 const ShillClientHelper::ErrorCallback& error_callback,
148 dbus::Response* response) {
149 dbus::MessageReader reader(response);
150 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
151 base::ListValue* result = NULL;
152 if (!value.get() || !value->GetAsList(&result)) {
153 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage);
154 return;
156 callback.Run(*result);
159 // Handles running appropriate error callbacks.
160 void OnError(const ShillClientHelper::ErrorCallback& error_callback,
161 dbus::ErrorResponse* response) {
162 std::string error_name;
163 std::string error_message;
164 if (response) {
165 // Error message may contain the error message as string.
166 dbus::MessageReader reader(response);
167 error_name = response->GetErrorName();
168 reader.PopString(&error_message);
170 error_callback.Run(error_name, error_message);
173 } // namespace
175 ShillClientHelper::ShillClientHelper(dbus::Bus* bus,
176 dbus::ObjectProxy* proxy)
177 : blocking_method_caller_(new BlockingMethodCaller(bus, proxy)),
178 proxy_(proxy),
179 weak_ptr_factory_(this) {
182 ShillClientHelper::~ShillClientHelper() {
183 LOG_IF(ERROR, observer_list_.size() != 0u)
184 << "ShillClientHelper destroyed with active observers: "
185 << observer_list_.size();
188 void ShillClientHelper::AddPropertyChangedObserver(
189 ShillPropertyChangedObserver* observer) {
190 // Excecute all the pending MonitorPropertyChanged calls.
191 for (size_t i = 0; i < interfaces_to_be_monitored_.size(); ++i) {
192 MonitorPropertyChangedInternal(interfaces_to_be_monitored_[i]);
194 interfaces_to_be_monitored_.clear();
196 observer_list_.AddObserver(observer);
199 void ShillClientHelper::RemovePropertyChangedObserver(
200 ShillPropertyChangedObserver* observer) {
201 observer_list_.RemoveObserver(observer);
204 void ShillClientHelper::MonitorPropertyChanged(
205 const std::string& interface_name) {
206 if (observer_list_.size() > 0) {
207 // Effectively monitor the PropertyChanged now.
208 MonitorPropertyChangedInternal(interface_name);
209 } else {
210 // Delay the ConnectToSignal until an observer is added.
211 interfaces_to_be_monitored_.push_back(interface_name);
215 void ShillClientHelper::MonitorPropertyChangedInternal(
216 const std::string& interface_name) {
217 // We are not using dbus::PropertySet to monitor PropertyChanged signal
218 // because the interface is not "org.freedesktop.DBus.Properties".
219 proxy_->ConnectToSignal(interface_name,
220 flimflam::kMonitorPropertyChanged,
221 base::Bind(&ShillClientHelper::OnPropertyChanged,
222 weak_ptr_factory_.GetWeakPtr()),
223 base::Bind(&ShillClientHelper::OnSignalConnected,
224 weak_ptr_factory_.GetWeakPtr()));
227 void ShillClientHelper::CallVoidMethod(
228 dbus::MethodCall* method_call,
229 const VoidDBusMethodCallback& callback) {
230 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
231 base::Bind(&OnVoidMethod,
232 callback));
235 void ShillClientHelper::CallObjectPathMethod(
236 dbus::MethodCall* method_call,
237 const ObjectPathDBusMethodCallback& callback) {
238 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
239 base::Bind(&OnObjectPathMethod,
240 callback));
243 void ShillClientHelper::CallObjectPathMethodWithErrorCallback(
244 dbus::MethodCall* method_call,
245 const ObjectPathCallback& callback,
246 const ErrorCallback& error_callback) {
247 proxy_->CallMethodWithErrorCallback(
248 method_call,
249 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
250 base::Bind(&OnObjectPathMethodWithoutStatus,
251 callback,
252 error_callback),
253 base::Bind(&OnError,
254 error_callback));
257 void ShillClientHelper::CallDictionaryValueMethod(
258 dbus::MethodCall* method_call,
259 const DictionaryValueCallback& callback) {
260 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
261 base::Bind(&OnDictionaryValueMethod,
262 callback));
265 void ShillClientHelper::CallVoidMethodWithErrorCallback(
266 dbus::MethodCall* method_call,
267 const base::Closure& callback,
268 const ErrorCallback& error_callback) {
269 proxy_->CallMethodWithErrorCallback(
270 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
271 base::Bind(&OnVoidMethodWithErrorCallback,
272 callback),
273 base::Bind(&OnError,
274 error_callback));
277 void ShillClientHelper::CallBooleanMethodWithErrorCallback(
278 dbus::MethodCall* method_call,
279 const BooleanCallback& callback,
280 const ErrorCallback& error_callback) {
281 proxy_->CallMethodWithErrorCallback(
282 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
283 base::Bind(&OnBooleanMethodWithErrorCallback,
284 callback,
285 error_callback),
286 base::Bind(&OnError,
287 error_callback));
290 void ShillClientHelper::CallStringMethodWithErrorCallback(
291 dbus::MethodCall* method_call,
292 const StringCallback& callback,
293 const ErrorCallback& error_callback) {
294 proxy_->CallMethodWithErrorCallback(
295 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
296 base::Bind(&OnStringMethodWithErrorCallback,
297 callback,
298 error_callback),
299 base::Bind(&OnError,
300 error_callback));
303 void ShillClientHelper::CallDictionaryValueMethodWithErrorCallback(
304 dbus::MethodCall* method_call,
305 const DictionaryValueCallbackWithoutStatus& callback,
306 const ErrorCallback& error_callback) {
307 proxy_->CallMethodWithErrorCallback(
308 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
309 base::Bind(
310 &OnDictionaryValueMethodWithErrorCallback,
311 callback,
312 error_callback),
313 base::Bind(&OnError,
314 error_callback));
317 void ShillClientHelper::CallListValueMethodWithErrorCallback(
318 dbus::MethodCall* method_call,
319 const ListValueCallback& callback,
320 const ErrorCallback& error_callback) {
321 proxy_->CallMethodWithErrorCallback(
322 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
323 base::Bind(
324 &OnListValueMethodWithErrorCallback,
325 callback,
326 error_callback),
327 base::Bind(&OnError,
328 error_callback));
331 bool ShillClientHelper::CallVoidMethodAndBlock(
332 dbus::MethodCall* method_call) {
333 scoped_ptr<dbus::Response> response(
334 blocking_method_caller_->CallMethodAndBlock(method_call));
335 if (!response.get())
336 return false;
337 return true;
340 base::DictionaryValue* ShillClientHelper::CallDictionaryValueMethodAndBlock(
341 dbus::MethodCall* method_call) {
342 scoped_ptr<dbus::Response> response(
343 blocking_method_caller_->CallMethodAndBlock(method_call));
344 if (!response.get())
345 return NULL;
347 dbus::MessageReader reader(response.get());
348 base::Value* value = dbus::PopDataAsValue(&reader);
349 base::DictionaryValue* result = NULL;
350 if (!value || !value->GetAsDictionary(&result)) {
351 delete value;
352 return NULL;
354 return result;
357 // static
358 void ShillClientHelper::AppendValueDataAsVariant(dbus::MessageWriter* writer,
359 const base::Value& value) {
360 // Support basic types and string-to-string dictionary.
361 switch (value.GetType()) {
362 case base::Value::TYPE_DICTIONARY: {
363 const base::DictionaryValue* dictionary = NULL;
364 value.GetAsDictionary(&dictionary);
365 dbus::MessageWriter variant_writer(NULL);
366 writer->OpenVariant("a{ss}", &variant_writer);
367 dbus::MessageWriter array_writer(NULL);
368 variant_writer.OpenArray("{ss}", &array_writer);
369 for (base::DictionaryValue::Iterator it(*dictionary);
370 !it.IsAtEnd();
371 it.Advance()) {
372 dbus::MessageWriter entry_writer(NULL);
373 array_writer.OpenDictEntry(&entry_writer);
374 entry_writer.AppendString(it.key());
375 const base::Value& value = it.value();
376 std::string value_string;
377 DLOG_IF(ERROR, value.GetType() != base::Value::TYPE_STRING)
378 << "Unexpected type " << value.GetType();
379 value.GetAsString(&value_string);
380 entry_writer.AppendString(value_string);
381 array_writer.CloseContainer(&entry_writer);
383 variant_writer.CloseContainer(&array_writer);
384 writer->CloseContainer(&variant_writer);
385 break;
387 case base::Value::TYPE_BOOLEAN:
388 case base::Value::TYPE_INTEGER:
389 case base::Value::TYPE_DOUBLE:
390 case base::Value::TYPE_STRING:
391 dbus::AppendBasicTypeValueDataAsVariant(writer, value);
392 break;
393 default:
394 DLOG(ERROR) << "Unexpected type " << value.GetType();
399 void ShillClientHelper::OnSignalConnected(const std::string& interface,
400 const std::string& signal,
401 bool success) {
402 LOG_IF(ERROR, !success) << "Connect to " << interface << " " << signal
403 << " failed.";
406 void ShillClientHelper::OnPropertyChanged(dbus::Signal* signal) {
407 if (!observer_list_.might_have_observers())
408 return;
410 dbus::MessageReader reader(signal);
411 std::string name;
412 if (!reader.PopString(&name))
413 return;
414 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
415 if (!value.get())
416 return;
418 FOR_EACH_OBSERVER(ShillPropertyChangedObserver, observer_list_,
419 OnPropertyChanged(name, *value));
423 } // namespace chromeos