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_
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"
26 class GaiaAuthFetcher;
27 class ProfileOAuth2TokenService;
29 class SigninOAuthHelper;
32 class CanonicalCookie;
35 class AccountReconcilor : public KeyedService,
36 public GaiaAuthConsumer,
37 public MergeSessionHelper::Observer,
38 public OAuth2TokenService::Consumer,
39 public OAuth2TokenService::Observer,
40 public SigninManagerBase::Observer {
42 AccountReconcilor(ProfileOAuth2TokenService* token_service,
43 SigninManagerBase* signin_manager,
44 SigninClient* client);
45 virtual ~AccountReconcilor();
47 void Initialize(bool start_reconcile_if_tokens_available);
49 // KeyedService implementation.
50 virtual void Shutdown() OVERRIDE;
52 // Add or remove observers for the merge session notification.
53 void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
54 void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
56 ProfileOAuth2TokenService* token_service() { return token_service_; }
57 SigninClient* client() { return client_; }
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> {
69 bool operator()(const std::string& s1, const std::string& s2) const;
71 typedef std::set<std::string, EmailLessFunc> EmailSet;
73 class RefreshTokenFetcher;
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> >& GetGaiaAccountsForTesting()
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<
100 void(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 RegisterForCookieChanges();
127 void UnregisterForCookieChanges();
128 void RegisterWithSigninManager();
129 void UnregisterWithSigninManager();
130 void RegisterWithTokenService();
131 void UnregisterWithTokenService();
133 bool IsProfileConnected();
135 void DeleteFetchers();
137 // All actions with side effects. Virtual so that they can be overridden
139 virtual void PerformMergeAction(const std::string& account_id);
140 virtual void PerformAddToChromeAction(const std::string& account_id,
142 virtual void PerformLogoutAllAccountsAction();
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);
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);
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();
168 void OnCookieChanged(const net::CanonicalCookie* cookie);
170 // Overriden from GaiaAuthConsumer.
171 virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE;
172 virtual void OnListAccountsFailure(const GoogleServiceAuthError& error)
175 // Overriden from MergeSessionHelper::Observer.
176 virtual void MergeSessionCompleted(const std::string& account_id,
177 const GoogleServiceAuthError& error)
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;
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;
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;
197 void MayBeDoNextListAccounts();
199 // The ProfileOAuth2TokenService associated with this reconcilor.
200 ProfileOAuth2TokenService* token_service_;
202 // The SigninManager associated with this reconcilor.
203 SigninManagerBase* signin_manager_;
205 // The SigninClient associated with this reconcilor.
206 SigninClient* client_;
208 MergeSessionHelper merge_session_helper_;
209 scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
210 bool registered_with_token_service_;
212 // True while the reconcilor is busy checking or managing the accounts in
214 bool is_reconcile_started_;
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_;
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_;
237 std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
239 DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
242 #endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_