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. 4 5 #include "chromeos/network/network_device_handler_impl.h" 6 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" 21 22 namespace chromeos { 23 24 namespace { 25 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; 40 } 41 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); 49 } 50 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); 62 } 63 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); 72 } 73 } 74 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; 90 } 91 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)); 99 } 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(); 106 } 107 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; 120 } 121 NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path); 122 if (!callback.is_null()) 123 callback.Run(); 124 } 125 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)); 138 } 139 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; 146 }; 147 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); 154 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; 169 } 170 171 if (!result.empty()) 172 NET_LOG_ERROR("Unexpected TDLS result: " + result, device_path); 173 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; 178 179 const int64 kRequestStatusDelayMs = 500; 180 base::TimeDelta request_delay; 181 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()) 182 request_delay = base::TimeDelta::FromMilliseconds(kRequestStatusDelayMs); 183 184 base::MessageLoopProxy::current()->PostDelayedTask( 185 FROM_HERE, 186 base::Bind(&CallPerformTDLSOperation, 187 device_path, status_params, callback, error_callback), 188 request_delay); 189 } 190 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); 211 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; 218 } 219 220 NET_LOG_ERROR("TDLS Error:" + dbus_error_name + ":" + dbus_error_message, 221 device_path); 222 if (error_callback.is_null()) 223 return; 224 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()); 234 } 235 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)); 250 } 251 252 } // namespace 253 254 NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() { 255 network_state_handler_->RemoveObserver(this, FROM_HERE); 256 } 257 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)); 266 } 267 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 277 }; 278 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; 286 } 287 } 288 289 SetDevicePropertyInternal( 290 device_path, property_name, value, callback, error_callback); 291 } 292 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); 301 } 302 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)); 310 } 311 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)); 322 } 323 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)); 334 } 335 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)); 348 } 349 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)); 360 } 361 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)); 374 } 375 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)); 388 } 389 390 void NetworkDeviceHandlerImpl::SetCellularAllowRoaming( 391 const bool allow_roaming) { 392 cellular_allow_roaming_ = allow_roaming; 393 ApplyCellularAllowRoamingToShill(); 394 } 395 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; 410 } 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); 417 } 418 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; 432 } 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); 438 } 439 440 void NetworkDeviceHandlerImpl::DeviceListChanged() { 441 ApplyCellularAllowRoamingToShill(); 442 } 443 444 NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl() 445 : network_state_handler_(NULL), 446 cellular_allow_roaming_(false) {} 447 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); 453 } 454 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; 463 } 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(); 468 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_; 472 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; 477 478 SetDevicePropertyInternal(device_state->path(), 479 shill::kCellularAllowRoamingProperty, 480 base::FundamentalValue(new_device_value), 481 base::Bind(&base::DoNothing), 482 network_handler::ErrorCallback()); 483 } 484 } 485 486 } // namespace chromeos 487