Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |