Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / chromeos / network / network_device_handler_impl.cc
blobfb66d903088bb97bf7673351704284fb0240c754
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"
7 #include "base/bind.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"
22 namespace chromeos {
24 namespace {
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),
58 device_path,
59 error_callback,
60 shill_error_name,
61 shill_error_message);
64 void IPConfigRefreshCallback(const std::string& ipconfig_path,
65 DBusMethodCallStatus call_status) {
66 if (call_status != DBUS_METHOD_CALL_SUCCESS) {
67 NET_LOG_ERROR(
68 base::StringPrintf("IPConfigs.Refresh Failed: %d", call_status),
69 ipconfig_path);
70 } else {
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",
86 device_path,
87 error_callback,
88 std::string("Missing ") + shill::kIPConfigsProperty, "");
89 return;
92 for (size_t i = 0; i < ip_configs->GetSize(); i++) {
93 std::string ipconfig_path;
94 if (!ip_configs->GetString(i, &ipconfig_path))
95 continue;
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())
105 callback.Run();
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",
116 device_path,
117 error_callback,
118 base::StringPrintf("DBus call failed: %d", call_status), "");
119 return;
121 NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path);
122 if (!callback.is_null())
123 callback.Run();
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),
134 property_name,
135 value,
136 callback,
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;
145 int retry_count;
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;
162 if (!result.empty())
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);
168 return;
171 if (!result.empty())
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(
185 FROM_HERE,
186 base::Bind(&CallPerformTDLSOperation,
187 device_path, status_params, callback, error_callback),
188 request_delay);
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),
206 device_path);
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(
213 FROM_HERE,
214 base::Bind(&CallPerformTDLSOperation,
215 device_path, retry_params, callback, error_callback),
216 request_delay);
217 return;
220 NET_LOG_ERROR("TDLS Error:" + dbus_error_name + ":" + dbus_error_message,
221 device_path);
222 if (error_callback.is_null())
223 return;
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),
244 params.operation,
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));
252 } // namespace
254 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() {
255 if (network_state_handler_)
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]) {
282 InvokeErrorCallback(
283 device_path,
284 error_callback,
285 "SetDeviceProperty called on blacklisted property " + property_name);
286 return;
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),
301 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),
320 network_id,
321 callback,
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),
332 carrier,
333 callback,
334 base::Bind(&HandleShillCallFailure, device_path, error_callback));
337 void NetworkDeviceHandlerImpl::RequirePin(
338 const std::string& device_path,
339 bool require_pin,
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),
345 pin,
346 require_pin,
347 callback,
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),
358 pin,
359 callback,
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),
371 puk,
372 new_pin,
373 callback,
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),
385 old_pin,
386 new_pin,
387 callback,
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,
399 bool enabled,
400 const network_handler::StringResultCallback& callback,
401 const network_handler::ErrorCallback& error_callback) {
402 const DeviceState* device_state = GetWifiDeviceState(error_callback);
403 if (!device_state)
404 return;
406 TDLSOperationParams params;
407 params.operation = enabled ? shill::kTDLSSetupOperation
408 : shill::kTDLSTeardownOperation;
409 params.ip_or_mac_address = ip_or_mac_address;
410 CallPerformTDLSOperation(
411 device_state->path(), params, callback, error_callback);
414 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
415 const std::string& ip_or_mac_address,
416 const network_handler::StringResultCallback& callback,
417 const network_handler::ErrorCallback& error_callback) {
418 const DeviceState* device_state = GetWifiDeviceState(error_callback);
419 if (!device_state)
420 return;
422 TDLSOperationParams params;
423 params.operation = shill::kTDLSStatusOperation;
424 params.ip_or_mac_address = ip_or_mac_address;
425 CallPerformTDLSOperation(
426 device_state->path(), params, callback, error_callback);
429 void NetworkDeviceHandlerImpl::AddWifiWakeOnPacketConnection(
430 const net::IPEndPoint& ip_endpoint,
431 const base::Closure& callback,
432 const network_handler::ErrorCallback& error_callback) {
433 const DeviceState* device_state = GetWifiDeviceState(error_callback);
434 if (!device_state)
435 return;
437 DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection(
438 dbus::ObjectPath(device_state->path()),
439 ip_endpoint,
440 callback,
441 base::Bind(&HandleShillCallFailure,
442 device_state->path(),
443 error_callback));
446 void NetworkDeviceHandlerImpl::RemoveWifiWakeOnPacketConnection(
447 const net::IPEndPoint& ip_endpoint,
448 const base::Closure& callback,
449 const network_handler::ErrorCallback& error_callback) {
450 const DeviceState* device_state = GetWifiDeviceState(error_callback);
451 if (!device_state)
452 return;
454 DBusThreadManager::Get()
455 ->GetShillDeviceClient()
456 ->RemoveWakeOnPacketConnection(dbus::ObjectPath(device_state->path()),
457 ip_endpoint,
458 callback,
459 base::Bind(&HandleShillCallFailure,
460 device_state->path(),
461 error_callback));
464 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
465 const base::Closure& callback,
466 const network_handler::ErrorCallback& error_callback) {
467 const DeviceState* device_state = GetWifiDeviceState(error_callback);
468 if (!device_state)
469 return;
471 DBusThreadManager::Get()
472 ->GetShillDeviceClient()
473 ->RemoveAllWakeOnPacketConnections(dbus::ObjectPath(device_state->path()),
474 callback,
475 base::Bind(&HandleShillCallFailure,
476 device_state->path(),
477 error_callback));
480 void NetworkDeviceHandlerImpl::DeviceListChanged() {
481 ApplyCellularAllowRoamingToShill();
484 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
485 : network_state_handler_(NULL),
486 cellular_allow_roaming_(false) {}
488 void NetworkDeviceHandlerImpl::Init(
489 NetworkStateHandler* network_state_handler) {
490 DCHECK(network_state_handler);
491 network_state_handler_ = network_state_handler;
492 network_state_handler_->AddObserver(this, FROM_HERE);
495 void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
496 NetworkStateHandler::DeviceStateList list;
497 network_state_handler_->GetDeviceListByType(NetworkTypePattern::Cellular(),
498 &list);
499 if (list.empty()) {
500 NET_LOG_DEBUG("No cellular device is available",
501 "Roaming is only supported by cellular devices.");
502 return;
504 for (NetworkStateHandler::DeviceStateList::const_iterator it = list.begin();
505 it != list.end(); ++it) {
506 const DeviceState* device_state = *it;
507 bool current_allow_roaming = device_state->allow_roaming();
509 // If roaming is required by the provider, always try to set to true.
510 bool new_device_value =
511 device_state->provider_requires_roaming() || cellular_allow_roaming_;
513 // Only set the value if the current value is different from
514 // |new_device_value|.
515 if (new_device_value == current_allow_roaming)
516 continue;
518 SetDevicePropertyInternal(device_state->path(),
519 shill::kCellularAllowRoamingProperty,
520 base::FundamentalValue(new_device_value),
521 base::Bind(&base::DoNothing),
522 network_handler::ErrorCallback());
526 const DeviceState* NetworkDeviceHandlerImpl::GetWifiDeviceState(
527 const network_handler::ErrorCallback& error_callback) {
528 const DeviceState* device_state =
529 network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi());
530 if (!device_state) {
531 if (error_callback.is_null())
532 return NULL;
533 scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue);
534 error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing);
535 error_callback.Run(kErrorDeviceMissing, error_data.Pass());
536 return NULL;
539 return device_state;
542 } // namespace chromeos