network_device_handler_impl.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy// Copyright 2013 The Chromium Authors. All rights reserved. 2c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy// Use of this source code is governed by a BSD-style license that can be 3c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy// found in the LICENSE file. 4c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy 5c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/network/network_device_handler_impl.h" 6c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy 7c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "base/bind.h" 8c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "base/location.h" 9c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "base/message_loop/message_loop_proxy.h" 10c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "base/time/time.h" 11c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "base/values.h" 12c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/dbus/dbus_thread_manager.h" 13c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/dbus/shill_device_client.h" 14c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/dbus/shill_ipconfig_client.h" 15c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/network/device_state.h" 16c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/network/network_event_log.h" 17c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/network/network_handler_callbacks.h" 18c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/network/network_state_handler.h" 19c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "chromeos/network/shill_property_util.h" 20c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "dbus/object_path.h" 21c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy#include "third_party/cros_system_api/dbus/service_constants.h" 22c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy 23a60c3889718f4513a6c9d8b80f655db5d6346905Romain Guynamespace chromeos { 24a60c3889718f4513a6c9d8b80f655db5d6346905Romain Guy 25a60c3889718f4513a6c9d8b80f655db5d6346905Romain Guynamespace { 26c9855a53edfac818dc68714557185977556f849dRomain Guy 27c9855a53edfac818dc68714557185977556f849dRomain Guystd::string GetErrorNameForShillError(const std::string& shill_error_name) { 28c9855a53edfac818dc68714557185977556f849dRomain Guy if (shill_error_name == shill::kErrorResultFailure) 29c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy return NetworkDeviceHandler::kErrorFailure; 30c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy if (shill_error_name == shill::kErrorResultNotSupported) 31c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy return NetworkDeviceHandler::kErrorNotSupported; 32bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy if (shill_error_name == shill::kErrorResultIncorrectPin) 339c10ab03cd6a35fca9eec617b9bd444d13544b99Romain Guy return NetworkDeviceHandler::kErrorIncorrectPin; 34bdf7609867a3f886455c51dba91623a86cceb6e2Romain Guy if (shill_error_name == shill::kErrorResultPinBlocked) 35aaceeb0c5be11121a81e44b9633c06fc5c0fcd4dRomain Guy return NetworkDeviceHandler::kErrorPinBlocked; 36c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy if (shill_error_name == shill::kErrorResultPinRequired) 37c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy return NetworkDeviceHandler::kErrorPinRequired; 38735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy if (shill_error_name == shill::kErrorResultNotFound) 39735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy return NetworkDeviceHandler::kErrorDeviceMissing; 40735738c4ddf3229caa5f6e634bf591953ac29944Romain Guy return NetworkDeviceHandler::kErrorUnknown; 41c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy} 42c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy 43c15008e72ec00ca20a271c3006dac649fd07533bRomain Guyvoid InvokeErrorCallback(const std::string& service_path, 44c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy const network_handler::ErrorCallback& error_callback, 45c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy const std::string& error_name) { 46c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy std::string error_msg = "Device Error: " + error_name; 478d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy NET_LOG_ERROR(error_msg, service_path); 488d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy network_handler::RunErrorCallback( 498d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy error_callback, service_path, error_name, error_msg); 503bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy} 513ff0bfdd144bba3b023eda8c49b25fb0d0de8653Romain Guy 523bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyvoid HandleShillCallFailure( 533bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy const std::string& device_path, 54aaceeb0c5be11121a81e44b9633c06fc5c0fcd4dRomain Guy const network_handler::ErrorCallback& error_callback, 55c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy const std::string& shill_error_name, 56a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy const std::string& shill_error_message) { 57a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy network_handler::ShillErrorCallbackFunction( 58a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy GetErrorNameForShillError(shill_error_name), 59fb13abd800cd610c7f46815848545feff83e5748Romain Guy device_path, 60fb13abd800cd610c7f46815848545feff83e5748Romain Guy error_callback, 61fb13abd800cd610c7f46815848545feff83e5748Romain Guy shill_error_name, 62fb13abd800cd610c7f46815848545feff83e5748Romain Guy shill_error_message); 63c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy} 6401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 65c46d07a29e94807e768f8b162ce9f77a88ba6f46Romain Guyvoid IPConfigRefreshCallback(const std::string& ipconfig_path, 6601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy DBusMethodCallStatus call_status) { 67c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy if (call_status != DBUS_METHOD_CALL_SUCCESS) { 68c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy NET_LOG_ERROR( 69c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy base::StringPrintf("IPConfigs.Refresh Failed: %d", call_status), 701fc883b271707c4206ae20cc9a935d7bd4a7485eRomain Guy ipconfig_path); 711fc883b271707c4206ae20cc9a935d7bd4a7485eRomain Guy } else { 721fc883b271707c4206ae20cc9a935d7bd4a7485eRomain Guy NET_LOG_EVENT("IPConfigs.Refresh Succeeded", ipconfig_path); 73b629490ffb21752750cc081827ca4c1eae1eb015Romain Guy } 74b629490ffb21752750cc081827ca4c1eae1eb015Romain Guy} 75b629490ffb21752750cc081827ca4c1eae1eb015Romain Guy 76c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikvoid RefreshIPConfigsCallback( 77c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const base::Closure& callback, 78c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik const network_handler::ErrorCallback& error_callback, 79ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy const std::string& device_path, 80ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy const base::DictionaryValue& properties) { 81ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy const base::ListValue* ip_configs; 828a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy if (!properties.GetListWithoutPathExpansion( 838a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy shill::kIPConfigsProperty, &ip_configs)) { 848a4ac610e1aaf04931ac1af54b146a7fc8e66114Romain Guy NET_LOG_ERROR("RequestRefreshIPConfigs Failed", device_path); 8562d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik network_handler::ShillErrorCallbackFunction( 8662d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik "RequestRefreshIPConfigs Failed", 8762d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik device_path, 88527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik error_callback, 89527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik std::string("Missing ") + shill::kIPConfigsProperty, ""); 90527a3aace1dd72432c2e0472a570e030ad04bf16Chris Craik return; 9155bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui } 9255bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui 9355bfb4e728fe1db619af5d2c287f4abe711b3343ztenghui for (size_t i = 0; i < ip_configs->GetSize(); i++) { 94c9855a53edfac818dc68714557185977556f849dRomain Guy std::string ipconfig_path; 955baa3a62a97544669fba6d65a11c07f252e654ddSteve Block if (!ip_configs->GetString(i, &ipconfig_path)) 96c9855a53edfac818dc68714557185977556f849dRomain Guy continue; 97c9855a53edfac818dc68714557185977556f849dRomain Guy DBusThreadManager::Get()->GetShillIPConfigClient()->Refresh( 98c9855a53edfac818dc68714557185977556f849dRomain Guy dbus::ObjectPath(ipconfig_path), 99c9855a53edfac818dc68714557185977556f849dRomain Guy base::Bind(&IPConfigRefreshCallback, ipconfig_path)); 100c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy } 101 // It is safe to invoke |callback| here instead of waiting for the 102 // IPConfig.Refresh callbacks to complete because the Refresh DBus calls will 103 // be executed in order and thus before any further DBus requests that 104 // |callback| may issue. 105 if (!callback.is_null()) 106 callback.Run(); 107} 108 109void ProposeScanCallback( 110 const std::string& device_path, 111 const base::Closure& callback, 112 const network_handler::ErrorCallback& error_callback, 113 DBusMethodCallStatus call_status) { 114 if (call_status != DBUS_METHOD_CALL_SUCCESS) { 115 network_handler::ShillErrorCallbackFunction( 116 "Device.ProposeScan Failed", 117 device_path, 118 error_callback, 119 base::StringPrintf("DBus call failed: %d", call_status), ""); 120 return; 121 } 122 NET_LOG_EVENT("Device.ProposeScan succeeded.", device_path); 123 if (!callback.is_null()) 124 callback.Run(); 125} 126 127void SetDevicePropertyInternal( 128 const std::string& device_path, 129 const std::string& property_name, 130 const base::Value& value, 131 const base::Closure& callback, 132 const network_handler::ErrorCallback& error_callback) { 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)); 139} 140 141// Struct containing TDLS Operation parameters. 142struct TDLSOperationParams { 143 TDLSOperationParams() : retry_count(0) {} 144 std::string operation; 145 std::string ip_or_mac_address; 146 int retry_count; 147}; 148 149// Forward declare for PostDelayedTask. 150void CallPerformTDLSOperation( 151 const std::string& device_path, 152 const TDLSOperationParams& params, 153 const network_handler::StringResultCallback& callback, 154 const network_handler::ErrorCallback& error_callback); 155 156void TDLSSuccessCallback( 157 const std::string& device_path, 158 const TDLSOperationParams& params, 159 const network_handler::StringResultCallback& callback, 160 const network_handler::ErrorCallback& error_callback, 161 const std::string& result) { 162 std::string event_desc = "TDLSSuccessCallback: " + params.operation; 163 if (!result.empty()) 164 event_desc += ": " + result; 165 NET_LOG_EVENT(event_desc, device_path); 166 if (params.operation != shill::kTDLSSetupOperation) { 167 if (!callback.is_null()) 168 callback.Run(result); 169 return; 170 } 171 172 if (!result.empty()) 173 NET_LOG_ERROR("Unexpected TDLS result: " + result, device_path); 174 175 // Send a delayed Status request after a successful Setup call. 176 TDLSOperationParams status_params; 177 status_params.operation = shill::kTDLSStatusOperation; 178 status_params.ip_or_mac_address = params.ip_or_mac_address; 179 180 const int64 kRequestStatusDelayMs = 500; 181 base::TimeDelta request_delay; 182 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()) 183 request_delay = base::TimeDelta::FromMilliseconds(kRequestStatusDelayMs); 184 185 base::MessageLoopProxy::current()->PostDelayedTask( 186 FROM_HERE, 187 base::Bind(&CallPerformTDLSOperation, 188 device_path, status_params, callback, error_callback), 189 request_delay); 190} 191 192void TDLSErrorCallback( 193 const std::string& device_path, 194 const TDLSOperationParams& params, 195 const network_handler::StringResultCallback& callback, 196 const network_handler::ErrorCallback& error_callback, 197 const std::string& dbus_error_name, 198 const std::string& dbus_error_message) { 199 // If a Setup operation receives an InProgress error, retry. 200 const int kMaxRetries = 5; 201 if (params.operation == shill::kTDLSSetupOperation && 202 dbus_error_name == shill::kErrorResultInProgress && 203 params.retry_count < kMaxRetries) { 204 TDLSOperationParams retry_params = params; 205 ++retry_params.retry_count; 206 NET_LOG_EVENT(base::StringPrintf("TDLS Retry: %d", params.retry_count), 207 device_path); 208 const int64 kReRequestDelayMs = 1000; 209 base::TimeDelta request_delay; 210 if (!DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()) 211 request_delay = base::TimeDelta::FromMilliseconds(kReRequestDelayMs); 212 213 base::MessageLoopProxy::current()->PostDelayedTask( 214 FROM_HERE, 215 base::Bind(&CallPerformTDLSOperation, 216 device_path, retry_params, callback, error_callback), 217 request_delay); 218 return; 219 } 220 221 NET_LOG_ERROR("TDLS Error:" + dbus_error_name + ":" + dbus_error_message, 222 device_path); 223 if (error_callback.is_null()) 224 return; 225 226 const std::string error_name = 227 dbus_error_name == shill::kErrorResultInProgress ? 228 NetworkDeviceHandler::kErrorTimeout : NetworkDeviceHandler::kErrorUnknown; 229 const std::string& error_detail = params.ip_or_mac_address; 230 scoped_ptr<base::DictionaryValue> error_data( 231 network_handler::CreateDBusErrorData( 232 device_path, error_name, error_detail, 233 dbus_error_name, dbus_error_message)); 234 error_callback.Run(error_name, error_data.Pass()); 235} 236 237void CallPerformTDLSOperation( 238 const std::string& device_path, 239 const TDLSOperationParams& params, 240 const network_handler::StringResultCallback& callback, 241 const network_handler::ErrorCallback& error_callback) { 242 NET_LOG_EVENT("CallPerformTDLSOperation: " + params.operation, device_path); 243 DBusThreadManager::Get()->GetShillDeviceClient()->PerformTDLSOperation( 244 dbus::ObjectPath(device_path), 245 params.operation, 246 params.ip_or_mac_address, 247 base::Bind(&TDLSSuccessCallback, 248 device_path, params, callback, error_callback), 249 base::Bind(&TDLSErrorCallback, 250 device_path, params, callback, error_callback)); 251} 252 253} // namespace 254 255NetworkDeviceHandlerImpl::~NetworkDeviceHandlerImpl() { 256 network_state_handler_->RemoveObserver(this, FROM_HERE); 257} 258 259void 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)); 267} 268 269void 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 278 }; 279 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; 287 } 288 } 289 290 SetDevicePropertyInternal( 291 device_path, property_name, value, callback, error_callback); 292} 293 294void 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); 302} 303 304void 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)); 311} 312 313void 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)); 323} 324 325void 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)); 335} 336 337void 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)); 349} 350 351void 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)); 361} 362 363void 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)); 375} 376 377void 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)); 389} 390 391void NetworkDeviceHandlerImpl::SetCellularAllowRoaming( 392 const bool allow_roaming) { 393 cellular_allow_roaming_ = allow_roaming; 394 ApplyCellularAllowRoamingToShill(); 395} 396 397void 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 = 403 network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi()); 404 if (!device_state) { 405 if (error_callback.is_null()) 406 return; 407 scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue); 408 error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing); 409 error_callback.Run(kErrorDeviceMissing, error_data.Pass()); 410 return; 411 } 412 TDLSOperationParams params; 413 params.operation = enabled ? shill::kTDLSSetupOperation 414 : shill::kTDLSTeardownOperation; 415 params.ip_or_mac_address = ip_or_mac_address; 416 CallPerformTDLSOperation( 417 device_state->path(), params, callback, error_callback); 418} 419 420void NetworkDeviceHandlerImpl::GetWifiTDLSStatus( 421 const std::string& ip_or_mac_address, 422 const network_handler::StringResultCallback& callback, 423 const network_handler::ErrorCallback& error_callback) { 424 const DeviceState* device_state = 425 network_state_handler_->GetDeviceStateByType(NetworkTypePattern::WiFi()); 426 if (!device_state) { 427 if (error_callback.is_null()) 428 return; 429 scoped_ptr<base::DictionaryValue> error_data(new base::DictionaryValue); 430 error_data->SetString(network_handler::kErrorName, kErrorDeviceMissing); 431 error_callback.Run(kErrorDeviceMissing, error_data.Pass()); 432 return; 433 } 434 TDLSOperationParams params; 435 params.operation = shill::kTDLSStatusOperation; 436 params.ip_or_mac_address = ip_or_mac_address; 437 CallPerformTDLSOperation( 438 device_state->path(), params, callback, error_callback); 439} 440 441void NetworkDeviceHandlerImpl::DeviceListChanged() { 442 ApplyCellularAllowRoamingToShill(); 443} 444 445NetworkDeviceHandlerImpl::NetworkDeviceHandlerImpl() 446 : network_state_handler_(NULL), 447 cellular_allow_roaming_(false) {} 448 449void NetworkDeviceHandlerImpl::Init( 450 NetworkStateHandler* network_state_handler) { 451 DCHECK(network_state_handler); 452 network_state_handler_ = network_state_handler; 453 network_state_handler_->AddObserver(this, FROM_HERE); 454} 455 456void NetworkDeviceHandlerImpl::ApplyCellularAllowRoamingToShill() { 457 NetworkStateHandler::DeviceStateList list; 458 network_state_handler_->GetDeviceListByType(NetworkTypePattern::Cellular(), 459 &list); 460 if (list.empty()) { 461 NET_LOG_DEBUG("No cellular device is available", 462 "Roaming is only supported by cellular devices."); 463 return; 464 } 465 for (NetworkStateHandler::DeviceStateList::const_iterator it = list.begin(); 466 it != list.end(); ++it) { 467 const DeviceState* device_state = *it; 468 bool current_device_value; 469 if (!device_state->properties().GetBooleanWithoutPathExpansion( 470 shill::kCellularAllowRoamingProperty, ¤t_device_value)) { 471 NET_LOG_ERROR( 472 "Could not get \"allow roaming\" property from cellular " 473 "device.", 474 device_state->path()); 475 continue; 476 } 477 478 // If roaming is required by the provider, always try to set to true. 479 bool new_device_value = 480 device_state->provider_requires_roaming() || cellular_allow_roaming_; 481 482 // Only set the value if the current value is different from 483 // |new_device_value|. 484 if (new_device_value == current_device_value) 485 continue; 486 487 SetDevicePropertyInternal(device_state->path(), 488 shill::kCellularAllowRoamingProperty, 489 base::FundamentalValue(new_device_value), 490 base::Bind(&base::DoNothing), 491 network_handler::ErrorCallback()); 492 } 493} 494 495} // namespace chromeos 496