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