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