1 // Copyright 2013 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/network/network_device_handler_impl.h"
8 #include "base/location.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/time/time.h"
11 #include "base/values.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/shill_device_client.h"
14 #include "chromeos/dbus/shill_ipconfig_client.h"
15 #include "chromeos/network/device_state.h"
16 #include "chromeos/network/network_event_log.h"
17 #include "chromeos/network/network_handler_callbacks.h"
18 #include "chromeos/network/network_state_handler.h"
19 #include "dbus/object_path.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
26 std::string
GetErrorNameForShillError(const std::string
& shill_error_name
) {
27 if (shill_error_name
== shill::kErrorResultFailure
)
28 return NetworkDeviceHandler::kErrorFailure
;
29 if (shill_error_name
== shill::kErrorResultNotSupported
)
30 return NetworkDeviceHandler::kErrorNotSupported
;
31 if (shill_error_name
== shill::kErrorResultIncorrectPin
)
32 return NetworkDeviceHandler::kErrorIncorrectPin
;
33 if (shill_error_name
== shill::kErrorResultPinBlocked
)
34 return NetworkDeviceHandler::kErrorPinBlocked
;
35 if (shill_error_name
== shill::kErrorResultPinRequired
)
36 return NetworkDeviceHandler::kErrorPinRequired
;
37 if (shill_error_name
== shill::kErrorResultNotFound
)
38 return NetworkDeviceHandler::kErrorDeviceMissing
;
39 return NetworkDeviceHandler::kErrorUnknown
;
42 void InvokeErrorCallback(const std::string
& service_path
,
43 const network_handler::ErrorCallback
& error_callback
,
44 const std::string
& error_name
) {
45 std::string error_msg
= "Device Error: " + error_name
;
46 NET_LOG_ERROR(error_msg
, service_path
);
47 network_handler::RunErrorCallback(
48 error_callback
, service_path
, error_name
, error_msg
);
51 void HandleShillCallFailure(
52 const std::string
& device_path
,
53 const network_handler::ErrorCallback
& error_callback
,
54 const std::string
& shill_error_name
,
55 const std::string
& shill_error_message
) {
56 network_handler::ShillErrorCallbackFunction(
57 GetErrorNameForShillError(shill_error_name
),
64 void IPConfigRefreshCallback(const std::string
& ipconfig_path
,
65 DBusMethodCallStatus call_status
) {
66 if (call_status
!= DBUS_METHOD_CALL_SUCCESS
) {
68 base::StringPrintf("IPConfigs.Refresh Failed: %d", call_status
),
71 NET_LOG_EVENT("IPConfigs.Refresh Succeeded", ipconfig_path
);
75 void RefreshIPConfigsCallback(
76 const base::Closure
& callback
,
77 const network_handler::ErrorCallback
& error_callback
,
78 const std::string
& device_path
,
79 const base::DictionaryValue
& properties
) {
80 const base::ListValue
* ip_configs
;
81 if (!properties
.GetListWithoutPathExpansion(
82 shill::kIPConfigsProperty
, &ip_configs
)) {
83 NET_LOG_ERROR("RequestRefreshIPConfigs Failed", device_path
);
84 network_handler::ShillErrorCallbackFunction(
85 "RequestRefreshIPConfigs Failed",
88 std::string("Missing ") + shill::kIPConfigsProperty
, "");
92 for (size_t i
= 0; i
< ip_configs
->GetSize(); i
++) {
93 std::string ipconfig_path
;
94 if (!ip_configs
->GetString(i
, &ipconfig_path
))
96 DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
97 dbus::ObjectPath(ipconfig_path
),
98 base::Bind(&IPConfigRefreshCallback
, ipconfig_path
));
100 // It is safe to invoke |callback| here instead of waiting for the
101 // IPConfig.Refresh callbacks to complete because the Refresh DBus calls will
102 // be executed in order and thus before any further DBus requests that
103 // |callback| may issue.
104 if (!callback
.is_null())
108 void ProposeScanCallback(
109 const std::string
& device_path
,
110 const base::Closure
& callback
,
111 const network_handler::ErrorCallback
& error_callback
,
112 DBusMethodCallStatus call_status
) {
113 if (call_status
!= DBUS_METHOD_CALL_SUCCESS
) {
114 network_handler::ShillErrorCallbackFunction(
115 "Device.ProposeScan Failed",
118 base::StringPrintf("DBus call failed: %d", call_status
), "");
121 NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path
);
122 if (!callback
.is_null())
126 void SetDevicePropertyInternal(
127 const std::string
& device_path
,
128 const std::string
& property_name
,
129 const base::Value
& value
,
130 const base::Closure
& callback
,
131 const network_handler::ErrorCallback
& error_callback
) {
132 DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
133 dbus::ObjectPath(device_path
),
137 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
140 // Struct containing TDLS Operation parameters.
141 struct TDLSOperationParams
{
142 TDLSOperationParams() : retry_count(0) {}
143 std::string operation
;
144 std::string ip_or_mac_address
;
148 // Forward declare for PostDelayedTask.
149 void CallPerformTDLSOperation(
150 const std::string
& device_path
,
151 const TDLSOperationParams
& params
,
152 const network_handler::StringResultCallback
& callback
,
153 const network_handler::ErrorCallback
& error_callback
);
155 void TDLSSuccessCallback(
156 const std::string
& device_path
,
157 const TDLSOperationParams
& params
,
158 const network_handler::StringResultCallback
& callback
,
159 const network_handler::ErrorCallback
& error_callback
,
160 const std::string
& result
) {
161 std::string event_desc
= "TDLSSuccessCallback: " + params
.operation
;
163 event_desc
+= ": " + result
;
164 NET_LOG_EVENT(event_desc
, device_path
);
165 if (params
.operation
!= shill::kTDLSSetupOperation
) {
166 if (!callback
.is_null())
167 callback
.Run(result
);
172 NET_LOG_ERROR("Unexpected TDLS result: " + result
, device_path
);
174 // Send a delayed Status request after a successful Setup call.
175 TDLSOperationParams status_params
;
176 status_params
.operation
= shill::kTDLSStatusOperation
;
177 status_params
.ip_or_mac_address
= params
.ip_or_mac_address
;
179 const int64 kRequestStatusDelayMs
= 500;
180 base::TimeDelta request_delay
;
181 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
182 request_delay
= base::TimeDelta::FromMilliseconds(kRequestStatusDelayMs
);
184 base::MessageLoopProxy::current()->PostDelayedTask(
186 base::Bind(&CallPerformTDLSOperation
,
187 device_path
, status_params
, callback
, error_callback
),
191 void TDLSErrorCallback(
192 const std::string
& device_path
,
193 const TDLSOperationParams
& params
,
194 const network_handler::StringResultCallback
& callback
,
195 const network_handler::ErrorCallback
& error_callback
,
196 const std::string
& dbus_error_name
,
197 const std::string
& dbus_error_message
) {
198 // If a Setup operation receives an InProgress error, retry.
199 const int kMaxRetries
= 5;
200 if (params
.operation
== shill::kTDLSSetupOperation
&&
201 dbus_error_name
== shill::kErrorResultInProgress
&&
202 params
.retry_count
< kMaxRetries
) {
203 TDLSOperationParams retry_params
= params
;
204 ++retry_params
.retry_count
;
205 NET_LOG_EVENT(base::StringPrintf("TDLS Retry: %d", params
.retry_count
),
207 const int64 kReRequestDelayMs
= 1000;
208 base::TimeDelta request_delay
;
209 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
210 request_delay
= base::TimeDelta::FromMilliseconds(kReRequestDelayMs
);
212 base::MessageLoopProxy::current()->PostDelayedTask(
214 base::Bind(&CallPerformTDLSOperation
,
215 device_path
, retry_params
, callback
, error_callback
),
220 NET_LOG_ERROR("TDLS Error:" + dbus_error_name
+ ":" + dbus_error_message
,
222 if (error_callback
.is_null())
225 const std::string error_name
=
226 dbus_error_name
== shill::kErrorResultInProgress
?
227 NetworkDeviceHandler::kErrorTimeout
: NetworkDeviceHandler::kErrorUnknown
;
228 const std::string
& error_detail
= params
.ip_or_mac_address
;
229 scoped_ptr
<base::DictionaryValue
> error_data(
230 network_handler::CreateDBusErrorData(
231 device_path
, error_name
, error_detail
,
232 dbus_error_name
, dbus_error_message
));
233 error_callback
.Run(error_name
, error_data
.Pass());
236 void CallPerformTDLSOperation(
237 const std::string
& device_path
,
238 const TDLSOperationParams
& params
,
239 const network_handler::StringResultCallback
& callback
,
240 const network_handler::ErrorCallback
& error_callback
) {
241 NET_LOG_EVENT("CallPerformTDLSOperation: " + params
.operation
, device_path
);
242 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
243 dbus::ObjectPath(device_path
),
245 params
.ip_or_mac_address
,
246 base::Bind(&TDLSSuccessCallback
,
247 device_path
, params
, callback
, error_callback
),
248 base::Bind(&TDLSErrorCallback
,
249 device_path
, params
, callback
, error_callback
));
254 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
255 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
258 void NetworkDeviceHandlerImpl::GetDeviceProperties(
259 const std::string
& device_path
,
260 const network_handler::DictionaryResultCallback
& callback
,
261 const network_handler::ErrorCallback
& error_callback
) const {
262 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
263 dbus::ObjectPath(device_path
),
264 base::Bind(&network_handler::GetPropertiesCallback
,
265 callback
, error_callback
, device_path
));
268 void NetworkDeviceHandlerImpl::SetDeviceProperty(
269 const std::string
& device_path
,
270 const std::string
& property_name
,
271 const base::Value
& value
,
272 const base::Closure
& callback
,
273 const network_handler::ErrorCallback
& error_callback
) {
274 const char* const property_blacklist
[] = {
275 // Must only be changed by policy/owner through.
276 shill::kCellularAllowRoamingProperty
279 for (size_t i
= 0; i
< arraysize(property_blacklist
); ++i
) {
280 if (property_name
== property_blacklist
[i
]) {
284 "SetDeviceProperty called on blacklisted property " + property_name
);
289 SetDevicePropertyInternal(
290 device_path
, property_name
, value
, callback
, error_callback
);
293 void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
294 const std::string
& device_path
,
295 const base::Closure
& callback
,
296 const network_handler::ErrorCallback
& error_callback
) {
297 GetDeviceProperties(device_path
,
298 base::Bind(&RefreshIPConfigsCallback
,
299 callback
, error_callback
),
303 void NetworkDeviceHandlerImpl::ProposeScan(
304 const std::string
& device_path
,
305 const base::Closure
& callback
,
306 const network_handler::ErrorCallback
& error_callback
) {
307 DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
308 dbus::ObjectPath(device_path
),
309 base::Bind(&ProposeScanCallback
, device_path
, callback
, error_callback
));
312 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
313 const std::string
& device_path
,
314 const std::string
& network_id
,
315 const base::Closure
& callback
,
316 const network_handler::ErrorCallback
& error_callback
) {
317 DBusThreadManager::Get()->GetShillDeviceClient()->Register(
318 dbus::ObjectPath(device_path
),
321 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
324 void NetworkDeviceHandlerImpl::SetCarrier(
325 const std::string
& device_path
,
326 const std::string
& carrier
,
327 const base::Closure
& callback
,
328 const network_handler::ErrorCallback
& error_callback
) {
329 DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
330 dbus::ObjectPath(device_path
),
333 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
336 void NetworkDeviceHandlerImpl::RequirePin(
337 const std::string
& device_path
,
339 const std::string
& pin
,
340 const base::Closure
& callback
,
341 const network_handler::ErrorCallback
& error_callback
) {
342 DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
343 dbus::ObjectPath(device_path
),
347 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
350 void NetworkDeviceHandlerImpl::EnterPin(
351 const std::string
& device_path
,
352 const std::string
& pin
,
353 const base::Closure
& callback
,
354 const network_handler::ErrorCallback
& error_callback
) {
355 DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
356 dbus::ObjectPath(device_path
),
359 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
362 void NetworkDeviceHandlerImpl::UnblockPin(
363 const std::string
& device_path
,
364 const std::string
& puk
,
365 const std::string
& new_pin
,
366 const base::Closure
& callback
,
367 const network_handler::ErrorCallback
& error_callback
) {
368 DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
369 dbus::ObjectPath(device_path
),
373 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
376 void NetworkDeviceHandlerImpl::ChangePin(
377 const std::string
& device_path
,
378 const std::string
& old_pin
,
379 const std::string
& new_pin
,
380 const base::Closure
& callback
,
381 const network_handler::ErrorCallback
& error_callback
) {
382 DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
383 dbus::ObjectPath(device_path
),
387 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
390 void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
391 const bool allow_roaming
) {
392 cellular_allow_roaming_
= allow_roaming
;
393 ApplyCellularAllowRoamingToShill();
396 void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
397 const std::string
& ip_or_mac_address
,
399 const network_handler::StringResultCallback
& callback
,
400 const network_handler::ErrorCallback
& error_callback
) {
401 const DeviceState
* device_state
=
402 network_state_handler_
->GetDeviceStateByType(NetworkTypePattern::WiFi());
404 if (error_callback
.is_null())
406 scoped_ptr
<base::DictionaryValue
> error_data(new base::DictionaryValue
);
407 error_data
->SetString(network_handler::kErrorName
, kErrorDeviceMissing
);
408 error_callback
.Run(kErrorDeviceMissing
, error_data
.Pass());
411 TDLSOperationParams params
;
412 params
.operation
= enabled
? shill::kTDLSSetupOperation
413 : shill::kTDLSTeardownOperation
;
414 params
.ip_or_mac_address
= ip_or_mac_address
;
415 CallPerformTDLSOperation(
416 device_state
->path(), params
, callback
, error_callback
);
419 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
420 const std::string
& ip_or_mac_address
,
421 const network_handler::StringResultCallback
& callback
,
422 const network_handler::ErrorCallback
& error_callback
) {
423 const DeviceState
* device_state
=
424 network_state_handler_
->GetDeviceStateByType(NetworkTypePattern::WiFi());
426 if (error_callback
.is_null())
428 scoped_ptr
<base::DictionaryValue
> error_data(new base::DictionaryValue
);
429 error_data
->SetString(network_handler::kErrorName
, kErrorDeviceMissing
);
430 error_callback
.Run(kErrorDeviceMissing
, error_data
.Pass());
433 TDLSOperationParams params
;
434 params
.operation
= shill::kTDLSStatusOperation
;
435 params
.ip_or_mac_address
= ip_or_mac_address
;
436 CallPerformTDLSOperation(
437 device_state
->path(), params
, callback
, error_callback
);
440 void NetworkDeviceHandlerImpl::DeviceListChanged() {
441 ApplyCellularAllowRoamingToShill();
444 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
445 : network_state_handler_(NULL
),
446 cellular_allow_roaming_(false) {}
448 void NetworkDeviceHandlerImpl::Init(
449 NetworkStateHandler
* network_state_handler
) {
450 DCHECK(network_state_handler
);
451 network_state_handler_
= network_state_handler
;
452 network_state_handler_
->AddObserver(this, FROM_HERE
);
455 void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
456 NetworkStateHandler::DeviceStateList list
;
457 network_state_handler_
->GetDeviceListByType(NetworkTypePattern::Cellular(),
460 NET_LOG_DEBUG("No cellular device is available",
461 "Roaming is only supported by cellular devices.");
464 for (NetworkStateHandler::DeviceStateList::const_iterator it
= list
.begin();
465 it
!= list
.end(); ++it
) {
466 const DeviceState
* device_state
= *it
;
467 bool current_allow_roaming
= device_state
->allow_roaming();
469 // If roaming is required by the provider, always try to set to true.
470 bool new_device_value
=
471 device_state
->provider_requires_roaming() || cellular_allow_roaming_
;
473 // Only set the value if the current value is different from
474 // |new_device_value|.
475 if (new_device_value
== current_allow_roaming
)
478 SetDevicePropertyInternal(device_state
->path(),
479 shill::kCellularAllowRoamingProperty
,
480 base::FundamentalValue(new_device_value
),
481 base::Bind(&base::DoNothing
),
482 network_handler::ErrorCallback());
486 } // namespace chromeos