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

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

Issue 9466022: Changes to the sign in manager in preparation for one-click sign in. This CL (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Merge after sync, no new changes Created 8 years, 9 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/signin/signin_manager.h" 5 #include "chrome/browser/signin/signin_manager.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/string_split.h" 11 #include "base/string_split.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "chrome/browser/prefs/pref_service.h" 13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/signin/token_service.h" 15 #include "chrome/browser/signin/token_service.h"
16 #include "chrome/browser/sync/profile_sync_service.h" 16 #include "chrome/browser/sync/profile_sync_service.h"
17 #include "chrome/common/chrome_notification_types.h" 17 #include "chrome/common/chrome_notification_types.h"
18 #include "chrome/common/chrome_switches.h" 18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/common/net/gaia/gaia_constants.h" 19 #include "chrome/common/net/gaia/gaia_constants.h"
20 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
21 #include "content/public/browser/notification_service.h" 21 #include "content/public/browser/notification_service.h"
22 #include "net/base/cookie_monster.h"
22 23
23 const char kGetInfoEmailKey[] = "email"; 24 const char kGetInfoEmailKey[] = "email";
24 const char kGetInfoServicesKey[] = "allServices"; 25 const char kGetInfoServicesKey[] = "allServices";
25 const char kGooglePlusServiceKey[] = "googleme"; 26 const char kGooglePlusServiceKey[] = "googleme";
26 27
27 SigninManager::SigninManager() 28 SigninManager::SigninManager()
28 : profile_(NULL), 29 : profile_(NULL),
29 had_two_factor_error_(false), 30 had_two_factor_error_(false),
30 last_login_auth_error_(GoogleServiceAuthError::None()) { 31 last_login_auth_error_(GoogleServiceAuthError::None()) {
31 } 32 }
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 GaiaConstants::kChromeSource, 136 GaiaConstants::kChromeSource,
136 profile_->GetRequestContext())); 137 profile_->GetRequestContext()));
137 client_login_->StartClientLogin(possibly_invalid_username_, 138 client_login_->StartClientLogin(possibly_invalid_username_,
138 access_code, 139 access_code,
139 "", 140 "",
140 std::string(), 141 std::string(),
141 std::string(), 142 std::string(),
142 GaiaAuthFetcher::HostedAccountsNotAllowed); 143 GaiaAuthFetcher::HostedAccountsNotAllowed);
143 } 144 }
144 145
146 void SigninManager::StartSignInWithCredentials(const std::string& username,
147 const std::string& password) {
148 DCHECK(authenticated_username_.empty());
149 PrepareForSignin();
150 possibly_invalid_username_.assign(username);
151 password_.assign(password);
152
153 client_login_.reset(new GaiaAuthFetcher(this,
154 GaiaConstants::kChromeSource,
155 profile_->GetRequestContext()));
156
157 // This function starts with the current state of the web session's cookie
158 // jar and mints a new ClientLogin-style SID/LSID pair. This involves going
159 // throug the follow process or requests to GAIA and LSO:
160 //
161 // - call /o/oauth2/programmatic_auth with the returned token to get oauth2
162 // access and refresh tokens
163 // - call /accounts/OAuthLogin with the oauth2 access token and get an uber
164 // auth token
165 // - call /TokenAuth with the uber auth token to get a SID/LSID pair for use
166 // by the token service
167 //
168 // The resulting SID/LSID can then be used just as if
169 // client_login_->StartClientLogin() had completed successfully.
170 client_login_->StartOAuthLoginTokenFetch("");
171 }
172
145 void SigninManager::ClearTransientSigninData() { 173 void SigninManager::ClearTransientSigninData() {
146 DCHECK(IsInitialized()); 174 DCHECK(IsInitialized());
147 175
148 CleanupNotificationRegistration(); 176 CleanupNotificationRegistration();
149 client_login_.reset(); 177 client_login_.reset();
150 last_result_ = ClientLoginResult(); 178 last_result_ = ClientLoginResult();
151 possibly_invalid_username_.clear(); 179 possibly_invalid_username_.clear();
152 password_.clear(); 180 password_.clear();
153 had_two_factor_error_ = false; 181 had_two_factor_error_ = false;
154 } 182 }
155 183
184 void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) {
185 last_login_auth_error_ = error;
186 content::NotificationService::current()->Notify(
187 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
188 content::Source<Profile>(profile_),
189 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_));
190
191 ClearTransientSigninData();
192 }
193
156 void SigninManager::SignOut() { 194 void SigninManager::SignOut() {
157 DCHECK(IsInitialized()); 195 DCHECK(IsInitialized());
158 if (authenticated_username_.empty() && !client_login_.get()) { 196 if (authenticated_username_.empty() && !client_login_.get()) {
159 // Just exit if we aren't signed in (or in the process of signing in). 197 // Just exit if we aren't signed in (or in the process of signing in).
160 // This avoids a perf regression because SignOut() is invoked on startup to 198 // This avoids a perf regression because SignOut() is invoked on startup to
161 // clean up any incomplete previous signin attempts. 199 // clean up any incomplete previous signin attempts.
162 return; 200 return;
163 } 201 }
164 202
165 ClearTransientSigninData(); 203 ClearTransientSigninData();
166 authenticated_username_.clear(); 204 authenticated_username_.clear();
167 profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername); 205 profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
168 profile_->GetPrefs()->ClearPref(prefs::kIsGooglePlusUser); 206 profile_->GetPrefs()->ClearPref(prefs::kIsGooglePlusUser);
169 profile_->GetTokenService()->ResetCredentialsInMemory(); 207 profile_->GetTokenService()->ResetCredentialsInMemory();
170 profile_->GetTokenService()->EraseTokensFromDB(); 208 profile_->GetTokenService()->EraseTokensFromDB();
171 } 209 }
172 210
173 const GoogleServiceAuthError& SigninManager::GetLoginAuthError() const { 211 const GoogleServiceAuthError& SigninManager::GetLoginAuthError() const {
174 return last_login_auth_error_; 212 return last_login_auth_error_;
175 } 213 }
176 214
177 bool SigninManager::AuthInProgress() const { 215 bool SigninManager::AuthInProgress() const {
178 return !possibly_invalid_username_.empty(); 216 return !possibly_invalid_username_.empty();
179 } 217 }
180 218
219 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
220 DCHECK(key == kGetInfoEmailKey);
221 LOG(ERROR) << "Account is not associated with a valid email address. "
222 << "Login failed.";
223 OnClientLoginFailure(GoogleServiceAuthError(
224 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
225 }
226
181 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) { 227 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
182 last_result_ = result; 228 last_result_ = result;
183 // Make a request for the canonical email address and services. 229 // Make a request for the canonical email address and services.
184 client_login_->StartGetUserInfo(result.lsid); 230 client_login_->StartGetUserInfo(result.lsid);
185 } 231 }
186 232
233 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
234 // If we got a bad ASP, prompt for an ASP again by forcing another TWO_FACTOR
235 // error.
236 bool invalid_gaia = error.state() ==
237 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
Andrew T Wilson (Slow) 2012/03/02 19:22:33 Probably worth documenting why we are not calling
Roger Tawa OOO till Jul 10th 2012/03/02 20:10:58 Done.
238 last_login_auth_error_ = (invalid_gaia && had_two_factor_error_) ?
239 GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR) : error;
240 content::NotificationService::current()->Notify(
241 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
242 content::Source<Profile>(profile_),
243 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_));
244
245 // We don't sign-out if the password was valid and we're just dealing with
246 // a second factor error, and we don't sign out if we're dealing with
247 // an invalid access code (again, because the password was valid).
248 if (last_login_auth_error_.state() == GoogleServiceAuthError::TWO_FACTOR) {
249 had_two_factor_error_ = true;
250 return;
251 }
252
253 ClearTransientSigninData();
254 }
255
256 void SigninManager::OnOAuthLoginTokenSuccess(const std::string& refresh_token,
257 const std::string& access_token,
258 int expires_in_secs) {
259 DVLOG(1) << "SigninManager::OnOAuthLoginTokenSuccess access_token="
260 << access_token;
261 client_login_->StartUberAuthTokenFetch(access_token);
262 }
263
264 void SigninManager::OnOAuthLoginTokenFailure(
265 const GoogleServiceAuthError& error) {
266 LOG(WARNING) << "SigninManager::OnOAuthLoginTokenFailure";
267 HandleAuthError(error);
268 }
269
187 void SigninManager::OnGetUserInfoSuccess(const UserInfoMap& data) { 270 void SigninManager::OnGetUserInfoSuccess(const UserInfoMap& data) {
188 UserInfoMap::const_iterator email_iter = data.find(kGetInfoEmailKey); 271 UserInfoMap::const_iterator email_iter = data.find(kGetInfoEmailKey);
189 if (email_iter == data.end()) { 272 if (email_iter == data.end()) {
190 OnGetUserInfoKeyNotFound(kGetInfoEmailKey); 273 OnGetUserInfoKeyNotFound(kGetInfoEmailKey);
191 return; 274 return;
192 } else { 275 } else {
193 DCHECK(email_iter->first == kGetInfoEmailKey); 276 DCHECK(email_iter->first == kGetInfoEmailKey);
194 last_login_auth_error_ = GoogleServiceAuthError::None(); 277 last_login_auth_error_ = GoogleServiceAuthError::None();
195 SetAuthenticatedUsername(email_iter->second); 278 SetAuthenticatedUsername(email_iter->second);
196 possibly_invalid_username_.clear(); 279 possibly_invalid_username_.clear();
(...skipping 21 matching lines...) Expand all
218 content::Source<Profile>(profile_), 301 content::Source<Profile>(profile_),
219 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); 302 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
220 303
221 password_.clear(); // Don't need it anymore. 304 password_.clear(); // Don't need it anymore.
222 305
223 profile_->GetTokenService()->UpdateCredentials(last_result_); 306 profile_->GetTokenService()->UpdateCredentials(last_result_);
224 DCHECK(profile_->GetTokenService()->AreCredentialsValid()); 307 DCHECK(profile_->GetTokenService()->AreCredentialsValid());
225 profile_->GetTokenService()->StartFetchingTokens(); 308 profile_->GetTokenService()->StartFetchingTokens();
226 } 309 }
227 310
228 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
229 DCHECK(key == kGetInfoEmailKey);
230 LOG(ERROR) << "Account is not associated with a valid email address. "
231 << "Login failed.";
232 OnClientLoginFailure(GoogleServiceAuthError(
233 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
234 }
235
236 void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) { 311 void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
237 LOG(ERROR) << "Unable to retreive the canonical email address. Login failed."; 312 LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
313 // REVIEW: why does this call OnClientLoginFailure?
Andrew T Wilson (Slow) 2012/03/02 19:22:33 Hmmm. I'm guessing to make sure the SIGNIN_FAILED
238 OnClientLoginFailure(error); 314 OnClientLoginFailure(error);
239 } 315 }
240 316
241 void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) { 317 void SigninManager::OnTokenAuthSuccess(const net::ResponseCookies& cookies,
242 #if !defined(OS_CHROMEOS) 318 const std::string& data) {
243 DVLOG(1) << "Unable to retrieve the token auth."; 319 DVLOG(1) << "SigninManager::OnTokenAuthSuccess";
244 CleanupNotificationRegistration(); 320
245 #endif 321 // The SID and LSID from this request is equivalent the pair returned by
322 // ClientLogin.
323 std::string sid;
324 std::string lsid;
325 for (net::ResponseCookies::const_iterator i = cookies.begin();
326 i != cookies.end(); ++i) {
327 net::CookieMonster::ParsedCookie parsed(*i);
328 if (parsed.Name() == "SID") {
329 sid = parsed.Value();
330 } else if (parsed.Name() == "LSID") {
331 lsid = parsed.Value();
332 }
333 }
334
335 if (!sid.empty() && !lsid.empty()) {
336 OnClientLoginSuccess(
337 GaiaAuthConsumer::ClientLoginResult(sid, lsid, "", data));
338 } else {
339 OnTokenAuthFailure(
340 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
341 }
246 } 342 }
247 343
248 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) { 344 void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) {
249 // If we got a bad ASP, prompt for an ASP again by forcing another TWO_FACTOR 345 DVLOG(1) << "Unable to retrieve the token auth.";
250 // error. 346 HandleAuthError(error);
251 bool invalid_gaia = error.state() == 347 }
252 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
253 last_login_auth_error_ = (invalid_gaia && had_two_factor_error_) ?
254 GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR) : error;
255 content::NotificationService::current()->Notify(
256 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
257 content::Source<Profile>(profile_),
258 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_));
259 348
260 // We don't sign-out if the password was valid and we're just dealing with 349 void SigninManager::OnUberAuthTokenSuccess(const std::string& token) {
261 // a second factor error, and we don't sign out if we're dealing with 350 DVLOG(1) << "SigninManager::OnUberAuthTokenSuccess token=" << token;
262 // an invalid access code (again, because the password was valid). 351 client_login_->StartTokenAuth(token);
263 if (last_login_auth_error_.state() == GoogleServiceAuthError::TWO_FACTOR) { 352 }
264 had_two_factor_error_ = true;
265 return;
266 }
267 353
268 ClearTransientSigninData(); 354 void SigninManager::OnUberAuthTokenFailure(
355 const GoogleServiceAuthError& error) {
356 LOG(WARNING) << "SigninManager::OnUberAuthTokenFailure";
357 HandleAuthError(error);
269 } 358 }
270 359
271 void SigninManager::Observe(int type, 360 void SigninManager::Observe(int type,
272 const content::NotificationSource& source, 361 const content::NotificationSource& source,
273 const content::NotificationDetails& details) { 362 const content::NotificationDetails& details) {
274 #if !defined(OS_CHROMEOS) 363 #if !defined(OS_CHROMEOS)
275 DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE); 364 DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
276 TokenService::TokenAvailableDetails* tok_details = 365 TokenService::TokenAvailableDetails* tok_details =
277 content::Details<TokenService::TokenAvailableDetails>(details).ptr(); 366 content::Details<TokenService::TokenAvailableDetails>(details).ptr();
278 367
279 // If a GAIA service token has become available, use it to pre-login the 368 // If a GAIA service token has become available, use it to pre-login the
280 // user to other services that depend on GAIA credentials. 369 // user to other services that depend on GAIA credentials.
281 if (tok_details->service() == GaiaConstants::kGaiaService) { 370 if (tok_details->service() == GaiaConstants::kGaiaService) {
282 if (client_login_.get() == NULL) { 371 if (client_login_.get() == NULL) {
283 client_login_.reset(new GaiaAuthFetcher(this, 372 client_login_.reset(new GaiaAuthFetcher(this,
284 GaiaConstants::kChromeSource, 373 GaiaConstants::kChromeSource,
285 profile_->GetRequestContext())); 374 profile_->GetRequestContext()));
286 } 375 }
287 376
288 client_login_->StartMergeSession(tok_details->token()); 377 client_login_->StartMergeSession(tok_details->token());
289 378
290 // We only want to do this once per sign-in. 379 // We only want to do this once per sign-in.
291 CleanupNotificationRegistration(); 380 CleanupNotificationRegistration();
292 } 381 }
293 #endif 382 #endif
294 } 383 }
OLDNEW
« no previous file with comments | « chrome/browser/signin/signin_manager.h ('k') | chrome/browser/signin/signin_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698