1 // Copyright 2013 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 CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_H_
5 #define CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_H_
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 "chrome/browser/signin/signin_manager.h"
20 #include "components/keyed_service/core/keyed_service.h"
21 #include "content/public/browser/notification_observer.h"
22 #include "content/public/browser/notification_registrar.h"
23 #include "google_apis/gaia/gaia_auth_consumer.h"
24 #include "google_apis/gaia/google_service_auth_error.h"
25 #include "google_apis/gaia/merge_session_helper.h"
26 #include "google_apis/gaia/oauth2_token_service.h"
28 struct ChromeCookieDetails;
29 class GaiaAuthFetcher;
31 class SigninOAuthHelper;
33 class AccountReconcilor : public KeyedService,
34 public content::NotificationObserver,
35 public GaiaAuthConsumer,
36 public MergeSessionHelper::Observer,
37 public OAuth2TokenService::Consumer,
38 public OAuth2TokenService::Observer,
39 public SigninManagerBase::Observer {
41 explicit AccountReconcilor(Profile* profile);
42 virtual ~AccountReconcilor();
44 void Initialize(bool start_reconcile_if_tokens_available);
46 // KeyedService implementation.
47 virtual void Shutdown() OVERRIDE;
49 // Add or remove observers for the merge session notification.
50 void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
51 void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
53 Profile* profile() { return profile_; }
56 // An std::set<> for use with email addresses that uses
57 // gaia::CanonicalizeEmail() during comparisons.
58 // TODO(rogerta): this is a workaround for the fact that SigninManager and
59 // SigninOAuthHelper use the gaia "email" property when adding accounts to
60 // the token service, whereas gaia::ParseListAccountsData() returns email
61 // addresses that have been passed through gaia::CanonicalizeEmail(). These
62 // two types of email addresses are not directly comparable.
63 class EmailLessFunc : public std::less<std::string> {
65 bool operator()(const std::string& s1, const std::string& s2) const;
67 typedef std::set<std::string, EmailLessFunc> EmailSet;
69 class RefreshTokenFetcher;
72 bool IsPeriodicReconciliationRunning() const {
73 return reconciliation_timer_.IsRunning();
76 bool IsRegisteredWithTokenService() const {
77 return registered_with_token_service_;
80 bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
82 bool AreAllRefreshTokensChecked() const;
84 const std::vector<std::pair<std::string, bool> >&
85 GetGaiaAccountsForTesting() const {
86 return gaia_accounts_;
89 const EmailSet& GetValidChromeAccountsForTesting() const {
90 return valid_chrome_accounts_;
93 const EmailSet& GetInvalidChromeAccountsForTesting() const {
94 return invalid_chrome_accounts_;
97 // Used during GetAccountsFromCookie.
98 // Stores a callback for the next action to perform.
99 typedef base::Callback<void(
100 const GoogleServiceAuthError& error,
101 const std::vector<std::pair<std::string, bool> >&)>
102 GetAccountsFromCookieCallback;
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);
125 // Register and unregister with dependent services.
126 void RegisterWithCookieMonster();
127 void UnregisterWithCookieMonster();
128 void RegisterWithSigninManager();
129 void UnregisterWithSigninManager();
130 void RegisterWithTokenService();
131 void UnregisterWithTokenService();
133 bool IsProfileConnected();
135 void DeleteFetchers();
137 // Start and stop the periodic reconciliation.
138 void StartPeriodicReconciliation();
139 void StopPeriodicReconciliation();
140 void PeriodicReconciliation();
142 // All actions with side effects. Virtual so that they can be overridden
144 virtual void PerformMergeAction(const std::string& account_id);
145 virtual void PerformAddToChromeAction(const std::string& account_id,
147 virtual void PerformLogoutAllAccountsAction();
149 // Used to remove an account from chrome and the cookie jar.
150 virtual void StartRemoveAction(const std::string& account_id);
151 virtual void FinishRemoveAction(
152 const std::string& account_id,
153 const GoogleServiceAuthError& error,
154 const std::vector<std::pair<std::string, bool> >& accounts);
156 // Used during periodic reconciliation.
157 void StartReconcile();
158 void FinishReconcile();
159 void AbortReconcile();
160 void CalculateIfReconcileIsDone();
161 void ScheduleStartReconcileIfChromeAccountsChanged();
162 void HandleSuccessfulAccountIdCheck(const std::string& account_id);
163 void HandleFailedAccountIdCheck(const std::string& account_id);
164 void HandleRefreshTokenFetched(const std::string& account_id,
165 const std::string& refresh_token);
167 void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
168 void ContinueReconcileActionAfterGetGaiaAccounts(
169 const GoogleServiceAuthError& error,
170 const std::vector<std::pair<std::string, bool> >& accounts);
171 void ValidateAccountsFromTokenService();
173 void OnCookieChanged(ChromeCookieDetails* details);
175 // Overriden from content::NotificationObserver.
176 virtual void Observe(int type,
177 const content::NotificationSource& source,
178 const content::NotificationDetails& details) OVERRIDE;
180 // Overriden from GaiaAuthConsumer.
181 virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
182 virtual void OnListAccountsFailure(
183 const GoogleServiceAuthError& error) OVERRIDE;
185 // Overriden from MergeSessionHelper::Observer.
186 virtual void MergeSessionCompleted(
187 const std::string& account_id,
188 const GoogleServiceAuthError& error) OVERRIDE;
190 // Overriden from OAuth2TokenService::Consumer.
191 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
192 const std::string& access_token,
193 const base::Time& expiration_time) OVERRIDE;
194 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
195 const GoogleServiceAuthError& error) OVERRIDE;
197 // Overriden from OAuth2TokenService::Observer.
198 virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE;
199 virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE;
200 virtual void OnRefreshTokensLoaded() OVERRIDE;
202 // Overriden from SigninManagerBase::Observer.
203 virtual void GoogleSigninSucceeded(const std::string& username,
204 const std::string& password) OVERRIDE;
205 virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
207 void MayBeDoNextListAccounts();
209 // The profile that this reconcilor belongs to.
211 content::NotificationRegistrar registrar_;
212 base::RepeatingTimer<AccountReconcilor> reconciliation_timer_;
213 MergeSessionHelper merge_session_helper_;
214 scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
215 bool registered_with_token_service_;
217 // True while the reconcilor is busy checking or managing the accounts in
219 bool is_reconcile_started_;
221 // Used during reconcile action.
222 // These members are used used to validate the gaia cookie. |gaia_accounts_|
223 // holds the state of google accounts in the gaia cookie. Each element is
224 // a pair that holds the email address of the account and a boolean that
225 // indicates whether the account is valid or not. The accounts in the vector
226 // are ordered the in same way as the gaia cookie.
227 bool are_gaia_accounts_set_;
228 std::vector<std::pair<std::string, bool> > gaia_accounts_;
230 // Used during reconcile action.
231 // These members are used to validate the tokens in OAuth2TokenService.
232 std::string primary_account_;
233 std::vector<std::string> chrome_accounts_;
234 scoped_ptr<OAuth2TokenService::Request>* requests_;
235 ScopedVector<UserIdFetcher> user_id_fetchers_;
236 ScopedVector<SigninOAuthHelper> refresh_token_fetchers_;
237 EmailSet valid_chrome_accounts_;
238 EmailSet invalid_chrome_accounts_;
239 std::vector<std::string> add_to_cookie_;
240 std::vector<std::pair<std::string, int> > add_to_chrome_;
242 std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
244 DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
247 #endif // CHROME_BROWSER_SIGNIN_ACCOUNT_RECONCILOR_H_