1 // Copyright (c) 2011 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/google_authenticator.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/file_path.h" 11 #include "base/file_util.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/message_loop.h" 14 #include "base/path_service.h" 15 #include "base/string_util.h" 16 #include "base/stringprintf.h" 17 #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" 18 #include "chrome/browser/chromeos/cros/mock_library_loader.h" 19 #include "chrome/browser/chromeos/login/client_login_response_handler.h" 20 #include "chrome/browser/chromeos/login/issue_response_handler.h" 21 #include "chrome/browser/chromeos/login/mock_auth_response_handler.h" 22 #include "chrome/browser/chromeos/login/mock_login_status_consumer.h" 23 #include "chrome/browser/chromeos/login/mock_url_fetchers.h" 24 #include "chrome/browser/chromeos/login/mock_user_manager.h" 25 #include "chrome/browser/chromeos/login/user_manager.h" 26 #include "chrome/common/chrome_paths.h" 27 #include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" 28 #include "chrome/common/net/url_fetcher.h" 29 #include "chrome/test/testing_profile.h" 30 #include "content/browser/browser_thread.h" 31 #include "googleurl/src/gurl.h" 32 #include "net/base/net_errors.h" 33 #include "net/url_request/url_request_status.h" 34 #include "testing/gmock/include/gmock/gmock.h" 35 #include "testing/gtest/include/gtest/gtest.h" 36 37 using namespace file_util; 38 using ::testing::AnyNumber; 39 using ::testing::DoAll; 40 using ::testing::Eq; 41 using ::testing::Invoke; 42 using ::testing::Return; 43 using ::testing::SetArgumentPointee; 44 using ::testing::_; 45 46 namespace chromeos { 47 48 class GoogleAuthenticatorTest : public ::testing::Test { 49 public: 50 GoogleAuthenticatorTest() 51 : message_loop_ui_(MessageLoop::TYPE_UI), 52 ui_thread_(BrowserThread::UI, &message_loop_ui_), 53 username_("me (at) nowhere.org"), 54 password_("fakepass"), 55 result_("", "", "", ""), 56 bytes_as_ascii_("ffff"), 57 user_manager_(new MockUserManager) { 58 memset(fake_hash_, 0, sizeof(fake_hash_)); 59 fake_hash_[0] = 10; 60 fake_hash_[1] = 1; 61 fake_hash_[7] = 10 << 4; 62 hash_ascii_.assign("0a010000000000a0"); 63 hash_ascii_.append(std::string(16, '0')); 64 65 memset(raw_bytes_, 0xff, sizeof(raw_bytes_)); 66 } 67 ~GoogleAuthenticatorTest() {} 68 69 virtual void SetUp() { 70 chromeos::CrosLibrary::TestApi* test_api = 71 chromeos::CrosLibrary::Get()->GetTestApi(); 72 73 loader_ = new MockLibraryLoader(); 74 ON_CALL(*loader_, Load(_)) 75 .WillByDefault(Return(true)); 76 EXPECT_CALL(*loader_, Load(_)) 77 .Times(AnyNumber()); 78 79 test_api->SetLibraryLoader(loader_, true); 80 81 mock_library_ = new MockCryptohomeLibrary(); 82 test_api->SetCryptohomeLibrary(mock_library_, true); 83 } 84 85 // Tears down the test fixture. 86 virtual void TearDown() { 87 // Prevent bogus gMock leak check from firing. 88 chromeos::CrosLibrary::TestApi* test_api = 89 chromeos::CrosLibrary::Get()->GetTestApi(); 90 test_api->SetLibraryLoader(NULL, false); 91 test_api->SetCryptohomeLibrary(NULL, false); 92 } 93 94 FilePath PopulateTempFile(const char* data, int data_len) { 95 FilePath out; 96 FILE* tmp_file = CreateAndOpenTemporaryFile(&out); 97 EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); 98 EXPECT_EQ(WriteFile(out, data, data_len), data_len); 99 EXPECT_TRUE(CloseFile(tmp_file)); 100 return out; 101 } 102 103 FilePath FakeLocalaccountFile(const std::string& ascii) { 104 FilePath exe_dir; 105 FilePath local_account_file; 106 PathService::Get(base::DIR_EXE, &exe_dir); 107 FILE* tmp_file = CreateAndOpenTemporaryFileInDir(exe_dir, 108 &local_account_file); 109 int ascii_len = ascii.length(); 110 EXPECT_NE(tmp_file, static_cast<FILE*>(NULL)); 111 EXPECT_EQ(WriteFile(local_account_file, ascii.c_str(), ascii_len), 112 ascii_len); 113 EXPECT_TRUE(CloseFile(tmp_file)); 114 return local_account_file; 115 } 116 117 void ReadLocalaccountFile(GoogleAuthenticator* auth, 118 const std::string& filename) { 119 BrowserThread file_thread(BrowserThread::FILE); 120 file_thread.Start(); 121 122 BrowserThread::PostTask( 123 BrowserThread::FILE, FROM_HERE, 124 NewRunnableMethod(auth, 125 &GoogleAuthenticator::LoadLocalaccount, 126 filename)); 127 } 128 129 void PrepForLogin(GoogleAuthenticator* auth) { 130 auth->set_password_hash(hash_ascii_); 131 auth->set_username(username_); 132 auth->set_password(password_); 133 auth->SetLocalaccount(""); 134 auth->set_user_manager(user_manager_.get()); 135 ON_CALL(*user_manager_.get(), IsKnownUser(username_)) 136 .WillByDefault(Return(true)); 137 } 138 139 void PrepForFailedLogin(GoogleAuthenticator* auth) { 140 PrepForLogin(auth); 141 auth->set_hosted_policy(GaiaAuthFetcher::HostedAccountsAllowed); 142 } 143 144 void CancelLogin(GoogleAuthenticator* auth) { 145 BrowserThread::PostTask( 146 BrowserThread::UI, 147 FROM_HERE, 148 NewRunnableMethod(auth, 149 &GoogleAuthenticator::CancelClientLogin)); 150 } 151 152 MessageLoop message_loop_ui_; 153 BrowserThread ui_thread_; 154 155 unsigned char fake_hash_[32]; 156 std::string hash_ascii_; 157 std::string username_; 158 std::string password_; 159 GaiaAuthConsumer::ClientLoginResult result_; 160 // Mocks, destroyed by CrosLibrary class. 161 MockCryptohomeLibrary* mock_library_; 162 MockLibraryLoader* loader_; 163 164 char raw_bytes_[2]; 165 std::string bytes_as_ascii_; 166 167 scoped_ptr<MockUserManager> user_manager_; 168 }; 169 170 TEST_F(GoogleAuthenticatorTest, SaltToAscii) { 171 unsigned char fake_salt[8] = { 0 }; 172 fake_salt[0] = 10; 173 fake_salt[1] = 1; 174 fake_salt[7] = 10 << 4; 175 std::vector<unsigned char> salt_v(fake_salt, fake_salt + sizeof(fake_salt)); 176 177 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); 178 179 ON_CALL(*mock_library_, GetSystemSalt()) 180 .WillByDefault(Return(salt_v)); 181 EXPECT_CALL(*mock_library_, GetSystemSalt()) 182 .Times(1) 183 .RetiresOnSaturation(); 184 185 EXPECT_EQ("0a010000000000a0", auth->SaltAsAscii()); 186 } 187 188 TEST_F(GoogleAuthenticatorTest, ReadLocalaccount) { 189 FilePath tmp_file_path = FakeLocalaccountFile(bytes_as_ascii_); 190 191 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); 192 ReadLocalaccountFile(auth.get(), tmp_file_path.BaseName().value()); 193 EXPECT_EQ(auth->localaccount_, bytes_as_ascii_); 194 Delete(tmp_file_path, false); 195 } 196 197 TEST_F(GoogleAuthenticatorTest, ReadLocalaccountTrailingWS) { 198 FilePath tmp_file_path = 199 FakeLocalaccountFile(base::StringPrintf("%s\n", 200 bytes_as_ascii_.c_str())); 201 202 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); 203 ReadLocalaccountFile(auth.get(), tmp_file_path.BaseName().value()); 204 EXPECT_EQ(auth->localaccount_, bytes_as_ascii_); 205 Delete(tmp_file_path, false); 206 } 207 208 TEST_F(GoogleAuthenticatorTest, ReadNoLocalaccount) { 209 FilePath tmp_file_path = FakeLocalaccountFile(bytes_as_ascii_); 210 EXPECT_TRUE(Delete(tmp_file_path, false)); // Ensure non-existent file. 211 212 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(NULL)); 213 ReadLocalaccountFile(auth.get(), tmp_file_path.BaseName().value()); 214 EXPECT_EQ(auth->localaccount_, std::string()); 215 } 216 217 TEST_F(GoogleAuthenticatorTest, OnLoginSuccess) { 218 MockConsumer consumer; 219 EXPECT_CALL(consumer, OnLoginSuccess(username_, password_, _, false)) 220 .Times(1) 221 .RetiresOnSaturation(); 222 223 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 224 .WillOnce(Return(true)) 225 .RetiresOnSaturation(); 226 227 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 228 auth->set_password_hash(hash_ascii_); 229 auth->set_username(username_); 230 auth->set_password(password_); 231 auth->OnLoginSuccess(result_, false); 232 } 233 234 TEST_F(GoogleAuthenticatorTest, MountFailure) { 235 MockConsumer consumer; 236 EXPECT_CALL(consumer, OnLoginFailure(_)) 237 .Times(1) 238 .RetiresOnSaturation(); 239 240 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 241 .WillOnce(Return(false)) 242 .RetiresOnSaturation(); 243 244 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 245 PrepForLogin(auth.get()); 246 auth->OnLoginSuccess(result_, false); 247 } 248 249 TEST_F(GoogleAuthenticatorTest, PasswordChange) { 250 MockConsumer consumer; 251 EXPECT_CALL(consumer, OnPasswordChangeDetected(result_)) 252 .Times(1) 253 .RetiresOnSaturation(); 254 EXPECT_CALL(consumer, OnLoginSuccess(username_, password_, result_, false)) 255 .Times(1) 256 .RetiresOnSaturation(); 257 258 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 259 .WillOnce( 260 DoAll(SetArgumentPointee<2>( 261 chromeos::kCryptohomeMountErrorKeyFailure), 262 Return(false))) 263 .WillOnce(Return(true)) 264 .RetiresOnSaturation(); 265 266 EXPECT_CALL(*mock_library_, GetSystemSalt()) 267 .WillOnce(Return(chromeos::CryptohomeBlob(8, 'a'))) 268 .RetiresOnSaturation(); 269 EXPECT_CALL(*mock_library_, MigrateKey(username_, _, hash_ascii_)) 270 .WillOnce(Return(true)) 271 .RetiresOnSaturation(); 272 273 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 274 PrepForLogin(auth.get()); 275 auth->OnLoginSuccess(result_, false); 276 auth->RecoverEncryptedData("whaty", result_); 277 } 278 279 TEST_F(GoogleAuthenticatorTest, PasswordChangeWrongPassword) { 280 MockConsumer consumer; 281 EXPECT_CALL(consumer, OnPasswordChangeDetected(result_)) 282 .Times(2) 283 .RetiresOnSaturation(); 284 285 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 286 .WillOnce( 287 DoAll(SetArgumentPointee<2>( 288 chromeos::kCryptohomeMountErrorKeyFailure), 289 Return(false))) 290 .RetiresOnSaturation(); 291 EXPECT_CALL(*mock_library_, GetSystemSalt()) 292 .WillOnce(Return(chromeos::CryptohomeBlob(8, 'a'))) 293 .RetiresOnSaturation(); 294 EXPECT_CALL(*mock_library_, MigrateKey(username_, _, hash_ascii_)) 295 .WillOnce(Return(false)) 296 .RetiresOnSaturation(); 297 298 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 299 PrepForLogin(auth.get()); 300 auth->OnLoginSuccess(result_, false); 301 auth->RecoverEncryptedData("whaty", result_); 302 } 303 304 TEST_F(GoogleAuthenticatorTest, ForgetOldData) { 305 MockConsumer consumer; 306 EXPECT_CALL(consumer, OnPasswordChangeDetected(result_)) 307 .Times(1) 308 .RetiresOnSaturation(); 309 EXPECT_CALL(consumer, OnLoginSuccess(username_, password_, result_, false)) 310 .Times(1) 311 .RetiresOnSaturation(); 312 313 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 314 .WillOnce( 315 DoAll(SetArgumentPointee<2>( 316 chromeos::kCryptohomeMountErrorKeyFailure), 317 Return(false))) 318 .WillOnce(Return(true)) 319 .RetiresOnSaturation(); 320 321 EXPECT_CALL(*mock_library_, Remove(username_)) 322 .WillOnce(Return(true)) 323 .RetiresOnSaturation(); 324 325 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 326 PrepForLogin(auth.get()); 327 auth->OnLoginSuccess(result_, false); 328 auth->ResyncEncryptedData(result_); 329 } 330 331 TEST_F(GoogleAuthenticatorTest, LoginNetFailure) { 332 GoogleServiceAuthError error = 333 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET); 334 335 LoginFailure failure = 336 LoginFailure::FromNetworkAuthFailure(error); 337 338 MockConsumer consumer; 339 EXPECT_CALL(consumer, OnLoginFailure(failure)) 340 .Times(1) 341 .RetiresOnSaturation(); 342 EXPECT_CALL(*mock_library_, CheckKey(username_, hash_ascii_)) 343 .WillOnce(Return(false)) 344 .RetiresOnSaturation(); 345 346 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 347 PrepForLogin(auth.get()); 348 auth->OnClientLoginFailure(error); 349 message_loop_ui_.RunAllPending(); 350 } 351 352 TEST_F(GoogleAuthenticatorTest, LoginDenied) { 353 GoogleServiceAuthError client_error( 354 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 355 356 MockConsumer consumer; 357 EXPECT_CALL(consumer, OnLoginFailure(_)) 358 .Times(1) 359 .RetiresOnSaturation(); 360 361 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 362 PrepForFailedLogin(auth.get()); 363 EXPECT_CALL(*user_manager_.get(), IsKnownUser(username_)) 364 .WillOnce(Return(true)) 365 .RetiresOnSaturation(); 366 auth->OnClientLoginFailure(client_error); 367 message_loop_ui_.RunAllPending(); 368 } 369 370 TEST_F(GoogleAuthenticatorTest, LoginAccountDisabled) { 371 GoogleServiceAuthError client_error( 372 GoogleServiceAuthError::ACCOUNT_DISABLED); 373 374 MockConsumer consumer; 375 EXPECT_CALL(consumer, OnLoginFailure(_)) 376 .Times(1) 377 .RetiresOnSaturation(); 378 379 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 380 PrepForFailedLogin(auth.get()); 381 auth->OnClientLoginFailure(client_error); 382 message_loop_ui_.RunAllPending(); 383 } 384 385 TEST_F(GoogleAuthenticatorTest, LoginAccountDeleted) { 386 GoogleServiceAuthError client_error( 387 GoogleServiceAuthError::ACCOUNT_DELETED); 388 389 MockConsumer consumer; 390 EXPECT_CALL(consumer, OnLoginFailure(_)) 391 .Times(1) 392 .RetiresOnSaturation(); 393 394 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 395 PrepForFailedLogin(auth.get()); 396 auth->OnClientLoginFailure(client_error); 397 message_loop_ui_.RunAllPending(); 398 } 399 400 TEST_F(GoogleAuthenticatorTest, LoginServiceUnavailable) { 401 GoogleServiceAuthError client_error( 402 GoogleServiceAuthError::SERVICE_UNAVAILABLE); 403 404 MockConsumer consumer; 405 EXPECT_CALL(consumer, OnLoginFailure(_)) 406 .Times(1) 407 .RetiresOnSaturation(); 408 409 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 410 PrepForFailedLogin(auth.get()); 411 auth->OnClientLoginFailure(client_error); 412 message_loop_ui_.RunAllPending(); 413 } 414 415 TEST_F(GoogleAuthenticatorTest, CaptchaErrorOutputted) { 416 GoogleServiceAuthError auth_error = 417 GoogleServiceAuthError::FromCaptchaChallenge( 418 "CCTOKEN", 419 GURL("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"), 420 GURL("http://www.google.com/login/captcha")); 421 422 LoginFailure failure = LoginFailure::FromNetworkAuthFailure(auth_error); 423 424 MockConsumer consumer; 425 EXPECT_CALL(consumer, OnLoginFailure(failure)) 426 .Times(1) 427 .RetiresOnSaturation(); 428 429 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 430 PrepForFailedLogin(auth.get()); 431 auth->OnClientLoginFailure(auth_error); 432 message_loop_ui_.RunAllPending(); 433 } 434 435 TEST_F(GoogleAuthenticatorTest, OfflineLogin) { 436 GoogleServiceAuthError auth_error( 437 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET)); 438 439 MockConsumer consumer; 440 EXPECT_CALL(consumer, OnLoginSuccess(username_, password_, result_, false)) 441 .Times(1) 442 .RetiresOnSaturation(); 443 EXPECT_CALL(*mock_library_, CheckKey(username_, hash_ascii_)) 444 .WillOnce(Return(true)) 445 .RetiresOnSaturation(); 446 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 447 .WillOnce(Return(true)) 448 .RetiresOnSaturation(); 449 450 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 451 PrepForLogin(auth.get()); 452 auth->OnClientLoginFailure(auth_error); 453 message_loop_ui_.RunAllPending(); 454 } 455 456 TEST_F(GoogleAuthenticatorTest, OnlineLogin) { 457 MockConsumer consumer; 458 EXPECT_CALL(consumer, OnLoginSuccess(username_, password_, result_, false)) 459 .Times(1) 460 .RetiresOnSaturation(); 461 EXPECT_CALL(*mock_library_, Mount(username_, hash_ascii_, _)) 462 .WillOnce(Return(true)) 463 .RetiresOnSaturation(); 464 465 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 466 PrepForLogin(auth.get()); 467 EXPECT_CALL(*user_manager_.get(), IsKnownUser(username_)) 468 .WillOnce(Return(true)) 469 .RetiresOnSaturation(); 470 auth->OnClientLoginSuccess(result_); 471 message_loop_ui_.RunAllPending(); 472 } 473 474 TEST_F(GoogleAuthenticatorTest, CheckLocalaccount) { 475 GURL source(AuthResponseHandler::kTokenAuthUrl); 476 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 477 478 MockConsumer consumer; 479 EXPECT_CALL(consumer, OnLoginSuccess(username_, std::string(), _, false)) 480 .Times(1) 481 .RetiresOnSaturation(); 482 EXPECT_CALL(*mock_library_, MountForBwsi(_)) 483 .WillOnce(Return(true)) 484 .RetiresOnSaturation(); 485 486 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 487 PrepForLogin(auth.get()); 488 auth->SetLocalaccount(username_); 489 490 auth->CheckLocalaccount(LoginFailure(LoginFailure::LOGIN_TIMED_OUT)); 491 } 492 493 TEST_F(GoogleAuthenticatorTest, LocalaccountLogin) { 494 // This test checks the logic that governs asynchronously reading the 495 // localaccount name off disk and trying to authenticate against it 496 // simultaneously. 497 MockConsumer consumer; 498 EXPECT_CALL(consumer, OnLoginSuccess(username_, std::string(), _, false)) 499 .WillOnce(Invoke(MockConsumer::OnSuccessQuit)) 500 .RetiresOnSaturation(); 501 EXPECT_CALL(*mock_library_, MountForBwsi(_)) 502 .WillOnce(Return(true)) 503 .RetiresOnSaturation(); 504 // Enable the test to terminate (and fail), even if the login fails. 505 ON_CALL(consumer, OnLoginFailure(_)) 506 .WillByDefault(Invoke(MockConsumer::OnFailQuitAndFail)); 507 508 // Manually prep for login, so that localaccount isn't set for us. 509 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 510 auth->set_password_hash(hash_ascii_); 511 auth->set_username(username_); 512 513 // First, force a check of username_ against the localaccount -- which we 514 // haven't yet gotten off disk. 515 BrowserThread::PostTask( 516 BrowserThread::UI, FROM_HERE, 517 NewRunnableMethod(auth.get(), 518 &GoogleAuthenticator::CheckLocalaccount, 519 LoginFailure(LoginFailure::LOGIN_TIMED_OUT))); 520 message_loop_ui_.RunAllPending(); 521 // The foregoing has now rescheduled itself in a few ms because we don't 522 // yet have the localaccount loaded off disk. 523 524 // Now, cause the FILE thread to go load the localaccount off disk. 525 FilePath tmp_file_path = FakeLocalaccountFile(username_); 526 ReadLocalaccountFile(auth.get(), tmp_file_path.BaseName().value()); 527 528 // Run remaining events, until OnLoginSuccess or OnLoginFailure is called. 529 message_loop_ui_.Run(); 530 531 // Cleanup. 532 Delete(tmp_file_path, false); 533 } 534 535 TEST_F(GoogleAuthenticatorTest, FullLogin) { 536 chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_)); 537 538 MockConsumer consumer; 539 EXPECT_CALL(consumer, OnLoginSuccess(username_, 540 password_, 541 Eq(result_), 542 false)) 543 .Times(1) 544 .RetiresOnSaturation(); 545 EXPECT_CALL(*mock_library_, Mount(username_, _, _)) 546 .WillOnce(Return(true)) 547 .RetiresOnSaturation(); 548 549 EXPECT_CALL(*mock_library_, GetSystemSalt()) 550 .WillOnce(Return(salt_v)) 551 .RetiresOnSaturation(); 552 553 TestingProfile profile; 554 555 MockFactory<MockFetcher> factory; 556 URLFetcher::set_factory(&factory); 557 558 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 559 EXPECT_CALL(*user_manager_.get(), IsKnownUser(username_)) 560 .WillOnce(Return(true)) 561 .RetiresOnSaturation(); 562 auth->set_user_manager(user_manager_.get()); 563 auth->AuthenticateToLogin( 564 &profile, username_, password_, std::string(), std::string()); 565 566 URLFetcher::set_factory(NULL); 567 message_loop_ui_.RunAllPending(); 568 } 569 570 TEST_F(GoogleAuthenticatorTest, FullHostedLoginFailure) { 571 chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_)); 572 573 LoginFailure failure_details = 574 LoginFailure::FromNetworkAuthFailure( 575 GoogleServiceAuthError( 576 GoogleServiceAuthError::HOSTED_NOT_ALLOWED)); 577 578 MockConsumer consumer; 579 EXPECT_CALL(consumer, OnLoginFailure(failure_details)) 580 .WillOnce(Invoke(MockConsumer::OnFailQuit)) 581 .RetiresOnSaturation(); 582 // A failure case, but we still want the test to finish gracefully. 583 ON_CALL(consumer, OnLoginSuccess(username_, password_, _, _)) 584 .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); 585 586 EXPECT_CALL(*mock_library_, GetSystemSalt()) 587 .WillOnce(Return(salt_v)) 588 .RetiresOnSaturation(); 589 590 TestingProfile profile; 591 592 MockFactory<HostedFetcher> factory_invalid; 593 URLFetcher::set_factory(&factory_invalid); 594 595 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 596 auth->set_user_manager(user_manager_.get()); 597 EXPECT_CALL(*user_manager_.get(), IsKnownUser(username_)) 598 .WillOnce(Return(false)) 599 .WillOnce(Return(false)) 600 .RetiresOnSaturation(); 601 auth->AuthenticateToLogin( 602 &profile, username_, hash_ascii_, std::string(), std::string()); 603 604 // For when |auth| tries to load the localaccount file. 605 BrowserThread file_thread(BrowserThread::FILE); 606 file_thread.Start(); 607 608 // Run the UI thread until we exit it gracefully. 609 message_loop_ui_.Run(); 610 URLFetcher::set_factory(NULL); 611 } 612 613 TEST_F(GoogleAuthenticatorTest, CancelLogin) { 614 chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_)); 615 616 MockConsumer consumer; 617 // The expected case. 618 EXPECT_CALL(consumer, OnLoginFailure(_)) 619 .WillOnce(Invoke(MockConsumer::OnFailQuit)) 620 .RetiresOnSaturation(); 621 622 // A failure case, but we still want the test to finish gracefully. 623 ON_CALL(consumer, OnLoginSuccess(username_, password_, _, _)) 624 .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); 625 626 // Stuff we expect to happen along the way. 627 EXPECT_CALL(*mock_library_, GetSystemSalt()) 628 .WillOnce(Return(salt_v)) 629 .RetiresOnSaturation(); 630 EXPECT_CALL(*mock_library_, CheckKey(username_, _)) 631 .WillOnce(Return(false)) 632 .RetiresOnSaturation(); 633 634 TestingProfile profile; 635 636 // This is how we inject fake URLFetcher objects, with a factory. 637 // This factory creates fake URLFetchers that Start() a fake fetch attempt 638 // and then come back on the UI thread after a small delay. They expect to 639 // be canceled before they come back, and the test will fail if they are not. 640 MockFactory<ExpectCanceledFetcher> factory; 641 URLFetcher::set_factory(&factory); 642 643 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 644 // For when |auth| tries to load the localaccount file. 645 BrowserThread file_thread(BrowserThread::FILE); 646 file_thread.Start(); 647 648 // Start an authentication attempt, which will kick off a URL "fetch" that 649 // we expect to cancel before it completes. 650 auth->AuthenticateToLogin( 651 &profile, username_, hash_ascii_, std::string(), std::string()); 652 653 // Post a task to cancel the login attempt. 654 CancelLogin(auth.get()); 655 656 URLFetcher::set_factory(NULL); 657 658 // Run the UI thread until we exit it gracefully. 659 message_loop_ui_.Run(); 660 } 661 662 TEST_F(GoogleAuthenticatorTest, CancelLoginAlreadyGotLocalaccount) { 663 chromeos::CryptohomeBlob salt_v(fake_hash_, fake_hash_ + sizeof(fake_hash_)); 664 665 MockConsumer consumer; 666 // The expected case. 667 EXPECT_CALL(consumer, OnLoginFailure(_)) 668 .WillOnce(Invoke(MockConsumer::OnFailQuit)) 669 .RetiresOnSaturation(); 670 671 // A failure case, but we still want the test to finish gracefully. 672 ON_CALL(consumer, OnLoginSuccess(username_, password_, _, _)) 673 .WillByDefault(Invoke(MockConsumer::OnSuccessQuitAndFail)); 674 675 // Stuff we expect to happen along the way. 676 EXPECT_CALL(*mock_library_, GetSystemSalt()) 677 .WillOnce(Return(salt_v)) 678 .RetiresOnSaturation(); 679 EXPECT_CALL(*mock_library_, CheckKey(username_, _)) 680 .WillOnce(Return(false)) 681 .RetiresOnSaturation(); 682 683 TestingProfile profile; 684 685 // This is how we inject fake URLFetcher objects, with a factory. 686 // This factory creates fake URLFetchers that Start() a fake fetch attempt 687 // and then come back on the UI thread after a small delay. They expect to 688 // be canceled before they come back, and the test will fail if they are not. 689 MockFactory<ExpectCanceledFetcher> factory; 690 URLFetcher::set_factory(&factory); 691 692 scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); 693 // This time, instead of allowing |auth| to go get the localaccount file 694 // itself, we simulate the case where the file is already loaded, which 695 // happens when this isn't the first login since chrome started. 696 ReadLocalaccountFile(auth.get(), ""); 697 698 // Start an authentication attempt, which will kick off a URL "fetch" that 699 // we expect to cancel before it completes. 700 auth->AuthenticateToLogin( 701 &profile, username_, hash_ascii_, std::string(), std::string()); 702 703 // Post a task to cancel the login attempt. 704 CancelLogin(auth.get()); 705 706 URLFetcher::set_factory(NULL); 707 708 // Run the UI thread until we exit it gracefully. 709 message_loop_ui_.Run(); 710 } 711 712 } // namespace chromeos 713