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