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 "chromeos/network/shill_property_util.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
& service_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
, service_path
);
48 network_handler::RunErrorCallback(
49 error_callback
, service_path
, error_name
, error_msg
);
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
) {
69 base::StringPrintf("IPConfigs.Refresh Failed: %d", call_status
),
72 NET_LOG_EVENT("IPConfigs.Refresh Succeeded", ipconfig_path
);
76 void RefreshIPConfigsCallback(
77 const base::Closure
& callback
,
78 const network_handler::ErrorCallback
& error_callback
,
79 const std::string
& device_path
,
80 const base::DictionaryValue
& properties
) {
81 const base::ListValue
* ip_configs
;
82 if (!properties
.GetListWithoutPathExpansion(
83 shill::kIPConfigsProperty
, &ip_configs
)) {
84 NET_LOG_ERROR("RequestRefreshIPConfigs Failed", device_path
);
85 network_handler::ShillErrorCallbackFunction(
86 "RequestRefreshIPConfigs Failed",
89 std::string("Missing ") + shill::kIPConfigsProperty
, "");
93 for (size_t i
= 0; i
< ip_configs
->GetSize(); i
++) {
94 std::string ipconfig_path
;
95 if (!ip_configs
->GetString(i
, &ipconfig_path
))
97 DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh(
98 dbus::ObjectPath(ipconfig_path
),
99 base::Bind(&IPConfigRefreshCallback
, ipconfig_path
));
101 // It is safe to invoke |callback| here instead of waiting for the
102 // IPConfig.Refresh callbacks to complete because the Refresh DBus calls will
103 // be executed in order and thus before any further DBus requests that
104 // |callback| may issue.
105 if (!callback
.is_null())
109 void ProposeScanCallback(
110 const std::string
& device_path
,
111 const base::Closure
& callback
,
112 const network_handler::ErrorCallback
& error_callback
,
113 DBusMethodCallStatus call_status
) {
114 if (call_status
!= DBUS_METHOD_CALL_SUCCESS
) {
115 network_handler::ShillErrorCallbackFunction(
116 "Device.ProposeScan Failed",
119 base::StringPrintf("DBus call failed: %d", call_status
), "");
122 NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path
);
123 if (!callback
.is_null())
127 void SetDevicePropertyInternal(
128 const std::string
& device_path
,
129 const std::string
& property_name
,
130 const base::Value
& value
,
131 const base::Closure
& callback
,
132 const network_handler::ErrorCallback
& error_callback
) {
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 ip_or_mac_address
;
149 // Forward declare for PostDelayedTask.
150 void CallPerformTDLSOperation(
151 const std::string
& device_path
,
152 const TDLSOperationParams
& params
,
153 const network_handler::StringResultCallback
& callback
,
154 const network_handler::ErrorCallback
& error_callback
);
156 void TDLSSuccessCallback(
157 const std::string
& device_path
,
158 const TDLSOperationParams
& params
,
159 const network_handler::StringResultCallback
& callback
,
160 const network_handler::ErrorCallback
& error_callback
,
161 const std::string
& result
) {
162 std::string event_desc
= "TDLSSuccessCallback: " + params
.operation
;
164 event_desc
+= ": " + result
;
165 NET_LOG_EVENT(event_desc
, device_path
);
166 if (params
.operation
!= shill::kTDLSSetupOperation
) {
167 if (!callback
.is_null())
168 callback
.Run(result
);
173 NET_LOG_ERROR("Unexpected TDLS result: " + result
, device_path
);
175 // Send a delayed Status request after a successful Setup call.
176 TDLSOperationParams status_params
;
177 status_params
.operation
= shill::kTDLSStatusOperation
;
178 status_params
.ip_or_mac_address
= params
.ip_or_mac_address
;
180 const int64 kRequestStatusDelayMs
= 500;
181 base::TimeDelta request_delay
;
182 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
183 request_delay
= base::TimeDelta::FromMilliseconds(kRequestStatusDelayMs
);
185 base::MessageLoopProxy::current()->PostDelayedTask(
187 base::Bind(&CallPerformTDLSOperation
,
188 device_path
, status_params
, callback
, error_callback
),
192 void TDLSErrorCallback(
193 const std::string
& device_path
,
194 const TDLSOperationParams
& params
,
195 const network_handler::StringResultCallback
& callback
,
196 const network_handler::ErrorCallback
& error_callback
,
197 const std::string
& dbus_error_name
,
198 const std::string
& dbus_error_message
) {
199 // If a Setup operation receives an InProgress error, retry.
200 const int kMaxRetries
= 5;
201 if (params
.operation
== shill::kTDLSSetupOperation
&&
202 dbus_error_name
== shill::kErrorResultInProgress
&&
203 params
.retry_count
< kMaxRetries
) {
204 TDLSOperationParams retry_params
= params
;
205 ++retry_params
.retry_count
;
206 NET_LOG_EVENT(base::StringPrintf("TDLS Retry: %d", params
.retry_count
),
208 const int64 kReRequestDelayMs
= 1000;
209 base::TimeDelta request_delay
;
210 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface())
211 request_delay
= base::TimeDelta::FromMilliseconds(kReRequestDelayMs
);
213 base::MessageLoopProxy::current()->PostDelayedTask(
215 base::Bind(&CallPerformTDLSOperation
,
216 device_path
, retry_params
, callback
, error_callback
),
221 NET_LOG_ERROR("TDLS Error:" + dbus_error_name
+ ":" + dbus_error_message
,
223 if (error_callback
.is_null())
226 const std::string error_name
=
227 dbus_error_name
== shill::kErrorResultInProgress
?
228 NetworkDeviceHandler::kErrorTimeout
: NetworkDeviceHandler::kErrorUnknown
;
229 const std::string
& error_detail
= params
.ip_or_mac_address
;
230 scoped_ptr
<base::DictionaryValue
> error_data(
231 network_handler::CreateDBusErrorData(
232 device_path
, error_name
, error_detail
,
233 dbus_error_name
, dbus_error_message
));
234 error_callback
.Run(error_name
, error_data
.Pass());
237 void CallPerformTDLSOperation(
238 const std::string
& device_path
,
239 const TDLSOperationParams
& params
,
240 const network_handler::StringResultCallback
& callback
,
241 const network_handler::ErrorCallback
& error_callback
) {
242 NET_LOG_EVENT("CallPerformTDLSOperation: " + params
.operation
, device_path
);
243 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
244 dbus::ObjectPath(device_path
),
246 params
.ip_or_mac_address
,
247 base::Bind(&TDLSSuccessCallback
,
248 device_path
, params
, callback
, error_callback
),
249 base::Bind(&TDLSErrorCallback
,
250 device_path
, params
, callback
, error_callback
));
255 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
256 network_state_handler_
->RemoveObserver(this, FROM_HERE
);
259 void NetworkDeviceHandlerImpl::GetDeviceProperties(
260 const std::string
& device_path
,
261 const network_handler::DictionaryResultCallback
& callback
,
262 const network_handler::ErrorCallback
& error_callback
) const {
263 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
264 dbus::ObjectPath(device_path
),
265 base::Bind(&network_handler::GetPropertiesCallback
,
266 callback
, error_callback
, device_path
));
269 void NetworkDeviceHandlerImpl::SetDeviceProperty(
270 const std::string
& device_path
,
271 const std::string
& property_name
,
272 const base::Value
& value
,
273 const base::Closure
& callback
,
274 const network_handler::ErrorCallback
& error_callback
) {
275 const char* const property_blacklist
[] = {
276 // Must only be changed by policy/owner through.
277 shill::kCellularAllowRoamingProperty
280 for (size_t i
= 0; i
< arraysize(property_blacklist
); ++i
) {
281 if (property_name
== property_blacklist
[i
]) {
285 "SetDeviceProperty called on blacklisted property " + property_name
);
290 SetDevicePropertyInternal(
291 device_path
, property_name
, value
, callback
, error_callback
);
294 void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
295 const std::string
& device_path
,
296 const base::Closure
& callback
,
297 const network_handler::ErrorCallback
& error_callback
) {
298 GetDeviceProperties(device_path
,
299 base::Bind(&RefreshIPConfigsCallback
,
300 callback
, error_callback
),
304 void NetworkDeviceHandlerImpl::ProposeScan(
305 const std::string
& device_path
,
306 const base::Closure
& callback
,
307 const network_handler::ErrorCallback
& error_callback
) {
308 DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
309 dbus::ObjectPath(device_path
),
310 base::Bind(&ProposeScanCallback
, device_path
, callback
, error_callback
));
313 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
314 const std::string
& device_path
,
315 const std::string
& network_id
,
316 const base::Closure
& callback
,
317 const network_handler::ErrorCallback
& error_callback
) {
318 DBusThreadManager::Get()->GetShillDeviceClient()->Register(
319 dbus::ObjectPath(device_path
),
322 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
325 void NetworkDeviceHandlerImpl::SetCarrier(
326 const std::string
& device_path
,
327 const std::string
& carrier
,
328 const base::Closure
& callback
,
329 const network_handler::ErrorCallback
& error_callback
) {
330 DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
331 dbus::ObjectPath(device_path
),
334 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
337 void NetworkDeviceHandlerImpl::RequirePin(
338 const std::string
& device_path
,
340 const std::string
& pin
,
341 const base::Closure
& callback
,
342 const network_handler::ErrorCallback
& error_callback
) {
343 DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
344 dbus::ObjectPath(device_path
),
348 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
351 void NetworkDeviceHandlerImpl::EnterPin(
352 const std::string
& device_path
,
353 const std::string
& pin
,
354 const base::Closure
& callback
,
355 const network_handler::ErrorCallback
& error_callback
) {
356 DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
357 dbus::ObjectPath(device_path
),
360 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
363 void NetworkDeviceHandlerImpl::UnblockPin(
364 const std::string
& device_path
,
365 const std::string
& puk
,
366 const std::string
& new_pin
,
367 const base::Closure
& callback
,
368 const network_handler::ErrorCallback
& error_callback
) {
369 DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
370 dbus::ObjectPath(device_path
),
374 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
377 void NetworkDeviceHandlerImpl::ChangePin(
378 const std::string
& device_path
,
379 const std::string
& old_pin
,
380 const std::string
& new_pin
,
381 const base::Closure
& callback
,
382 const network_handler::ErrorCallback
& error_callback
) {
383 DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
384 dbus::ObjectPath(device_path
),
388 base::Bind(&HandleShillCallFailure
, device_path
, error_callback
));
391 void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
392 const bool allow_roaming
) {
393 cellular_allow_roaming_
= allow_roaming
;
394 ApplyCellularAllowRoamingToShill();
397 void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
398 const std::string
& ip_or_mac_address
,
400 const network_handler::StringResultCallback
& callback
,
401 const network_handler::ErrorCallback
& error_callback
) {
402 const DeviceState
* device_state
=
403 network_state_handler_
->GetDeviceStateByType(NetworkTypePattern::WiFi());
405 if (error_callback
.is_null())
407 scoped_ptr
<base::DictionaryValue
> error_data(new base::DictionaryValue
);
408 error_data
->SetString(network_handler::kErrorName
, kErrorDeviceMissing
);
409 error_callback
.Run(kErrorDeviceMissing
, error_data
.Pass());
412 TDLSOperationParams params
;
413 params
.operation
= enabled
? shill::kTDLSSetupOperation
414 : shill::kTDLSTeardownOperation
;
415 params
.ip_or_mac_address
= ip_or_mac_address
;
416 CallPerformTDLSOperation(
417 device_state
->path(), params
, callback
, error_callback
);
420 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
421 const std::string
& ip_or_mac_address
,
422 const network_handler::StringResultCallback
& callback
,
423 const network_handler::ErrorCallback
& error_callback
) {
424 const DeviceState
* device_state
=
425 network_state_handler_
->GetDeviceStateByType(NetworkTypePattern::WiFi());
427 if (error_callback
.is_null())
429 scoped_ptr
<base::DictionaryValue
> error_data(new base::DictionaryValue
);
430 error_data
->SetString(network_handler::kErrorName
, kErrorDeviceMissing
);
431 error_callback
.Run(kErrorDeviceMissing
, error_data
.Pass());
434 TDLSOperationParams params
;
435 params
.operation
= shill::kTDLSStatusOperation
;
436 params
.ip_or_mac_address
= ip_or_mac_address
;
437 CallPerformTDLSOperation(
438 device_state
->path(), params
, callback
, error_callback
);
441 void NetworkDeviceHandlerImpl::DeviceListChanged() {
442 ApplyCellularAllowRoamingToShill();
445 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
446 : network_state_handler_(NULL
),
447 cellular_allow_roaming_(false) {}
449 void NetworkDeviceHandlerImpl::Init(
450 NetworkStateHandler
* network_state_handler
) {
451 DCHECK(network_state_handler
);
452 network_state_handler_
= network_state_handler
;
453 network_state_handler_
->AddObserver(this, FROM_HERE
);
456 void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
457 NetworkStateHandler::DeviceStateList list
;
458 network_state_handler_
->GetDeviceListByType(NetworkTypePattern::Cellular(),
461 NET_LOG_DEBUG("No cellular device is available",
462 "Roaming is only supported by cellular devices.");
465 for (NetworkStateHandler::DeviceStateList::const_iterator it
= list
.begin();
466 it
!= list
.end(); ++it
) {
467 const DeviceState
* device_state
= *it
;
468 bool current_allow_roaming
= device_state
->allow_roaming();
470 // If roaming is required by the provider, always try to set to true.
471 bool new_device_value
=
472 device_state
->provider_requires_roaming() || cellular_allow_roaming_
;
474 // Only set the value if the current value is different from
475 // |new_device_value|.
476 if (new_device_value
== current_allow_roaming
)
479 SetDevicePropertyInternal(device_state
->path(),
480 shill::kCellularAllowRoamingProperty
,
481 base::FundamentalValue(new_device_value
),
482 base::Bind(&base::DoNothing
),
483 network_handler::ErrorCallback());
487 } // namespace chromeos