• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GoogleAuthenticatorTest()50   GoogleAuthenticatorTest()
51       : message_loop_ui_(MessageLoop::TYPE_UI),
52         ui_thread_(BrowserThread::UI, &message_loop_ui_),
53         username_("me@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   }
~GoogleAuthenticatorTest()67   ~GoogleAuthenticatorTest() {}
68 
SetUp()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.
TearDown()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 
PopulateTempFile(const char * data,int data_len)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 
FakeLocalaccountFile(const std::string & ascii)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 
ReadLocalaccountFile(GoogleAuthenticator * auth,const std::string & filename)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 
PrepForLogin(GoogleAuthenticator * auth)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 
PrepForFailedLogin(GoogleAuthenticator * auth)139   void PrepForFailedLogin(GoogleAuthenticator* auth) {
140     PrepForLogin(auth);
141     auth->set_hosted_policy(GaiaAuthFetcher::HostedAccountsAllowed);
142   }
143 
CancelLogin(GoogleAuthenticator * auth)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 
TEST_F(GoogleAuthenticatorTest,SaltToAscii)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 
TEST_F(GoogleAuthenticatorTest,ReadLocalaccount)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 
TEST_F(GoogleAuthenticatorTest,ReadLocalaccountTrailingWS)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 
TEST_F(GoogleAuthenticatorTest,ReadNoLocalaccount)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 
TEST_F(GoogleAuthenticatorTest,OnLoginSuccess)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 
TEST_F(GoogleAuthenticatorTest,MountFailure)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 
TEST_F(GoogleAuthenticatorTest,PasswordChange)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 
TEST_F(GoogleAuthenticatorTest,PasswordChangeWrongPassword)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 
TEST_F(GoogleAuthenticatorTest,ForgetOldData)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 
TEST_F(GoogleAuthenticatorTest,LoginNetFailure)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 
TEST_F(GoogleAuthenticatorTest,LoginDenied)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 
TEST_F(GoogleAuthenticatorTest,LoginAccountDisabled)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 
TEST_F(GoogleAuthenticatorTest,LoginAccountDeleted)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 
TEST_F(GoogleAuthenticatorTest,LoginServiceUnavailable)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 
TEST_F(GoogleAuthenticatorTest,CaptchaErrorOutputted)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 
TEST_F(GoogleAuthenticatorTest,OfflineLogin)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 
TEST_F(GoogleAuthenticatorTest,OnlineLogin)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 
TEST_F(GoogleAuthenticatorTest,CheckLocalaccount)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 
TEST_F(GoogleAuthenticatorTest,LocalaccountLogin)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 
TEST_F(GoogleAuthenticatorTest,FullLogin)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 
TEST_F(GoogleAuthenticatorTest,FullHostedLoginFailure)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 
TEST_F(GoogleAuthenticatorTest,CancelLogin)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 
TEST_F(GoogleAuthenticatorTest,CancelLoginAlreadyGotLocalaccount)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