google_authenticator_unittest.cc revision dc0f95d653279beabeb9817299e2902918ba123e
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/message_loop.h"
13#include "base/path_service.h"
14#include "base/scoped_ptr.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
37using namespace file_util;
38using ::testing::AnyNumber;
39using ::testing::DoAll;
40using ::testing::Eq;
41using ::testing::Invoke;
42using ::testing::Return;
43using ::testing::SetArgumentPointee;
44using ::testing::_;
45
46namespace chromeos {
47
48class 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@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, reinterpret_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, reinterpret_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
170TEST_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
188TEST_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
197TEST_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
208TEST_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
217TEST_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
234TEST_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
249TEST_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
279TEST_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
304TEST_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
331TEST_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
352TEST_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
370TEST_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
385TEST_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
400TEST_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
415TEST_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
435TEST_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
456TEST_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
474TEST_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
493TEST_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
535TEST_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
570TEST_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
613TEST_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
662TEST_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