signin_manager.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2010 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/profile.h"
11#include "chrome/common/net/gaia/gaia_constants.h"
12#include "chrome/common/notification_service.h"
13#include "chrome/common/pref_names.h"
14
15const char kGetInfoEmailKey[] = "email";
16
17SigninManager::SigninManager()
18    : profile_(NULL), had_two_factor_error_(false) {}
19
20SigninManager::~SigninManager() {}
21
22// static
23void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
24  user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, "");
25}
26
27void 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.
38const std::string& SigninManager::GetUsername() {
39  return username_;
40}
41
42void SigninManager::SetUsername(const std::string& username) {
43  username_ = username;
44}
45
46// Users must always sign out before they sign in again.
47void 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  // The Sign out should clear the token service credentials.
53  DCHECK(!profile_->GetTokenService()->AreCredentialsValid());
54
55  username_.assign(username);
56  password_.assign(password);
57
58  client_login_.reset(new GaiaAuthFetcher(this,
59                                          GaiaConstants::kChromeSource,
60                                          profile_->GetRequestContext()));
61  client_login_->StartClientLogin(username,
62                                  password,
63                                  "",
64                                  login_token,
65                                  login_captcha,
66                                  GaiaAuthFetcher::HostedAccountsNotAllowed);
67}
68
69void SigninManager::ProvideSecondFactorAccessCode(
70    const std::string& access_code) {
71  DCHECK(!username_.empty() && !password_.empty() &&
72      last_result_.data.empty());
73
74  client_login_.reset(new GaiaAuthFetcher(this,
75                                          GaiaConstants::kChromeSource,
76                                          profile_->GetRequestContext()));
77  client_login_->StartClientLogin(username_,
78                                  access_code,
79                                  "",
80                                  std::string(),
81                                  std::string(),
82                                  GaiaAuthFetcher::HostedAccountsNotAllowed);
83}
84
85void SigninManager::SignOut() {
86  if (!profile_)
87    return;
88
89  client_login_.reset();
90  last_result_ = ClientLoginResult();
91  username_.clear();
92  password_.clear();
93  had_two_factor_error_ = false;
94  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
95  profile_->GetPrefs()->ScheduleSavePersistentPrefs();
96  profile_->GetTokenService()->ResetCredentialsInMemory();
97  profile_->GetTokenService()->EraseTokensFromDB();
98}
99
100void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
101  last_result_ = result;
102  // Make a request for the canonical email address.
103  client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey);
104}
105
106void SigninManager::OnGetUserInfoSuccess(const std::string& key,
107                                         const std::string& value) {
108  DCHECK(key == kGetInfoEmailKey);
109
110  username_ = value;
111  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
112  profile_->GetPrefs()->ScheduleSavePersistentPrefs();
113
114  GoogleServiceSigninSuccessDetails details(username_, password_);
115  NotificationService::current()->Notify(
116      NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
117      Source<Profile>(profile_),
118      Details<const GoogleServiceSigninSuccessDetails>(&details));
119
120  password_.clear();  // Don't need it anymore.
121
122  profile_->GetTokenService()->UpdateCredentials(last_result_);
123  DCHECK(profile_->GetTokenService()->AreCredentialsValid());
124  profile_->GetTokenService()->StartFetchingTokens();
125}
126
127void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
128  DCHECK(key == kGetInfoEmailKey);
129  LOG(ERROR) << "Account is not associated with a valid email address. "
130             << "Login failed.";
131  OnClientLoginFailure(GoogleServiceAuthError(
132      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
133}
134
135void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
136  LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
137  OnClientLoginFailure(error);
138}
139
140void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
141  NotificationService::current()->Notify(
142      NotificationType::GOOGLE_SIGNIN_FAILED,
143      Source<Profile>(profile_),
144      Details<const GoogleServiceAuthError>(&error));
145
146  // We don't sign-out if the password was valid and we're just dealing with
147  // a second factor error, and we don't sign out if we're dealing with
148  // an invalid access code (again, because the password was valid).
149  bool invalid_gaia = error.state() ==
150      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
151  if (error.state() == GoogleServiceAuthError::TWO_FACTOR ||
152      (had_two_factor_error_ && invalid_gaia)) {
153    had_two_factor_error_ = true;
154    return;
155  }
156
157  SignOut();
158}
159