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/strings/stringprintf.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/shill_device_client.h"
15 #include "chromeos/dbus/shill_ipconfig_client.h"
16 #include "chromeos/network/device_state.h"
17 #include "chromeos/network/network_state_handler.h"
18 #include "components/device_event_log/device_event_log.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
& device_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
<< ": " << device_path
;
47 network_handler::RunErrorCallback(error_callback
, device_path
, error_name
,
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
) {
67 NET_LOG(ERROR
) << "IPConfigs.Refresh Failed: " << call_status
<< ": "
70 NET_LOG(EVENT
) << "IPConfigs.Refresh Succeeded: " << ipconfig_path
;
74 void RefreshIPConfigsCallback(
75 const base::Closure
& callback
,
76 const network_handler::ErrorCallback
& error_callback
,
77 const std::string
& device_path
,
78 const base::DictionaryValue
& properties
) {
79 const base::ListValue
* ip_configs
;
80 if (!properties
.GetListWithoutPathExpansion(
81 shill::kIPConfigsProperty
, &ip_configs
)) {
82 NET_LOG(ERROR
) << "RequestRefreshIPConfigs Failed: " << device_path
;
83 network_handler::ShillErrorCallbackFunction(
84 "RequestRefreshIPConfigs Failed",
87 std::string("Missing ") + shill::kIPConfigsProperty
, "");
91 for (size_t i
= 0; i
< ip_configs
->GetSize(); i
++) {
92 std::string ipconfig_path
;
93 if (!ip_configs
->GetString(i
, &ipconfig_path
))
95 DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
96 dbus::ObjectPath(ipconfig_path
),
97 base::Bind(&IPConfigRefreshCallback
, ipconfig_path
));
99 // It is safe to invoke |callback| here instead of waiting for the
100 // IPConfig.Refresh callbacks to complete because the Refresh DBus calls will
101 // be executed in order and thus before any further DBus requests that
102 // |callback| may issue.
103 if (!callback
.is_null())
107 void ProposeScanCallback(
108 const std::string
& device_path
,
109 const base::Closure
& callback
,
110 const network_handler::ErrorCallback
& error_callback
,
111 DBusMethodCallStatus call_status
) {
112 if (call_status
!= DBUS_METHOD_CALL_SUCCESS
) {
113 network_handler::ShillErrorCallbackFunction(
114 "Device.ProposeScan Failed",
117 base::StringPrintf("DBus call failed: %d", call_status
), "");
120 NET_LOG(EVENT
) << "Device.ProposeScan succeeded: " << device_path
;
121 if (!callback
.is_null())
125 void SetDevicePropertyInternal(
126 const std::string
& device_path
,
127 const std::string
& property_name
,
128 const base::Value
& value
,
129 const base::Closure
& callback
,
130 const network_handler::ErrorCallback
& error_callback
) {
131 DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
132 dbus::ObjectPath(device_path
),
136 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
139 // Struct containing TDLS Operation parameters.
140 struct TDLSOperationParams
{
141 TDLSOperationParams() : retry_count(0) {}
142 std::string operation
;
143 std::string next_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
;
166 if (params
.operation
!= shill::kTDLSStatusOperation
&& !result
.empty()) {
167 NET_LOG(ERROR
) << "Unexpected TDLS result: " + result
<< ": "
171 TDLSOperationParams new_params
;
172 const int64 kRequestStatusDelayMs
= 500;
173 int64 request_delay_ms
= 0;
174 if (params
.operation
== shill::kTDLSStatusOperation
) {
175 // If this is the last operation, or the result is 'Nonexistent',
176 // return the result.
177 if (params
.next_operation
.empty() ||
178 result
== shill::kTDLSNonexistentState
) {
179 if (!callback
.is_null())
180 callback
.Run(result
);
183 // Otherwise start the next operation.
184 new_params
.operation
= params
.next_operation
;
185 } else if (params
.operation
== shill::kTDLSDiscoverOperation
) {
186 // Send a delayed Status request followed by a Setup request.
187 request_delay_ms
= kRequestStatusDelayMs
;
188 new_params
.operation
= shill::kTDLSStatusOperation
;
189 new_params
.next_operation
= shill::kTDLSSetupOperation
;
190 } else if (params
.operation
== shill::kTDLSSetupOperation
||
191 params
.operation
== shill::kTDLSTeardownOperation
) {
192 // Send a delayed Status request.
193 request_delay_ms
= kRequestStatusDelayMs
;
194 new_params
.operation
= shill::kTDLSStatusOperation
;
196 NET_LOG(ERROR
) << "Unexpected TDLS operation: " + params
.operation
;
200 new_params
.ip_or_mac_address
= params
.ip_or_mac_address
;
202 base::TimeDelta request_delay
;
203 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
204 request_delay
= base::TimeDelta::FromMilliseconds(request_delay_ms
);
206 base::MessageLoopProxy::current()->PostDelayedTask(
207 FROM_HERE
, base::Bind(&CallPerformTDLSOperation
, device_path
, new_params
,
208 callback
, error_callback
),
212 void TDLSErrorCallback(
213 const std::string
& device_path
,
214 const TDLSOperationParams
& params
,
215 const network_handler::StringResultCallback
& callback
,
216 const network_handler::ErrorCallback
& error_callback
,
217 const std::string
& dbus_error_name
,
218 const std::string
& dbus_error_message
) {
219 // If a Setup operation receives an InProgress error, retry.
220 const int kMaxRetries
= 5;
221 if ((params
.operation
== shill::kTDLSDiscoverOperation
||
222 params
.operation
== shill::kTDLSSetupOperation
) &&
223 dbus_error_name
== shill::kErrorResultInProgress
&&
224 params
.retry_count
< kMaxRetries
) {
225 TDLSOperationParams retry_params
= params
;
226 ++retry_params
.retry_count
;
227 NET_LOG(EVENT
) << "TDLS Retry: " << params
.retry_count
<< ": "
229 const int64 kReRequestDelayMs
= 1000;
230 base::TimeDelta request_delay
;
231 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
232 request_delay
= base::TimeDelta::FromMilliseconds(kReRequestDelayMs
);
234 base::MessageLoopProxy::current()->PostDelayedTask(
236 base::Bind(&CallPerformTDLSOperation
,
237 device_path
, retry_params
, callback
, error_callback
),
242 NET_LOG(ERROR
) << "TDLS Operation: " << params
.operation
243 << " Error: " << dbus_error_name
<< ": " << dbus_error_message
244 << ": " << device_path
;
245 if (error_callback
.is_null())
248 const std::string error_name
=
249 dbus_error_name
== shill::kErrorResultInProgress
?
250 NetworkDeviceHandler::kErrorTimeout
: NetworkDeviceHandler::kErrorUnknown
;
251 const std::string
& error_detail
= params
.ip_or_mac_address
;
252 scoped_ptr
<base::DictionaryValue
> error_data(
253 network_handler::CreateDBusErrorData(
254 device_path
, error_name
, error_detail
,
255 dbus_error_name
, dbus_error_message
));
256 error_callback
.Run(error_name
, error_data
.Pass());
259 void CallPerformTDLSOperation(
260 const std::string
& device_path
,
261 const TDLSOperationParams
& params
,
262 const network_handler::StringResultCallback
& callback
,
263 const network_handler::ErrorCallback
& error_callback
) {
264 LOG(ERROR
) << "TDLS: " << params
.operation
;
265 NET_LOG(EVENT
) << "CallPerformTDLSOperation: " << params
.operation
<< ": "
267 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
268 dbus::ObjectPath(device_path
),
270 params
.ip_or_mac_address
,
271 base::Bind(&TDLSSuccessCallback
,
272 device_path
, params
, callback
, error_callback
),
273 base::Bind(&TDLSErrorCallback
,
274 device_path
, params
, callback
, error_callback
));
279 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
280 if (network_state_handler_
)
281 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
284 void NetworkDeviceHandlerImpl::GetDeviceProperties(
285 const std::string
& device_path
,
286 const network_handler::DictionaryResultCallback
& callback
,
287 const network_handler::ErrorCallback
& error_callback
) const {
288 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
289 dbus::ObjectPath(device_path
),
290 base::Bind(&network_handler::GetPropertiesCallback
,
291 callback
, error_callback
, device_path
));
294 void NetworkDeviceHandlerImpl::SetDeviceProperty(
295 const std::string
& device_path
,
296 const std::string
& property_name
,
297 const base::Value
& value
,
298 const base::Closure
& callback
,
299 const network_handler::ErrorCallback
& error_callback
) {
300 const char* const property_blacklist
[] = {
301 // Must only be changed by policy/owner through.
302 shill::kCellularAllowRoamingProperty
305 for (size_t i
= 0; i
< arraysize(property_blacklist
); ++i
) {
306 if (property_name
== property_blacklist
[i
]) {
310 "SetDeviceProperty called on blacklisted property " + property_name
);
315 SetDevicePropertyInternal(
316 device_path
, property_name
, value
, callback
, error_callback
);
319 void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
320 const std::string
& device_path
,
321 const base::Closure
& callback
,
322 const network_handler::ErrorCallback
& error_callback
) {
323 GetDeviceProperties(device_path
,
324 base::Bind(&RefreshIPConfigsCallback
,
325 callback
, error_callback
),
329 void NetworkDeviceHandlerImpl::ProposeScan(
330 const std::string
& device_path
,
331 const base::Closure
& callback
,
332 const network_handler::ErrorCallback
& error_callback
) {
333 DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
334 dbus::ObjectPath(device_path
),
335 base::Bind(&ProposeScanCallback
, device_path
, callback
, error_callback
));
338 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
339 const std::string
& device_path
,
340 const std::string
& network_id
,
341 const base::Closure
& callback
,
342 const network_handler::ErrorCallback
& error_callback
) {
343 DBusThreadManager::Get()->GetShillDeviceClient()->Register(
344 dbus::ObjectPath(device_path
),
347 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
350 void NetworkDeviceHandlerImpl::SetCarrier(
351 const std::string
& device_path
,
352 const std::string
& carrier
,
353 const base::Closure
& callback
,
354 const network_handler::ErrorCallback
& error_callback
) {
355 DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
356 dbus::ObjectPath(device_path
),
359 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
362 void NetworkDeviceHandlerImpl::RequirePin(
363 const std::string
& device_path
,
365 const std::string
& pin
,
366 const base::Closure
& callback
,
367 const network_handler::ErrorCallback
& error_callback
) {
368 DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
369 dbus::ObjectPath(device_path
),
373 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
376 void NetworkDeviceHandlerImpl::EnterPin(
377 const std::string
& device_path
,
378 const std::string
& pin
,
379 const base::Closure
& callback
,
380 const network_handler::ErrorCallback
& error_callback
) {
381 DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
382 dbus::ObjectPath(device_path
),
385 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
388 void NetworkDeviceHandlerImpl::UnblockPin(
389 const std::string
& device_path
,
390 const std::string
& puk
,
391 const std::string
& new_pin
,
392 const base::Closure
& callback
,
393 const network_handler::ErrorCallback
& error_callback
) {
394 DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
395 dbus::ObjectPath(device_path
),
399 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
402 void NetworkDeviceHandlerImpl::ChangePin(
403 const std::string
& device_path
,
404 const std::string
& old_pin
,
405 const std::string
& new_pin
,
406 const base::Closure
& callback
,
407 const network_handler::ErrorCallback
& error_callback
) {
408 DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
409 dbus::ObjectPath(device_path
),
413 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
416 void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
417 const bool allow_roaming
) {
418 cellular_allow_roaming_
= allow_roaming
;
419 ApplyCellularAllowRoamingToShill();
422 void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
423 const std::string
& ip_or_mac_address
,
425 const network_handler::StringResultCallback
& callback
,
426 const network_handler::ErrorCallback
& error_callback
) {
427 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
431 TDLSOperationParams params
;
433 enabled
? shill::kTDLSDiscoverOperation
: shill::kTDLSTeardownOperation
;
434 params
.ip_or_mac_address
= ip_or_mac_address
;
435 CallPerformTDLSOperation(
436 device_state
->path(), params
, callback
, error_callback
);
439 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
440 const std::string
& ip_or_mac_address
,
441 const network_handler::StringResultCallback
& callback
,
442 const network_handler::ErrorCallback
& error_callback
) {
443 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
447 TDLSOperationParams params
;
448 params
.operation
= shill::kTDLSStatusOperation
;
449 params
.ip_or_mac_address
= ip_or_mac_address
;
450 CallPerformTDLSOperation(
451 device_state
->path(), params
, callback
, error_callback
);
454 void NetworkDeviceHandlerImpl::AddWifiWakeOnPacketConnection(
455 const net::IPEndPoint
& ip_endpoint
,
456 const base::Closure
& callback
,
457 const network_handler::ErrorCallback
& error_callback
) {
458 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
462 DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection(
463 dbus::ObjectPath(device_state
->path()),
466 base::Bind(&HandleShillCallFailure
,
467 device_state
->path(),
471 void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketConnection(
472 const net::IPEndPoint
& ip_endpoint
,
473 const base::Closure
& callback
,
474 const network_handler::ErrorCallback
& error_callback
) {
475 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
479 DBusThreadManager::Get()
480 ->GetShillDeviceClient()
481 ->RemoveWakeOnPacketConnection(dbus::ObjectPath(device_state
->path()),
484 base::Bind(&HandleShillCallFailure
,
485 device_state
->path(),
489 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
490 const base::Closure
& callback
,
491 const network_handler::ErrorCallback
& error_callback
) {
492 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
496 DBusThreadManager::Get()
497 ->GetShillDeviceClient()
498 ->RemoveAllWakeOnPacketConnections(dbus::ObjectPath(device_state
->path()),
500 base::Bind(&HandleShillCallFailure
,
501 device_state
->path(),
505 void NetworkDeviceHandlerImpl::DeviceListChanged() {
506 ApplyCellularAllowRoamingToShill();
509 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
510 : network_state_handler_(NULL
),
511 cellular_allow_roaming_(false) {}
513 void NetworkDeviceHandlerImpl::Init(
514 NetworkStateHandler
* network_state_handler
) {
515 DCHECK(network_state_handler
);
516 network_state_handler_
= network_state_handler
;
517 network_state_handler_
->AddObserver(this, FROM_HERE
);
520 void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
521 NetworkStateHandler::DeviceStateList list
;
522 network_state_handler_
->GetDeviceListByType(NetworkTypePattern::Cellular(),
525 NET_LOG(DEBUG
) << "No cellular device available. Roaming is only supported "
526 "by cellular devices.";
529 for (NetworkStateHandler::DeviceStateList::const_iterator it
= list
.begin();
530 it
!= list
.end(); ++it
) {
531 const DeviceState
* device_state
= *it
;
532 bool current_allow_roaming
= device_state
->allow_roaming();
534 // If roaming is required by the provider, always try to set to true.
535 bool new_device_value
=
536 device_state
->provider_requires_roaming() || cellular_allow_roaming_
;
538 // Only set the value if the current value is different from
539 // |new_device_value|.
540 if (new_device_value
== current_allow_roaming
)
543 SetDevicePropertyInternal(device_state
->path(),
544 shill::kCellularAllowRoamingProperty
,
545 base::FundamentalValue(new_device_value
),
546 base::Bind(&base::DoNothing
),
547 network_handler::ErrorCallback());
551 const DeviceState
* NetworkDeviceHandlerImpl::GetWifiDeviceState(
552 const network_handler::ErrorCallback
& error_callback
) {
553 const DeviceState
* device_state
=
554 network_state_handler_
->GetDeviceStateByType(NetworkTypePattern::WiFi());
556 if (error_callback
.is_null())
558 scoped_ptr
<base::DictionaryValue
> error_data(new base::DictionaryValue
);
559 error_data
->SetString(network_handler::kErrorName
, kErrorDeviceMissing
);
560 error_callback
.Run(kErrorDeviceMissing
, error_data
.Pass());
567 } // namespace chromeos