#include "base/time/time.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_client.h"
-#include "components/signin/core/browser/signin_oauth_helper.h"
+#include "components/signin/core/browser/signin_metrics.h"
+#include "components/signin/core/common/profile_management_switches.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_constants.h"
return p1.second == p2.second && gaia::AreEmailsSame(p1.first, p2.first);
}
-} // namespace
-
-
-// Fetches a refresh token from the given session in the GAIA cookie. This is
-// a best effort only. If it should fail, another reconcile action will occur
-// shortly anyway.
-class AccountReconcilor::RefreshTokenFetcher
- : public SigninOAuthHelper,
- public SigninOAuthHelper::Consumer {
- public:
- RefreshTokenFetcher(AccountReconcilor* reconcilor,
- const std::string& account_id,
- int session_index);
- virtual ~RefreshTokenFetcher() {}
-
- private:
- // Overridden from GaiaAuthConsumer:
- virtual void OnSigninOAuthInformationAvailable(
- const std::string& email,
- const std::string& display_email,
- const std::string& refresh_token) OVERRIDE;
-
- // Called when an error occurs while getting the information.
- virtual void OnSigninOAuthInformationFailure(
- const GoogleServiceAuthError& error) OVERRIDE;
-
- AccountReconcilor* reconcilor_;
- const std::string account_id_;
- int session_index_;
-
- DISALLOW_COPY_AND_ASSIGN(RefreshTokenFetcher);
-};
-
-AccountReconcilor::RefreshTokenFetcher::RefreshTokenFetcher(
- AccountReconcilor* reconcilor,
- const std::string& account_id,
- int session_index)
- : SigninOAuthHelper(reconcilor->client()->GetURLRequestContext(),
- base::IntToString(session_index),
- this),
- reconcilor_(reconcilor),
- account_id_(account_id),
- session_index_(session_index) {
- DCHECK(reconcilor_);
- DCHECK(!account_id.empty());
-}
-
-void AccountReconcilor::RefreshTokenFetcher::OnSigninOAuthInformationAvailable(
- const std::string& email,
- const std::string& display_email,
- const std::string& refresh_token) {
- VLOG(1) << "RefreshTokenFetcher::OnSigninOAuthInformationAvailable:"
- << " account=" << account_id_ << " email=" << email
- << " displayEmail=" << display_email;
-
- // TODO(rogerta): because of the problem with email vs displayEmail and
- // emails that have been canonicalized, the argument |email| is used here
- // to make sure the correct string is used when calling the token service.
- // This will be cleaned up when chrome moves to using gaia obfuscated id.
- reconcilor_->HandleRefreshTokenFetched(email, refresh_token);
-}
-
-void AccountReconcilor::RefreshTokenFetcher::OnSigninOAuthInformationFailure(
- const GoogleServiceAuthError& error) {
- VLOG(1) << "RefreshTokenFetcher::OnSigninOAuthInformationFailure:"
- << " account=" << account_id_ << " session_index=" << session_index_;
- reconcilor_->HandleRefreshTokenFetched(account_id_, std::string());
-}
-
-bool AccountReconcilor::EmailLessFunc::operator()(const std::string& s1,
- const std::string& s2) const {
- return gaia::CanonicalizeEmail(s1) < gaia::CanonicalizeEmail(s2);
-}
-
-class AccountReconcilor::UserIdFetcher
- : public gaia::GaiaOAuthClient::Delegate {
+class AreEmailsSameFunc : public std::equal_to<std::string> {
public:
- UserIdFetcher(AccountReconcilor* reconcilor,
- const std::string& access_token,
- const std::string& account_id);
-
- // Returns the scopes needed by the UserIdFetcher.
- static OAuth2TokenService::ScopeSet GetScopes();
-
- private:
- // Overriden from gaia::GaiaOAuthClient::Delegate.
- virtual void OnGetUserIdResponse(const std::string& user_id) OVERRIDE;
- virtual void OnOAuthError() OVERRIDE;
- virtual void OnNetworkError(int response_code) OVERRIDE;
-
- AccountReconcilor* const reconcilor_;
- const std::string account_id_;
- const std::string access_token_;
- gaia::GaiaOAuthClient gaia_auth_client_;
-
- DISALLOW_COPY_AND_ASSIGN(UserIdFetcher);
+ bool operator()(const std::string& p1,
+ const std::string& p2) const;
};
-AccountReconcilor::UserIdFetcher::UserIdFetcher(AccountReconcilor* reconcilor,
- const std::string& access_token,
- const std::string& account_id)
- : reconcilor_(reconcilor),
- account_id_(account_id),
- access_token_(access_token),
- gaia_auth_client_(reconcilor_->client()->GetURLRequestContext()) {
- DCHECK(reconcilor_);
- DCHECK(!account_id_.empty());
-
- const int kMaxRetries = 5;
- gaia_auth_client_.GetUserId(access_token_, kMaxRetries, this);
-}
-
-// static
-OAuth2TokenService::ScopeSet AccountReconcilor::UserIdFetcher::GetScopes() {
- OAuth2TokenService::ScopeSet scopes;
- scopes.insert("https://www.googleapis.com/auth/userinfo.profile");
- return scopes;
-}
-
-void AccountReconcilor::UserIdFetcher::OnGetUserIdResponse(
- const std::string& user_id) {
- VLOG(1) << "AccountReconcilor::OnGetUserIdResponse: " << account_id_;
-
- // HandleSuccessfulAccountIdCheck() may delete |this|, so call it last.
- reconcilor_->HandleSuccessfulAccountIdCheck(account_id_);
+bool AreEmailsSameFunc::operator()(
+ const std::string& p1,
+ const std::string& p2) const {
+ return gaia::AreEmailsSame(p1, p2);
}
-void AccountReconcilor::UserIdFetcher::OnOAuthError() {
- VLOG(1) << "AccountReconcilor::OnOAuthError: " << account_id_;
-
- // Invalidate the access token to force a refetch next time.
- reconcilor_->token_service()->InvalidateToken(
- account_id_, GetScopes(), access_token_);
-
- // HandleFailedAccountIdCheck() may delete |this|, so call it last.
- reconcilor_->HandleFailedAccountIdCheck(account_id_);
-}
-
-void AccountReconcilor::UserIdFetcher::OnNetworkError(int response_code) {
- VLOG(1) << "AccountReconcilor::OnNetworkError: " << account_id_
- << " response_code=" << response_code;
+} // namespace
- // TODO(rogerta): some response error should not be treated like
- // permanent errors. Figure out appropriate ones.
- // HandleFailedAccountIdCheck() may delete |this|, so call it last.
- reconcilor_->HandleFailedAccountIdCheck(account_id_);
-}
AccountReconcilor::AccountReconcilor(ProfileOAuth2TokenService* token_service,
SigninManagerBase* signin_manager,
SigninClient* client)
- : OAuth2TokenService::Consumer("account_reconcilor"),
- token_service_(token_service),
+ : token_service_(token_service),
signin_manager_(signin_manager),
client_(client),
merge_session_helper_(token_service_,
this),
registered_with_token_service_(false),
is_reconcile_started_(false),
- are_gaia_accounts_set_(false),
- requests_(NULL) {
+ first_execution_(true),
+ are_gaia_accounts_set_(false) {
VLOG(1) << "AccountReconcilor::AccountReconcilor";
}
VLOG(1) << "AccountReconcilor::~AccountReconcilor";
// Make sure shutdown was called first.
DCHECK(!registered_with_token_service_);
- DCHECK(!requests_);
- DCHECK_EQ(0u, user_id_fetchers_.size());
- DCHECK_EQ(0u, refresh_token_fetchers_.size());
}
void AccountReconcilor::Initialize(bool start_reconcile_if_tokens_available) {
merge_session_helper_.CancelAll();
merge_session_helper_.RemoveObserver(this);
gaia_fetcher_.reset();
- DeleteFetchers();
+ get_gaia_accounts_callbacks_.clear();
UnregisterWithSigninManager();
UnregisterWithTokenService();
UnregisterForCookieChanges();
merge_session_helper_.RemoveObserver(observer);
}
-void AccountReconcilor::DeleteFetchers() {
- delete[] requests_;
- requests_ = NULL;
-
- user_id_fetchers_.clear();
- refresh_token_fetchers_.clear();
-}
-
-bool AccountReconcilor::AreAllRefreshTokensChecked() const {
- return chrome_accounts_.size() ==
- (valid_chrome_accounts_.size() + invalid_chrome_accounts_.size());
-}
-
void AccountReconcilor::RegisterForCookieChanges() {
// First clear any existing registration to avoid DCHECKs that can otherwise
// go off in some embedders on reauth (e.g., ChromeSigninClient).
UnregisterForCookieChanges();
- client_->SetCookieChangedCallback(
+ cookie_changed_subscription_ = client_->AddCookieChangedCallback(
base::Bind(&AccountReconcilor::OnCookieChanged, base::Unretained(this)));
}
void AccountReconcilor::UnregisterForCookieChanges() {
- client_->SetCookieChangedCallback(SigninClient::CookieChangedCallback());
+ cookie_changed_subscription_.reset();
}
void AccountReconcilor::RegisterWithSigninManager() {
}
bool AccountReconcilor::IsProfileConnected() {
- return !signin_manager_->GetAuthenticatedUsername().empty();
+ return signin_manager_->IsAuthenticated();
}
void AccountReconcilor::OnCookieChanged(const net::CanonicalCookie* cookie) {
cookie->Domain() == GaiaUrls::GetInstance()->gaia_url().host() &&
cookie->IsSecure() && cookie->IsHttpOnly()) {
VLOG(1) << "AccountReconcilor::OnCookieChanged: LSID changed";
-#ifdef OS_CHROMEOS
- // On Chrome OS it is possible that O2RT is not available at this moment
- // because profile data transfer is still in progress.
+
+ // It is possible that O2RT is not available at this moment.
if (!token_service_->GetAccounts().size()) {
VLOG(1) << "AccountReconcilor::OnCookieChanged: cookie change is ingored"
- "because profile data transfer is in progress.";
+ "because O2RT is not available yet.";
return;
}
-#endif
+
StartReconcile();
}
}
-void AccountReconcilor::OnRefreshTokenAvailable(const std::string& account_id) {
- VLOG(1) << "AccountReconcilor::OnRefreshTokenAvailable: " << account_id;
+void AccountReconcilor::OnEndBatchChanges() {
+ VLOG(1) << "AccountReconcilor::OnEndBatchChanges";
StartReconcile();
}
-void AccountReconcilor::OnRefreshTokenRevoked(const std::string& account_id) {
- VLOG(1) << "AccountReconcilor::OnRefreshTokenRevoked: " << account_id;
- StartRemoveAction(account_id);
-}
-
-void AccountReconcilor::OnRefreshTokensLoaded() {}
-
-void AccountReconcilor::GoogleSigninSucceeded(const std::string& username,
+void AccountReconcilor::GoogleSigninSucceeded(const std::string& account_id,
+ const std::string& username,
const std::string& password) {
VLOG(1) << "AccountReconcilor::GoogleSigninSucceeded: signed in";
RegisterForCookieChanges();
RegisterWithTokenService();
}
-void AccountReconcilor::GoogleSignedOut(const std::string& username) {
+void AccountReconcilor::GoogleSignedOut(const std::string& account_id,
+ const std::string& username) {
VLOG(1) << "AccountReconcilor::GoogleSignedOut: signed out";
+ gaia_fetcher_.reset();
+ get_gaia_accounts_callbacks_.clear();
+ AbortReconcile();
UnregisterWithTokenService();
UnregisterForCookieChanges();
+ PerformLogoutAllAccountsAction();
}
void AccountReconcilor::PerformMergeAction(const std::string& account_id) {
+ if (!switches::IsEnableAccountConsistency()) {
+ MarkAccountAsAddedToCookie(account_id);
+ return;
+ }
VLOG(1) << "AccountReconcilor::PerformMergeAction: " << account_id;
merge_session_helper_.LogIn(account_id);
}
-void AccountReconcilor::StartRemoveAction(const std::string& account_id) {
- VLOG(1) << "AccountReconcilor::StartRemoveAction: " << account_id;
- GetAccountsFromCookie(base::Bind(&AccountReconcilor::FinishRemoveAction,
- base::Unretained(this),
- account_id));
-}
-
-void AccountReconcilor::FinishRemoveAction(
- const std::string& account_id,
- const GoogleServiceAuthError& error,
- const std::vector<std::pair<std::string, bool> >& accounts) {
- VLOG(1) << "AccountReconcilor::FinishRemoveAction:"
- << " account=" << account_id << " error=" << error.ToString();
- if (error.state() == GoogleServiceAuthError::NONE) {
- AbortReconcile();
- std::vector<std::string> accounts_only;
- for (std::vector<std::pair<std::string, bool> >::const_iterator i =
- accounts.begin();
- i != accounts.end();
- ++i) {
- accounts_only.push_back(i->first);
- }
- merge_session_helper_.LogOut(account_id, accounts_only);
- }
- // Wait for the next ReconcileAction if there is an error.
-}
-
-void AccountReconcilor::PerformAddToChromeAction(const std::string& account_id,
- int session_index) {
- VLOG(1) << "AccountReconcilor::PerformAddToChromeAction:"
- << " account=" << account_id << " session_index=" << session_index;
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
- refresh_token_fetchers_.push_back(
- new RefreshTokenFetcher(this, account_id, session_index));
-#endif
-}
-
void AccountReconcilor::PerformLogoutAllAccountsAction() {
+ if (!switches::IsEnableAccountConsistency())
+ return;
VLOG(1) << "AccountReconcilor::PerformLogoutAllAccountsAction";
merge_session_helper_.LogOutAllAccounts();
}
void AccountReconcilor::StartReconcile() {
- if (!IsProfileConnected() || is_reconcile_started_)
+ if (!IsProfileConnected() || is_reconcile_started_ ||
+ get_gaia_accounts_callbacks_.size() > 0 ||
+ merge_session_helper_.is_running())
return;
is_reconcile_started_ = true;
+ StartFetchingExternalCcResult();
+
// Reset state for validating gaia cookie.
are_gaia_accounts_set_ = false;
gaia_accounts_.clear();
// Reset state for validating oauth2 tokens.
primary_account_.clear();
chrome_accounts_.clear();
- DeleteFetchers();
- valid_chrome_accounts_.clear();
- invalid_chrome_accounts_.clear();
add_to_cookie_.clear();
- add_to_chrome_.clear();
ValidateAccountsFromTokenService();
}
}
}
+void AccountReconcilor::StartFetchingExternalCcResult() {
+ merge_session_helper_.StartFetchingExternalCcResult();
+}
+
void AccountReconcilor::OnListAccountsSuccess(const std::string& data) {
gaia_fetcher_.reset();
}
void AccountReconcilor::ValidateAccountsFromTokenService() {
- primary_account_ = signin_manager_->GetAuthenticatedUsername();
+ primary_account_ = signin_manager_->GetAuthenticatedAccountId();
DCHECK(!primary_account_.empty());
chrome_accounts_ = token_service_->GetAccounts();
- DCHECK_GT(chrome_accounts_.size(), 0u);
VLOG(1) << "AccountReconcilor::ValidateAccountsFromTokenService: "
<< "Chrome " << chrome_accounts_.size() << " accounts, "
<< "Primary is '" << primary_account_ << "'";
-
- DCHECK(!requests_);
- requests_ =
- new scoped_ptr<OAuth2TokenService::Request>[chrome_accounts_.size()];
- const OAuth2TokenService::ScopeSet scopes =
- AccountReconcilor::UserIdFetcher::GetScopes();
- for (size_t i = 0; i < chrome_accounts_.size(); ++i) {
- requests_[i] =
- token_service_->StartRequest(chrome_accounts_[i], scopes, this);
- }
-
- DCHECK_EQ(0u, user_id_fetchers_.size());
- user_id_fetchers_.resize(chrome_accounts_.size());
-}
-
-void AccountReconcilor::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) {
- size_t index;
- for (index = 0; index < chrome_accounts_.size(); ++index) {
- if (request == requests_[index].get())
- break;
- }
- DCHECK(index < chrome_accounts_.size());
-
- const std::string& account_id = chrome_accounts_[index];
-
- VLOG(1) << "AccountReconcilor::OnGetTokenSuccess: valid " << account_id;
-
- DCHECK(!user_id_fetchers_[index]);
- user_id_fetchers_[index] = new UserIdFetcher(this, access_token, account_id);
}
-void AccountReconcilor::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) {
- size_t index;
- for (index = 0; index < chrome_accounts_.size(); ++index) {
- if (request == requests_[index].get())
- break;
+void AccountReconcilor::OnNewProfileManagementFlagChanged(
+ bool new_flag_status) {
+ if (new_flag_status) {
+ // The reconciler may have been newly created just before this call, or may
+ // have already existed and in mid-reconcile. To err on the safe side, force
+ // a restart.
+ Shutdown();
+ Initialize(true);
+ } else {
+ Shutdown();
}
- DCHECK(index < chrome_accounts_.size());
-
- const std::string& account_id = chrome_accounts_[index];
-
- VLOG(1) << "AccountReconcilor::OnGetTokenFailure: invalid " << account_id;
- HandleFailedAccountIdCheck(account_id);
}
void AccountReconcilor::FinishReconcile() {
- // Make sure that the process of validating the gaia cookie and the oauth2
- // tokens individually is done before proceeding with reconciliation.
- if (!are_gaia_accounts_set_ || !AreAllRefreshTokensChecked())
- return;
-
VLOG(1) << "AccountReconcilor::FinishReconcile";
-
- DeleteFetchers();
-
+ DCHECK(are_gaia_accounts_set_);
DCHECK(add_to_cookie_.empty());
- DCHECK(add_to_chrome_.empty());
- bool are_primaries_equal =
- gaia_accounts_.size() > 0 &&
+ int number_gaia_accounts = gaia_accounts_.size();
+ bool are_primaries_equal = number_gaia_accounts > 0 &&
gaia::AreEmailsSame(primary_account_, gaia_accounts_[0].first);
- if (are_primaries_equal) {
- // Determine if we need to merge accounts from gaia cookie to chrome.
- for (size_t i = 0; i < gaia_accounts_.size(); ++i) {
- const std::string& gaia_account = gaia_accounts_[i].first;
- if (gaia_accounts_[i].second &&
- valid_chrome_accounts_.find(gaia_account) ==
- valid_chrome_accounts_.end()) {
- add_to_chrome_.push_back(std::make_pair(gaia_account, i));
- }
+ // If there are any accounts in the gaia cookie but not in chrome, then
+ // those accounts need to be removed from the cookie. This means we need
+ // to blow the cookie away.
+ int removed_from_cookie = 0;
+ for (size_t i = 0; i < gaia_accounts_.size(); ++i) {
+ const std::string& gaia_account = gaia_accounts_[i].first;
+ if (gaia_accounts_[i].second &&
+ chrome_accounts_.end() ==
+ std::find_if(chrome_accounts_.begin(),
+ chrome_accounts_.end(),
+ std::bind1st(AreEmailsSameFunc(), gaia_account))) {
+ ++removed_from_cookie;
}
- } else {
+ }
+
+ bool rebuild_cookie = !are_primaries_equal || removed_from_cookie > 0;
+ std::vector<std::pair<std::string, bool> > original_gaia_accounts =
+ gaia_accounts_;
+ if (rebuild_cookie) {
VLOG(1) << "AccountReconcilor::FinishReconcile: rebuild cookie";
// Really messed up state. Blow away the gaia cookie completely and
// rebuild it, making sure the primary account as specified by the
// The primary account must be first to make sure it becomes the default
// account in the case where chrome is completely rebuilding the cookie.
add_to_cookie_.push_back(primary_account_);
- for (EmailSet::const_iterator i = valid_chrome_accounts_.begin();
- i != valid_chrome_accounts_.end();
- ++i) {
- if (*i != primary_account_)
- add_to_cookie_.push_back(*i);
+ for (size_t i = 0; i < chrome_accounts_.size(); ++i) {
+ if (chrome_accounts_[i] != primary_account_)
+ add_to_cookie_.push_back(chrome_accounts_[i]);
}
// For each account known to chrome, PerformMergeAction() if the account is
// completed otherwise. Make a copy of |add_to_cookie_| since calls to
// SignalComplete() will change the array.
std::vector<std::string> add_to_cookie_copy = add_to_cookie_;
+ int added_to_cookie = 0;
+ bool external_cc_result_completed =
+ !merge_session_helper_.StillFetchingExternalCcResult();
for (size_t i = 0; i < add_to_cookie_copy.size(); ++i) {
if (gaia_accounts_.end() !=
std::find_if(gaia_accounts_.begin(),
GoogleServiceAuthError::AuthErrorNone());
} else {
PerformMergeAction(add_to_cookie_copy[i]);
+ if (original_gaia_accounts.end() ==
+ std::find_if(original_gaia_accounts.begin(),
+ original_gaia_accounts.end(),
+ std::bind1st(EmailEqualToFunc(),
+ std::make_pair(add_to_cookie_copy[i],
+ true)))) {
+ added_to_cookie++;
+ }
}
}
- // For each account in the gaia cookie not known to chrome,
- // PerformAddToChromeAction.
- for (std::vector<std::pair<std::string, int> >::const_iterator i =
- add_to_chrome_.begin();
- i != add_to_chrome_.end();
- ++i) {
- PerformAddToChromeAction(i->first, i->second);
- }
-
+ // Log whether the external connection checks were completed when we tried
+ // to add the accounts to the cookie.
+ if (rebuild_cookie || added_to_cookie > 0)
+ signin_metrics::LogExternalCcResultFetches(external_cc_result_completed);
+
+ signin_metrics::LogSigninAccountReconciliation(chrome_accounts_.size(),
+ added_to_cookie,
+ removed_from_cookie,
+ are_primaries_equal,
+ first_execution_,
+ number_gaia_accounts);
+ first_execution_ = false;
CalculateIfReconcileIsDone();
ScheduleStartReconcileIfChromeAccountsChanged();
}
void AccountReconcilor::AbortReconcile() {
VLOG(1) << "AccountReconcilor::AbortReconcile: we'll try again later";
- DeleteFetchers();
add_to_cookie_.clear();
- add_to_chrome_.clear();
CalculateIfReconcileIsDone();
}
void AccountReconcilor::CalculateIfReconcileIsDone() {
- is_reconcile_started_ = !add_to_cookie_.empty() || !add_to_chrome_.empty();
+ is_reconcile_started_ = !add_to_cookie_.empty();
if (!is_reconcile_started_)
VLOG(1) << "AccountReconcilor::CalculateIfReconcileIsDone: done";
}
}
}
-void AccountReconcilor::MergeSessionCompleted(
- const std::string& account_id,
- const GoogleServiceAuthError& error) {
- VLOG(1) << "AccountReconcilor::MergeSessionCompleted: account_id="
- << account_id;
-
- // Remove the account from the list that is being merged.
+// Remove the account from the list that is being merged.
+bool AccountReconcilor::MarkAccountAsAddedToCookie(
+ const std::string& account_id) {
for (std::vector<std::string>::iterator i = add_to_cookie_.begin();
i != add_to_cookie_.end();
++i) {
if (account_id == *i) {
add_to_cookie_.erase(i);
- break;
+ return true;
}
}
-
- CalculateIfReconcileIsDone();
- ScheduleStartReconcileIfChromeAccountsChanged();
+ return false;
}
-void AccountReconcilor::HandleSuccessfulAccountIdCheck(
- const std::string& account_id) {
- valid_chrome_accounts_.insert(account_id);
- FinishReconcile();
-}
-
-void AccountReconcilor::HandleFailedAccountIdCheck(
- const std::string& account_id) {
- invalid_chrome_accounts_.insert(account_id);
- FinishReconcile();
-}
-
-void AccountReconcilor::HandleRefreshTokenFetched(
+void AccountReconcilor::MergeSessionCompleted(
const std::string& account_id,
- const std::string& refresh_token) {
- if (!refresh_token.empty()) {
- token_service_->UpdateCredentials(account_id, refresh_token);
- }
+ const GoogleServiceAuthError& error) {
+ VLOG(1) << "AccountReconcilor::MergeSessionCompleted: account_id="
+ << account_id << " error=" << error.ToString();
- // Remove the account from the list that is being updated.
- for (std::vector<std::pair<std::string, int> >::iterator i =
- add_to_chrome_.begin();
- i != add_to_chrome_.end();
- ++i) {
- if (gaia::AreEmailsSame(account_id, i->first)) {
- add_to_chrome_.erase(i);
- break;
- }
+ if (MarkAccountAsAddedToCookie(account_id)) {
+ CalculateIfReconcileIsDone();
+ ScheduleStartReconcileIfChromeAccountsChanged();
}
-
- CalculateIfReconcileIsDone();
}