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