blob: 3009afe65c208df91dafb24d3425b793a0401e7e [file] [log] [blame]
// Copyright 2020 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.
#include "chrome/browser/signin/signin_manager.h"
#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Mock;
namespace signin {
namespace {
const char kTestEmail[] = "me@gmail.com";
const char kTestEmail2[] = "me2@gmail.com";
class IdentityManagerObserver : public IdentityManager::Observer {
public:
MOCK_METHOD1(OnUnconsentedPrimaryAccountChanged,
void(const CoreAccountInfo& unconsented_primary_account_info));
MOCK_METHOD1(BeforePrimaryAccountCleared,
void(const CoreAccountInfo& previous_primary_account_info));
};
} // namespace
class SigninManagerTest : public testing::Test {
public:
SigninManagerTest() = default;
void SetUp() override {
testing::Test::SetUp();
RecreateSigninManager();
VerifyAndResetCallExpectations();
identity_manager()->AddObserver(&observer_);
}
void TearDown() override { identity_manager()->RemoveObserver(&observer_); }
void RecreateSigninManager() {
signin_manger_ = std::make_unique<SigninManager>(identity_manager());
}
AccountInfo GetAccountInfo(const std::string& email) {
AccountInfo account_info;
account_info.gaia = GetTestGaiaIdForEmail(email);
account_info.account_id =
identity_manager()->PickAccountIdForAccount(account_info.gaia, email);
account_info.email = email;
return account_info;
}
IdentityManager* identity_manager() {
return identity_test_env_.identity_manager();
}
IdentityTestEnvironment* identity_test_env() { return &identity_test_env_; }
void MakeAccountAvailableWithCookies(const AccountInfo& account_info) {
EXPECT_EQ(account_info, identity_test_env_.MakeAccountAvailableWithCookies(
account_info.email, account_info.gaia));
}
IdentityManagerObserver& observer() { return observer_; }
void VerifyAndResetCallExpectations() {
Mock::VerifyAndClear(&observer_);
EXPECT_CALL(observer_, OnUnconsentedPrimaryAccountChanged(_)).Times(0);
EXPECT_CALL(observer_, BeforePrimaryAccountCleared(_)).Times(0);
}
content::BrowserTaskEnvironment task_environment_;
IdentityTestEnvironment identity_test_env_;
std::unique_ptr<SigninManager> signin_manger_;
IdentityManagerObserver observer_;
DISALLOW_COPY_AND_ASSIGN(SigninManagerTest);
};
TEST_F(
SigninManagerTest,
UnconsentedPrimaryAccountUpdatedOnItsAccountRefreshTokenUpdateWithValidTokenWhenNoSyncConsent) {
// Add an unconsented primary account, incl. proper cookies.
AccountInfo account_info = GetAccountInfo(kTestEmail);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
MakeAccountAvailableWithCookies(account_info);
VerifyAndResetCallExpectations();
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
account_info);
}
TEST_F(
SigninManagerTest,
UnconsentedPrimaryAccountUpdatedOnItsAccountRefreshTokenUpdateWithInvalidTokenWhenNoSyncConsent) {
// Add an unconsented primary account, incl. proper cookies.
AccountInfo account_info = GetAccountInfo(kTestEmail);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
MakeAccountAvailableWithCookies(account_info);
VerifyAndResetCallExpectations();
// Invalid token.
CoreAccountInfo empty_info;
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(empty_info))
.Times(1);
SetInvalidRefreshTokenForAccount(identity_manager(), account_info.account_id);
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
empty_info);
VerifyAndResetCallExpectations();
// Update with a valid token.
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
UpdatePersistentErrorOfRefreshTokenForAccount(
identity_manager(), account_info.account_id,
GoogleServiceAuthError::AuthErrorNone());
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
account_info);
// Unconsented primary account should not be called.
VerifyAndResetCallExpectations();
}
TEST_F(
SigninManagerTest,
UnconsentedPrimaryAccountRemovedOnItsAccountRefreshTokenRemovalWhenNoSyncConsent) {
// Add an unconsented primary account, incl. proper cookies.
AccountInfo account_info = GetAccountInfo(kTestEmail);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
MakeAccountAvailableWithCookies(account_info);
VerifyAndResetCallExpectations();
// With no refresh token, there is no unconsented primary account any more.
CoreAccountInfo empty_info;
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(empty_info))
.Times(1);
identity_test_env()->RemoveRefreshTokenForAccount(account_info.account_id);
VerifyAndResetCallExpectations();
EXPECT_FALSE(
identity_manager()->HasPrimaryAccount(ConsentLevel::kNotRequired));
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
empty_info);
VerifyAndResetCallExpectations();
}
TEST_F(SigninManagerTest, UnconsentedPrimaryAccountNotChangedOnSignout) {
// Setup cookies and token for the main account.
AccountInfo account_info = GetAccountInfo(kTestEmail);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
identity_test_env()->MakePrimaryAccountAvailable(account_info.email);
identity_test_env()->SetCookieAccounts(
{{account_info.email, account_info.gaia}});
EXPECT_EQ(account_info, identity_manager()->GetPrimaryAccountInfo(
ConsentLevel::kNotRequired));
EXPECT_EQ(account_info,
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSync));
EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken());
VerifyAndResetCallExpectations();
// Tests that OnUnconsentedPrimaryAccountChanged is never called.
EXPECT_CALL(observer(), BeforePrimaryAccountCleared(account_info)).Times(1);
// Clear primary account but do not delete the account.
identity_test_env()->ClearPrimaryAccount(
ClearPrimaryAccountPolicy::KEEP_ALL_ACCOUNTS);
// Primary account is cleared, but unconsented account is not.
EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
EXPECT_EQ(account_info, identity_manager()->GetPrimaryAccountInfo(
ConsentLevel::kNotRequired));
// OnUnconsentedPrimaryAccountChanged was not fired.
VerifyAndResetCallExpectations();
}
TEST_F(SigninManagerTest,
UnconsentedPrimaryAccountTokenRevokedWithStaleCookies) {
AccountInfo account_info = GetAccountInfo(kTestEmail);
// Add an unconsented primary account, incl. proper cookies.
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
MakeAccountAvailableWithCookies(account_info);
VerifyAndResetCallExpectations();
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
account_info);
// Make the cookies stale and remove the account.
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(CoreAccountInfo()))
.Times(1);
identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
// Removing the refresh token for the unconsented primary account is
// sufficient to clear it.
identity_test_env()->RemoveRefreshTokenForAccount(account_info.account_id);
AccountsInCookieJarInfo cookie_info =
identity_manager()->GetAccountsInCookieJar();
ASSERT_FALSE(cookie_info.accounts_are_fresh);
// Unconsented account was removed.
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
CoreAccountInfo());
}
TEST_F(SigninManagerTest,
UnconsentedPrimaryAccountTokenRevokedWithStaleCookiesMultipleAccounts) {
// Add two accounts with cookies.
AccountInfo main_account_info =
identity_test_env()->MakeAccountAvailable(kTestEmail);
AccountInfo secondary_account_info =
identity_test_env()->MakeAccountAvailable(kTestEmail2);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(main_account_info))
.Times(1);
identity_test_env()->SetCookieAccounts(
{{main_account_info.email, main_account_info.gaia},
{secondary_account_info.email, secondary_account_info.gaia}});
VerifyAndResetCallExpectations();
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
main_account_info);
// Make the cookies stale and remove the main account.
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(CoreAccountInfo()))
.Times(1);
identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
identity_test_env()->RemoveRefreshTokenForAccount(
main_account_info.account_id);
AccountsInCookieJarInfo cookie_info =
identity_manager()->GetAccountsInCookieJar();
ASSERT_FALSE(cookie_info.accounts_are_fresh);
// Unconsented account was removed.
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
CoreAccountInfo());
}
TEST_F(SigninManagerTest, UnconsentedPrimaryAccountDuringLoad) {
// Add two accounts with cookies.
AccountInfo main_account_info =
identity_test_env()->MakeAccountAvailable(kTestEmail);
AccountInfo secondary_account_info =
identity_test_env()->MakeAccountAvailable(kTestEmail2);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(main_account_info))
.Times(1);
identity_test_env()->SetCookieAccounts(
{{main_account_info.email, main_account_info.gaia},
{secondary_account_info.email, secondary_account_info.gaia}});
VerifyAndResetCallExpectations();
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
main_account_info);
// Set the token service in "loading" mode.
identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
RecreateSigninManager();
// Unconsented primary account is available while tokens are not loaded.
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
main_account_info);
VerifyAndResetCallExpectations();
// Revoking an unrelated token doesn't change the unconsented primary account.
identity_test_env()->RemoveRefreshTokenForAccount(
secondary_account_info.account_id);
EXPECT_EQ(
identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kNotRequired),
main_account_info);
// Revoke the unconsented primary account while tokens are not loaded.
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(CoreAccountInfo()))
.Times(1);
identity_test_env()->RemoveRefreshTokenForAccount(
main_account_info.account_id);
EXPECT_FALSE(
identity_manager()->HasPrimaryAccount(ConsentLevel::kNotRequired));
VerifyAndResetCallExpectations();
// Finish the token load.
identity_test_env()->ReloadAccountsFromDisk();
EXPECT_FALSE(
identity_manager()->HasPrimaryAccount(ConsentLevel::kNotRequired));
}
TEST_F(SigninManagerTest,
UnconsentedPrimaryAccountUpdatedOnSyncConsentRevoked) {
AccountInfo first_account_info =
identity_test_env()->MakeAccountAvailable(kTestEmail);
AccountInfo second_account_info =
identity_test_env()->MakeAccountAvailable(kTestEmail2);
EXPECT_CALL(observer(),
OnUnconsentedPrimaryAccountChanged(first_account_info))
.Times(1);
identity_test_env()->SetCookieAccounts(
{{first_account_info.email, first_account_info.gaia},
{second_account_info.email, second_account_info.gaia}});
VerifyAndResetCallExpectations();
// Set the primary account to the second account in cookies.
// The unconsented primary account should be updated.
EXPECT_CALL(observer(),
OnUnconsentedPrimaryAccountChanged(second_account_info))
.Times(1);
identity_test_env()->SetPrimaryAccount(second_account_info.email);
EXPECT_EQ(identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSync),
second_account_info);
VerifyAndResetCallExpectations();
// Clear primary account but do not delete the account. The unconsented
// primary account should be updated to be the first account in cookies.
EXPECT_CALL(observer(), BeforePrimaryAccountCleared(second_account_info))
.Times(1);
EXPECT_CALL(observer(),
OnUnconsentedPrimaryAccountChanged(first_account_info))
.Times(1);
identity_test_env()->ClearPrimaryAccount(
ClearPrimaryAccountPolicy::KEEP_ALL_ACCOUNTS);
// Primary account is cleared, but unconsented account is not.
EXPECT_FALSE(identity_manager()->HasPrimaryAccount());
EXPECT_EQ(first_account_info, identity_manager()->GetPrimaryAccountInfo(
ConsentLevel::kNotRequired));
// OnUnconsentedPrimaryAccountChanged was fired.
VerifyAndResetCallExpectations();
}
TEST_F(SigninManagerTest, ClearPrimaryAccountAndSignOut) {
AccountInfo account_info = GetAccountInfo(kTestEmail);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(account_info))
.Times(1);
identity_test_env()->MakePrimaryAccountAvailable(kTestEmail);
EXPECT_EQ(identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSync),
account_info);
VerifyAndResetCallExpectations();
identity_test_env()->SetCookieAccounts(
{{account_info.email, account_info.gaia}});
EXPECT_CALL(observer(), BeforePrimaryAccountCleared(account_info)).Times(1);
EXPECT_CALL(observer(), OnUnconsentedPrimaryAccountChanged(CoreAccountInfo()))
.Times(1);
identity_test_env()->ClearPrimaryAccount(
ClearPrimaryAccountPolicy::REMOVE_ALL_ACCOUNTS);
VerifyAndResetCallExpectations();
}
} // namespace signin