Home | History | Annotate | Download | only in signin
      1 // Copyright 2014 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 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_LOGIN_MANAGER_H_
      6 #define CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_LOGIN_MANAGER_H_
      7 
      8 #include <string>
      9 
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/observer_list.h"
     12 #include "base/time/time.h"
     13 #include "chrome/browser/chromeos/login/signin/oauth2_login_verifier.h"
     14 #include "chrome/browser/chromeos/login/signin/oauth2_token_fetcher.h"
     15 #include "components/keyed_service/core/keyed_service.h"
     16 #include "google_apis/gaia/gaia_oauth_client.h"
     17 #include "google_apis/gaia/oauth2_token_service.h"
     18 #include "net/url_request/url_request_context_getter.h"
     19 
     20 class GoogleServiceAuthError;
     21 class Profile;
     22 class ProfileOAuth2TokenService;
     23 
     24 namespace chromeos {
     25 
     26 // This class is responsible for restoring authenticated web sessions out of
     27 // OAuth2 refresh tokens or pre-authenticated cookie jar.
     28 class OAuth2LoginManager : public KeyedService,
     29                            public gaia::GaiaOAuthClient::Delegate,
     30                            public OAuth2LoginVerifier::Delegate,
     31                            public OAuth2TokenFetcher::Delegate,
     32                            public OAuth2TokenService::Observer {
     33  public:
     34   // Session restore states.
     35   enum SessionRestoreState {
     36     // Session restore is not started.
     37     SESSION_RESTORE_NOT_STARTED,
     38     // Session restore is being prepared.
     39     SESSION_RESTORE_PREPARING,
     40     // Session restore is in progress. We are currently issuing calls to verify
     41     // stored OAuth tokens and populate cookie jar with GAIA credentials.
     42     SESSION_RESTORE_IN_PROGRESS,
     43     // Session restore is completed.
     44     SESSION_RESTORE_DONE,
     45     // Session restore failed.
     46     SESSION_RESTORE_FAILED,
     47     // Session restore failed due to connection or service errors.
     48     SESSION_RESTORE_CONNECTION_FAILED,
     49   };
     50 
     51   // Session restore strategy.
     52   enum SessionRestoreStrategy {
     53     // Generate OAuth2 refresh token from authentication profile's cookie jar.
     54     // Restore session from generated OAuth2 refresh token.
     55     RESTORE_FROM_COOKIE_JAR,
     56     // Restore session from saved OAuth2 refresh token from TokenServices.
     57     RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN,
     58     // Restore session from OAuth2 refresh token passed via command line.
     59     RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN,
     60     // Restore session from authentication code passed via command line.
     61     RESTORE_FROM_AUTH_CODE,
     62   };
     63 
     64   class Observer {
     65    public:
     66     virtual ~Observer() {}
     67 
     68     // Raised when merge session state changes.
     69     virtual void OnSessionRestoreStateChanged(Profile* user_profile,
     70                                               SessionRestoreState state) {}
     71 
     72     // Raised when a new OAuth2 refresh token is avaialble.
     73     virtual void OnNewRefreshTokenAvaiable(Profile* user_profile) {}
     74 
     75     // Raised when session's GAIA credentials (SID+LSID) are available to
     76     // other signed in services.
     77     virtual void OnSessionAuthenticated(Profile* user_profile) {}
     78   };
     79 
     80   explicit OAuth2LoginManager(Profile* user_profile);
     81   virtual ~OAuth2LoginManager();
     82 
     83   void AddObserver(OAuth2LoginManager::Observer* observer);
     84   void RemoveObserver(OAuth2LoginManager::Observer* observer);
     85 
     86   // Restores and verifies OAuth tokens either following specified
     87   // |restore_strategy|. For |restore_strategy| with values
     88   // RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN or
     89   // RESTORE_FROM_AUTH_CODE, respectively
     90   // parameters |oauth2_refresh_token| or |auth_code| need to have non-empty
     91   // value.
     92   void RestoreSession(
     93       net::URLRequestContextGetter* auth_request_context,
     94       SessionRestoreStrategy restore_strategy,
     95       const std::string& oauth2_refresh_token,
     96       const std::string& auth_code);
     97 
     98   // Continues session restore after transient network errors.
     99   void ContinueSessionRestore();
    100 
    101   // Start resporting session from saved OAuth2 refresh token.
    102   void RestoreSessionFromSavedTokens();
    103 
    104   // Stops all background authentication requests.
    105   void Stop();
    106 
    107   // Returns session restore state.
    108   SessionRestoreState state() { return state_; }
    109 
    110   const base::Time& session_restore_start() { return session_restore_start_; }
    111 
    112   // Returns true if the tab loading should block until session restore
    113   // finishes.
    114   bool ShouldBlockTabLoading();
    115 
    116  private:
    117   friend class MergeSessionLoadPageTest;
    118   friend class OAuth2Test;
    119 
    120   // Session restore outcomes (for UMA).
    121   enum SessionRestoreOutcome {
    122     SESSION_RESTORE_UNDEFINED = 0,
    123     SESSION_RESTORE_SUCCESS = 1,
    124     SESSION_RESTORE_TOKEN_FETCH_FAILED = 2,
    125     SESSION_RESTORE_NO_REFRESH_TOKEN_FAILED = 3,
    126     SESSION_RESTORE_OAUTHLOGIN_FAILED = 4,
    127     SESSION_RESTORE_MERGE_SESSION_FAILED = 5,
    128     SESSION_RESTORE_LISTACCOUNTS_FAILED = 6,
    129     SESSION_RESTORE_NOT_NEEDED = 7,
    130     SESSION_RESTORE_COUNT = 8,
    131   };
    132 
    133   // Outcomes of post-merge session verification.
    134   // This enum is used for an UMA histogram, and hence new items should only be
    135   // appended at the end.
    136   enum MergeVerificationOutcome {
    137     POST_MERGE_UNDEFINED  = 0,
    138     POST_MERGE_SUCCESS = 1,
    139     POST_MERGE_NO_ACCOUNTS = 2,
    140     POST_MERGE_MISSING_PRIMARY_ACCOUNT = 3,
    141     POST_MERGE_PRIMARY_NOT_FIRST_ACCOUNT = 4,
    142     POST_MERGE_VERIFICATION_FAILED = 5,
    143     POST_MERGE_CONNECTION_FAILED = 6,
    144     POST_MERGE_COUNT = 7,
    145   };
    146 
    147   // KeyedService implementation.
    148   virtual void Shutdown() OVERRIDE;
    149 
    150   // gaia::GaiaOAuthClient::Delegate overrides.
    151   virtual void OnRefreshTokenResponse(const std::string& access_token,
    152                                       int expires_in_seconds) OVERRIDE;
    153   virtual void OnGetUserEmailResponse(const std::string& user_email) OVERRIDE;
    154   virtual void OnOAuthError() OVERRIDE;
    155   virtual void OnNetworkError(int response_code) OVERRIDE;
    156 
    157   // OAuth2LoginVerifier::Delegate overrides.
    158   virtual void OnSessionMergeSuccess() OVERRIDE;
    159   virtual void OnSessionMergeFailure(bool connection_error) OVERRIDE;
    160   virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
    161   virtual void OnListAccountsFailure(bool connection_error) OVERRIDE;
    162 
    163   // OAuth2TokenFetcher::Delegate overrides.
    164   virtual void OnOAuth2TokensAvailable(
    165       const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) OVERRIDE;
    166   virtual void OnOAuth2TokensFetchFailed() OVERRIDE;
    167 
    168   // OAuth2TokenService::Observer implementation:
    169   virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
    170 
    171   // Signals delegate that authentication is completed, kicks off token fetching
    172   // process.
    173   void CompleteAuthentication();
    174 
    175   // Retrieves ProfileOAuth2TokenService for |user_profile_|.
    176   ProfileOAuth2TokenService* GetTokenService();
    177 
    178   // Retrieves the primary account for |user_profile_|.
    179   const std::string& GetPrimaryAccountId();
    180 
    181   // Records |refresh_token_| to token service. The associated account id is
    182   // assumed to be the primary account id of the user profile. If the primary
    183   // account id is not present, GetAccountIdOfRefreshToken will be called to
    184   // retrieve the associated account id.
    185   void StoreOAuth2Token();
    186 
    187   // Get the account id corresponding to the specified refresh token.
    188   void GetAccountIdOfRefreshToken(const std::string& refresh_token);
    189 
    190   // Attempts to fetch OAuth2 tokens by using pre-authenticated cookie jar from
    191   // provided |auth_profile|.
    192   void FetchOAuth2Tokens();
    193 
    194   // Reports when all tokens are loaded.
    195   void ReportOAuth2TokensLoaded();
    196 
    197   // Checks if primary account sessions cookies are stale and restores them
    198   // if needed.
    199   void VerifySessionCookies();
    200 
    201   // Issue GAIA cookie recovery (MergeSession) from |refresh_token_|.
    202   void RestoreSessionCookies();
    203 
    204   // Checks GAIA error and figures out whether the request should be
    205   // re-attempted.
    206   bool RetryOnError(const GoogleServiceAuthError& error);
    207 
    208   // Changes |state_|, if needed fires observers (OnSessionRestoreStateChanged).
    209   void SetSessionRestoreState(SessionRestoreState state);
    210 
    211   // Testing helper.
    212   void SetSessionRestoreStartForTesting(const base::Time& time);
    213 
    214   // Records |outcome| of session restore process and sets new |state|.
    215   void RecordSessionRestoreOutcome(SessionRestoreOutcome outcome,
    216                                    SessionRestoreState state);
    217 
    218   // Records |outcome| of merge verification check. |is_pre_merge| specifies
    219   // if this is pre or post merge session verification.
    220   static void RecordCookiesCheckOutcome(
    221       bool is_pre_merge,
    222       MergeVerificationOutcome outcome);
    223 
    224   // Keeps the track if we have already reported OAuth2 token being loaded
    225   // by OAuth2TokenService.
    226   Profile* user_profile_;
    227   scoped_refptr<net::URLRequestContextGetter> auth_request_context_;
    228   SessionRestoreStrategy restore_strategy_;
    229   SessionRestoreState state_;
    230 
    231   scoped_ptr<OAuth2TokenFetcher> oauth2_token_fetcher_;
    232   scoped_ptr<OAuth2LoginVerifier> login_verifier_;
    233   scoped_ptr<gaia::GaiaOAuthClient> account_id_fetcher_;
    234 
    235   // OAuth2 refresh token.
    236   std::string refresh_token_;
    237 
    238   // OAuthLogin scoped access token.
    239   std::string oauthlogin_access_token_;
    240 
    241   // Authorization code for fetching OAuth2 tokens.
    242   std::string auth_code_;
    243 
    244   // Session restore start time.
    245   base::Time session_restore_start_;
    246 
    247   // List of observers to notify when token availability changes.
    248   // Makes sure list is empty on destruction.
    249   // TODO(zelidrag|gspencer): Figure out how to get rid of ProfileHelper so we
    250   // can change the line below to ObserverList<Observer, true>.
    251   ObserverList<Observer, false> observer_list_;
    252 
    253   DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManager);
    254 };
    255 
    256 }  // namespace chromeos
    257 
    258 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_LOGIN_MANAGER_H_
    259