Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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/auto_connect_handler.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/callback.h" | |
| 11 #include "base/files/file_util.h" | |
| 12 #include "base/json/json_reader.h" | |
| 13 #include "base/memory/scoped_ptr.h" | |
| 14 #include "base/message_loop/message_loop.h" | |
| 15 #include "base/run_loop.h" | |
| 16 #include "base/strings/stringprintf.h" | |
| 17 #include "chromeos/cert_loader.h" | |
| 18 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 19 #include "chromeos/dbus/shill_device_client.h" | |
| 20 #include "chromeos/dbus/shill_manager_client.h" | |
| 21 #include "chromeos/dbus/shill_profile_client.h" | |
| 22 #include "chromeos/dbus/shill_service_client.h" | |
| 23 #include "chromeos/network/client_cert_resolver.h" | |
| 24 #include "chromeos/network/managed_network_configuration_handler_impl.h" | |
| 25 #include "chromeos/network/network_configuration_handler.h" | |
| 26 #include "chromeos/network/network_profile_handler.h" | |
| 27 #include "chromeos/network/network_state_handler.h" | |
| 28 #include "chromeos/network/onc/onc_utils.h" | |
| 29 #include "components/onc/onc_constants.h" | |
| 30 #include "crypto/scoped_nss_types.h" | |
| 31 #include "crypto/scoped_test_nss_db.h" | |
| 32 #include "net/base/net_errors.h" | |
| 33 #include "net/base/test_data_directory.h" | |
| 34 #include "net/cert/nss_cert_database_chromeos.h" | |
| 35 #include "net/cert/x509_certificate.h" | |
| 36 #include "net/test/cert_test_util.h" | |
| 37 #include "testing/gtest/include/gtest/gtest.h" | |
| 38 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 39 | |
| 40 // http://crbug.com/418369 | |
| 41 #ifdef NDEBUG | |
| 42 | |
| 43 namespace chromeos { | |
| 44 | |
| 45 namespace { | |
| 46 | |
| 47 const char* kUserHash = "user_hash"; | |
| 48 | |
| 49 void ConfigureCallback(const dbus::ObjectPath& result) { | |
|
stevenjb
2014/11/07 17:19:06
nit: Might be worth making these member functions
pneubeck (no reviews)
2014/11/08 16:49:55
these are only used for the test setup and don't t
| |
| 50 } | |
| 51 | |
| 52 void ConfigureErrorCallback(const std::string& error_name, | |
| 53 const std::string& error_message) { | |
| 54 } | |
| 55 | |
| 56 class TestCertResolveObserver : public ClientCertResolver::Observer { | |
| 57 public: | |
| 58 explicit TestCertResolveObserver(ClientCertResolver* cert_resolver) | |
| 59 : changed_network_properties_(false), cert_resolver_(cert_resolver) { | |
| 60 cert_resolver_->AddObserver(this); | |
| 61 } | |
| 62 | |
| 63 void ResolveRequestCompleted(bool changed_network_properties) override { | |
| 64 cert_resolver_->RemoveObserver(this); | |
| 65 changed_network_properties_ = changed_network_properties; | |
| 66 } | |
| 67 | |
| 68 bool DidNetworkPropertiesChange() { return changed_network_properties_; } | |
| 69 | |
| 70 private: | |
| 71 bool changed_network_properties_; | |
| 72 ClientCertResolver* cert_resolver_; | |
| 73 }; | |
| 74 | |
| 75 } // namespace | |
| 76 | |
| 77 class AutoConnectHandlerTest : public testing::Test { | |
| 78 public: | |
| 79 AutoConnectHandlerTest() | |
| 80 : test_manager_client_(nullptr), test_service_client_(nullptr) {} | |
| 81 | |
| 82 void SetUp() override { | |
| 83 ASSERT_TRUE(test_nssdb_.is_open()); | |
| 84 | |
| 85 // Use the same DB for public and private slot. | |
| 86 test_nsscertdb_.reset(new net::NSSCertDatabaseChromeOS( | |
| 87 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())), | |
| 88 crypto::ScopedPK11Slot(PK11_ReferenceSlot(test_nssdb_.slot())))); | |
| 89 test_nsscertdb_->SetSlowTaskRunnerForTest(message_loop_.task_runner()); | |
| 90 | |
| 91 CertLoader::Initialize(); | |
| 92 CertLoader::ForceHardwareBackedForTesting(); | |
| 93 | |
| 94 DBusThreadManager::Initialize(); | |
| 95 DBusThreadManager* dbus_manager = DBusThreadManager::Get(); | |
| 96 test_manager_client_ = | |
| 97 dbus_manager->GetShillManagerClient()->GetTestInterface(); | |
| 98 test_service_client_ = | |
| 99 dbus_manager->GetShillServiceClient()->GetTestInterface(); | |
| 100 | |
| 101 test_manager_client_->AddTechnology(shill::kTypeWifi, true /* enabled */); | |
| 102 dbus_manager->GetShillDeviceClient()->GetTestInterface()->AddDevice( | |
| 103 "/device/wifi1", shill::kTypeWifi, "wifi_device1"); | |
| 104 test_manager_client_->AddTechnology(shill::kTypeCellular, | |
| 105 true /* enabled */); | |
| 106 dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile( | |
| 107 "shared_profile_path", std::string() /* shared profile */); | |
| 108 dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile( | |
| 109 "user_profile_path", kUserHash); | |
| 110 | |
| 111 base::RunLoop().RunUntilIdle(); | |
| 112 LoginState::Initialize(); | |
| 113 network_state_handler_.reset(NetworkStateHandler::InitializeForTest()); | |
| 114 network_config_handler_.reset( | |
| 115 NetworkConfigurationHandler::InitializeForTest( | |
| 116 network_state_handler_.get())); | |
| 117 | |
| 118 network_profile_handler_.reset(new NetworkProfileHandler()); | |
| 119 network_profile_handler_->Init(); | |
| 120 | |
| 121 managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl()); | |
| 122 managed_config_handler_->Init( | |
| 123 network_state_handler_.get(), network_profile_handler_.get(), | |
| 124 network_config_handler_.get(), nullptr /* network_device_handler */); | |
| 125 | |
| 126 client_cert_resolver_.reset(new ClientCertResolver()); | |
| 127 client_cert_resolver_->Init(network_state_handler_.get(), | |
| 128 managed_config_handler_.get()); | |
| 129 client_cert_resolver_->SetSlowTaskRunnerForTest( | |
| 130 message_loop_.task_runner()); | |
| 131 | |
| 132 auto_connect_handler_.reset(new AutoConnectHandler()); | |
| 133 auto_connect_handler_->Init(client_cert_resolver_.get(), | |
| 134 nullptr, // no connection handler | |
| 135 network_state_handler_.get(), | |
| 136 managed_config_handler_.get()); | |
| 137 | |
| 138 base::RunLoop().RunUntilIdle(); | |
| 139 } | |
| 140 | |
| 141 void TearDown() override { | |
| 142 auto_connect_handler_.reset(); | |
| 143 client_cert_resolver_.reset(); | |
| 144 managed_config_handler_.reset(); | |
| 145 network_profile_handler_.reset(); | |
| 146 network_config_handler_.reset(); | |
| 147 network_state_handler_.reset(); | |
| 148 CertLoader::Shutdown(); | |
| 149 LoginState::Shutdown(); | |
| 150 DBusThreadManager::Shutdown(); | |
| 151 } | |
| 152 | |
| 153 protected: | |
| 154 bool Configure(const std::string& json_string) { | |
| 155 scoped_ptr<base::DictionaryValue> json_dict = | |
| 156 onc::ReadDictionaryFromJson(json_string); | |
| 157 if (!json_dict) { | |
| 158 LOG(ERROR) << "Error parsing json: " << json_string; | |
| 159 return false; | |
| 160 } | |
| 161 DBusThreadManager::Get()->GetShillManagerClient()->ConfigureService( | |
| 162 *json_dict, base::Bind(&ConfigureCallback), | |
| 163 base::Bind(&ConfigureErrorCallback)); | |
| 164 base::RunLoop().RunUntilIdle(); | |
| 165 return true; | |
| 166 } | |
| 167 | |
| 168 std::string GetServiceState(const std::string& service_path) { | |
| 169 const base::DictionaryValue* properties = | |
| 170 test_service_client_->GetServiceProperties(service_path); | |
| 171 std::string result; | |
| 172 if (properties) | |
| 173 properties->GetStringWithoutPathExpansion(shill::kStateProperty, &result); | |
| 174 return result; | |
| 175 } | |
| 176 | |
| 177 void StartCertLoader() { | |
| 178 CertLoader::Get()->StartWithNSSDB(test_nsscertdb_.get()); | |
| 179 base::RunLoop().RunUntilIdle(); | |
| 180 } | |
| 181 | |
| 182 void LoginToRegularUser() { | |
| 183 LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_ACTIVE, | |
| 184 LoginState::LOGGED_IN_USER_REGULAR); | |
| 185 base::RunLoop().RunUntilIdle(); | |
| 186 } | |
| 187 | |
| 188 scoped_refptr<net::X509Certificate> ImportTestClientCert() { | |
| 189 net::CertificateList ca_cert_list = net::CreateCertificateListFromFile( | |
| 190 net::GetTestCertsDirectory(), "client_1_ca.pem", | |
| 191 net::X509Certificate::FORMAT_AUTO); | |
| 192 if (ca_cert_list.empty()) { | |
| 193 LOG(ERROR) << "No CA cert loaded."; | |
| 194 return nullptr; | |
| 195 } | |
| 196 net::NSSCertDatabase::ImportCertFailureList failures; | |
| 197 EXPECT_TRUE(test_nsscertdb_->ImportCACerts( | |
| 198 ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures)); | |
| 199 if (!failures.empty()) { | |
| 200 LOG(ERROR) << net::ErrorToString(failures[0].net_error); | |
| 201 return nullptr; | |
| 202 } | |
| 203 | |
| 204 // Import a client cert signed by that CA. | |
| 205 scoped_refptr<net::X509Certificate> client_cert( | |
| 206 net::ImportClientCertAndKeyFromFile(net::GetTestCertsDirectory(), | |
| 207 "client_1.pem", "client_1.pk8", | |
| 208 test_nssdb_.slot())); | |
| 209 return client_cert; | |
| 210 } | |
| 211 | |
| 212 void SetupPolicy(const std::string& network_configs_json, | |
| 213 const base::DictionaryValue& global_config, | |
| 214 bool user_policy) { | |
| 215 scoped_ptr<base::ListValue> network_configs(new base::ListValue); | |
| 216 if (!network_configs_json.empty()) { | |
| 217 std::string error; | |
| 218 base::Value* network_configs_value = base::JSONReader::ReadAndReturnError( | |
| 219 network_configs_json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, | |
| 220 &error); | |
| 221 ASSERT_TRUE(network_configs_value) << error; | |
| 222 base::ListValue* network_configs_list = nullptr; | |
| 223 ASSERT_TRUE(network_configs_value->GetAsList(&network_configs_list)); | |
| 224 network_configs.reset(network_configs_list); | |
| 225 } | |
| 226 | |
| 227 if (user_policy) { | |
| 228 managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_USER_POLICY, | |
| 229 kUserHash, *network_configs, | |
| 230 global_config); | |
| 231 } else { | |
| 232 managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY, | |
| 233 std::string(), // no username hash | |
| 234 *network_configs, global_config); | |
| 235 } | |
| 236 base::RunLoop().RunUntilIdle(); | |
| 237 } | |
| 238 | |
| 239 scoped_ptr<AutoConnectHandler> auto_connect_handler_; | |
| 240 scoped_ptr<ClientCertResolver> client_cert_resolver_; | |
| 241 scoped_ptr<NetworkStateHandler> network_state_handler_; | |
| 242 scoped_ptr<NetworkConfigurationHandler> network_config_handler_; | |
| 243 scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_; | |
| 244 scoped_ptr<NetworkProfileHandler> network_profile_handler_; | |
| 245 ShillManagerClient::TestInterface* test_manager_client_; | |
| 246 ShillServiceClient::TestInterface* test_service_client_; | |
| 247 crypto::ScopedTestNSSDB test_nssdb_; | |
| 248 scoped_ptr<net::NSSCertDatabaseChromeOS> test_nsscertdb_; | |
| 249 base::MessageLoopForUI message_loop_; | |
| 250 | |
| 251 private: | |
| 252 DISALLOW_COPY_AND_ASSIGN(AutoConnectHandlerTest); | |
| 253 }; | |
| 254 | |
| 255 namespace { | |
| 256 | |
| 257 const char* kConfigUnmanagedSharedConnected = | |
| 258 "{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"online\", " | |
| 259 " \"Security\": \"wpa\" }"; | |
| 260 const char* kConfigManagedSharedConnectable = | |
| 261 "{ \"GUID\": \"wifi1\", \"Type\": \"wifi\", \"State\": \"idle\", " | |
| 262 " \"Connectable\": true, \"Security\": \"wpa\" }"; | |
| 263 | |
| 264 const char* kPolicy = | |
| 265 "[ { \"GUID\": \"wifi1\"," | |
| 266 " \"Name\": \"wifi1\"," | |
| 267 " \"Type\": \"WiFi\"," | |
| 268 " \"WiFi\": {" | |
| 269 " \"Security\": \"WPA-PSK\"," | |
| 270 " \"SSID\": \"wifi1\"," | |
| 271 " \"Passphrase\": \"passphrase\"" | |
| 272 " }" | |
| 273 "} ]"; | |
| 274 | |
| 275 const char* kPolicyCertPattern = | |
| 276 "[ { \"GUID\": \"wifi1\"," | |
| 277 " \"Name\": \"wifi1\"," | |
| 278 " \"Type\": \"WiFi\"," | |
| 279 " \"WiFi\": {" | |
| 280 " \"Security\": \"WPA-EAP\"," | |
| 281 " \"SSID\": \"wifi1\"," | |
| 282 " \"EAP\": {" | |
| 283 " \"Outer\": \"EAP-TLS\"," | |
| 284 " \"ClientCertType\": \"Pattern\"," | |
| 285 " \"ClientCertPattern\": {" | |
| 286 " \"Issuer\": {" | |
| 287 " \"CommonName\": \"B CA\"" | |
| 288 " }" | |
| 289 " }" | |
| 290 " }" | |
| 291 " }" | |
| 292 "} ]"; | |
| 293 } // namespace | |
| 294 | |
| 295 TEST_F(AutoConnectHandlerTest, ReconnectOnCertLoading) { | |
| 296 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected)); | |
| 297 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable)); | |
| 298 test_manager_client_->SetBestServiceToConnect("wifi1"); | |
| 299 | |
| 300 // User login shouldn't trigger any change until the certificates and policy | |
| 301 // are loaded. | |
| 302 LoginToRegularUser(); | |
| 303 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 304 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 305 | |
| 306 // Applying the policy which restricts autoconnect should disconnect from the | |
| 307 // shared, unmanaged network. | |
| 308 base::DictionaryValue global_config; | |
| 309 global_config.SetBooleanWithoutPathExpansion( | |
| 310 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, | |
| 311 true); | |
| 312 | |
| 313 SetupPolicy(std::string(), // no network configs | |
| 314 base::DictionaryValue(), // no global config | |
| 315 true); // load as user policy | |
| 316 SetupPolicy(kPolicy, global_config, false /* load as device policy */); | |
| 317 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0")); | |
| 318 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 319 | |
| 320 // Certificate loading should trigger connecting to the 'best' network. | |
| 321 StartCertLoader(); | |
| 322 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0")); | |
| 323 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1")); | |
| 324 } | |
| 325 | |
| 326 TEST_F(AutoConnectHandlerTest, ReconnectOnCertPatternResolved) { | |
| 327 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected)); | |
| 328 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable)); | |
| 329 test_manager_client_->SetBestServiceToConnect("wifi0"); | |
| 330 | |
| 331 SetupPolicy(std::string(), // no device policy | |
| 332 base::DictionaryValue(), // no global config | |
| 333 false); // load as device policy | |
| 334 LoginToRegularUser(); | |
| 335 StartCertLoader(); | |
| 336 SetupPolicy(kPolicyCertPattern, | |
| 337 base::DictionaryValue(), // no global config | |
| 338 true); // load as user policy | |
| 339 | |
| 340 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 341 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 342 | |
| 343 test_manager_client_->SetBestServiceToConnect("wifi1"); | |
| 344 TestCertResolveObserver observer(client_cert_resolver_.get()); | |
| 345 | |
| 346 scoped_refptr<net::X509Certificate> cert = ImportTestClientCert(); | |
| 347 ASSERT_TRUE(cert.get()); | |
| 348 | |
| 349 base::RunLoop().RunUntilIdle(); | |
| 350 EXPECT_TRUE(observer.DidNetworkPropertiesChange()); | |
| 351 | |
| 352 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0")); | |
| 353 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1")); | |
| 354 } | |
| 355 | |
| 356 // Ensure that resolving of certificate patterns only triggers a reconnect if at | |
| 357 // least one pattern was resolved. | |
| 358 TEST_F(AutoConnectHandlerTest, NoReconnectIfNoCertResolved) { | |
| 359 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected)); | |
| 360 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable)); | |
| 361 test_manager_client_->SetBestServiceToConnect("wifi0"); | |
| 362 | |
| 363 SetupPolicy(std::string(), // no device policy | |
| 364 base::DictionaryValue(), // no global config | |
| 365 false); // load as device policy | |
| 366 LoginToRegularUser(); | |
| 367 StartCertLoader(); | |
| 368 SetupPolicy(kPolicy, | |
| 369 base::DictionaryValue(), // no global config | |
| 370 true); // load as user policy | |
| 371 | |
| 372 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 373 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 374 | |
| 375 test_manager_client_->SetBestServiceToConnect("wifi1"); | |
| 376 TestCertResolveObserver observer(client_cert_resolver_.get()); | |
| 377 scoped_refptr<net::X509Certificate> cert = ImportTestClientCert(); | |
| 378 ASSERT_TRUE(cert.get()); | |
| 379 | |
| 380 base::RunLoop().RunUntilIdle(); | |
| 381 EXPECT_FALSE(observer.DidNetworkPropertiesChange()); | |
| 382 | |
| 383 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 384 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 385 } | |
| 386 | |
| 387 TEST_F(AutoConnectHandlerTest, DisconnectOnPolicyLoading) { | |
| 388 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected)); | |
| 389 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable)); | |
| 390 | |
| 391 // User login and certificate loading shouldn't trigger any change until the | |
| 392 // policy is loaded. | |
| 393 LoginToRegularUser(); | |
| 394 StartCertLoader(); | |
| 395 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 396 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 397 | |
| 398 base::DictionaryValue global_config; | |
| 399 global_config.SetBooleanWithoutPathExpansion( | |
| 400 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, | |
| 401 true); | |
| 402 | |
| 403 // Applying the policy which restricts autoconnect should disconnect from the | |
| 404 // shared, unmanaged network. | |
| 405 // Because no best service is set, the fake implementation of | |
| 406 // ConnectToBestServices will be a no-op. | |
| 407 SetupPolicy(kPolicy, global_config, false /* load as device policy */); | |
| 408 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0")); | |
| 409 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 410 } | |
| 411 | |
| 412 // After login a reconnect is triggered even if there is no managed network. | |
| 413 TEST_F(AutoConnectHandlerTest, ReconnectAfterLogin) { | |
| 414 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected)); | |
| 415 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable)); | |
| 416 test_manager_client_->SetBestServiceToConnect("wifi1"); | |
| 417 | |
| 418 // User login and certificate loading shouldn't trigger any change until the | |
| 419 // policy is loaded. | |
| 420 LoginToRegularUser(); | |
| 421 StartCertLoader(); | |
| 422 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 423 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 424 | |
| 425 // Applying an empty device policy will not trigger anything yet, until also | |
| 426 // the user policy is applied. | |
| 427 SetupPolicy(std::string(), // no network configs | |
| 428 base::DictionaryValue(), // no global config | |
| 429 false); // load as device policy | |
| 430 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 431 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 432 | |
| 433 // Applying also an empty user policy should trigger connecting to the 'best' | |
| 434 // network. | |
| 435 SetupPolicy(std::string(), // no network configs | |
| 436 base::DictionaryValue(), // no global config | |
| 437 true); // load as user policy | |
| 438 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi0")); | |
| 439 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi1")); | |
| 440 } | |
| 441 | |
| 442 TEST_F(AutoConnectHandlerTest, ManualConnectAbortsReconnectAfterLogin) { | |
| 443 EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected)); | |
| 444 EXPECT_TRUE(Configure(kConfigManagedSharedConnectable)); | |
| 445 test_manager_client_->SetBestServiceToConnect("wifi1"); | |
| 446 | |
| 447 // User login and certificate loading shouldn't trigger any change until the | |
| 448 // policy is loaded. | |
| 449 LoginToRegularUser(); | |
| 450 StartCertLoader(); | |
| 451 SetupPolicy(std::string(), // no network configs | |
| 452 base::DictionaryValue(), // no global config | |
| 453 false); // load as device policy | |
| 454 | |
| 455 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 456 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 457 | |
| 458 // A manual connect request should prevent a reconnect after login. | |
| 459 auto_connect_handler_->ConnectToNetworkRequested(); | |
| 460 | |
| 461 // Applying the user policy after login would usually trigger connecting to | |
| 462 // the 'best' network. But the manual connect prevents this. | |
| 463 SetupPolicy(std::string(), // no network configs | |
| 464 base::DictionaryValue(), // no global config | |
| 465 true); // load as user policy | |
| 466 EXPECT_EQ(shill::kStateOnline, GetServiceState("wifi0")); | |
| 467 EXPECT_EQ(shill::kStateIdle, GetServiceState("wifi1")); | |
| 468 } | |
| 469 | |
| 470 } // namespace chromeos | |
| 471 | |
| 472 #endif | |
| OLD | NEW |