| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/sync/signin_manager.h" |
| |
| #include "base/string_util.h" |
| #include "chrome/browser/net/gaia/token_service.h" |
| #include "chrome/browser/prefs/pref_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/net/gaia/gaia_constants.h" |
| #include "chrome/common/pref_names.h" |
| #include "content/common/notification_service.h" |
| |
| const char kGetInfoEmailKey[] = "email"; |
| |
| SigninManager::SigninManager() |
| : profile_(NULL), had_two_factor_error_(false) {} |
| |
| SigninManager::~SigninManager() {} |
| |
| // static |
| void SigninManager::RegisterUserPrefs(PrefService* user_prefs) { |
| user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, ""); |
| } |
| |
| void SigninManager::Initialize(Profile* profile) { |
| profile_ = profile; |
| username_ = profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername); |
| profile_->GetTokenService()->Initialize( |
| GaiaConstants::kChromeSource, profile_); |
| if (!username_.empty()) { |
| profile_->GetTokenService()->LoadTokensFromDB(); |
| } |
| } |
| |
| // If a username already exists, the user is logged in. |
| const std::string& SigninManager::GetUsername() { |
| return username_; |
| } |
| |
| void SigninManager::SetUsername(const std::string& username) { |
| username_ = username; |
| } |
| |
| // Users must always sign out before they sign in again. |
| void SigninManager::StartSignIn(const std::string& username, |
| const std::string& password, |
| const std::string& login_token, |
| const std::string& login_captcha) { |
| DCHECK(username_.empty()); |
| #if !defined(OS_CHROMEOS) |
| // The Sign out should clear the token service credentials. |
| // Note: In CHROMEOS we might have valid credentials but still need to |
| // set up 2-factor authentication. |
| DCHECK(!profile_->GetTokenService()->AreCredentialsValid()); |
| #endif |
| username_.assign(username); |
| password_.assign(password); |
| |
| client_login_.reset(new GaiaAuthFetcher(this, |
| GaiaConstants::kChromeSource, |
| profile_->GetRequestContext())); |
| client_login_->StartClientLogin(username, |
| password, |
| "", |
| login_token, |
| login_captcha, |
| GaiaAuthFetcher::HostedAccountsNotAllowed); |
| } |
| |
| void SigninManager::ProvideSecondFactorAccessCode( |
| const std::string& access_code) { |
| DCHECK(!username_.empty() && !password_.empty() && |
| last_result_.data.empty()); |
| |
| client_login_.reset(new GaiaAuthFetcher(this, |
| GaiaConstants::kChromeSource, |
| profile_->GetRequestContext())); |
| client_login_->StartClientLogin(username_, |
| access_code, |
| "", |
| std::string(), |
| std::string(), |
| GaiaAuthFetcher::HostedAccountsNotAllowed); |
| } |
| |
| void SigninManager::SignOut() { |
| if (!profile_) |
| return; |
| |
| client_login_.reset(); |
| last_result_ = ClientLoginResult(); |
| username_.clear(); |
| password_.clear(); |
| had_two_factor_error_ = false; |
| profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_); |
| profile_->GetPrefs()->ScheduleSavePersistentPrefs(); |
| profile_->GetTokenService()->ResetCredentialsInMemory(); |
| profile_->GetTokenService()->EraseTokensFromDB(); |
| } |
| |
| void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) { |
| last_result_ = result; |
| // Make a request for the canonical email address. |
| client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey); |
| } |
| |
| void SigninManager::OnGetUserInfoSuccess(const std::string& key, |
| const std::string& value) { |
| DCHECK(key == kGetInfoEmailKey); |
| |
| username_ = value; |
| profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_); |
| profile_->GetPrefs()->ScheduleSavePersistentPrefs(); |
| |
| GoogleServiceSigninSuccessDetails details(username_, password_); |
| NotificationService::current()->Notify( |
| NotificationType::GOOGLE_SIGNIN_SUCCESSFUL, |
| Source<Profile>(profile_), |
| Details<const GoogleServiceSigninSuccessDetails>(&details)); |
| |
| password_.clear(); // Don't need it anymore. |
| |
| profile_->GetTokenService()->UpdateCredentials(last_result_); |
| DCHECK(profile_->GetTokenService()->AreCredentialsValid()); |
| profile_->GetTokenService()->StartFetchingTokens(); |
| } |
| |
| void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) { |
| DCHECK(key == kGetInfoEmailKey); |
| LOG(ERROR) << "Account is not associated with a valid email address. " |
| << "Login failed."; |
| OnClientLoginFailure(GoogleServiceAuthError( |
| GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); |
| } |
| |
| void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) { |
| LOG(ERROR) << "Unable to retreive the canonical email address. Login failed."; |
| OnClientLoginFailure(error); |
| } |
| |
| void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) { |
| NotificationService::current()->Notify( |
| NotificationType::GOOGLE_SIGNIN_FAILED, |
| Source<Profile>(profile_), |
| Details<const GoogleServiceAuthError>(&error)); |
| |
| // We don't sign-out if the password was valid and we're just dealing with |
| // a second factor error, and we don't sign out if we're dealing with |
| // an invalid access code (again, because the password was valid). |
| bool invalid_gaia = error.state() == |
| GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS; |
| if (error.state() == GoogleServiceAuthError::TWO_FACTOR || |
| (had_two_factor_error_ && invalid_gaia)) { |
| had_two_factor_error_ = true; |
| return; |
| } |
| |
| SignOut(); |
| } |