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/single_thread_task_runner.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "chromeos/dbus/dbus_thread_manager.h"
15 #include "chromeos/dbus/shill_device_client.h"
16 #include "chromeos/dbus/shill_ipconfig_client.h"
17 #include "chromeos/network/device_state.h"
18 #include "chromeos/network/network_state_handler.h"
19 #include "components/device_event_log/device_event_log.h"
20 #include "dbus/object_path.h"
21 #include "third_party/cros_system_api/dbus/service_constants.h"
27 std::string
GetErrorNameForShillError(const std::string
& shill_error_name
) {
28 if (shill_error_name
== shill::kErrorResultFailure
)
29 return NetworkDeviceHandler::kErrorFailure
;
30 if (shill_error_name
== shill::kErrorResultNotSupported
)
31 return NetworkDeviceHandler::kErrorNotSupported
;
32 if (shill_error_name
== shill::kErrorResultIncorrectPin
)
33 return NetworkDeviceHandler::kErrorIncorrectPin
;
34 if (shill_error_name
== shill::kErrorResultPinBlocked
)
35 return NetworkDeviceHandler::kErrorPinBlocked
;
36 if (shill_error_name
== shill::kErrorResultPinRequired
)
37 return NetworkDeviceHandler::kErrorPinRequired
;
38 if (shill_error_name
== shill::kErrorResultNotFound
)
39 return NetworkDeviceHandler::kErrorDeviceMissing
;
40 return NetworkDeviceHandler::kErrorUnknown
;
43 void InvokeErrorCallback(const std::string
& device_path
,
44 const network_handler::ErrorCallback
& error_callback
,
45 const std::string
& error_name
) {
46 std::string error_msg
= "Device Error: " + error_name
;
47 NET_LOG(ERROR
) << error_msg
<< ": " << device_path
;
48 network_handler::RunErrorCallback(error_callback
, device_path
, error_name
,
52 void HandleShillCallFailure(
53 const std::string
& device_path
,
54 const network_handler::ErrorCallback
& error_callback
,
55 const std::string
& shill_error_name
,
56 const std::string
& shill_error_message
) {
57 network_handler::ShillErrorCallbackFunction(
58 GetErrorNameForShillError(shill_error_name
),
65 void IPConfigRefreshCallback(const std::string
& ipconfig_path
,
66 DBusMethodCallStatus call_status
) {
67 if (call_status
!= DBUS_METHOD_CALL_SUCCESS
) {
68 NET_LOG(ERROR
) << "IPConfigs.Refresh Failed: " << 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 NET_LOG(USER
) << "Device.SetProperty: " << property_name
;
133 DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
134 dbus::ObjectPath(device_path
),
138 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
141 // Struct containing TDLS Operation parameters.
142 struct TDLSOperationParams
{
143 TDLSOperationParams() : retry_count(0) {}
144 std::string operation
;
145 std::string next_operation
;
146 std::string ip_or_mac_address
;
150 // Forward declare for PostDelayedTask.
151 void CallPerformTDLSOperation(
152 const std::string
& device_path
,
153 const TDLSOperationParams
& params
,
154 const network_handler::StringResultCallback
& callback
,
155 const network_handler::ErrorCallback
& error_callback
);
157 void TDLSSuccessCallback(
158 const std::string
& device_path
,
159 const TDLSOperationParams
& params
,
160 const network_handler::StringResultCallback
& callback
,
161 const network_handler::ErrorCallback
& error_callback
,
162 const std::string
& result
) {
163 std::string event_desc
= "TDLSSuccessCallback: " + params
.operation
;
165 event_desc
+= ": " + result
;
166 NET_LOG(EVENT
) << event_desc
<< ": " << device_path
;
168 if (params
.operation
!= shill::kTDLSStatusOperation
&& !result
.empty()) {
169 NET_LOG(ERROR
) << "Unexpected TDLS result: " + result
<< ": "
173 TDLSOperationParams new_params
;
174 const int64 kRequestStatusDelayMs
= 500;
175 int64 request_delay_ms
= 0;
176 if (params
.operation
== shill::kTDLSStatusOperation
) {
177 // If this is the last operation, or the result is 'Nonexistent',
178 // return the result.
179 if (params
.next_operation
.empty() ||
180 result
== shill::kTDLSNonexistentState
) {
181 if (!callback
.is_null())
182 callback
.Run(result
);
185 // Otherwise start the next operation.
186 new_params
.operation
= params
.next_operation
;
187 } else if (params
.operation
== shill::kTDLSDiscoverOperation
) {
188 // Send a delayed Status request followed by a Setup request.
189 request_delay_ms
= kRequestStatusDelayMs
;
190 new_params
.operation
= shill::kTDLSStatusOperation
;
191 new_params
.next_operation
= shill::kTDLSSetupOperation
;
192 } else if (params
.operation
== shill::kTDLSSetupOperation
||
193 params
.operation
== shill::kTDLSTeardownOperation
) {
194 // Send a delayed Status request.
195 request_delay_ms
= kRequestStatusDelayMs
;
196 new_params
.operation
= shill::kTDLSStatusOperation
;
198 NET_LOG(ERROR
) << "Unexpected TDLS operation: " + params
.operation
;
202 new_params
.ip_or_mac_address
= params
.ip_or_mac_address
;
204 base::TimeDelta request_delay
;
205 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
206 request_delay
= base::TimeDelta::FromMilliseconds(request_delay_ms
);
208 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
209 FROM_HERE
, base::Bind(&CallPerformTDLSOperation
, device_path
, new_params
,
210 callback
, error_callback
),
214 void TDLSErrorCallback(
215 const std::string
& device_path
,
216 const TDLSOperationParams
& params
,
217 const network_handler::StringResultCallback
& callback
,
218 const network_handler::ErrorCallback
& error_callback
,
219 const std::string
& dbus_error_name
,
220 const std::string
& dbus_error_message
) {
221 // If a Setup operation receives an InProgress error, retry.
222 const int kMaxRetries
= 5;
223 if ((params
.operation
== shill::kTDLSDiscoverOperation
||
224 params
.operation
== shill::kTDLSSetupOperation
) &&
225 dbus_error_name
== shill::kErrorResultInProgress
&&
226 params
.retry_count
< kMaxRetries
) {
227 TDLSOperationParams retry_params
= params
;
228 ++retry_params
.retry_count
;
229 NET_LOG(EVENT
) << "TDLS Retry: " << params
.retry_count
<< ": "
231 const int64 kReRequestDelayMs
= 1000;
232 base::TimeDelta request_delay
;
233 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
234 request_delay
= base::TimeDelta::FromMilliseconds(kReRequestDelayMs
);
236 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
237 FROM_HERE
, base::Bind(&CallPerformTDLSOperation
, device_path
,
238 retry_params
, callback
, error_callback
),
243 NET_LOG(ERROR
) << "TDLS Operation: " << params
.operation
244 << " Error: " << dbus_error_name
<< ": " << dbus_error_message
245 << ": " << device_path
;
246 if (error_callback
.is_null())
249 const std::string error_name
=
250 dbus_error_name
== shill::kErrorResultInProgress
?
251 NetworkDeviceHandler::kErrorTimeout
: NetworkDeviceHandler::kErrorUnknown
;
252 const std::string
& error_detail
= params
.ip_or_mac_address
;
253 scoped_ptr
<base::DictionaryValue
> error_data(
254 network_handler::CreateDBusErrorData(
255 device_path
, error_name
, error_detail
,
256 dbus_error_name
, dbus_error_message
));
257 error_callback
.Run(error_name
, error_data
.Pass());
260 void CallPerformTDLSOperation(
261 const std::string
& device_path
,
262 const TDLSOperationParams
& params
,
263 const network_handler::StringResultCallback
& callback
,
264 const network_handler::ErrorCallback
& error_callback
) {
265 LOG(ERROR
) << "TDLS: " << params
.operation
;
266 NET_LOG(EVENT
) << "CallPerformTDLSOperation: " << params
.operation
<< ": "
268 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
269 dbus::ObjectPath(device_path
),
271 params
.ip_or_mac_address
,
272 base::Bind(&TDLSSuccessCallback
,
273 device_path
, params
, callback
, error_callback
),
274 base::Bind(&TDLSErrorCallback
,
275 device_path
, params
, callback
, error_callback
));
280 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
281 if (network_state_handler_
)
282 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
285 void NetworkDeviceHandlerImpl::GetDeviceProperties(
286 const std::string
& device_path
,
287 const network_handler::DictionaryResultCallback
& callback
,
288 const network_handler::ErrorCallback
& error_callback
) const {
289 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
290 dbus::ObjectPath(device_path
),
291 base::Bind(&network_handler::GetPropertiesCallback
,
292 callback
, error_callback
, device_path
));
295 void NetworkDeviceHandlerImpl::SetDeviceProperty(
296 const std::string
& device_path
,
297 const std::string
& property_name
,
298 const base::Value
& value
,
299 const base::Closure
& callback
,
300 const network_handler::ErrorCallback
& error_callback
) {
301 const char* const property_blacklist
[] = {
302 // Must only be changed by policy/owner through.
303 shill::kCellularAllowRoamingProperty
306 for (size_t i
= 0; i
< arraysize(property_blacklist
); ++i
) {
307 if (property_name
== property_blacklist
[i
]) {
311 "SetDeviceProperty called on blacklisted property " + property_name
);
316 SetDevicePropertyInternal(
317 device_path
, property_name
, value
, callback
, error_callback
);
320 void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
321 const std::string
& device_path
,
322 const base::Closure
& callback
,
323 const network_handler::ErrorCallback
& error_callback
) {
324 GetDeviceProperties(device_path
,
325 base::Bind(&RefreshIPConfigsCallback
,
326 callback
, error_callback
),
330 void NetworkDeviceHandlerImpl::ProposeScan(
331 const std::string
& device_path
,
332 const base::Closure
& callback
,
333 const network_handler::ErrorCallback
& error_callback
) {
334 DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
335 dbus::ObjectPath(device_path
),
336 base::Bind(&ProposeScanCallback
, device_path
, callback
, error_callback
));
339 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
340 const std::string
& device_path
,
341 const std::string
& network_id
,
342 const base::Closure
& callback
,
343 const network_handler::ErrorCallback
& error_callback
) {
344 NET_LOG(USER
) << "Device.RegisterCellularNetwork: " << device_path
345 << " Id: " << network_id
;
346 DBusThreadManager::Get()->GetShillDeviceClient()->Register(
347 dbus::ObjectPath(device_path
),
350 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
353 void NetworkDeviceHandlerImpl::SetCarrier(
354 const std::string
& device_path
,
355 const std::string
& carrier
,
356 const base::Closure
& callback
,
357 const network_handler::ErrorCallback
& error_callback
) {
358 NET_LOG(USER
) << "Device.SetCarrier: " << device_path
359 << " carrier: " << carrier
;
360 DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
361 dbus::ObjectPath(device_path
),
364 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
367 void NetworkDeviceHandlerImpl::RequirePin(
368 const std::string
& device_path
,
370 const std::string
& pin
,
371 const base::Closure
& callback
,
372 const network_handler::ErrorCallback
& error_callback
) {
373 NET_LOG(USER
) << "Device.RequirePin: " << device_path
<< ": " << require_pin
;
374 DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
375 dbus::ObjectPath(device_path
),
379 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
382 void NetworkDeviceHandlerImpl::EnterPin(
383 const std::string
& device_path
,
384 const std::string
& pin
,
385 const base::Closure
& callback
,
386 const network_handler::ErrorCallback
& error_callback
) {
387 NET_LOG(USER
) << "Device.EnterPin: " << device_path
;
388 DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
389 dbus::ObjectPath(device_path
),
392 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
395 void NetworkDeviceHandlerImpl::UnblockPin(
396 const std::string
& device_path
,
397 const std::string
& puk
,
398 const std::string
& new_pin
,
399 const base::Closure
& callback
,
400 const network_handler::ErrorCallback
& error_callback
) {
401 NET_LOG(USER
) << "Device.UnblockPin: " << device_path
;
402 DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
403 dbus::ObjectPath(device_path
),
407 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
410 void NetworkDeviceHandlerImpl::ChangePin(
411 const std::string
& device_path
,
412 const std::string
& old_pin
,
413 const std::string
& new_pin
,
414 const base::Closure
& callback
,
415 const network_handler::ErrorCallback
& error_callback
) {
416 NET_LOG(USER
) << "Device.ChangePin: " << device_path
;
417 DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
418 dbus::ObjectPath(device_path
),
422 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
425 void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
426 const bool allow_roaming
) {
427 cellular_allow_roaming_
= allow_roaming
;
428 ApplyCellularAllowRoamingToShill();
431 void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
432 const std::string
& ip_or_mac_address
,
434 const network_handler::StringResultCallback
& callback
,
435 const network_handler::ErrorCallback
& error_callback
) {
436 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
440 TDLSOperationParams params
;
442 enabled
? shill::kTDLSDiscoverOperation
: shill::kTDLSTeardownOperation
;
443 params
.ip_or_mac_address
= ip_or_mac_address
;
444 CallPerformTDLSOperation(
445 device_state
->path(), params
, callback
, error_callback
);
448 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
449 const std::string
& ip_or_mac_address
,
450 const network_handler::StringResultCallback
& callback
,
451 const network_handler::ErrorCallback
& error_callback
) {
452 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
456 TDLSOperationParams params
;
457 params
.operation
= shill::kTDLSStatusOperation
;
458 params
.ip_or_mac_address
= ip_or_mac_address
;
459 CallPerformTDLSOperation(
460 device_state
->path(), params
, callback
, error_callback
);
463 void NetworkDeviceHandlerImpl::AddWifiWakeOnPacketConnection(
464 const net::IPEndPoint
& ip_endpoint
,
465 const base::Closure
& callback
,
466 const network_handler::ErrorCallback
& error_callback
) {
467 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
471 NET_LOG(USER
) << "Device.AddWakeOnWifi: " << device_state
->path();
472 DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection(
473 dbus::ObjectPath(device_state
->path()),
476 base::Bind(&HandleShillCallFailure
,
477 device_state
->path(),
481 void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketConnection(
482 const net::IPEndPoint
& ip_endpoint
,
483 const base::Closure
& callback
,
484 const network_handler::ErrorCallback
& error_callback
) {
485 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
489 NET_LOG(USER
) << "Device.RemoveWakeOnWifi: " << device_state
->path();
490 DBusThreadManager::Get()
491 ->GetShillDeviceClient()
492 ->RemoveWakeOnPacketConnection(dbus::ObjectPath(device_state
->path()),
495 base::Bind(&HandleShillCallFailure
,
496 device_state
->path(),
500 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
501 const base::Closure
& callback
,
502 const network_handler::ErrorCallback
& error_callback
) {
503 const DeviceState
* device_state
= GetWifiDeviceState(error_callback
);
507 NET_LOG(USER
) << "Device.RemoveAllWakeOnWifi: " << device_state
->path();
508 DBusThreadManager::Get()
509 ->GetShillDeviceClient()
510 ->RemoveAllWakeOnPacketConnections(dbus::ObjectPath(device_state
->path()),
512 base::Bind(&HandleShillCallFailure
,
513 device_state
->path(),
517 void NetworkDeviceHandlerImpl::DeviceListChanged() {
518 ApplyCellularAllowRoamingToShill();
521 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
522 : network_state_handler_(NULL
),
523 cellular_allow_roaming_(false) {}
525 void NetworkDeviceHandlerImpl::Init(
526 NetworkStateHandler
* network_state_handler
) {
527 DCHECK(network_state_handler
);
528 network_state_handler_
= network_state_handler
;
529 network_state_handler_
->AddObserver(this, FROM_HERE
);
532 void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
533 NetworkStateHandler::DeviceStateList list
;
534 network_state_handler_
->GetDeviceListByType(NetworkTypePattern::Cellular(),
537 NET_LOG(DEBUG
) << "No cellular device available. Roaming is only supported "
538 "by cellular devices.";
541 for (NetworkStateHandler::DeviceStateList::const_iterator it
= list
.begin();
542 it
!= list
.end(); ++it
) {
543 const DeviceState
* device_state
= *it
;
544 bool current_allow_roaming
= device_state
->allow_roaming();
546 // If roaming is required by the provider, always try to set to true.
547 bool new_device_value
=
548 device_state
->provider_requires_roaming() || cellular_allow_roaming_
;
550 // Only set the value if the current value is different from
551 // |new_device_value|.
552 if (new_device_value
== current_allow_roaming
)
555 SetDevicePropertyInternal(device_state
->path(),
556 shill::kCellularAllowRoamingProperty
,
557 base::FundamentalValue(new_device_value
),
558 base::Bind(&base::DoNothing
),
559 network_handler::ErrorCallback());
563 const DeviceState
* NetworkDeviceHandlerImpl::GetWifiDeviceState(
564 const network_handler::ErrorCallback
& error_callback
) {
565 const DeviceState
* device_state
=
566 network_state_handler_
->GetDeviceStateByType(NetworkTypePattern::WiFi());
568 if (error_callback
.is_null())
570 scoped_ptr
<base::DictionaryValue
> error_data(new base::DictionaryValue
);
571 error_data
->SetString(network_handler::kErrorName
, kErrorDeviceMissing
);
572 error_callback
.Run(kErrorDeviceMissing
, error_data
.Pass());
579 } // namespace chromeos