diff options
author | chron@chromium.org <chron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-19 18:44:19 +0000 |
---|---|---|
committer | chron@chromium.org <chron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-19 18:44:19 +0000 |
commit | 99074c5d22fac9f990aebe5055ea0bf68aef7ad7 (patch) | |
tree | 0ec4b33ed7b0758221befa68e1bba2c6fec0010f /chrome | |
parent | 2313f55f13ee9f5d45f85a22f9e0459990aedc5a (diff) | |
download | chromium_src-99074c5d22fac9f990aebe5055ea0bf68aef7ad7.zip chromium_src-99074c5d22fac9f990aebe5055ea0bf68aef7ad7.tar.gz chromium_src-99074c5d22fac9f990aebe5055ea0bf68aef7ad7.tar.bz2 |
Switch to GoogleServiceAuthError struct instead of GaiaAuthError.
Remove CAPTCHA code from existing user controller and plumb into google
authenticator2.
TEST=Install ChromeOS build. Hit Captcha. Enter captcha.
BUG=50408
Review URL: http://codereview.chromium.org/3134009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56724 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
35 files changed, 409 insertions, 213 deletions
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 381f7be..08dbb7e 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -29,7 +29,6 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/browser/defaults.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/memory_details.h" #include "chrome/browser/metrics/histogram_synchronizer.h" #include "chrome/browser/net/predictor_api.h" @@ -44,6 +43,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/jstemplate_builder.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index fb7c6c3..dad1cec 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -740,8 +740,8 @@ class StubLogin : public chromeos::LoginStatusConsumer { std::string()); } - void OnLoginFailure(const std::string& error) { - LOG(ERROR) << "Login Failure: " << error; + void OnLoginFailure(const chromeos::LoginFailure& error) { + LOG(ERROR) << "Login Failure: " << error.GetErrorString(); delete this; } diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h index 861b1ce..823eee4 100644 --- a/chrome/browser/chromeos/login/authenticator.h +++ b/chrome/browser/chromeos/login/authenticator.h @@ -54,7 +54,7 @@ class Authenticator : public base::RefCountedThreadSafe<Authenticator> { // and also call back to the login UI. virtual void OnLoginSuccess( const GaiaAuthConsumer::ClientLoginResult& credentials) = 0; - virtual void OnLoginFailure(const std::string& data) = 0; + virtual void OnLoginFailure(const LoginFailure& error) = 0; // Call these methods on the UI thread. // If a password logs the user in online, but cannot be used to diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index 414e6b2..1395e1b 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc @@ -47,16 +47,6 @@ const size_t kMaxUsers = 6; // Used to indicate no user has been selected. const size_t kNotSelected = -1; -// ClientLogin response parameters. -const char kError[] = "Error="; -const char kCaptchaError[] = "CaptchaRequired"; -const char kCaptchaUrlParam[] = "CaptchaUrl="; -const char kCaptchaTokenParam[] = "CaptchaToken="; -const char kParamSuffix[] = "\n"; - -// URL prefix for CAPTCHA image. -const char kCaptchaUrlPrefix[] = "http://www.google.com/accounts/"; - // Checks if display names are unique. If there are duplicates, enables // tooltips with full emails to let users distinguish their accounts. // Otherwise, disables the tooltips. @@ -290,10 +280,12 @@ void ExistingUserController::SelectUser(int index) { } } -void ExistingUserController::OnLoginFailure(const std::string& error) { +void ExistingUserController::OnLoginFailure(const LoginFailure& failure) { LOG(INFO) << "OnLoginFailure"; ClearCaptchaState(); + std::string error = failure.GetErrorString(); + // Check networking after trying to login in case user is // cached locally or the local admin account. NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary(); @@ -302,28 +294,25 @@ void ExistingUserController::OnLoginFailure(const std::string& error) { } else if (!network->Connected()) { ShowError(IDS_LOGIN_ERROR_OFFLINE_FAILED_NETWORK_NOT_CONNECTED, error); } else { - std::string error_code = LoginUtils::ExtractClientLoginParam(error, - kError, - kParamSuffix); - std::string captcha_url; - if (error_code == kCaptchaError) - captcha_url = LoginUtils::ExtractClientLoginParam(error, - kCaptchaUrlParam, - kParamSuffix); - if (captcha_url.empty()) { - ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error); + + if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED && + failure.error().state() == GoogleServiceAuthError::CAPTCHA_REQUIRED) { + if (!failure.error().captcha().image_url.is_empty()) { + // Save token for next login retry. + login_token_ = failure.error().captcha().token; + CaptchaView* view = + new CaptchaView(failure.error().captcha().image_url); + view->set_delegate(this); + views::Window* window = views::Window::CreateChromeWindow( + GetNativeWindow(), gfx::Rect(), view); + window->SetIsAlwaysOnTop(true); + window->Show(); + } else { + LOG(WARNING) << "No captcha image url was found?"; + ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error); + } } else { - // Save token for next login retry. - login_token_ = LoginUtils::ExtractClientLoginParam(error, - kCaptchaTokenParam, - kParamSuffix); - CaptchaView* view = - new CaptchaView(GURL(kCaptchaUrlPrefix + captcha_url)); - view->set_delegate(this); - views::Window* window = views::Window::CreateChromeWindow( - GetNativeWindow(), gfx::Rect(), view); - window->SetIsAlwaysOnTop(true); - window->Show(); + ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error); } } diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h index ae3429c..62ac125 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.h +++ b/chrome/browser/chromeos/login/existing_user_controller.h @@ -86,7 +86,7 @@ class ExistingUserController : public WmMessageListener::Observer, virtual void SelectUser(int index); // LoginStatusConsumer: - virtual void OnLoginFailure(const std::string& error); + virtual void OnLoginFailure(const LoginFailure& error); virtual void OnLoginSuccess(const std::string& username, const GaiaAuthConsumer::ClientLoginResult& credentials); virtual void OnOffTheRecordLoginSuccess(); diff --git a/chrome/browser/chromeos/login/google_authenticator.cc b/chrome/browser/chromeos/login/google_authenticator.cc index bd4c027..214c12c 100644 --- a/chrome/browser/chromeos/login/google_authenticator.cc +++ b/chrome/browser/chromeos/login/google_authenticator.cc @@ -73,7 +73,7 @@ void GoogleAuthenticator::CancelClientLogin() { &GoogleAuthenticator::LoadLocalaccount, std::string(kLocalaccountFile))); - CheckOffline("Login has timed out; please try again!"); + CheckOffline(LoginFailure(LoginFailure::LOGIN_TIMED_OUT)); } } @@ -148,7 +148,7 @@ bool GoogleAuthenticator::AuthenticateToUnlock(const std::string& username, ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, NewRunnableMethod(this, &GoogleAuthenticator::CheckOffline, - std::string("unlock failed"))); + LoginFailure(LoginFailure::UNLOCK_FAILED))); } return true; } @@ -164,8 +164,9 @@ void GoogleAuthenticator::LoginOffTheRecord() { Details<AuthenticationNotificationDetails>(&details)); consumer_->OnOffTheRecordLoginSuccess(); } else { - LOG(ERROR) << "Could not mount tmpfs cryptohome: " << mount_error; - consumer_->OnLoginFailure("Could not mount tmpfs cryptohome"); + LOG(ERROR) << "Could not mount tmpfs: " << mount_error; + consumer_->OnLoginFailure( + LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); } } @@ -183,9 +184,9 @@ void GoogleAuthenticator::OnClientLoginSuccess( } void GoogleAuthenticator::OnClientLoginFailure( - const GaiaAuthConsumer::GaiaAuthError& error) { + const GoogleServiceAuthError& error) { - if (error.code == GaiaAuthConsumer::REQUEST_CANCELED) { + if (error.state() == GoogleServiceAuthError::REQUEST_CANCELED) { if (try_again_) { try_again_ = false; LOG(ERROR) << "Login attempt canceled!?!? Trying again."; @@ -197,7 +198,7 @@ void GoogleAuthenticator::OnClientLoginFailure( ClearClientLoginAttempt(); - if (error.code == GaiaAuthConsumer::TWO_FACTOR) { + if (error.state() == GoogleServiceAuthError::TWO_FACTOR) { LOG(WARNING) << "Two factor authenticated. Sync will not work."; OnClientLoginSuccess(GaiaAuthConsumer::ClientLoginResult()); return; @@ -209,12 +210,14 @@ void GoogleAuthenticator::OnClientLoginFailure( &GoogleAuthenticator::LoadLocalaccount, std::string(kLocalaccountFile))); - if (error.code == GaiaAuthConsumer::NETWORK_ERROR) { + LoginFailure failure_details = LoginFailure::FromNetworkAuthFailure(error); + + if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED) { // The fetch failed for network reasons, try offline login. ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, NewRunnableMethod(this, &GoogleAuthenticator::CheckOffline, - net::ErrorToString(error.network_error))); + failure_details)); return; } @@ -223,7 +226,7 @@ void GoogleAuthenticator::OnClientLoginFailure( ChromeThread::UI, FROM_HERE, NewRunnableMethod(this, &GoogleAuthenticator::CheckLocalaccount, - error.data)); + failure_details)); } void GoogleAuthenticator::OnLoginSuccess( @@ -246,11 +249,11 @@ void GoogleAuthenticator::OnLoginSuccess( mount_error == chromeos::kCryptohomeMountErrorKeyFailure) { consumer_->OnPasswordChangeDetected(credentials); } else { - OnLoginFailure("Could not mount cryptohome"); + OnLoginFailure(LoginFailure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME)); } } -void GoogleAuthenticator::CheckOffline(const std::string& error) { +void GoogleAuthenticator::CheckOffline(const LoginFailure& error) { LOG(INFO) << "Attempting offline login"; if (CrosLibrary::Get()->GetCryptohomeLibrary()->CheckKey( username_.c_str(), @@ -264,7 +267,7 @@ void GoogleAuthenticator::CheckOffline(const std::string& error) { } } -void GoogleAuthenticator::CheckLocalaccount(const std::string& error) { +void GoogleAuthenticator::CheckLocalaccount(const LoginFailure& error) { { AutoLock for_this_block(localaccount_lock_); LOG(INFO) << "Checking localaccount"; @@ -280,25 +283,30 @@ void GoogleAuthenticator::CheckLocalaccount(const std::string& error) { } } int mount_error = chromeos::kCryptohomeMountErrorNone; - if (!localaccount_.empty() && localaccount_ == username_ && - CrosLibrary::Get()->GetCryptohomeLibrary()->MountForBwsi(&mount_error)) { - LOG(WARNING) << "Logging in with localaccount: " << localaccount_; - consumer_->OnLoginSuccess(username_, GaiaAuthConsumer::ClientLoginResult()); + if (!localaccount_.empty() && localaccount_ == username_) { + if (CrosLibrary::Get()->GetCryptohomeLibrary()->MountForBwsi( + &mount_error)) { + LOG(WARNING) << "Logging in with localaccount: " << localaccount_; + consumer_->OnLoginSuccess(username_, + GaiaAuthConsumer::ClientLoginResult()); + } else { + LOG(ERROR) << "Could not mount tmpfs for local account: " << mount_error; + OnLoginFailure( + LoginFailure(LoginFailure::COULD_NOT_MOUNT_TMPFS)); + } } else { OnLoginFailure(error); } } -void GoogleAuthenticator::OnLoginFailure(const std::string& error) { +void GoogleAuthenticator::OnLoginFailure(const LoginFailure& error) { // Send notification of failure AuthenticationNotificationDetails details(false); NotificationService::current()->Notify( NotificationType::LOGIN_AUTHENTICATION, NotificationService::AllSources(), Details<AuthenticationNotificationDetails>(&details)); - LOG(WARNING) << "Login failed: " << error; - // TODO(cmasone): what can we do to expose these OS/server-side error strings - // in an internationalizable way? + LOG(WARNING) << "Login failed: " << error.GetErrorString(); consumer_->OnLoginFailure(error); } @@ -322,7 +330,7 @@ void GoogleAuthenticator::ResyncEncryptedData( if (CrosLibrary::Get()->GetCryptohomeLibrary()->Remove(username_)) { OnLoginSuccess(credentials); } else { - OnLoginFailure("Could not destroy your old data!"); + OnLoginFailure(LoginFailure(LoginFailure::DATA_REMOVAL_FAILED)); } } diff --git a/chrome/browser/chromeos/login/google_authenticator.h b/chrome/browser/chromeos/login/google_authenticator.h index 8ddc137..bc43485 100644 --- a/chrome/browser/chromeos/login/google_authenticator.h +++ b/chrome/browser/chromeos/login/google_authenticator.h @@ -22,6 +22,8 @@ class Lock; class Profile; class GaiaAuthenticator2; +class GoogleServiceAuthError; +class LoginFailure; namespace chromeos { @@ -72,9 +74,9 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { // These methods must be called on the UI thread, as they make DBus calls // and also call back to the login UI. void OnLoginSuccess(const GaiaAuthConsumer::ClientLoginResult& credentials); - void CheckOffline(const std::string& error); - void CheckLocalaccount(const std::string& error); - void OnLoginFailure(const std::string& error); + void CheckOffline(const LoginFailure& error); + void CheckLocalaccount(const LoginFailure& error); + void OnLoginFailure(const LoginFailure& error); // Call these methods on the UI thread. void RecoverEncryptedData( @@ -91,7 +93,7 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { // Callbacks from GaiaAuthenticator2 virtual void OnClientLoginFailure( - const GaiaAuthConsumer::GaiaAuthError& error); + const GoogleServiceAuthError& error); virtual void OnClientLoginSuccess( const GaiaAuthConsumer::ClientLoginResult& credentials); diff --git a/chrome/browser/chromeos/login/google_authenticator_unittest.cc b/chrome/browser/chromeos/login/google_authenticator_unittest.cc index 9f372b6..5489fd9 100644 --- a/chrome/browser/chromeos/login/google_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/google_authenticator_unittest.cc @@ -42,7 +42,7 @@ class MockConsumer : public LoginStatusConsumer { public: MockConsumer() {} ~MockConsumer() {} - MOCK_METHOD1(OnLoginFailure, void(const std::string& error)); + MOCK_METHOD1(OnLoginFailure, void(const LoginFailure& error)); MOCK_METHOD2(OnLoginSuccess, void(const std::string& username, const GaiaAuthConsumer::ClientLoginResult& result)); MOCK_METHOD0(OnOffTheRecordLoginSuccess, void(void)); @@ -395,15 +395,14 @@ TEST_F(GoogleAuthenticatorTest, LoginNetFailure) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); - int error_no = net::ERR_CONNECTION_RESET; - std::string data(net::ErrorToString(error_no)); + GoogleServiceAuthError error = + GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET); - GaiaAuthConsumer::GaiaAuthError error; - error.code = GaiaAuthConsumer::NETWORK_ERROR; - error.network_error = error_no; + LoginFailure failure = + LoginFailure::FromNetworkAuthFailure(error); MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginFailure(data)) + EXPECT_CALL(consumer, OnLoginFailure(failure)) .Times(1) .RetiresOnSaturation(); EXPECT_CALL(*mock_library_, CheckKey(username_, hash_ascii_)) @@ -420,8 +419,8 @@ TEST_F(GoogleAuthenticatorTest, LoginDenied) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); - GaiaAuthConsumer::GaiaAuthError error; - error.code = GaiaAuthConsumer::PERMISSION_DENIED; + GoogleServiceAuthError client_error( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); MockConsumer consumer; EXPECT_CALL(consumer, OnLoginFailure(_)) @@ -430,7 +429,7 @@ TEST_F(GoogleAuthenticatorTest, LoginDenied) { scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); PrepForLogin(auth.get()); - auth->OnClientLoginFailure(error); + auth->OnClientLoginFailure(client_error); message_loop.RunAllPending(); } @@ -438,22 +437,22 @@ TEST_F(GoogleAuthenticatorTest, CaptchaErrorOutputted) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); - // TODO(chron): Swap out this captcha passing for actual captcha parsing. - GaiaAuthConsumer::GaiaAuthError error; - error.code = GaiaAuthConsumer::PERMISSION_DENIED; - error.data = "Url=http://www.google.com/login/captcha\n" - "Error=CaptchaRequired\n" - "CaptchaToken=DQAAAGgA...dkI1LK9\n" - "CaptchaUrl=Captcha?ctoken=...\n"; + GoogleServiceAuthError auth_error = + GoogleServiceAuthError::FromCaptchaChallenge( + "CCTOKEN", + GURL("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"), + GURL("http://www.google.com/login/captcha")); + + LoginFailure failure = LoginFailure::FromNetworkAuthFailure(auth_error); MockConsumer consumer; - EXPECT_CALL(consumer, OnLoginFailure(error.data)) + EXPECT_CALL(consumer, OnLoginFailure(failure)) .Times(1) .RetiresOnSaturation(); scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); PrepForLogin(auth.get()); - auth->OnClientLoginFailure(error); + auth->OnClientLoginFailure(auth_error); message_loop.RunAllPending(); } @@ -461,9 +460,8 @@ TEST_F(GoogleAuthenticatorTest, OfflineLogin) { MessageLoopForUI message_loop; ChromeThread ui_thread(ChromeThread::UI, &message_loop); - GaiaAuthConsumer::GaiaAuthError error; - error.code = GaiaAuthConsumer::NETWORK_ERROR; - error.network_error = net::ERR_CONNECTION_RESET; + GoogleServiceAuthError auth_error( + GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET)); MockConsumer consumer; EXPECT_CALL(consumer, OnLoginSuccess(username_, result_)) @@ -478,7 +476,7 @@ TEST_F(GoogleAuthenticatorTest, OfflineLogin) { scoped_refptr<GoogleAuthenticator> auth(new GoogleAuthenticator(&consumer)); PrepForLogin(auth.get()); - auth->OnClientLoginFailure(error); + auth->OnClientLoginFailure(auth_error); message_loop.RunAllPending(); } @@ -516,7 +514,7 @@ TEST_F(GoogleAuthenticatorTest, CheckLocalaccount) { PrepForLogin(auth.get()); auth->SetLocalaccount(username_); - auth->CheckLocalaccount(std::string()); + auth->CheckLocalaccount(LoginFailure(LoginFailure::LOGIN_TIMED_OUT)); } namespace { @@ -536,11 +534,11 @@ static void OnSuccessQuitAndFail( } // Compatible with LoginStatusConsumer::OnLoginFailure() -static void OnFailQuit(const std::string& error) { +static void OnFailQuit(const LoginFailure& error) { MessageLoop::current()->Quit(); } -static void OnFailQuitAndFail(const std::string& error) { +static void OnFailQuitAndFail(const LoginFailure& error) { ADD_FAILURE() << "Login should have succeeded!"; MessageLoop::current()->Quit(); } @@ -576,7 +574,7 @@ TEST_F(GoogleAuthenticatorTest, LocalaccountLogin) { ChromeThread::UI, FROM_HERE, NewRunnableMethod(auth.get(), &GoogleAuthenticator::CheckLocalaccount, - std::string("fail"))); + LoginFailure(LoginFailure::LOGIN_TIMED_OUT))); message_loop.RunAllPending(); // The foregoing has now rescheduled itself in a few ms because we don't // yet have the localaccount loaded off disk. diff --git a/chrome/browser/chromeos/login/login_screen.cc b/chrome/browser/chromeos/login/login_screen.cc index caa84a1..847106e 100644 --- a/chrome/browser/chromeos/login/login_screen.cc +++ b/chrome/browser/chromeos/login/login_screen.cc @@ -74,7 +74,8 @@ void LoginScreen::ClearErrors() { bubble_->Close(); } -void LoginScreen::OnLoginFailure(const std::string& error) { +void LoginScreen::OnLoginFailure(const LoginFailure& failure) { + const std::string error = failure.GetErrorString(); LOG(INFO) << "LoginManagerView: OnLoginFailure() " << error; NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary(); diff --git a/chrome/browser/chromeos/login/login_screen.h b/chrome/browser/chromeos/login/login_screen.h index 3022b8f..9b52162 100644 --- a/chrome/browser/chromeos/login/login_screen.h +++ b/chrome/browser/chromeos/login/login_screen.h @@ -41,7 +41,7 @@ class LoginScreen : public ViewScreen<NewUserView>, virtual void NavigateAway() {} // Overridden from LoginStatusConsumer. - virtual void OnLoginFailure(const std::string& error); + virtual void OnLoginFailure(const LoginFailure& error); virtual void OnLoginSuccess(const std::string& username, const GaiaAuthConsumer::ClientLoginResult& credentials); virtual void OnOffTheRecordLoginSuccess(); diff --git a/chrome/browser/chromeos/login/login_status_consumer.h b/chrome/browser/chromeos/login/login_status_consumer.h index f0e2752..bf2c3f0 100644 --- a/chrome/browser/chromeos/login/login_status_consumer.h +++ b/chrome/browser/chromeos/login/login_status_consumer.h @@ -8,16 +8,86 @@ #include <string> #include "chrome/common/net/gaia/gaia_auth_consumer.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" +#include "net/base/net_errors.h" namespace chromeos { +class LoginFailure { + public: + enum FailureReason { + COULD_NOT_MOUNT_CRYPTOHOME, + COULD_NOT_MOUNT_TMPFS, + DATA_REMOVAL_FAILED, // Could not destroy your old data + LOGIN_TIMED_OUT, + UNLOCK_FAILED, + NETWORK_AUTH_FAILED, // Could not authenticate against Google + }; + + explicit LoginFailure(FailureReason reason) + : reason_(reason), + error_(GoogleServiceAuthError::NONE) { + DCHECK(reason != NETWORK_AUTH_FAILED); + } + + inline bool operator==(const LoginFailure &b) const { + if (reason_ != b.reason_) { + return false; + } + if (reason_ == NETWORK_AUTH_FAILED) { + return error_ == b.error_; + } + return true; + } + + static LoginFailure FromNetworkAuthFailure( + const GoogleServiceAuthError& error) { + return LoginFailure(NETWORK_AUTH_FAILED, error); + } + + const std::string GetErrorString() const { + switch (reason_) { + case DATA_REMOVAL_FAILED: + return "Could not destroy your old data."; + case COULD_NOT_MOUNT_CRYPTOHOME: + return "Could not mount cryptohome."; + case COULD_NOT_MOUNT_TMPFS: + return "Could not mount tmpfs."; + case LOGIN_TIMED_OUT: + return "Login timed out. Please try again."; + case UNLOCK_FAILED: + return "Unlock failed."; + case NETWORK_AUTH_FAILED: + if (error_.state() == GoogleServiceAuthError::CONNECTION_FAILED) { + return net::ErrorToString(error_.network_error()); + } + return "Google authentication failed."; + default: + NOTREACHED(); + return std::string(); + } + } + + const GoogleServiceAuthError& error() const { return error_; } + const FailureReason& reason() const { return reason_; } + + private: + LoginFailure(FailureReason reason, GoogleServiceAuthError error) + : reason_(reason), + error_(error) { + } + + FailureReason reason_; + GoogleServiceAuthError error_; +}; + // An interface that defines the callbacks for objects that the // Authenticator class will call to report the success/failure of // authentication for Chromium OS. class LoginStatusConsumer { public: virtual ~LoginStatusConsumer() {} - virtual void OnLoginFailure(const std::string& error) = 0; + virtual void OnLoginFailure(const LoginFailure& error) = 0; virtual void OnLoginSuccess(const std::string& username, const GaiaAuthConsumer::ClientLoginResult& credentials) = 0; virtual void OnOffTheRecordLoginSuccess() {} diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index 9d6df17..afb1a33 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -264,18 +264,4 @@ void LoginUtils::DoBrowserLaunch(Profile* profile) { &return_code); } -std::string LoginUtils::ExtractClientLoginParam( - const std::string& credentials, - const std::string& param_prefix, - const std::string& param_suffix) { - size_t start = credentials.find(param_prefix); - if (start == std::string::npos) - return std::string(); - start += param_prefix.size(); - size_t end = credentials.find(param_suffix, start); - if (end == std::string::npos) - return std::string(); - return credentials.substr(start, end - start); -} - } // namespace chromeos diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h index 2daa68d..b23c60d 100644 --- a/chrome/browser/chromeos/login/login_utils.h +++ b/chrome/browser/chromeos/login/login_utils.h @@ -31,13 +31,6 @@ class LoginUtils { // Task posted to the UI thread. static void DoBrowserLaunch(Profile* profile); - // Extracts specified param from given ClientLogin response. - // Returns the param value if found, empty string otherwise. - // Ex. prefix: "Auth=", suffix: "\n" - static std::string ExtractClientLoginParam(const std::string& credentials, - const std::string& param_prefix, - const std::string& param_suffix); - virtual ~LoginUtils() {} // Invoked after the user has successfully logged in. This launches a browser diff --git a/chrome/browser/chromeos/login/mock_authenticator.h b/chrome/browser/chromeos/login/mock_authenticator.h index 403af44..fa37555 100644 --- a/chrome/browser/chromeos/login/mock_authenticator.h +++ b/chrome/browser/chromeos/login/mock_authenticator.h @@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/login/authenticator.h" #include "chrome/browser/chromeos/login/login_utils.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "testing/gtest/include/gtest/gtest.h" class Profile; @@ -44,11 +45,13 @@ class MockAuthenticator : public Authenticator { GaiaAuthConsumer::ClientLoginResult())); return true; } else { + GoogleServiceAuthError error( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, NewRunnableMethod(this, &MockAuthenticator::OnLoginFailure, - std::string("Login failed"))); + LoginFailure::FromNetworkAuthFailure(error))); return false; } } @@ -69,8 +72,8 @@ class MockAuthenticator : public Authenticator { consumer_->OnLoginSuccess(expected_username_, credentials); } - void OnLoginFailure(const std::string& data) { - consumer_->OnLoginFailure(data); + void OnLoginFailure(const LoginFailure& failure) { + consumer_->OnLoginFailure(failure); LOG(INFO) << "Posting a QuitTask to UI thread"; ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, new MessageLoop::QuitTask); diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index 93c9e60..3272a9e 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -486,7 +486,7 @@ void ScreenLocker::Init() { lock_window->set_toplevel_focus_widget(lock_widget_->window_contents()); } -void ScreenLocker::OnLoginFailure(const std::string& error) { +void ScreenLocker::OnLoginFailure(const LoginFailure& error) { DLOG(INFO) << "OnLoginFailure"; EnableInput(); // Don't enable signout button here as we're showing @@ -500,8 +500,9 @@ void ScreenLocker::OnLoginFailure(const std::string& error) { if (error_info_) error_info_->Close(); std::wstring msg = l10n_util::GetString(IDS_LOGIN_ERROR_AUTHENTICATING); - if (!error.empty()) - msg += L"\n" + ASCIIToWide(error); + const std::string error_text = error.GetErrorString(); + if (!error_text.empty()) + msg += L"\n" + ASCIIToWide(error_text); InputMethodLibrary* input_method_library = CrosLibrary::Get()->GetInputMethodLibrary(); diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h index b871f4c..5879342 100644 --- a/chrome/browser/chromeos/login/screen_locker.h +++ b/chrome/browser/chromeos/login/screen_locker.h @@ -28,6 +28,7 @@ class InputEventObserver; class MessageBubble; class MouseEventRelay; class ScreenLockView; +class LoginFailure; namespace test { class ScreenLockerTester; @@ -45,7 +46,7 @@ class ScreenLocker : public LoginStatusConsumer, void Init(); // LoginStatusConsumer implements: - virtual void OnLoginFailure(const std::string& error); + virtual void OnLoginFailure(const chromeos::LoginFailure& error); virtual void OnLoginSuccess(const std::string& username, const GaiaAuthConsumer::ClientLoginResult& result); diff --git a/chrome/browser/net/gaia/token_service.cc b/chrome/browser/net/gaia/token_service.cc index 103c102..b46868f 100644 --- a/chrome/browser/net/gaia/token_service.cc +++ b/chrome/browser/net/gaia/token_service.cc @@ -138,7 +138,7 @@ void TokenService::FireTokenAvailableNotification( void TokenService::FireTokenRequestFailedNotification( const std::string& service, - const GaiaAuthError& error) { + const GoogleServiceAuthError& error) { TokenRequestFailedDetails details(service, error); NotificationService::current()->Notify( @@ -157,7 +157,7 @@ void TokenService::OnIssueAuthTokenSuccess(const std::string& service, } void TokenService::OnIssueAuthTokenFailure(const std::string& service, - const GaiaAuthError& error) { + const GoogleServiceAuthError& error) { DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); LOG(WARNING) << "Auth token issuing failed for service:" << service; FireTokenRequestFailedNotification(service, error); diff --git a/chrome/browser/net/gaia/token_service.h b/chrome/browser/net/gaia/token_service.h index f182e6a..20ca12d 100644 --- a/chrome/browser/net/gaia/token_service.h +++ b/chrome/browser/net/gaia/token_service.h @@ -41,6 +41,7 @@ #include "chrome/browser/webdata/web_data_service.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" #include "chrome/common/net/gaia/gaia_authenticator2.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "base/gtest_prod_util.h" class URLRequestContextGetter; @@ -70,15 +71,16 @@ class TokenService : public GaiaAuthConsumer, class TokenRequestFailedDetails { public: - TokenRequestFailedDetails() {} + TokenRequestFailedDetails() + : error_(GoogleServiceAuthError::NONE) {} TokenRequestFailedDetails(const std::string& service, - const GaiaAuthError& error) + const GoogleServiceAuthError& error) : service_(service), error_(error) {} const std::string& service() const { return service_; } - const GaiaAuthError& error() const { return error_; } + const GoogleServiceAuthError& error() const { return error_; } private: std::string service_; - GaiaAuthError error_; + GoogleServiceAuthError error_; }; // Initialize this token service with a request source @@ -125,7 +127,7 @@ class TokenService : public GaiaAuthConsumer, virtual void OnIssueAuthTokenSuccess(const std::string& service, const std::string& auth_token); virtual void OnIssueAuthTokenFailure(const std::string& service, - const GaiaAuthError& error); + const GoogleServiceAuthError& error); // WebDataServiceConsumer implementation. virtual void OnWebDataServiceRequestDone(WebDataService::Handle h, @@ -137,7 +139,7 @@ class TokenService : public GaiaAuthConsumer, const std::string& auth_token); void FireTokenRequestFailedNotification(const std::string& service, - const GaiaAuthError& error); + const GoogleServiceAuthError& error); void LoadTokensIntoMemory(const std::map<std::string, std::string>& in_toks, std::map<std::string, std::string>* out_toks); diff --git a/chrome/browser/net/gaia/token_service_unittest.cc b/chrome/browser/net/gaia/token_service_unittest.cc index 1082121..c560b61 100644 --- a/chrome/browser/net/gaia/token_service_unittest.cc +++ b/chrome/browser/net/gaia/token_service_unittest.cc @@ -159,8 +159,7 @@ TEST_F(TokenServiceTest, NotificationSuccess) { TEST_F(TokenServiceTest, NotificationFailed) { EXPECT_EQ(0U, success_tracker_.size()); EXPECT_EQ(0U, failure_tracker_.size()); - GaiaAuthConsumer::GaiaAuthError error; - error.code = GaiaAuthConsumer::REQUEST_CANCELED; + GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); service_.OnIssueAuthTokenFailure(GaiaConstants::kSyncService, error); EXPECT_EQ(0U, success_tracker_.size()); EXPECT_EQ(1U, failure_tracker_.size()); diff --git a/chrome/browser/remoting/remoting_setup_flow.cc b/chrome/browser/remoting/remoting_setup_flow.cc index 27deaff..5bf1a23 100644 --- a/chrome/browser/remoting/remoting_setup_flow.cc +++ b/chrome/browser/remoting/remoting_setup_flow.cc @@ -14,7 +14,6 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/dom_ui/dom_ui_util.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" @@ -24,6 +23,7 @@ #include "chrome/browser/service/service_process_control_manager.h" #include "chrome/common/net/gaia/gaia_authenticator2.h" #include "chrome/common/net/gaia/gaia_constants.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" #include "chrome/common/service_process_type.h" #include "gfx/font.h" @@ -103,7 +103,7 @@ void RemotingSetupFlow::OnUserSubmittedAuth(const std::string& user, } void RemotingSetupFlow::OnClientLoginFailure( - const GaiaAuthConsumer::GaiaAuthError& error) { + const GoogleServiceAuthError& error) { message_handler_->ShowGaiaFailed(); authenticator_.reset(); } @@ -150,7 +150,7 @@ void RemotingSetupFlow::OnIssueAuthTokenSuccess(const std::string& service, } void RemotingSetupFlow::OnIssueAuthTokenFailure(const std::string& service, - const GaiaAuthError& error) { + const GoogleServiceAuthError& error) { // TODO(hclam): Do something to show the error. authenticator_.reset(); } diff --git a/chrome/browser/remoting/remoting_setup_flow.h b/chrome/browser/remoting/remoting_setup_flow.h index 91912e8..1397f10 100644 --- a/chrome/browser/remoting/remoting_setup_flow.h +++ b/chrome/browser/remoting/remoting_setup_flow.h @@ -19,6 +19,7 @@ class GaiaAuthenticator2; class RemotingSetupMessageHandler; class ServiceProcessControl; +class GoogleServiceAuthError; // The state machine used by Remoting for setup wizard. class RemotingSetupFlow : public HtmlDialogUIDelegate, @@ -70,13 +71,13 @@ class RemotingSetupFlow : public HtmlDialogUIDelegate, // GaiaAuthConsumer implementation. virtual void OnClientLoginFailure( - const GaiaAuthConsumer::GaiaAuthError& error); + const GoogleServiceAuthError& error); virtual void OnClientLoginSuccess( const GaiaAuthConsumer::ClientLoginResult& credentials); virtual void OnIssueAuthTokenSuccess(const std::string& service, const std::string& auth_token); virtual void OnIssueAuthTokenFailure(const std::string& service, - const GaiaAuthError& error); + const GoogleServiceAuthError& error); // Called by RemotingSetupMessageHandler. void OnUserSubmittedAuth(const std::string& user, diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h index 65000b7..7760fd9 100644 --- a/chrome/browser/sync/engine/syncapi.h +++ b/chrome/browser/sync/engine/syncapi.h @@ -46,10 +46,10 @@ #include "base/gtest_prod_util.h" #include "base/scoped_ptr.h" #include "build/build_config.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/sync/notification_method.h" #include "chrome/browser/sync/syncable/model_type.h" #include "chrome/browser/sync/util/cryptographer.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "googleurl/src/gurl.h" class FilePath; diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index bc2d572..c7350aa 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -16,13 +16,13 @@ #include "base/ref_counted.h" #include "base/thread.h" #include "base/timer.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/sync/notification_method.h" #include "chrome/browser/sync/engine/syncapi.h" #include "chrome/browser/sync/engine/model_safe_worker.h" #include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/glue/ui_model_worker.h" #include "chrome/browser/sync/syncable/model_type.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/net/url_request_context_getter.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 3f5ddaa..c6637b6 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -14,7 +14,6 @@ #include "base/scoped_ptr.h" #include "base/string16.h" #include "base/time.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/pref_member.h" #include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/glue/data_type_manager.h" @@ -25,6 +24,7 @@ #include "chrome/browser/sync/sync_setup_wizard.h" #include "chrome/browser/sync/syncable/model_type.h" #include "chrome/browser/sync/unrecoverable_error_handler.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" #include "googleurl/src/gurl.h" diff --git a/chrome/browser/sync/sync_setup_flow.cc b/chrome/browser/sync/sync_setup_flow.cc index b8fc556..27549de 100644 --- a/chrome/browser/sync/sync_setup_flow.cc +++ b/chrome/browser/sync/sync_setup_flow.cc @@ -18,7 +18,6 @@ #include "chrome/browser/cocoa/html_dialog_window_controller_cppsafe.h" #endif #include "chrome/browser/dom_ui/dom_ui_util.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" @@ -26,6 +25,7 @@ #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/syncable/model_type.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" #include "gfx/font.h" #include "grit/locale_settings.h" diff --git a/chrome/browser/sync/sync_setup_wizard_unittest.cc b/chrome/browser/sync/sync_setup_wizard_unittest.cc index 0d64385..788746b 100644 --- a/chrome/browser/sync/sync_setup_wizard_unittest.cc +++ b/chrome/browser/sync/sync_setup_wizard_unittest.cc @@ -10,11 +10,11 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/sync/profile_sync_factory_mock.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_setup_flow.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" #include "chrome/test/browser_with_test_window_test.h" #include "chrome/test/testing_profile.h" diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc index 3364f67..c7c1575 100644 --- a/chrome/browser/sync/sync_ui_util.cc +++ b/chrome/browser/sync/sync_ui_util.cc @@ -6,10 +6,10 @@ #include "app/l10n_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/profile.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/options_window.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index f2c3886..82d8bd4 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi @@ -373,6 +373,7 @@ 'common/net/gaia/gaia_authenticator.h', 'common/net/gaia/gaia_authenticator2.cc', 'common/net/gaia/gaia_authenticator2.h', + 'common/net/gaia/google_service_auth_error.h', 'common/net/gaia/signin.h', ], 'dependencies': [ diff --git a/chrome/common/net/gaia/gaia_auth_consumer.h b/chrome/common/net/gaia/gaia_auth_consumer.h index d3adf16..474f33b 100644 --- a/chrome/common/net/gaia/gaia_auth_consumer.h +++ b/chrome/common/net/gaia/gaia_auth_consumer.h @@ -8,6 +8,8 @@ #include <string> +class GoogleServiceAuthError; + // An interface that defines the callbacks for objects that // GaiaAuthenticator2 can return data to. class GaiaAuthConsumer { @@ -37,38 +39,15 @@ class GaiaAuthConsumer { std::string data; // Full contents of ClientLogin return. }; - enum GaiaAuthErrorCode { - NETWORK_ERROR, - REQUEST_CANCELED, - TWO_FACTOR, // Callers can treat this as a success. - PERMISSION_DENIED - }; - - struct GaiaAuthError { - inline bool operator==(const GaiaAuthError &b) const { - if (code != b.code) { - return false; - } - if (code == NETWORK_ERROR) { - return network_error == b.network_error; - } - return true; - } - - GaiaAuthErrorCode code; - int network_error; // This field is only valid if NETWORK_ERROR occured. - std::string data; // TODO(chron): Remove this field. Should preparse data. - }; - virtual ~GaiaAuthConsumer() {} virtual void OnClientLoginSuccess(const ClientLoginResult& result) {} - virtual void OnClientLoginFailure(const GaiaAuthError& error) {} + virtual void OnClientLoginFailure(const GoogleServiceAuthError& error) {} virtual void OnIssueAuthTokenSuccess(const std::string& service, const std::string& auth_token) {} virtual void OnIssueAuthTokenFailure(const std::string& service, - const GaiaAuthError& error) {} + const GoogleServiceAuthError& error) {} }; #endif // CHROME_COMMON_NET_GAIA_GAIA_AUTH_CONSUMER_H_ diff --git a/chrome/common/net/gaia/gaia_authenticator2.cc b/chrome/common/net/gaia/gaia_authenticator2.cc index a0e7b2f..063d0546 100644 --- a/chrome/common/net/gaia/gaia_authenticator2.cc +++ b/chrome/common/net/gaia/gaia_authenticator2.cc @@ -9,6 +9,7 @@ #include "base/string_split.h" #include "base/string_util.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/net/http_return.h" #include "chrome/common/net/url_request_context_getter.h" #include "net/base/load_flags.h" @@ -42,6 +43,20 @@ const char GaiaAuthenticator2::kIssueAuthTokenFormat[] = "Session=true"; // static +const char GaiaAuthenticator2::kCaptchaError[] = "CaptchaRequired"; +// static +const char GaiaAuthenticator2::kErrorParam[] = "Error"; +// static +const char GaiaAuthenticator2::kErrorUrlParam[] = "Url"; +// static +const char GaiaAuthenticator2::kCaptchaUrlParam[] = "CaptchaUrl"; +// static +const char GaiaAuthenticator2::kCaptchaTokenParam[] = "CaptchaToken"; +// static +const char GaiaAuthenticator2::kCaptchaUrlPrefix[] = + "http://www.google.com/accounts/"; + +// static const char GaiaAuthenticator2::kCookiePersistence[] = "true"; // static const char GaiaAuthenticator2::kAccountType[] = "HOSTED_OR_GOOGLE"; @@ -161,6 +176,32 @@ void GaiaAuthenticator2::ParseClientLoginResponse(const std::string& data, } } +// static +void GaiaAuthenticator2::ParseClientLoginFailure(const std::string& data, + std::string* error, + std::string* error_url, + std::string* captcha_url, + std::string* captcha_token) { + using std::vector; + using std::pair; + using std::string; + + vector<pair<string, string> > tokens; + base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens); + for (vector<pair<string, string> >::iterator i = tokens.begin(); + i != tokens.end(); ++i) { + if (i->first == kErrorParam) { + error->assign(i->second); + } else if (i->first == kErrorUrlParam) { + error_url->assign(i->second); + } else if (i->first == kCaptchaUrlParam) { + captcha_url->assign(i->second); + } else if (i->first == kCaptchaTokenParam) { + captcha_token->assign(i->second); + } + } +} + void GaiaAuthenticator2::StartClientLogin(const std::string& username, const std::string& password, const char* const service, @@ -205,31 +246,42 @@ void GaiaAuthenticator2::StartIssueAuthToken(const std::string& sid, fetcher_->Start(); } -GaiaAuthConsumer::GaiaAuthError GaiaAuthenticator2::GenerateAuthError( +// static +GoogleServiceAuthError GaiaAuthenticator2::GenerateAuthError( const std::string& data, const URLRequestStatus& status) { - GaiaAuthConsumer::GaiaAuthError error; - error.data = data; - if (!status.is_success()) { if (status.status() == URLRequestStatus::CANCELED) { - error.code = GaiaAuthConsumer::REQUEST_CANCELED; + return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); } else { - error.code = GaiaAuthConsumer::NETWORK_ERROR; - error.network_error = status.os_error(); LOG(WARNING) << "Could not reach Google Accounts servers: errno " - << status.os_error(); + << status.os_error(); + return GoogleServiceAuthError::FromConnectionError(status.os_error()); } } else { if (IsSecondFactorSuccess(data)) { - error.code = GaiaAuthConsumer::TWO_FACTOR; - } else { - error.code = GaiaAuthConsumer::PERMISSION_DENIED; + return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); } + + std::string error; + std::string url; + std::string captcha_url; + std::string captcha_token; + ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token); + + if (error == kCaptchaError) { + GURL image_url(kCaptchaUrlPrefix + captcha_url); + GURL unlock_url(url); + return GoogleServiceAuthError::FromCaptchaChallenge( + captcha_token, image_url, unlock_url); + } + + return GoogleServiceAuthError( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); } - return error; + NOTREACHED(); } void GaiaAuthenticator2::OnClientLoginFetched(const std::string& data, diff --git a/chrome/common/net/gaia/gaia_authenticator2.h b/chrome/common/net/gaia/gaia_authenticator2.h index 50be1d3..2b114f5 100644 --- a/chrome/common/net/gaia/gaia_authenticator2.h +++ b/chrome/common/net/gaia/gaia_authenticator2.h @@ -86,6 +86,14 @@ class GaiaAuthenticator2 : public URLFetcher::Delegate { // The format of the POST body for IssueAuthToken. static const char kIssueAuthTokenFormat[]; + // Constants for parsing ClientLogin errors. + static const char kCaptchaError[]; + static const char kErrorParam[]; + static const char kErrorUrlParam[]; + static const char kCaptchaUrlParam[]; + static const char kCaptchaTokenParam[]; + static const char kCaptchaUrlPrefix[]; + // Process the results of a ClientLogin fetch. void OnClientLoginFetched(const std::string& data, const URLRequestStatus& status, @@ -101,10 +109,16 @@ class GaiaAuthenticator2 : public URLFetcher::Delegate { std::string* lsid, std::string* token); - // From a URLFetcher result, generate an appropriate GaiaAuthError. + static void ParseClientLoginFailure(const std::string& data, + std::string* error, + std::string* error_url, + std::string* captcha_url, + std::string* captcha_token); + + // From a URLFetcher result, generate an appropriate error. // From the API documentation, both IssueAuthToken and ClientLogin have // the same error returns. - static GaiaAuthConsumer::GaiaAuthError GenerateAuthError( + static GoogleServiceAuthError GenerateAuthError( const std::string& data, const URLRequestStatus& status); @@ -145,9 +159,10 @@ class GaiaAuthenticator2 : public URLFetcher::Delegate { bool fetch_pending_; friend class GaiaAuthenticator2Test; - FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, LoginNetFailure); + FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, CaptchaParse); FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, CheckNormalErrorCode); FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, CheckTwoFactorResponse); + FRIEND_TEST_ALL_PREFIXES(GaiaAuthenticator2Test, LoginNetFailure); DISALLOW_COPY_AND_ASSIGN(GaiaAuthenticator2); }; diff --git a/chrome/common/net/gaia/gaia_authenticator2_unittest.cc b/chrome/common/net/gaia/gaia_authenticator2_unittest.cc index 181a002..2061a19 100644 --- a/chrome/common/net/gaia/gaia_authenticator2_unittest.cc +++ b/chrome/common/net/gaia/gaia_authenticator2_unittest.cc @@ -12,6 +12,7 @@ #include "chrome/common/net/gaia/gaia_auth_consumer.h" #include "chrome/common/net/gaia/gaia_authenticator2.h" #include "chrome/common/net/gaia/gaia_authenticator2_unittest.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/net/http_return.h" #include "chrome/common/net/test_url_fetcher_factory.h" #include "chrome/common/net/url_fetcher.h" @@ -47,6 +48,27 @@ class GaiaAuthenticator2Test : public testing::Test { EXPECT_EQ(token, out_token); } + void RunErrorParsingTest(const std::string& data, + const std::string& error, + const std::string& error_url, + const std::string& captcha_url, + const std::string& captcha_token) { + std::string out_error; + std::string out_error_url; + std::string out_captcha_url; + std::string out_captcha_token; + + GaiaAuthenticator2::ParseClientLoginFailure(data, + &out_error, + &out_error_url, + &out_captcha_url, + &out_captcha_token); + EXPECT_EQ(error, out_error); + EXPECT_EQ(error_url, out_error_url); + EXPECT_EQ(captcha_url, out_captcha_url); + EXPECT_EQ(captcha_token, out_captcha_token); + } + ResponseCookies cookies_; GURL client_login_source_; GURL issue_auth_token_source_; @@ -61,28 +83,30 @@ class MockGaiaConsumer : public GaiaAuthConsumer { MOCK_METHOD1(OnClientLoginSuccess, void(const ClientLoginResult& result)); MOCK_METHOD2(OnIssueAuthTokenSuccess, void(const std::string& service, const std::string& token)); - MOCK_METHOD1(OnClientLoginFailure, void(const GaiaAuthError& error)); + MOCK_METHOD1(OnClientLoginFailure, + void(const GoogleServiceAuthError& error)); MOCK_METHOD2(OnIssueAuthTokenFailure, void(const std::string& service, - const GaiaAuthError& error)); + const GoogleServiceAuthError& error)); }; TEST_F(GaiaAuthenticator2Test, ErrorComparator) { - GaiaAuthConsumer::GaiaAuthError expected_error; - expected_error.code = GaiaAuthConsumer::NETWORK_ERROR; - expected_error.network_error = -101; + GoogleServiceAuthError expected_error = + GoogleServiceAuthError::FromConnectionError(-101); - GaiaAuthConsumer::GaiaAuthError matching_error; - matching_error.code = GaiaAuthConsumer::NETWORK_ERROR; - matching_error.network_error = -101; + GoogleServiceAuthError matching_error = + GoogleServiceAuthError::FromConnectionError(-101); EXPECT_TRUE(expected_error == matching_error); - expected_error.network_error = 6; + expected_error = GoogleServiceAuthError::FromConnectionError(6); EXPECT_FALSE(expected_error == matching_error); - expected_error.code = GaiaAuthConsumer::PERMISSION_DENIED; - matching_error.code = GaiaAuthConsumer::PERMISSION_DENIED; + expected_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE); + + EXPECT_FALSE(expected_error == matching_error); + + matching_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE); EXPECT_TRUE(expected_error == matching_error); } @@ -91,9 +115,8 @@ TEST_F(GaiaAuthenticator2Test, LoginNetFailure) { int error_no = net::ERR_CONNECTION_RESET; URLRequestStatus status(URLRequestStatus::FAILED, error_no); - GaiaAuthConsumer::GaiaAuthError expected_error; - expected_error.code = GaiaAuthConsumer::NETWORK_ERROR; - expected_error.network_error = error_no; + GoogleServiceAuthError expected_error = + GoogleServiceAuthError::FromConnectionError(error_no); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(expected_error)) @@ -114,9 +137,8 @@ TEST_F(GaiaAuthenticator2Test, TokenNetFailure) { int error_no = net::ERR_CONNECTION_RESET; URLRequestStatus status(URLRequestStatus::FAILED, error_no); - GaiaAuthConsumer::GaiaAuthError expected_error; - expected_error.code = GaiaAuthConsumer::NETWORK_ERROR; - expected_error.network_error = error_no; + GoogleServiceAuthError expected_error = + GoogleServiceAuthError::FromConnectionError(error_no); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnIssueAuthTokenFailure(_, expected_error)) @@ -138,8 +160,8 @@ TEST_F(GaiaAuthenticator2Test, LoginDenied) { std::string data("Error: NO!"); URLRequestStatus status(URLRequestStatus::SUCCESS, 0); - GaiaAuthConsumer::GaiaAuthError expected_error; - expected_error.code = GaiaAuthConsumer::PERMISSION_DENIED; + GoogleServiceAuthError expected_error( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(expected_error)) @@ -165,6 +187,22 @@ TEST_F(GaiaAuthenticator2Test, ParseRequest) { RunParsingTest("SID=sid", "sid", "", ""); } +TEST_F(GaiaAuthenticator2Test, ParseErrorRequest) { + RunErrorParsingTest("Url=U\n" + "Error=E\n" + "CaptchaToken=T\n" + "CaptchaUrl=C\n", "E", "U", "C", "T"); + RunErrorParsingTest("CaptchaToken=T\n" + "Error=E\n" + "Url=U\n" + "CaptchaUrl=C\n", "E", "U", "C", "T"); + RunErrorParsingTest("\n\n\nCaptchaToken=T\n" + "\nError=E\n" + "\nUrl=U\n" + "CaptchaUrl=C\n", "E", "U", "C", "T"); +} + + TEST_F(GaiaAuthenticator2Test, OnlineLogin) { std::string data("SID=sid\nLSID=lsid\nAuth=auth\n"); @@ -218,12 +256,11 @@ TEST_F(GaiaAuthenticator2Test, CheckNormalErrorCode) { } TEST_F(GaiaAuthenticator2Test, TwoFactorLogin) { - std::string response = - StringPrintf("Error=BadAuthentication\n%s\n", - GaiaAuthenticator2::kSecondFactor); + std::string response = StringPrintf("Error=BadAuthentication\n%s\n", + GaiaAuthenticator2::kSecondFactor); - GaiaAuthConsumer::GaiaAuthError error; - error.code = GaiaAuthConsumer::TWO_FACTOR; + GoogleServiceAuthError error = + GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(error)) @@ -240,6 +277,25 @@ TEST_F(GaiaAuthenticator2Test, TwoFactorLogin) { response); } +TEST_F(GaiaAuthenticator2Test, CaptchaParse) { + URLRequestStatus status(URLRequestStatus::SUCCESS, 0); + std::string data = "Url=http://www.google.com/login/captcha\n" + "Error=CaptchaRequired\n" + "CaptchaToken=CCTOKEN\n" + "CaptchaUrl=Captcha?ctoken=CCTOKEN\n"; + GoogleServiceAuthError error = + GaiaAuthenticator2::GenerateAuthError(data, status); + + std::string token = "CCTOKEN"; + GURL image_url("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"); + GURL unlock_url("http://www.google.com/login/captcha"); + + EXPECT_EQ(error.state(), GoogleServiceAuthError::CAPTCHA_REQUIRED); + EXPECT_EQ(error.captcha().token, token); + EXPECT_EQ(error.captcha().image_url, image_url); + EXPECT_EQ(error.captcha().unlock_url, unlock_url); +} + TEST_F(GaiaAuthenticator2Test, FullLogin) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginSuccess(_)) diff --git a/chrome/browser/google_service_auth_error.h b/chrome/common/net/gaia/google_service_auth_error.h index 03b61d8..7cc2751 100644 --- a/chrome/browser/google_service_auth_error.h +++ b/chrome/common/net/gaia/google_service_auth_error.h @@ -19,11 +19,12 @@ // may forward declare and typedef GoogleServiceAuthError to something shorter // in the comfort of your own translation unit. -#ifndef CHROME_BROWSER_GOOGLE_SERVICE_AUTH_ERROR_H_ -#define CHROME_BROWSER_GOOGLE_SERVICE_AUTH_ERROR_H_ +#ifndef CHROME_COMMON_NET_GAIA_GOOGLE_SERVICE_AUTH_ERROR_H_ +#define CHROME_COMMON_NET_GAIA_GOOGLE_SERVICE_AUTH_ERROR_H_ #pragma once #include <string> +#include "base/logging.h" #include "googleurl/src/gurl.h" class GoogleServiceAuthError { @@ -32,6 +33,9 @@ class GoogleServiceAuthError { // The user is authenticated. NONE = 0, + // The password is valid but we need two factor to get a token. + TWO_FACTOR, + // The credentials supplied to GAIA were either invalid, or the locally // cached credentials have expired. INVALID_GAIA_CREDENTIALS, @@ -44,6 +48,10 @@ class GoogleServiceAuthError { // the service needing GAIA tokens during authentication. CONNECTION_FAILED, + // The requestor of the authentication step cancelled the request + // prior to completion. + REQUEST_CANCELED, + // The user needs to satisfy a CAPTCHA challenge to unlock their account. // If no other information is available, this can be resolved by visiting // https://www.google.com/accounts/DisplayUnlockCaptcha. Otherwise, @@ -61,8 +69,28 @@ class GoogleServiceAuthError { GURL unlock_url; // Pretty unlock page containing above captcha. }; + // For test only. + inline bool operator==(const GoogleServiceAuthError &b) const { + return (state_ == b.state_ && + network_error_ == b.network_error_ && + captcha_.token == b.captcha_.token && + captcha_.image_url == b.captcha_.image_url && + captcha_.unlock_url == b.captcha_.unlock_url); + } + // Construct a GoogleServiceAuthError from a State with no additional data. - explicit GoogleServiceAuthError(State s) : state_(s) {} + explicit GoogleServiceAuthError(State s) + : state_(s), + captcha_("", GURL(), GURL()), + network_error_(0) { + DCHECK(s != CONNECTION_FAILED); + } + + // Construct a GoogleServiceAuthError from a network error. + // It will be created with CONNECTION_FAILED set. + static GoogleServiceAuthError FromConnectionError(int error) { + return GoogleServiceAuthError(CONNECTION_FAILED, error); + } // Construct a CAPTCHA_REQUIRED error with CAPTCHA challenge data. static GoogleServiceAuthError FromCaptchaChallenge( @@ -84,17 +112,28 @@ class GoogleServiceAuthError { // The error information. const State& state() const { return state_; } const Captcha& captcha() const { return captcha_; } + const int network_error() const { + return network_error_; + } private: + GoogleServiceAuthError(State s, int error) + : state_(s), + captcha_("", GURL(), GURL()), + network_error_(error) { + } + GoogleServiceAuthError(State s, const std::string& captcha_token, const GURL& captcha_image_url, const GURL& captcha_unlock_url) : state_(s), - captcha_(captcha_token, captcha_image_url, captcha_unlock_url) { + captcha_(captcha_token, captcha_image_url, captcha_unlock_url), + network_error_(0) { } State state_; Captcha captcha_; + int network_error_; }; -#endif // CHROME_BROWSER_GOOGLE_SERVICE_AUTH_ERROR_H_ +#endif // CHROME_COMMON_NET_GAIA_GOOGLE_SERVICE_AUTH_ERROR_H_ diff --git a/chrome/test/live_sync/offline_sync_test.cc b/chrome/test/live_sync/offline_sync_test.cc index 8f0dea2..c64df34 100644 --- a/chrome/test/live_sync/offline_sync_test.cc +++ b/chrome/test/live_sync/offline_sync_test.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/profile.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/test/live_sync/live_sync_test.h" #include "chrome/test/live_sync/profile_sync_service_test_harness.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chrome/test/live_sync/profile_sync_service_test_harness.cc b/chrome/test/live_sync/profile_sync_service_test_harness.cc index 14d44d1..6d51e3e 100644 --- a/chrome/test/live_sync/profile_sync_service_test_harness.cc +++ b/chrome/test/live_sync/profile_sync_service_test_harness.cc @@ -5,12 +5,12 @@ #include "base/message_loop.h" #include "chrome/browser/browser.h" #include "chrome/browser/defaults.h" -#include "chrome/browser/google_service_auth_error.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/sync/glue/sync_backend_host.h" #include "chrome/browser/sync/sessions/session_state.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/pref_names.h" #include "chrome/test/live_sync/profile_sync_service_test_harness.h" #include "chrome/test/ui_test_utils.h" |