• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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