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
20class GoogleServiceAuthError;
21class Profile;
22class ProfileOAuth2TokenService;
23
24namespace chromeos {
25
26// This class is responsible for restoring authenticated web sessions out of
27// OAuth2 refresh tokens or pre-authenticated cookie jar.
28class 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