// Copyright 2014 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/extensions/extension_service_test_base.h"
#include "base/memory/raw_ptr.h"

#include <utility>

#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_garbage_collector_factory.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/load_error_reporter.h"
#include "chrome/browser/extensions/shared_module_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/signin/test_signin_client_builder.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/trusted_vault/trusted_vault_service_factory.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/crx_file/crx_verifier.h"
#include "components/policy/core/common/policy_service_impl.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/supervised_user/core/common/buildflags.h"
#include "components/sync_preferences/pref_service_mock_factory.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/extensions_client.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/extensions/install_limiter.h"
#endif

namespace extensions {

namespace {

// Create a testing profile according to |params|.
std::unique_ptr<TestingProfile> BuildTestingProfile(
    const ExtensionServiceTestBase::ExtensionServiceInitParams& params,
    base::ScopedTempDir& temp_dir,
    policy::PolicyService* policy_service) {
  TestingProfile::Builder profile_builder;

  if (!temp_dir.CreateUniqueTempDir()) {
    return nullptr;
  }

  base::FilePath profile_dir =
      temp_dir.GetPath().Append(FILE_PATH_LITERAL("TestingExtensionsPath"));
  if (base::File::Error error = base::File::FILE_OK;
      !base::CreateDirectoryAndGetError(profile_dir, &error)) {
    LOG(ERROR) << "Failed to create profile directory: " << error;
    return nullptr;
  }

  // If pref_file is empty, TestingProfile automatically creates
  // sync_preferences::TestingPrefServiceSyncable instance.
  if (params.prefs_content.has_value()) {
    base::FilePath prefs_path =
        profile_dir.Append(chrome::kPreferencesFilename);
    if (!base::WriteFile(prefs_path, params.prefs_content.value())) {
      LOG(ERROR) << "Failed to write a prefs file";
      return nullptr;
    }

    // Create a PrefService that only contains user defined preference values
    // and policies.
    sync_preferences::PrefServiceMockFactory factory;
    factory.SetUserPrefsFile(
        prefs_path, base::SingleThreadTaskRunner::GetCurrentDefault().get());
    factory.SetManagedPolicies(policy_service,
                               g_browser_process->browser_policy_connector());
    scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
        new user_prefs::PrefRegistrySyncable);
    std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs(
        factory.CreateSyncable(registry.get()));
    RegisterUserProfilePrefs(registry.get());
    profile_builder.SetPrefService(std::move(prefs));
  }

  base::FilePath extensions_install_dir =
      profile_dir.AppendASCII(kInstallDirectoryName);
  if (!base::DeletePathRecursively(extensions_install_dir)) {
    LOG(ERROR) << "Failed to clean extensions directory";
    return nullptr;
  }
  if (params.extensions_dir.empty()) {
    if (base::File::Error error = base::File::FILE_OK;
        !base::CreateDirectoryAndGetError(extensions_install_dir, &error)) {
      LOG(ERROR) << "Failed to create extensions directory: " << error;
      return nullptr;
    }
  } else {
    if (!base::CopyDirectory(params.extensions_dir, extensions_install_dir,
                             true)) {
      LOG(ERROR) << "Failed to copy extensions directory";
      return nullptr;
    }
  }

  // Only perform cleanup and copying of unpacked extensions if the path exists
  // for the test since this is less common than for packed extensions.
  if (base::PathExists(params.unpacked_extensions_dir)) {
    base::FilePath unpacked_extensions_install_dir =
        profile_dir.AppendASCII(kUnpackedInstallDirectoryName);
    if (!base::DeletePathRecursively(unpacked_extensions_install_dir)) {
      LOG(ERROR) << "Failed to clean unpacked extensions directory";
      return nullptr;
    }
    if (params.unpacked_extensions_dir.empty()) {
      if (base::File::Error error = base::File::FILE_OK;
          !base::CreateDirectoryAndGetError(unpacked_extensions_install_dir,
                                            &error)) {
        LOG(ERROR) << "Failed to create unpacked extensions directory: "
                   << error;
        return nullptr;
      }
    } else {
      if (!base::CopyDirectory(params.unpacked_extensions_dir,
                               unpacked_extensions_install_dir, true)) {
        LOG(ERROR) << "Failed to copy unpacked extensions directory";
        return nullptr;
      }
    }
  }

  if (params.profile_is_supervised) {
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
    profile_builder.SetIsSupervisedProfile();
#endif
  }

  if (params.profile_is_guest) {
    profile_builder.SetGuestSession();
  }

  if (params.enable_bookmark_model) {
    profile_builder.AddTestingFactory(
        BookmarkModelFactory::GetInstance(),
        BookmarkModelFactory::GetDefaultFactory());
    profile_builder.AddTestingFactory(
        ManagedBookmarkServiceFactory::GetInstance(),
        ManagedBookmarkServiceFactory::GetDefaultFactory());
  }

  profile_builder.AddTestingFactory(
      ChromeSigninClientFactory::GetInstance(),
      base::BindRepeating(&signin::BuildTestSigninClient));
  profile_builder.AddTestingFactories(
      IdentityTestEnvironmentProfileAdaptor::
          GetIdentityTestEnvironmentFactories());
  // TODO(crbug.com/1222596): SyncService (and thus TrustedVaultService)
  // instantiation can be scoped down to a few derived fixtures.
  profile_builder.AddTestingFactory(
      TrustedVaultServiceFactory::GetInstance(),
      TrustedVaultServiceFactory::GetDefaultFactory());
  profile_builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
                                    SyncServiceFactory::GetDefaultFactory());
  profile_builder.AddTestingFactory(
      ExtensionGarbageCollectorFactory::GetInstance(),
      base::BindRepeating(&ExtensionGarbageCollectorFactory::BuildInstanceFor));
  profile_builder.SetPath(profile_dir);
  return profile_builder.Build();
}

}  // namespace

ExtensionServiceTestBase::ExtensionServiceInitParams::
    ExtensionServiceInitParams() = default;

ExtensionServiceTestBase::ExtensionServiceInitParams::
    ExtensionServiceInitParams(const ExtensionServiceInitParams& other) =
        default;

ExtensionServiceTestBase::ExtensionServiceInitParams::
    ~ExtensionServiceInitParams() = default;

bool ExtensionServiceTestBase::ExtensionServiceInitParams::
    SetPrefsContentFromFile(const base::FilePath& filepath) {
  std::string content;
  if (!base::ReadFileToString(filepath, &content)) {
    return false;
  }
  prefs_content.emplace(std::move(content));
  return true;
}

bool ExtensionServiceTestBase::ExtensionServiceInitParams::
    ConfigureByTestDataDirectory(const base::FilePath& filepath) {
  if (!SetPrefsContentFromFile(filepath.Append(chrome::kPreferencesFilename))) {
    return false;
  }
  extensions_dir = filepath.AppendASCII(kInstallDirectoryName);
  unpacked_extensions_dir = filepath.AppendASCII(kUnpackedInstallDirectoryName);
  return true;
}

ExtensionServiceTestBase::ExtensionServiceTestBase()
    : ExtensionServiceTestBase(
          std::make_unique<content::BrowserTaskEnvironment>(
              base::test::TaskEnvironment::MainThreadType::IO)) {}

ExtensionServiceTestBase::ExtensionServiceTestBase(
    std::unique_ptr<content::BrowserTaskEnvironment> task_environment)
    : task_environment_(std::move(task_environment)),
      service_(nullptr),
      testing_local_state_(TestingBrowserProcess::GetGlobal()),
      registry_(nullptr),
      verifier_format_override_(crx_file::VerifierFormat::CRX3) {
  base::FilePath test_data_dir;
  if (!base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
    ADD_FAILURE();
    return;
  }
  data_dir_ = test_data_dir.AppendASCII("extensions");

  policy_service_ = std::make_unique<policy::PolicyServiceImpl>(
      std::vector<
          raw_ptr<policy::ConfigurationPolicyProvider, VectorExperimental>>{
          &policy_provider_});
}

ExtensionServiceTestBase::~ExtensionServiceTestBase() {
  // Why? Because |profile_| has to be destroyed before |at_exit_manager_|, but
  // is declared above it in the class definition since it's protected.
  // TODO(1269752): Since we're getting rid of at_exit_manager_, perhaps
  // we don't need this call?
  profile_.reset();
}

void ExtensionServiceTestBase::InitializeExtensionService(
    const ExtensionServiceTestBase::ExtensionServiceInitParams& params) {
  profile_ = BuildTestingProfile(params, temp_dir_, policy_service_.get());
  extensions_install_dir_ =
      profile_->GetPath().AppendASCII(kInstallDirectoryName);
  unpacked_install_dir_ =
      profile_->GetPath().AppendASCII(kUnpackedInstallDirectoryName);

  CreateExtensionService(params);
  registry_ = ExtensionRegistry::Get(profile());
}

void ExtensionServiceTestBase::InitializeEmptyExtensionService() {
  ExtensionServiceInitParams params;
  params.prefs_content = "";
  InitializeExtensionService(params);
}

void ExtensionServiceTestBase::InitializeGoodInstalledExtensionService() {
  ExtensionServiceInitParams params;
  ASSERT_TRUE(
      params.ConfigureByTestDataDirectory(data_dir().AppendASCII("good")));
  InitializeExtensionService(params);
}

void ExtensionServiceTestBase::InitializeExtensionServiceWithUpdater() {
  ExtensionServiceInitParams params;
  params.autoupdate_enabled = true;
  InitializeExtensionService(params);
  service_->updater()->Start();
}

void ExtensionServiceTestBase::
    InitializeExtensionServiceWithExtensionsDisabled() {
  ExtensionServiceInitParams params;
  params.extensions_enabled = false;
  InitializeExtensionService(params);
}

size_t ExtensionServiceTestBase::GetPrefKeyCount() {
  const base::Value::Dict& dict =
      profile()->GetPrefs()->GetDict(pref_names::kExtensions);
  return dict.size();
}

void ExtensionServiceTestBase::ValidatePrefKeyCount(size_t count) {
  EXPECT_EQ(count, GetPrefKeyCount());
}

testing::AssertionResult ExtensionServiceTestBase::ValidateBooleanPref(
    const std::string& extension_id,
    const std::string& pref_path,
    bool expected_val) {
  std::string msg =
      base::StringPrintf("while checking: %s %s == %s", extension_id.c_str(),
                         pref_path.c_str(), expected_val ? "true" : "false");

  PrefService* prefs = profile()->GetPrefs();
  const base::Value::Dict& dict = prefs->GetDict(pref_names::kExtensions);

  const base::Value::Dict* pref = dict.FindDict(extension_id);
  if (!pref) {
    return testing::AssertionFailure()
           << "extension pref does not exist " << msg;
  }

  std::optional<bool> val = pref->FindBoolByDottedPath(pref_path);
  if (!val.has_value()) {
    return testing::AssertionFailure()
           << pref_path << " pref not found " << msg;
  }

  return expected_val == val.value() ? testing::AssertionSuccess()
                                     : testing::AssertionFailure()
                                           << "base::Value is incorrect "
                                           << msg;
}

void ExtensionServiceTestBase::ValidateIntegerPref(
    const std::string& extension_id,
    const std::string& pref_path,
    int expected_val) {
  std::string msg = base::StringPrintf(
      "while checking: %s %s == %s", extension_id.c_str(), pref_path.c_str(),
      base::NumberToString(expected_val).c_str());

  PrefService* prefs = profile()->GetPrefs();
  const base::Value::Dict& dict = prefs->GetDict(pref_names::kExtensions);
  const base::Value::Dict* pref = dict.FindDict(extension_id);
  ASSERT_TRUE(pref) << msg;
  EXPECT_EQ(expected_val, pref->FindIntByDottedPath(pref_path)) << msg;
}

void ExtensionServiceTestBase::ValidateStringPref(
    const std::string& extension_id,
    const std::string& pref_path,
    const std::string& expected_val) {
  std::string msg = base::StringPrintf("while checking: %s.manifest.%s == %s",
                                       extension_id.c_str(), pref_path.c_str(),
                                       expected_val.c_str());

  const base::Value::Dict& dict =
      profile()->GetPrefs()->GetDict(pref_names::kExtensions);
  std::string manifest_path = extension_id + ".manifest";
  const base::Value::Dict* pref = dict.FindDictByDottedPath(manifest_path);
  ASSERT_TRUE(pref) << msg;
  const std::string* val = pref->FindStringByDottedPath(pref_path);
  ASSERT_TRUE(val) << msg;
  EXPECT_EQ(expected_val, *val) << msg;
}

void ExtensionServiceTestBase::SetUp() {
  LoadErrorReporter::GetInstance()->ClearErrors();

  // Force TabManager/TabLifecycleUnitSource creation.
  g_browser_process->resource_coordinator_parts();

  // Update the webstore update url. Some tests leave it set to a non-default
  // webstore_update_url_. This can make extension_urls::IsWebstoreUpdateUrl
  // return a false negative.
  ExtensionsClient::Get()->InitializeWebStoreUrls(
      base::CommandLine::ForCurrentProcess());

#if BUILDFLAG(IS_CHROMEOS_ASH)
  // TODO(b/308107135) own KioskController instead of KioskAppManager.
  // A test might have initialized a `KioskAppManager` already.
  if (!ash::KioskChromeAppManager::IsInitialized()) {
    kiosk_chrome_app_manager_ = std::make_unique<ash::KioskChromeAppManager>();
  }
#endif
}

void ExtensionServiceTestBase::TearDown() {
  if (profile_) {
    content::StoragePartitionConfig default_storage_partition_config =
        content::StoragePartitionConfig::CreateDefault(profile());
    auto* partition = profile_->GetStoragePartition(
        default_storage_partition_config, /*can_create=*/false);
    if (partition) {
      partition->WaitForDeletionTasksForTesting();
    }
  }
  policy_provider_.Shutdown();
#if BUILDFLAG(IS_CHROMEOS_ASH)
  kiosk_chrome_app_manager_.reset();
#endif
}

void ExtensionServiceTestBase::SetUpTestSuite() {
  // Safe to call multiple times.
  LoadErrorReporter::Init(false);  // no noisy errors.
}

// These are declared in the .cc so that all inheritors don't need to know
// that TestingProfile derives Profile derives BrowserContext.
content::BrowserContext* ExtensionServiceTestBase::browser_context() {
  return profile();
}

Profile* ExtensionServiceTestBase::profile() {
// TODO(crbug.com/1414225): Refactor this convenience upstream to test callers.
// Possibly just BuiltInAppTest.BuildGuestMode.
#if BUILDFLAG(IS_CHROMEOS_ASH)
  if (profile_->IsGuestSession()) {
    return profile_->GetPrimaryOTRProfile(/*create_if_needed=*/true);
  }
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

  return profile_.get();
}

sync_preferences::TestingPrefServiceSyncable*
ExtensionServiceTestBase::testing_pref_service() {
  return profile_->GetTestingPrefService();
}

void ExtensionServiceTestBase::CreateExtensionService(
    const ExtensionServiceInitParams& params) {
  TestExtensionSystem* system =
      static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()));
  if (!params.is_first_run) {
    ExtensionPrefs::Get(profile())->SetAlertSystemFirstRun();
  }

  service_ = system->CreateExtensionService(
      base::CommandLine::ForCurrentProcess(), extensions_install_dir_,
      unpacked_install_dir_, params.autoupdate_enabled,
      params.extensions_enabled);

  service_->component_loader()->set_ignore_allowlist_for_testing(true);

  // When we start up, we want to make sure there is no external provider,
  // since the ExtensionService on Windows will use the Registry as a default
  // provider and if there is something already registered there then it will
  // interfere with the tests. Those tests that need an external provider
  // will register one specifically.
  service_->ClearProvidersForTesting();

  service_->RegisterInstallGate(ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
                                service_->shared_module_service());

#if BUILDFLAG(IS_CHROMEOS_ASH)
  if (!params.enable_install_limiter) {
    InstallLimiter::Get(profile())->DisableForTest();
  }
#endif
}

}  // namespace extensions
