Home | History | Annotate | Download | only in login
      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 <string>
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/run_loop.h"
     10 #include "chrome/browser/chromeos/cros/network_library.h"
     11 #include "chrome/browser/chromeos/login/auth_attempt_state.h"
     12 #include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h"
     13 #include "chrome/browser/chromeos/login/mock_url_fetchers.h"
     14 #include "chrome/browser/chromeos/login/online_attempt.h"
     15 #include "chrome/browser/chromeos/login/test_attempt_state.h"
     16 #include "chrome/browser/chromeos/login/user.h"
     17 #include "chrome/test/base/testing_profile.h"
     18 #include "content/public/browser/browser_thread.h"
     19 #include "content/public/test/test_browser_thread_bundle.h"
     20 #include "google_apis/gaia/gaia_auth_consumer.h"
     21 #include "google_apis/gaia/mock_url_fetcher_factory.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 #include "url/gurl.h"
     25 
     26 using ::testing::AnyNumber;
     27 using ::testing::Invoke;
     28 using ::testing::Return;
     29 using ::testing::_;
     30 using content::BrowserThread;
     31 
     32 namespace chromeos {
     33 
     34 class OnlineAttemptTest : public testing::Test {
     35  public:
     36   OnlineAttemptTest()
     37       : state_(UserContext(), "", "", "", User::USER_TYPE_REGULAR, false),
     38         attempt_(new OnlineAttempt(&state_, &resolver_)) {
     39   }
     40 
     41   void RunFailureTest(const GoogleServiceAuthError& error) {
     42     EXPECT_CALL(resolver_, Resolve())
     43         .Times(1)
     44         .RetiresOnSaturation();
     45 
     46     BrowserThread::PostTask(
     47         BrowserThread::UI, FROM_HERE,
     48         base::Bind(&OnlineAttempt::OnClientLoginFailure,
     49                    attempt_->weak_factory_.GetWeakPtr(),
     50                    error));
     51     // Force UI thread to finish tasks so I can verify |state_|.
     52     base::RunLoop().RunUntilIdle();
     53     EXPECT_TRUE(error == state_.online_outcome().error());
     54   }
     55 
     56   void CancelLogin(OnlineAttempt* auth) {
     57     BrowserThread::PostTask(
     58         BrowserThread::UI, FROM_HERE,
     59         base::Bind(&OnlineAttempt::CancelClientLogin,
     60                    auth->weak_factory_.GetWeakPtr()));
     61   }
     62 
     63   content::TestBrowserThreadBundle thread_bundle_;
     64   TestAttemptState state_;
     65   MockAuthAttemptStateResolver resolver_;
     66   scoped_ptr<OnlineAttempt> attempt_;
     67 
     68   // Initializes / shuts down a stub NetworkLibrary.
     69   ScopedStubNetworkLibraryEnabler stub_network_library_enabler_;
     70 };
     71 
     72 TEST_F(OnlineAttemptTest, LoginSuccess) {
     73   EXPECT_CALL(resolver_, Resolve())
     74       .Times(1)
     75       .RetiresOnSaturation();
     76 
     77   BrowserThread::PostTask(
     78       BrowserThread::UI, FROM_HERE,
     79       base::Bind(&OnlineAttempt::OnClientLoginSuccess,
     80                  attempt_->weak_factory_.GetWeakPtr(),
     81                  GaiaAuthConsumer::ClientLoginResult()));
     82   // Force UI thread to finish tasks so I can verify |state_|.
     83   base::RunLoop().RunUntilIdle();
     84 }
     85 
     86 TEST_F(OnlineAttemptTest, LoginCancelRetry) {
     87   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
     88   TestingProfile profile;
     89 
     90   base::RunLoop run_loop;
     91   EXPECT_CALL(resolver_, Resolve())
     92       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
     93       .RetiresOnSaturation();
     94 
     95   // This is how we inject fake URLFetcher objects, with a factory.
     96   // This factory creates fake URLFetchers that Start() a fake fetch attempt
     97   // and then come back on the UI thread saying they've been canceled.
     98   MockURLFetcherFactory<GotCanceledFetcher> factory;
     99 
    100   attempt_->Initiate(&profile);
    101 
    102   run_loop.Run();
    103 
    104   EXPECT_TRUE(error == state_.online_outcome().error());
    105   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
    106             state_.online_outcome().reason());
    107 }
    108 
    109 TEST_F(OnlineAttemptTest, LoginTimeout) {
    110   LoginFailure error(LoginFailure::LOGIN_TIMED_OUT);
    111   TestingProfile profile;
    112 
    113   base::RunLoop run_loop;
    114   EXPECT_CALL(resolver_, Resolve())
    115       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
    116       .RetiresOnSaturation();
    117 
    118   // This is how we inject fake URLFetcher objects, with a factory.
    119   // This factory creates fake URLFetchers that Start() a fake fetch attempt
    120   // and then come back on the UI thread saying they've been canceled.
    121   MockURLFetcherFactory<ExpectCanceledFetcher> factory;
    122 
    123   attempt_->Initiate(&profile);
    124 
    125   // Post a task to cancel the login attempt.
    126   CancelLogin(attempt_.get());
    127 
    128   run_loop.Run();
    129 
    130   EXPECT_EQ(LoginFailure::LOGIN_TIMED_OUT, state_.online_outcome().reason());
    131 }
    132 
    133 TEST_F(OnlineAttemptTest, HostedLoginRejected) {
    134   LoginFailure error(
    135       LoginFailure::FromNetworkAuthFailure(
    136           GoogleServiceAuthError(
    137               GoogleServiceAuthError::HOSTED_NOT_ALLOWED)));
    138   TestingProfile profile;
    139 
    140   base::RunLoop run_loop;
    141   EXPECT_CALL(resolver_, Resolve())
    142       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
    143       .RetiresOnSaturation();
    144 
    145   // This is how we inject fake URLFetcher objects, with a factory.
    146   MockURLFetcherFactory<HostedFetcher> factory;
    147 
    148   TestAttemptState local_state(UserContext(), "", "", "",
    149                                User::USER_TYPE_REGULAR, true);
    150   attempt_.reset(new OnlineAttempt(&local_state, &resolver_));
    151   attempt_->Initiate(&profile);
    152 
    153   run_loop.Run();
    154 
    155   EXPECT_EQ(error, local_state.online_outcome());
    156   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
    157             local_state.online_outcome().reason());
    158 }
    159 
    160 TEST_F(OnlineAttemptTest, FullLogin) {
    161   TestingProfile profile;
    162 
    163   base::RunLoop run_loop;
    164   EXPECT_CALL(resolver_, Resolve())
    165       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
    166       .RetiresOnSaturation();
    167 
    168   // This is how we inject fake URLFetcher objects, with a factory.
    169   MockURLFetcherFactory<SuccessFetcher> factory;
    170 
    171   TestAttemptState local_state(UserContext(), "", "", "",
    172                                User::USER_TYPE_REGULAR, true);
    173   attempt_.reset(new OnlineAttempt(&local_state, &resolver_));
    174   attempt_->Initiate(&profile);
    175 
    176   run_loop.Run();
    177 
    178   EXPECT_EQ(LoginFailure::LoginFailureNone(), local_state.online_outcome());
    179 }
    180 
    181 TEST_F(OnlineAttemptTest, LoginNetFailure) {
    182   RunFailureTest(
    183       GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET));
    184 }
    185 
    186 TEST_F(OnlineAttemptTest, LoginDenied) {
    187   RunFailureTest(
    188       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
    189 }
    190 
    191 TEST_F(OnlineAttemptTest, LoginAccountDisabled) {
    192   RunFailureTest(
    193       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
    194 }
    195 
    196 TEST_F(OnlineAttemptTest, LoginAccountDeleted) {
    197   RunFailureTest(
    198       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED));
    199 }
    200 
    201 TEST_F(OnlineAttemptTest, LoginServiceUnavailable) {
    202   RunFailureTest(
    203       GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
    204 }
    205 
    206 TEST_F(OnlineAttemptTest, CaptchaErrorOutputted) {
    207   GoogleServiceAuthError auth_error =
    208       GoogleServiceAuthError::FromClientLoginCaptchaChallenge(
    209           "CCTOKEN",
    210           GURL("http://accounts.google.com/Captcha?ctoken=CCTOKEN"),
    211           GURL("http://www.google.com/login/captcha"));
    212   RunFailureTest(auth_error);
    213 }
    214 
    215 TEST_F(OnlineAttemptTest, TwoFactorSuccess) {
    216   EXPECT_CALL(resolver_, Resolve())
    217       .Times(1)
    218       .RetiresOnSaturation();
    219   GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
    220   BrowserThread::PostTask(
    221       BrowserThread::UI, FROM_HERE,
    222       base::Bind(&OnlineAttempt::OnClientLoginFailure,
    223                  attempt_->weak_factory_.GetWeakPtr(),
    224                  error));
    225 
    226   // Force UI thread to finish tasks so I can verify |state_|.
    227   base::RunLoop().RunUntilIdle();
    228   EXPECT_TRUE(GoogleServiceAuthError::AuthErrorNone() ==
    229               state_.online_outcome().error());
    230 }
    231 
    232 }  // namespace chromeos
    233