account_reconcilor.h revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
5#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
6
7#include <deque>
8#include <functional>
9#include <set>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "base/basictypes.h"
15#include "base/callback_forward.h"
16#include "base/compiler_specific.h"
17#include "base/memory/scoped_ptr.h"
18#include "base/memory/scoped_vector.h"
19#include "components/keyed_service/core/keyed_service.h"
20#include "components/signin/core/browser/signin_manager.h"
21#include "google_apis/gaia/gaia_auth_consumer.h"
22#include "google_apis/gaia/google_service_auth_error.h"
23#include "google_apis/gaia/merge_session_helper.h"
24#include "google_apis/gaia/oauth2_token_service.h"
25
26class GaiaAuthFetcher;
27class ProfileOAuth2TokenService;
28class SigninClient;
29class SigninOAuthHelper;
30
31namespace net {
32class CanonicalCookie;
33}
34
35class AccountReconcilor : public KeyedService,
36                          public GaiaAuthConsumer,
37                          public MergeSessionHelper::Observer,
38                          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  virtual void PerformAddAccountToTokenService(
144      const std::string& account_id,
145      const std::string& refresh_token);
146
147  // Used to remove an account from chrome and the cookie jar.
148  virtual void PerformStartRemoveAction(const std::string& account_id);
149  virtual void PerformFinishRemoveAction(
150      const std::string& account_id,
151      const GoogleServiceAuthError& error,
152      const std::vector<std::pair<std::string, bool> >& accounts);
153
154  // Used during periodic reconciliation.
155  void StartReconcile();
156  void FinishReconcile();
157  void AbortReconcile();
158  void CalculateIfReconcileIsDone();
159  void ScheduleStartReconcileIfChromeAccountsChanged();
160  void HandleSuccessfulAccountIdCheck(const std::string& account_id);
161  void HandleFailedAccountIdCheck(const std::string& account_id);
162  void HandleRefreshTokenFetched(const std::string& account_id,
163                                 const std::string& refresh_token);
164
165  void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
166  void ContinueReconcileActionAfterGetGaiaAccounts(
167      const GoogleServiceAuthError& error,
168      const std::vector<std::pair<std::string, bool> >& accounts);
169  void ValidateAccountsFromTokenService();
170
171  void OnCookieChanged(const net::CanonicalCookie* cookie);
172
173  // Overriden from GaiaAuthConsumer.
174  virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
175  virtual void OnListAccountsFailure(const GoogleServiceAuthError& error)
176      OVERRIDE;
177
178  // Overriden from MergeSessionHelper::Observer.
179  virtual void MergeSessionCompleted(const std::string& account_id,
180                                     const GoogleServiceAuthError& error)
181      OVERRIDE;
182
183  // Overriden from OAuth2TokenService::Consumer.
184  virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
185                                 const std::string& access_token,
186                                 const base::Time& expiration_time) OVERRIDE;
187  virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
188                                 const GoogleServiceAuthError& error) OVERRIDE;
189
190  // Overriden from OAuth2TokenService::Observer.
191  virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
192  virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
193  virtual void OnRefreshTokensLoaded() OVERRIDE;
194
195  // Overriden from SigninManagerBase::Observer.
196  virtual void GoogleSigninSucceeded(const std::string& username,
197                                     const std::string& password) OVERRIDE;
198  virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
199
200  void MayBeDoNextListAccounts();
201
202  // The ProfileOAuth2TokenService associated with this reconcilor.
203  ProfileOAuth2TokenService* token_service_;
204
205  // The SigninManager associated with this reconcilor.
206  SigninManagerBase* signin_manager_;
207
208  // The SigninClient associated with this reconcilor.
209  SigninClient* client_;
210
211  MergeSessionHelper merge_session_helper_;
212  scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
213  bool registered_with_token_service_;
214
215  // True while the reconcilor is busy checking or managing the accounts in
216  // this profile.
217  bool is_reconcile_started_;
218
219  // True iff this is the first time the reconcilor is executing.
220  bool first_execution_;
221
222  // Used during reconcile action.
223  // These members are used used to validate the gaia cookie.  |gaia_accounts_|
224  // holds the state of google accounts in the gaia cookie.  Each element is
225  // a pair that holds the email address of the account and a boolean that
226  // indicates whether the account is valid or not.  The accounts in the vector
227  // are ordered the in same way as the gaia cookie.
228  bool are_gaia_accounts_set_;
229  std::vector<std::pair<std::string, bool> > gaia_accounts_;
230
231  // Used during reconcile action.
232  // These members are used to validate the tokens in OAuth2TokenService.
233  std::string primary_account_;
234  std::vector<std::string> chrome_accounts_;
235  scoped_ptr<OAuth2TokenService::Request>* requests_;
236  ScopedVector<UserIdFetcher> user_id_fetchers_;
237  ScopedVector<SigninOAuthHelper> refresh_token_fetchers_;
238  EmailSet valid_chrome_accounts_;
239  EmailSet invalid_chrome_accounts_;
240  std::vector<std::string> add_to_cookie_;
241  std::vector<std::pair<std::string, int> > add_to_chrome_;
242
243  std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
244
245  DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
246};
247
248#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
249