1 // Copyright (c) 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_connection_handler.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "base/json/json_reader.h" 10 #include "chromeos/chromeos_switches.h" 11 #include "chromeos/dbus/dbus_thread_manager.h" 12 #include "chromeos/dbus/shill_manager_client.h" 13 #include "chromeos/dbus/shill_service_client.h" 14 #include "chromeos/network/client_cert_util.h" 15 #include "chromeos/network/managed_network_configuration_handler.h" 16 #include "chromeos/network/network_configuration_handler.h" 17 #include "chromeos/network/network_event_log.h" 18 #include "chromeos/network/network_handler_callbacks.h" 19 #include "chromeos/network/network_state.h" 20 #include "chromeos/network/network_state_handler.h" 21 #include "chromeos/network/network_ui_data.h" 22 #include "dbus/object_path.h" 23 #include "net/cert/x509_certificate.h" 24 #include "third_party/cros_system_api/dbus/service_constants.h" 25 26 namespace chromeos { 27 28 namespace { 29 30 void InvokeErrorCallback(const std::string& service_path, 31 const network_handler::ErrorCallback& error_callback, 32 const std::string& error_name) { 33 std::string error_msg = "Connect Error: " + error_name; 34 NET_LOG_ERROR(error_msg, service_path); 35 if (error_callback.is_null()) 36 return; 37 scoped_ptr<base::DictionaryValue> error_data( 38 network_handler::CreateErrorData(service_path, error_name, error_msg)); 39 error_callback.Run(error_name, error_data.Pass()); 40 } 41 42 bool IsAuthenticationError(const std::string& error) { 43 return (error == flimflam::kErrorBadWEPKey || 44 error == flimflam::kErrorPppAuthFailed || 45 error == shill::kErrorEapLocalTlsFailed || 46 error == shill::kErrorEapRemoteTlsFailed || 47 error == shill::kErrorEapAuthenticationFailed); 48 } 49 50 void CopyStringFromDictionary(const base::DictionaryValue& source, 51 const std::string& key, 52 base::DictionaryValue* dest) { 53 std::string string_value; 54 if (source.GetStringWithoutPathExpansion(key, &string_value)) 55 dest->SetStringWithoutPathExpansion(key, string_value); 56 } 57 58 bool NetworkRequiresActivation(const NetworkState* network) { 59 return (network->type() == flimflam::kTypeCellular && 60 ((network->activation_state() != flimflam::kActivationStateActivated && 61 network->activation_state() != flimflam::kActivationStateUnknown))); 62 } 63 64 bool VPNIsConfigured(const std::string& service_path, 65 const std::string& provider_type, 66 const base::DictionaryValue& provider_properties) { 67 if (provider_type == flimflam::kProviderOpenVpn) { 68 std::string hostname; 69 provider_properties.GetStringWithoutPathExpansion( 70 flimflam::kHostProperty, &hostname); 71 if (hostname.empty()) { 72 NET_LOG_EVENT("OpenVPN: No hostname", service_path); 73 return false; 74 } 75 std::string username; 76 provider_properties.GetStringWithoutPathExpansion( 77 flimflam::kOpenVPNUserProperty, &username); 78 if (username.empty()) { 79 NET_LOG_EVENT("OpenVPN: No username", service_path); 80 return false; 81 } 82 bool passphrase_required = false; 83 provider_properties.GetBooleanWithoutPathExpansion( 84 flimflam::kPassphraseRequiredProperty, &passphrase_required); 85 if (passphrase_required) { 86 NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path); 87 return false; 88 } 89 NET_LOG_EVENT("OpenVPN Is Configured", service_path); 90 } else { 91 bool passphrase_required = false; 92 std::string passphrase; 93 provider_properties.GetBooleanWithoutPathExpansion( 94 flimflam::kL2tpIpsecPskRequiredProperty, &passphrase_required); 95 if (passphrase_required) { 96 NET_LOG_EVENT("VPN: Passphrase Required", service_path); 97 return false; 98 } 99 NET_LOG_EVENT("VPN Is Configured", service_path); 100 } 101 return true; 102 } 103 104 } // namespace 105 106 const char NetworkConnectionHandler::kErrorNotFound[] = "not-found"; 107 const char NetworkConnectionHandler::kErrorConnected[] = "connected"; 108 const char NetworkConnectionHandler::kErrorConnecting[] = "connecting"; 109 const char NetworkConnectionHandler::kErrorNotConnected[] = "not-connected"; 110 const char NetworkConnectionHandler::kErrorPassphraseRequired[] = 111 "passphrase-required"; 112 const char NetworkConnectionHandler::kErrorActivationRequired[] = 113 "activation-required"; 114 const char NetworkConnectionHandler::kErrorCertificateRequired[] = 115 "certificate-required"; 116 const char NetworkConnectionHandler::kErrorConfigurationRequired[] = 117 "configuration-required"; 118 const char NetworkConnectionHandler::kErrorAuthenticationRequired[] = 119 "authentication-required"; 120 const char NetworkConnectionHandler::kErrorShillError[] = "shill-error"; 121 const char NetworkConnectionHandler::kErrorConfigureFailed[] = 122 "configure-failed"; 123 const char NetworkConnectionHandler::kErrorConnectCanceled[] = 124 "connect-canceled"; 125 126 struct NetworkConnectionHandler::ConnectRequest { 127 ConnectRequest(const std::string& service_path, 128 const base::Closure& success, 129 const network_handler::ErrorCallback& error) 130 : service_path(service_path), 131 connect_state(CONNECT_REQUESTED), 132 success_callback(success), 133 error_callback(error) { 134 } 135 enum ConnectState { 136 CONNECT_REQUESTED = 0, 137 CONNECT_STARTED = 1, 138 CONNECT_CONNECTING = 2 139 }; 140 std::string service_path; 141 ConnectState connect_state; 142 base::Closure success_callback; 143 network_handler::ErrorCallback error_callback; 144 }; 145 146 NetworkConnectionHandler::NetworkConnectionHandler() 147 : cert_loader_(NULL), 148 network_state_handler_(NULL), 149 network_configuration_handler_(NULL), 150 logged_in_(false), 151 certificates_loaded_(false) { 152 } 153 154 NetworkConnectionHandler::~NetworkConnectionHandler() { 155 if (network_state_handler_) 156 network_state_handler_->RemoveObserver(this, FROM_HERE); 157 if (cert_loader_) 158 cert_loader_->RemoveObserver(this); 159 if (LoginState::IsInitialized()) 160 LoginState::Get()->RemoveObserver(this); 161 } 162 163 void NetworkConnectionHandler::Init( 164 NetworkStateHandler* network_state_handler, 165 NetworkConfigurationHandler* network_configuration_handler) { 166 if (LoginState::IsInitialized()) { 167 LoginState::Get()->AddObserver(this); 168 logged_in_ = 169 LoginState::Get()->GetLoggedInState() == LoginState::LOGGED_IN_ACTIVE; 170 } 171 if (CertLoader::IsInitialized()) { 172 cert_loader_ = CertLoader::Get(); 173 cert_loader_->AddObserver(this); 174 certificates_loaded_ = cert_loader_->certificates_loaded(); 175 } else { 176 // TODO(stevenjb): Require a mock or stub cert_loader in tests. 177 certificates_loaded_ = true; 178 } 179 if (network_state_handler) { 180 network_state_handler_ = network_state_handler; 181 network_state_handler_->AddObserver(this, FROM_HERE); 182 } 183 network_configuration_handler_ = network_configuration_handler; 184 } 185 186 void NetworkConnectionHandler::LoggedInStateChanged( 187 LoginState::LoggedInState state) { 188 if (state == LoginState::LOGGED_IN_ACTIVE) { 189 logged_in_ = true; 190 NET_LOG_EVENT("Logged In", ""); 191 } 192 } 193 194 void NetworkConnectionHandler::OnCertificatesLoaded( 195 const net::CertificateList& cert_list, 196 bool initial_load) { 197 certificates_loaded_ = true; 198 NET_LOG_EVENT("Certificates Loaded", ""); 199 if (queued_connect_) { 200 NET_LOG_EVENT("Connecting to Queued Network", 201 queued_connect_->service_path); 202 ConnectToNetwork(queued_connect_->service_path, 203 queued_connect_->success_callback, 204 queued_connect_->error_callback, 205 false /* check_error_state */); 206 } else if (initial_load) { 207 // Once certificates have loaded, connect to the "best" available network. 208 network_state_handler_->ConnectToBestWifiNetwork(); 209 } 210 } 211 212 void NetworkConnectionHandler::ConnectToNetwork( 213 const std::string& service_path, 214 const base::Closure& success_callback, 215 const network_handler::ErrorCallback& error_callback, 216 bool check_error_state) { 217 NET_LOG_USER("ConnectToNetwork", service_path); 218 // Clear any existing queued connect request. 219 queued_connect_.reset(); 220 if (HasConnectingNetwork(service_path)) { 221 NET_LOG_USER("Connect Request While Pending", service_path); 222 InvokeErrorCallback(service_path, error_callback, kErrorConnecting); 223 return; 224 } 225 226 // Check cached network state for connected, connecting, or unactivated 227 // networks. These states will not be affected by a recent configuration. 228 // Note: NetworkState may not exist for a network that was recently 229 // configured, in which case these checks do not apply anyway. 230 const NetworkState* network = 231 network_state_handler_->GetNetworkState(service_path); 232 233 if (network) { 234 // For existing networks, perform some immediate consistency checks. 235 if (network->IsConnectedState()) { 236 InvokeErrorCallback(service_path, error_callback, kErrorConnected); 237 return; 238 } 239 if (network->IsConnectingState()) { 240 InvokeErrorCallback(service_path, error_callback, kErrorConnecting); 241 return; 242 } 243 if (NetworkRequiresActivation(network)) { 244 InvokeErrorCallback(service_path, error_callback, 245 kErrorActivationRequired); 246 return; 247 } 248 249 if (check_error_state) { 250 const std::string& error = network->error(); 251 if (error == flimflam::kErrorBadPassphrase) { 252 InvokeErrorCallback(service_path, error_callback, error); 253 return; 254 } 255 if (IsAuthenticationError(error)) { 256 InvokeErrorCallback( 257 service_path, error_callback, kErrorAuthenticationRequired); 258 return; 259 } 260 } 261 } 262 263 // All synchronous checks passed, add |service_path| to connecting list. 264 pending_requests_.insert(std::make_pair( 265 service_path, 266 ConnectRequest(service_path, success_callback, error_callback))); 267 268 // Connect immediately to 'connectable' networks. 269 // TODO(stevenjb): Shill needs to properly set Connectable for VPN. 270 if (network && 271 network->connectable() && network->type() != flimflam::kTypeVPN) { 272 CallShillConnect(service_path); 273 return; 274 } 275 276 // Request additional properties to check. VerifyConfiguredAndConnect will 277 // use only these properties, not cached properties, to ensure that they 278 // are up to date after any recent configuration. 279 network_configuration_handler_->GetProperties( 280 service_path, 281 base::Bind(&NetworkConnectionHandler::VerifyConfiguredAndConnect, 282 AsWeakPtr(), check_error_state), 283 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, 284 AsWeakPtr(), service_path)); 285 } 286 287 void NetworkConnectionHandler::DisconnectNetwork( 288 const std::string& service_path, 289 const base::Closure& success_callback, 290 const network_handler::ErrorCallback& error_callback) { 291 NET_LOG_USER("DisconnectNetwork", service_path); 292 const NetworkState* network = 293 network_state_handler_->GetNetworkState(service_path); 294 if (!network) { 295 InvokeErrorCallback(service_path, error_callback, kErrorNotFound); 296 return; 297 } 298 if (!network->IsConnectedState()) { 299 InvokeErrorCallback(service_path, error_callback, kErrorNotConnected); 300 return; 301 } 302 CallShillDisconnect(service_path, success_callback, error_callback); 303 } 304 305 void NetworkConnectionHandler::ActivateNetwork( 306 const std::string& service_path, 307 const std::string& carrier, 308 const base::Closure& success_callback, 309 const network_handler::ErrorCallback& error_callback) { 310 NET_LOG_USER("DisconnectNetwork", service_path); 311 const NetworkState* network = 312 network_state_handler_->GetNetworkState(service_path); 313 if (!network) { 314 InvokeErrorCallback(service_path, error_callback, kErrorNotFound); 315 return; 316 } 317 CallShillActivate(service_path, carrier, success_callback, error_callback); 318 } 319 320 bool NetworkConnectionHandler::HasConnectingNetwork( 321 const std::string& service_path) { 322 return pending_requests_.count(service_path) != 0; 323 } 324 325 void NetworkConnectionHandler::NetworkListChanged() { 326 CheckAllPendingRequests(); 327 } 328 329 void NetworkConnectionHandler::NetworkPropertiesUpdated( 330 const NetworkState* network) { 331 if (HasConnectingNetwork(network->path())) 332 CheckPendingRequest(network->path()); 333 } 334 335 NetworkConnectionHandler::ConnectRequest* 336 NetworkConnectionHandler::GetPendingRequest(const std::string& service_path) { 337 std::map<std::string, ConnectRequest>::iterator iter = 338 pending_requests_.find(service_path); 339 return iter != pending_requests_.end() ? &(iter->second) : NULL; 340 } 341 342 // ConnectToNetwork implementation 343 344 void NetworkConnectionHandler::VerifyConfiguredAndConnect( 345 bool check_error_state, 346 const std::string& service_path, 347 const base::DictionaryValue& service_properties) { 348 NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path); 349 350 // If 'passphrase_required' is still true, then the 'Passphrase' property 351 // has not been set to a minimum length value. 352 bool passphrase_required = false; 353 service_properties.GetBooleanWithoutPathExpansion( 354 flimflam::kPassphraseRequiredProperty, &passphrase_required); 355 if (passphrase_required) { 356 ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired); 357 return; 358 } 359 360 std::string type, security; 361 service_properties.GetStringWithoutPathExpansion( 362 flimflam::kTypeProperty, &type); 363 service_properties.GetStringWithoutPathExpansion( 364 flimflam::kSecurityProperty, &security); 365 bool connectable = false; 366 service_properties.GetBooleanWithoutPathExpansion( 367 flimflam::kConnectableProperty, &connectable); 368 369 // In case NetworkState was not available in ConnectToNetwork (e.g. it had 370 // been recently configured), we need to check Connectable again. 371 if (connectable && type != flimflam::kTypeVPN) { 372 // TODO(stevenjb): Shill needs to properly set Connectable for VPN. 373 CallShillConnect(service_path); 374 return; 375 } 376 377 // Get VPN provider type and host (required for configuration) and ensure 378 // that required VPN non-cert properties are set. 379 std::string vpn_provider_type, vpn_provider_host; 380 if (type == flimflam::kTypeVPN) { 381 // VPN Provider values are read from the "Provider" dictionary, not the 382 // "Provider.Type", etc keys (which are used only to set the values). 383 const base::DictionaryValue* provider_properties; 384 if (service_properties.GetDictionaryWithoutPathExpansion( 385 flimflam::kProviderProperty, &provider_properties)) { 386 provider_properties->GetStringWithoutPathExpansion( 387 flimflam::kTypeProperty, &vpn_provider_type); 388 provider_properties->GetStringWithoutPathExpansion( 389 flimflam::kHostProperty, &vpn_provider_host); 390 } 391 if (vpn_provider_type.empty() || vpn_provider_host.empty()) { 392 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 393 return; 394 } 395 // VPN requires a host and username to be set. 396 if (!VPNIsConfigured( 397 service_path, vpn_provider_type, *provider_properties)) { 398 NET_LOG_ERROR("VPN Not Configured", service_path); 399 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 400 return; 401 } 402 } 403 404 client_cert::ConfigType client_cert_type = client_cert::CONFIG_TYPE_NONE; 405 if (type == flimflam::kTypeVPN) { 406 if (vpn_provider_type == flimflam::kProviderOpenVpn) 407 client_cert_type = client_cert::CONFIG_TYPE_OPENVPN; 408 else 409 client_cert_type = client_cert::CONFIG_TYPE_IPSEC; 410 } else if (type == flimflam::kTypeWifi && 411 security == flimflam::kSecurity8021x) { 412 client_cert_type = client_cert::CONFIG_TYPE_EAP; 413 } 414 415 base::DictionaryValue config_properties; 416 if (client_cert_type != client_cert::CONFIG_TYPE_NONE) { 417 // If the client certificate must be configured, this will be set to a 418 // non-empty string. 419 std::string pkcs11_id; 420 421 // Check certificate properties in kUIDataProperty if configured. 422 // Note: Wifi/VPNConfigView set these properties explicitly, in which case 423 // only the TPM must be configured. 424 scoped_ptr<NetworkUIData> ui_data = 425 ManagedNetworkConfigurationHandler::GetUIData(service_properties); 426 if (ui_data && ui_data->certificate_type() == CLIENT_CERT_TYPE_PATTERN) { 427 // User must be logged in to connect to a network requiring a certificate. 428 if (!logged_in_ || !cert_loader_) { 429 ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); 430 return; 431 } 432 433 // If certificates have not been loaded yet, queue the connect request. 434 if (!certificates_loaded_) { 435 ConnectRequest* request = GetPendingRequest(service_path); 436 if (!request) { 437 NET_LOG_ERROR("No pending request to queue", service_path); 438 return; 439 } 440 NET_LOG_EVENT("Connect Request Queued", service_path); 441 queued_connect_.reset(new ConnectRequest( 442 service_path, request->success_callback, request->error_callback)); 443 pending_requests_.erase(service_path); 444 return; 445 } 446 447 pkcs11_id = CertificateIsConfigured(ui_data.get()); 448 // Ensure the certificate is available and configured. 449 if (!cert_loader_->IsHardwareBacked() || pkcs11_id.empty()) { 450 ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); 451 return; 452 } 453 } 454 455 // The network may not be 'Connectable' because the TPM properties are not 456 // set up, so configure tpm slot/pin before connecting. 457 if (cert_loader_ && cert_loader_->IsHardwareBacked()) { 458 // Pass NULL if pkcs11_id is empty, so that it doesn't clear any 459 // previously configured client cert. 460 client_cert::SetShillProperties(client_cert_type, 461 cert_loader_->tpm_token_slot(), 462 cert_loader_->tpm_user_pin(), 463 pkcs11_id.empty() ? NULL : &pkcs11_id, 464 &config_properties); 465 } 466 } 467 468 if (!config_properties.empty()) { 469 NET_LOG_EVENT("Configuring Network", service_path); 470 471 // Set configuration properties required by Shill to identify the network. 472 config_properties.SetStringWithoutPathExpansion( 473 flimflam::kTypeProperty, type); 474 CopyStringFromDictionary(service_properties, flimflam::kNameProperty, 475 &config_properties); 476 CopyStringFromDictionary(service_properties, flimflam::kGuidProperty, 477 &config_properties); 478 if (type == flimflam::kTypeVPN) { 479 config_properties.SetStringWithoutPathExpansion( 480 flimflam::kProviderTypeProperty, vpn_provider_type); 481 config_properties.SetStringWithoutPathExpansion( 482 flimflam::kProviderHostProperty, vpn_provider_host); 483 } else if (type == flimflam::kTypeWifi) { 484 config_properties.SetStringWithoutPathExpansion( 485 flimflam::kSecurityProperty, security); 486 } 487 488 network_configuration_handler_->SetProperties( 489 service_path, 490 config_properties, 491 base::Bind(&NetworkConnectionHandler::CallShillConnect, 492 AsWeakPtr(), service_path), 493 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, 494 AsWeakPtr(), service_path)); 495 return; 496 } 497 498 // Otherwise, we probably still need to configure the network since 499 // 'Connectable' is false. If |check_error_state| is true, signal an 500 // error, otherwise attempt to connect to possibly gain additional error 501 // state from Shill (or in case 'Connectable' is improperly unset). 502 if (check_error_state) 503 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 504 else 505 CallShillConnect(service_path); 506 } 507 508 void NetworkConnectionHandler::CallShillConnect( 509 const std::string& service_path) { 510 NET_LOG_EVENT("Sending Connect Request to Shill", service_path); 511 DBusThreadManager::Get()->GetShillServiceClient()->Connect( 512 dbus::ObjectPath(service_path), 513 base::Bind(&NetworkConnectionHandler::HandleShillConnectSuccess, 514 AsWeakPtr(), service_path), 515 base::Bind(&NetworkConnectionHandler::HandleShillConnectFailure, 516 AsWeakPtr(), service_path)); 517 } 518 519 void NetworkConnectionHandler::HandleConfigurationFailure( 520 const std::string& service_path, 521 const std::string& error_name, 522 scoped_ptr<base::DictionaryValue> error_data) { 523 ConnectRequest* request = GetPendingRequest(service_path); 524 if (!request) { 525 NET_LOG_ERROR("HandleConfigurationFailure called with no pending request.", 526 service_path); 527 return; 528 } 529 network_handler::ErrorCallback error_callback = request->error_callback; 530 pending_requests_.erase(service_path); 531 if (!error_callback.is_null()) 532 error_callback.Run(kErrorConfigureFailed, error_data.Pass()); 533 } 534 535 void NetworkConnectionHandler::HandleShillConnectSuccess( 536 const std::string& service_path) { 537 ConnectRequest* request = GetPendingRequest(service_path); 538 if (!request) { 539 NET_LOG_ERROR("HandleShillConnectSuccess called with no pending request.", 540 service_path); 541 return; 542 } 543 request->connect_state = ConnectRequest::CONNECT_STARTED; 544 NET_LOG_EVENT("Connect Request Acknowledged", service_path); 545 // Do not call success_callback here, wait for one of the following 546 // conditions: 547 // * State transitions to a non connecting state indicating succes or failure 548 // * Network is no longer in the visible list, indicating failure 549 CheckPendingRequest(service_path); 550 } 551 552 void NetworkConnectionHandler::HandleShillConnectFailure( 553 const std::string& service_path, 554 const std::string& dbus_error_name, 555 const std::string& dbus_error_message) { 556 ConnectRequest* request = GetPendingRequest(service_path); 557 if (!request) { 558 NET_LOG_ERROR("HandleShillConnectFailure called with no pending request.", 559 service_path); 560 return; 561 } 562 network_handler::ErrorCallback error_callback = request->error_callback; 563 pending_requests_.erase(service_path); 564 network_handler::ShillErrorCallbackFunction( 565 flimflam::kErrorConnectFailed, service_path, error_callback, 566 dbus_error_name, dbus_error_message); 567 } 568 569 void NetworkConnectionHandler::CheckPendingRequest( 570 const std::string service_path) { 571 ConnectRequest* request = GetPendingRequest(service_path); 572 DCHECK(request); 573 if (request->connect_state == ConnectRequest::CONNECT_REQUESTED) 574 return; // Request has not started, ignore update 575 const NetworkState* network = 576 network_state_handler_->GetNetworkState(service_path); 577 if (!network) 578 return; // NetworkState may not be be updated yet. 579 580 if (network->IsConnectingState()) { 581 request->connect_state = ConnectRequest::CONNECT_CONNECTING; 582 return; 583 } 584 if (network->IsConnectedState()) { 585 NET_LOG_EVENT("Connect Request Succeeded", service_path); 586 if (!request->success_callback.is_null()) 587 request->success_callback.Run(); 588 pending_requests_.erase(service_path); 589 return; 590 } 591 if (network->connection_state() == flimflam::kStateIdle && 592 request->connect_state != ConnectRequest::CONNECT_CONNECTING) { 593 // Connection hasn't started yet, keep waiting. 594 return; 595 } 596 597 // Network is neither connecting or connected; an error occurred. 598 std::string error_name, error_detail; 599 if (network->connection_state() == flimflam::kStateIdle && 600 pending_requests_.size() > 1) { 601 // Another connect request canceled this one. 602 error_name = kErrorConnectCanceled; 603 error_detail = ""; 604 } else { 605 error_name = flimflam::kErrorConnectFailed; 606 error_detail = network->error(); 607 if (error_detail.empty()) { 608 if (network->connection_state() == flimflam::kStateFailure) 609 error_detail = flimflam::kUnknownString; 610 else 611 error_detail = "Unexpected State: " + network->connection_state(); 612 } 613 } 614 std::string error_msg = error_name + ": " + error_detail; 615 NET_LOG_ERROR(error_msg, service_path); 616 617 network_handler::ErrorCallback error_callback = request->error_callback; 618 pending_requests_.erase(service_path); 619 if (error_callback.is_null()) 620 return; 621 scoped_ptr<base::DictionaryValue> error_data( 622 network_handler::CreateErrorData(service_path, error_name, error_msg)); 623 error_callback.Run(error_name, error_data.Pass()); 624 } 625 626 void NetworkConnectionHandler::CheckAllPendingRequests() { 627 for (std::map<std::string, ConnectRequest>::iterator iter = 628 pending_requests_.begin(); iter != pending_requests_.end(); ++iter) { 629 CheckPendingRequest(iter->first); 630 } 631 } 632 633 std::string NetworkConnectionHandler::CertificateIsConfigured( 634 NetworkUIData* ui_data) { 635 if (ui_data->certificate_pattern().Empty()) 636 return std::string(); 637 // Find the matching certificate. 638 scoped_refptr<net::X509Certificate> matching_cert = 639 client_cert::GetCertificateMatch(ui_data->certificate_pattern()); 640 if (!matching_cert.get()) 641 return std::string(); 642 return CertLoader::GetPkcs11IdForCert(*matching_cert.get()); 643 } 644 645 void NetworkConnectionHandler::ErrorCallbackForPendingRequest( 646 const std::string& service_path, 647 const std::string& error_name) { 648 ConnectRequest* request = GetPendingRequest(service_path); 649 if (!request) { 650 NET_LOG_ERROR("ErrorCallbackForPendingRequest with no pending request.", 651 service_path); 652 return; 653 } 654 // Remove the entry before invoking the callback in case it triggers a retry. 655 network_handler::ErrorCallback error_callback = request->error_callback; 656 pending_requests_.erase(service_path); 657 InvokeErrorCallback(service_path, error_callback, error_name); 658 } 659 660 // Disconnect 661 662 void NetworkConnectionHandler::CallShillDisconnect( 663 const std::string& service_path, 664 const base::Closure& success_callback, 665 const network_handler::ErrorCallback& error_callback) { 666 NET_LOG_USER("Disconnect Request", service_path); 667 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect( 668 dbus::ObjectPath(service_path), 669 base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess, 670 AsWeakPtr(), service_path, success_callback), 671 base::Bind(&network_handler::ShillErrorCallbackFunction, 672 kErrorShillError, service_path, error_callback)); 673 } 674 675 void NetworkConnectionHandler::HandleShillDisconnectSuccess( 676 const std::string& service_path, 677 const base::Closure& success_callback) { 678 NET_LOG_EVENT("Disconnect Request Sent", service_path); 679 if (!success_callback.is_null()) 680 success_callback.Run(); 681 } 682 683 // Activate 684 685 void NetworkConnectionHandler::CallShillActivate( 686 const std::string& service_path, 687 const std::string& carrier, 688 const base::Closure& success_callback, 689 const network_handler::ErrorCallback& error_callback) { 690 NET_LOG_USER("Activate Request", service_path + ": '" + carrier + "'"); 691 DBusThreadManager::Get()->GetShillServiceClient()->ActivateCellularModem( 692 dbus::ObjectPath(service_path), 693 carrier, 694 base::Bind(&NetworkConnectionHandler::HandleShillActivateSuccess, 695 AsWeakPtr(), service_path, success_callback), 696 base::Bind(&network_handler::ShillErrorCallbackFunction, 697 kErrorShillError, service_path, error_callback)); 698 } 699 700 void NetworkConnectionHandler::HandleShillActivateSuccess( 701 const std::string& service_path, 702 const base::Closure& success_callback) { 703 NET_LOG_EVENT("Activate Request Sent", service_path); 704 if (!success_callback.is_null()) 705 success_callback.Run(); 706 } 707 708 } // namespace chromeos 709