account_reconcilor.h revision 116680a4aac90f2aa7413d9095a592090648e557
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 // Signal that the status of the new_profile_management flag has changed. 50 // Pass the new status as an explicit parameter since disabling the flag 51 // doesn't remove it from the CommandLine::ForCurrentProcess(). 52 void OnNewProfileManagementFlagChanged(bool new_flag_status); 53 54 // KeyedService implementation. 55 virtual void Shutdown() OVERRIDE; 56 57 // Add or remove observers for the merge session notification. 58 void AddMergeSessionObserver(MergeSessionHelper::Observer* observer); 59 void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer); 60 61 ProfileOAuth2TokenService* token_service() { return token_service_; } 62 SigninClient* client() { return client_; } 63 64 protected: 65 // Used during GetAccountsFromCookie. 66 // Stores a callback for the next action to perform. 67 typedef base::Callback< 68 void(const GoogleServiceAuthError& error, 69 const std::vector<std::pair<std::string, bool> >&)> 70 GetAccountsFromCookieCallback; 71 72 virtual void GetAccountsFromCookie(GetAccountsFromCookieCallback callback); 73 74 private: 75 // An std::set<> for use with email addresses that uses 76 // gaia::CanonicalizeEmail() during comparisons. 77 // TODO(rogerta): this is a workaround for the fact that SigninManager and 78 // SigninOAuthHelper use the gaia "email" property when adding accounts to 79 // the token service, whereas gaia::ParseListAccountsData() returns email 80 // addresses that have been passed through gaia::CanonicalizeEmail(). These 81 // two types of email addresses are not directly comparable. 82 class EmailLessFunc : public std::less<std::string> { 83 public: 84 bool operator()(const std::string& s1, const std::string& s2) const; 85 }; 86 typedef std::set<std::string, EmailLessFunc> EmailSet; 87 88 class RefreshTokenFetcher; 89 class UserIdFetcher; 90 91 bool IsRegisteredWithTokenService() const { 92 return registered_with_token_service_; 93 } 94 95 bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; } 96 97 bool AreAllRefreshTokensChecked() const; 98 99 const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting() 100 const { 101 return gaia_accounts_; 102 } 103 104 const EmailSet& GetValidChromeAccountsForTesting() const { 105 return valid_chrome_accounts_; 106 } 107 108 const EmailSet& GetInvalidChromeAccountsForTesting() const { 109 return invalid_chrome_accounts_; 110 } 111 112 113 friend class AccountReconcilorTest; 114 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, SigninManagerRegistration); 115 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, Reauth); 116 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ProfileAlreadyConnected); 117 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieSuccess); 118 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieFailure); 119 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ValidateAccountsFromTokens); 120 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 121 ValidateAccountsFromTokensFailedUserInfo); 122 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 123 ValidateAccountsFromTokensFailedTokenRequest); 124 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoop); 125 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopWithDots); 126 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopMultiple); 127 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToCookie); 128 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 129 StartReconcileAddToCookieTwice); 130 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToChrome); 131 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileBadPrimary); 132 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileOnlyOnce); 133 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 134 StartReconcileWithSessionInfoExpiredDefault); 135 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 136 MergeSessionCompletedWithBogusAccount); 137 138 // Register and unregister with dependent services. 139 void RegisterForCookieChanges(); 140 void UnregisterForCookieChanges(); 141 void RegisterWithSigninManager(); 142 void UnregisterWithSigninManager(); 143 void RegisterWithTokenService(); 144 void UnregisterWithTokenService(); 145 146 bool IsProfileConnected(); 147 148 void DeleteFetchers(); 149 150 // All actions with side effects. Virtual so that they can be overridden 151 // in tests. 152 virtual void PerformMergeAction(const std::string& account_id); 153 virtual void PerformAddToChromeAction( 154 const std::string& account_id, 155 int session_index, 156 const std::string& signin_scoped_device_id); 157 virtual void PerformLogoutAllAccountsAction(); 158 virtual void PerformAddAccountToTokenService( 159 const std::string& account_id, 160 const std::string& refresh_token); 161 162 // Used to remove an account from chrome and the cookie jar. 163 virtual void PerformStartRemoveAction(const std::string& account_id); 164 virtual void PerformFinishRemoveAction( 165 const std::string& account_id, 166 const GoogleServiceAuthError& error, 167 const std::vector<std::pair<std::string, bool> >& accounts); 168 169 // Used during periodic reconciliation. 170 void StartReconcile(); 171 void FinishReconcile(); 172 void AbortReconcile(); 173 void CalculateIfReconcileIsDone(); 174 void ScheduleStartReconcileIfChromeAccountsChanged(); 175 void HandleSuccessfulAccountIdCheck(const std::string& account_id); 176 void HandleFailedAccountIdCheck(const std::string& account_id); 177 void HandleRefreshTokenFetched(const std::string& account_id, 178 const std::string& refresh_token); 179 180 void ContinueReconcileActionAfterGetGaiaAccounts( 181 const GoogleServiceAuthError& error, 182 const std::vector<std::pair<std::string, bool> >& accounts); 183 void ValidateAccountsFromTokenService(); 184 // Note internally that this |account_id| is added to the cookie jar. 185 bool MarkAccountAsAddedToCookie(const std::string& account_id); 186 // Note internally that this |account_id| is added to the token service. 187 void MarkAccountAsAddedToChrome(const std::string& account_id); 188 189 void OnCookieChanged(const net::CanonicalCookie* cookie); 190 191 // Overriden from GaiaAuthConsumer. 192 virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE; 193 virtual void OnListAccountsFailure(const GoogleServiceAuthError& error) 194 OVERRIDE; 195 196 // Overriden from MergeSessionHelper::Observer. 197 virtual void MergeSessionCompleted(const std::string& account_id, 198 const GoogleServiceAuthError& error) 199 OVERRIDE; 200 201 // Overriden from OAuth2TokenService::Consumer. 202 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 203 const std::string& access_token, 204 const base::Time& expiration_time) OVERRIDE; 205 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 206 const GoogleServiceAuthError& error) OVERRIDE; 207 208 // Overriden from OAuth2TokenService::Observer. 209 virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE; 210 virtual void OnEndBatchChanges() OVERRIDE; 211 212 // Overriden from SigninManagerBase::Observer. 213 virtual void GoogleSigninSucceeded(const std::string& username, 214 const std::string& password) OVERRIDE; 215 virtual void GoogleSignedOut(const std::string& username) OVERRIDE; 216 217 void MayBeDoNextListAccounts(); 218 219 // The ProfileOAuth2TokenService associated with this reconcilor. 220 ProfileOAuth2TokenService* token_service_; 221 222 // The SigninManager associated with this reconcilor. 223 SigninManagerBase* signin_manager_; 224 225 // The SigninClient associated with this reconcilor. 226 SigninClient* client_; 227 228 MergeSessionHelper merge_session_helper_; 229 scoped_ptr<GaiaAuthFetcher> gaia_fetcher_; 230 bool registered_with_token_service_; 231 232 // True while the reconcilor is busy checking or managing the accounts in 233 // this profile. 234 bool is_reconcile_started_; 235 236 // True iff this is the first time the reconcilor is executing. 237 bool first_execution_; 238 239 // Used during reconcile action. 240 // These members are used used to validate the gaia cookie. |gaia_accounts_| 241 // holds the state of google accounts in the gaia cookie. Each element is 242 // a pair that holds the email address of the account and a boolean that 243 // indicates whether the account is valid or not. The accounts in the vector 244 // are ordered the in same way as the gaia cookie. 245 bool are_gaia_accounts_set_; 246 std::vector<std::pair<std::string, bool> > gaia_accounts_; 247 248 // Used during reconcile action. 249 // These members are used to validate the tokens in OAuth2TokenService. 250 std::string primary_account_; 251 std::vector<std::string> chrome_accounts_; 252 scoped_ptr<OAuth2TokenService::Request>* requests_; 253 ScopedVector<UserIdFetcher> user_id_fetchers_; 254 ScopedVector<SigninOAuthHelper> refresh_token_fetchers_; 255 EmailSet valid_chrome_accounts_; 256 EmailSet invalid_chrome_accounts_; 257 std::vector<std::string> add_to_cookie_; 258 std::vector<std::pair<std::string, int> > add_to_chrome_; 259 260 std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_; 261 262 DISALLOW_COPY_AND_ASSIGN(AccountReconcilor); 263}; 264 265#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_ 266