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

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: Created 8 years, 10 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 }
(...skipping 16 matching lines...) Expand all
171 } 199 }
172 200
173 const GoogleServiceAuthError& SigninManager::GetLoginAuthError() const { 201 const GoogleServiceAuthError& SigninManager::GetLoginAuthError() const {
174 return last_login_auth_error_; 202 return last_login_auth_error_;
175 } 203 }
176 204
177 bool SigninManager::AuthInProgress() const { 205 bool SigninManager::AuthInProgress() const {
178 return !possibly_invalid_username_.empty(); 206 return !possibly_invalid_username_.empty();
179 } 207 }
180 208
209 void SigninManager::OnGetUserInfoKeyNotFound(const std::string& key) {
210 DCHECK(key == kGetInfoEmailKey);
211 LOG(ERROR) << "Account is not associated with a valid email address. "
212 << "Login failed.";
213 OnClientLoginFailure(GoogleServiceAuthError(
214 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
215 }
216
181 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) { 217 void SigninManager::OnClientLoginSuccess(const ClientLoginResult& result) {
182 last_result_ = result; 218 last_result_ = result;
183 // Make a request for the canonical email address and services. 219 // Make a request for the canonical email address and services.
184 client_login_->StartGetUserInfo(result.lsid); 220 client_login_->StartGetUserInfo(result.lsid);
185 } 221 }
186 222
223 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
Andrew T Wilson (Slow) 2012/02/27 19:00:10 nit: my preference is not to move functions around
Roger Tawa OOO till Jul 10th 2012/02/29 21:02:54 OK Drew, will do that net time. I moved them arou
224 // If we got a bad ASP, prompt for an ASP again by forcing another TWO_FACTOR
225 // error.
226 bool invalid_gaia = error.state() ==
227 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
228 last_login_auth_error_ = (invalid_gaia && had_two_factor_error_) ?
229 GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR) : error;
230 content::NotificationService::current()->Notify(
231 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
232 content::Source<Profile>(profile_),
233 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_));
234
235 // We don't sign-out if the password was valid and we're just dealing with
236 // a second factor error, and we don't sign out if we're dealing with
237 // an invalid access code (again, because the password was valid).
238 if (last_login_auth_error_.state() == GoogleServiceAuthError::TWO_FACTOR) {
239 had_two_factor_error_ = true;
240 return;
241 }
242
243 ClearTransientSigninData();
244 }
245
246 void SigninManager::OnOAuthLoginTokenSuccess(const std::string& refresh_token,
247 const std::string& access_token,
248 int expires_in_secs) {
249 DVLOG(1) << "SigninManager::OnOAuthLoginTokenSuccess access_token="
250 << access_token;
251 client_login_->StartUberAuthTokenFetch(access_token);
252 }
253
254 void SigninManager::OnOAuthLoginTokenFailure(
255 const GoogleServiceAuthError& error) {
256 LOG(WARNING) << "SigninManager::OnOAuthLoginTokenFailure";
257 last_login_auth_error_ = error;
258 content::NotificationService::current()->Notify(
259 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
260 content::Source<Profile>(profile_),
261 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_));
262
263 ClearTransientSigninData();
264 }
265
187 void SigninManager::OnGetUserInfoSuccess(const UserInfoMap& data) { 266 void SigninManager::OnGetUserInfoSuccess(const UserInfoMap& data) {
188 UserInfoMap::const_iterator email_iter = data.find(kGetInfoEmailKey); 267 UserInfoMap::const_iterator email_iter = data.find(kGetInfoEmailKey);
189 if (email_iter == data.end()) { 268 if (email_iter == data.end()) {
190 OnGetUserInfoKeyNotFound(kGetInfoEmailKey); 269 OnGetUserInfoKeyNotFound(kGetInfoEmailKey);
191 return; 270 return;
192 } else { 271 } else {
193 DCHECK(email_iter->first == kGetInfoEmailKey); 272 DCHECK(email_iter->first == kGetInfoEmailKey);
194 last_login_auth_error_ = GoogleServiceAuthError::None(); 273 last_login_auth_error_ = GoogleServiceAuthError::None();
195 SetAuthenticatedUsername(email_iter->second); 274 SetAuthenticatedUsername(email_iter->second);
196 possibly_invalid_username_.clear(); 275 possibly_invalid_username_.clear();
(...skipping 21 matching lines...) Expand all
218 content::Source<Profile>(profile_), 297 content::Source<Profile>(profile_),
219 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); 298 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
220 299
221 password_.clear(); // Don't need it anymore. 300 password_.clear(); // Don't need it anymore.
222 301
223 profile_->GetTokenService()->UpdateCredentials(last_result_); 302 profile_->GetTokenService()->UpdateCredentials(last_result_);
224 DCHECK(profile_->GetTokenService()->AreCredentialsValid()); 303 DCHECK(profile_->GetTokenService()->AreCredentialsValid());
225 profile_->GetTokenService()->StartFetchingTokens(); 304 profile_->GetTokenService()->StartFetchingTokens();
226 } 305 }
227 306
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) { 307 void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
237 LOG(ERROR) << "Unable to retreive the canonical email address. Login failed."; 308 LOG(ERROR) << "Unable to retreive the canonical email address. Login failed.";
238 OnClientLoginFailure(error); 309 OnClientLoginFailure(error);
239 } 310 }
240 311
312 void SigninManager::OnTokenAuthSuccess(const net::ResponseCookies& cookies,
313 const std::string& data) {
314 DVLOG(1) << "SigninManager::OnTokenAuthSuccess";
315
316 // The SID and LSID from this request is equivalent the pair returned by
317 // ClientLogin.
318 std::string sid;
319 std::string lsid;
320 for (net::ResponseCookies::const_iterator i = cookies.begin();
321 i != cookies.end(); ++i) {
322 net::CookieMonster::ParsedCookie parsed(*i);
323 if (parsed.Name() == "SID") {
324 sid = parsed.Value();
325 } else if (parsed.Name() == "LSID") {
326 lsid = parsed.Value();
327 }
328 }
329
330 if (!sid.empty() && !lsid.empty()) {
331 OnClientLoginSuccess(
332 GaiaAuthConsumer::ClientLoginResult(sid, lsid, "", data));
333 } else {
334 OnTokenAuthFailure(
335 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
336 }
337 }
338
241 void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) { 339 void SigninManager::OnTokenAuthFailure(const GoogleServiceAuthError& error) {
242 #if !defined(OS_CHROMEOS)
Andrew T Wilson (Slow) 2012/02/27 19:00:10 Is it OK to remove this #ifdef?
Roger Tawa OOO till Jul 10th 2012/02/29 21:02:54 This was dead code that was not used. When I firs
243 DVLOG(1) << "Unable to retrieve the token auth."; 340 DVLOG(1) << "Unable to retrieve the token auth.";
244 CleanupNotificationRegistration(); 341 CleanupNotificationRegistration();
245 #endif
246 } 342 }
247 343
248 void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) { 344 void SigninManager::OnUberAuthTokenSuccess(const std::string& token) {
249 // If we got a bad ASP, prompt for an ASP again by forcing another TWO_FACTOR 345 DVLOG(1) << "SigninManager::OnUberAuthTokenSuccess token=" << token;
250 // error. 346 client_login_->StartTokenAuth(token);
251 bool invalid_gaia = error.state() == 347 }
252 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS; 348
253 last_login_auth_error_ = (invalid_gaia && had_two_factor_error_) ? 349 void SigninManager::OnUberAuthTokenFailure(
254 GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR) : error; 350 const GoogleServiceAuthError& error) {
351 LOG(WARNING) << "SigninManager::OnUberAuthTokenFailure";
352 last_login_auth_error_ = error;
255 content::NotificationService::current()->Notify( 353 content::NotificationService::current()->Notify(
256 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED, 354 chrome::NOTIFICATION_GOOGLE_SIGNIN_FAILED,
257 content::Source<Profile>(profile_), 355 content::Source<Profile>(profile_),
258 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_)); 356 content::Details<const GoogleServiceAuthError>(&last_login_auth_error_));
259 357
260 // We don't sign-out if the password was valid and we're just dealing with
261 // a second factor error, and we don't sign out if we're dealing with
262 // an invalid access code (again, because the password was valid).
263 if (last_login_auth_error_.state() == GoogleServiceAuthError::TWO_FACTOR) {
264 had_two_factor_error_ = true;
265 return;
266 }
267
268 ClearTransientSigninData(); 358 ClearTransientSigninData();
269 } 359 }
270 360
271 void SigninManager::Observe(int type, 361 void SigninManager::Observe(int type,
272 const content::NotificationSource& source, 362 const content::NotificationSource& source,
273 const content::NotificationDetails& details) { 363 const content::NotificationDetails& details) {
274 #if !defined(OS_CHROMEOS) 364 #if !defined(OS_CHROMEOS)
275 DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE); 365 DCHECK(type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
276 TokenService::TokenAvailableDetails* tok_details = 366 TokenService::TokenAvailableDetails* tok_details =
277 content::Details<TokenService::TokenAvailableDetails>(details).ptr(); 367 content::Details<TokenService::TokenAvailableDetails>(details).ptr();
278 368
279 // If a GAIA service token has become available, use it to pre-login the 369 // If a GAIA service token has become available, use it to pre-login the
280 // user to other services that depend on GAIA credentials. 370 // user to other services that depend on GAIA credentials.
281 if (tok_details->service() == GaiaConstants::kGaiaService) { 371 if (tok_details->service() == GaiaConstants::kGaiaService) {
282 if (client_login_.get() == NULL) { 372 if (client_login_.get() == NULL) {
283 client_login_.reset(new GaiaAuthFetcher(this, 373 client_login_.reset(new GaiaAuthFetcher(this,
284 GaiaConstants::kChromeSource, 374 GaiaConstants::kChromeSource,
285 profile_->GetRequestContext())); 375 profile_->GetRequestContext()));
286 } 376 }
287 377
288 client_login_->StartMergeSession(tok_details->token()); 378 client_login_->StartMergeSession(tok_details->token());
289 379
290 // We only want to do this once per sign-in. 380 // We only want to do this once per sign-in.
291 CleanupNotificationRegistration(); 381 CleanupNotificationRegistration();
292 } 382 }
293 #endif 383 #endif
294 } 384 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698