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_client.h" 21 #include "components/signin/core/browser/signin_manager.h" 22 #include "google_apis/gaia/gaia_auth_consumer.h" 23 #include "google_apis/gaia/google_service_auth_error.h" 24 #include "google_apis/gaia/merge_session_helper.h" 25 #include "google_apis/gaia/oauth2_token_service.h" 26 27 class GaiaAuthFetcher; 28 class ProfileOAuth2TokenService; 29 class SigninClient; 30 31 namespace net { 32 class CanonicalCookie; 33 } 34 35 class AccountReconcilor : public KeyedService, 36 public GaiaAuthConsumer, 37 public MergeSessionHelper::Observer, 38 public OAuth2TokenService::Observer, 39 public SigninManagerBase::Observer { 40 public: 41 AccountReconcilor(ProfileOAuth2TokenService* token_service, 42 SigninManagerBase* signin_manager, 43 SigninClient* client); 44 virtual ~AccountReconcilor(); 45 46 void Initialize(bool start_reconcile_if_tokens_available); 47 48 // Signal that the status of the new_profile_management flag has changed. 49 // Pass the new status as an explicit parameter since disabling the flag 50 // doesn't remove it from the CommandLine::ForCurrentProcess(). 51 void OnNewProfileManagementFlagChanged(bool new_flag_status); 52 53 // KeyedService implementation. 54 virtual void Shutdown() OVERRIDE; 55 56 // Add or remove observers for the merge session notification. 57 void AddMergeSessionObserver(MergeSessionHelper::Observer* observer); 58 void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer); 59 token_service()60 ProfileOAuth2TokenService* token_service() { return token_service_; } client()61 SigninClient* client() { return client_; } 62 63 protected: 64 // Used during GetAccountsFromCookie. 65 // Stores a callback for the next action to perform. 66 typedef base::Callback< 67 void(const GoogleServiceAuthError& error, 68 const std::vector<std::pair<std::string, bool> >&)> 69 GetAccountsFromCookieCallback; 70 71 virtual void GetAccountsFromCookie(GetAccountsFromCookieCallback callback); 72 73 private: IsRegisteredWithTokenService()74 bool IsRegisteredWithTokenService() const { 75 return registered_with_token_service_; 76 } 77 AreGaiaAccountsSet()78 bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; } 79 GetGaiaAccountsForTesting()80 const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting() 81 const { 82 return gaia_accounts_; 83 } 84 85 // Virtual so that it can be overridden in tests. 86 virtual void StartFetchingExternalCcResult(); 87 88 friend class AccountReconcilorTest; 89 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, SigninManagerRegistration); 90 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, Reauth); 91 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ProfileAlreadyConnected); 92 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieSuccess); 93 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieFailure); 94 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoop); 95 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopWithDots); 96 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopMultiple); 97 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToCookie); 98 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 99 StartReconcileRemoveFromCookie); 100 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 101 StartReconcileAddToCookieTwice); 102 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileBadPrimary); 103 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileOnlyOnce); 104 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 105 StartReconcileWithSessionInfoExpiredDefault); 106 FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, 107 MergeSessionCompletedWithBogusAccount); 108 109 // Register and unregister with dependent services. 110 void RegisterForCookieChanges(); 111 void UnregisterForCookieChanges(); 112 void RegisterWithSigninManager(); 113 void UnregisterWithSigninManager(); 114 void RegisterWithTokenService(); 115 void UnregisterWithTokenService(); 116 117 bool IsProfileConnected(); 118 119 // All actions with side effects. Virtual so that they can be overridden 120 // in tests. 121 virtual void PerformMergeAction(const std::string& account_id); 122 virtual void PerformLogoutAllAccountsAction(); 123 124 // Used during periodic reconciliation. 125 void StartReconcile(); 126 void FinishReconcile(); 127 void AbortReconcile(); 128 void CalculateIfReconcileIsDone(); 129 void ScheduleStartReconcileIfChromeAccountsChanged(); 130 131 void ContinueReconcileActionAfterGetGaiaAccounts( 132 const GoogleServiceAuthError& error, 133 const std::vector<std::pair<std::string, bool> >& accounts); 134 void ValidateAccountsFromTokenService(); 135 // Note internally that this |account_id| is added to the cookie jar. 136 bool MarkAccountAsAddedToCookie(const std::string& account_id); 137 138 void OnCookieChanged(const net::CanonicalCookie* cookie); 139 140 // Overriden from GaiaAuthConsumer. 141 virtual void OnListAccountsSuccess(const std::string& data) OVERRIDE; 142 virtual void OnListAccountsFailure(const GoogleServiceAuthError& error) 143 OVERRIDE; 144 145 // Overriden from MergeSessionHelper::Observer. 146 virtual void MergeSessionCompleted(const std::string& account_id, 147 const GoogleServiceAuthError& error) 148 OVERRIDE; 149 150 // Overriden from OAuth2TokenService::Observer. 151 virtual void OnEndBatchChanges() OVERRIDE; 152 153 // Overriden from SigninManagerBase::Observer. 154 virtual void GoogleSigninSucceeded(const std::string& account_id, 155 const std::string& username, 156 const std::string& password) OVERRIDE; 157 virtual void GoogleSignedOut(const std::string& account_id, 158 const std::string& username) OVERRIDE; 159 160 void MayBeDoNextListAccounts(); 161 162 // The ProfileOAuth2TokenService associated with this reconcilor. 163 ProfileOAuth2TokenService* token_service_; 164 165 // The SigninManager associated with this reconcilor. 166 SigninManagerBase* signin_manager_; 167 168 // The SigninClient associated with this reconcilor. 169 SigninClient* client_; 170 171 MergeSessionHelper merge_session_helper_; 172 scoped_ptr<GaiaAuthFetcher> gaia_fetcher_; 173 bool registered_with_token_service_; 174 175 // True while the reconcilor is busy checking or managing the accounts in 176 // this profile. 177 bool is_reconcile_started_; 178 179 // True iff this is the first time the reconcilor is executing. 180 bool first_execution_; 181 182 // Used during reconcile action. 183 // These members are used to validate the gaia cookie. |gaia_accounts_| 184 // holds the state of google accounts in the gaia cookie. Each element is 185 // a pair that holds the email address of the account and a boolean that 186 // indicates whether the account is valid or not. The accounts in the vector 187 // are ordered the in same way as the gaia cookie. 188 bool are_gaia_accounts_set_; 189 std::vector<std::pair<std::string, bool> > gaia_accounts_; 190 191 // Used during reconcile action. 192 // These members are used to validate the tokens in OAuth2TokenService. 193 std::string primary_account_; 194 std::vector<std::string> chrome_accounts_; 195 std::vector<std::string> add_to_cookie_; 196 197 std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_; 198 199 scoped_ptr<SigninClient::CookieChangedCallbackList::Subscription> 200 cookie_changed_subscription_; 201 202 DISALLOW_COPY_AND_ASSIGN(AccountReconcilor); 203 }; 204 205 #endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_ 206