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