OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/dbus/shill_client_helper.h" | 5 #include "chromeos/dbus/shill_client_helper.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "dbus/message.h" | 9 #include "dbus/message.h" |
10 #include "dbus/object_proxy.h" | 10 #include "dbus/object_proxy.h" |
11 #include "dbus/values_util.h" | 11 #include "dbus/values_util.h" |
12 #include "third_party/cros_system_api/dbus/service_constants.h" | 12 #include "third_party/cros_system_api/dbus/service_constants.h" |
13 | 13 |
14 namespace chromeos { | 14 namespace chromeos { |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
18 const char kInvalidResponseErrorName[] = ""; // No error name. | 18 const char kInvalidResponseErrorName[] = ""; // No error name. |
19 const char kInvalidResponseErrorMessage[] = "Invalid response."; | 19 const char kInvalidResponseErrorMessage[] = "Invalid response."; |
20 | 20 |
21 } // namespace | 21 } // namespace |
22 | 22 |
23 ShillClientHelper::ShillClientHelper(dbus::Bus* bus, | 23 ShillClientHelper::ShillClientHelper(dbus::Bus* bus, |
24 dbus::ObjectProxy* proxy) | 24 dbus::ObjectProxy* proxy) |
25 : blocking_method_caller_(bus, proxy), | 25 : blocking_method_caller_(bus, proxy), |
26 proxy_(proxy), | 26 proxy_(proxy), |
| 27 in_progress_calls_(0), |
27 weak_ptr_factory_(this) { | 28 weak_ptr_factory_(this) { |
28 } | 29 } |
29 | 30 |
30 ShillClientHelper::~ShillClientHelper() { | 31 ShillClientHelper::~ShillClientHelper() { |
31 LOG_IF(ERROR, observer_list_.size() != 0u) | 32 LOG_IF(ERROR, observer_list_.size() != 0u) |
32 << "ShillClientHelper destroyed with active observers: " | 33 << "ShillClientHelper destroyed with active observers: " |
33 << observer_list_.size(); | 34 << observer_list_.size(); |
34 } | 35 } |
35 | 36 |
| 37 bool ShillClientHelper::IsObserved() const { |
| 38 return observer_list_.size() > 0; |
| 39 } |
| 40 |
| 41 bool ShillClientHelper::IsWaitingResponse() const { |
| 42 return in_progress_calls_ > 0; |
| 43 } |
| 44 |
36 void ShillClientHelper::AddPropertyChangedObserver( | 45 void ShillClientHelper::AddPropertyChangedObserver( |
37 ShillPropertyChangedObserver* observer) { | 46 ShillPropertyChangedObserver* observer) { |
| 47 // Excecutes all the pending MonitorPropertyChanged calls. |
| 48 for (std::vector<std::string>::iterator it = monitored_interfaces_.begin(); |
| 49 it != monitored_interfaces_.end(); ++it) { |
| 50 MonitorPropertyChangedInternal(*it); |
| 51 } |
| 52 monitored_interfaces_.clear(); |
| 53 |
38 observer_list_.AddObserver(observer); | 54 observer_list_.AddObserver(observer); |
39 } | 55 } |
40 | 56 |
41 void ShillClientHelper::RemovePropertyChangedObserver( | 57 void ShillClientHelper::RemovePropertyChangedObserver( |
42 ShillPropertyChangedObserver* observer) { | 58 ShillPropertyChangedObserver* observer) { |
43 observer_list_.RemoveObserver(observer); | 59 observer_list_.RemoveObserver(observer); |
44 } | 60 } |
45 | 61 |
46 void ShillClientHelper::MonitorPropertyChanged( | 62 void ShillClientHelper::MonitorPropertyChanged( |
47 const std::string& interface_name) { | 63 const std::string& interface_name) { |
| 64 if (observer_list_.size() > 0) |
| 65 // Effectively monitor the PropertyChanged now. |
| 66 MonitorPropertyChangedInternal(interface_name); |
| 67 else |
| 68 // Delay the ConnectToSignal until an observer is added. |
| 69 monitored_interfaces_.push_back(interface_name); |
| 70 } |
| 71 |
| 72 void ShillClientHelper::MonitorPropertyChangedInternal( |
| 73 const std::string& interface_name) { |
48 // We are not using dbus::PropertySet to monitor PropertyChanged signal | 74 // We are not using dbus::PropertySet to monitor PropertyChanged signal |
49 // because the interface is not "org.freedesktop.DBus.Properties". | 75 // because the interface is not "org.freedesktop.DBus.Properties". |
50 proxy_->ConnectToSignal(interface_name, | 76 proxy_->ConnectToSignal(interface_name, |
51 flimflam::kMonitorPropertyChanged, | 77 flimflam::kMonitorPropertyChanged, |
52 base::Bind(&ShillClientHelper::OnPropertyChanged, | 78 base::Bind(&ShillClientHelper::OnPropertyChanged, |
53 weak_ptr_factory_.GetWeakPtr()), | 79 weak_ptr_factory_.GetWeakPtr()), |
54 base::Bind(&ShillClientHelper::OnSignalConnected, | 80 base::Bind(&ShillClientHelper::OnSignalConnected, |
55 weak_ptr_factory_.GetWeakPtr())); | 81 weak_ptr_factory_.GetWeakPtr())); |
56 } | 82 } |
57 | 83 |
58 void ShillClientHelper::CallVoidMethod( | 84 void ShillClientHelper::CallVoidMethod( |
59 dbus::MethodCall* method_call, | 85 dbus::MethodCall* method_call, |
60 const VoidDBusMethodCallback& callback) { | 86 const VoidDBusMethodCallback& callback) { |
| 87 ++in_progress_calls_; |
61 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 88 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
62 base::Bind(&ShillClientHelper::OnVoidMethod, | 89 base::Bind(&ShillClientHelper::OnVoidMethod, |
63 weak_ptr_factory_.GetWeakPtr(), | 90 weak_ptr_factory_.GetWeakPtr(), |
64 callback)); | 91 callback)); |
65 } | 92 } |
66 | 93 |
67 void ShillClientHelper::CallObjectPathMethod( | 94 void ShillClientHelper::CallObjectPathMethod( |
68 dbus::MethodCall* method_call, | 95 dbus::MethodCall* method_call, |
69 const ObjectPathDBusMethodCallback& callback) { | 96 const ObjectPathDBusMethodCallback& callback) { |
| 97 ++in_progress_calls_; |
70 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 98 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
71 base::Bind(&ShillClientHelper::OnObjectPathMethod, | 99 base::Bind(&ShillClientHelper::OnObjectPathMethod, |
72 weak_ptr_factory_.GetWeakPtr(), | 100 weak_ptr_factory_.GetWeakPtr(), |
73 callback)); | 101 callback)); |
74 } | 102 } |
75 | 103 |
76 void ShillClientHelper::CallObjectPathMethodWithErrorCallback( | 104 void ShillClientHelper::CallObjectPathMethodWithErrorCallback( |
77 dbus::MethodCall* method_call, | 105 dbus::MethodCall* method_call, |
78 const ObjectPathCallback& callback, | 106 const ObjectPathCallback& callback, |
79 const ErrorCallback& error_callback) { | 107 const ErrorCallback& error_callback) { |
| 108 ++in_progress_calls_; |
80 proxy_->CallMethodWithErrorCallback( | 109 proxy_->CallMethodWithErrorCallback( |
81 method_call, | 110 method_call, |
82 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 111 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
83 base::Bind(&ShillClientHelper::OnObjectPathMethodWithoutStatus, | 112 base::Bind(&ShillClientHelper::OnObjectPathMethodWithoutStatus, |
84 weak_ptr_factory_.GetWeakPtr(), | 113 weak_ptr_factory_.GetWeakPtr(), |
85 callback, | 114 callback, |
86 error_callback), | 115 error_callback), |
87 base::Bind(&ShillClientHelper::OnError, | 116 base::Bind(&ShillClientHelper::OnError, |
88 weak_ptr_factory_.GetWeakPtr(), | 117 weak_ptr_factory_.GetWeakPtr(), |
89 error_callback)); | 118 error_callback)); |
90 } | 119 } |
91 | 120 |
92 void ShillClientHelper::CallDictionaryValueMethod( | 121 void ShillClientHelper::CallDictionaryValueMethod( |
93 dbus::MethodCall* method_call, | 122 dbus::MethodCall* method_call, |
94 const DictionaryValueCallback& callback) { | 123 const DictionaryValueCallback& callback) { |
| 124 ++in_progress_calls_; |
95 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 125 proxy_->CallMethod(method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
96 base::Bind(&ShillClientHelper::OnDictionaryValueMethod, | 126 base::Bind(&ShillClientHelper::OnDictionaryValueMethod, |
97 weak_ptr_factory_.GetWeakPtr(), | 127 weak_ptr_factory_.GetWeakPtr(), |
98 callback)); | 128 callback)); |
99 } | 129 } |
100 | 130 |
101 void ShillClientHelper::CallVoidMethodWithErrorCallback( | 131 void ShillClientHelper::CallVoidMethodWithErrorCallback( |
102 dbus::MethodCall* method_call, | 132 dbus::MethodCall* method_call, |
103 const base::Closure& callback, | 133 const base::Closure& callback, |
104 const ErrorCallback& error_callback) { | 134 const ErrorCallback& error_callback) { |
| 135 ++in_progress_calls_; |
105 proxy_->CallMethodWithErrorCallback( | 136 proxy_->CallMethodWithErrorCallback( |
106 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 137 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
107 base::Bind(&ShillClientHelper::OnVoidMethodWithErrorCallback, | 138 base::Bind(&ShillClientHelper::OnVoidMethodWithErrorCallback, |
108 weak_ptr_factory_.GetWeakPtr(), | 139 weak_ptr_factory_.GetWeakPtr(), |
109 callback), | 140 callback), |
110 base::Bind(&ShillClientHelper::OnError, | 141 base::Bind(&ShillClientHelper::OnError, |
111 weak_ptr_factory_.GetWeakPtr(), | 142 weak_ptr_factory_.GetWeakPtr(), |
112 error_callback)); | 143 error_callback)); |
113 } | 144 } |
114 | 145 |
115 void ShillClientHelper::CallDictionaryValueMethodWithErrorCallback( | 146 void ShillClientHelper::CallDictionaryValueMethodWithErrorCallback( |
116 dbus::MethodCall* method_call, | 147 dbus::MethodCall* method_call, |
117 const DictionaryValueCallbackWithoutStatus& callback, | 148 const DictionaryValueCallbackWithoutStatus& callback, |
118 const ErrorCallback& error_callback) { | 149 const ErrorCallback& error_callback) { |
| 150 ++in_progress_calls_; |
119 proxy_->CallMethodWithErrorCallback( | 151 proxy_->CallMethodWithErrorCallback( |
120 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 152 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
121 base::Bind( | 153 base::Bind( |
122 &ShillClientHelper::OnDictionaryValueMethodWithErrorCallback, | 154 &ShillClientHelper::OnDictionaryValueMethodWithErrorCallback, |
123 weak_ptr_factory_.GetWeakPtr(), | 155 weak_ptr_factory_.GetWeakPtr(), |
124 callback, | 156 callback, |
125 error_callback), | 157 error_callback), |
126 base::Bind(&ShillClientHelper::OnError, | 158 base::Bind(&ShillClientHelper::OnError, |
127 weak_ptr_factory_.GetWeakPtr(), | 159 weak_ptr_factory_.GetWeakPtr(), |
128 error_callback)); | 160 error_callback)); |
129 } | 161 } |
130 | 162 |
131 void ShillClientHelper::CallListValueMethodWithErrorCallback( | 163 void ShillClientHelper::CallListValueMethodWithErrorCallback( |
132 dbus::MethodCall* method_call, | 164 dbus::MethodCall* method_call, |
133 const ListValueCallback& callback, | 165 const ListValueCallback& callback, |
134 const ErrorCallback& error_callback) { | 166 const ErrorCallback& error_callback) { |
| 167 ++in_progress_calls_; |
135 proxy_->CallMethodWithErrorCallback( | 168 proxy_->CallMethodWithErrorCallback( |
136 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 169 method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
137 base::Bind( | 170 base::Bind( |
138 &ShillClientHelper::OnListValueMethodWithErrorCallback, | 171 &ShillClientHelper::OnListValueMethodWithErrorCallback, |
139 weak_ptr_factory_.GetWeakPtr(), | 172 weak_ptr_factory_.GetWeakPtr(), |
140 callback, | 173 callback, |
141 error_callback), | 174 error_callback), |
142 base::Bind(&ShillClientHelper::OnError, | 175 base::Bind(&ShillClientHelper::OnError, |
143 weak_ptr_factory_.GetWeakPtr(), | 176 weak_ptr_factory_.GetWeakPtr(), |
144 error_callback)); | 177 error_callback)); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); | 263 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); |
231 if (!value.get()) | 264 if (!value.get()) |
232 return; | 265 return; |
233 | 266 |
234 FOR_EACH_OBSERVER(ShillPropertyChangedObserver, observer_list_, | 267 FOR_EACH_OBSERVER(ShillPropertyChangedObserver, observer_list_, |
235 OnPropertyChanged(name, *value)); | 268 OnPropertyChanged(name, *value)); |
236 } | 269 } |
237 | 270 |
238 void ShillClientHelper::OnVoidMethod(const VoidDBusMethodCallback& callback, | 271 void ShillClientHelper::OnVoidMethod(const VoidDBusMethodCallback& callback, |
239 dbus::Response* response) { | 272 dbus::Response* response) { |
| 273 --in_progress_calls_; |
240 if (!response) { | 274 if (!response) { |
241 callback.Run(DBUS_METHOD_CALL_FAILURE); | 275 callback.Run(DBUS_METHOD_CALL_FAILURE); |
242 return; | 276 return; |
243 } | 277 } |
244 callback.Run(DBUS_METHOD_CALL_SUCCESS); | 278 callback.Run(DBUS_METHOD_CALL_SUCCESS); |
245 } | 279 } |
246 | 280 |
247 void ShillClientHelper::OnObjectPathMethod( | 281 void ShillClientHelper::OnObjectPathMethod( |
248 const ObjectPathDBusMethodCallback& callback, | 282 const ObjectPathDBusMethodCallback& callback, |
249 dbus::Response* response) { | 283 dbus::Response* response) { |
| 284 --in_progress_calls_; |
250 if (!response) { | 285 if (!response) { |
251 callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath()); | 286 callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath()); |
252 return; | 287 return; |
253 } | 288 } |
254 dbus::MessageReader reader(response); | 289 dbus::MessageReader reader(response); |
255 dbus::ObjectPath result; | 290 dbus::ObjectPath result; |
256 if (!reader.PopObjectPath(&result)) { | 291 if (!reader.PopObjectPath(&result)) { |
257 callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath()); | 292 callback.Run(DBUS_METHOD_CALL_FAILURE, dbus::ObjectPath()); |
258 return; | 293 return; |
259 } | 294 } |
260 callback.Run(DBUS_METHOD_CALL_SUCCESS, result); | 295 callback.Run(DBUS_METHOD_CALL_SUCCESS, result); |
261 } | 296 } |
262 | 297 |
263 void ShillClientHelper::OnObjectPathMethodWithoutStatus( | 298 void ShillClientHelper::OnObjectPathMethodWithoutStatus( |
264 const ObjectPathCallback& callback, | 299 const ObjectPathCallback& callback, |
265 const ErrorCallback& error_callback, | 300 const ErrorCallback& error_callback, |
266 dbus::Response* response) { | 301 dbus::Response* response) { |
| 302 --in_progress_calls_; |
267 if (!response) { | 303 if (!response) { |
268 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); | 304 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
269 return; | 305 return; |
270 } | 306 } |
271 dbus::MessageReader reader(response); | 307 dbus::MessageReader reader(response); |
272 dbus::ObjectPath result; | 308 dbus::ObjectPath result; |
273 if (!reader.PopObjectPath(&result)) { | 309 if (!reader.PopObjectPath(&result)) { |
274 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); | 310 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
275 return; | 311 return; |
276 } | 312 } |
277 callback.Run(result); | 313 callback.Run(result); |
278 } | 314 } |
279 | 315 |
280 void ShillClientHelper::OnDictionaryValueMethod( | 316 void ShillClientHelper::OnDictionaryValueMethod( |
281 const DictionaryValueCallback& callback, | 317 const DictionaryValueCallback& callback, |
282 dbus::Response* response) { | 318 dbus::Response* response) { |
| 319 --in_progress_calls_; |
283 if (!response) { | 320 if (!response) { |
284 base::DictionaryValue result; | 321 base::DictionaryValue result; |
285 callback.Run(DBUS_METHOD_CALL_FAILURE, result); | 322 callback.Run(DBUS_METHOD_CALL_FAILURE, result); |
286 return; | 323 return; |
287 } | 324 } |
288 dbus::MessageReader reader(response); | 325 dbus::MessageReader reader(response); |
289 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); | 326 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); |
290 base::DictionaryValue* result = NULL; | 327 base::DictionaryValue* result = NULL; |
291 if (!value.get() || !value->GetAsDictionary(&result)) { | 328 if (!value.get() || !value->GetAsDictionary(&result)) { |
292 base::DictionaryValue result; | 329 base::DictionaryValue result; |
293 callback.Run(DBUS_METHOD_CALL_FAILURE, result); | 330 callback.Run(DBUS_METHOD_CALL_FAILURE, result); |
294 return; | 331 return; |
295 } | 332 } |
296 callback.Run(DBUS_METHOD_CALL_SUCCESS, *result); | 333 callback.Run(DBUS_METHOD_CALL_SUCCESS, *result); |
297 } | 334 } |
298 | 335 |
299 void ShillClientHelper::OnVoidMethodWithErrorCallback( | 336 void ShillClientHelper::OnVoidMethodWithErrorCallback( |
300 const base::Closure& callback, | 337 const base::Closure& callback, |
301 dbus::Response* response) { | 338 dbus::Response* response) { |
| 339 --in_progress_calls_; |
302 callback.Run(); | 340 callback.Run(); |
303 } | 341 } |
304 | 342 |
305 void ShillClientHelper::OnDictionaryValueMethodWithErrorCallback( | 343 void ShillClientHelper::OnDictionaryValueMethodWithErrorCallback( |
306 const DictionaryValueCallbackWithoutStatus& callback, | 344 const DictionaryValueCallbackWithoutStatus& callback, |
307 const ErrorCallback& error_callback, | 345 const ErrorCallback& error_callback, |
308 dbus::Response* response) { | 346 dbus::Response* response) { |
| 347 --in_progress_calls_; |
309 dbus::MessageReader reader(response); | 348 dbus::MessageReader reader(response); |
310 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); | 349 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); |
311 base::DictionaryValue* result = NULL; | 350 base::DictionaryValue* result = NULL; |
312 if (!value.get() || !value->GetAsDictionary(&result)) { | 351 if (!value.get() || !value->GetAsDictionary(&result)) { |
313 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); | 352 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
314 return; | 353 return; |
315 } | 354 } |
316 callback.Run(*result); | 355 callback.Run(*result); |
317 } | 356 } |
318 | 357 |
319 void ShillClientHelper::OnListValueMethodWithErrorCallback( | 358 void ShillClientHelper::OnListValueMethodWithErrorCallback( |
320 const ListValueCallback& callback, | 359 const ListValueCallback& callback, |
321 const ErrorCallback& error_callback, | 360 const ErrorCallback& error_callback, |
322 dbus::Response* response) { | 361 dbus::Response* response) { |
| 362 --in_progress_calls_; |
323 dbus::MessageReader reader(response); | 363 dbus::MessageReader reader(response); |
324 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); | 364 scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader)); |
325 base::ListValue* result = NULL; | 365 base::ListValue* result = NULL; |
326 if (!value.get() || !value->GetAsList(&result)) { | 366 if (!value.get() || !value->GetAsList(&result)) { |
327 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); | 367 error_callback.Run(kInvalidResponseErrorName, kInvalidResponseErrorMessage); |
328 return; | 368 return; |
329 } | 369 } |
330 callback.Run(*result); | 370 callback.Run(*result); |
331 } | 371 } |
332 | 372 |
333 void ShillClientHelper::OnError(const ErrorCallback& error_callback, | 373 void ShillClientHelper::OnError(const ErrorCallback& error_callback, |
334 dbus::ErrorResponse* response) { | 374 dbus::ErrorResponse* response) { |
| 375 --in_progress_calls_; |
335 std::string error_name; | 376 std::string error_name; |
336 std::string error_message; | 377 std::string error_message; |
337 if (response) { | 378 if (response) { |
338 // Error message may contain the error message as string. | 379 // Error message may contain the error message as string. |
339 dbus::MessageReader reader(response); | 380 dbus::MessageReader reader(response); |
340 error_name = response->GetErrorName(); | 381 error_name = response->GetErrorName(); |
341 reader.PopString(&error_message); | 382 reader.PopString(&error_message); |
342 } | 383 } |
343 error_callback.Run(error_name, error_message); | 384 error_callback.Run(error_name, error_message); |
344 } | 385 } |
345 | 386 |
346 } // namespace chromeos | 387 } // namespace chromeos |
OLD | NEW |