blob: 7d3caf4acf4d4d87eb2365a8eb4d1d2723cd9ed8 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
#include <deque>
#include <functional>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/signin_client.h"
#include "components/signin/core/browser/signin_manager.h"
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/merge_session_helper.h"
#include "google_apis/gaia/oauth2_token_service.h"
class GaiaAuthFetcher;
class ProfileOAuth2TokenService;
class SigninClient;
namespace net {
class CanonicalCookie;
}
class AccountReconcilor : public KeyedService,
public GaiaAuthConsumer,
public MergeSessionHelper::Observer,
public OAuth2TokenService::Observer,
public SigninManagerBase::Observer {
public:
AccountReconcilor(ProfileOAuth2TokenService* token_service,
SigninManagerBase* signin_manager,
SigninClient* client);
~AccountReconcilor() override;
void Initialize(bool start_reconcile_if_tokens_available);
// Signal that the status of the new_profile_management flag has changed.
// Pass the new status as an explicit parameter since disabling the flag
// doesn't remove it from the CommandLine::ForCurrentProcess().
void OnNewProfileManagementFlagChanged(bool new_flag_status);
// KeyedService implementation.
void Shutdown() override;
// Add or remove observers for the merge session notification.
void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
ProfileOAuth2TokenService* token_service() { return token_service_; }
SigninClient* client() { return client_; }
protected:
// Used during GetAccountsFromCookie.
// Stores a callback for the next action to perform.
typedef base::Callback<
void(const GoogleServiceAuthError& error,
const std::vector<std::pair<std::string, bool> >&)>
GetAccountsFromCookieCallback;
virtual void GetAccountsFromCookie(GetAccountsFromCookieCallback callback);
private:
bool IsRegisteredWithTokenService() const {
return registered_with_token_service_;
}
bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; }
const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting()
const {
return gaia_accounts_;
}
// Virtual so that it can be overridden in tests.
virtual void StartFetchingExternalCcResult();
friend class AccountReconcilorTest;
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, SigninManagerRegistration);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, Reauth);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ProfileAlreadyConnected);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieSuccess);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, GetAccountsFromCookieFailure);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoop);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopWithDots);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileNoopMultiple);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileAddToCookie);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
StartReconcileRemoveFromCookie);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
StartReconcileAddToCookieTwice);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileBadPrimary);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, StartReconcileOnlyOnce);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
StartReconcileWithSessionInfoExpiredDefault);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest,
MergeSessionCompletedWithBogusAccount);
// Register and unregister with dependent services.
void RegisterForCookieChanges();
void UnregisterForCookieChanges();
void RegisterWithSigninManager();
void UnregisterWithSigninManager();
void RegisterWithTokenService();
void UnregisterWithTokenService();
bool IsProfileConnected();
// All actions with side effects. Virtual so that they can be overridden
// in tests.
virtual void PerformMergeAction(const std::string& account_id);
virtual void PerformLogoutAllAccountsAction();
// Used during periodic reconciliation.
void StartReconcile();
void FinishReconcile();
void AbortReconcile();
void CalculateIfReconcileIsDone();
void ScheduleStartReconcileIfChromeAccountsChanged();
void ContinueReconcileActionAfterGetGaiaAccounts(
const GoogleServiceAuthError& error,
const std::vector<std::pair<std::string, bool> >& accounts);
void ValidateAccountsFromTokenService();
// Note internally that this |account_id| is added to the cookie jar.
bool MarkAccountAsAddedToCookie(const std::string& account_id);
void OnCookieChanged(const net::CanonicalCookie* cookie);
// Overriden from GaiaAuthConsumer.
void OnListAccountsSuccess(const std::string& data) override;
void OnListAccountsFailure(const GoogleServiceAuthError& error) override;
// Overriden from MergeSessionHelper::Observer.
void MergeSessionCompleted(const std::string& account_id,
const GoogleServiceAuthError& error) override;
// Overriden from OAuth2TokenService::Observer.
void OnEndBatchChanges() override;
// Overriden from SigninManagerBase::Observer.
void GoogleSigninSucceeded(const std::string& account_id,
const std::string& username,
const std::string& password) override;
void GoogleSignedOut(const std::string& account_id,
const std::string& username) override;
void MayBeDoNextListAccounts();
// The ProfileOAuth2TokenService associated with this reconcilor.
ProfileOAuth2TokenService* token_service_;
// The SigninManager associated with this reconcilor.
SigninManagerBase* signin_manager_;
// The SigninClient associated with this reconcilor.
SigninClient* client_;
MergeSessionHelper merge_session_helper_;
scoped_ptr<GaiaAuthFetcher> gaia_fetcher_;
bool registered_with_token_service_;
// True while the reconcilor is busy checking or managing the accounts in
// this profile.
bool is_reconcile_started_;
// True iff this is the first time the reconcilor is executing.
bool first_execution_;
// Used during reconcile action.
// These members are used to validate the gaia cookie. |gaia_accounts_|
// holds the state of google accounts in the gaia cookie. Each element is
// a pair that holds the email address of the account and a boolean that
// indicates whether the account is valid or not. The accounts in the vector
// are ordered the in same way as the gaia cookie.
bool are_gaia_accounts_set_;
std::vector<std::pair<std::string, bool> > gaia_accounts_;
// Used during reconcile action.
// These members are used to validate the tokens in OAuth2TokenService.
std::string primary_account_;
std::vector<std::string> chrome_accounts_;
std::vector<std::string> add_to_cookie_;
std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_;
scoped_ptr<SigninClient::CookieChangedCallbackList::Subscription>
cookie_changed_subscription_;
DISALLOW_COPY_AND_ASSIGN(AccountReconcilor);
};
#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_