Commit af984caa authored by Alex Ilin's avatar Alex Ilin Committed by Commit Bot

[Signin] Block AccountReconcilor on log out completion

While working on live tests I discovered that there is no reliable way
to observe account deletion from cookies during the log out.
AccountReconcilor changes its state to DONE as soon as Gaia log out is
started without waiting for the log out request completion.

This CL adds missing log out observers to GaiaCookieManagerService and
makes AccountReconcilor wait until the log out is done.

NOTE: This CL doesn't block AccountReconcilor on log out completion if
multilogin endpoint is used. This is left as a TODO in code.

Bug: 1054167
Change-Id: If10aede8c5ed10791f4554e91c39526772e075ce
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1832263
Commit-Queue: Alex Ilin <alexilin@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#750931}
parent f530de6f
......@@ -238,7 +238,8 @@ void ProcessMirrorHeader(
gaia::AreEmailsSame(primary_account.email,
manage_accounts_params.email)) {
identity_manager->GetAccountsCookieMutator()->LogOutAllAccounts(
gaia::GaiaSource::kChromeOS);
gaia::GaiaSource::kChromeOS,
signin::AccountsCookieMutator::LogOutFromCookieCompletedCallback());
UMA_HISTOGRAM_BOOLEAN("AccountManager.MirrorReauthenticationRequest",
true);
return;
......
......@@ -238,6 +238,7 @@ AccountReconcilor::AccountReconcilor(
error_during_last_reconcile_(GoogleServiceAuthError::AuthErrorNone()),
reconcile_is_noop_(true),
set_accounts_in_progress_(false),
log_out_in_progress_(false),
chrome_accounts_changed_(false),
account_reconcilor_lock_count_(0),
reconcile_on_unblock_(false),
......@@ -445,7 +446,9 @@ void AccountReconcilor::PerformLogoutAllAccountsAction() {
return;
VLOG(1) << "AccountReconcilor::PerformLogoutAllAccountsAction";
identity_manager_->GetAccountsCookieMutator()->LogOutAllAccounts(
delegate_->GetGaiaApiSource());
delegate_->GetGaiaApiSource(),
base::BindOnce(&AccountReconcilor::OnLogOutFromCookieCompleted,
weak_factory_.GetWeakPtr()));
}
void AccountReconcilor::StartReconcile() {
......@@ -541,6 +544,7 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
// instead.
PerformLogoutAllAccountsAction();
gaia_accounts.clear();
// TODO(alexilin): Asynchronously wait until the logout is complete.
OnSetAccountsInCookieCompleted(
signin::SetAccountsInCookieResult::kSuccess);
DCHECK(!is_reconcile_started_);
......@@ -754,6 +758,7 @@ void AccountReconcilor::FinishReconcile(
// Really messed up state. Blow away the gaia cookie completely and
// rebuild it, making sure the primary account as specified by the
// IdentityManager is the first session in the gaia cookie.
log_out_in_progress_ = true;
PerformLogoutAllAccountsAction();
gaia_accounts.clear();
}
......@@ -816,6 +821,7 @@ void AccountReconcilor::FinishReconcile(
void AccountReconcilor::AbortReconcile() {
VLOG(1) << "AccountReconcilor::AbortReconcile: try again later";
log_out_in_progress_ = false;
add_to_cookie_.clear();
CalculateIfReconcileIsDone();
......@@ -826,7 +832,8 @@ void AccountReconcilor::AbortReconcile() {
void AccountReconcilor::CalculateIfReconcileIsDone() {
base::TimeDelta duration = base::Time::Now() - reconcile_start_time_;
// Record the duration if reconciliation was underway and now it is over.
if (is_reconcile_started_ && add_to_cookie_.empty()) {
if (is_reconcile_started_ && add_to_cookie_.empty() &&
!log_out_in_progress_) {
bool was_last_reconcile_successful =
(error_during_last_reconcile_.state() ==
GoogleServiceAuthError::State::NONE);
......@@ -848,7 +855,7 @@ void AccountReconcilor::CalculateIfReconcileIsDone() {
}
}
is_reconcile_started_ = !add_to_cookie_.empty();
is_reconcile_started_ = !add_to_cookie_.empty() || log_out_in_progress_;
if (!is_reconcile_started_)
VLOG(1) << "AccountReconcilor::CalculateIfReconcileIsDone: done";
}
......@@ -939,6 +946,23 @@ void AccountReconcilor::OnAddAccountToCookieCompleted(
}
}
void AccountReconcilor::OnLogOutFromCookieCompleted(
const GoogleServiceAuthError& error) {
VLOG(1) << "AccountReconcilor::OnLogOutFromCookieCompleted: "
<< "Error was " << error.ToString();
if (is_reconcile_started_) {
if (error.state() != GoogleServiceAuthError::State::NONE &&
!error_during_last_reconcile_.IsPersistentError()) {
error_during_last_reconcile_ = error;
}
log_out_in_progress_ = false;
CalculateIfReconcileIsDone();
ScheduleStartReconcileIfChromeAccountsChanged();
}
}
void AccountReconcilor::IncrementLockCount() {
DCHECK_GE(account_reconcilor_lock_count_, 0);
++account_reconcilor_lock_count_;
......
......@@ -284,6 +284,7 @@ class AccountReconcilor : public KeyedService,
void OnAddAccountToCookieCompleted(const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
void OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult result);
void OnLogOutFromCookieCompleted(const GoogleServiceAuthError& error);
// Lock related methods.
void IncrementLockCount();
......@@ -343,6 +344,7 @@ class AccountReconcilor : public KeyedService,
// Used during reconcile action.
std::vector<CoreAccountId> add_to_cookie_; // Progress of AddAccount calls.
bool set_accounts_in_progress_; // Progress of SetAccounts calls.
bool log_out_in_progress_; // Progress of LogOut calls.
bool chrome_accounts_changed_;
// Used for the Lock.
......
......@@ -255,14 +255,17 @@ class AccountReconcilorTest : public ::testing::Test {
const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
void SimulateCookieContentSettingsChanged(
content_settings::Observer* observer,
const ContentSettingsPattern& primary_pattern);
void SimulateSetAccountsInCookieCompleted(
AccountReconcilor* reconcilor,
signin::SetAccountsInCookieResult result);
void SimulateLogOutFromCookieCompleted(AccountReconcilor* reconcilor,
const GoogleServiceAuthError& error);
void SimulateCookieContentSettingsChanged(
content_settings::Observer* observer,
const ContentSettingsPattern& primary_pattern);
void SetAccountConsistency(signin::AccountConsistencyMethod method);
// Should never be called before |SetAccountConsistency|.
......@@ -384,6 +387,12 @@ void AccountReconcilorTest::SimulateSetAccountsInCookieCompleted(
reconcilor->OnSetAccountsInCookieCompleted(result);
}
void AccountReconcilorTest::SimulateLogOutFromCookieCompleted(
AccountReconcilor* reconcilor,
const GoogleServiceAuthError& error) {
reconcilor->OnLogOutFromCookieCompleted(error);
}
void AccountReconcilorTest::SimulateCookieContentSettingsChanged(
content_settings::Observer* observer,
const ContentSettingsPattern& primary_pattern) {
......@@ -675,8 +684,11 @@ class BaseAccountReconcilorTestTable : public AccountReconcilorTest {
ASSERT_TRUE(reconcilor->delegate_->IsAccountConsistencyEnforced());
reconcilor->StartReconcile();
for (int i = 0; gaia_api_calls_[i] != '\0'; ++i) {
if (gaia_api_calls_[i] == 'X')
if (gaia_api_calls_[i] == 'X') {
SimulateLogOutFromCookieCompleted(
reconcilor, GoogleServiceAuthError::AuthErrorNone());
continue;
}
CoreAccountId account_id =
PickAccountIdForAccount(accounts_[gaia_api_calls_[i]].gaia_id,
accounts_[gaia_api_calls_[i]].email);
......@@ -1361,6 +1373,8 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
if (!IsMultiloginEnabled()) {
SimulateLogOutFromCookieCompleted(reconcilor,
GoogleServiceAuthError::AuthErrorNone());
SimulateAddAccountToCookieCompleted(
reconcilor, account_id_1, GoogleServiceAuthError::AuthErrorNone());
SimulateAddAccountToCookieCompleted(
......
......@@ -4,6 +4,7 @@
#include "components/signin/core/browser/cookie_reminter.h"
#include "base/bind_helpers.h"
#include "base/metrics/histogram_macros.h"
#include "base/syslog_logging.h"
#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
......@@ -52,6 +53,7 @@ void CookieReminter::OnRefreshTokenUpdatedForAccount(
// Cookies are going to be reminted for all accounts.
accounts_requiring_cookie_remint_.clear();
identity_manager_->GetAccountsCookieMutator()->LogOutAllAccounts(
gaia::GaiaSource::kChromeOS);
gaia::GaiaSource::kChromeOS,
signin::AccountsCookieMutator::LogOutFromCookieCompletedCallback());
}
}
......@@ -108,8 +108,11 @@ void AccountsCookieMutatorImpl::ForceTriggerOnCookieChange() {
}
#endif
void AccountsCookieMutatorImpl::LogOutAllAccounts(gaia::GaiaSource source) {
gaia_cookie_manager_service_->LogOutAllAccounts(source);
void AccountsCookieMutatorImpl::LogOutAllAccounts(
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback completion_callback) {
gaia_cookie_manager_service_->LogOutAllAccounts(
source, std::move(completion_callback));
}
} // namespace signin
......@@ -64,7 +64,9 @@ class AccountsCookieMutatorImpl : public AccountsCookieMutator {
void ForceTriggerOnCookieChange() override;
#endif
void LogOutAllAccounts(gaia::GaiaSource source) override;
void LogOutAllAccounts(
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback completion_callback) override;
private:
class MultiloginHelperWrapper : public SetAccountsInCookieTask {
......
......@@ -163,6 +163,12 @@ void GaiaCookieManagerService::GaiaCookieRequest::
std::move(add_account_to_cookie_completed_callback_).Run(account_id, error);
}
void GaiaCookieManagerService::GaiaCookieRequest::
RunLogOutFromCookieCompletedCallback(const GoogleServiceAuthError& error) {
if (log_out_from_cookie_completed_callback_)
std::move(log_out_from_cookie_completed_callback_).Run(error);
}
// static
GaiaCookieManagerService::GaiaCookieRequest
GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest(
......@@ -194,9 +200,12 @@ GaiaCookieManagerService::GaiaCookieRequest::CreateSetAccountsRequest(
// static
GaiaCookieManagerService::GaiaCookieRequest
GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest(
gaia::GaiaSource source) {
return GaiaCookieManagerService::GaiaCookieRequest(
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback callback) {
GaiaCookieManagerService::GaiaCookieRequest request(
GaiaCookieRequestType::LOG_OUT, source);
request.log_out_from_cookie_completed_callback_ = std::move(callback);
return request;
}
// static
......@@ -598,7 +607,9 @@ void GaiaCookieManagerService::ForceOnCookieChangeProcessing() {
net::CookieChangeCause::UNKNOWN_DELETION));
}
void GaiaCookieManagerService::LogOutAllAccounts(gaia::GaiaSource source) {
void GaiaCookieManagerService::LogOutAllAccounts(
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback completion_callback) {
VLOG(1) << "GaiaCookieManagerService::LogOutAllAccounts";
bool log_out_queued = false;
......@@ -638,13 +649,17 @@ void GaiaCookieManagerService::LogOutAllAccounts(gaia::GaiaSource source) {
}
if (!log_out_queued) {
requests_.push_back(GaiaCookieRequest::CreateLogOutRequest(source));
requests_.push_back(GaiaCookieRequest::CreateLogOutRequest(
source, std::move(completion_callback)));
if (requests_.size() == 1) {
fetcher_retries_ = 0;
signin_client_->DelayNetworkCall(
base::BindOnce(&GaiaCookieManagerService::StartGaiaLogOut,
weak_ptr_factory_.GetWeakPtr()));
}
} else {
std::move(completion_callback)
.Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
}
}
......@@ -741,6 +756,12 @@ void GaiaCookieManagerService::SignalSetAccountsComplete(
requests_.front().RunSetAccountsInCookieCompletedCallback(result);
}
void GaiaCookieManagerService::SignalLogOutComplete(
const GoogleServiceAuthError& error) {
DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT);
requests_.front().RunLogOutFromCookieCompletedCallback(error);
}
void GaiaCookieManagerService::SetGaiaAccountsInCookieUpdatedCallback(
GaiaAccountsInCookieUpdatedCallback callback) {
DCHECK(!gaia_accounts_updated_in_cookie_callback_);
......@@ -910,6 +931,7 @@ void GaiaCookieManagerService::OnLogOutSuccess() {
RecordLogoutRequestState(LogoutRequestState::kSuccess);
MarkListAccountsStale();
SignalLogOutComplete(GoogleServiceAuthError::AuthErrorNone());
fetcher_backoff_.InformOfRequest(true);
HandleNextRequest();
}
......@@ -931,6 +953,7 @@ void GaiaCookieManagerService::OnLogOutFailure(
return;
}
SignalLogOutComplete(error);
HandleNextRequest();
}
......
......@@ -74,6 +74,8 @@ class GaiaCookieManagerService
typedef base::OnceCallback<void(const CoreAccountId&,
const GoogleServiceAuthError&)>
AddAccountToCookieCompletedCallback;
typedef base::OnceCallback<void(const GoogleServiceAuthError&)>
LogOutFromCookieCompletedCallback;
typedef base::RepeatingCallback<void(const std::vector<gaia::ListedAccount>&,
const std::vector<gaia::ListedAccount>&,
......@@ -106,12 +108,16 @@ class GaiaCookieManagerService
void RunAddAccountToCookieCompletedCallback(
const CoreAccountId& account_id,
const GoogleServiceAuthError& error);
void RunLogOutFromCookieCompletedCallback(
const GoogleServiceAuthError& error);
static GaiaCookieRequest CreateAddAccountRequest(
const CoreAccountId& account_id,
gaia::GaiaSource source,
AddAccountToCookieCompletedCallback callback);
static GaiaCookieRequest CreateLogOutRequest(gaia::GaiaSource source);
static GaiaCookieRequest CreateLogOutRequest(
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback callback);
static GaiaCookieRequest CreateListAccountsRequest();
static GaiaCookieRequest CreateSetAccountsRequest(
gaia::MultiloginMode mode,
......@@ -145,6 +151,7 @@ class GaiaCookieManagerService
set_accounts_in_cookie_completed_callback_;
AddAccountToCookieCompletedCallback
add_account_to_cookie_completed_callback_;
LogOutFromCookieCompletedCallback log_out_from_cookie_completed_callback_;
DISALLOW_COPY_AND_ASSIGN(GaiaCookieRequest);
};
......@@ -259,7 +266,8 @@ class GaiaCookieManagerService
void CancelAll();
// Signout all accounts.
void LogOutAllAccounts(gaia::GaiaSource source);
void LogOutAllAccounts(gaia::GaiaSource source,
LogOutFromCookieCompletedCallback callback);
// Call observers when setting accounts in cookie completes.
void SignalSetAccountsComplete(signin::SetAccountsInCookieResult result);
......@@ -316,6 +324,9 @@ class GaiaCookieManagerService
const base::circular_deque<GaiaCookieRequest>::iterator& request,
const GoogleServiceAuthError& error);
// Calls the LogOutFromCookie completion callback.
void SignalLogOutComplete(const GoogleServiceAuthError& error);
// Marks the list account being staled, and for iOS only, it triggers to fetch
// the list of accounts (on iOS there is no OnCookieChange() notification).
void MarkListAccountsStale();
......
......@@ -42,6 +42,8 @@ const char kAccountId4[] = "account_id4";
using MockAddAccountToCookieCompletedCallback = base::MockCallback<
GaiaCookieManagerService::AddAccountToCookieCompletedCallback>;
using MockLogOutFromCookieCompletedCallback = base::MockCallback<
GaiaCookieManagerService::LogOutFromCookieCompletedCallback>;
class MockObserver {
public:
......@@ -455,7 +457,11 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsNoQueue) {
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
EXPECT_CALL(log_out_from_cookie_completed, Run(no_error()));
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
SimulateLogOutSuccess(&helper);
ASSERT_FALSE(helper.is_running());
}
......@@ -474,7 +480,10 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsFails) {
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
// A completion callback shouldn't be called.
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
SimulateLogOutFailure(&helper, error());
// CookieManagerService is still running; it is retrying the failed logout.
ASSERT_TRUE(helper.is_running());
......@@ -489,10 +498,13 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsAfterOneAddInQueue) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed;
EXPECT_CALL(add_account_to_cookie_completed, Run(account_id2_, no_error()));
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
EXPECT_CALL(log_out_from_cookie_completed, Run(no_error()));
helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
SimulateLogOutSuccess(&helper);
......@@ -509,13 +521,16 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsAfterTwoAddsInQueue) {
add_account_to_cookie_completed2;
EXPECT_CALL(add_account_to_cookie_completed1, Run(account_id1_, no_error()));
EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, canceled()));
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
EXPECT_CALL(log_out_from_cookie_completed, Run(no_error()));
helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
// The Log Out should prevent this AddAccount from being fetched.
helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
SimulateLogOutSuccess(&helper);
......@@ -535,9 +550,16 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsTwice) {
add_account_to_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed1,
log_out_from_cookie_completed2;
EXPECT_CALL(log_out_from_cookie_completed1, Run(no_error()));
EXPECT_CALL(log_out_from_cookie_completed2, Run(canceled()));
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed1.Get());
// Only one LogOut will be fetched.
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed2.Get());
SimulateLogOutSuccess(&helper);
}
......@@ -557,7 +579,11 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsBeforeAdd) {
add_account_to_cookie_completed2.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
EXPECT_CALL(log_out_from_cookie_completed, Run(no_error()));
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
helper.AddAccountToCookie(account_id3_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed3.Get());
......@@ -582,9 +608,16 @@ TEST_F(GaiaCookieManagerServiceTest, LogOutAllAccountsBeforeLogoutAndAdd) {
add_account_to_cookie_completed2.Get());
SimulateMergeSessionSuccess(&helper, "token1");
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed1,
log_out_from_cookie_completed2;
EXPECT_CALL(log_out_from_cookie_completed1, Run(no_error()));
EXPECT_CALL(log_out_from_cookie_completed2, Run(canceled()));
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed1.Get());
// Second LogOut will never be fetched.
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed2.Get());
helper.AddAccountToCookie(account_id3_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed3.Get());
......@@ -606,13 +639,16 @@ TEST_F(GaiaCookieManagerServiceTest, PendingSigninThenSignout) {
MockAddAccountToCookieCompletedCallback add_account_to_cookie_completed3;
EXPECT_CALL(add_account_to_cookie_completed3, Run(account_id3_, no_error()));
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
EXPECT_CALL(log_out_from_cookie_completed, Run(no_error()));
// Total sign in 2 times, not enforcing ordered sequences.
EXPECT_CALL(helper, StartFetchingUbertoken()).Times(2);
helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
SimulateLogOutSuccess(&helper);
......@@ -633,11 +669,15 @@ TEST_F(GaiaCookieManagerServiceTest, CancelSignIn) {
EXPECT_CALL(add_account_to_cookie_completed2, Run(account_id2_, canceled()));
EXPECT_CALL(helper, StartFetchingLogOut());
MockLogOutFromCookieCompletedCallback log_out_from_cookie_completed;
EXPECT_CALL(log_out_from_cookie_completed, Run(no_error()));
helper.AddAccountToCookie(account_id1_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed1.Get());
helper.AddAccountToCookie(account_id2_, gaia::GaiaSource::kChrome,
add_account_to_cookie_completed2.Get());
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome);
helper.LogOutAllAccounts(gaia::GaiaSource::kChrome,
log_out_from_cookie_completed.Get());
SimulateMergeSessionSuccess(&helper, "token1");
SimulateLogOutSuccess(&helper);
......
......@@ -55,6 +55,8 @@ class AccountsCookieMutator {
typedef base::OnceCallback<void(const CoreAccountId& account_id,
const GoogleServiceAuthError& error)>
AddAccountToCookieCompletedCallback;
typedef base::OnceCallback<void(const GoogleServiceAuthError& error)>
LogOutFromCookieCompletedCallback;
// Adds an account identified by |account_id| to the cookie responsible for
// tracking the list of logged-in Google sessions across the web.
......@@ -121,7 +123,9 @@ class AccountsCookieMutator {
#endif
// Remove all accounts from the Gaia cookie.
virtual void LogOutAllAccounts(gaia::GaiaSource source) = 0;
virtual void LogOutAllAccounts(
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback completion_callback) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(AccountsCookieMutator);
......
......@@ -55,6 +55,7 @@ enum class AccountsCookiesMutatorAction {
kTriggerCookieJarUpdateNoAccounts,
kTriggerCookieJarUpdateOneAccount,
kTriggerOnCookieChangeNoAccounts,
kLogOutFromCookie,
};
} // namespace
......@@ -131,6 +132,13 @@ class AccountsCookieMutatorTest
case AccountsCookiesMutatorAction::kTriggerOnCookieChangeNoAccounts:
SetListAccountsResponseNoAccounts(GetTestURLLoaderFactory());
break;
case AccountsCookiesMutatorAction::kLogOutFromCookie:
GetTestURLLoaderFactory()->AddResponse(
GaiaUrls::GetInstance()
->LogOutURLWithSource(GaiaConstants::kChromeSource)
.spec(),
std::string(), net::HTTP_OK);
break;
}
}
......@@ -505,19 +513,19 @@ TEST_F(AccountsCookieMutatorTest, ForceTriggerOnCookieChange) {
// Test that trying to log out all sessions generates the right network request.
TEST_F(AccountsCookieMutatorTest, LogOutAllAccounts) {
PrepareURLLoaderResponsesForAction(
AccountsCookiesMutatorAction::kLogOutFromCookie);
base::RunLoop run_loop;
GetTestURLLoaderFactory()->SetInterceptor(base::BindRepeating(
[](base::OnceClosure quit_closure,
const network::ResourceRequest& request) {
EXPECT_EQ(request.url.spec(),
GaiaUrls::GetInstance()
->LogOutURLWithSource(GaiaConstants::kChromeSource)
.spec());
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
accounts_cookie_mutator()->LogOutAllAccounts(gaia::GaiaSource::kChrome);
accounts_cookie_mutator()->LogOutAllAccounts(
gaia::GaiaSource::kChrome, base::BindOnce(
[](base::OnceClosure quit_closure,
const GoogleServiceAuthError& error) {
EXPECT_EQ(error.state(),
GoogleServiceAuthError::NONE);
std::move(quit_closure).Run();
},
run_loop.QuitClosure()));
run_loop.Run();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment