ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chromeos / network / network_device_handler_impl.cc
blob3e8c629211f53b533d9e166038258cb823d81579
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/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"
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& 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,
48 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) << "IPConfigs.Refresh Failed: " << call_status << ": "
68 << ipconfig_path;
69 } else {
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",
85 device_path,
86 error_callback,
87 std::string("Missing ") + shill::kIPConfigsProperty, "");
88 return;
91 for (size_t i = 0; i < ip_configs->GetSize(); i++) {
92 std::string ipconfig_path;
93 if (!ip_configs->GetString(i, &ipconfig_path))
94 continue;
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())
104 callback.Run();
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",
115 device_path,
116 error_callback,
117 base::StringPrintf("DBus call failed: %d", call_status), "");
118 return;
120 NET_LOG(EVENT) << "Device.ProposeScan succeeded: " << device_path;
121 if (!callback.is_null())
122 callback.Run();
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),
133 property_name,
134 value,
135 callback,
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;
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;
166 if (params.operation != shill::kTDLSStatusOperation && !result.empty()) {
167 NET_LOG(ERROR) << "Unexpected TDLS result: " + result << ": "
168 << device_path;
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);
181 return;
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;
195 } else {
196 NET_LOG(ERROR) << "Unexpected TDLS operation: " + params.operation;
197 NOTREACHED();
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),
209 request_delay);
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 << ": "
228 << device_path;
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(
235 FROM_HERE,
236 base::Bind(&CallPerformTDLSOperation,
237 device_path, retry_params, callback, error_callback),
238 request_delay);
239 return;
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())
246 return;
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 << ": "
266 << device_path;
267 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation(
268 dbus::ObjectPath(device_path),
269 params.operation,
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));
277 } // namespace
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]) {
307 InvokeErrorCallback(
308 device_path,
309 error_callback,
310 "SetDeviceProperty called on blacklisted property " + property_name);
311 return;
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),
326 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),
345 network_id,
346 callback,
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),
357 carrier,
358 callback,
359 base::Bind(&HandleShillCallFailure, device_path, error_callback));
362 void NetworkDeviceHandlerImpl::RequirePin(
363 const std::string& device_path,
364 bool require_pin,
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),
370 pin,
371 require_pin,
372 callback,
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),
383 pin,
384 callback,
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),
396 puk,
397 new_pin,
398 callback,
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),
410 old_pin,
411 new_pin,
412 callback,
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,
424 bool enabled,
425 const network_handler::StringResultCallback& callback,
426 const network_handler::ErrorCallback& error_callback) {
427 const DeviceState* device_state = GetWifiDeviceState(error_callback);
428 if (!device_state)
429 return;
431 TDLSOperationParams params;
432 params.operation =
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);
444 if (!device_state)
445 return;
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);
459 if (!device_state)
460 return;
462 DBusThreadManager::Get()->GetShillDeviceClient()->AddWakeOnPacketConnection(
463 dbus::ObjectPath(device_state->path()),
464 ip_endpoint,
465 callback,
466 base::Bind(&HandleShillCallFailure,
467 device_state->path(),
468 error_callback));
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);
476 if (!device_state)
477 return;
479 DBusThreadManager::Get()
480 ->GetShillDeviceClient()
481 ->RemoveWakeOnPacketConnection(dbus::ObjectPath(device_state->path()),
482 ip_endpoint,
483 callback,
484 base::Bind(&HandleShillCallFailure,
485 device_state->path(),
486 error_callback));
489 void NetworkDeviceHandlerImpl::RemoveAllWifiWakeOnPacketConnections(
490 const base::Closure& callback,
491 const network_handler::ErrorCallback& error_callback) {
492 const DeviceState* device_state = GetWifiDeviceState(error_callback);
493 if (!device_state)
494 return;
496 DBusThreadManager::Get()
497 ->GetShillDeviceClient()
498 ->RemoveAllWakeOnPacketConnections(dbus::ObjectPath(device_state->path()),
499 callback,
500 base::Bind(&HandleShillCallFailure,
501 device_state->path(),
502 error_callback));
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(),
523 &list);
524 if (list.empty()) {
525 NET_LOG(DEBUG) << "No cellular device available. Roaming is only supported "
526 "by cellular devices.";
527 return;
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)
541 continue;
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());
555 if (!device_state) {
556 if (error_callback.is_null())
557 return 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());
561 return NULL;
564 return device_state;
567 } // namespace chromeos