// Copyright 2026 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/policy/cloud/extension_install_policy_service.h"

#include "chrome/browser/extensions/extension_management.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/policy/cloud/extension_install_policy_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_constants.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 "components/policy/core/common/cloud/cloud_external_data_manager.h"
#include "components/policy/core/common/cloud/cloud_policy_client_types.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/policy/core/common/cloud/mock_user_cloud_policy_store.h"
#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
#include "components/policy/core/common/features.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/mock_policy_service.h"
#include "components/policy/core/common/policy_service_impl.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/pref_names.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_urls.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/browser_process_platform_part.h"  // nogncheck
#include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "components/user_manager/scoped_user_manager.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

using ManagementPrefUpdater = extensions::ExtensionManagementPrefUpdater<
    sync_preferences::TestingPrefServiceSyncable>;

namespace policy {
namespace {

constexpr char kExtensionId[] = "abcdefghijklmnopabcdefghijklmnop";
constexpr char kExtensionVersion[] = "1.0.0.0";

#if BUILDFLAG(IS_CHROMEOS)
constexpr char kEmail[] = "user@example.com";
constexpr GaiaId::Literal kTestGaiaId("12345");
#endif  // BUILDFLAG(IS_CHROMEOS)

base::Value GetPolicyValueForAction(
    const std::string& extension_version,
    enterprise_management::ExtensionInstallPolicy::Action action) {
  return base::Value(base::DictValue().Set(
      extension_version, base::DictValue().Set("action", action)));
}

class MockExtensionInstallPolicyServiceObserver
    : public ExtensionInstallPolicyService::Observer {
 public:
  MOCK_METHOD(void, OnExtensionInstallPolicyUpdated, (), (override));
};

}  // namespace

class ExtensionInstallPolicyServiceTest : public testing::Test {
 public:
  void SetUp() override {
    TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory(
        test_url_loader_factory_.GetSafeWeakWrapper());

    policy_provider_ =
        std::make_unique<testing::NiceMock<MockConfigurationPolicyProvider>>();
    policy_provider_->SetDefaultReturns(
        /*is_initialization_complete_return=*/true,
        /*is_first_policy_load_complete_return=*/true);
    std::vector<raw_ptr<ConfigurationPolicyProvider, VectorExperimental>>
        providers = {policy_provider_.get()};
    auto policy_service_ = std::make_unique<PolicyServiceImpl>(providers);

    // The initialization path that blocks on the initial policy fetch requires
    // a signin Profile to use its URLRequestContext.
    profile_manager_ = std::make_unique<TestingProfileManager>(
        TestingBrowserProcess::GetGlobal());
    ASSERT_TRUE(profile_manager_->SetUp());
#if BUILDFLAG(IS_CHROMEOS)
    auto fake_user_manager = std::make_unique<ash::FakeChromeUserManager>();
    const AccountId account_id = AccountId::FromUserEmail(kEmail);
    fake_user_manager->AddUser(account_id);
    fake_user_manager->LoginUser(account_id);
    scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
        std::move(fake_user_manager));

    profile_ = profile_manager_->CreateTestingProfile(
        kEmail,
        /*prefs=*/nullptr,
        /*user_name=*/u"user",
        /*avatar_id=*/0,
        /*testing_factories=*/{},
        /*is_supervised_profile=*/false,
        /*is_new_profile=*/false, std::move(policy_service_),
        /*shared_url_loader_factory=*/nullptr,
        /*user_cloud_policy_manager=*/nullptr);
    profile_->SetUserCloudPolicyManagerAsh(BuildUserCloudPolicyManagerAsh());
#else
    profile_ = profile_manager_->CreateTestingProfile(
        chrome::kInitialProfile,
        /*prefs=*/nullptr,
        /*user_name=*/u"",
        /*avatar_id=*/0,
        /*testing_factories=*/{},
        /*is_supervised_profile=*/false,
        /*is_new_profile=*/false, std::move(policy_service_),
        /*shared_url_loader_factory=*/nullptr, BuildUserCloudPolicyManager());
#endif  // BUILDFLAG(IS_CHROMEOS)

    profile_->GetPrefs()->SetBoolean(
        extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled,
        true);

    client_ = std::make_unique<MockCloudPolicyClient>();
    client_->SetDMToken("dm_token");
    client_->SetClientId("client_id");
    auto* manager = profile_->GetCloudPolicyManager();
    CHECK(manager);
    manager->Init(&schema_registry_);
    manager->core()->store()->SetFirstPoliciesLoaded(true);
#if BUILDFLAG(IS_CHROMEOS)
    manager->core()->Connect(std::move(client_));
#else
    manager->Connect(g_browser_process->local_state(), std::move(client_));
#endif
    service_ = static_cast<ExtensionInstallPolicyServiceImpl*>(
        ExtensionInstallPolicyServiceFactory::GetForBrowserContext(profile()));
  }

  void TearDown() override {
    service_->Shutdown();
    service_ = nullptr;
    profile_ = nullptr;
    profile_manager_->DeleteAllTestingProfiles();
    profile_manager_ = nullptr;
    TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory(nullptr);
#if !BUILDFLAG(IS_CHROMEOS)
    TestingBrowserProcess::GetGlobal()->local_state()->ClearPref(
        extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled);
#endif
  }

  TestingProfile* profile() { return profile_; }

#if !BUILDFLAG(IS_CHROMEOS)
  // Build a test version CloudPolicyManager for testing profiles.
  std::unique_ptr<UserCloudPolicyManager> BuildUserCloudPolicyManager() {
    auto mock_user_cloud_policy_store =
        std::make_unique<MockUserCloudPolicyStore>(
            dm_protocol::GetChromeUserPolicyType());
    std::unique_ptr<MockUserCloudPolicyStore>
        mock_user_cloud_policy_extension_install_store;
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
    mock_user_cloud_policy_extension_install_store =
        std::make_unique<MockUserCloudPolicyStore>(
            dm_protocol::kChromeExtensionInstallUserCloudPolicyType);
#endif

    return std::make_unique<UserCloudPolicyManager>(
        std::move(mock_user_cloud_policy_store),
        std::move(mock_user_cloud_policy_extension_install_store),
        base::FilePath(),
        /*cloud_external_data_manager=*/nullptr,
        task_environment_.GetMainThreadTaskRunner(),
        network::TestNetworkConnectionTracker::CreateGetter());
  }
#else
  std::unique_ptr<UserCloudPolicyManagerAsh> BuildUserCloudPolicyManagerAsh() {
    auto mock_user_cloud_policy_store = std::make_unique<MockCloudPolicyStore>(
        dm_protocol::GetChromeUserPolicyType());
    std::unique_ptr<MockCloudPolicyStore>
        mock_user_cloud_policy_extension_install_store =
            std::make_unique<MockCloudPolicyStore>(
                dm_protocol::kChromeExtensionInstallUserCloudPolicyType);

    auto cloud_external_data_manager =
        std::make_unique<MockCloudExternalDataManager>();
    cloud_external_data_manager->SetPolicyStore(
        mock_user_cloud_policy_store.get());

    return std::make_unique<UserCloudPolicyManagerAsh>(
        TestingBrowserProcess::GetGlobal()->local_state(),
        test_url_loader_factory_.GetSafeWeakWrapper(),
        TestingBrowserProcess::GetGlobal()
            ->platform_part()
            ->browser_policy_connector_ash(),
        profile_, std::move(mock_user_cloud_policy_store),
        std::move(mock_user_cloud_policy_extension_install_store),
        std::move(cloud_external_data_manager), base::FilePath(),
        UserCloudPolicyManagerAsh::PolicyEnforcement::kPolicyRequired,
        /*policy_refresh_timeout=*/base::TimeDelta(),
        /*fatal_error_callback=*/base::OnceClosure(),
        AccountId::FromUserEmailGaiaId(kEmail, kTestGaiaId),
        task_environment_.GetMainThreadTaskRunner());
  }
#endif  // !BUILDFLAG(IS_CHROMEOS)

 protected:
  content::BrowserTaskEnvironment task_environment_;
  std::unique_ptr<MockConfigurationPolicyProvider> policy_provider_;
  std::unique_ptr<MockCloudPolicyClient> client_;
  raw_ptr<TestingProfile> profile_;
  std::unique_ptr<TestingProfileManager> profile_manager_;
  raw_ptr<ExtensionInstallPolicyServiceImpl> service_;
  base::test::ScopedFeatureList scoped_feature_list_{
      features::kEnableExtensionInstallPolicyFetching};
  SchemaRegistry schema_registry_;
#if BUILDFLAG(IS_CHROMEOS)
  std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
#endif
  network::TestURLLoaderFactory test_url_loader_factory_;
};

TEST_F(ExtensionInstallPolicyServiceTest, IsExtensionAllowedUnknown) {
  TestingProfile::Builder builder;
  auto policy_service = std::make_unique<MockPolicyService>();
  EXPECT_CALL(*policy_service,
              IsInitializationComplete(POLICY_DOMAIN_EXTENSION_INSTALL))
      .WillRepeatedly(testing::Return(false));
  EXPECT_CALL(*policy_service, AddObserver(testing::_, testing::_));
  EXPECT_CALL(*policy_service, RemoveObserver(testing::_, testing::_));
  EXPECT_CALL(*policy_service,
              AddObserver(POLICY_DOMAIN_EXTENSION_INSTALL, testing::_))
      .Times(1);
  EXPECT_CALL(*policy_service,
              RemoveObserver(POLICY_DOMAIN_EXTENSION_INSTALL, testing::_))
      .Times(1);
  builder.SetPolicyService(std::move(policy_service));
  auto test_profile = builder.Build();
  test_profile->GetPrefs()->SetBoolean(
      extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled, true);

  ExtensionInstallPolicyServiceImpl service(test_profile.get());
  EXPECT_FALSE(service
                   .IsExtensionAllowed(
                       ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                   .has_value());
  service.Shutdown();
}

TEST_F(ExtensionInstallPolicyServiceTest, MustRemainDisabledWhileUnknown) {
  // Mock PolicyService to return unknown for extension install policies.
  auto policy_service = std::make_unique<MockPolicyService>();
  bool extension_install_policy_initialized = false;
  PolicyMap empty_policy_map;

  EXPECT_CALL(*policy_service, IsInitializationComplete(testing::_))
      .WillRepeatedly(testing::Return(true));
  EXPECT_CALL(*policy_service,
              IsInitializationComplete(POLICY_DOMAIN_EXTENSION_INSTALL))
      .WillRepeatedly(
          testing::ReturnPointee(&extension_install_policy_initialized));
  EXPECT_CALL(*policy_service, GetPolicies(testing::_))
      .WillRepeatedly(testing::ReturnRef(empty_policy_map));

  EXPECT_CALL(*policy_service, AddObserver(testing::_, testing::_))
      .Times(testing::AnyNumber());
  EXPECT_CALL(*policy_service, RemoveObserver(testing::_, testing::_))
      .Times(testing::AnyNumber());

  // We need a profile with this mocked policy service.
  TestingProfile::Builder builder;
  builder.SetPolicyService(std::move(policy_service));
  auto test_profile = builder.Build();
  test_profile->GetPrefs()->SetBoolean(
      extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled, true);

  ExtensionInstallPolicyServiceImpl service(test_profile.get());

  // Create an extension.
  scoped_refptr<const extensions::Extension> extension =
      extensions::ExtensionBuilder("test").SetID(kExtensionId).Build();

  // 1. If the extension was NOT disabled by policy, it should NOT remain
  // disabled.
  EXPECT_FALSE(service.MustRemainDisabled(extension.get(), nullptr));

  // 2. Set the disable reason.
  extensions::ExtensionPrefs::Get(test_profile.get())
      ->AddDisableReason(kExtensionId,
                         extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY);

  // The extension should now remain disabled because the policy value is not
  // known.
  EXPECT_TRUE(service.MustRemainDisabled(extension.get(), nullptr));

  // 3. Initialize the policies.
  extension_install_policy_initialized = true;

  // The extension should NO LONGER remain disabled because the policy value
  // is now known (and it's allowed by default).
  EXPECT_FALSE(service.MustRemainDisabled(extension.get(), nullptr));

  service.Shutdown();
}

TEST_F(ExtensionInstallPolicyServiceTest, IsExtensionAllowedByDefault) {
  EXPECT_TRUE(service_
                  ->IsExtensionAllowed(
                      ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                  .value());
}

TEST_F(ExtensionInstallPolicyServiceTest, IsExtensionAllowedByPolicy) {
  PolicyMap policy;
  policy.Set(kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
             POLICY_SOURCE_CLOUD,
             GetPolicyValueForAction(
                 kExtensionVersion,
                 enterprise_management::ExtensionInstallPolicy::ACTION_ALLOW),
             nullptr);
  policy_provider_->UpdateExtensionInstallPolicy(policy);

  EXPECT_TRUE(service_
                  ->IsExtensionAllowed(
                      ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                  .value());
}

TEST_F(ExtensionInstallPolicyServiceTest, IsExtensionBlockedByPolicy) {
  PolicyMap policy;
  policy.Set(kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
             POLICY_SOURCE_CLOUD,
             GetPolicyValueForAction(
                 kExtensionVersion,
                 enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
             nullptr);
  policy_provider_->UpdateExtensionInstallPolicy(policy);

  EXPECT_FALSE(service_
                   ->IsExtensionAllowed(
                       ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                   .value());
}

#if !BUILDFLAG(IS_CHROMEOS)
TEST_F(ExtensionInstallPolicyServiceTest, IsExtensionBlockedByMachinePolicy) {
  PolicyMap policy;
  policy.Set(kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
             POLICY_SOURCE_CLOUD,
             GetPolicyValueForAction(
                 kExtensionVersion,
                 enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
             nullptr);
  policy_provider_->UpdateExtensionInstallPolicy(policy);

  profile()->GetPrefs()->SetBoolean(
      extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled, false);
  TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean(
      extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled, true);

  EXPECT_FALSE(service_
                   ->IsExtensionAllowed(
                       ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                   .value());
}
#endif  // !BUILDFLAG(IS_CHROMEOS)

TEST_F(ExtensionInstallPolicyServiceTest,
       IsExtensionBlockedByExtensionSettings) {
  // Force-install `kExtensionId`.
  std::string webstore_update_url =
      extension_urls::GetWebstoreUpdateUrl().spec();
  {
    ManagementPrefUpdater pref(profile()->GetTestingPrefService());
    // Mark good.crx for force-installation.
    pref.SetIndividualExtensionAutoInstalled(kExtensionId, webstore_update_url,
                                             true);
  }
  auto* extension_management =
      extensions::ExtensionManagementFactory::GetForBrowserContext(profile());
  ASSERT_TRUE(extension_management);
  ASSERT_EQ(extensions::ManagedInstallationMode::kForced,
            extension_management->GetInstallationMode(kExtensionId,
                                                      webstore_update_url));

  // IsExtensionAllowed() returns true even though the extension is blocked by
  // the ExtensionSettings policy. "true" here means "EIPS will not block it",
  // but other things still can (in this case,
  // StandardManagementPolicyProvider).
  EXPECT_TRUE(service_
                  ->IsExtensionAllowed(
                      ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                  .value());
}

TEST_F(ExtensionInstallPolicyServiceTest, ExtensionAllowlisted) {
  {
    ManagementPrefUpdater pref(profile()->GetTestingPrefService());
    pref.SetIndividualExtensionInstallationAllowed(kExtensionId, true);
  }

  PolicyMap extension_install_policy;
  extension_install_policy.Set(
      kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
      POLICY_SOURCE_CLOUD,
      GetPolicyValueForAction(
          kExtensionVersion,
          enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
      nullptr);

  policy_provider_->UpdateExtensionInstallPolicy(extension_install_policy);

  // IsExtensionAllowed() returns true even though the extension is blocked by
  // the ExtensionInstallPolicy. "true" here means "EIPS will not block it",
  // but other things still can (in this case, ExtensionSettings policy).
  EXPECT_TRUE(service_
                  ->IsExtensionAllowed(
                      ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                  .value());
}

TEST_F(ExtensionInstallPolicyServiceTest, ExtensionForceInstalled) {
  std::string webstore_update_url =
      extension_urls::GetWebstoreUpdateUrl().spec();
  {
    ManagementPrefUpdater pref(profile()->GetTestingPrefService());
    pref.SetIndividualExtensionAutoInstalled(kExtensionId, webstore_update_url,
                                             true);
  }

  PolicyMap extension_install_policy;
  extension_install_policy.Set(
      kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
      POLICY_SOURCE_CLOUD,
      GetPolicyValueForAction(
          kExtensionVersion,
          enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
      nullptr);

  policy_provider_->UpdateExtensionInstallPolicy(extension_install_policy);

  // IsExtensionAllowed() returns true even though the extension is blocked by
  // the ExtensionInstallPolicy. "true" here means "EIPS will not block it",
  // but other things still can (in this case, ExtensionSettings policy).
  EXPECT_TRUE(service_
                  ->IsExtensionAllowed(
                      ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                  .value());
}

TEST_F(ExtensionInstallPolicyServiceTest, ExtensionBlocklisted) {
  {
    ManagementPrefUpdater pref(profile()->GetTestingPrefService());
    pref.SetIndividualExtensionInstallationAllowed(kExtensionId, false);
  }

  PolicyMap extension_install_policy;
  extension_install_policy.Set(
      kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
      POLICY_SOURCE_CLOUD,
      GetPolicyValueForAction(
          kExtensionVersion,
          enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
      nullptr);

  policy_provider_->UpdateExtensionInstallPolicy(extension_install_policy);

  // IsExtensionAllowed() returns true even though the extension is blocked by
  // the ExtensionSettings policy. "true" here means "EIPS will not block it",
  // but other things still can (in this case,
  // StandardManagementPolicyProvider).
  EXPECT_TRUE(service_
                  ->IsExtensionAllowed(
                      ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                  .value());
}

TEST_F(ExtensionInstallPolicyServiceTest,
       IsExtensionBlockedByConflictingPolicy) {
  PolicyMap policy;
  PolicyMap::Entry entry(
      POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
      GetPolicyValueForAction(
          kExtensionVersion,
          enterprise_management::ExtensionInstallPolicy::ACTION_ALLOW),
      nullptr);

  PolicyMap::Entry conflicting_policy(
      POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
      GetPolicyValueForAction(
          kExtensionVersion,
          enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
      nullptr);
  entry.AddConflictingPolicy(std::move(conflicting_policy));

  policy.Set(kExtensionId, std::move(entry));

  policy_provider_->UpdateExtensionInstallPolicy(policy);

  EXPECT_FALSE(service_
                   ->IsExtensionAllowed(
                       ExtensionIdAndVersion(kExtensionId, kExtensionVersion))
                   .value());
}

TEST_F(ExtensionInstallPolicyServiceTest, PolicyUpdateNotifiesObservers) {
  MockExtensionInstallPolicyServiceObserver observer;
  service_->AddObserver(&observer);

  EXPECT_CALL(observer, OnExtensionInstallPolicyUpdated()).Times(1);
  PolicyMap policy;
  policy.Set(kExtensionId, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
             POLICY_SOURCE_CLOUD,
             GetPolicyValueForAction(
                 kExtensionVersion,
                 enterprise_management::ExtensionInstallPolicy::ACTION_BLOCK),
             nullptr);
  policy_provider_->UpdateExtensionInstallPolicy(policy);
  service_->RemoveObserver(&observer);
}

TEST_F(ExtensionInstallPolicyServiceTest, TypesToFetch) {
  auto* manager = profile()->GetCloudPolicyManager();
  ASSERT_TRUE(manager);

  ASSERT_TRUE(manager->extension_install_core()->client());

  // This EIPS should now be in types_to_fetch().
  EXPECT_THAT(manager->extension_install_core()->client()->types_to_fetch(),
              testing::UnorderedElementsAre(PolicyTypeToFetch(
                  dm_protocol::kChromeExtensionInstallUserCloudPolicyType,
                  service_.get())));

#if !BUILDFLAG(IS_CHROMEOS)
  auto* extension_install_store_mock = static_cast<MockUserCloudPolicyStore*>(
      static_cast<UserCloudPolicyManager*>(manager)->extension_install_store());
  EXPECT_CALL(*extension_install_store_mock, Clear()).Times(1);
#endif

  // Disable the feature, it should get removed from types_to_fetch().
  profile()->GetPrefs()->SetBoolean(
      extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled, false);
  EXPECT_TRUE(
      manager->extension_install_core()->client()->types_to_fetch().empty());

  // Re-enable the feature, it should get re-added to types_to_fetch().
  profile()->GetPrefs()->SetBoolean(
      extensions::pref_names::kExtensionInstallCloudPolicyChecksEnabled, true);
  EXPECT_THAT(manager->extension_install_core()->client()->types_to_fetch(),
              testing::UnorderedElementsAre(PolicyTypeToFetch(
                  dm_protocol::kChromeExtensionInstallUserCloudPolicyType,
                  service_.get())));

  service_->Shutdown();
  EXPECT_TRUE(
      manager->extension_install_core()->client()->types_to_fetch().empty());
#if !BUILDFLAG(IS_CHROMEOS)
  testing::Mock::VerifyAndClearExpectations(extension_install_store_mock);
#endif
}

}  // namespace policy
