chromium/chrome/browser/profiles/profile_manager_unittest.cc

// Copyright 2012 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/profiles/profile_manager.h"

#include <stddef.h>

#include <string>
#include <utility>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_path_watcher.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/delete_profile_helper.h"
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_init_params.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/fake_profile_manager.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/account_id/account_id.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/supervised_user/core/common/pref_names.h"
#include "components/supervised_user/core/common/supervised_user_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"

#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/lifetime/application_lifetime_desktop.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/test_browser_window.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/arc_features.h"
#include "ash/components/arc/arc_prefs.h"
#include "ash/components/arc/session/arc_management_transition.h"
#include "ash/constants/ash_switches.h"
#include "chrome/browser/ash/login/users/avatar/user_image_manager_impl.h"
#include "chrome/browser/ash/login/users/chrome_user_manager_impl.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/ash/wallpaper_handlers/test_wallpaper_fetcher_delegate.h"
#include "chrome/browser/ui/ash/wallpaper/test_wallpaper_controller.h"
#include "chrome/browser/ui/ash/wallpaper/wallpaper_controller_client_impl.h"
#include "chromeos/ash/components/system/fake_statistics_provider.h"
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_names.h"
#include "extensions/common/features/feature_session_type.h"
#include "extensions/common/mojom/feature_session_type.mojom.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
#include "chromeos/lacros/lacros_test_helper.h"
#include "chromeos/startup/browser_init_params.h"
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

ASCIIToUTF16;

namespace {

// This global variable is used to check that value returned to different
// observers is the same.
Profile* g_created_profile =;

void ExpectNullProfile(base::OnceClosure closure, Profile* profile) {}

void ExpectProfileWithName(const std::string& profile_name,
                           bool incognito,
                           base::OnceClosure closure,
                           Profile* profile) {}

class ProfileDeletionWaiter {};

}  // namespace

class ProfileManagerTest : public testing::Test {};

TEST_F(ProfileManagerTest, GetProfile) {}

TEST_F(ProfileManagerTest, DefaultProfileDir) {}

MATCHER(SameNotNull, "The same non-NULL value for all calls.") {}

#if BUILDFLAG(IS_CHROMEOS_ASH)

// This functionality only exists on Chrome OS.
TEST_F(ProfileManagerTest, LoggedInProfileDir) {
  base::FilePath expected_default =
      base::FilePath().AppendASCII(chrome::kInitialProfile);
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  EXPECT_EQ(expected_default.value(),
            profile_manager->GetInitialProfileDir().value());

  constexpr char kTestUserName[] = "[email protected]";
  constexpr char kTestUserGaiaId[] = "0123456789";
  const AccountId test_account_id(
      AccountId::FromUserEmailGaiaId(kTestUserName, kTestUserGaiaId));
  auto* user_manager = new ash::FakeChromeUserManager();
  user_manager::ScopedUserManager enabler(base::WrapUnique(user_manager));

  const user_manager::User* active_user =
      user_manager->AddUser(test_account_id);
  user_manager->LoginUser(test_account_id);
  user_manager->SwitchActiveUser(test_account_id);

  base::FilePath expected_logged_in(
      ash::ProfileHelper::GetUserProfileDir(active_user->username_hash()));
  EXPECT_EQ(expected_logged_in.value(),
            profile_manager->GetInitialProfileDir().value());
  VLOG(1) << temp_dir_.GetPath()
                 .Append(profile_manager->GetInitialProfileDir())
                 .value();
}

// Test Get[ActiveUser|PrimaryUser|LastUsed]Profile does not load user profile.
TEST_F(ProfileManagerTest, UserProfileLoading) {
  using ::ash::ProfileHelper;

  Profile* const signin_profile = ProfileHelper::GetSigninProfile();

  // Get[Active|Primary|LastUsed]Profile return the sign-in profile before login
  // happens. IsSameOrParent() is used to properly test against TestProfile
  // whose OTR version uses a different temp path.
  EXPECT_TRUE(
      ProfileManager::GetActiveUserProfile()->IsSameOrParent(signin_profile));
  EXPECT_TRUE(
      ProfileManager::GetPrimaryUserProfile()->IsSameOrParent(signin_profile));
  EXPECT_TRUE(
      ProfileManager::GetLastUsedProfile()->IsSameOrParent(signin_profile));

  // User signs in but user profile loading has not started.
  const AccountId account_id =
      AccountId::FromUserEmailGaiaId("[email protected]", "0123456789");
  const std::string user_id_hash =
      user_manager::FakeUserManager::GetFakeUsernameHash(account_id);
  user_manager::UserManager::Get()->UserLoggedIn(account_id, user_id_hash,
                                                 false /* browser_restart */,
                                                 false /* is_child */);

  // Sign-in profile should be returned at this stage. Otherwise, login code
  // ends up in an invalid state. Strange things as in http://crbug.com/728683
  // and http://crbug.com/718734 happens.
  EXPECT_TRUE(
      ProfileManager::GetActiveUserProfile()->IsSameOrParent(signin_profile));
  EXPECT_TRUE(
      ProfileManager::GetPrimaryUserProfile()->IsSameOrParent(signin_profile));

  // GetLastUsedProfile() after login but before a user profile is loaded is
  // fatal.
  EXPECT_DEATH_IF_SUPPORTED(ProfileManager::GetLastUsedProfile(), ".*");

  // Simulate UserSessionManager loads the profile.
  Profile* const user_profile =
      g_browser_process->profile_manager()->GetProfile(
          ProfileHelper::Get()->GetProfilePathByUserIdHash(user_id_hash));
  ASSERT_FALSE(user_profile->IsSameOrParent(signin_profile));

  // User profile is returned thereafter.
  EXPECT_TRUE(
      ProfileManager::GetActiveUserProfile()->IsSameOrParent(user_profile));
  EXPECT_TRUE(
      ProfileManager::GetPrimaryUserProfile()->IsSameOrParent(user_profile));
  EXPECT_TRUE(
      ProfileManager::GetLastUsedProfile()->IsSameOrParent(user_profile));
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(ProfileManagerTest, CreateAndUseTwoProfiles) {}

TEST_F(ProfileManagerTest, LoadNonExistingProfile) {}

TEST_F(ProfileManagerTest, LoadExistingProfile) {}

TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) {}

TEST_F(ProfileManagerTest, CreateProfilesAsync) {}

// Regression test for https://crbug.com/1472849
TEST_F(ProfileManagerTest, ConcurrentCreationAsyncAndSync) {}

#if !BUILDFLAG(IS_ANDROID)
// There's no multi-profiles on Android.
TEST_F(ProfileManagerTest, CreateMultiProfileAsync) {}

TEST_F(ProfileManagerTest, CreateMultiProfilesAsync) {}

TEST_F(ProfileManagerTest, CreateMultiProfileAsyncMultipleRequests) {}

TEST_F(ProfileManagerTest,
       CreateMultiProfilesAsyncWithBrokenPrefAndProfileInCache) {}

TEST_F(ProfileManagerTest,
       PRE_CreateMultiProfilesAsyncWithBrokenPrefAndProfileOnDisk) {}

// We need to restart Chrome in the mean-time to make sure the profile is not
// loaded in memory.
TEST_F(ProfileManagerTest,
       CreateMultiProfilesAsyncWithBrokenPrefAndProfileOnDisk) {}

TEST_F(ProfileManagerTest, CreateHiddenProfileAsync) {}
#endif  // !BUILDFLAG(IS_ANDROID)

// Checks that the supervised profiles no longer marked as omitted on creation.
TEST_F(ProfileManagerTest, AddProfileToStorageCheckNotOmitted) {}

#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
TEST_F(ProfileManagerTest, GetSystemProfilePath) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)

// Test profile manager that creates all profiles as guest by default.
class UnittestGuestProfileManager : public FakeProfileManager {};

class ProfileManagerGuestTest : public ProfileManagerTest {};

TEST_F(ProfileManagerGuestTest, GetLastUsedProfileAllowedByPolicy) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ProfileManagerGuestTest, GuestProfileIncognito) {
  Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
  EXPECT_TRUE(primary_profile->IsOffTheRecord());

  Profile* active_profile = ProfileManager::GetActiveUserProfile();
  EXPECT_TRUE(active_profile->IsOffTheRecord());

  EXPECT_TRUE(active_profile->IsSameOrParent(primary_profile));

  Profile* last_used_profile = ProfileManager::GetLastUsedProfile();
  EXPECT_TRUE(last_used_profile->IsOffTheRecord());

  EXPECT_TRUE(last_used_profile->IsSameOrParent(active_profile));
}
#endif

TEST_F(ProfileManagerGuestTest, GetGuestProfilePath) {}

TEST_F(ProfileManagerGuestTest, GuestProfileAttributes) {}

TEST_F(ProfileManagerTest, AutoloadProfilesWithBackgroundApps) {}

TEST_F(ProfileManagerTest, DoNotAutoloadProfilesIfBackgroundModeOff) {}

TEST_F(ProfileManagerTest, InitProfileUserPrefs) {}

// Tests that a new profile's entry in the profile attributes storage is setup
// with the same values that are in the profile prefs.
TEST_F(ProfileManagerTest, InitProfileAttributesStorageForAProfile) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ProfileManagerTest, InitProfileForChildOnFirstSignIn) {
  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      true /* profile_is_new */, false /* arc_signed_in */,
      false /* profile_is_child */, true /* user_is_child */,
      false /* profile_is_managed */, false /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION));
  EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId),
            supervised_user::kChildAccountSUID);
}

TEST_F(ProfileManagerTest, InitProfileForRegularToChildTransition) {
  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      false /* profile_is_new */, true /* arc_signed_in */,
      false /* profile_is_child */, true /* user_is_child */,
      false /* profile_is_managed */, false /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::REGULAR_TO_CHILD));
  EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId),
            supervised_user::kChildAccountSUID);
}

TEST_F(ProfileManagerTest, InitProfileForChildToRegularTransition) {
  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      false /* profile_is_new */, true /* arc_signed_in */,
      true /* profile_is_child */, false /* user_is_child */,
      true /* profile_is_managed */, false /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::CHILD_TO_REGULAR));
  EXPECT_TRUE(profile->GetPrefs()->GetString(prefs::kSupervisedUserId).empty());
}

TEST_F(ProfileManagerTest, InitProfileForUnmanagedToManagedTransition) {
  base::test::ScopedFeatureList features;
  features.InitAndEnableFeature(
      arc::kEnableUnmanagedToManagedTransitionFeature);

  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      false /* profile_is_new */, true /* arc_signed_in */,
      false /* profile_is_child */, false /* user_is_child */,
      true /* profile_is_managed */, false /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::UNMANAGED_TO_MANAGED));
}

TEST_F(ProfileManagerTest, InitProfileForManagedUserOnFirstSignIn) {
  base::test::ScopedFeatureList features;
  features.InitAndEnableFeature(
      arc::kEnableUnmanagedToManagedTransitionFeature);

  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      true /* profile_is_new */, false /* arc_signed_in */,
      false /* profile_is_child */, false /* user_is_child */,
      true /* profile_is_managed */, false /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION));
}

TEST_F(ProfileManagerTest,
       InitProfileForChildToRegularTransitionArcNotSignedIn) {
  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      false /* profile_is_new */, false /* arc_signed_in */,
      true /* profile_is_child */, false /* user_is_child */,
      true /* profile_is_managed */, false /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION));
  EXPECT_TRUE(profile->GetPrefs()->GetString(prefs::kSupervisedUserId).empty());
}

TEST_F(ProfileManagerTest,
       InitProfileForManagedUserForFirstSignInOnNewVersion) {
  base::test::ScopedFeatureList features;
  features.InitAndEnableFeature(
      arc::kEnableUnmanagedToManagedTransitionFeature);

  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      false /* profile_is_new */, true /* arc_signed_in */,
      false /* profile_is_child */, false /* user_is_child */,
      true /* profile_is_managed */, std::nullopt /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION));
}

TEST_F(ProfileManagerTest, InitProfileForChildUserForFirstSignInOnNewVersion) {
  base::test::ScopedFeatureList features;
  features.InitAndEnableFeature(
      arc::kEnableUnmanagedToManagedTransitionFeature);

  std::unique_ptr<Profile> profile = InitProfileForArcTransitionTest(
      false /* profile_is_new */, true /* arc_signed_in */,
      true /* profile_is_child */, true /* user_is_child */,
      true /* profile_is_managed */, std::nullopt /* arc_is_managed */);

  EXPECT_EQ(
      profile->GetPrefs()->GetInteger(arc::prefs::kArcManagementTransition),
      static_cast<int>(arc::ArcManagementTransition::NO_TRANSITION));
  EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId),
            supervised_user::kChildAccountSUID);
}

#endif

TEST_F(ProfileManagerTest, GetLastUsedProfileAllowedByPolicy) {}

#if !BUILDFLAG(IS_ANDROID)
// There's no Browser object on Android.
TEST_F(ProfileManagerTest, LastOpenedProfiles) {}

TEST_F(ProfileManagerTest, LastOpenedProfilesAtShutdown) {}

TEST_F(ProfileManagerTest, LastOpenedProfilesDoesNotContainIncognito) {}
#endif  // !BUILDFLAG(IS_ANDROID)

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
// There's no Browser object on Android and there's no multi-profiles on Chrome.
TEST_F(ProfileManagerTest, EphemeralProfilesDontEndUpAsLastProfile) {}

TEST_F(ProfileManagerTest, EphemeralProfilesDontEndUpAsLastOpenedAtShutdown) {}

TEST_F(ProfileManagerTest, CleanUpEphemeralProfiles) {}

TEST_F(ProfileManagerGuestTest, CleanUpOnlyEphemeralProfiles) {}

TEST_F(ProfileManagerTest, CleanUpEphemeralProfilesWithGuestLastUsedProfile) {}

TEST_F(ProfileManagerTest, DestroyProfileOnBrowserClose) {}

TEST_F(ProfileManagerTest, DestroyEphemeralProfileOnBrowserClose) {}

TEST_F(ProfileManagerTest, ActiveProfileDeleted) {}

TEST_F(ProfileManagerTest, LastProfileDeleted) {}

TEST_F(ProfileManagerGuestTest, LastProfileDeletedWithGuestActiveProfile) {}

TEST_F(ProfileManagerTest, ProfileDisplayNameResetsDefaultName) {}

TEST_F(ProfileManagerTest, ProfileDisplayNamePreservesCustomName) {}

TEST_F(ProfileManagerTest, ProfileDisplayNamePreservesSignedInName) {}
#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)

// GetAvatarNameForProfile() is not defined on Android.
#if !BUILDFLAG(IS_ANDROID)
TEST_F(ProfileManagerTest, ProfileDisplayNameIsEmailIfDefaultName) {}
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(IS_MAC)
// These tests are for a Mac-only code path that assumes the browser
// process isn't killed when all browser windows are closed.
TEST_F(ProfileManagerTest, ActiveProfileDeletedNeedsToLoadNextProfile) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  ASSERT_TRUE(profile_manager);

  // Create and load one profile, and just create a second profile.
  const std::string profile_basename1 = "New Profile 1";
  const std::string profile_basename2 = "New Profile 2";
  base::FilePath profile_path1 =
      temp_dir_.GetPath().AppendASCII(profile_basename1);
  base::FilePath profile_path2 =
      temp_dir_.GetPath().AppendASCII(profile_basename2);

  MockObserver mock_observer;
  EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull()))
      .Times(testing::AtLeast(1));
  EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull()))
      .Times(testing::AtLeast(1));
  CreateProfileAsync(profile_manager, profile_path1, &mock_observer);
  content::RunAllTasksUntilIdle();

  // Track the profile, but don't load it.
  ProfileAttributesStorage& storage =
      profile_manager->GetProfileAttributesStorage();
  ProfileAttributesInitParams params;
  params.profile_path = profile_path2;
  params.profile_name = ASCIIToUTF16(profile_basename2);
  params.gaia_id = "23456";
  params.is_consented_primary_account = true;
  storage.AddProfile(std::move(params));
  content::RunAllTasksUntilIdle();

  EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size());
  EXPECT_EQ(2u, storage.GetNumberOfProfiles());

  // Set the active profile.
  PrefService* local_state = g_browser_process->local_state();
  local_state->SetString(prefs::kProfileLastUsed, profile_basename1);

  // Delete the active profile. This should switch and load the unloaded
  // profile.
  profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion(
      profile_path1, base::DoNothing(),
      ProfileMetrics::DELETE_PROFILE_USER_MANAGER);

  content::RunAllTasksUntilIdle();

  EXPECT_EQ(profile_path2, profile_manager->GetLastUsedProfile()->GetPath());
  EXPECT_EQ(profile_basename2, local_state->GetString(prefs::kProfileLastUsed));
}

// This tests the recursive call in ProfileManager::OnNewActiveProfileLoaded
// by simulating a scenario in which the profile that is being loaded as
// the next active profile has also been marked for deletion, so the
// ProfileManager needs to recursively select a different next profile.
TEST_F(ProfileManagerTest, ActiveProfileDeletedNextProfileDeletedToo) {
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  ASSERT_TRUE(profile_manager);

  // Create and load one profile, and create two more profiles.
  const std::string profile_basename1 = "New Profile 1";
  const std::string profile_basename2 = "New Profile 2";
  const std::string profile_basename3 = "New Profile 3";
  base::FilePath profile_path1 =
      temp_dir_.GetPath().AppendASCII(profile_basename1);
  base::FilePath profile_path2 =
      temp_dir_.GetPath().AppendASCII(profile_basename2);
  base::FilePath profile_path3 =
      temp_dir_.GetPath().AppendASCII(profile_basename3);

  MockObserver mock_observer;
  EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull()))
      .Times(testing::AtLeast(1));
  EXPECT_CALL(mock_observer, OnProfileInitialized(testing::NotNull()))
      .Times(testing::AtLeast(1));
  CreateProfileAsync(profile_manager, profile_path1, &mock_observer);
  content::RunAllTasksUntilIdle();

  // Create the other profiles, but don't load them. Assign a fake avatar icon
  // to ensure that profiles in the profile attributes storage are sorted by the
  // profile name, and not randomly by the avatar name.
  ProfileAttributesStorage& storage =
      profile_manager->GetProfileAttributesStorage();
  ProfileAttributesInitParams params2;
  params2.profile_path = profile_path2;
  params2.profile_name = ASCIIToUTF16(profile_basename2);
  params2.gaia_id = "23456";
  params2.user_name = ASCIIToUTF16(profile_basename2);
  params2.is_consented_primary_account = true;
  params2.icon_index = 1;
  storage.AddProfile(std::move(params2));
  ProfileAttributesInitParams params3;
  params3.profile_path = profile_path3;
  params3.profile_name = ASCIIToUTF16(profile_basename3);
  params3.gaia_id = "34567";
  params3.user_name = ASCIIToUTF16(profile_basename3);
  params3.is_consented_primary_account = true;
  params3.icon_index = 2;
  storage.AddProfile(std::move(params3));

  content::RunAllTasksUntilIdle();

  EXPECT_EQ(1u, profile_manager->GetLoadedProfiles().size());
  EXPECT_EQ(3u, storage.GetNumberOfProfiles());

  // Set the active profile.
  PrefService* local_state = g_browser_process->local_state();
  local_state->SetString(prefs::kProfileLastUsed,
                         profile_path1.BaseName().MaybeAsASCII());

  // Delete the active profile, Profile1.
  // This will post a CreateProfileAsync message, that tries to load Profile2,
  // which checks that the profile is not being deleted, and then calls back
  // FinishDeletingProfile for Profile1.
  // Try to break this flow by setting the active profile to Profile2 in the
  // middle (so after the first posted message), and trying to delete Profile2,
  // so that the ProfileManager has to look for a different profile to load.
  profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion(
      profile_path1, base::DoNothing(),
      ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
  local_state->SetString(prefs::kProfileLastUsed,
                         profile_path2.BaseName().MaybeAsASCII());
  profile_manager->GetDeleteProfileHelper().MaybeScheduleProfileForDeletion(
      profile_path2, base::DoNothing(),
      ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
  content::RunAllTasksUntilIdle();

  EXPECT_EQ(profile_path3, profile_manager->GetLastUsedProfile()->GetPath());
  EXPECT_EQ(profile_basename3, local_state->GetString(prefs::kProfileLastUsed));
}
#endif  // BUILDFLAG(IS_MAC)

TEST_F(ProfileManagerTest, CannotCreateProfileOutsideUserDir) {}

TEST_F(ProfileManagerTest, CannotCreateProfileOutsideUserDirAsync) {}

TEST_F(ProfileManagerTest, ScopedProfileKeepAlive) {}

#if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_F(ProfileManagerTest, RegularSession) {
  // Setup regular session in LaCrOS.
  crosapi::mojom::BrowserInitParamsPtr init_params =
      crosapi::mojom::BrowserInitParams::New();
  init_params->session_type = crosapi::mojom::SessionType::kRegularSession;
  chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));

  base::FilePath dest_path = temp_dir_.GetPath();
  dest_path = dest_path.Append(FILE_PATH_LITERAL("Regular Profile"));

  // Create and initialize a profile.
  ProfileManager* profile_manager = g_browser_process->profile_manager();
  Profile* profile = profile_manager->GetProfile(dest_path);

  ASSERT_TRUE(profile);
  EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId),
            std::string());
  EXPECT_FALSE(profile->IsChild());
}

TEST_F(ProfileManagerTest, ChildSession) {
  // Setup child session in LaCrOS.
  crosapi::mojom::BrowserInitParamsPtr init_params =
      crosapi::mojom::BrowserInitParams::New();
  init_params->session_type = crosapi::mojom::SessionType::kChildSession;
  chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));

  // Create and initialize a profile.
  base::FilePath dest_path = temp_dir_.GetPath();
  dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile"));

  ProfileManager* profile_manager = g_browser_process->profile_manager();
  const Profile* profile = profile_manager->GetProfile(dest_path);

  ASSERT_TRUE(profile);
  EXPECT_EQ(profile->GetPrefs()->GetString(prefs::kSupervisedUserId),
            supervised_user::kChildAccountSUID);
  EXPECT_TRUE(profile->IsChild());
}
#endif

// Tests that a new profile's entry in the profile attributes storage is setup
// with the same values that are in the profile prefs.
TEST_F(ProfileManagerTest, ProfileCountRecordedAtProfileInit) {}