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