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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/chromeos/login/oauth2_login_manager.h" 6 7 #include "base/command_line.h" 8 #include "base/metrics/histogram.h" 9 #include "base/prefs/pref_service.h" 10 #include "base/strings/string_util.h" 11 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/chromeos/login/user_manager.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/signin/profile_oauth2_token_service.h" 15 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 16 #include "chrome/browser/signin/token_service.h" 17 #include "chrome/browser/signin/token_service_factory.h" 18 #include "chrome/common/chrome_switches.h" 19 #include "google_apis/gaia/gaia_constants.h" 20 #include "net/url_request/url_request_context_getter.h" 21 22 namespace chromeos { 23 24 OAuth2LoginManager::OAuth2LoginManager(OAuthLoginManager::Delegate* delegate) 25 : OAuthLoginManager(delegate), 26 loading_reported_(false) { 27 } 28 29 OAuth2LoginManager::~OAuth2LoginManager() { 30 StopObservingRefreshToken(); 31 } 32 33 void OAuth2LoginManager::RestoreSession( 34 Profile* user_profile, 35 net::URLRequestContextGetter* auth_request_context, 36 SessionRestoreStrategy restore_strategy, 37 const std::string& oauth2_refresh_token, 38 const std::string& auth_code) { 39 StopObservingRefreshToken(); 40 user_profile_ = user_profile; 41 auth_request_context_ = auth_request_context; 42 state_ = OAuthLoginManager::SESSION_RESTORE_IN_PROGRESS; 43 restore_strategy_ = restore_strategy; 44 refresh_token_ = oauth2_refresh_token; 45 auth_code_ = auth_code; 46 47 // TODO(nkostylev): drop the previous fetchers if RestoreSession() is invoked 48 // for a second Profile, when using multi-profiles. This avoids the DCHECKs 49 // below until OAuthLoginManager fully supports multi-profiles. 50 Stop(); 51 52 ProfileOAuth2TokenServiceFactory::GetForProfile(user_profile_)-> 53 AddObserver(this); 54 55 ContinueSessionRestore(); 56 } 57 58 void OAuth2LoginManager::ContinueSessionRestore() { 59 if (restore_strategy_ == RESTORE_FROM_COOKIE_JAR || 60 restore_strategy_ == RESTORE_FROM_AUTH_CODE) { 61 FetchOAuth2Tokens(); 62 return; 63 } 64 65 // Save passed OAuth2 refresh token. 66 if (restore_strategy_ == RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN) { 67 DCHECK(!refresh_token_.empty()); 68 restore_strategy_ = RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN; 69 GaiaAuthConsumer::ClientOAuthResult oauth2_tokens; 70 oauth2_tokens.refresh_token = refresh_token_; 71 StoreOAuth2Tokens(oauth2_tokens); 72 return; 73 } 74 75 DCHECK(restore_strategy_ == RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN); 76 LoadAndVerifyOAuth2Tokens(); 77 } 78 79 void OAuth2LoginManager::Stop() { 80 oauth2_token_fetcher_.reset(); 81 login_verifier_.reset(); 82 } 83 84 void OAuth2LoginManager::OnRefreshTokenAvailable( 85 const std::string& account_id) { 86 // TODO(fgorski): Once ProfileOAuth2TokenService supports multi-login, make 87 // sure to restore session cookies in the context of the correct account_id. 88 RestoreSessionCookies(); 89 } 90 91 TokenService* OAuth2LoginManager::SetupTokenService() { 92 TokenService* token_service = 93 TokenServiceFactory::GetForProfile(user_profile_); 94 return token_service; 95 } 96 97 void OAuth2LoginManager::StoreOAuth2Tokens( 98 const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) { 99 TokenService* token_service = SetupTokenService(); 100 token_service->UpdateCredentialsWithOAuth2(oauth2_tokens); 101 102 delegate_->OnNewRefreshTokenAvaiable(user_profile_); 103 } 104 105 void OAuth2LoginManager::LoadAndVerifyOAuth2Tokens() { 106 // If we have no cookies, try to load saved OAuth2 token from TokenService. 107 TokenService* token_service = SetupTokenService(); 108 token_service->Initialize(GaiaConstants::kChromeSource, user_profile_); 109 token_service->LoadTokensFromDB(); 110 } 111 112 void OAuth2LoginManager::FetchOAuth2Tokens() { 113 DCHECK(auth_request_context_.get()); 114 // If we have authenticated cookie jar, get OAuth1 token first, then fetch 115 // SID/LSID cookies through OAuthLogin call. 116 if (restore_strategy_ == RESTORE_FROM_COOKIE_JAR) { 117 oauth2_token_fetcher_.reset( 118 new OAuth2TokenFetcher(this, auth_request_context_.get())); 119 oauth2_token_fetcher_->StartExchangeFromCookies(); 120 } else if (restore_strategy_ == RESTORE_FROM_AUTH_CODE) { 121 DCHECK(!auth_code_.empty()); 122 oauth2_token_fetcher_.reset( 123 new OAuth2TokenFetcher(this, 124 g_browser_process->system_request_context())); 125 oauth2_token_fetcher_->StartExchangeFromAuthCode(auth_code_); 126 } else { 127 NOTREACHED(); 128 } 129 } 130 131 void OAuth2LoginManager::OnOAuth2TokensAvailable( 132 const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) { 133 LOG(INFO) << "OAuth2 tokens fetched"; 134 StoreOAuth2Tokens(oauth2_tokens); 135 } 136 137 void OAuth2LoginManager::OnOAuth2TokensFetchFailed() { 138 LOG(ERROR) << "OAuth2 tokens fetch failed!"; 139 state_ = OAuthLoginManager::SESSION_RESTORE_DONE; 140 UserManager::Get()->SaveUserOAuthStatus( 141 UserManager::Get()->GetLoggedInUser()->email(), 142 User::OAUTH2_TOKEN_STATUS_INVALID); 143 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", 144 SESSION_RESTORE_TOKEN_FETCH_FAILED, 145 SESSION_RESTORE_COUNT); 146 } 147 148 void OAuth2LoginManager::RestoreSessionCookies() { 149 DCHECK(!login_verifier_.get()); 150 login_verifier_.reset( 151 new OAuth2LoginVerifier(this, 152 g_browser_process->system_request_context(), 153 user_profile_->GetRequestContext())); 154 login_verifier_->VerifyProfileTokens(user_profile_); 155 } 156 157 void OAuth2LoginManager::OnOAuthLoginSuccess( 158 const GaiaAuthConsumer::ClientLoginResult& gaia_credentials) { 159 LOG(INFO) << "OAuth2 refresh token successfully exchanged for GAIA token."; 160 StartTokenService(gaia_credentials); 161 } 162 163 void OAuth2LoginManager::OnOAuthLoginFailure() { 164 LOG(ERROR) << "OAuth2 refresh token verification failed!"; 165 state_ = OAuthLoginManager::SESSION_RESTORE_DONE; 166 UserManager::Get()->SaveUserOAuthStatus( 167 UserManager::Get()->GetLoggedInUser()->email(), 168 User::OAUTH2_TOKEN_STATUS_INVALID); 169 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", 170 SESSION_RESTORE_OAUTHLOGIN_FAILED, 171 SESSION_RESTORE_COUNT); 172 delegate_->OnCompletedMergeSession(); 173 } 174 175 void OAuth2LoginManager::OnSessionMergeSuccess() { 176 LOG(INFO) << "OAuth2 refresh and/or GAIA token verification succeeded."; 177 state_ = OAuthLoginManager::SESSION_RESTORE_DONE; 178 UserManager::Get()->SaveUserOAuthStatus( 179 UserManager::Get()->GetLoggedInUser()->email(), 180 User::OAUTH2_TOKEN_STATUS_VALID); 181 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", 182 SESSION_RESTORE_SUCCESS, 183 SESSION_RESTORE_COUNT); 184 delegate_->OnCompletedMergeSession(); 185 } 186 187 void OAuth2LoginManager::OnSessionMergeFailure() { 188 LOG(ERROR) << "OAuth2 refresh and GAIA token verification failed!"; 189 state_ = OAuthLoginManager::SESSION_RESTORE_DONE; 190 UserManager::Get()->SaveUserOAuthStatus( 191 UserManager::Get()->GetLoggedInUser()->email(), 192 User::OAUTH2_TOKEN_STATUS_INVALID); 193 UMA_HISTOGRAM_ENUMERATION("OAuth2Login.SessionRestore", 194 SESSION_RESTORE_MERGE_SESSION_FAILED, 195 SESSION_RESTORE_COUNT); 196 delegate_->OnCompletedMergeSession(); 197 } 198 199 void OAuth2LoginManager::StartTokenService( 200 const GaiaAuthConsumer::ClientLoginResult& gaia_credentials) { 201 TokenService* token_service = SetupTokenService(); 202 token_service->UpdateCredentials(gaia_credentials); 203 CompleteAuthentication(); 204 } 205 206 void OAuth2LoginManager::StopObservingRefreshToken() { 207 if (user_profile_) { 208 ProfileOAuth2TokenServiceFactory::GetForProfile(user_profile_)-> 209 RemoveObserver(this); 210 } 211 } 212 213 } // namespace chromeos 214