Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: chrome/browser/sync/signin_manager.cc

Issue 7497069: Support Sync following Gaia OAuth authentication (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: clean-up Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/signin_manager.h" 5 #include "chrome/browser/sync/signin_manager.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "chrome/browser/net/gaia/token_service.h" 9 #include "chrome/browser/net/gaia/token_service.h"
10 #include "chrome/browser/prefs/pref_service.h" 10 #include "chrome/browser/prefs/pref_service.h"
11 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/sync/profile_sync_service.h" 12 #include "chrome/browser/sync/profile_sync_service.h"
13 #include "chrome/browser/sync/util/oauth.h"
13 #include "chrome/common/chrome_notification_types.h" 14 #include "chrome/common/chrome_notification_types.h"
15 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/net/gaia/gaia_constants.h" 16 #include "chrome/common/net/gaia/gaia_constants.h"
15 #include "chrome/common/pref_names.h" 17 #include "chrome/common/pref_names.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "content/common/notification_service.h" 18 #include "content/common/notification_service.h"
18 19
19 const char kGetInfoEmailKey[] = "email"; 20 const char kGetInfoEmailKey[] = "email";
20 21
21 SigninManager::SigninManager() 22 SigninManager::SigninManager()
22 : profile_(NULL), had_two_factor_error_(false) {} 23 : profile_(NULL), had_two_factor_error_(false) {}
23 24
24 SigninManager::~SigninManager() {} 25 SigninManager::~SigninManager() {}
25 26
26 // static 27 // static
27 void SigninManager::RegisterUserPrefs(PrefService* user_prefs) { 28 void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
28 user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, 29 user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername,
29 "", 30 "",
30 PrefService::UNSYNCABLE_PREF); 31 PrefService::UNSYNCABLE_PREF);
31 user_prefs->RegisterBooleanPref(prefs::kAutologinEnabled, 32 user_prefs->RegisterBooleanPref(prefs::kAutologinEnabled,
32 true, 33 true,
33 PrefService::UNSYNCABLE_PREF); 34 PrefService::UNSYNCABLE_PREF);
34 } 35 }
35 36
36 void SigninManager::Initialize(Profile* profile) { 37 void SigninManager::Initialize(Profile* profile) {
37 profile_ = profile; 38 profile_ = profile;
38 username_ = profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername); 39 SetUsername(profile_->GetPrefs()->GetString(prefs::kGoogleServicesUsername));
39 profile_->GetTokenService()->Initialize( 40 profile_->GetTokenService()->Initialize(
40 GaiaConstants::kChromeSource, profile_); 41 GaiaConstants::kChromeSource, profile_);
41 if (!username_.empty()) { 42 if (!GetUsername().empty()) {
42 profile_->GetTokenService()->LoadTokensFromDB(); 43 profile_->GetTokenService()->LoadTokensFromDB();
43 } 44 }
44 } 45 }
45 46
46 bool SigninManager::IsInitialized() const { 47 bool SigninManager::IsInitialized() const {
47 return profile_ != NULL; 48 return profile_ != NULL;
48 } 49 }
49 50
50 void SigninManager::CleanupNotificationRegistration() { 51 void SigninManager::CleanupNotificationRegistration() {
51 #if !defined(OS_CHROMEOS) 52 #if !defined(OS_CHROMEOS)
52 Source<TokenService> token_service(profile_->GetTokenService()); 53 Source<TokenService> token_service(profile_->GetTokenService());
53 if (registrar_.IsRegistered(this, 54 if (registrar_.IsRegistered(this,
54 chrome::NOTIFICATION_TOKEN_AVAILABLE, 55 chrome::NOTIFICATION_TOKEN_AVAILABLE,
55 token_service)) { 56 token_service)) {
56 registrar_.Remove(this, 57 registrar_.Remove(this,
57 chrome::NOTIFICATION_TOKEN_AVAILABLE, 58 chrome::NOTIFICATION_TOKEN_AVAILABLE,
58 token_service); 59 token_service);
59 } 60 }
60 #endif 61 #endif
61 } 62 }
62 63
63 // If a username already exists, the user is logged in. 64 // If a username already exists, the user is logged in.
64 const std::string& SigninManager::GetUsername() { 65 const std::string& SigninManager::GetUsername() {
65 return username_; 66 return browser_sync::IsUsingOAuth() ? oauth_username_ : username_;
66 } 67 }
67 68
68 void SigninManager::SetUsername(const std::string& username) { 69 void SigninManager::SetUsername(const std::string& username) {
69 username_ = username; 70 if (browser_sync::IsUsingOAuth())
71 oauth_username_ = username;
72 else
73 username_ = username;
70 } 74 }
71 75
72 // static 76 // static
73 void SigninManager::PrepareForSignin() { 77 void SigninManager::PrepareForSignin() {
74 DCHECK(username_.empty()); 78 DCHECK(username_.empty());
75 #if !defined(OS_CHROMEOS) 79 #if !defined(OS_CHROMEOS)
76 // The Sign out should clear the token service credentials. 80 // The Sign out should clear the token service credentials.
77 // Note: In CHROMEOS we might have valid credentials but still need to 81 // Note: In CHROMEOS we might have valid credentials but still need to
78 // set up 2-factor authentication. 82 // set up 2-factor authentication.
79 DCHECK(!profile_->GetTokenService()->AreCredentialsValid()); 83 DCHECK(!profile_->GetTokenService()->AreCredentialsValid());
80 #endif 84 #endif
81 } 85 }
82 86
87 // static
88 void SigninManager::PrepareForOAuthSignin() {
89 DCHECK(oauth_username_.empty());
90 #if !defined(OS_CHROMEOS)
91 // The Sign out should clear the token service credentials.
92 // Note: In CHROMEOS we might have valid credentials but still need to
93 // set up 2-factor authentication.
94 DCHECK(!profile_->GetTokenService()->AreOAuthCredentialsValid());
95 #endif
96 }
97
83 // Users must always sign out before they sign in again. 98 // Users must always sign out before they sign in again.
84 void SigninManager::StartOAuthSignIn() { 99 void SigninManager::StartOAuthSignIn() {
85 PrepareForSignin(); 100 PrepareForOAuthSignin();
86 oauth_login_.reset(new GaiaOAuthFetcher(this, 101 oauth_login_.reset(new GaiaOAuthFetcher(this,
87 profile_->GetRequestContext(), 102 profile_->GetRequestContext(),
88 profile_, 103 profile_,
89 GaiaConstants::kSyncServiceOAuth)); 104 GaiaConstants::kSyncServiceOAuth));
90 oauth_login_->StartGetOAuthToken(); 105 oauth_login_->StartGetOAuthToken();
106 // TODO(rogerta?): Bug 92325: Expand Autologin to include OAuth signin
91 } 107 }
92 108
93 // Users must always sign out before they sign in again. 109 // Users must always sign out before they sign in again.
94 void SigninManager::StartSignIn(const std::string& username, 110 void SigninManager::StartSignIn(const std::string& username,
95 const std::string& password, 111 const std::string& password,
96 const std::string& login_token, 112 const std::string& login_token,
97 const std::string& login_captcha) { 113 const std::string& login_captcha) {
98 PrepareForSignin(); 114 PrepareForSignin();
99 username_.assign(username); 115 username_.assign(username);
100 password_.assign(password); 116 password_.assign(password);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 155
140 void SigninManager::SignOut() { 156 void SigninManager::SignOut() {
141 if (!profile_) 157 if (!profile_)
142 return; 158 return;
143 159
144 CleanupNotificationRegistration(); 160 CleanupNotificationRegistration();
145 161
146 client_login_.reset(); 162 client_login_.reset();
147 last_result_ = ClientLoginResult(); 163 last_result_ = ClientLoginResult();
148 username_.clear(); 164 username_.clear();
165 oauth_username_.clear();
149 password_.clear(); 166 password_.clear();
150 had_two_factor_error_ = false; 167 had_two_factor_error_ = false;
151 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_); 168 profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
169 profile_->GetPrefs()->ClearPref(prefs::kSyncUsingOAuth);
152 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); 170 profile_->GetPrefs()->ScheduleSavePersistentPrefs();
153 profile_->GetTokenService()->ResetCredentialsInMemory(); 171 profile_->GetTokenService()->ResetCredentialsInMemory();
154 profile_->GetTokenService()->EraseTokensFromDB(); 172 profile_->GetTokenService()->EraseTokensFromDB();
155 } 173 }
156 174
157 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) { 175 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
176 DCHECK(!browser_sync::IsUsingOAuth());
158 last_result_ = result; 177 last_result_ = result;
159 // Make a request for the canonical email address. 178 // Make a request for the canonical email address.
160 client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey); 179 client_login_->StartGetUserInfo(result.lsid, kGetInfoEmailKey);
161 } 180 }
162 181
182 // NOTE: GetUserInfo is a ClientLogin request similar to OAuth's userinfo
163 void SigninManager::OnGetUserInfoSuccess(const std::string& key, 183 void SigninManager::OnGetUserInfoSuccess(const std::string& key,
164 const std::string& value) { 184 const std::string& value) {
185 DCHECK(!browser_sync::IsUsingOAuth());
165 DCHECK(key == kGetInfoEmailKey); 186 DCHECK(key == kGetInfoEmailKey);
166 187
167 username_ = value; 188 username_ = value;
168 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_); 189 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
190 profile_->GetPrefs()->SetBoolean(prefs::kSyncUsingOAuth, false);
169 profile_->GetPrefs()->ScheduleSavePersistentPrefs(); 191 profile_->GetPrefs()->ScheduleSavePersistentPrefs();
170 192
171 GoogleServiceSigninSuccessDetails details(username_, password_); 193 GoogleServiceSigninSuccessDetails details(username_, password_);
172 NotificationService::current()->Notify( 194 NotificationService::current()->Notify(
173 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, 195 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
174 Source<Profile>(profile_), 196 Source<Profile>(profile_),
175 Details<const GoogleServiceSigninSuccessDetails>(&details)); 197 Details<const GoogleServiceSigninSuccessDetails>(&details));
176 198
177 password_.clear(); // Don't need it anymore. 199 password_.clear(); // Don't need it anymore.
178 200
179 profile_->GetTokenService()->UpdateCredentials(last_result_); 201 profile_->GetTokenService()->UpdateCredentials(last_result_);
180 DCHECK(profile_->GetTokenService()->AreCredentialsValid()); 202 DCHECK(profile_->GetTokenService()->AreCredentialsValid());
181 profile_->GetTokenService()->StartFetchingTokens(); 203 profile_->GetTokenService()->StartFetchingTokens();
182 } 204 }
183 205
184 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) { 206 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
207 DCHECK(!browser_sync::IsUsingOAuth());
185 DCHECK(key == kGetInfoEmailKey); 208 DCHECK(key == kGetInfoEmailKey);
186 LOG(ERROR) << "Account is not associated with a valid email address. " 209 LOG(ERROR) << "Account is not associated with a valid email address. "
187 << "Login failed."; 210 << "Login failed.";
188 OnClientLoginFailure(GoogleServiceAuthError( 211 OnClientLoginFailure(GoogleServiceAuthError(
189 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 212 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
190 } 213 }
191 214
192 void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) { 215 void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
216 DCHECK(!browser_sync::IsUsingOAuth());
193 LOG(ERROR) << "Unable to retreive the canonical email address. Login failed."; 217 LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
194 OnClientLoginFailure(error); 218 OnClientLoginFailure(error);
195 } 219 }
196 220
197 void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) { 221 void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) {
222 DCHECK(!browser_sync::IsUsingOAuth());
198 #if !defined(OS_CHROMEOS) 223 #if !defined(OS_CHROMEOS)
199 VLOG(1) << "Unable to retrieve the token auth."; 224 VLOG(1) << "Unable to retrieve the token auth.";
200 CleanupNotificationRegistration(); 225 CleanupNotificationRegistration();
201 #endif 226 #endif
202 } 227 }
203 228
204 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) { 229 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
230 DCHECK(!browser_sync::IsUsingOAuth());
205 NotificationService::current()->Notify( 231 NotificationService::current()->Notify(
206 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED, 232 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
207 Source<Profile>(profile_), 233 Source<Profile>(profile_),
208 Details<const GoogleServiceAuthError>(&error)); 234 Details<const GoogleServiceAuthError>(&error));
209 235
210 // We don't sign-out if the password was valid and we're just dealing with 236 // We don't sign-out if the password was valid and we're just dealing with
211 // a second factor error, and we don't sign out if we're dealing with 237 // a second factor error, and we don't sign out if we're dealing with
212 // an invalid access code (again, because the password was valid). 238 // an invalid access code (again, because the password was valid).
213 bool invalid_gaia = error.state() == 239 bool invalid_gaia = error.state() ==
214 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS; 240 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
215 if (error.state() == GoogleServiceAuthError::TWO_FACTOR || 241 if (error.state() == GoogleServiceAuthError::TWO_FACTOR ||
216 (had_two_factor_error_ && invalid_gaia)) { 242 (had_two_factor_error_ && invalid_gaia)) {
217 had_two_factor_error_ = true; 243 had_two_factor_error_ = true;
218 return; 244 return;
219 } 245 }
220 246
221 SignOut(); 247 SignOut();
222 } 248 }
223 249
224 void SigninManager::OnGetOAuthTokenSuccess(const std::string& oauth_token) { 250 void SigninManager::OnGetOAuthTokenSuccess(const std::string& oauth_token) {
251 DCHECK(browser_sync::IsUsingOAuth());
225 VLOG(1) << "SigninManager::SigninManager::OnGetOAuthTokenSuccess"; 252 VLOG(1) << "SigninManager::SigninManager::OnGetOAuthTokenSuccess";
226 } 253 }
227 254
228 void SigninManager::OnGetOAuthTokenFailure() { 255 void SigninManager::OnGetOAuthTokenFailure() {
229 VLOG(1) << "SigninManager::OnGetOAuthTokenFailure"; 256 DCHECK(browser_sync::IsUsingOAuth());
257 LOG(WARNING) << "SigninManager::OnGetOAuthTokenFailure";
230 } 258 }
231 259
232 void SigninManager::OnOAuthGetAccessTokenSuccess(const std::string& token, 260 void SigninManager::OnOAuthGetAccessTokenSuccess(const std::string& token,
233 const std::string& secret) { 261 const std::string& secret) {
262 DCHECK(browser_sync::IsUsingOAuth());
234 VLOG(1) << "SigninManager::OnOAuthGetAccessTokenSuccess"; 263 VLOG(1) << "SigninManager::OnOAuthGetAccessTokenSuccess";
264 profile_->GetTokenService()->UpdateOAuthCredentials(token, secret);
235 } 265 }
236 266
237 void SigninManager::OnOAuthGetAccessTokenFailure( 267 void SigninManager::OnOAuthGetAccessTokenFailure(
238 const GoogleServiceAuthError& error) { 268 const GoogleServiceAuthError& error) {
239 VLOG(1) << "SigninManager::OnOAuthGetAccessTokenFailure"; 269 DCHECK(browser_sync::IsUsingOAuth());
270 LOG(WARNING) << "SigninManager::OnOAuthGetAccessTokenFailure";
240 } 271 }
241 272
242 void SigninManager::OnOAuthWrapBridgeSuccess(const std::string& service_name, 273 void SigninManager::OnOAuthWrapBridgeSuccess(const std::string& service_name,
243 const std::string& token, 274 const std::string& token,
244 const std::string& expires_in) { 275 const std::string& expires_in) {
276 DCHECK(browser_sync::IsUsingOAuth());
245 VLOG(1) << "SigninManager::OnOAuthWrapBridgeSuccess"; 277 VLOG(1) << "SigninManager::OnOAuthWrapBridgeSuccess";
246 } 278 }
247 279
248 void SigninManager::OnOAuthWrapBridgeFailure( 280 void SigninManager::OnOAuthWrapBridgeFailure(
249 const std::string& service_scope, 281 const std::string& service_scope,
250 const GoogleServiceAuthError& error) { 282 const GoogleServiceAuthError& error) {
251 VLOG(1) << "SigninManager::OnOAuthWrapBridgeFailure"; 283 DCHECK(browser_sync::IsUsingOAuth());
284 LOG(WARNING) << "SigninManager::OnOAuthWrapBridgeFailure";
252 } 285 }
253 286
287 // NOTE: userinfo is an OAuth request similar to ClientLogin's GetUserInfo
254 void SigninManager::OnUserInfoSuccess(const std::string& email) { 288 void SigninManager::OnUserInfoSuccess(const std::string& email) {
255 VLOG(1) << "SigninManager::OnUserInfoSuccess(\"" << email << "\")"; 289 DCHECK(browser_sync::IsUsingOAuth());
290 VLOG(1) << "Sync signin for " << email << " is complete.";
291 oauth_username_ = email;
292 profile_->GetPrefs()->SetString(
293 prefs::kGoogleServicesUsername, oauth_username_);
294 profile_->GetPrefs()->SetBoolean(prefs::kSyncUsingOAuth, true);
295 profile_->GetPrefs()->ScheduleSavePersistentPrefs();
296
297 DCHECK(password_.empty());
298 GoogleServiceSigninSuccessDetails details(oauth_username_, "");
299 NotificationService::current()->Notify(
300 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
301 Source<Profile>(profile_),
302 Details<const GoogleServiceSigninSuccessDetails>(&details));
303
304 DCHECK(profile_->GetTokenService()->AreOAuthCredentialsValid());
305 profile_->GetTokenService()->StartFetchingOAuthTokens();
256 } 306 }
257 307
258 void SigninManager::OnUserInfoFailure(const GoogleServiceAuthError& error) { 308 void SigninManager::OnUserInfoFailure(const GoogleServiceAuthError& error) {
259 VLOG(1) << "SigninManager::OnUserInfoFailure"; 309 DCHECK(browser_sync::IsUsingOAuth());
310 LOG(WARNING) << "SigninManager::OnUserInfoFailure";
260 } 311 }
261 312
262 void SigninManager::Observe(int type, 313 void SigninManager::Observe(int type,
263 const NotificationSource& source, 314 const NotificationSource& source,
264 const NotificationDetails& details) { 315 const NotificationDetails& details) {
265 #if !defined(OS_CHROMEOS) 316 #if !defined(OS_CHROMEOS)
266 DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE); 317 DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
267 TokenService::TokenAvailableDetails* tok_details = 318 TokenService::TokenAvailableDetails* tok_details =
268 Details<TokenService::TokenAvailableDetails>(details).ptr(); 319 Details<TokenService::TokenAvailableDetails>(details).ptr();
269 320
270 // If a GAIA service token has become available, use it to pre-login the 321 // If a GAIA service token has become available, use it to pre-login the
271 // user to other services that depend on GAIA credentials. 322 // user to other services that depend on GAIA credentials.
272 if (tok_details->service() == GaiaConstants::kGaiaService) { 323 if (tok_details->service() == GaiaConstants::kGaiaService) {
273 if (client_login_.get() == NULL) { 324 if (client_login_.get() == NULL) {
274 client_login_.reset(new GaiaAuthFetcher(this, 325 client_login_.reset(new GaiaAuthFetcher(this,
275 GaiaConstants::kChromeSource, 326 GaiaConstants::kChromeSource,
276 profile_->GetRequestContext())); 327 profile_->GetRequestContext()));
277 } 328 }
278 329
279 client_login_->StartTokenAuth(tok_details->token()); 330 client_login_->StartTokenAuth(tok_details->token());
280 331
281 // We only want to do this once per sign-in. 332 // We only want to do this once per sign-in.
282 CleanupNotificationRegistration(); 333 CleanupNotificationRegistration();
283 } 334 }
284 #endif 335 #endif
285 } 336 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698