chromium/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.h"

#include <memory>
#include <string>

#include "ash/constants/ash_pref_names.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/test/test_future.h"
#include "base/values.h"
#include "chrome/browser/ash/child_accounts/edu_coexistence_tos_store_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/ash/edu_coexistence/edu_coexistence_login_handler.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/components/account_manager/account_manager_factory.h"
#include "components/account_id/account_id.h"
#include "components/account_manager_core/account.h"
#include "components/account_manager_core/account_manager_facade.h"
#include "components/account_manager_core/chromeos/account_manager.h"
#include "components/account_manager_core/chromeos/account_manager_facade_factory.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

namespace {

constexpr char kValidToken[] = "valid-token";

constexpr char kPrimaryAccount[] = "[email protected]";
constexpr char kPrimaryAccountGaiaId[] = "primary-account-id";

constexpr char kSecondaryAccount1[] = "[email protected]";
constexpr char kSecondaryAccount1GaiaId[] = "secondary-account-1";

constexpr char kSecondaryAccount2[] = "[email protected]";
constexpr char kSecondaryAccount2GaiaId[] = "secondary-account-2";

constexpr char kSecondaryAccount3[] = "[email protected]";
constexpr char kSecondaryAccount3GaiaId[] = "secondary-account-3";

constexpr char kSecondaryAccount4[] = "[email protected]";
constexpr char kSecondaryAccount4GaiaId[] = "secondary-account-4";

const AccountId kDeviceAccount =
    AccountId::FromUserEmailGaiaId(kPrimaryAccount, kPrimaryAccountGaiaId);

::account_manager::Account GetAccountFor(const std::string& email,
                                         const std::string& gaia_id) {
  ::account_manager::AccountKey key(gaia_id,
                                    ::account_manager::AccountType::kGaia);
  return {key, email};
}

void AddAccount(account_manager::AccountManager* account_manager,
                const std::string& email,
                const std::string& gaia_id) {
  ::account_manager::AccountKey account_key(
      gaia_id, ::account_manager::AccountType::kGaia);
  account_manager->UpsertAccount(account_key, email, kValidToken);
}

}  // namespace

class AccountManagerEducoexistenceControllerTest : public testing::Test {
 public:
  AccountManagerEducoexistenceControllerTest() = default;
  AccountManagerEducoexistenceControllerTest(
      const AccountManagerEducoexistenceControllerTest&) = delete;
  AccountManagerEducoexistenceControllerTest& operator=(
      const AccountManagerEducoexistenceControllerTest&) = delete;
  ~AccountManagerEducoexistenceControllerTest() override = default;

  void SetUp() override;

  void UpdatEduCoexistenceToSAcceptedVersion(const std::string& email,
                                             const std::string& tosVersion);

  void UpdateEduCoexistenceToSVersion(const std::string& new_version);

  bool HasInvalidGaiaToken(const ::account_manager::Account& account);

 protected:
  Profile* profile() { return &testing_profile_; }

  account_manager::AccountManager* account_manager() {
    return account_manager_;
  }
  account_manager::AccountManagerFacade* account_manager_facade() {
    return account_manager_facade_;
  }

 private:
  // To support context of browser threads.
  content::BrowserTaskEnvironment task_environment_;
  raw_ptr<account_manager::AccountManager> account_manager_ = nullptr;
  raw_ptr<account_manager::AccountManagerFacade> account_manager_facade_ =
      nullptr;
  network::TestURLLoaderFactory test_url_loader_factory_;
  TestingProfile testing_profile_;
};

void AccountManagerEducoexistenceControllerTest::SetUp() {
  testing_profile_.SetIsSupervisedProfile();
  account_manager_ = g_browser_process->platform_part()
                         ->GetAccountManagerFactory()
                         ->GetAccountManager(profile()->GetPath().value());
  account_manager_facade_ =
      ::GetAccountManagerFacade(profile()->GetPath().value());

  AddAccount(account_manager(), kPrimaryAccount, kPrimaryAccountGaiaId);
}

void AccountManagerEducoexistenceControllerTest::
    UpdatEduCoexistenceToSAcceptedVersion(const std::string& gaia_id,
                                          const std::string& tosVersion) {
  edu_coexistence::UpdateAcceptedToSVersionPref(
      profile(), edu_coexistence::UserConsentInfo(gaia_id, tosVersion));
}

void AccountManagerEducoexistenceControllerTest::UpdateEduCoexistenceToSVersion(
    const std::string& new_version) {
  profile()->GetPrefs()->SetString(prefs::kEduCoexistenceToSVersion,
                                   new_version);
}

bool AccountManagerEducoexistenceControllerTest::HasInvalidGaiaToken(
    const ::account_manager::Account& account) {
  base::test::TestFuture<bool> future;
  account_manager()->HasDummyGaiaToken(account.key, future.GetCallback());
  return future.Get();
}

TEST_F(AccountManagerEducoexistenceControllerTest,
       AccountsInPrefWithInvalidTokenShouldBeInvalidated) {
  // Account will be invalidated.
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount1GaiaId, "0");
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount1GaiaId),
            "0");

  // Account will not be invalidated fine.
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount2GaiaId, "5");
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount2GaiaId),
            "5");

  AddAccount(account_manager(), kSecondaryAccount1, kSecondaryAccount1GaiaId);
  AddAccount(account_manager(), kSecondaryAccount2, kSecondaryAccount2GaiaId);
  EXPECT_FALSE(HasInvalidGaiaToken(
      GetAccountFor(kSecondaryAccount1, kSecondaryAccount1GaiaId)));
  EXPECT_FALSE(HasInvalidGaiaToken(
      GetAccountFor(kSecondaryAccount2, kSecondaryAccount2GaiaId)));

  UpdateEduCoexistenceToSVersion("5");

  EduCoexistenceConsentInvalidationController
      edu_coexistence_invalidation_controller(profile(), account_manager(),
                                              account_manager_facade(),
                                              kDeviceAccount);
  edu_coexistence_invalidation_controller.Init();

  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(HasInvalidGaiaToken(
      GetAccountFor(kSecondaryAccount1, kSecondaryAccount1GaiaId)));
  EXPECT_FALSE(HasInvalidGaiaToken(
      GetAccountFor(kSecondaryAccount2, kSecondaryAccount2GaiaId)));
}

TEST_F(AccountManagerEducoexistenceControllerTest,
       AccountsNotInPrefShouldBeAddedToUserPref) {
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount1GaiaId, "5");
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount2GaiaId, "6");
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount3GaiaId, "7");

  AddAccount(account_manager(), kSecondaryAccount1, kSecondaryAccount1GaiaId);
  AddAccount(account_manager(), kSecondaryAccount2, kSecondaryAccount2GaiaId);
  AddAccount(account_manager(), kSecondaryAccount3, kSecondaryAccount3GaiaId);

  // Note: kSecondaryAccount4 is not present in pref.
  AddAccount(account_manager(), kSecondaryAccount4, kSecondaryAccount4GaiaId);

  EduCoexistenceConsentInvalidationController
      edu_coexistence_invalidation_controller(profile(), account_manager(),
                                              account_manager_facade(),
                                              kDeviceAccount);
  edu_coexistence_invalidation_controller.Init();

  base::RunLoop().RunUntilIdle();

  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount4GaiaId),
            edu_coexistence::kMinTOSVersionNumber);
}

TEST_F(AccountManagerEducoexistenceControllerTest,
       AccountsNotInAccountManagerShouldBeRemovedFromUserPref) {
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount1GaiaId, "5");
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount2GaiaId, "6");
  UpdatEduCoexistenceToSAcceptedVersion(kSecondaryAccount3GaiaId, "7");

  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount1GaiaId),
            "5");
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount2GaiaId),
            "6");
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount3GaiaId),
            "7");

  // kSecondaryAccount1 was unfortunately removed and is not present in account
  // manager.
  AddAccount(account_manager(), kSecondaryAccount2, kSecondaryAccount2GaiaId);
  AddAccount(account_manager(), kSecondaryAccount3, kSecondaryAccount3GaiaId);

  EduCoexistenceConsentInvalidationController
      edu_coexistence_invalidation_controller(profile(), account_manager(),
                                              account_manager_facade(),
                                              kDeviceAccount);
  edu_coexistence_invalidation_controller.Init();

  base::RunLoop().RunUntilIdle();

  // kSecondaryAccount1 is not present
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount1GaiaId),
            "");

  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount2GaiaId),
            "6");
  EXPECT_EQ(edu_coexistence::GetAcceptedToSVersion(profile(),
                                                   kSecondaryAccount3GaiaId),
            "7");
}

}  // namespace ash