chromium/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_utils_unittest.cc

// Copyright 2024 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/system_web_apps/apps/personalization_app/personalization_app_utils.h"

#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/ash/login/demo_mode/demo_mode_test_helper.h"
#include "chrome/browser/ash/login/demo_mode/demo_session.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/install_attributes/stub_install_attributes.h"
#include "components/account_id/account_id.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/account_capabilities_test_mutator.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_type.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash::personalization_app {

namespace {

void AddAndLoginUser(const AccountId& account_id,
                     const user_manager::UserType user_type) {
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  user_manager::User* user = nullptr;
  switch (user_type) {
    case user_manager::UserType::kRegular:
      user = user_manager->AddUser(account_id);
      break;
    case user_manager::UserType::kGuest:
      ASSERT_TRUE(account_id.empty());
      user = user_manager->AddGuestUser();
      break;
    case user_manager::UserType::kChild:
      user = user_manager->AddChildUser(account_id);
      break;
    case user_manager::UserType::kPublicAccount:
      user = user_manager->AddPublicAccountUser(account_id);
      break;
    default:
      GTEST_FAIL() << "Unsupported user type " << user_type;
  }
  user_manager->LoginUser(user->GetAccountId());
  user_manager->SwitchActiveUser(user->GetAccountId());
}

class PersonalizationAppUtilsTest : public testing::Test {
 public:
  PersonalizationAppUtilsTest()
      : scoped_user_manager_(std::make_unique<ash::FakeChromeUserManager>()),
        profile_manager_(TestingBrowserProcess::GetGlobal()) {
    scoped_feature_list_.InitWithFeatures(
        {features::kSeaPen, features::kSeaPenDemoMode,
         features::kFeatureManagementSeaPen},
        {});
  }

  PersonalizationAppUtilsTest(const PersonalizationAppUtilsTest&) = delete;
  PersonalizationAppUtilsTest& operator=(const PersonalizationAppUtilsTest&) =
      delete;
  ~PersonalizationAppUtilsTest() override = default;

  TestingProfileManager& profile_manager() { return profile_manager_; }

  ash::FakeChromeUserManager* GetFakeUserManager() {
    return static_cast<ash::FakeChromeUserManager*>(
        user_manager::UserManager::Get());
  }

  void SetUp() override {
    testing::Test::SetUp();
    ASSERT_TRUE(profile_manager().SetUp());
  }

  void TearDown() override {
    profile_manager().DeleteAllTestingProfiles();
    testing::Test::TearDown();
  }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
  content::BrowserTaskEnvironment task_environment_;
  user_manager::ScopedUserManager scoped_user_manager_;
  TestingProfileManager profile_manager_;
};

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_Guest) {
  auto* guest_profile = profile_manager().CreateGuestProfile();
  AddAndLoginUser(EmptyAccountId(), user_manager::UserType::kGuest);
  ASSERT_FALSE(IsEligibleForSeaPen(guest_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_Child) {
  const std::string email = "[email protected]";
  auto* child_profile = profile_manager().CreateTestingProfile(email);
  child_profile->SetIsSupervisedProfile();
  AddAndLoginUser(AccountId::FromUserEmail(email),
                  user_manager::UserType::kChild);
  ASSERT_FALSE(IsEligibleForSeaPen(child_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_NoProfile) {
  ASSERT_FALSE(IsEligibleForSeaPen(nullptr));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_Googler) {
  const std::string email = "[email protected]";
  auto* googler_profile = profile_manager().CreateTestingProfile(email);
  googler_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  AddAndLoginUser(AccountId::FromUserEmail(email),
                  user_manager::UserType::kRegular);
  ASSERT_TRUE(IsEligibleForSeaPen(googler_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_Managed) {
  const std::string email = "[email protected]";
  auto* managed_profile = profile_manager().CreateTestingProfile(email);
  managed_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  AddAndLoginUser(AccountId::FromUserEmail(email),
                  user_manager::UserType::kRegular);
  ASSERT_FALSE(IsEligibleForSeaPen(managed_profile));
}

TEST_F(PersonalizationAppUtilsTest,
       IsEligibleForSeaPen_Managed_SeaPenEnterpriseEnabled_capabilityIsTrue) {
  base::test::ScopedFeatureList features(features::kSeaPenEnterprise);
  const std::string email = "[email protected]";
  auto* managed_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(managed_profile);
  managed_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);
  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(true);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  ASSERT_TRUE(IsEligibleForSeaPen(managed_profile));
}

TEST_F(PersonalizationAppUtilsTest,
       IsEligibleForSeaPen_Managed_SeaPenEnterpriseEnabled_CapabilityIsFalse) {
  base::test::ScopedFeatureList features(features::kSeaPenEnterprise);
  const std::string email = "[email protected]";
  auto* managed_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(managed_profile);
  managed_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);
  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(false);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  ASSERT_FALSE(IsEligibleForSeaPen(managed_profile));
}

TEST_F(
    PersonalizationAppUtilsTest,
    IsEligibleForSeaPen_Managed_SeaPenEnterpriseEnabled_CapabilityIsUnknown) {
  base::test::ScopedFeatureList features(features::kSeaPenEnterprise);
  const std::string email = "[email protected]";
  auto* managed_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(managed_profile);
  managed_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);
  // No capability is set.

  ASSERT_FALSE(IsEligibleForSeaPen(managed_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_Regular) {
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  AddAndLoginUser(AccountId::FromUserEmail(email),
                  user_manager::UserType::kRegular);
  ASSERT_TRUE(IsEligibleForSeaPen(regular_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_PublicAccount) {
  const std::string email = "[email protected]";
  auto* managed_profile = profile_manager().CreateTestingProfile(email);
  managed_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  AddAndLoginUser(AccountId::FromUserEmail(email),
                  user_manager::UserType::kPublicAccount);

  ASSERT_FALSE(IsEligibleForSeaPen(managed_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPen_PublicAccountDemoMode) {
  const std::string email = "[email protected]";
  auto* managed_profile = profile_manager().CreateTestingProfile(email);
  managed_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
      true);
  AddAndLoginUser(AccountId::FromUserEmail(email),
                  user_manager::UserType::kPublicAccount);

  // Force device into demo mode.
  ASSERT_FALSE(::ash::DemoSession::IsDeviceInDemoMode());
  managed_profile->ScopedCrosSettingsTestHelper()
      ->InstallAttributes()
      ->SetDemoMode();
  ASSERT_TRUE(::ash::DemoSession::IsDeviceInDemoMode());

  // Force demo mode session to start.
  ASSERT_FALSE(::ash::DemoSession::Get());
  auto demo_mode_test_helper = std::make_unique<::ash::DemoModeTestHelper>();
  demo_mode_test_helper->InitializeSession();
  ASSERT_TRUE(::ash::DemoSession::Get());

  ASSERT_TRUE(IsEligibleForSeaPen(managed_profile))
      << "Demo mode should force enable SeaPen for managed profile";
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPenTextInput_UnknownAge) {
  base::test::ScopedFeatureList features(features::kSeaPenTextInput);
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(regular_profile);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);
  // No capability is set.

  ASSERT_FALSE(IsEligibleForSeaPenTextInput(regular_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPenTextInput_MinorUser) {
  base::test::ScopedFeatureList features(features::kSeaPenTextInput);
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(regular_profile);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);

  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(false);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  ASSERT_FALSE(IsEligibleForSeaPenTextInput(regular_profile));
}

TEST_F(PersonalizationAppUtilsTest,
       IsEligibleForSeaPenTextInput_WithoutSeaPenTextInput_AdultUser) {
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(regular_profile);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);

  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(true);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  ASSERT_FALSE(IsEligibleForSeaPenTextInput(regular_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPenTextInput_AdultUser) {
  base::test::ScopedFeatureList features(features::kSeaPenTextInput);
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(regular_profile);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);

  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(true);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  ASSERT_TRUE(IsEligibleForSeaPenTextInput(regular_profile));
}

TEST_F(PersonalizationAppUtilsTest, IsEligibleForSeaPenTextInputEnglishUsers) {
  base::test::ScopedFeatureList features(features::kSeaPenTextInput);
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(regular_profile);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);

  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(true);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  // Set application locale.
  g_browser_process->SetApplicationLocale("en-GB");

  ASSERT_TRUE(IsSystemInEnglishLanguage());
  ASSERT_TRUE(IsEligibleForSeaPenTextInput(regular_profile));
}

TEST_F(PersonalizationAppUtilsTest,
       IsEligibleForSeaPenTextInputNonEnglishUsers) {
  base::test::ScopedFeatureList features(features::kSeaPenTextInput);
  const std::string email = "[email protected]";
  auto* regular_profile = profile_manager().CreateTestingProfile(email);
  auto* identity_manager =
      IdentityManagerFactory::GetForProfile(regular_profile);
  // Set up gaia id.
  ash::FakeChromeUserManager* user_manager =
      static_cast<ash::FakeChromeUserManager*>(
          user_manager::UserManager::Get());
  AccountInfo primary_account = signin::MakePrimaryAccountAvailable(
      identity_manager, email, signin::ConsentLevel::kSignin);
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId(email, primary_account.gaia);
  user_manager->AddUser(account_id);
  user_manager->LoginUser(account_id);

  // Set up capability.
  AccountCapabilitiesTestMutator mutator(&primary_account.capabilities);
  mutator.set_can_use_manta_service(true);
  signin::UpdateAccountInfoForAccount(identity_manager, primary_account);

  // Set application locale.
  g_browser_process->SetApplicationLocale("de");

  ASSERT_FALSE(IsSystemInEnglishLanguage());
  ASSERT_FALSE(IsEligibleForSeaPenTextInput(regular_profile));
}
}  // namespace

}  // namespace ash::personalization_app