Some additional network settings cleanup
[chromium-blink-merge.git] / chromeos / network / network_device_handler_impl.cc
blobac5e47b7a2cb7198dfe5b680659e14ad1718a934
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 network_state_handler_->RemoveObserver(this, FROM_HERE);
258 void NetworkDeviceHandlerImpl::GetDeviceProperties(
259 const std::string& device_path,
260 const network_handler::DictionaryResultCallback& callback,
261 const network_handler::ErrorCallback& error_callback) const {
262 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties(
263 dbus::ObjectPath(device_path),
264 base::Bind(&network_handler::GetPropertiesCallback,
265 callback, error_callback, device_path));
268 void NetworkDeviceHandlerImpl::SetDeviceProperty(
269 const std::string& device_path,
270 const std::string& property_name,
271 const base::Value& value,
272 const base::Closure& callback,
273 const network_handler::ErrorCallback& error_callback) {
274 const char* const property_blacklist[] = {
275 // Must only be changed by policy/owner through.
276 shill::kCellularAllowRoamingProperty
279 for (size_t i = 0; i < arraysize(property_blacklist); ++i) {
280 if (property_name == property_blacklist[i]) {
281 InvokeErrorCallback(
282 device_path,
283 error_callback,
284 "SetDeviceProperty called on blacklisted property " + property_name);
285 return;
289 SetDevicePropertyInternal(
290 device_path, property_name, value, callback, error_callback);
293 void NetworkDeviceHandlerImpl::RequestRefreshIPConfigs(
294 const std::string& device_path,
295 const base::Closure& callback,
296 const network_handler::ErrorCallback& error_callback) {
297 GetDeviceProperties(device_path,
298 base::Bind(&RefreshIPConfigsCallback,
299 callback, error_callback),
300 error_callback);
303 void NetworkDeviceHandlerImpl::ProposeScan(
304 const std::string& device_path,
305 const base::Closure& callback,
306 const network_handler::ErrorCallback& error_callback) {
307 DBusThreadManager::Get()->GetShillDeviceClient()->ProposeScan(
308 dbus::ObjectPath(device_path),
309 base::Bind(&ProposeScanCallback, device_path, callback, error_callback));
312 void NetworkDeviceHandlerImpl::RegisterCellularNetwork(
313 const std::string& device_path,
314 const std::string& network_id,
315 const base::Closure& callback,
316 const network_handler::ErrorCallback& error_callback) {
317 DBusThreadManager::Get()->GetShillDeviceClient()->Register(
318 dbus::ObjectPath(device_path),
319 network_id,
320 callback,
321 base::Bind(&HandleShillCallFailure, device_path, error_callback));
324 void NetworkDeviceHandlerImpl::SetCarrier(
325 const std::string& device_path,
326 const std::string& carrier,
327 const base::Closure& callback,
328 const network_handler::ErrorCallback& error_callback) {
329 DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier(
330 dbus::ObjectPath(device_path),
331 carrier,
332 callback,
333 base::Bind(&HandleShillCallFailure, device_path, error_callback));
336 void NetworkDeviceHandlerImpl::RequirePin(
337 const std::string& device_path,
338 bool require_pin,
339 const std::string& pin,
340 const base::Closure& callback,
341 const network_handler::ErrorCallback& error_callback) {
342 DBusThreadManager::Get()->GetShillDeviceClient()->RequirePin(
343 dbus::ObjectPath(device_path),
344 pin,
345 require_pin,
346 callback,
347 base::Bind(&HandleShillCallFailure, device_path, error_callback));
350 void NetworkDeviceHandlerImpl::EnterPin(
351 const std::string& device_path,
352 const std::string& pin,
353 const base::Closure& callback,
354 const network_handler::ErrorCallback& error_callback) {
355 DBusThreadManager::Get()->GetShillDeviceClient()->EnterPin(
356 dbus::ObjectPath(device_path),
357 pin,
358 callback,
359 base::Bind(&HandleShillCallFailure, device_path, error_callback));
362 void NetworkDeviceHandlerImpl::UnblockPin(
363 const std::string& device_path,
364 const std::string& puk,
365 const std::string& new_pin,
366 const base::Closure& callback,
367 const network_handler::ErrorCallback& error_callback) {
368 DBusThreadManager::Get()->GetShillDeviceClient()->UnblockPin(
369 dbus::ObjectPath(device_path),
370 puk,
371 new_pin,
372 callback,
373 base::Bind(&HandleShillCallFailure, device_path, error_callback));
376 void NetworkDeviceHandlerImpl::ChangePin(
377 const std::string& device_path,
378 const std::string& old_pin,
379 const std::string& new_pin,
380 const base::Closure& callback,
381 const network_handler::ErrorCallback& error_callback) {
382 DBusThreadManager::Get()->GetShillDeviceClient()->ChangePin(
383 dbus::ObjectPath(device_path),
384 old_pin,
385 new_pin,
386 callback,
387 base::Bind(&HandleShillCallFailure, device_path, error_callback));
390 void NetworkDeviceHandlerImpl::SetCellularAllowRoaming(
391 const bool allow_roaming) {
392 cellular_allow_roaming_ = allow_roaming;
393 ApplyCellularAllowRoamingToShill();
396 void NetworkDeviceHandlerImpl::SetWifiTDLSEnabled(
397 const std::string& ip_or_mac_address,
398 bool enabled,
399 const network_handler::StringResultCallback& callback,
400 const network_handler::ErrorCallback& error_callback) {
401 const DeviceState* device_state =
402 network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi());
403 if (!device_state) {
404 if (error_callback.is_null())
405 return;
406 scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue);
407 error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing);
408 error_callback.Run(kErrorDeviceMissing, error_data.Pass());
409 return;
411 TDLSOperationParams params;
412 params.operation = enabled ? shill::kTDLSSetupOperation
413 : shill::kTDLSTeardownOperation;
414 params.ip_or_mac_address = ip_or_mac_address;
415 CallPerformTDLSOperation(
416 device_state->path(), params, callback, error_callback);
419 void NetworkDeviceHandlerImpl::GetWifiTDLSStatus(
420 const std::string& ip_or_mac_address,
421 const network_handler::StringResultCallback& callback,
422 const network_handler::ErrorCallback& error_callback) {
423 const DeviceState* device_state =
424 network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi());
425 if (!device_state) {
426 if (error_callback.is_null())
427 return;
428 scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue);
429 error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing);
430 error_callback.Run(kErrorDeviceMissing, error_data.Pass());
431 return;
433 TDLSOperationParams params;
434 params.operation = shill::kTDLSStatusOperation;
435 params.ip_or_mac_address = ip_or_mac_address;
436 CallPerformTDLSOperation(
437 device_state->path(), params, callback, error_callback);
440 void NetworkDeviceHandlerImpl::DeviceListChanged() {
441 ApplyCellularAllowRoamingToShill();
444 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl()
445 : network_state_handler_(NULL),
446 cellular_allow_roaming_(false) {}
448 void NetworkDeviceHandlerImpl::Init(
449 NetworkStateHandler* network_state_handler) {
450 DCHECK(network_state_handler);
451 network_state_handler_ = network_state_handler;
452 network_state_handler_->AddObserver(this, FROM_HERE);
455 void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() {
456 NetworkStateHandler::DeviceStateList list;
457 network_state_handler_->GetDeviceListByType(NetworkTypePattern::Cellular(),
458 &list);
459 if (list.empty()) {
460 NET_LOG_DEBUG("No cellular device is available",
461 "Roaming is only supported by cellular devices.");
462 return;
464 for (NetworkStateHandler::DeviceStateList::const_iterator it = list.begin();
465 it != list.end(); ++it) {
466 const DeviceState* device_state = *it;
467 bool current_allow_roaming = device_state->allow_roaming();
469 // If roaming is required by the provider, always try to set to true.
470 bool new_device_value =
471 device_state->provider_requires_roaming() || cellular_allow_roaming_;
473 // Only set the value if the current value is different from
474 // |new_device_value|.
475 if (new_device_value == current_allow_roaming)
476 continue;
478 SetDevicePropertyInternal(device_state->path(),
479 shill::kCellularAllowRoamingProperty,
480 base::FundamentalValue(new_device_value),
481 base::Bind(&base::DoNothing),
482 network_handler::ErrorCallback());
486 } // namespace chromeos