chromium/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc

// Copyright 2017 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/lock_screen_apps/lock_screen_profile_creator_impl.h"

#include <initializer_list>
#include <memory>
#include <ostream>
#include <string>
#include <type_traits>
#include <utility>

#include "ash/components/arc/session/arc_service_manager.h"
#include "ash/components/arc/session/arc_session.h"
#include "ash/components/arc/session/arc_session_runner.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/numerics/clamped_math.h"
#include "base/numerics/safe_conversions.h"
#include "base/one_shot_event.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
#include "base/traits_bag.h"
#include "base/values.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/app_service_test.h"
#include "chrome/browser/ash/arc/session/arc_session_manager.h"
#include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/note_taking/note_taking_helper.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/common/pref_names.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 "chromeos/ash/components/dbus/concierge/concierge_client.h"
#include "components/account_id/account_id.h"
#include "components/crx_file/id_util.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/switches.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

using ::ash::ProfileHelper;
using lock_screen_apps::LockScreenProfileCreator;
using lock_screen_apps::LockScreenProfileCreatorImpl;

const char kPrimaryUser[] = "user@user";

std::unique_ptr<arc::ArcSession> ArcSessionFactory() {
  ADD_FAILURE() << "Attempt to create arc session.";
  return nullptr;
}

void SetWasRun(bool* was_run) {
  *was_run = true;
}

// Wrapper around a |Profile::Delegate| used to manage timing of an async
// profile creation callbacks, and to provide a way to override profile creation
// result.
// An instance can be passed to TestingProfile as delegate - when the testing
// profile creation is done, i.e. when the delegate's
// |OnProfileCreationFinished| is called this will remember the result. The
// creation result will be forwarded to the actual (wrapped) delegate when
// |WaitForCreationAndOverrideResponse| is called. This method will additionally
// wait until the profile creation finishes.
class PendingProfileCreation : public Profile::Delegate {
 public:
  PendingProfileCreation() {}

  PendingProfileCreation(const PendingProfileCreation&) = delete;
  PendingProfileCreation& operator=(const PendingProfileCreation&) = delete;

  ~PendingProfileCreation() override {}

  // Sets the pending profile creation to track a profile creation,
  // |path| - the created profile path.
  // |delegate| - the original profile creation delegate - the delegate to
  //     which creation result should be forwarded when appropriate.
  //
  // This will cause test failure if called when the |PendingProfileCreation| is
  // already set up to track a profile. The |PendingProfileCreation| will be
  // reset when the profile creation result is forwarded to |delegate|.
  void Set(const base::FilePath& path, Profile::Delegate* delegate) {
    ASSERT_TRUE(path_.empty());
    ASSERT_FALSE(delegate_);

    path_ = path;
    delegate_ = delegate;
    profile_ = nullptr;

    if (!wait_quit_closure_.is_null()) {
      ADD_FAILURE() << "Wait closure set on reset.";
      RunWaitQuitClosure();
    }
  }

  // Tracked profile path.
  const base::FilePath& path() const { return path_; }

  // Waits for profile creation to finish, and then forwards creation result to
  // the original delegate, with profile creation success value set to
  // |success|. This will return false if the |PendingProfileCreation| is not
  // set to track a profile, or if the profile creation fails.
  bool WaitForCreationAndOverrideResponse(bool success) {
    if (path_.empty() || !delegate_)
      return false;

    if (!profile_) {
      base::RunLoop run_loop;
      wait_quit_closure_ = run_loop.QuitClosure();
      run_loop.Run();
    }

    if (!profile_)
      return false;

    if (!success_)
      return false;

    path_ = base::FilePath();

    Profile::Delegate* delegate = delegate_;
    delegate_ = nullptr;

    Profile* profile = profile_;
    profile_ = nullptr;

    delegate->OnProfileCreationFinished(
        profile, Profile::CreateMode::kAsynchronous, success, is_new_profile_);
    return true;
  }

  void OnProfileCreationStarted(Profile* profile,
                                Profile::CreateMode create_mode) override {}

  // Called when the profile is created - it caches the result, and quits the
  // run loop potentially set in |WaitForCreationAndOverrideResponse|.
  void OnProfileCreationFinished(Profile* profile,
                                 Profile::CreateMode create_mode,
                                 bool success,
                                 bool is_new_profile) override {
    ASSERT_FALSE(profile_);

    profile_ = profile;
    success_ = success;
    is_new_profile_ = is_new_profile;

    RunWaitQuitClosure();
  }

 private:
  // Quits run loop set in |WaitForCreationAndOverrideResponse|.
  void RunWaitQuitClosure() {
    if (wait_quit_closure_.is_null())
      return;

    std::move(wait_quit_closure_).Run();
  }

  base::FilePath path_;
  raw_ptr<Profile::Delegate> delegate_ = nullptr;
  base::OnceClosure wait_quit_closure_;

  raw_ptr<Profile> profile_ = nullptr;
  bool success_ = false;
  bool is_new_profile_ = false;
};

// Test profile manager implementation used to track async profile creation.
class UnittestProfileManager : public FakeProfileManager {
 public:
  explicit UnittestProfileManager(const base::FilePath& user_data_dir)
      : FakeProfileManager(user_data_dir) {}

  ~UnittestProfileManager() override = default;

  PendingProfileCreation* pending_profile_creation() {
    return &pending_profile_creation_;
  }

  std::unique_ptr<TestingProfile> BuildTestingProfile(
      const base::FilePath& path,
      Delegate* delegate,
      Profile::CreateMode create_mode) override {
    pending_profile_creation_.Set(path, delegate);

    auto new_profile = std::make_unique<TestingProfile>(
        path, &pending_profile_creation_, create_mode);

    // Build accompaning incognito profile, to ensure it has the same path
    // as the original profile.
    TestingProfile::Builder incognito_builder;
    incognito_builder.SetPath(path);
    incognito_builder.BuildIncognito(new_profile.get());

    return new_profile;
  }

 private:
  PendingProfileCreation pending_profile_creation_;
};

class LockScreenProfileCreatorImplTest : public testing::Test {
 public:
  LockScreenProfileCreatorImplTest()
      : local_state_(TestingBrowserProcess::GetGlobal()) {}

  LockScreenProfileCreatorImplTest(const LockScreenProfileCreatorImplTest&) =
      delete;
  LockScreenProfileCreatorImplTest& operator=(
      const LockScreenProfileCreatorImplTest&) = delete;

  ~LockScreenProfileCreatorImplTest() override {}

  void SetUp() override {
    ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);

    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
        extensions::switches::kAllowlistedExtensionID,
        crx_file::id_util::GenerateId("test_app"));
    ASSERT_TRUE(user_data_dir_.CreateUniqueTempDir());

    auto profile_manager_unique =
        std::make_unique<UnittestProfileManager>(user_data_dir_.GetPath());
    profile_manager_ = profile_manager_unique.get();
    TestingBrowserProcess::GetGlobal()->SetProfileManager(
        std::move(profile_manager_unique));

    CreatePrimaryProfile();

    InitExtensionSystem(primary_profile_);

    apps::WaitForAppServiceProxyReady(
        apps::AppServiceProxyFactory::GetForProfile(primary_profile_));

    // Needed by note taking helper.
    arc_session_manager_ = arc::CreateTestArcSessionManager(
        std::make_unique<arc::ArcSessionRunner>(
            base::BindRepeating(&ArcSessionFactory)));
    ash::NoteTakingHelper::Initialize();

    lock_screen_profile_creator_ =
        std::make_unique<LockScreenProfileCreatorImpl>(primary_profile_,
                                                       &tick_clock_);
  }

  void TearDown() override {
    lock_screen_profile_creator_.reset();
    arc_session_manager_.reset();
    ash::NoteTakingHelper::Shutdown();
    TestingBrowserProcess::GetGlobal()->SetProfileManager(nullptr);

    ash::ConciergeClient::Shutdown();
  }

  UnittestProfileManager* profile_manager() { return profile_manager_; }

  Profile* primary_profile() { return primary_profile_; }

  LockScreenProfileCreator* lock_screen_profile_creator() {
    return lock_screen_profile_creator_.get();
  }

  base::SimpleTestTickClock* tick_clock() { return &tick_clock_; }

  extensions::TestExtensionSystem* GetExtensionSystem(Profile* profile) {
    return static_cast<extensions::TestExtensionSystem*>(
        extensions::ExtensionSystem::Get(profile));
  }

  // Creates a lock screen enabled note taking app.
  scoped_refptr<const extensions::Extension> CreateTestNoteTakingApp() {
    base::Value::Dict background = base::Value::Dict().Set(
        "scripts", base::Value::List().Append("background.js"));
    base::Value::List action_handlers =
        base::Value::List().Append(base::Value::Dict()
                                       .Set("action", "new_note")
                                       .Set("enabled_on_lock_screen", true));

    auto manifest_builder =
        base::Value::Dict()
            .Set("name", "Note taking app")
            .Set("manifest_version", 2)
            .Set("version", "1.1")
            .Set("app",
                 base::Value::Dict().Set("background", std::move(background)))
            .Set("permissions", base::Value::List().Append("lockScreen"))
            .Set("action_handlers", std::move(action_handlers));

    return extensions::ExtensionBuilder()
        .SetManifest(std::move(manifest_builder))
        .SetID(crx_file::id_util::GenerateId("test_app"))
        .Build();
  }

  // Creates a lock screen enabled note taking app and adds it to the profile's
  // extension service.
  scoped_refptr<const extensions::Extension> AddTestNoteTakingApp(
      Profile* profile) {
    scoped_refptr<const extensions::Extension> app = CreateTestNoteTakingApp();
    extensions::ExtensionSystem::Get(profile)
        ->extension_service()
        ->AddExtension(app.get());
    return app;
  }

  // Sets |app| as the default note taking app in a  profile, and sets whether
  // it's enabled on the lock screen.
  void SetAppEnabledOnLockScreen(Profile* profile,
                                 const extensions::Extension* app,
                                 bool enabled) {
    ash::NoteTakingHelper::Get()->SetPreferredApp(profile, app->id());
    ash::NoteTakingHelper::Get()->SetPreferredAppEnabledOnLockScreen(profile,
                                                                     enabled);
  }

  // Marks extension system as ready.
  void SetExtensionSystemReady(Profile* profile) {
    GetExtensionSystem(profile)->SetReady();
    base::RunLoop run_loop;
    GetExtensionSystem(profile)->ready().Post(FROM_HERE,
                                              run_loop.QuitClosure());
    run_loop.Run();
  }

  void RecordLockScreenProfile(Profile** lock_screen_profile) {
    *lock_screen_profile = lock_screen_profile_creator()->lock_screen_profile();
  }

 private:
  void InitExtensionSystem(Profile* profile) {
    GetExtensionSystem(profile)->CreateExtensionService(
        base::CommandLine::ForCurrentProcess(),
        profile->GetPath().Append("Extensions") /* install_directory */,
        false /* autoupdate_enabled */);
  }

  void CreatePrimaryProfile() {
    DCHECK(!scoped_user_manager_) << "there can be only one primary profile";
    auto user_manager = std::make_unique<ash::FakeChromeUserManager>();
    const AccountId account_id(AccountId::FromUserEmail(kPrimaryUser));
    user_manager->AddUser(account_id);
    user_manager->LoginUser(account_id);
    scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
        std::move(user_manager));

    base::FilePath user_profile_path =
        user_data_dir_.GetPath().Append(ProfileHelper::Get()->GetUserProfileDir(
            user_manager::FakeUserManager::GetFakeUsernameHash(account_id)));
    auto profile = std::make_unique<TestingProfile>(user_profile_path);
    primary_profile_ = profile.get();
    profile_manager_->RegisterTestingProfile(std::move(profile),
                                             false /*add_to_storage*/);
    DCHECK(ash::ProfileHelper::IsPrimaryProfile(primary_profile_));
  }

  base::ScopedTempDir user_data_dir_;
  ScopedTestingLocalState local_state_;
  content::BrowserTaskEnvironment task_environment_;

  ash::ScopedCrosSettingsTestHelper cros_settings_test_helper_;
  std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;

  raw_ptr<UnittestProfileManager, DanglingUntriaged> profile_manager_;

  raw_ptr<TestingProfile, DanglingUntriaged> primary_profile_ = nullptr;

  base::SimpleTestTickClock tick_clock_;

  std::unique_ptr<arc::ArcServiceManager> arc_service_manager_;
  std::unique_ptr<arc::ArcSessionManager> arc_session_manager_;

  std::unique_ptr<LockScreenProfileCreator> lock_screen_profile_creator_;
};

}  // namespace

TEST_F(LockScreenProfileCreatorImplTest,
       CreateProfileWhenLockScreenNotesEnabled) {
  EXPECT_FALSE(lock_screen_profile_creator()->Initialized());
  lock_screen_profile_creator()->Initialize();

  EXPECT_TRUE(lock_screen_profile_creator()->Initialized());

  bool callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_run));

  SetExtensionSystemReady(primary_profile());

  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());

  EXPECT_FALSE(lock_screen_profile_creator()->lock_screen_profile());
  EXPECT_FALSE(lock_screen_profile_creator()->ProfileCreated());
  EXPECT_FALSE(callback_run);

  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(true));

  EXPECT_TRUE(callback_run);
  EXPECT_TRUE(lock_screen_profile_creator()->ProfileCreated());

  Profile* lock_screen_profile =
      lock_screen_profile_creator()->lock_screen_profile();
  ASSERT_TRUE(lock_screen_profile);

  EXPECT_TRUE(ProfileHelper::IsLockScreenAppProfile(lock_screen_profile));
  EXPECT_FALSE(
      lock_screen_profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled));
  EXPECT_TRUE(lock_screen_profile->GetPrefs()->GetBoolean(
      prefs::kForceEphemeralProfiles));
  EXPECT_FALSE(ProfileHelper::Get()->GetUserByProfile(lock_screen_profile));

  // `AppManagerImpl` uses the original non-OffTheRecord profile to install apps
  // to the lock screen. Regular web apps and app service should be available,
  // but not system web apps.
  EXPECT_TRUE(lock_screen_profile->IsOffTheRecord());
  EXPECT_TRUE(web_app::WebAppProvider::GetForLocalAppsUnchecked(
      lock_screen_profile->GetOriginalProfile()));
  EXPECT_TRUE(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(
      lock_screen_profile->GetOriginalProfile()));
  EXPECT_FALSE(
      ash::SystemWebAppManager::Get(lock_screen_profile->GetOriginalProfile()));

  // Profile should not be recreated if lock screen note taking gets re-enabled.
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), false);
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_TRUE(profile_manager()->pending_profile_creation()->path().empty());
}

TEST_F(LockScreenProfileCreatorImplTest, ProfileCreationError) {
  lock_screen_profile_creator()->Initialize();

  bool callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_run));

  SetExtensionSystemReady(primary_profile());

  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_FALSE(lock_screen_profile_creator()->ProfileCreated());
  EXPECT_FALSE(callback_run);

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());
  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(false));

  EXPECT_TRUE(callback_run);
  EXPECT_TRUE(lock_screen_profile_creator()->ProfileCreated());
  EXPECT_FALSE(lock_screen_profile_creator()->lock_screen_profile());

  // Profile should not be recreated if lock screen note taking gets reenabled.
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), false);
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_TRUE(profile_manager()->pending_profile_creation()->path().empty());
}

TEST_F(LockScreenProfileCreatorImplTest,
       WaitUntilPrimaryExtensionSystemReadyBeforeCreatingProfile) {
  lock_screen_profile_creator()->Initialize();

  bool callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_run));

  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_TRUE(profile_manager()->pending_profile_creation()->path().empty());
  EXPECT_FALSE(lock_screen_profile_creator()->lock_screen_profile());
  EXPECT_FALSE(callback_run);

  SetExtensionSystemReady(primary_profile());

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());

  EXPECT_FALSE(callback_run);

  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(true));

  EXPECT_TRUE(callback_run);
  Profile* lock_screen_profile =
      lock_screen_profile_creator()->lock_screen_profile();
  ASSERT_TRUE(lock_screen_profile);
  EXPECT_TRUE(ProfileHelper::IsLockScreenAppProfile(lock_screen_profile));
}

TEST_F(LockScreenProfileCreatorImplTest, InitializedAfterNoteTakingEnabled) {
  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);
  SetExtensionSystemReady(primary_profile());

  lock_screen_profile_creator()->Initialize();
  base::RunLoop().RunUntilIdle();

  bool callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_run));

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());

  EXPECT_FALSE(callback_run);
  EXPECT_FALSE(lock_screen_profile_creator()->ProfileCreated());
  EXPECT_FALSE(lock_screen_profile_creator()->lock_screen_profile());

  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(true));

  EXPECT_TRUE(callback_run);
  Profile* lock_screen_profile =
      lock_screen_profile_creator()->lock_screen_profile();
  ASSERT_TRUE(lock_screen_profile);
  EXPECT_TRUE(ProfileHelper::IsLockScreenAppProfile(lock_screen_profile));
}

TEST_F(LockScreenProfileCreatorImplTest, MultipleCallbacks) {
  lock_screen_profile_creator()->Initialize();

  bool first_callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &first_callback_run));

  bool second_callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &second_callback_run));

  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());
  SetExtensionSystemReady(primary_profile());
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_FALSE(first_callback_run);
  EXPECT_FALSE(second_callback_run);

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());

  bool callback_added_during_creation_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_added_during_creation_run));

  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(true));

  EXPECT_TRUE(lock_screen_profile_creator()->lock_screen_profile());

  EXPECT_TRUE(first_callback_run);
  EXPECT_TRUE(second_callback_run);
  EXPECT_TRUE(callback_added_during_creation_run);

  bool callback_added_after_creation_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_added_after_creation_run));
  EXPECT_TRUE(callback_added_after_creation_run);
}

TEST_F(LockScreenProfileCreatorImplTest, LockScreenProfileSetBeforeCallback) {
  lock_screen_profile_creator()->Initialize();

  Profile* lock_screen_profile = nullptr;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&LockScreenProfileCreatorImplTest::RecordLockScreenProfile,
                     base::Unretained(this), &lock_screen_profile));

  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());
  SetExtensionSystemReady(primary_profile());
  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);
  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(true));

  EXPECT_TRUE(lock_screen_profile_creator()->lock_screen_profile());
  EXPECT_EQ(lock_screen_profile_creator()->lock_screen_profile(),
            lock_screen_profile);

  lock_screen_profile = nullptr;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&LockScreenProfileCreatorImplTest::RecordLockScreenProfile,
                     base::Unretained(this), &lock_screen_profile));

  EXPECT_EQ(lock_screen_profile_creator()->lock_screen_profile(),
            lock_screen_profile);
}

TEST_F(LockScreenProfileCreatorImplTest, MetricsOnSuccess) {
  auto histogram_tester = std::make_unique<base::HistogramTester>();
  lock_screen_profile_creator()->Initialize();

  bool callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_run));

  SetExtensionSystemReady(primary_profile());
  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());

  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_FALSE(lock_screen_profile_creator()->ProfileCreated());
  EXPECT_FALSE(callback_run);

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());

  tick_clock()->Advance(base::Milliseconds(20));

  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(true));

  EXPECT_TRUE(callback_run);
}

TEST_F(LockScreenProfileCreatorImplTest, MetricsOnFailure) {
  auto histogram_tester = std::make_unique<base::HistogramTester>();
  lock_screen_profile_creator()->Initialize();

  bool callback_run = false;
  lock_screen_profile_creator()->AddCreateProfileCallback(
      base::BindOnce(&SetWasRun, &callback_run));

  SetExtensionSystemReady(primary_profile());
  scoped_refptr<const extensions::Extension> test_app =
      AddTestNoteTakingApp(primary_profile());

  SetAppEnabledOnLockScreen(primary_profile(), test_app.get(), true);

  EXPECT_FALSE(lock_screen_profile_creator()->ProfileCreated());
  EXPECT_FALSE(callback_run);

  ASSERT_EQ(ProfileHelper::GetLockScreenAppProfilePath(),
            profile_manager()->pending_profile_creation()->path());

  tick_clock()->Advance(base::Milliseconds(20));

  ASSERT_TRUE(profile_manager()
                  ->pending_profile_creation()
                  ->WaitForCreationAndOverrideResponse(false));

  EXPECT_TRUE(callback_run);
}