Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / chromeos / network / network_device_handler_impl.cc
blob177fbcc32fb5d087fa36e747ecf3ae82471a5d1a
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/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"
23 namespace chromeos {
25 namespace {
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,
49 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),
59 device_path,
60 error_callback,
61 shill_error_name,
62 shill_error_message);
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 << ": "
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 NET_LOG(USER) << "Device.SetProperty: " << property_name;
133 DBusThreadManager::Get()->GetShillDeviceClient()->SetProperty(
134 dbus::ObjectPath(device_path),
135 property_name,
136 value,
137 callback,
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;
147 int retry_count;
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;
164 if (!result.empty())
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 << ": "
170 << device_path;
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);
183 return;
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;
197 } else {
198 NET_LOG(ERROR) << "Unexpected TDLS operation: " + params.operation;
199 NOTREACHED();
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),
211 request_delay);
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 << ": "
230 << device_path;
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),
239 request_delay);
240 return;
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())
247 return;
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 << ": "
267 << device_path;
268 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
269 dbus::ObjectPath(device_path),
270 params.operation,
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));
278 } // namespace
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]) {
308 InvokeErrorCallback(
309 device_path,
310 error_callback,
311 "SetDeviceProperty called on blacklisted property " + property_name);
312 return;
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),
327 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),
348 network_id,
349 callback,
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),
362 carrier,
363 callback,
364 base::Bind(&HandleShillCallFailure, device_path, error_callback));
367 void NetworkDeviceHandlerImpl::RequirePin(
368 const std::string& device_path,
369 bool require_pin,
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),
376 pin,
377 require_pin,
378 callback,
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),
390 pin,
391 callback,
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),
404 puk,
405 new_pin,
406 callback,
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),
419 old_pin,
420 new_pin,
421 callback,
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,
433 bool enabled,
434 const network_handler::StringResultCallback& callback,
435 const network_handler::ErrorCallback& error_callback) {
436 const DeviceState* device_state = GetWifiDeviceState(error_callback);
437 if (!device_state)
438 return;
440 TDLSOperationParams params;
441 params.operation =
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);
453 if (!device_state)
454 return;
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);
468 if (!device_state)
469 return;
471 NET_LOG(USER) << "Device.AddWakeOnWifi: " << device_state->path();
472 DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection(
473 dbus::ObjectPath(device_state->path()),
474 ip_endpoint,
475 callback,
476 base::Bind(&HandleShillCallFailure,
477 device_state->path(),
478 error_callback));
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);
486 if (!device_state)
487 return;
489 NET_LOG(USER) << "Device.RemoveWakeOnWifi: " << device_state->path();
490 DBusThreadManager::Get()
491 ->GetShillDeviceClient()
492 ->RemoveWakeOnPacketConnection(dbus::ObjectPath(device_state->path()),
493 ip_endpoint,
494 callback,
495 base::Bind(&HandleShillCallFailure,
496 device_state->path(),
497 error_callback));
500 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
501 const base::Closure& callback,
502 const network_handler::ErrorCallback& error_callback) {
503 const DeviceState* device_state = GetWifiDeviceState(error_callback);
504 if (!device_state)
505 return;
507 NET_LOG(USER) << "Device.RemoveAllWakeOnWifi: " << device_state->path();
508 DBusThreadManager::Get()
509 ->GetShillDeviceClient()
510 ->RemoveAllWakeOnPacketConnections(dbus::ObjectPath(device_state->path()),
511 callback,
512 base::Bind(&HandleShillCallFailure,
513 device_state->path(),
514 error_callback));
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(),
535 &list);
536 if (list.empty()) {
537 NET_LOG(DEBUG) << "No cellular device available. Roaming is only supported "
538 "by cellular devices.";
539 return;
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)
553 continue;
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());
567 if (!device_state) {
568 if (error_callback.is_null())
569 return 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());
573 return NULL;
576 return device_state;
579 } // namespace chromeos