account_reconcilor.h revision 0de6073388f4e2780db8536178b129cd8f6ab386
103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// found in the LICENSE file.
403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <deque>
803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <functional>
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <set>
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <string>
1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <utility>
1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <vector>
1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/basictypes.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/callback_forward.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/compiler_specific.h"
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/memory/scoped_vector.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/keyed_service/core/keyed_service.h"
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/signin/core/browser/signin_manager.h"
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_consumer.h"
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "google_apis/gaia/merge_session_helper.h"
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h"
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class GaiaAuthFetcher;
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class ProfileOAuth2TokenService;
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class SigninClient;
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class SigninOAuthHelper;
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace net {
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CanonicalCookie;
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class AccountReconcilor : public KeyedService,
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          public GaiaAuthConsumer,
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          public MergeSessionHelper::Observer,
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          public OAuth2TokenService::Consumer,
39                          public OAuth2TokenService::Observer,
40                          public SigninManagerBase::Observer {
41 public:
42  AccountReconcilor(ProfileOAuth2TokenService* token_service,
43                    SigninManagerBase* signin_manager,
44                    SigninClient* client);
45  virtual ~AccountReconcilor();
46
47  void Initialize(bool start_reconcile_if_tokens_available);
48
49  // KeyedService implementation.
50  virtual void Shutdown() OVERRIDE;
51
52  // Add or remove observers for the merge session notification.
53  void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
54  void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
55
56  ProfileOAuth2TokenService* token_service() { return token_service_; }
57  SigninClient* client() { return client_; }
58
59 private:
60  // An std::set<> for use with email addresses that uses
61  // gaia::CanonicalizeEmail() during comparisons.
62  // TODO(rogerta): this is a workaround for the fact that SigninManager and
63  // SigninOAuthHelper use the gaia "email" property when adding accounts to
64  // the token service, whereas gaia::ParseListAccountsData() returns email
65  // addresses that have been passed through gaia::CanonicalizeEmail().  These
66  // two types of email addresses are not directly comparable.
67  class EmailLessFunc : public std::less<std::string> {
68   public:
69    bool operator()(const std::string& s1, const std::string& s2) const;
70  };
71  typedef std::set<std::string, EmailLessFunc> EmailSet;
72
73  class RefreshTokenFetcher;
74  class UserIdFetcher;
75
76  bool IsRegisteredWithTokenService() const {
77    return registered_with_token_service_;
78  }
79
80  bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
81
82  bool AreAllRefreshTokensChecked() const;
83
84  const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting()
85      const {
86    return gaia_accounts_;
87  }
88
89  const EmailSet& GetValidChromeAccountsForTesting() const {
90    return valid_chrome_accounts_;
91  }
92
93  const EmailSet& GetInvalidChromeAccountsForTesting() const {
94    return invalid_chrome_accounts_;
95  }
96
97  // Used during GetAccountsFromCookie.
98  // Stores a callback for the next action to perform.
99  typedef base::Callback<
100      void(const GoogleServiceAuthError& error,
101           const std::vector<std::pair<std::string, bool> >&)>
102      GetAccountsFromCookieCallback;
103
104  friend class AccountReconcilorTest;
105  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, SigninManagerRegistration);
106  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, Reauth);
107  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ProfileAlreadyConnected);
108  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieSuccess);
109  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieFailure);
110  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ValidateAccountsFromTokens);
111  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
112                           ValidateAccountsFromTokensFailedUserInfo);
113  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
114                           ValidateAccountsFromTokensFailedTokenRequest);
115  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoop);
116  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopWithDots);
117  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopMultiple);
118  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToCookie);
119  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToChrome);
120  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileBadPrimary);
121  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileOnlyOnce);
122  FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
123                           StartReconcileWithSessionInfoExpiredDefault);
124
125  // Register and unregister with dependent services.
126  void RegisterForCookieChanges();
127  void UnregisterForCookieChanges();
128  void RegisterWithSigninManager();
129  void UnregisterWithSigninManager();
130  void RegisterWithTokenService();
131  void UnregisterWithTokenService();
132
133  bool IsProfileConnected();
134
135  void DeleteFetchers();
136
137  // All actions with side effects.  Virtual so that they can be overridden
138  // in tests.
139  virtual void PerformMergeAction(const std::string& account_id);
140  virtual void PerformAddToChromeAction(const std::string& account_id,
141                                        int session_index);
142  virtual void PerformLogoutAllAccountsAction();
143
144  // Used to remove an account from chrome and the cookie jar.
145  virtual void StartRemoveAction(const std::string& account_id);
146  virtual void FinishRemoveAction(
147      const std::string& account_id,
148      const GoogleServiceAuthError& error,
149      const std::vector<std::pair<std::string, bool> >& accounts);
150
151  // Used during periodic reconciliation.
152  void StartReconcile();
153  void FinishReconcile();
154  void AbortReconcile();
155  void CalculateIfReconcileIsDone();
156  void ScheduleStartReconcileIfChromeAccountsChanged();
157  void HandleSuccessfulAccountIdCheck(const std::string& account_id);
158  void HandleFailedAccountIdCheck(const std::string& account_id);
159  void HandleRefreshTokenFetched(const std::string& account_id,
160                                 const std::string& refresh_token);
161
162  void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
163  void ContinueReconcileActionAfterGetGaiaAccounts(
164      const GoogleServiceAuthError& error,
165      const std::vector<std::pair<std::string, bool> >& accounts);
166  void ValidateAccountsFromTokenService();
167
168  void OnCookieChanged(const net::CanonicalCookie* cookie);
169
170  // Overriden from GaiaAuthConsumer.
171  virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
172  virtual void OnListAccountsFailure(const GoogleServiceAuthError& error)
173      OVERRIDE;
174
175  // Overriden from MergeSessionHelper::Observer.
176  virtual void MergeSessionCompleted(const std::string& account_id,
177                                     const GoogleServiceAuthError& error)
178      OVERRIDE;
179
180  // Overriden from OAuth2TokenService::Consumer.
181  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
182                                 const std::string& access_token,
183                                 const base::Time& expiration_time) OVERRIDE;
184  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
185                                 const GoogleServiceAuthError& error) OVERRIDE;
186
187  // Overriden from OAuth2TokenService::Observer.
188  virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
189  virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
190  virtual void OnRefreshTokensLoaded() OVERRIDE;
191
192  // Overriden from SigninManagerBase::Observer.
193  virtual void GoogleSigninSucceeded(const std::string& username,
194                                     const std::string& password) OVERRIDE;
195  virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
196
197  void MayBeDoNextListAccounts();
198
199  // The ProfileOAuth2TokenService associated with this reconcilor.
200  ProfileOAuth2TokenService* token_service_;
201
202  // The SigninManager associated with this reconcilor.
203  SigninManagerBase* signin_manager_;
204
205  // The SigninClient associated with this reconcilor.
206  SigninClient* client_;
207
208  MergeSessionHelper merge_session_helper_;
209  scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
210  bool registered_with_token_service_;
211
212  // True while the reconcilor is busy checking or managing the accounts in
213  // this profile.
214  bool is_reconcile_started_;
215
216  // Used during reconcile action.
217  // These members are used used to validate the gaia cookie.  |gaia_accounts_|
218  // holds the state of google accounts in the gaia cookie.  Each element is
219  // a pair that holds the email address of the account and a boolean that
220  // indicates whether the account is valid or not.  The accounts in the vector
221  // are ordered the in same way as the gaia cookie.
222  bool are_gaia_accounts_set_;
223  std::vector<std::pair<std::string, bool> > gaia_accounts_;
224
225  // Used during reconcile action.
226  // These members are used to validate the tokens in OAuth2TokenService.
227  std::string primary_account_;
228  std::vector<std::string> chrome_accounts_;
229  scoped_ptr<OAuth2TokenService::Request>* requests_;
230  ScopedVector<UserIdFetcher> user_id_fetchers_;
231  ScopedVector<SigninOAuthHelper> refresh_token_fetchers_;
232  EmailSet valid_chrome_accounts_;
233  EmailSet invalid_chrome_accounts_;
234  std::vector<std::string> add_to_cookie_;
235  std::vector<std::pair<std::string, int> > add_to_chrome_;
236
237  std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
238
239  DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
240};
241
242#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
243