summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/signin/signin_manager_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/signin/signin_manager_unittest.cc')
-rw-r--r--chromium/chrome/browser/signin/signin_manager_unittest.cc421
1 files changed, 421 insertions, 0 deletions
diff --git a/chromium/chrome/browser/signin/signin_manager_unittest.cc b/chromium/chrome/browser/signin/signin_manager_unittest.cc
new file mode 100644
index 00000000000..e2bb33af9f0
--- /dev/null
+++ b/chromium/chrome/browser/signin/signin_manager_unittest.cc
@@ -0,0 +1,421 @@
+// 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 "base/memory/raw_ptr.h"
+#include "components/signin/public/base/signin_pref_names.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 "components/sync_preferences/testing_pref_service_syncable.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 FakeIdentityManagerObserver : public IdentityManager::Observer {
+ public:
+ explicit FakeIdentityManagerObserver(IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {}
+ ~FakeIdentityManagerObserver() override = default;
+
+ void OnPrimaryAccountChanged(
+ const PrimaryAccountChangeEvent& event) override {
+ auto current_state = event.GetCurrentState();
+ EXPECT_EQ(
+ current_state.primary_account,
+ identity_manager_->GetPrimaryAccountInfo(current_state.consent_level));
+ events_.push_back(event);
+ }
+
+ const std::vector<PrimaryAccountChangeEvent>& events() const {
+ return events_;
+ }
+
+ void Reset() { events_.clear(); }
+
+ private:
+ raw_ptr<IdentityManager> identity_manager_;
+ std::vector<PrimaryAccountChangeEvent> events_;
+};
+} // namespace
+
+class SigninManagerTest : public testing::Test {
+ public:
+ SigninManagerTest()
+ : identity_test_env_(/*test_url_loader_factory=*/nullptr,
+ /*pref_service=*/&prefs_,
+ signin::AccountConsistencyMethod::kDice,
+ /*test_signin_client=*/nullptr),
+ observer_(identity_test_env_.identity_manager()) {}
+
+ SigninManagerTest(const SigninManagerTest&) = delete;
+ SigninManagerTest& operator=(const SigninManagerTest&) = delete;
+
+ void SetUp() override {
+ testing::Test::SetUp();
+ RecreateSigninManager();
+ identity_manager()->AddObserver(&observer_);
+ }
+
+ void TearDown() override { identity_manager()->RemoveObserver(&observer_); }
+
+ void RecreateSigninManager() {
+ signin_manger_ =
+ std::make_unique<SigninManager>(&prefs_, 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;
+ }
+
+ void ExpectUnconsentedPrimaryAccountSetEvent(
+ const CoreAccountInfo& expected_primary_account) {
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_TRUE(event.GetPreviousState().primary_account.IsEmpty());
+ EXPECT_EQ(expected_primary_account,
+ event.GetCurrentState().primary_account);
+ observer().Reset();
+ }
+
+ void ExpectUnconsentedPrimaryAccountClearedEvent(
+ const CoreAccountInfo& expected_cleared_account) {
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(expected_cleared_account,
+ event.GetPreviousState().primary_account);
+ EXPECT_TRUE(event.GetCurrentState().primary_account.IsEmpty());
+ observer().Reset();
+ }
+
+ void ExpectSyncPrimaryAccountSetEvent(
+ const CoreAccountInfo& expected_primary_account) {
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+ event.GetEventTypeFor(ConsentLevel::kSync));
+ EXPECT_TRUE(event.GetPreviousState().primary_account.IsEmpty());
+ EXPECT_EQ(expected_primary_account,
+ event.GetCurrentState().primary_account);
+ observer().Reset();
+ }
+
+ IdentityManager* identity_manager() {
+ return identity_test_env_.identity_manager();
+ }
+
+ IdentityTestEnvironment* identity_test_env() { return &identity_test_env_; }
+
+ AccountInfo MakeAccountAvailableWithCookies(const std::string& email) {
+ AccountInfo account = GetAccountInfo(kTestEmail);
+ identity_test_env_.MakeAccountAvailableWithCookies(account.email,
+ account.gaia);
+ EXPECT_FALSE(account.IsEmpty());
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+ return account;
+ }
+
+ AccountInfo MakeSyncAccountAvailableWithCookies(const std::string& email) {
+ AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable(
+ email, signin::ConsentLevel::kSync);
+ identity_test_env_.SetCookieAccounts({{account.email, account.gaia}});
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSync));
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken(
+ signin::ConsentLevel::kSync));
+ return account;
+ }
+
+ FakeIdentityManagerObserver& observer() { return observer_; }
+
+ sync_preferences::TestingPrefServiceSyncable prefs_;
+ content::BrowserTaskEnvironment task_environment_;
+ IdentityTestEnvironment identity_test_env_;
+ std::unique_ptr<SigninManager> signin_manger_;
+ FakeIdentityManagerObserver observer_;
+};
+
+TEST_F(
+ SigninManagerTest,
+ UnconsentedPrimaryAccountUpdatedOnItsAccountRefreshTokenUpdateWithValidTokenWhenNoSyncConsent) {
+ // Add an unconsented primary account, incl. proper cookies.
+ AccountInfo account = MakeAccountAvailableWithCookies(kTestEmail);
+ ExpectUnconsentedPrimaryAccountSetEvent(account);
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+}
+
+TEST_F(
+ SigninManagerTest,
+ UnconsentedPrimaryAccountUpdatedOnItsAccountRefreshTokenUpdateWithInvalidTokenWhenNoSyncConsent) {
+ // Prerequisite: add an unconsented primary account, incl. proper cookies.
+ AccountInfo account = MakeAccountAvailableWithCookies(kTestEmail);
+ ExpectUnconsentedPrimaryAccountSetEvent(account);
+
+ // Invalid token.
+ SetInvalidRefreshTokenForAccount(identity_manager(), account.account_id);
+ ExpectUnconsentedPrimaryAccountClearedEvent(account);
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+
+ // Update with a valid token.
+ SetRefreshTokenForAccount(identity_manager(), account.account_id, "");
+ ExpectUnconsentedPrimaryAccountSetEvent(account);
+ EXPECT_EQ(identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin),
+ account);
+}
+
+TEST_F(
+ SigninManagerTest,
+ UnconsentedPrimaryAccountRemovedOnItsAccountRefreshTokenRemovalWhenNoSyncConsent) {
+ // Prerequisite: Add an unconsented primary account, incl. proper cookies.
+ AccountInfo account = MakeAccountAvailableWithCookies(kTestEmail);
+ ExpectUnconsentedPrimaryAccountSetEvent(account);
+
+ // With no refresh token, there is no unconsented primary account any more.
+ identity_test_env()->RemoveRefreshTokenForAccount(account.account_id);
+ ExpectUnconsentedPrimaryAccountClearedEvent(account);
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+}
+
+TEST_F(SigninManagerTest, UnconsentedPrimaryAccountNotChangedOnSignout) {
+ // Set a primary account at sync consent level.
+ AccountInfo account = MakeSyncAccountAvailableWithCookies(kTestEmail);
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSync));
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccountWithRefreshToken(
+ signin::ConsentLevel::kSync));
+
+ // Verify the primary account changed event.
+ ExpectSyncPrimaryAccountSetEvent(account);
+
+ // Tests that sync primary account is cleared, but unconsented account is not.
+ identity_test_env()->RevokeSyncConsent();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kNone,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+ event.GetEventTypeFor(ConsentLevel::kSync));
+ EXPECT_EQ(account, event.GetPreviousState().primary_account);
+ EXPECT_EQ(account, event.GetCurrentState().primary_account);
+}
+
+TEST_F(SigninManagerTest,
+ UnconsentedPrimaryAccountTokenRevokedWithStaleCookies) {
+ // Prerequisite: add an unconsented primary account, incl. proper cookies.
+ AccountInfo account = MakeAccountAvailableWithCookies(kTestEmail);
+ ExpectUnconsentedPrimaryAccountSetEvent(account);
+
+ // Make the cookies stale and remove the account.
+ // Removing the refresh token for the unconsented primary account is
+ // sufficient to clear it.
+ identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
+ identity_test_env()->RemoveRefreshTokenForAccount(account.account_id);
+ ASSERT_FALSE(identity_manager()->GetAccountsInCookieJar().accounts_are_fresh);
+
+ // Unconsented account was removed.
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+ ExpectUnconsentedPrimaryAccountClearedEvent(account);
+}
+
+TEST_F(SigninManagerTest,
+ UnconsentedPrimaryAccountTokenRevokedWithStaleCookiesMultipleAccounts) {
+ // Add two accounts with cookies.
+ AccountInfo main_account =
+ identity_test_env()->MakeAccountAvailable(kTestEmail);
+ AccountInfo secondary_account =
+ identity_test_env()->MakeAccountAvailable(kTestEmail2);
+ identity_test_env()->SetCookieAccounts(
+ {{main_account.email, main_account.gaia},
+ {secondary_account.email, secondary_account.gaia}});
+
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+ EXPECT_EQ(main_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ ExpectUnconsentedPrimaryAccountSetEvent(main_account);
+
+ // Make the cookies stale and remove the main account.
+ identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
+ identity_test_env()->RemoveRefreshTokenForAccount(main_account.account_id);
+ ASSERT_FALSE(identity_manager()->GetAccountsInCookieJar().accounts_are_fresh);
+
+ // Unconsented account was removed.
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+ ExpectUnconsentedPrimaryAccountClearedEvent(main_account);
+}
+
+TEST_F(SigninManagerTest, UnconsentedPrimaryAccountDuringLoad) {
+ // Pre-requisite: Add two accounts with cookies.
+ AccountInfo main_account =
+ identity_test_env()->MakeAccountAvailable(kTestEmail);
+ AccountInfo secondary_account =
+ identity_test_env()->MakeAccountAvailable(kTestEmail2);
+ identity_test_env()->SetCookieAccounts(
+ {{main_account.email, main_account.gaia},
+ {secondary_account.email, secondary_account.gaia}});
+ ASSERT_EQ(main_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ ASSERT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+ ExpectUnconsentedPrimaryAccountSetEvent(main_account);
+
+ // Set the token service in "loading" mode.
+ identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
+ RecreateSigninManager();
+
+ // Unconsented primary account is available while tokens are not loaded.
+ EXPECT_EQ(main_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_TRUE(observer().events().empty());
+
+ // Revoking an unrelated token doesn't change the unconsented primary account.
+ identity_test_env()->RemoveRefreshTokenForAccount(
+ secondary_account.account_id);
+ EXPECT_EQ(main_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_TRUE(observer().events().empty());
+
+ // Revoking the token of the unconsented primary account while the tokens
+ // are still loading does not change the unconsented primary account.
+ identity_test_env()->RemoveRefreshTokenForAccount(main_account.account_id);
+ EXPECT_EQ(main_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ EXPECT_TRUE(observer().events().empty());
+
+ // Finish the token load should clear the primary account as the token of the
+ // primary account was revoked.
+ identity_test_env()->ReloadAccountsFromDisk();
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+ ExpectUnconsentedPrimaryAccountClearedEvent(main_account);
+}
+
+TEST_F(SigninManagerTest,
+ UnconsentedPrimaryAccountUpdatedOnSyncConsentRevoked) {
+ AccountInfo first_account =
+ identity_test_env()->MakeAccountAvailable(kTestEmail);
+ AccountInfo second_account =
+ identity_test_env()->MakeAccountAvailable(kTestEmail2);
+ identity_test_env()->SetCookieAccounts(
+ {{first_account.email, first_account.gaia},
+ {second_account.email, second_account.gaia}});
+ ASSERT_EQ(first_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+ ExpectUnconsentedPrimaryAccountSetEvent(first_account);
+
+ // Set the sync primary account to the second account in cookies.
+ // The unconsented primary account should be updated.
+ identity_test_env()->SetPrimaryAccount(second_account.email,
+ signin::ConsentLevel::kSync);
+ EXPECT_EQ(second_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSync));
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+ event.GetEventTypeFor(ConsentLevel::kSync));
+ EXPECT_EQ(first_account, event.GetPreviousState().primary_account);
+ EXPECT_EQ(second_account, event.GetCurrentState().primary_account);
+ observer().Reset();
+
+ // Clear primary account but do not delete the account. The unconsented
+ // primary account should be updated to be the first account in cookies.
+ identity_test_env()->RevokeSyncConsent();
+ base::RunLoop().RunUntilIdle();
+
+ // Primary account is cleared, but unconsented account is not.
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSync));
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+ EXPECT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
+ EXPECT_EQ(first_account,
+ identity_manager()->GetPrimaryAccountInfo(ConsentLevel::kSignin));
+
+ EXPECT_EQ(2U, observer().events().size());
+ event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+ event.GetEventTypeFor(ConsentLevel::kSync));
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kNone,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(second_account, event.GetPreviousState().primary_account);
+ EXPECT_EQ(second_account, event.GetCurrentState().primary_account);
+
+ event = observer().events()[1];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kNone,
+ event.GetEventTypeFor(ConsentLevel::kSync));
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(second_account, event.GetPreviousState().primary_account);
+ EXPECT_EQ(first_account, event.GetCurrentState().primary_account);
+}
+
+TEST_F(SigninManagerTest, ClearPrimaryAccountAndSignOut) {
+ AccountInfo account = MakeSyncAccountAvailableWithCookies(kTestEmail);
+ ExpectSyncPrimaryAccountSetEvent(account);
+
+ identity_test_env()->ClearPrimaryAccount();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+ event.GetEventTypeFor(ConsentLevel::kSync));
+ EXPECT_EQ(account, event.GetPreviousState().primary_account);
+ EXPECT_TRUE(event.GetCurrentState().primary_account.IsEmpty());
+}
+
+TEST_F(SigninManagerTest,
+ UnconsentedPrimaryAccountClearedWhenSigninDisallowed) {
+ // Prerequisite: add an unconsented primary account.
+ AccountInfo account = MakeAccountAvailableWithCookies(kTestEmail);
+ ExpectUnconsentedPrimaryAccountSetEvent(account);
+
+ prefs_.SetBoolean(prefs::kSigninAllowed, false);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(
+ identity_manager()->HasPrimaryAccount(signin::ConsentLevel::kSignin));
+
+ EXPECT_EQ(1U, observer().events().size());
+ auto event = observer().events()[0];
+ EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+ event.GetEventTypeFor(ConsentLevel::kSignin));
+ EXPECT_EQ(account, event.GetPreviousState().primary_account);
+ EXPECT_TRUE(event.GetCurrentState().primary_account.IsEmpty());
+}
+
+} // namespace signin