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