Home | History | Annotate | Download | only in login
      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