#include "components/sync/driver/sync_auth_manager.h"
#include "base/functional/callback_helpers.h"
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "components/sync/engine/connection_status.h"
#include "components/sync/engine/sync_credentials.h"
#include "net/base/net_errors.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
class SyncAuthManagerTest : public testing::Test {
protected:
using AccountStateChangedCallback =
SyncAuthManager::AccountStateChangedCallback;
using CredentialsChangedCallback =
SyncAuthManager::CredentialsChangedCallback;
SyncAuthManagerTest() : identity_env_(&test_url_loader_factory_) {}
~SyncAuthManagerTest() override = default;
std::unique_ptr<SyncAuthManager> CreateAuthManager() {
return CreateAuthManager(base::DoNothing(), base::DoNothing());
}
std::unique_ptr<SyncAuthManager> CreateAuthManager(
const AccountStateChangedCallback& account_state_changed,
const CredentialsChangedCallback& credentials_changed) {
return std::make_unique<SyncAuthManager>(identity_env_.identity_manager(),
account_state_changed,
credentials_changed);
}
std::unique_ptr<SyncAuthManager> CreateAuthManagerForLocalSync() {
return std::make_unique<SyncAuthManager>(nullptr, base::DoNothing(),
base::DoNothing());
}
signin::IdentityTestEnvironment* identity_env() { return &identity_env_; }
private:
base::test::SingleThreadTaskEnvironment task_environment_;
network::TestURLLoaderFactory test_url_loader_factory_;
signin::IdentityTestEnvironment identity_env_;
};
TEST_F(SyncAuthManagerTest, ProvidesNothingInLocalSyncMode) {
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManagerForLocalSync();
EXPECT_TRUE(auth_manager->GetActiveAccountInfo().account_info.IsEmpty());
syncer::SyncCredentials credentials = auth_manager->GetCredentials();
EXPECT_TRUE(credentials.email.empty());
EXPECT_TRUE(credentials.access_token.empty());
EXPECT_TRUE(auth_manager->access_token().empty());
}
TEST_F(SyncAuthManagerTest, IgnoresEventsIfNotRegistered) {
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
EXPECT_CALL(account_state_changed, Run()).Times(0);
EXPECT_CALL(credentials_changed, Run()).Times(0);
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
EXPECT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
identity_env()->SetRefreshTokenForPrimaryAccount();
EXPECT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
#if !BUILDFLAG(IS_CHROMEOS_ASH)
identity_env()->ClearPrimaryAccount();
EXPECT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
#endif
}
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(SyncAuthManagerTest, ForwardsPrimaryAccountEvents) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
EXPECT_CALL(account_state_changed, Run()).Times(0);
EXPECT_CALL(credentials_changed, Run()).Times(0);
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
EXPECT_CALL(account_state_changed, Run());
EXPECT_CALL(credentials_changed, Run()).Times(testing::AtMost(1));
identity_env()->ClearPrimaryAccount();
EXPECT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
EXPECT_CALL(account_state_changed, Run());
CoreAccountId second_account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
second_account_id);
}
TEST_F(SyncAuthManagerTest, NotifiesOfSignoutBeforeAccessTokenIsGone) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), base::DoNothing());
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
EXPECT_CALL(account_state_changed, Run()).WillOnce([&]() {
EXPECT_FALSE(auth_manager->GetCredentials().access_token.empty());
});
identity_env()->ClearPrimaryAccount();
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
ASSERT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
}
#endif
#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(SyncAuthManagerTest, ForwardsUnconsentedAccountEvents) {
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
EXPECT_CALL(account_state_changed, Run()).Times(0);
EXPECT_CALL(credentials_changed, Run()).Times(0);
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
auth_manager->RegisterForAuthNotifications();
ASSERT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
EXPECT_CALL(account_state_changed, Run());
AccountInfo account_info = identity_env()->MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSignin);
EXPECT_FALSE(auth_manager->GetActiveAccountInfo().is_sync_consented);
EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_info.account_id);
EXPECT_CALL(account_state_changed, Run());
signin::PrimaryAccountMutator* primary_account_mutator =
identity_env()->identity_manager()->GetPrimaryAccountMutator();
primary_account_mutator->SetPrimaryAccount(account_info.account_id,
signin::ConsentLevel::kSync);
EXPECT_TRUE(auth_manager->GetActiveAccountInfo().is_sync_consented);
}
#endif
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(SyncAuthManagerTest, ClearsAuthErrorOnSignoutWithRefreshTokenRemoval) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
ASSERT_EQ(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
identity_env()->RemoveRefreshTokenForPrimaryAccount();
identity_env()->ClearPrimaryAccount();
EXPECT_EQ(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
}
TEST_F(SyncAuthManagerTest,
ClearsAuthErrorOnSignoutWithoutRefreshTokenRemoval) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
ASSERT_EQ(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
identity_env()->ClearPrimaryAccount();
EXPECT_EQ(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
}
#endif
TEST_F(SyncAuthManagerTest, DoesNotClearAuthErrorOnSyncDisable) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
ASSERT_EQ(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
auth_manager->ConnectionOpened();
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
ASSERT_NE(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
auth_manager->ConnectionClosed();
EXPECT_NE(auth_manager->GetLastAuthError().state(),
GoogleServiceAuthError::NONE);
}
TEST_F(SyncAuthManagerTest, ForwardsCredentialsEvents) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
EXPECT_CALL(account_state_changed, Run()).Times(0);
EXPECT_CALL(credentials_changed, Run()).Times(0);
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
EXPECT_CALL(credentials_changed, Run());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
EXPECT_CALL(credentials_changed, Run());
identity_env()->SetRefreshTokenForPrimaryAccount();
ASSERT_TRUE(auth_manager->GetCredentials().access_token.empty());
EXPECT_CALL(credentials_changed, Run());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token_2", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
EXPECT_CALL(credentials_changed, Run()).Times(testing::AtLeast(1));
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
}
TEST_F(SyncAuthManagerTest, RequestsAccessTokenOnSyncStartup) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token");
}
TEST_F(SyncAuthManagerTest,
RetriesAccessTokenFetchWithBackoffOnTransientFailure) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT));
EXPECT_TRUE(auth_manager->IsRetryingAccessTokenFetchForTest());
EXPECT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
}
TEST_F(SyncAuthManagerTest,
RetriesAccessTokenFetchWithoutBackoffOnceOnFirstCancelTransientFailure) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
EXPECT_TRUE(auth_manager->IsRetryingAccessTokenFetchForTest());
}
TEST_F(SyncAuthManagerTest,
RetriesAccessTokenFetchOnFirstCancelTransientFailure) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
}
TEST_F(SyncAuthManagerTest, AbortsAccessTokenFetchOnPersistentFailure) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
GoogleServiceAuthError auth_error =
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_SERVER);
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
auth_error);
EXPECT_FALSE(auth_manager->IsRetryingAccessTokenFetchForTest());
EXPECT_EQ(auth_manager->GetLastAuthError(), auth_error);
}
TEST_F(SyncAuthManagerTest, FetchesNewAccessTokenWithBackoffOnServerError) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_AUTH_ERROR);
EXPECT_TRUE(auth_manager->IsRetryingAccessTokenFetchForTest());
EXPECT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
}
TEST_F(SyncAuthManagerTest, DoesNotExposeServerError) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_SERVER_ERROR);
EXPECT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token");
}
TEST_F(SyncAuthManagerTest, ClearsServerErrorOnSyncDisable) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
GoogleServiceAuthError auth_error =
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_SERVER);
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_AUTH_ERROR);
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
auth_error);
ASSERT_NE(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
auth_manager->ConnectionClosed();
EXPECT_NE(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
}
TEST_F(SyncAuthManagerTest, RequestsNewAccessTokenOnExpiry) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
ASSERT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_AUTH_ERROR);
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token_2", base::Time::Now() + base::Hours(1));
EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
}
TEST_F(SyncAuthManagerTest, RequestsNewAccessTokenOnRefreshTokenUpdate) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
ASSERT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
identity_env()->SetRefreshTokenForPrimaryAccount();
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token_2", base::Time::Now() + base::Hours(1));
EXPECT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
}
TEST_F(SyncAuthManagerTest, DoesNotRequestAccessTokenAutonomously) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
base::MockCallback<base::OnceClosure> access_token_requested;
EXPECT_CALL(access_token_requested, Run()).Times(0);
identity_env()->SetCallbackForNextAccessTokenRequest(
access_token_requested.Get());
identity_env()->SetRefreshTokenForPrimaryAccount();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
}
TEST_F(SyncAuthManagerTest, ClearsCredentialsOnRefreshTokenRemoval) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
ASSERT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
base::MockCallback<base::OnceClosure> access_token_requested;
EXPECT_CALL(access_token_requested, Run()).Times(0);
identity_env()->SetCallbackForNextAccessTokenRequest(
access_token_requested.Get());
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
EXPECT_NE(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
base::RunLoop().RunUntilIdle();
}
TEST_F(SyncAuthManagerTest, ClearsCredentialsOnInvalidRefreshToken) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
ASSERT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
base::MockCallback<base::OnceClosure> access_token_requested;
EXPECT_CALL(access_token_requested, Run()).Times(0);
identity_env()->SetCallbackForNextAccessTokenRequest(
access_token_requested.Get());
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
GoogleServiceAuthError invalid_token_error =
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
GoogleServiceAuthError::InvalidGaiaCredentialsReason::
CREDENTIALS_REJECTED_BY_CLIENT);
EXPECT_EQ(auth_manager->GetLastAuthError(), invalid_token_error);
EXPECT_TRUE(auth_manager->IsSyncPaused());
base::RunLoop().RunUntilIdle();
}
TEST_F(SyncAuthManagerTest, EntersPausedStateOnPersistentAuthError) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
ASSERT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
identity_env()->UpdatePersistentErrorOfRefreshTokenForAccount(
auth_manager->GetActiveAccountInfo().account_info.account_id,
GoogleServiceAuthError::FromServiceError("Test error"));
EXPECT_TRUE(auth_manager->GetCredentials().access_token.empty());
EXPECT_TRUE(auth_manager->GetLastAuthError().IsPersistentError());
EXPECT_TRUE(auth_manager->IsSyncPaused());
}
TEST_F(SyncAuthManagerTest,
RequestsAccessTokenWhenInvalidRefreshTokenResolved) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
auth_manager->ConnectionOpened();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
auth_manager->ConnectionStatusChanged(syncer::CONNECTION_OK);
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token");
ASSERT_EQ(auth_manager->GetLastAuthError(),
GoogleServiceAuthError::AuthErrorNone());
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
ASSERT_TRUE(auth_manager->GetCredentials().access_token.empty());
ASSERT_TRUE(auth_manager->IsSyncPaused());
identity_env()->SetRefreshTokenForPrimaryAccount();
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
"access_token_2", base::Time::Now() + base::Hours(1));
ASSERT_EQ(auth_manager->GetCredentials().access_token, "access_token_2");
}
TEST_F(SyncAuthManagerTest, DoesNotRequestAccessTokenIfSyncInactive) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
EXPECT_CALL(account_state_changed, Run()).Times(0);
EXPECT_CALL(credentials_changed, Run()).Times(0);
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
EXPECT_CALL(credentials_changed, Run()).Times(testing::AtLeast(1));
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
ASSERT_TRUE(auth_manager->GetCredentials().access_token.empty());
ASSERT_TRUE(auth_manager->IsSyncPaused());
base::MockCallback<base::OnceClosure> access_token_requested;
EXPECT_CALL(access_token_requested, Run()).Times(0);
identity_env()->SetCallbackForNextAccessTokenRequest(
access_token_requested.Get());
EXPECT_CALL(credentials_changed, Run());
identity_env()->SetRefreshTokenForPrimaryAccount();
ASSERT_FALSE(auth_manager->IsSyncPaused());
base::RunLoop().RunUntilIdle();
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(SyncAuthManagerTest, PrimaryAccountWithNoSyncConsent) {
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
AccountInfo account_info = identity_env()->MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSignin);
EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_info.account_id);
}
#endif
#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
TEST_F(SyncAuthManagerTest, PicksNewPrimaryAccountWithSyncConsent) {
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
ASSERT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
AccountInfo unconsented_primary_account_info =
identity_env()->MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSignin);
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
unconsented_primary_account_info.account_id);
AccountInfo primary_account_info =
identity_env()->MakePrimaryAccountAvailable("primary@email.com",
signin::ConsentLevel::kSync);
EXPECT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
primary_account_info.account_id);
}
TEST_F(SyncAuthManagerTest,
DropsAccountWhenPrimaryAccountWithNoSyncConsentGoesAway) {
std::unique_ptr<SyncAuthManager> auth_manager = CreateAuthManager();
auth_manager->RegisterForAuthNotifications();
AccountInfo account_info = identity_env()->MakePrimaryAccountAvailable(
"test@email.com", signin::ConsentLevel::kSignin);
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_info.account_id);
identity_env()->ClearPrimaryAccount();
EXPECT_TRUE(
auth_manager->GetActiveAccountInfo().account_info.account_id.empty());
}
#endif
TEST_F(SyncAuthManagerTest, DetectsInvalidRefreshTokenAtStartup) {
CoreAccountId account_id =
identity_env()
->MakePrimaryAccountAvailable("test@email.com",
signin::ConsentLevel::kSync)
.account_id;
identity_env()->SetInvalidRefreshTokenForPrimaryAccount();
base::MockCallback<AccountStateChangedCallback> account_state_changed;
base::MockCallback<CredentialsChangedCallback> credentials_changed;
EXPECT_CALL(account_state_changed, Run()).Times(0);
EXPECT_CALL(credentials_changed, Run()).Times(0);
std::unique_ptr<SyncAuthManager> auth_manager =
CreateAuthManager(account_state_changed.Get(), credentials_changed.Get());
auth_manager->RegisterForAuthNotifications();
ASSERT_EQ(auth_manager->GetActiveAccountInfo().account_info.account_id,
account_id);
EXPECT_TRUE(auth_manager->GetLastAuthError().IsPersistentError());
}
}
}