Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/chromeos/login/oauth2_login_manager.h" | 5 #include "chrome/browser/chromeos/login/oauth2_login_manager.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 | 92 |
| 93 DCHECK(restore_strategy_ == RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN); | 93 DCHECK(restore_strategy_ == RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN); |
| 94 RestoreSessionFromSavedTokens(); | 94 RestoreSessionFromSavedTokens(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 void OAuth2LoginManager::RestoreSessionFromSavedTokens() { | 97 void OAuth2LoginManager::RestoreSessionFromSavedTokens() { |
| 98 ProfileOAuth2TokenService* token_service = GetTokenService(); | 98 ProfileOAuth2TokenService* token_service = GetTokenService(); |
| 99 const std::string& primary_account_id = GetPrimaryAccountId(); | 99 const std::string& primary_account_id = GetPrimaryAccountId(); |
| 100 if (token_service->RefreshTokenIsAvailable(primary_account_id)) { | 100 if (token_service->RefreshTokenIsAvailable(primary_account_id)) { |
| 101 LOG(WARNING) << "OAuth2 refresh token is already loaded."; | 101 LOG(WARNING) << "OAuth2 refresh token is already loaded."; |
| 102 RestoreSessionCookies(); | 102 VerifySessionCookies(); |
| 103 } else { | 103 } else { |
| 104 LOG(WARNING) << "Loading OAuth2 refresh token from database."; | 104 LOG(WARNING) << "Loading OAuth2 refresh token from database."; |
| 105 | 105 |
| 106 // Flag user with unknown token status in case there are no saved tokens | 106 // Flag user with unknown token status in case there are no saved tokens |
| 107 // and OnRefreshTokenAvailable is not called. Flagging it here would | 107 // and OnRefreshTokenAvailable is not called. Flagging it here would |
| 108 // cause user to go through Gaia in next login to obtain a new refresh | 108 // cause user to go through Gaia in next login to obtain a new refresh |
| 109 // token. | 109 // token. |
| 110 UserManager::Get()->SaveUserOAuthStatus(primary_account_id, | 110 UserManager::Get()->SaveUserOAuthStatus(primary_account_id, |
| 111 User::OAUTH_TOKEN_STATUS_UNKNOWN); | 111 User::OAUTH_TOKEN_STATUS_UNKNOWN); |
| 112 | 112 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 138 // oauth2 token. | 138 // oauth2 token. |
| 139 if (UserManager::Get()->IsLoggedInAsLocallyManagedUser()) { | 139 if (UserManager::Get()->IsLoggedInAsLocallyManagedUser()) { |
| 140 LOG(WARNING) << "Logged in as managed user, skip token validation."; | 140 LOG(WARNING) << "Logged in as managed user, skip token validation."; |
| 141 return; | 141 return; |
| 142 } | 142 } |
| 143 // Only restore session cookies for the primary account in the profile. | 143 // Only restore session cookies for the primary account in the profile. |
| 144 if (GetPrimaryAccountId() == account_id) { | 144 if (GetPrimaryAccountId() == account_id) { |
| 145 // Token is loaded. Undo the flagging before token loading. | 145 // Token is loaded. Undo the flagging before token loading. |
| 146 UserManager::Get()->SaveUserOAuthStatus(account_id, | 146 UserManager::Get()->SaveUserOAuthStatus(account_id, |
| 147 User::OAUTH2_TOKEN_STATUS_VALID); | 147 User::OAUTH2_TOKEN_STATUS_VALID); |
| 148 RestoreSessionCookies(); | 148 VerifySessionCookies(); |
| 149 } | 149 } |
| 150 } | 150 } |
| 151 | 151 |
| 152 ProfileOAuth2TokenService* OAuth2LoginManager::GetTokenService() { | 152 ProfileOAuth2TokenService* OAuth2LoginManager::GetTokenService() { |
| 153 return ProfileOAuth2TokenServiceFactory::GetForProfile(user_profile_); | 153 return ProfileOAuth2TokenServiceFactory::GetForProfile(user_profile_); |
| 154 } | 154 } |
| 155 | 155 |
| 156 const std::string& OAuth2LoginManager::GetPrimaryAccountId() { | 156 const std::string& OAuth2LoginManager::GetPrimaryAccountId() { |
| 157 SigninManagerBase* signin_manager = | 157 SigninManagerBase* signin_manager = |
| 158 SigninManagerFactory::GetForProfile(user_profile_); | 158 SigninManagerFactory::GetForProfile(user_profile_); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) { | 236 const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) { |
| 237 VLOG(1) << "OAuth2 tokens fetched"; | 237 VLOG(1) << "OAuth2 tokens fetched"; |
| 238 DCHECK(refresh_token_.empty()); | 238 DCHECK(refresh_token_.empty()); |
| 239 refresh_token_.assign(oauth2_tokens.refresh_token); | 239 refresh_token_.assign(oauth2_tokens.refresh_token); |
| 240 oauthlogin_access_token_ = oauth2_tokens.access_token; | 240 oauthlogin_access_token_ = oauth2_tokens.access_token; |
| 241 StoreOAuth2Token(); | 241 StoreOAuth2Token(); |
| 242 } | 242 } |
| 243 | 243 |
| 244 void OAuth2LoginManager::OnOAuth2TokensFetchFailed() { | 244 void OAuth2LoginManager::OnOAuth2TokensFetchFailed() { |
| 245 LOG(ERROR) << "OAuth2 tokens fetch failed!"; | 245 LOG(ERROR) << "OAuth2 tokens fetch failed!"; |
| 246 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", | 246 RecordSessionRestoreOutcome(SESSION_RESTORE_TOKEN_FETCH_FAILED, |
| 247 SESSION_RESTORE_TOKEN_FETCH_FAILED, | 247 SESSION_RESTORE_FAILED); |
| 248 SESSION_RESTORE_COUNT); | |
| 249 SetSessionRestoreState(OAuth2LoginManager::SESSION_RESTORE_FAILED); | |
| 250 } | 248 } |
| 251 | 249 |
| 252 void OAuth2LoginManager::RestoreSessionCookies() { | 250 void OAuth2LoginManager::VerifySessionCookies() { |
| 253 DCHECK(!login_verifier_.get()); | 251 DCHECK(!login_verifier_.get()); |
| 254 SetSessionRestoreState(SESSION_RESTORE_IN_PROGRESS); | |
| 255 login_verifier_.reset( | 252 login_verifier_.reset( |
| 256 new OAuth2LoginVerifier(this, | 253 new OAuth2LoginVerifier(this, |
| 257 g_browser_process->system_request_context(), | 254 g_browser_process->system_request_context(), |
| 258 user_profile_->GetRequestContext(), | 255 user_profile_->GetRequestContext(), |
| 259 oauthlogin_access_token_)); | 256 oauthlogin_access_token_)); |
| 257 | |
| 258 if (restore_strategy_ == RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) { | |
| 259 login_verifier_->VerifyUserCookies(user_profile_); | |
| 260 return; | |
| 261 } | |
| 262 | |
| 263 RestoreSessionCookies(); | |
| 264 } | |
| 265 | |
| 266 void OAuth2LoginManager::RestoreSessionCookies() { | |
| 267 SetSessionRestoreState(SESSION_RESTORE_IN_PROGRESS); | |
| 260 login_verifier_->VerifyProfileTokens(user_profile_); | 268 login_verifier_->VerifyProfileTokens(user_profile_); |
| 261 } | 269 } |
| 262 | 270 |
| 263 void OAuth2LoginManager::Shutdown() { | 271 void OAuth2LoginManager::Shutdown() { |
| 264 GetTokenService()->RemoveObserver(this); | 272 GetTokenService()->RemoveObserver(this); |
| 265 login_verifier_.reset(); | 273 login_verifier_.reset(); |
| 266 oauth2_token_fetcher_.reset(); | 274 oauth2_token_fetcher_.reset(); |
| 267 } | 275 } |
| 268 | 276 |
| 269 void OAuth2LoginManager::OnSessionMergeSuccess() { | 277 void OAuth2LoginManager::OnSessionMergeSuccess() { |
| 270 VLOG(1) << "OAuth2 refresh and/or GAIA token verification succeeded."; | 278 VLOG(1) << "OAuth2 refresh and/or GAIA token verification succeeded."; |
| 271 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", | 279 RecordSessionRestoreOutcome(SESSION_RESTORE_SUCCESS, |
| 272 SESSION_RESTORE_SUCCESS, | 280 SESSION_RESTORE_DONE); |
| 273 SESSION_RESTORE_COUNT); | |
| 274 SetSessionRestoreState(OAuth2LoginManager::SESSION_RESTORE_DONE); | |
| 275 } | 281 } |
| 276 | 282 |
| 277 void OAuth2LoginManager::OnSessionMergeFailure(bool connection_error) { | 283 void OAuth2LoginManager::OnSessionMergeFailure(bool connection_error) { |
| 278 LOG(ERROR) << "OAuth2 refresh and GAIA token verification failed!" | 284 LOG(ERROR) << "OAuth2 refresh and GAIA token verification failed!" |
| 279 << " connection_error: " << connection_error; | 285 << " connection_error: " << connection_error; |
| 280 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", | 286 RecordSessionRestoreOutcome(SESSION_RESTORE_MERGE_SESSION_FAILED, |
| 281 SESSION_RESTORE_MERGE_SESSION_FAILED, | 287 connection_error ? |
| 282 SESSION_RESTORE_COUNT); | 288 SESSION_RESTORE_CONNECTION_FAILED : |
| 283 SetSessionRestoreState(connection_error ? | 289 SESSION_RESTORE_FAILED); |
| 284 OAuth2LoginManager::SESSION_RESTORE_CONNECTION_FAILED : | |
| 285 OAuth2LoginManager::SESSION_RESTORE_FAILED); | |
| 286 } | 290 } |
| 287 | 291 |
| 288 void OAuth2LoginManager::OnListAccountsSuccess(const std::string& data) { | 292 void OAuth2LoginManager::OnListAccountsSuccess(const std::string& data) { |
| 289 PostMergeVerificationOutcome outcome = POST_MERGE_SUCCESS; | 293 MergeVerificationOutcome outcome = POST_MERGE_SUCCESS; |
| 290 // Let's analyze which accounts we see logged in here: | 294 // Let's analyze which accounts we see logged in here: |
| 291 std::vector<std::string> accounts = gaia::ParseListAccountsData(data); | 295 std::vector<std::string> accounts = gaia::ParseListAccountsData(data); |
| 292 std::string user_email = gaia::CanonicalizeEmail(GetPrimaryAccountId()); | 296 std::string user_email = gaia::CanonicalizeEmail(GetPrimaryAccountId()); |
| 293 if (!accounts.empty()) { | 297 if (!accounts.empty()) { |
| 294 bool found = false; | 298 bool found = false; |
| 295 bool first = true; | 299 bool first = true; |
| 296 for (std::vector<std::string>::const_iterator iter = accounts.begin(); | 300 for (std::vector<std::string>::const_iterator iter = accounts.begin(); |
| 297 iter != accounts.end(); ++iter) { | 301 iter != accounts.end(); ++iter) { |
| 298 if (gaia::CanonicalizeEmail(*iter) == user_email) { | 302 if (gaia::CanonicalizeEmail(*iter) == user_email) { |
| 299 found = true; | 303 found = true; |
| 300 break; | 304 break; |
| 301 } | 305 } |
| 302 | 306 |
| 303 first = false; | 307 first = false; |
| 304 } | 308 } |
| 305 | 309 |
| 306 if (!found) | 310 if (!found) |
| 307 outcome = POST_MERGE_MISSING_PRIMARY_ACCOUNT; | 311 outcome = POST_MERGE_MISSING_PRIMARY_ACCOUNT; |
| 308 else if (!first) | 312 else if (!first) |
| 309 outcome = POST_MERGE_PRIMARY_NOT_FIRST_ACCOUNT; | 313 outcome = POST_MERGE_PRIMARY_NOT_FIRST_ACCOUNT; |
| 310 | 314 |
| 311 } else { | 315 } else { |
| 312 outcome = POST_MERGE_NO_ACCOUNTS; | 316 outcome = POST_MERGE_NO_ACCOUNTS; |
| 313 } | 317 } |
| 314 | 318 |
| 315 RecordPostMergeOutcome(outcome); | 319 bool is_pre_merge = (state_ == SESSION_RESTORE_PREPARING); |
| 320 RecordCookiesCheckOutcome(is_pre_merge, outcome); | |
| 321 // If the primary account is missing during the initial cookie freshness | |
| 322 // check, try to restore GAIA session cookies form the OAuth2 tokens. | |
| 323 if (is_pre_merge) { | |
| 324 if (outcome != POST_MERGE_SUCCESS && | |
| 325 outcome != POST_MERGE_PRIMARY_NOT_FIRST_ACCOUNT) { | |
| 326 RestoreSessionCookies(); | |
| 327 } else { | |
| 328 // We are done with this account, it's GAIA cookies are legit. | |
| 329 RecordSessionRestoreOutcome(SESSION_RESTORE_NOT_NEEDED, | |
| 330 SESSION_RESTORE_DONE); | |
| 331 } | |
| 332 } | |
| 316 } | 333 } |
| 317 | 334 |
| 318 void OAuth2LoginManager::OnListAccountsFailure(bool connection_error) { | 335 void OAuth2LoginManager::OnListAccountsFailure(bool connection_error) { |
| 319 RecordPostMergeOutcome(connection_error ? POST_MERGE_CONNECTION_FAILED : | 336 bool is_pre_merge = (state_ == SESSION_RESTORE_PREPARING); |
| 320 POST_MERGE_VERIFICATION_FAILED); | 337 RecordCookiesCheckOutcome( |
| 338 is_pre_merge, | |
| 339 connection_error ? POST_MERGE_CONNECTION_FAILED : | |
| 340 POST_MERGE_VERIFICATION_FAILED); | |
| 341 if (is_pre_merge) { | |
| 342 if (!connection_error) { | |
| 343 // If we failed to get account list, our cookies might be stale so we | |
| 344 // need to attempt to restore them. | |
| 345 RestoreSessionCookies(); | |
| 346 } else { | |
| 347 RecordSessionRestoreOutcome(SESSION_RESTORE_LISTACCOUNTS_FAILED, | |
| 348 SESSION_RESTORE_CONNECTION_FAILED); | |
| 349 } | |
| 350 } | |
| 351 } | |
| 352 | |
| 353 void OAuth2LoginManager::RecordSessionRestoreOutcome( | |
| 354 SessionRestoreOutcome outcome, | |
| 355 OAuth2LoginManager::SessionRestoreState state) { | |
| 356 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", | |
| 357 outcome, | |
| 358 SESSION_RESTORE_COUNT); | |
| 359 SetSessionRestoreState(state); | |
| 321 } | 360 } |
| 322 | 361 |
| 323 // static | 362 // static |
| 324 void OAuth2LoginManager::RecordPostMergeOutcome( | 363 void OAuth2LoginManager::RecordCookiesCheckOutcome( |
| 325 PostMergeVerificationOutcome outcome) { | 364 bool is_pre_merge, |
| 326 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.PostMergeVerification", | 365 MergeVerificationOutcome outcome) { |
| 327 outcome, | 366 if (is_pre_merge) { |
| 328 POST_MERGE_COUNT); | 367 UMA_HISTOGRAM_ENUMERATION( |
| 368 "OAuth2Login.PreMergeVerification", | |
|
Alexei Svitkine (slow)
2014/01/29 17:41:22
Nit: Move this on the line above and align the oth
zel
2014/01/29 17:51:46
Done.
| |
| 369 outcome, | |
| 370 POST_MERGE_COUNT); | |
| 371 } else { | |
| 372 UMA_HISTOGRAM_ENUMERATION( | |
| 373 "OAuth2Login.PostMergeVerification", | |
| 374 outcome, | |
| 375 POST_MERGE_COUNT); | |
| 376 } | |
| 329 } | 377 } |
| 330 | 378 |
| 331 | |
| 332 void OAuth2LoginManager::SetSessionRestoreState( | 379 void OAuth2LoginManager::SetSessionRestoreState( |
| 333 OAuth2LoginManager::SessionRestoreState state) { | 380 OAuth2LoginManager::SessionRestoreState state) { |
| 334 if (state_ == state) | 381 if (state_ == state) |
| 335 return; | 382 return; |
| 336 | 383 |
| 337 state_ = state; | 384 state_ = state; |
| 338 if (state == OAuth2LoginManager::SESSION_RESTORE_FAILED) { | 385 if (state == OAuth2LoginManager::SESSION_RESTORE_FAILED) { |
| 339 UMA_HISTOGRAM_TIMES("OAuth2Login.SessionRestoreTimeToFailure", | 386 UMA_HISTOGRAM_TIMES("OAuth2Login.SessionRestoreTimeToFailure", |
| 340 base::Time::Now() - session_restore_start_); | 387 base::Time::Now() - session_restore_start_); |
| 341 } else if (state == OAuth2LoginManager::SESSION_RESTORE_DONE) { | 388 } else if (state == OAuth2LoginManager::SESSION_RESTORE_DONE) { |
| 342 UMA_HISTOGRAM_TIMES("OAuth2Login.SessionRestoreTimeToSuccess", | 389 UMA_HISTOGRAM_TIMES("OAuth2Login.SessionRestoreTimeToSuccess", |
| 343 base::Time::Now() - session_restore_start_); | 390 base::Time::Now() - session_restore_start_); |
| 344 } | 391 } |
| 345 | 392 |
| 346 FOR_EACH_OBSERVER(Observer, observer_list_, | 393 FOR_EACH_OBSERVER(Observer, observer_list_, |
| 347 OnSessionRestoreStateChanged(user_profile_, state_)); | 394 OnSessionRestoreStateChanged(user_profile_, state_)); |
| 348 } | 395 } |
| 349 | 396 |
| 350 void OAuth2LoginManager::SetSessionRestoreStartForTesting( | 397 void OAuth2LoginManager::SetSessionRestoreStartForTesting( |
| 351 const base::Time& time) { | 398 const base::Time& time) { |
| 352 session_restore_start_ = time; | 399 session_restore_start_ = time; |
| 353 } | 400 } |
| 354 | 401 |
| 355 } // namespace chromeos | 402 } // namespace chromeos |
| OLD | NEW |