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

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

Powered by Google App Engine
This is Rietveld 408576698