login_utils_browsertest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2012 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 "chrome/browser/chromeos/login/login_utils.h" 6 7#include "base/basictypes.h" 8#include "base/bind.h" 9#include "base/command_line.h" 10#include "base/files/scoped_temp_dir.h" 11#include "base/message_loop/message_loop.h" 12#include "base/path_service.h" 13#include "base/prefs/pref_registry_simple.h" 14#include "base/run_loop.h" 15#include "base/strings/string_util.h" 16#include "base/synchronization/waitable_event.h" 17#include "base/threading/sequenced_worker_pool.h" 18#include "base/threading/thread.h" 19#include "chrome/browser/chrome_notification_types.h" 20#include "chrome/browser/chromeos/input_method/input_method_configuration.h" 21#include "chrome/browser/chromeos/input_method/mock_input_method_manager.h" 22#include "chrome/browser/chromeos/login/authenticator.h" 23#include "chrome/browser/chromeos/login/login_status_consumer.h" 24#include "chrome/browser/chromeos/login/user_manager.h" 25#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 26#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" 27#include "chrome/browser/chromeos/profiles/profile_helper.h" 28#include "chrome/browser/chromeos/settings/cros_settings.h" 29#include "chrome/browser/chromeos/settings/device_settings_service.h" 30#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" 31#include "chrome/browser/chromeos/settings/mock_owner_key_util.h" 32#include "chrome/browser/io_thread.h" 33#include "chrome/browser/net/predictor.h" 34#include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h" 35#include "chrome/browser/profiles/profile_manager.h" 36#include "chrome/browser/rlz/rlz.h" 37#include "chrome/common/chrome_paths.h" 38#include "chrome/common/pref_names.h" 39#include "chrome/test/base/scoped_testing_local_state.h" 40#include "chrome/test/base/testing_browser_process.h" 41#include "chromeos/chromeos_switches.h" 42#include "chromeos/cryptohome/mock_async_method_caller.h" 43#include "chromeos/cryptohome/system_salt_getter.h" 44#include "chromeos/dbus/fake_dbus_thread_manager.h" 45#include "chromeos/disks/disk_mount_manager.h" 46#include "chromeos/disks/mock_disk_mount_manager.h" 47#include "chromeos/login/login_state.h" 48#include "chromeos/network/network_handler.h" 49#include "chromeos/system/mock_statistics_provider.h" 50#include "chromeos/system/statistics_provider.h" 51#include "components/policy/core/common/cloud/device_management_service.h" 52#include "components/policy/core/common/policy_service.h" 53#include "components/policy/core/common/policy_switches.h" 54#include "content/public/browser/browser_thread.h" 55#include "content/public/test/test_browser_thread.h" 56#include "content/public/test/test_utils.h" 57#include "google_apis/gaia/gaia_auth_consumer.h" 58#include "google_apis/gaia/gaia_urls.h" 59#include "net/url_request/test_url_fetcher_factory.h" 60#include "net/url_request/url_fetcher_delegate.h" 61#include "net/url_request/url_request.h" 62#include "net/url_request/url_request_context_getter.h" 63#include "net/url_request/url_request_status.h" 64#include "net/url_request/url_request_test_util.h" 65#include "policy/proto/device_management_backend.pb.h" 66#include "testing/gmock/include/gmock/gmock.h" 67#include "testing/gtest/include/gtest/gtest.h" 68 69#if defined(ENABLE_RLZ) 70#include "rlz/lib/rlz_value_store.h" 71#endif 72 73using ::testing::AnyNumber; 74 75namespace chromeos { 76 77namespace { 78 79namespace em = enterprise_management; 80 81using ::testing::DoAll; 82using ::testing::Return; 83using ::testing::SaveArg; 84using ::testing::SetArgPointee; 85using ::testing::_; 86using content::BrowserThread; 87 88const char kDomain[] = "domain.com"; 89const char kUsername[] = "user@domain.com"; 90const char kDeviceId[] = "100200300"; 91const char kUsernameOtherDomain[] = "user@other.com"; 92 93const char kOAuthTokenCookie[] = "oauth_token=1234"; 94 95const char kGaiaAccountDisabledResponse[] = "Error=AccountDeleted"; 96 97const char kOAuth2TokenPairData[] = 98 "{" 99 " \"refresh_token\": \"1234\"," 100 " \"access_token\": \"5678\"," 101 " \"expires_in\": 3600" 102 "}"; 103 104const char kOAuth2AccessTokenData[] = 105 "{" 106 " \"access_token\": \"5678\"," 107 " \"expires_in\": 3600" 108 "}"; 109 110const char kDMServer[] = "http://server/device_management"; 111const char kDMRegisterRequest[] = 112 "http://server/device_management?request=register"; 113const char kDMPolicyRequest[] = 114 "http://server/device_management?request=policy"; 115 116const char kDMToken[] = "1234"; 117 118// Single task of the fake IO loop used in the test, that just waits until 119// it is signaled to quit or perform some work. 120// |completion| is the event to wait for, and |work| is the task to invoke 121// when signaled. If the task returns false then this quits the IO loop. 122void BlockLoop(base::WaitableEvent* completion, base::Callback<bool()> work) { 123 do { 124 completion->Wait(); 125 } while (work.Run()); 126 base::MessageLoop::current()->QuitNow(); 127} 128 129void CopyLockResult(base::RunLoop* loop, 130 policy::EnterpriseInstallAttributes::LockResult* out, 131 policy::EnterpriseInstallAttributes::LockResult result) { 132 *out = result; 133 loop->Quit(); 134} 135 136class LoginUtilsTest : public testing::Test, 137 public LoginUtils::Delegate, 138 public LoginStatusConsumer { 139 public: 140 // Initialization here is important. The UI thread gets the test's 141 // message loop, as does the file thread (which never actually gets 142 // started - so this is a way to fake multiple threads on a single 143 // test thread). The IO thread does not get the message loop set, 144 // and is never started. This is necessary so that we skip various 145 // bits of initialization that get posted to the IO thread. We do 146 // however, at one point in the test, temporarily set the message 147 // loop for the IO thread. 148 LoginUtilsTest() 149 : fake_io_thread_completion_(false, false), 150 fake_io_thread_("fake_io_thread"), 151 browser_process_(TestingBrowserProcess::GetGlobal()), 152 local_state_(browser_process_), 153 ui_thread_(BrowserThread::UI, &loop_), 154 db_thread_(BrowserThread::DB, &loop_), 155 file_thread_(BrowserThread::FILE, &loop_), 156 mock_input_method_manager_(NULL), 157 mock_async_method_caller_(NULL), 158 connector_(NULL), 159 prepared_profile_(NULL) {} 160 161 virtual void SetUp() OVERRIDE { 162 // This test is not a full blown InProcessBrowserTest, and doesn't have 163 // all the usual threads running. However a lot of subsystems pulled from 164 // ProfileImpl post to IO (usually from ProfileIOData), and DCHECK that 165 // those tasks were posted. Those tasks in turn depend on a lot of other 166 // components that aren't there during this test, so this kludge is used to 167 // have a running IO loop that doesn't really execute any tasks. 168 // 169 // See InvokeOnIO() below for a way to perform specific tasks on IO, when 170 // that's necessary. 171 172 // A thread is needed to create a new MessageLoop, since there can be only 173 // one loop per thread. 174 fake_io_thread_.StartWithOptions( 175 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 176 base::MessageLoop* fake_io_loop = fake_io_thread_.message_loop(); 177 // Make this loop enter the single task, BlockLoop(). Pass in the completion 178 // event and the work callback. 179 fake_io_thread_.StopSoon(); 180 fake_io_loop->PostTask( 181 FROM_HERE, 182 base::Bind( 183 BlockLoop, 184 &fake_io_thread_completion_, 185 base::Bind(&LoginUtilsTest::DoIOWork, base::Unretained(this)))); 186 // Map BrowserThread::IO to this loop. This allows posting to IO but nothing 187 // will be executed. 188 io_thread_.reset( 189 new content::TestBrowserThread(BrowserThread::IO, fake_io_loop)); 190 191 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); 192 193 CommandLine* command_line = CommandLine::ForCurrentProcess(); 194 command_line->AppendSwitchASCII( 195 policy::switches::kDeviceManagementUrl, kDMServer); 196 command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); 197 198 // DBusThreadManager should be initialized before io_thread_state_, as 199 // DBusThreadManager is used from chromeos::ProxyConfigServiceImpl, 200 // which is part of io_thread_state_. 201 DBusThreadManager::InitializeWithStub(); 202 203 SystemSaltGetter::Initialize(); 204 LoginState::Initialize(); 205 206 EXPECT_CALL(mock_statistics_provider_, GetMachineStatistic(_, _)) 207 .WillRepeatedly(Return(false)); 208 chromeos::system::StatisticsProvider::SetTestProvider( 209 &mock_statistics_provider_); 210 211 mock_input_method_manager_ = new input_method::MockInputMethodManager(); 212 input_method::InitializeForTesting(mock_input_method_manager_); 213 disks::DiskMountManager::InitializeForTesting(&mock_disk_mount_manager_); 214 mock_disk_mount_manager_.SetupDefaultReplies(); 215 216 mock_async_method_caller_ = new cryptohome::MockAsyncMethodCaller; 217 cryptohome::AsyncMethodCaller::InitializeForTesting( 218 mock_async_method_caller_); 219 220 test_device_settings_service_.reset(new ScopedTestDeviceSettingsService); 221 test_cros_settings_.reset(new ScopedTestCrosSettings); 222 test_user_manager_.reset(new ScopedTestUserManager); 223 224 // IOThread creates ProxyConfigServiceImpl and 225 // BrowserPolicyConnector::Init() creates a NetworkConfigurationUpdater, 226 // which both access NetworkHandler. Thus initialize it here before creating 227 // IOThread and before calling BrowserPolicyConnector::Init(). 228 NetworkHandler::Initialize(); 229 230 browser_process_->SetProfileManager( 231 new ProfileManagerWithoutInit(scoped_temp_dir_.path())); 232 browser_process_->SetSystemRequestContext( 233 new net::TestURLRequestContextGetter( 234 base::MessageLoopProxy::current())); 235 connector_ = 236 browser_process_->platform_part()->browser_policy_connector_chromeos(); 237 connector_->Init(local_state_.Get(), 238 browser_process_->system_request_context()); 239 240 io_thread_state_.reset(new IOThread(local_state_.Get(), 241 browser_process_->policy_service(), 242 NULL, NULL)); 243 browser_process_->SetIOThread(io_thread_state_.get()); 244 245#if defined(ENABLE_RLZ) 246 rlz_initialized_cb_ = base::Bind(&base::DoNothing); 247 rlz_lib::testing::SetRlzStoreDirectory(scoped_temp_dir_.path()); 248 RLZTracker::EnableZeroDelayForTesting(); 249#endif 250 251 RunUntilIdle(); 252 } 253 254 virtual void TearDown() OVERRIDE { 255 cryptohome::AsyncMethodCaller::Shutdown(); 256 mock_async_method_caller_ = NULL; 257 258 test_user_manager_.reset(); 259 260 InvokeOnIO( 261 base::Bind(&LoginUtilsTest::TearDownOnIO, base::Unretained(this))); 262 263 // LoginUtils instance must not outlive Profile instances. 264 LoginUtils::Set(NULL); 265 266 input_method::Shutdown(); 267 LoginState::Shutdown(); 268 SystemSaltGetter::Shutdown(); 269 270 // These trigger some tasks that have to run while BrowserThread::UI 271 // exists. Delete all the profiles before deleting the connector. 272 browser_process_->SetProfileManager(NULL); 273 connector_ = NULL; 274 browser_process_->SetBrowserPolicyConnector(NULL); 275 QuitIOLoop(); 276 RunUntilIdle(); 277 } 278 279 void TearDownOnIO() { 280 // chrome_browser_net::Predictor usually skips its shutdown routines on 281 // unit_tests, but does the full thing when 282 // g_browser_process->profile_manager() is valid during initialization. 283 // That includes a WaitableEvent on UI waiting for a task on IO, so that 284 // task must execute. Do it directly from here now. 285 std::vector<Profile*> profiles = 286 browser_process_->profile_manager()->GetLoadedProfiles(); 287 for (size_t i = 0; i < profiles.size(); ++i) { 288 chrome_browser_net::Predictor* predictor = 289 profiles[i]->GetNetworkPredictor(); 290 if (predictor) { 291 predictor->EnablePredictorOnIOThread(false); 292 predictor->Shutdown(); 293 } 294 } 295 } 296 297 void RunUntilIdle() { 298 loop_.RunUntilIdle(); 299 BrowserThread::GetBlockingPool()->FlushForTesting(); 300 loop_.RunUntilIdle(); 301 } 302 303 // Invokes |task| on the IO loop and returns after it has executed. 304 void InvokeOnIO(const base::Closure& task) { 305 fake_io_thread_work_ = task; 306 fake_io_thread_completion_.Signal(); 307 content::RunMessageLoop(); 308 } 309 310 // Makes the fake IO loop return. 311 void QuitIOLoop() { 312 fake_io_thread_completion_.Signal(); 313 content::RunMessageLoop(); 314 } 315 316 // Helper for BlockLoop, InvokeOnIO and QuitIOLoop. 317 bool DoIOWork() { 318 bool has_work = !fake_io_thread_work_.is_null(); 319 if (has_work) 320 fake_io_thread_work_.Run(); 321 fake_io_thread_work_.Reset(); 322 BrowserThread::PostTask( 323 BrowserThread::UI, FROM_HERE, 324 base::MessageLoop::QuitWhenIdleClosure()); 325 // If there was work then keep waiting for more work. 326 // If there was no work then quit the fake IO loop. 327 return has_work; 328 } 329 330 virtual void OnProfilePrepared(Profile* profile) OVERRIDE { 331 EXPECT_FALSE(prepared_profile_); 332 prepared_profile_ = profile; 333 } 334 335#if defined(ENABLE_RLZ) 336 virtual void OnRlzInitialized(Profile* profile) OVERRIDE { 337 rlz_initialized_cb_.Run(); 338 } 339#endif 340 341 virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE { 342 FAIL() << "OnLoginFailure not expected"; 343 } 344 345 virtual void OnLoginSuccess(const UserContext& user_context) OVERRIDE { 346 FAIL() << "OnLoginSuccess not expected"; 347 } 348 349 void EnrollDevice(const std::string& username) { 350 base::RunLoop loop; 351 policy::EnterpriseInstallAttributes::LockResult result; 352 connector_->GetInstallAttributes()->LockDevice( 353 username, policy::DEVICE_MODE_ENTERPRISE, kDeviceId, 354 base::Bind(&CopyLockResult, &loop, &result)); 355 loop.Run(); 356 EXPECT_EQ(policy::EnterpriseInstallAttributes::LOCK_SUCCESS, result); 357 RunUntilIdle(); 358 } 359 360 void PrepareProfile(const std::string& username) { 361 // Normally this would happen during browser startup, but for tests 362 // we need to trigger creation of Profile-related services. 363 ChromeBrowserMainExtraPartsProfiles:: 364 EnsureBrowserContextKeyedServiceFactoriesBuilt(); 365 366 DeviceSettingsTestHelper device_settings_test_helper; 367 DeviceSettingsService::Get()->SetSessionManager( 368 &device_settings_test_helper, new MockOwnerKeyUtil()); 369 370 EXPECT_CALL(*mock_async_method_caller_, AsyncMount(_, _, _, _)) 371 .WillRepeatedly(Return()); 372 EXPECT_CALL(*mock_async_method_caller_, AsyncGetSanitizedUsername(_, _)) 373 .WillRepeatedly(Return()); 374 375 scoped_refptr<Authenticator> authenticator = 376 LoginUtils::Get()->CreateAuthenticator(this); 377 authenticator->CompleteLogin(ProfileHelper::GetSigninProfile(), 378 UserContext(username, 379 "password", 380 std::string(), 381 username)); // username_hash 382 383 const bool kUsingOAuth = true; 384 // Setting |kHasCookies| to false prevents ProfileAuthData::Transfer from 385 // waiting for an IO task before proceeding. 386 const bool kHasCookies = false; 387 const bool kHasActiveSession = false; 388 LoginUtils::Get()->PrepareProfile( 389 UserContext(username, 390 "password", 391 std::string(), 392 username, 393 kUsingOAuth, 394 UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML), 395 std::string(), kHasCookies, kHasActiveSession, this); 396 device_settings_test_helper.Flush(); 397 RunUntilIdle(); 398 399 DeviceSettingsService::Get()->UnsetSessionManager(); 400 } 401 402 net::TestURLFetcher* PrepareOAuthFetcher(const GURL& expected_url) { 403 net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID(0); 404 EXPECT_TRUE(fetcher); 405 if (!fetcher) 406 return NULL; 407 EXPECT_TRUE(fetcher->delegate()); 408 EXPECT_TRUE(StartsWithASCII(fetcher->GetOriginalURL().spec(), 409 expected_url.spec(), 410 true)); 411 fetcher->set_url(fetcher->GetOriginalURL()); 412 fetcher->set_response_code(200); 413 fetcher->set_status(net::URLRequestStatus()); 414 return fetcher; 415 } 416 417 net::TestURLFetcher* PrepareDMServiceFetcher( 418 const std::string& expected_url, 419 const em::DeviceManagementResponse& response) { 420 net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID( 421 policy::DeviceManagementService::kURLFetcherID); 422 EXPECT_TRUE(fetcher); 423 if (!fetcher) 424 return NULL; 425 EXPECT_TRUE(fetcher->delegate()); 426 EXPECT_TRUE(StartsWithASCII(fetcher->GetOriginalURL().spec(), 427 expected_url, 428 true)); 429 fetcher->set_url(fetcher->GetOriginalURL()); 430 fetcher->set_response_code(200); 431 fetcher->set_status(net::URLRequestStatus()); 432 std::string data; 433 EXPECT_TRUE(response.SerializeToString(&data)); 434 fetcher->SetResponseString(data); 435 return fetcher; 436 } 437 438 net::TestURLFetcher* PrepareDMRegisterFetcher() { 439 em::DeviceManagementResponse response; 440 em::DeviceRegisterResponse* register_response = 441 response.mutable_register_response(); 442 register_response->set_device_management_token(kDMToken); 443 register_response->set_enrollment_type( 444 em::DeviceRegisterResponse::ENTERPRISE); 445 return PrepareDMServiceFetcher(kDMRegisterRequest, response); 446 } 447 448 net::TestURLFetcher* PrepareDMPolicyFetcher() { 449 em::DeviceManagementResponse response; 450 response.mutable_policy_response()->add_response(); 451 return PrepareDMServiceFetcher(kDMPolicyRequest, response); 452 } 453 454 protected: 455 // Must be the first member variable as browser_process_ and local_state_ 456 // rely on this being set up. 457 TestingBrowserProcessInitializer initializer_; 458 459 base::Closure fake_io_thread_work_; 460 base::WaitableEvent fake_io_thread_completion_; 461 base::Thread fake_io_thread_; 462 463 base::MessageLoopForIO loop_; 464 TestingBrowserProcess* browser_process_; 465 ScopedTestingLocalState local_state_; 466 467 content::TestBrowserThread ui_thread_; 468 content::TestBrowserThread db_thread_; 469 content::TestBrowserThread file_thread_; 470 scoped_ptr<content::TestBrowserThread> io_thread_; 471 scoped_ptr<IOThread> io_thread_state_; 472 473 input_method::MockInputMethodManager* mock_input_method_manager_; 474 disks::MockDiskMountManager mock_disk_mount_manager_; 475 net::TestURLFetcherFactory test_url_fetcher_factory_; 476 477 cryptohome::MockAsyncMethodCaller* mock_async_method_caller_; 478 479 chromeos::system::MockStatisticsProvider mock_statistics_provider_; 480 481 policy::BrowserPolicyConnectorChromeOS* connector_; 482 483 scoped_ptr<ScopedTestDeviceSettingsService> test_device_settings_service_; 484 scoped_ptr<ScopedTestCrosSettings> test_cros_settings_; 485 scoped_ptr<ScopedTestUserManager> test_user_manager_; 486 487 Profile* prepared_profile_; 488 489 base::Closure rlz_initialized_cb_; 490 491 private: 492 base::ScopedTempDir scoped_temp_dir_; 493 494 std::string device_policy_; 495 std::string user_policy_; 496 497 DISALLOW_COPY_AND_ASSIGN(LoginUtilsTest); 498}; 499 500class LoginUtilsBlockingLoginTest 501 : public LoginUtilsTest, 502 public testing::WithParamInterface<int> {}; 503 504TEST_F(LoginUtilsTest, NormalLoginDoesntBlock) { 505 UserManager* user_manager = UserManager::Get(); 506 EXPECT_FALSE(user_manager->IsUserLoggedIn()); 507 EXPECT_FALSE(connector_->IsEnterpriseManaged()); 508 EXPECT_FALSE(prepared_profile_); 509 EXPECT_EQ(policy::USER_AFFILIATION_NONE, 510 connector_->GetUserAffiliation(kUsername)); 511 512 // The profile will be created without waiting for a policy response. 513 PrepareProfile(kUsername); 514 515 EXPECT_TRUE(prepared_profile_); 516 ASSERT_TRUE(user_manager->IsUserLoggedIn()); 517 EXPECT_EQ(kUsername, user_manager->GetLoggedInUser()->email()); 518} 519 520TEST_F(LoginUtilsTest, EnterpriseLoginDoesntBlockForNormalUser) { 521 UserManager* user_manager = UserManager::Get(); 522 EXPECT_FALSE(user_manager->IsUserLoggedIn()); 523 EXPECT_FALSE(connector_->IsEnterpriseManaged()); 524 EXPECT_FALSE(prepared_profile_); 525 526 // Enroll the device. 527 EnrollDevice(kUsername); 528 529 EXPECT_FALSE(user_manager->IsUserLoggedIn()); 530 EXPECT_TRUE(connector_->IsEnterpriseManaged()); 531 EXPECT_EQ(kDomain, connector_->GetEnterpriseDomain()); 532 EXPECT_FALSE(prepared_profile_); 533 EXPECT_EQ(policy::USER_AFFILIATION_NONE, 534 connector_->GetUserAffiliation(kUsernameOtherDomain)); 535 536 // Login with a non-enterprise user shouldn't block. 537 PrepareProfile(kUsernameOtherDomain); 538 539 EXPECT_TRUE(prepared_profile_); 540 ASSERT_TRUE(user_manager->IsUserLoggedIn()); 541 EXPECT_EQ(kUsernameOtherDomain, user_manager->GetLoggedInUser()->email()); 542} 543 544#if defined(ENABLE_RLZ) 545TEST_F(LoginUtilsTest, RlzInitialized) { 546 // No RLZ brand code set initially. 547 EXPECT_FALSE(local_state_.Get()->HasPrefPath(prefs::kRLZBrand)); 548 549 base::RunLoop wait_for_rlz_init; 550 rlz_initialized_cb_ = wait_for_rlz_init.QuitClosure(); 551 552 PrepareProfile(kUsername); 553 554 wait_for_rlz_init.Run(); 555 // Wait for blocking RLZ tasks to complete. 556 RunUntilIdle(); 557 558 // RLZ brand code has been set to empty string. 559 EXPECT_TRUE(local_state_.Get()->HasPrefPath(prefs::kRLZBrand)); 560 EXPECT_EQ(std::string(), local_state_.Get()->GetString(prefs::kRLZBrand)); 561 562 // RLZ value for homepage access point should have been initialized. 563 base::string16 rlz_string; 564 EXPECT_TRUE(RLZTracker::GetAccessPointRlz( 565 RLZTracker::CHROME_HOME_PAGE, &rlz_string)); 566 EXPECT_EQ(base::string16(), rlz_string); 567} 568#endif 569 570TEST_P(LoginUtilsBlockingLoginTest, EnterpriseLoginBlocksForEnterpriseUser) { 571 UserManager* user_manager = UserManager::Get(); 572 EXPECT_FALSE(user_manager->IsUserLoggedIn()); 573 EXPECT_FALSE(connector_->IsEnterpriseManaged()); 574 EXPECT_FALSE(prepared_profile_); 575 576 // Enroll the device. 577 EnrollDevice(kUsername); 578 579 EXPECT_FALSE(user_manager->IsUserLoggedIn()); 580 EXPECT_TRUE(connector_->IsEnterpriseManaged()); 581 EXPECT_EQ(kDomain, connector_->GetEnterpriseDomain()); 582 EXPECT_FALSE(prepared_profile_); 583 EXPECT_EQ(policy::USER_AFFILIATION_MANAGED, 584 connector_->GetUserAffiliation(kUsername)); 585 EXPECT_FALSE(user_manager->IsKnownUser(kUsername)); 586 587 // Login with a user of the enterprise domain waits for policy. 588 PrepareProfile(kUsername); 589 590 EXPECT_FALSE(prepared_profile_); 591 ASSERT_TRUE(user_manager->IsUserLoggedIn()); 592 EXPECT_TRUE(user_manager->IsCurrentUserNew()); 593 594 GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); 595 net::TestURLFetcher* fetcher; 596 597 // |steps| is the test parameter, and is the number of successful fetches. 598 // The first incomplete fetch will fail. In any case, the profile creation 599 // should resume. 600 int steps = GetParam(); 601 602 // The next expected fetcher ID. This is used to make it fail. 603 int next_expected_fetcher_id = 0; 604 605 do { 606 if (steps < 1) break; 607 608 // Fake refresh token retrieval: 609 fetcher = PrepareOAuthFetcher(gaia_urls->client_login_to_oauth2_url()); 610 ASSERT_TRUE(fetcher); 611 net::ResponseCookies cookies; 612 cookies.push_back(kOAuthTokenCookie); 613 fetcher->set_cookies(cookies); 614 fetcher->delegate()->OnURLFetchComplete(fetcher); 615 if (steps < 2) break; 616 617 // Fake OAuth2 token pair retrieval: 618 fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url()); 619 ASSERT_TRUE(fetcher); 620 fetcher->SetResponseString(kOAuth2TokenPairData); 621 fetcher->delegate()->OnURLFetchComplete(fetcher); 622 if (steps < 3) break; 623 624 // Fake OAuth2 access token retrieval: 625 fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url()); 626 ASSERT_TRUE(fetcher); 627 fetcher->SetResponseString(kOAuth2AccessTokenData); 628 fetcher->delegate()->OnURLFetchComplete(fetcher); 629 630 // The cloud policy subsystem is now ready to fetch the dmtoken and the user 631 // policy. 632 next_expected_fetcher_id = policy::DeviceManagementService::kURLFetcherID; 633 RunUntilIdle(); 634 if (steps < 4) break; 635 636 fetcher = PrepareDMRegisterFetcher(); 637 ASSERT_TRUE(fetcher); 638 fetcher->delegate()->OnURLFetchComplete(fetcher); 639 // The policy fetch job has now been scheduled, run it: 640 RunUntilIdle(); 641 if (steps < 5) break; 642 643 // Verify that there is no profile prepared just before the policy fetch. 644 EXPECT_FALSE(prepared_profile_); 645 646 fetcher = PrepareDMPolicyFetcher(); 647 ASSERT_TRUE(fetcher); 648 fetcher->delegate()->OnURLFetchComplete(fetcher); 649 RunUntilIdle(); 650 } while (0); 651 652 if (steps < 5) { 653 // Verify that the profile hasn't been created yet. 654 EXPECT_FALSE(prepared_profile_); 655 656 // Make the current fetcher fail with a Gaia error. 657 net::TestURLFetcher* fetcher = test_url_fetcher_factory_.GetFetcherByID( 658 next_expected_fetcher_id); 659 ASSERT_TRUE(fetcher); 660 EXPECT_TRUE(fetcher->delegate()); 661 fetcher->set_url(fetcher->GetOriginalURL()); 662 fetcher->set_response_code(401); 663 // This response body is important to make the gaia fetcher skip its delayed 664 // retry behavior, which makes testing harder. If this is sent to the policy 665 // fetchers then it will make them fail too. 666 fetcher->SetResponseString(kGaiaAccountDisabledResponse); 667 fetcher->delegate()->OnURLFetchComplete(fetcher); 668 RunUntilIdle(); 669 } 670 671 // The profile is finally ready: 672 EXPECT_TRUE(prepared_profile_); 673} 674 675INSTANTIATE_TEST_CASE_P( 676 LoginUtilsBlockingLoginTestInstance, 677 LoginUtilsBlockingLoginTest, 678 testing::Values(0, 1, 2, 3, 4, 5)); 679 680} // namespace 681 682} // namespace chromeos 683