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: ~Observer()66 virtual ~Observer() {} 67 68 // Raised when merge session state changes. OnSessionRestoreStateChanged(Profile * user_profile,SessionRestoreState state)69 virtual void OnSessionRestoreStateChanged(Profile* user_profile, 70 SessionRestoreState state) {} 71 72 // Raised when a new OAuth2 refresh token is avaialble. OnNewRefreshTokenAvaiable(Profile * user_profile)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. OnSessionAuthenticated(Profile * user_profile)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. state()108 SessionRestoreState state() { return state_; } 109 session_restore_start()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