network_connection_handler.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// Use of this source code is governed by a BSD-style license that can be 3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// found in the LICENSE file. 4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com 5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com#include "chromeos/network/network_connection_handler.h" 6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com 7cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com#include "base/bind.h" 8cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com#include "base/json/json_reader.h" 9cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com#include "base/location.h" 108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "base/message_loop/message_loop_proxy.h" 118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "base/strings/string_number_conversions.h" 128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/cert_loader.h" 138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/dbus/dbus_thread_manager.h" 148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/dbus/shill_manager_client.h" 158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/dbus/shill_service_client.h" 168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/certificate_pattern.h" 178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/client_cert_resolver.h" 188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/client_cert_util.h" 198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/managed_network_configuration_handler.h" 208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/network_configuration_handler.h" 218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/network_event_log.h" 228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/network_handler_callbacks.h" 238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/network_profile_handler.h" 248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/network_state.h" 258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/network_state_handler.h" 268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "chromeos/network/shill_property_util.h" 278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "dbus/object_path.h" 288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "net/cert/x509_certificate.h" 298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com#include "third_party/cros_system_api/dbus/service_constants.h" 308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comnamespace chromeos { 328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comnamespace { 348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid InvokeErrorCallback(const std::string& service_path, 368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const network_handler::ErrorCallback& error_callback, 378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& error_name) { 388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_ERROR("Connect Error: " + error_name, service_path); 398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_handler::RunErrorCallback( 408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com error_callback, service_path, error_name, ""); 418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.combool IsAuthenticationError(const std::string& error) { 448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return (error == shill::kErrorBadWEPKey || 458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com error == shill::kErrorPppAuthFailed || 468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com error == shill::kErrorEapLocalTlsFailed || 478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com error == shill::kErrorEapRemoteTlsFailed || 488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com error == shill::kErrorEapAuthenticationFailed); 498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.combool VPNRequiresCredentials(const std::string& service_path, 528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& provider_type, 538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::DictionaryValue& provider_properties) { 548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (provider_type == shill::kProviderOpenVpn) { 558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string username; 568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties.GetStringWithoutPathExpansion( 578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kOpenVPNUserProperty, &username); 588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (username.empty()) { 598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("OpenVPN: No username", service_path); 608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return true; 618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool passphrase_required = false; 638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties.GetBooleanWithoutPathExpansion( 648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kPassphraseRequiredProperty, &passphrase_required); 658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (passphrase_required) { 668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path); 678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return true; 688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("OpenVPN Is Configured", service_path); 708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } else { 718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool passphrase_required = false; 728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties.GetBooleanWithoutPathExpansion( 738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kL2tpIpsecPskRequiredProperty, &passphrase_required); 748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (passphrase_required) { 758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("VPN: PSK Required", service_path); 768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return true; 778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties.GetBooleanWithoutPathExpansion( 798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kPassphraseRequiredProperty, &passphrase_required); 808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (passphrase_required) { 818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("VPN: Passphrase Required", service_path); 828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return true; 838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("VPN Is Configured", service_path); 858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return false; 878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comstd::string GetDefaultUserProfilePath(const NetworkState* network) { 908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!NetworkHandler::IsInitialized() || 918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com (LoginState::IsInitialized() && 928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com !LoginState::Get()->UserHasNetworkProfile()) || 938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com (network && network->type() == shill::kTypeWifi && 948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network->security() == shill::kSecurityNone)) { 958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return NetworkProfileHandler::GetSharedProfilePath(); 968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const NetworkProfile* profile = 988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NetworkHandler::Get()->network_profile_handler()->GetDefaultUserProfile(); 998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return profile ? profile->path 1008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com : NetworkProfileHandler::GetSharedProfilePath(); 1018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} // namespace 1048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorNotFound[] = "not-found"; 1068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorConnected[] = "connected"; 1078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorConnecting[] = "connecting"; 1088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorNotConnected[] = "not-connected"; 1098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorPassphraseRequired[] = 1108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "passphrase-required"; 1118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorActivationRequired[] = 1128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "activation-required"; 1138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorCertificateRequired[] = 1148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "certificate-required"; 1158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorConfigurationRequired[] = 1168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "configuration-required"; 1178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorAuthenticationRequired[] = 1188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "authentication-required"; 1198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorShillError[] = "shill-error"; 1208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorConfigureFailed[] = 1218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "configure-failed"; 1228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorConnectCanceled[] = 1238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "connect-canceled"; 1248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comconst char NetworkConnectionHandler::kErrorCertLoadTimeout[] = 1258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com "cert-load-timeout"; 1268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comstruct NetworkConnectionHandler::ConnectRequest { 1288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ConnectRequest(const std::string& service_path, 1298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& profile_path, 1308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::Closure& success, 1318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const network_handler::ErrorCallback& error) 1328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com : service_path(service_path), 1338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com profile_path(profile_path), 1348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com connect_state(CONNECT_REQUESTED), 1358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com success_callback(success), 1368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com error_callback(error) { 1378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com enum ConnectState { 1398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CONNECT_REQUESTED = 0, 1408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CONNECT_STARTED = 1, 1418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CONNECT_CONNECTING = 2 1428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com }; 1438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string service_path; 1448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string profile_path; 1458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ConnectState connect_state; 1468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com base::Closure success_callback; 1478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_handler::ErrorCallback error_callback; 1488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com}; 1498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comNetworkConnectionHandler::NetworkConnectionHandler() 1518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com : cert_loader_(NULL), 1528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_state_handler_(NULL), 1538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com configuration_handler_(NULL), 1548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com logged_in_(false), 1558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com certificates_loaded_(false), 1568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com applied_autoconnect_policy_(false), 1578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com requested_connect_to_best_network_(false) { 1588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comNetworkConnectionHandler::~NetworkConnectionHandler() { 1618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (network_state_handler_) 1628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_state_handler_->RemoveObserver(this, FROM_HERE); 1638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (cert_loader_) 1648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com cert_loader_->RemoveObserver(this); 1658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (LoginState::IsInitialized()) 1668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com LoginState::Get()->RemoveObserver(this); 1678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 1688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::Init( 1708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NetworkStateHandler* network_state_handler, 1718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NetworkConfigurationHandler* network_configuration_handler, 1728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ManagedNetworkConfigurationHandler* managed_network_configuration_handler) { 1738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (LoginState::IsInitialized()) 1748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com LoginState::Get()->AddObserver(this); 1758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (CertLoader::IsInitialized()) { 1778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com cert_loader_ = CertLoader::Get(); 1788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com cert_loader_->AddObserver(this); 1798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (cert_loader_->certificates_loaded()) { 1808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("Certificates Loaded", ""); 1818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com certificates_loaded_ = true; 1828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } else { 1848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // TODO(tbarzic): Require a mock or stub cert_loader in tests. 1858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("Certificate Loader not initialized", ""); 1868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com certificates_loaded_ = true; 1878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (network_state_handler) { 1908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_state_handler_ = network_state_handler; 1918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_state_handler_->AddObserver(this, FROM_HERE); 1928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com configuration_handler_ = network_configuration_handler; 1948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 1958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (managed_network_configuration_handler) { 1968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com managed_configuration_handler_ = managed_network_configuration_handler; 1978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com managed_configuration_handler_->AddObserver(this); 1988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 1998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // After this point, the NetworkConnectionHandler is fully initialized (all 2018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // handler references set, observers registered, ...). 2028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (LoginState::IsInitialized()) 2048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com LoggedInStateChanged(); 2058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 2068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::LoggedInStateChanged() { 2088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com LoginState* login_state = LoginState::Get(); 2098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (logged_in_ || !login_state->IsUserLoggedIn()) 2108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("Logged In", ""); 2138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com logged_in_ = true; 2148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com logged_in_time_ = base::TimeTicks::Now(); 2158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com DisconnectIfPolicyRequires(); 2178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 2188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::OnCertificatesLoaded( 2208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const net::CertificateList& cert_list, 2218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool initial_load) { 2228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com certificates_loaded_ = true; 2238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("Certificates Loaded", ""); 2248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (queued_connect_) { 2258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ConnectToQueuedNetwork(); 2268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } else if (initial_load) { 2278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Connecting to the "best" available network requires certificates to be 2288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // loaded. Try to connect now. 2298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ConnectToBestNetworkAfterLogin(); 2308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 2328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::PolicyChanged(const std::string& userhash) { 2348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Ignore user policies. 2358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!userhash.empty()) 2368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com DisconnectIfPolicyRequires(); 2388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 2398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::ConnectToNetwork( 2418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& service_path, 2428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::Closure& success_callback, 2438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const network_handler::ErrorCallback& error_callback, 2448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool check_error_state) { 2458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_USER("ConnectToNetwork", service_path); 2468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Clear any existing queued connect request. 2478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com queued_connect_.reset(); 2488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (HasConnectingNetwork(service_path)) { 2498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_USER("Connect Request While Pending", service_path); 2508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback(service_path, error_callback, kErrorConnecting); 2518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Check cached network state for connected, connecting, or unactivated 2558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // networks. These states will not be affected by a recent configuration. 2568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Note: NetworkState may not exist for a network that was recently 2578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // configured, in which case these checks do not apply anyway. 2588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const NetworkState* network = 2598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_state_handler_->GetNetworkState(service_path); 2608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (network) { 2628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // For existing networks, perform some immediate consistency checks. 2638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (network->IsConnectedState()) { 2648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback(service_path, error_callback, kErrorConnected); 2658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (network->IsConnectingState()) { 2688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback(service_path, error_callback, kErrorConnecting); 2698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (check_error_state) { 2738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& error = network->last_error(); 2748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (error == shill::kErrorBadPassphrase) { 2758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback(service_path, error_callback, error); 2768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (IsAuthenticationError(error)) { 2798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback( 2808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path, error_callback, kErrorAuthenticationRequired); 2818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 2828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 2858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // If the network does not have a profile path, specify the correct default 2878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // profile here and set it once connected. Otherwise leave it empty to 2888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // indicate that it does not need to be set. 2898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string profile_path; 2908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!network || network->profile_path().empty()) 2918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com profile_path = GetDefaultUserProfilePath(network); 2928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // All synchronous checks passed, add |service_path| to connecting list. 2948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com pending_requests_.insert(std::make_pair( 2958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path, 2968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ConnectRequest(service_path, profile_path, 2978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com success_callback, error_callback))); 2988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 2998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Connect immediately to 'connectable' networks. 3008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // TODO(stevenjb): Shill needs to properly set Connectable for VPN. 3018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (network && network->connectable() && network->type() != shill::kTypeVPN) { 3028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CallShillConnect(service_path); 3038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 3048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Request additional properties to check. VerifyConfiguredAndConnect will 3078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // use only these properties, not cached properties, to ensure that they 3088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // are up to date after any recent configuration. 3098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com configuration_handler_->GetProperties( 3108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path, 3118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com base::Bind(&NetworkConnectionHandler::VerifyConfiguredAndConnect, 3128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com AsWeakPtr(), check_error_state), 3138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, 3148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com AsWeakPtr(), service_path)); 3158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::DisconnectNetwork( 3188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& service_path, 3198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::Closure& success_callback, 3208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const network_handler::ErrorCallback& error_callback) { 3218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_USER("DisconnectNetwork", service_path); 3228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const NetworkState* network = 3238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com network_state_handler_->GetNetworkState(service_path); 3248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!network) { 3258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback(service_path, error_callback, kErrorNotFound); 3268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 3278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!network->IsConnectedState()) { 3298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com InvokeErrorCallback(service_path, error_callback, kErrorNotConnected); 3308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 3318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CallShillDisconnect(service_path, success_callback, error_callback); 3338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.combool NetworkConnectionHandler::HasConnectingNetwork( 3368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& service_path) { 3378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return pending_requests_.count(service_path) != 0; 3388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.combool NetworkConnectionHandler::HasPendingConnectRequest() { 3418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return pending_requests_.size() > 0; 3428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::NetworkListChanged() { 3458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CheckAllPendingRequests(); 3468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::NetworkPropertiesUpdated( 3498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const NetworkState* network) { 3508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (HasConnectingNetwork(network->path())) 3518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CheckPendingRequest(network->path()); 3528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comNetworkConnectionHandler::ConnectRequest* 3558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comNetworkConnectionHandler::GetPendingRequest(const std::string& service_path) { 3568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::map<std::string, ConnectRequest>::iterator iter = 3578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com pending_requests_.find(service_path); 3588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return iter != pending_requests_.end() ? &(iter->second) : NULL; 3598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com} 3608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// ConnectToNetwork implementation 3628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comvoid NetworkConnectionHandler::VerifyConfiguredAndConnect( 3648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool check_error_state, 3658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const std::string& service_path, 3668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::DictionaryValue& service_properties) { 3678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path); 3688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // If 'passphrase_required' is still true, then the 'Passphrase' property 3708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // has not been set to a minimum length value. 3718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool passphrase_required = false; 3728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties.GetBooleanWithoutPathExpansion( 3738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kPassphraseRequiredProperty, &passphrase_required); 3748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (passphrase_required) { 3758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired); 3768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 3778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string type, security; 3808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); 3818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties.GetStringWithoutPathExpansion( 3828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kSecurityProperty, &security); 3838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com bool connectable = false; 3848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties.GetBooleanWithoutPathExpansion( 3858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kConnectableProperty, &connectable); 3868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // In case NetworkState was not available in ConnectToNetwork (e.g. it had 3888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // been recently configured), we need to check Connectable again. 3898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (connectable && type != shill::kTypeVPN) { 3908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // TODO(stevenjb): Shill needs to properly set Connectable for VPN. 3918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CallShillConnect(service_path); 3928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 3938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 3948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 3958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Get VPN provider type and host (required for configuration) and ensure 3968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // that required VPN non-cert properties are set. 3978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::DictionaryValue* provider_properties = NULL; 3988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string vpn_provider_type, vpn_provider_host, vpn_client_cert_id; 3998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (type == shill::kTypeVPN) { 4008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // VPN Provider values are read from the "Provider" dictionary, not the 4018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // "Provider.Type", etc keys (which are used only to set the values). 4028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (service_properties.GetDictionaryWithoutPathExpansion( 4038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kProviderProperty, &provider_properties)) { 4048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties->GetStringWithoutPathExpansion( 4058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kTypeProperty, &vpn_provider_type); 4068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties->GetStringWithoutPathExpansion( 4078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kHostProperty, &vpn_provider_host); 4088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com provider_properties->GetStringWithoutPathExpansion( 4098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com shill::kL2tpIpsecClientCertIdProperty, &vpn_client_cert_id); 4108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (vpn_provider_type.empty() || vpn_provider_host.empty()) { 4128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 4138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 4148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string guid; 4188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &guid); 4198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com std::string profile; 4208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties.GetStringWithoutPathExpansion(shill::kProfileProperty, 4218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com &profile); 4228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com const base::DictionaryValue* user_policy = 4238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com managed_configuration_handler_->FindPolicyByGuidAndProfile(guid, profile); 4248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert::ClientCertConfig cert_config_from_policy; 4268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (user_policy) 4278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert::OncToClientCertConfig(*user_policy, &cert_config_from_policy); 4288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert::ConfigType client_cert_type = client_cert::CONFIG_TYPE_NONE; 4308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (type == shill::kTypeVPN) { 4318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (vpn_provider_type == shill::kProviderOpenVpn) { 4328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert_type = client_cert::CONFIG_TYPE_OPENVPN; 4338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } else { 4348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // L2TP/IPSec only requires a certificate if one is specified in ONC 4358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // or one was configured by the UI. Otherwise it is L2TP/IPSec with 4368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // PSK and doesn't require a certificate. 4378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // 4388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // TODO(benchan): Modify shill to specify the authentication type via 4398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // the kL2tpIpsecAuthenticationType property, so that Chrome doesn't need 4408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // to deduce the authentication type based on the 4418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // kL2tpIpsecClientCertIdProperty here (and also in VPNConfigView). 4428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!vpn_client_cert_id.empty() || 4438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com cert_config_from_policy.client_cert_type != 4448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com onc::client_cert::kClientCertTypeNone) { 4458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert_type = client_cert::CONFIG_TYPE_IPSEC; 4468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } else if (type == shill::kTypeWifi && security == shill::kSecurity8021x) { 4498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert_type = client_cert::CONFIG_TYPE_EAP; 4508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com base::DictionaryValue config_properties; 4538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (client_cert_type != client_cert::CONFIG_TYPE_NONE) { 4548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Note: if we get here then a certificate *may* be required, so we want 4558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // to ensure that certificates have loaded successfully before attempting 4568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // to connect. 4578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // User must be logged in to connect to a network requiring a certificate. 4598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!logged_in_ || !cert_loader_) { 4608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_ERROR("User not logged in", ""); 4618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); 4628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 4638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // If certificates have not been loaded yet, queue the connect request. 4658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!certificates_loaded_) { 4668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("Certificates not loaded", ""); 4678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com QueueConnectRequest(service_path); 4688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 4698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Check certificate properties from policy. 4728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (cert_config_from_policy.client_cert_type == 4738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com onc::client_cert::kPattern) { 4748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!ClientCertResolver::ResolveCertificatePatternSync( 4758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com client_cert_type, 4768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com cert_config_from_policy.pattern, 4778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com &config_properties)) { 4788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); 4798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 4808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } else if (check_error_state && 4828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com !client_cert::IsCertificateConfigured(client_cert_type, 4838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_properties)) { 4848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Network may not be configured. 4858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 4868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 4878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 4898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 4908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (type == shill::kTypeVPN) { 4918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // VPN may require a username, and/or passphrase to be set. (Check after 4928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // ensuring that any required certificates are configured). 4938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com DCHECK(provider_properties); 4948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (VPNRequiresCredentials( 4958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path, vpn_provider_type, *provider_properties)) { 4968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_USER("VPN Requires Credentials", service_path); 4978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 4988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 4998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 5018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // If it's L2TP/IPsec PSK, there is no properties to configure, so proceed 5028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // to connect. 5038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (client_cert_type == client_cert::CONFIG_TYPE_NONE) { 5048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com CallShillConnect(service_path); 5058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 5068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 5098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com if (!config_properties.empty()) { 5108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com NET_LOG_EVENT("Configuring Network", service_path); 5118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com configuration_handler_->SetProperties( 5128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path, 5138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com config_properties, 5148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com base::Bind(&NetworkConnectionHandler::CallShillConnect, 5158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com AsWeakPtr(), 5168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path), 5178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, 5188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com AsWeakPtr(), 5198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com service_path)); 5208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com return; 5218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com } 5228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com 5238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // Otherwise, we probably still need to configure the network since 5248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // 'Connectable' is false. If |check_error_state| is true, signal an 5258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // error, otherwise attempt to connect to possibly gain additional error 5268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com // state from Shill (or in case 'Connectable' is improperly unset). 527cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com if (check_error_state) 528 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 529 else 530 CallShillConnect(service_path); 531} 532 533void NetworkConnectionHandler::QueueConnectRequest( 534 const std::string& service_path) { 535 ConnectRequest* request = GetPendingRequest(service_path); 536 if (!request) { 537 NET_LOG_ERROR("No pending request to queue", service_path); 538 return; 539 } 540 541 const int kMaxCertLoadTimeSeconds = 15; 542 base::TimeDelta dtime = base::TimeTicks::Now() - logged_in_time_; 543 if (dtime > base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds)) { 544 NET_LOG_ERROR("Certificate load timeout", service_path); 545 InvokeErrorCallback(service_path, 546 request->error_callback, 547 kErrorCertLoadTimeout); 548 return; 549 } 550 551 NET_LOG_EVENT("Connect Request Queued", service_path); 552 queued_connect_.reset(new ConnectRequest( 553 service_path, request->profile_path, 554 request->success_callback, request->error_callback)); 555 pending_requests_.erase(service_path); 556 557 // Post a delayed task to check to see if certificates have loaded. If they 558 // haven't, and queued_connect_ has not been cleared (e.g. by a successful 559 // connect request), cancel the request and notify the user. 560 base::MessageLoopProxy::current()->PostDelayedTask( 561 FROM_HERE, 562 base::Bind(&NetworkConnectionHandler::CheckCertificatesLoaded, 563 AsWeakPtr()), 564 base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds) - dtime); 565} 566 567void NetworkConnectionHandler::CheckCertificatesLoaded() { 568 if (certificates_loaded_) 569 return; 570 // If queued_connect_ has been cleared (e.g. another connect request occurred 571 // and wasn't queued), do nothing here. 572 if (!queued_connect_) 573 return; 574 // Otherwise, notify the user. 575 NET_LOG_ERROR("Certificate load timeout", queued_connect_->service_path); 576 InvokeErrorCallback(queued_connect_->service_path, 577 queued_connect_->error_callback, 578 kErrorCertLoadTimeout); 579 queued_connect_.reset(); 580} 581 582void NetworkConnectionHandler::ConnectToQueuedNetwork() { 583 DCHECK(queued_connect_); 584 585 // Make a copy of |queued_connect_| parameters, because |queued_connect_| 586 // will get reset at the beginning of |ConnectToNetwork|. 587 std::string service_path = queued_connect_->service_path; 588 base::Closure success_callback = queued_connect_->success_callback; 589 network_handler::ErrorCallback error_callback = 590 queued_connect_->error_callback; 591 592 NET_LOG_EVENT("Connecting to Queued Network", service_path); 593 ConnectToNetwork(service_path, success_callback, error_callback, 594 false /* check_error_state */); 595} 596 597void NetworkConnectionHandler::CallShillConnect( 598 const std::string& service_path) { 599 NET_LOG_EVENT("Sending Connect Request to Shill", service_path); 600 network_state_handler_->ClearLastErrorForNetwork(service_path); 601 DBusThreadManager::Get()->GetShillServiceClient()->Connect( 602 dbus::ObjectPath(service_path), 603 base::Bind(&NetworkConnectionHandler::HandleShillConnectSuccess, 604 AsWeakPtr(), service_path), 605 base::Bind(&NetworkConnectionHandler::HandleShillConnectFailure, 606 AsWeakPtr(), service_path)); 607} 608 609void NetworkConnectionHandler::HandleConfigurationFailure( 610 const std::string& service_path, 611 const std::string& error_name, 612 scoped_ptr<base::DictionaryValue> error_data) { 613 ConnectRequest* request = GetPendingRequest(service_path); 614 if (!request) { 615 NET_LOG_ERROR("HandleConfigurationFailure called with no pending request.", 616 service_path); 617 return; 618 } 619 network_handler::ErrorCallback error_callback = request->error_callback; 620 pending_requests_.erase(service_path); 621 if (!error_callback.is_null()) 622 error_callback.Run(kErrorConfigureFailed, error_data.Pass()); 623} 624 625void NetworkConnectionHandler::HandleShillConnectSuccess( 626 const std::string& service_path) { 627 ConnectRequest* request = GetPendingRequest(service_path); 628 if (!request) { 629 NET_LOG_ERROR("HandleShillConnectSuccess called with no pending request.", 630 service_path); 631 return; 632 } 633 request->connect_state = ConnectRequest::CONNECT_STARTED; 634 NET_LOG_EVENT("Connect Request Acknowledged", service_path); 635 // Do not call success_callback here, wait for one of the following 636 // conditions: 637 // * State transitions to a non connecting state indicating success or failure 638 // * Network is no longer in the visible list, indicating failure 639 CheckPendingRequest(service_path); 640} 641 642void NetworkConnectionHandler::HandleShillConnectFailure( 643 const std::string& service_path, 644 const std::string& dbus_error_name, 645 const std::string& dbus_error_message) { 646 ConnectRequest* request = GetPendingRequest(service_path); 647 if (!request) { 648 NET_LOG_ERROR("HandleShillConnectFailure called with no pending request.", 649 service_path); 650 return; 651 } 652 network_handler::ErrorCallback error_callback = request->error_callback; 653 pending_requests_.erase(service_path); 654 network_handler::ShillErrorCallbackFunction( 655 shill::kErrorConnectFailed, service_path, error_callback, 656 dbus_error_name, dbus_error_message); 657} 658 659void NetworkConnectionHandler::CheckPendingRequest( 660 const std::string service_path) { 661 ConnectRequest* request = GetPendingRequest(service_path); 662 DCHECK(request); 663 if (request->connect_state == ConnectRequest::CONNECT_REQUESTED) 664 return; // Request has not started, ignore update 665 const NetworkState* network = 666 network_state_handler_->GetNetworkState(service_path); 667 if (!network) 668 return; // NetworkState may not be be updated yet. 669 670 if (network->IsConnectingState()) { 671 request->connect_state = ConnectRequest::CONNECT_CONNECTING; 672 return; 673 } 674 if (network->IsConnectedState()) { 675 NET_LOG_EVENT("Connect Request Succeeded", service_path); 676 if (!request->profile_path.empty()) { 677 // If a profile path was specified, set it on a successful connection. 678 configuration_handler_->SetNetworkProfile( 679 service_path, 680 request->profile_path, 681 base::Bind(&base::DoNothing), 682 chromeos::network_handler::ErrorCallback()); 683 } 684 if (!request->success_callback.is_null()) 685 request->success_callback.Run(); 686 pending_requests_.erase(service_path); 687 return; 688 } 689 if (network->connection_state() == shill::kStateIdle && 690 request->connect_state != ConnectRequest::CONNECT_CONNECTING) { 691 // Connection hasn't started yet, keep waiting. 692 return; 693 } 694 695 // Network is neither connecting or connected; an error occurred. 696 std::string error_name; // 'Canceled' or 'Failed' 697 if (network->connection_state() == shill::kStateIdle && 698 pending_requests_.size() > 1) { 699 // Another connect request canceled this one. 700 error_name = kErrorConnectCanceled; 701 } else { 702 error_name = shill::kErrorConnectFailed; 703 if (network->connection_state() != shill::kStateFailure) { 704 NET_LOG_ERROR("Unexpected State: " + network->connection_state(), 705 service_path); 706 } 707 } 708 709 network_handler::ErrorCallback error_callback = request->error_callback; 710 pending_requests_.erase(service_path); 711 if (error_callback.is_null()) { 712 NET_LOG_ERROR("Connect Error, no callback: " + error_name, service_path); 713 return; 714 } 715 InvokeErrorCallback(service_path, error_callback, error_name); 716} 717 718void NetworkConnectionHandler::CheckAllPendingRequests() { 719 for (std::map<std::string, ConnectRequest>::iterator iter = 720 pending_requests_.begin(); iter != pending_requests_.end(); ++iter) { 721 CheckPendingRequest(iter->first); 722 } 723} 724 725void NetworkConnectionHandler::ErrorCallbackForPendingRequest( 726 const std::string& service_path, 727 const std::string& error_name) { 728 ConnectRequest* request = GetPendingRequest(service_path); 729 if (!request) { 730 NET_LOG_ERROR("ErrorCallbackForPendingRequest with no pending request.", 731 service_path); 732 return; 733 } 734 // Remove the entry before invoking the callback in case it triggers a retry. 735 network_handler::ErrorCallback error_callback = request->error_callback; 736 pending_requests_.erase(service_path); 737 InvokeErrorCallback(service_path, error_callback, error_name); 738} 739 740// Disconnect 741 742void NetworkConnectionHandler::CallShillDisconnect( 743 const std::string& service_path, 744 const base::Closure& success_callback, 745 const network_handler::ErrorCallback& error_callback) { 746 NET_LOG_USER("Disconnect Request", service_path); 747 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect( 748 dbus::ObjectPath(service_path), 749 base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess, 750 AsWeakPtr(), service_path, success_callback), 751 base::Bind(&network_handler::ShillErrorCallbackFunction, 752 kErrorShillError, service_path, error_callback)); 753} 754 755void NetworkConnectionHandler::HandleShillDisconnectSuccess( 756 const std::string& service_path, 757 const base::Closure& success_callback) { 758 NET_LOG_EVENT("Disconnect Request Sent", service_path); 759 if (!success_callback.is_null()) 760 success_callback.Run(); 761} 762 763void NetworkConnectionHandler::ConnectToBestNetworkAfterLogin() { 764 if (requested_connect_to_best_network_ || !applied_autoconnect_policy_ || 765 !certificates_loaded_) { 766 return; 767 } 768 769 requested_connect_to_best_network_ = true; 770 network_state_handler_->ConnectToBestWifiNetwork(); 771} 772 773void NetworkConnectionHandler::DisconnectIfPolicyRequires() { 774 if (applied_autoconnect_policy_ || !LoginState::Get()->IsUserLoggedIn()) 775 return; 776 777 const base::DictionaryValue* global_network_config = 778 managed_configuration_handler_->GetGlobalConfigFromPolicy(std::string()); 779 if (!global_network_config) 780 return; 781 782 applied_autoconnect_policy_ = true; 783 784 bool only_policy_autoconnect = false; 785 global_network_config->GetBooleanWithoutPathExpansion( 786 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, 787 &only_policy_autoconnect); 788 789 if (!only_policy_autoconnect) 790 return; 791 792 NET_LOG_DEBUG("DisconnectIfPolicyRequires", 793 "Disconnecting unmanaged and shared networks if any exist."); 794 795 // Get the list of unmanaged & shared networks that are connected or 796 // connecting. 797 NetworkStateHandler::NetworkStateList networks; 798 network_state_handler_->GetVisibleNetworkListByType( 799 NetworkTypePattern::Wireless(), &networks); 800 for (NetworkStateHandler::NetworkStateList::const_iterator it = 801 networks.begin(); 802 it != networks.end(); 803 ++it) { 804 const NetworkState* network = *it; 805 if (!(network->IsConnectingState() || network->IsConnectedState())) 806 break; // Connected and connecting networks are listed first. 807 808 if (network->IsPrivate()) 809 continue; 810 811 const bool network_is_policy_managed = 812 !network->profile_path().empty() && !network->guid().empty() && 813 managed_configuration_handler_->FindPolicyByGuidAndProfile( 814 network->guid(), network->profile_path()); 815 if (network_is_policy_managed) 816 continue; 817 818 NET_LOG_EVENT("Disconnect Forced by Policy", network->path()); 819 CallShillDisconnect( 820 network->path(), base::Closure(), network_handler::ErrorCallback()); 821 } 822 823 ConnectToBestNetworkAfterLogin(); 824} 825 826} // namespace chromeos 827