• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/sync/signin_manager.h"
6 
7 #include "base/string_util.h"
8 #include "chrome/browser/net/gaia/token_service.h"
9 #include "chrome/browser/prefs/pref_service.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/common/net/gaia/gaia_constants.h"
12 #include "chrome/common/pref_names.h"
13 #include "content/common/notification_service.h"
14 
15 const char kGetInfoEmailKey[] = "email";
16 
SigninManager()17 SigninManager::SigninManager()
18     : profile_(NULL), had_two_factor_error_(false) {}
19 
~SigninManager()20 SigninManager::~SigninManager() {}
21 
22 // static
RegisterUserPrefs(PrefService * user_prefs)23 void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
24   user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, "");
25 }
26 
Initialize(Profile * profile)27 void SigninManager::Initialize(Profile* profile) {
28   profile_ = profile;
29   username_ = profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
30   profile_->GetTokenService()->Initialize(
31       GaiaConstants::kChromeSource, profile_);
32   if (!username_.empty()) {
33     profile_->GetTokenService()->LoadTokensFromDB();
34   }
35 }
36 
37 // If a username already exists, the user is logged in.
GetUsername()38 const std::string& SigninManager::GetUsername() {
39   return username_;
40 }
41 
SetUsername(const std::string & username)42 void SigninManager::SetUsername(const std::string& username) {
43   username_ = username;
44 }
45 
46 // Users must always sign out before they sign in again.
StartSignIn(const std::string & username,const std::string & password,const std::string & login_token,const std::string & login_captcha)47 void SigninManager::StartSignIn(const std::string& username,
48                                 const std::string& password,
49                                 const std::string& login_token,
50                                 const std::string& login_captcha) {
51   DCHECK(username_.empty());
52 #if !defined(OS_CHROMEOS)
53   // The Sign out should clear the token service credentials.
54   // Note: In CHROMEOS we might have valid credentials but still need to
55   // set up 2-factor authentication.
56   DCHECK(!profile_->GetTokenService()->AreCredentialsValid());
57 #endif
58   username_.assign(username);
59   password_.assign(password);
60 
61   client_login_.reset(new GaiaAuthFetcher(this,
62                                           GaiaConstants::kChromeSource,
63                                           profile_->GetRequestContext()));
64   client_login_->StartClientLogin(username,
65                                   password,
66                                   "",
67                                   login_token,
68                                   login_captcha,
69                                   GaiaAuthFetcher::HostedAccountsNotAllowed);
70 }
71 
ProvideSecondFactorAccessCode(const std::string & access_code)72 void SigninManager::ProvideSecondFactorAccessCode(
73     const std::string& access_code) {
74   DCHECK(!username_.empty() && !password_.empty() &&
75       last_result_.data.empty());
76 
77   client_login_.reset(new GaiaAuthFetcher(this,
78                                           GaiaConstants::kChromeSource,
79                                           profile_->GetRequestContext()));
80   client_login_->StartClientLogin(username_,
81                                   access_code,
82                                   "",
83                                   std::string(),
84                                   std::string(),
85                                   GaiaAuthFetcher::HostedAccountsNotAllowed);
86 }
87 
SignOut()88 void SigninManager::SignOut() {
89   if (!profile_)
90     return;
91 
92   client_login_.reset();
93   last_result_ = ClientLoginResult();
94   username_.clear();
95   password_.clear();
96   had_two_factor_error_ = false;
97   profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
98   profile_->GetPrefs()->ScheduleSavePersistentPrefs();
99   profile_->GetTokenService()->ResetCredentialsInMemory();
100   profile_->GetTokenService()->EraseTokensFromDB();
101 }
102 
OnClientLoginSuccess(const ClientLoginResult & result)103 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
104   last_result_ = result;
105   // Make a request for the canonical email address.
106   client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey);
107 }
108 
OnGetUserInfoSuccess(const std::string & key,const std::string & value)109 void SigninManager::OnGetUserInfoSuccess(const std::string& key,
110                                          const std::string& value) {
111   DCHECK(key == kGetInfoEmailKey);
112 
113   username_ = value;
114   profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
115   profile_->GetPrefs()->ScheduleSavePersistentPrefs();
116 
117   GoogleServiceSigninSuccessDetails details(username_, password_);
118   NotificationService::current()->Notify(
119       NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
120       Source<Profile>(profile_),
121       Details<const GoogleServiceSigninSuccessDetails>(&details));
122 
123   password_.clear();  // Don't need it anymore.
124 
125   profile_->GetTokenService()->UpdateCredentials(last_result_);
126   DCHECK(profile_->GetTokenService()->AreCredentialsValid());
127   profile_->GetTokenService()->StartFetchingTokens();
128 }
129 
OnGetUserInfoKeyNotFound(const std::string & key)130 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
131   DCHECK(key == kGetInfoEmailKey);
132   LOG(ERROR) << "Account is not associated with a valid email address. "
133              << "Login failed.";
134   OnClientLoginFailure(GoogleServiceAuthError(
135       GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
136 }
137 
OnGetUserInfoFailure(const GoogleServiceAuthError & error)138 void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
139   LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
140   OnClientLoginFailure(error);
141 }
142 
OnClientLoginFailure(const GoogleServiceAuthError & error)143 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
144   NotificationService::current()->Notify(
145       NotificationType::GOOGLE_SIGNIN_FAILED,
146       Source<Profile>(profile_),
147       Details<const GoogleServiceAuthError>(&error));
148 
149   // We don't sign-out if the password was valid and we're just dealing with
150   // a second factor error, and we don't sign out if we're dealing with
151   // an invalid access code (again, because the password was valid).
152   bool invalid_gaia = error.state() ==
153       GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
154   if (error.state() == GoogleServiceAuthError::TWO_FACTOR ||
155       (had_two_factor_error_ && invalid_gaia)) {
156     had_two_factor_error_ = true;
157     return;
158   }
159 
160   SignOut();
161 }
162