// 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_management.h"

#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/json/json_reader.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "chrome/browser/enterprise/browser_management/management_service_factory.h"
#include "chrome/browser/extensions/cws_info_service.h"
#include "chrome/browser/extensions/extension_management_internal.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
#include "chrome/browser/extensions/external_policy_loader.h"
#include "chrome/browser/extensions/managed_installation_mode.h"
#include "chrome/browser/extensions/standard_management_policy_provider.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/core/common/management/scoped_management_service_override_for_testing.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/blocklist_extension_prefs.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/pref_names.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/api_permission_set.h"
#include "extensions/common/url_pattern.h"
#include "extensions/common/url_pattern_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));

using extensions::mojom::APIPermissionID;
using extensions::mojom::ManifestLocation;

namespace extensions {

namespace {

const char kTargetExtension[] = "abcdefghijklmnopabcdefghijklmnop";
const char kTargetExtension2[] = "bcdefghijklmnopabcdefghijklmnopa";
const char kTargetExtension3[] = "cdefghijklmnopabcdefghijklmnopab";
const char kTargetExtension4[] = "defghijklmnopabcdefghijklmnopabc";
const char kTargetExtension5[] = "efghijklmnopabcdefghijklmnopabcd";
const char kTargetExtension6[] = "fghijklmnopabcdefghijklmnopabcde";
const char kTargetExtension7[] = "ghijklmnopabcdefghijklmnopabcdef";
const char kTargetExtension8[] = "hijklmnopabcdefghijklmnopabcdefg";
const char kTargetExtension9[] = "ijklmnopabcdefghijklmnopabcdefgh";
const char kExampleUpdateUrl[] = "http://example.com/update_url";

const char kNonExistingExtension[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const char kNonExistingUpdateUrl[] = "http://example.net/update.xml";

const char kExampleForceInstalledDictPreference[] = R"({
  "abcdefghijklmnopabcdefghijklmnop" : {
    "installation_mode" : "force_installed",
    "update_url" : "http://example.com/update_url",
    "override_update_url": true,
  },
  "bcdefghijklmnopabcdefghijklmnopa" : {
    "installation_mode" : "force_installed",
    "update_url" : "http://example.com/update_url"
  }
})";

const char kExampleDictPreferenceWithoutInstallationMode[] = R"({
  "abcdefghijklmnopabcdefghijklmnop" : {
    "override_update_url": true,
  },
  "bcdefghijklmnopabcdefghijklmnopa" : {
    "minimum_version_required": "1.1.0"
  }
})";

const char kExampleDictPreferenceWithMultipleEntries[] = R"({
  "abcdefghijklmnopabcdefghijklmnop,bcdefghijklmnopabcdefghijklmnopa" : {
    "installation_mode": "blocked",
  },
  "bcdefghijklmnopabcdefghijklmnopa,cdefghijklmnopabcdefghijklmnopab" : {
    "minimum_version_required": "2.0"
  }
})";

const char kExampleDictPreference[] =
    R"(
{
  "abcdefghijklmnopabcdefghijklmnop": {
    "installation_mode": "allowed",
    "blocked_permissions": ["fileSystem", "bookmarks", "downloads"],
    "minimum_version_required": "1.1.0",
    "runtime_allowed_hosts": ["<all_urls>"],
  },
  "bcdefghijklmnopabcdefghijklmnopa": {
    "installation_mode": "force_installed",
    "update_url": "http://example.com/update_url",
    "blocked_permissions": ["downloads"],
  },
  "cdefghijklmnopabcdefghijklmnopab": {
    "installation_mode": "normal_installed",
    "update_url": "http://example.com/update_url",
    "blocked_permissions": ["fileSystem", "history"],
  },
  "defghijklmnopabcdefghijklmnopabc": {
    "installation_mode": "blocked",
    "runtime_blocked_hosts": ["*://*.foo.com", "https://bar.org/test"],
    "blocked_install_message": "Custom Error Extension4",
  },
  "efghijklmnopabcdefghijklmnopabcd,fghijklmnopabcdefghijklmnopabcde": {
    "installation_mode": "allowed",
  },
  "ghijklmnopabcdefghijklmnopabcdef,hijklmnopabcdefghijklmnopabcdefg,": {
    "installation_mode": "allowed",
  },
  "ijklmnopabcdefghijklmnopabcdefgh": {
    "installation_mode": "removed",
  },
  "update_url:http://example.com/update_url": {
    "installation_mode": "allowed",
    "blocked_permissions": ["fileSystem", "bookmarks"],
  },
  "*": {
    "installation_mode": "blocked",
    "install_sources": ["*://foo.com/*"],
    "allowed_types": ["theme", "user_script"],
    "blocked_permissions": ["fileSystem", "downloads"],
    "runtime_blocked_hosts": ["*://*.example.com"],
    "blocked_install_message": "Custom Error Default",
  },
})";

const char kExampleDictNoCustomError[] =
    "{"
    "  \"*\": {"
    "    \"installation_mode\": \"blocked\","
    "  },"
    "}";

}  // namespace

class ExtensionManagementServiceTest : public testing::Test {
 public:
  typedef ExtensionManagementPrefUpdater<
      sync_preferences::TestingPrefServiceSyncable>
      PrefUpdater;

  ExtensionManagementServiceTest() = default;
  ~ExtensionManagementServiceTest() override = default;

  // testing::Test:
  void SetUp() override { InitPrefService(); }

  void InitPrefService() {
    extension_management_.reset();
    profile_ = std::make_unique<TestingProfile>();
    pref_service_ = profile_->GetTestingPrefService();
    extension_management_ =
        std::make_unique<ExtensionManagement>(profile_.get());
  }

  void SetPref(bool managed,
               const char* path,
               std::unique_ptr<base::Value> value) {
    if (managed) {
      pref_service_->SetManagedPref(path, std::move(value));
    } else {
      pref_service_->SetUserPref(path, std::move(value));
    }
  }

  void SetPref(bool managed, const char* path, base::Value value) {
    SetPref(managed, path, base::Value::ToUniquePtrValue(std::move(value)));
  }

  void SetPref(bool managed, const char* path, base::Value::Dict dict) {
    SetPref(managed, path, base::Value(std::move(dict)));
  }

  void RemovePref(bool managed, const char* path) {
    if (managed) {
      pref_service_->RemoveManagedPref(path);
    } else {
      pref_service_->RemoveUserPref(path);
    }
  }

  const internal::GlobalSettings* ReadGlobalSettings() {
    return extension_management_->global_settings_.get();
  }

  ManagedInstallationMode GetInstallationModeById(const std::string& id) {
    return GetInstallationMode(id, kNonExistingUpdateUrl);
  }

  ManagedInstallationMode GetInstallationModeByUpdateUrl(
      const std::string& update_url) {
    return GetInstallationMode(kNonExistingExtension, update_url);
  }

  void CheckAutomaticallyInstalledUpdateUrl(const std::string& id,
                                            const std::string& update_url) {
    auto iter = extension_management_->settings_by_id_.find(id);
    ASSERT_TRUE(iter != extension_management_->settings_by_id_.end());
    ASSERT_TRUE(
        (iter->second->installation_mode == ManagedInstallationMode::kForced) ||
        (iter->second->installation_mode ==
         ManagedInstallationMode::kRecommended));
    EXPECT_EQ(iter->second->update_url, update_url);
  }

  APIPermissionSet GetBlockedAPIPermissionsById(const std::string& id) {
    return GetBlockedAPIPermissions(id, kNonExistingUpdateUrl);
  }

  APIPermissionSet GetBlockedAPIPermissionsByUpdateUrl(
      const std::string& update_url) {
    return GetBlockedAPIPermissions(kNonExistingExtension, update_url);
  }

  void SetExampleDictPref(std::string_view example_dict_preference) {
    auto result = base::JSONReader::ReadAndReturnValueWithError(
        example_dict_preference,
        base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS);
    ASSERT_TRUE(result.has_value()) << result.error().message;
    ASSERT_TRUE(result->is_dict());
    SetPref(true, pref_names::kExtensionManagement, std::move(*result));
  }

  // Wrapper of ExtensionManagement::GetInstallationMode, |id| and
  // |update_url| are used to construct an Extension for testing.
  ManagedInstallationMode GetInstallationMode(const std::string& id,
                                              const std::string& update_url) {
    scoped_refptr<const Extension> extension =
        CreateExtension(ManifestLocation::kUnpacked, "0.1", id, update_url);
    return extension_management_->GetInstallationMode(extension.get());
  }

  // Wrapper of ExtensionManagement::GetPolicyBlockedHosts, |id| is used
  // to construct an Extension for testing.
  URLPatternSet GetPolicyBlockedHosts(const std::string& id) {
    scoped_refptr<const Extension> extension = CreateExtension(
        ManifestLocation::kUnpacked, "0.1", id, kNonExistingUpdateUrl);
    return extension_management_->GetPolicyBlockedHosts(extension.get())
        .Clone();
  }

  // Wrapper of ExtensionManagement::GetPolicyAllowedHosts, |id| is used
  // to construct an Extension for testing.
  URLPatternSet GetPolicyAllowedHosts(const std::string& id) {
    scoped_refptr<const Extension> extension = CreateExtension(
        ManifestLocation::kUnpacked, "0.1", id, kNonExistingUpdateUrl);
    return extension_management_->GetPolicyAllowedHosts(extension.get())
        .Clone();
  }

  // Wrapper of ExtensionManagement::BlockedInstallMessage, |id| is used
  // in case the message is extension specific.
  const std::string GetBlockedInstallMessage(const std::string& id) {
    return extension_management_->BlockedInstallMessage(id);
  }

  // Wrapper of ExtensionManagement::GetBlockedAPIPermissions, |id| and
  // |update_url| are used to construct an Extension for testing.
  APIPermissionSet GetBlockedAPIPermissions(const std::string& id,
                                            const std::string& update_url) {
    scoped_refptr<const Extension> extension =
        CreateExtension(ManifestLocation::kUnpacked, "0.1", id, update_url);
    return extension_management_->GetBlockedAPIPermissions(extension.get());
  }

  // Wrapper of ExtensionManagement::CheckMinimumVersion, |id| and
  // |version| are used to construct an Extension for testing.
  bool CheckMinimumVersion(const std::string& id, const std::string& version) {
    scoped_refptr<const Extension> extension = CreateExtension(
        ManifestLocation::kUnpacked, version, id, kNonExistingUpdateUrl);
    std::string minimum_version_required;
    bool ret = extension_management_->CheckMinimumVersion(
        extension.get(), &minimum_version_required);
    EXPECT_EQ(ret, minimum_version_required.empty());
    EXPECT_EQ(ret, extension_management_->CheckMinimumVersion(extension.get(),
                                                              nullptr));
    return ret;
  }

 protected:
  scoped_refptr<const Extension> CreateExtensionHelper(
      ManifestLocation location,
      const std::string& version,
      const std::string& id,
      const std::string& update_url,
      int flags) {
    base::Value::Dict manifest_dict;
    manifest_dict.Set(manifest_keys::kName, "test");
    manifest_dict.Set(manifest_keys::kVersion, version);
    manifest_dict.Set(manifest_keys::kManifestVersion, 2);
    manifest_dict.Set(manifest_keys::kUpdateURL, update_url);
    std::u16string error;
    scoped_refptr<const Extension> extension =
        Extension::Create(base::FilePath(), location, std::move(manifest_dict),
                          flags, id, &error);
    CHECK(extension.get()) << error;
    return extension;
  }

  // Create an extension with specified |location|, |version|, |id| and
  // |update_url|. The extension created is NOT marked as originating from CWS.
  scoped_refptr<const Extension> CreateExtension(
      ManifestLocation location,
      const std::string& version,
      const std::string& id,
      const std::string& update_url) {
    return CreateExtensionHelper(location, version, id, update_url,
                                 Extension::NO_FLAGS);
  }

  scoped_refptr<const Extension> CreateOffstoreExtension(
      const std::string& id) {
    return CreateExtensionHelper(ManifestLocation::kUnpacked, "0.1", id,
                                 kNonExistingUpdateUrl, Extension::NO_FLAGS);
  }
  scoped_refptr<const Extension> CreateNormalExtension(const std::string& id) {
    return CreateExtensionHelper(ManifestLocation::kInternal, "0.1", id,
                                 extension_urls::kChromeWebstoreUpdateURL,
                                 Extension::FROM_WEBSTORE);
  }

  scoped_refptr<const Extension> CreateForcedExtension(const std::string& id) {
    return CreateForcedExtension(id, Extension::FROM_WEBSTORE);
  }

  scoped_refptr<const Extension> CreateForcedExtension(const std::string& id,
                                                       int flags) {
    scoped_refptr<const Extension> extension = CreateExtensionHelper(
        ManifestLocation::kExternalPolicy, "0.1", id, kExampleUpdateUrl, flags);
    base::Value::Dict forced_list_pref;
    ExternalPolicyLoader::AddExtension(forced_list_pref, id, kExampleUpdateUrl);
    SetPref(true, pref_names::kInstallForceList, forced_list_pref.Clone());
    return extension;
  }

  void SetExtensionLastUpdateTime(const std::string& id,
                                  base::Time update_time) {
    auto* extension_prefs = ExtensionPrefs::Get(profile_.get());
    extension_prefs->SetTimePref(
        id,
        {"last_update_time", PrefType::kTime, PrefScope::kExtensionSpecific},
        update_time);
  }

  bool IsUpdateUrlOverridden(const ExtensionId& extension_id) {
    return extension_management_->IsUpdateUrlOverridden(extension_id);
  }

  void SetCWSInfoService(CWSInfoServiceInterface* cws_info_service) {
    extension_management_->cws_info_service_ = cws_info_service;
  }

  bool IsFileUrlNavigationAllowed(const ExtensionId& extension_id) {
    return extension_management_->IsFileUrlNavigationAllowed(extension_id);
  }

  extensions::ManagedToolbarPinMode GetToolbarPinMode(const ExtensionId& id) {
    return extension_management_->GetToolbarPinMode(id);
  }

  content::BrowserTaskEnvironment task_environment_;
  std::unique_ptr<TestingProfile> profile_;
  raw_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_;
  std::unique_ptr<ExtensionManagement> extension_management_;
};

class MockCWSInfoService : public CWSInfoServiceInterface {
 public:
  MOCK_METHOD(std::optional<bool>,
              IsLiveInCWS,
              (const Extension&),
              (const, override));
  MOCK_METHOD(std::optional<CWSInfoServiceInterface::CWSInfo>,
              GetCWSInfo,
              (const Extension&),
              (const, override));
  MOCK_METHOD(void, CheckAndMaybeFetchInfo, (), (override));
  MOCK_METHOD(void,
              AddObserver,
              (CWSInfoServiceInterface::Observer*),
              (override));
  MOCK_METHOD(void,
              RemoveObserver,
              (CWSInfoServiceInterface::Observer*),
              (override));
};

class ExtensionAdminPolicyTest : public ExtensionManagementServiceTest {
 public:
  ExtensionAdminPolicyTest() = default;
  ~ExtensionAdminPolicyTest() override = default;

  void SetUpPolicyProvider() {
    provider_ = std::make_unique<StandardManagementPolicyProvider>(
        extension_management_.get(), profile_.get());
  }

  void CreateExtension(ManifestLocation location) {
    base::Value::Dict values;
    CreateExtensionFromValues(location, &values);
  }

  void CreateHostedApp(ManifestLocation location) {
    base::Value::Dict values;
    values.SetByDottedPath(manifest_keys::kWebURLs,
                           base::Value(base::Value::Type::LIST));
    values.SetByDottedPath(manifest_keys::kLaunchWebURL,
                           "http://www.example.com");
    CreateExtensionFromValues(location, &values);
  }

  void CreateExtensionFromValues(ManifestLocation location,
                                 base::Value::Dict* values) {
    values->Set(manifest_keys::kName, "test");
    values->Set(manifest_keys::kVersion, "0.1");
    values->Set(manifest_keys::kManifestVersion, 2);
    std::u16string error;
    extension_ = Extension::Create(base::FilePath(), location, *values,
                                   Extension::NO_FLAGS, &error);
    ASSERT_TRUE(extension_.get());
  }

  // Wrappers for legacy admin policy functions, for testing purpose only.
  bool BlocklistedByDefault(const base::Value::List* blocklist);
  bool UserMayLoad(const base::Value::List* blocklist,
                   const base::Value::List* allowlist,
                   const base::Value::List* allowed_types,
                   const Extension* extension,
                   std::u16string* error);
  bool UserMayModifySettings(const Extension* extension, std::u16string* error);
  bool ExtensionMayModifySettings(const Extension* source_extension,
                                  const Extension* extension,
                                  std::u16string* error);
  bool MustRemainEnabled(const Extension* extension, std::u16string* error);

 protected:
  std::unique_ptr<StandardManagementPolicyProvider> provider_;
  scoped_refptr<Extension> extension_;
};

bool ExtensionAdminPolicyTest::BlocklistedByDefault(
    const base::Value::List* blocklist) {
  SetUpPolicyProvider();
  if (blocklist) {
    SetPref(true, pref_names::kInstallDenyList,
            base::Value(blocklist->Clone()));
  }
  return extension_management_->BlocklistedByDefault();
}

bool ExtensionAdminPolicyTest::UserMayLoad(
    const base::Value::List* blocklist,
    const base::Value::List* allowlist,
    const base::Value::List* allowed_types,
    const Extension* extension,
    std::u16string* error) {
  SetUpPolicyProvider();
  if (blocklist) {
    SetPref(true, pref_names::kInstallDenyList,
            base::Value(blocklist->Clone()));
  }
  if (allowlist) {
    SetPref(true, pref_names::kInstallAllowList,
            base::Value(allowlist->Clone()));
  }
  if (allowed_types) {
    SetPref(true, pref_names::kAllowedTypes,
            base::Value(allowed_types->Clone()));
  }
  return provider_->UserMayLoad(extension, error);
}

bool ExtensionAdminPolicyTest::UserMayModifySettings(const Extension* extension,
                                                     std::u16string* error) {
  SetUpPolicyProvider();
  return provider_->UserMayModifySettings(extension, error);
}

bool ExtensionAdminPolicyTest::ExtensionMayModifySettings(
    const Extension* source_extension,
    const Extension* extension,
    std::u16string* error) {
  SetUpPolicyProvider();
  return provider_->ExtensionMayModifySettings(source_extension, extension,
                                               error);
}

bool ExtensionAdminPolicyTest::MustRemainEnabled(const Extension* extension,
                                                 std::u16string* error) {
  SetUpPolicyProvider();
  return provider_->MustRemainEnabled(extension, error);
}

// Verify that preference controlled by legacy ExtensionInstallSources policy is
// handled well.
TEST_F(ExtensionManagementServiceTest, LegacyInstallSources) {
  base::Value::List allowed_sites_pref;
  allowed_sites_pref.Append("https://www.example.com/foo");
  allowed_sites_pref.Append("https://corp.mycompany.com/*");
  SetPref(true, pref_names::kAllowedInstallSites,
          base::Value(std::move(allowed_sites_pref)));
  ASSERT_TRUE(ReadGlobalSettings()->install_sources);
  const URLPatternSet& allowed_sites = *ReadGlobalSettings()->install_sources;
  EXPECT_FALSE(allowed_sites.is_empty());
  EXPECT_TRUE(allowed_sites.MatchesURL(GURL("https://www.example.com/foo")));
  EXPECT_FALSE(allowed_sites.MatchesURL(GURL("https://www.example.com/bar")));
  EXPECT_TRUE(
      allowed_sites.MatchesURL(GURL("https://corp.mycompany.com/entry")));
  EXPECT_FALSE(
      allowed_sites.MatchesURL(GURL("https://www.mycompany.com/entry")));
}

// Verify that preference controlled by legacy ExtensionAllowedTypes policy is
// handled well.
TEST_F(ExtensionManagementServiceTest, LegacyAllowedTypes) {
  base::Value::List allowed_types_pref;
  allowed_types_pref.Append(Manifest::TYPE_THEME);
  allowed_types_pref.Append(Manifest::TYPE_USER_SCRIPT);

  SetPref(true, pref_names::kAllowedTypes,
          base::Value(std::move(allowed_types_pref)));
  ASSERT_TRUE(ReadGlobalSettings()->allowed_types);
  const std::vector<Manifest::Type>& allowed_types =
      *ReadGlobalSettings()->allowed_types;
  EXPECT_EQ(allowed_types.size(), 2u);
  EXPECT_FALSE(base::Contains(allowed_types, Manifest::TYPE_EXTENSION));
  EXPECT_TRUE(base::Contains(allowed_types, Manifest::TYPE_THEME));
  EXPECT_TRUE(base::Contains(allowed_types, Manifest::TYPE_USER_SCRIPT));
}

// Verify that preference controlled by legacy ExtensionInstallBlocklist policy
// is handled well.
TEST_F(ExtensionManagementServiceTest, LegacyInstallBlocklist) {
  base::Value::List denied_list_pref;
  denied_list_pref.Append(kTargetExtension);

  SetPref(true, pref_names::kInstallDenyList,
          base::Value(std::move(denied_list_pref)));
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kBlocked);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kAllowed);
}

// Verify that preference controlled by legacy ExtensionInstallAllowlist policy
// is handled well.
TEST_F(ExtensionManagementServiceTest, LegacyAllowlist) {
  base::Value::List denied_list_pref;
  denied_list_pref.Append("*");
  base::Value::List allowed_list_pref;
  allowed_list_pref.Append(kTargetExtension);

  SetPref(true, pref_names::kInstallDenyList,
          base::Value(std::move(denied_list_pref)));
  SetPref(true, pref_names::kInstallAllowList,
          base::Value(allowed_list_pref.Clone()));
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kBlocked);

  // Verify that install allowlist preference set by user is ignored.
  RemovePref(true, pref_names::kInstallAllowList);
  SetPref(false, pref_names::kInstallAllowList,
          base::Value(std::move(allowed_list_pref)));
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kBlocked);
}

// Verify that preference controlled by legacy ExtensionInstallForcelist policy
// is handled well.
TEST_F(ExtensionManagementServiceTest, LegacyInstallForcelist) {
  base::Value::Dict forced_list_pref;
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension,
                                     kExampleUpdateUrl);

  SetPref(true, pref_names::kInstallForceList, forced_list_pref.Clone());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  CheckAutomaticallyInstalledUpdateUrl(kTargetExtension, kExampleUpdateUrl);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kAllowed);

  // Verify that install forcelist preference set by user is ignored.
  RemovePref(true, pref_names::kInstallForceList);
  SetPref(false, pref_names::kInstallForceList, forced_list_pref.Clone());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kAllowed);
}

// Verify that update url is overridden for extensions specified in
// |kInstallForcelist| pref but |installation_mode| is missing in
// |kExtensionSettings| pref.
TEST_F(ExtensionManagementServiceTest,
       InstallUpdateUrlEnforcedForceInstalledPref) {
  base::Value::Dict forced_list_pref;
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension,
                                     kExampleUpdateUrl);
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension2,
                                     kExampleUpdateUrl);

  SetPref(true, pref_names::kInstallForceList, forced_list_pref.Clone());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kForced);

  SetExampleDictPref(kExampleDictPreferenceWithoutInstallationMode);

  // Verify that the update URL is overridden for kTargetExtension.
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  EXPECT_TRUE(IsUpdateUrlOverridden(kTargetExtension));

  // Verify that the update URL is not overridden for kTargetExtension2 because
  // |override_update_url| flag is not specified for it in |kExtensionSettings|
  // pref.
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kForced);
  EXPECT_FALSE(IsUpdateUrlOverridden(kTargetExtension2));
}

// Verify that update url is not overridden for extensions not specified in
// |kInstallForcelist| and |installation_mode| is missing in
// |kExtensionSettings|.
TEST_F(ExtensionManagementServiceTest,
       InstallUpdateUrlEnforcedForceInstalledPrefMissing) {
  base::Value::Dict forced_list_pref;
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension2,
                                     kExampleUpdateUrl);
  SetPref(true, pref_names::kInstallForceList, forced_list_pref.Clone());

  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kForced);

  SetExampleDictPref(kExampleDictPreferenceWithoutInstallationMode);

  // Verify that the update URL is not overridden for kTargetExtension as it is
  // not listed in |kInstallForcelist| pref.
  EXPECT_NE(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  EXPECT_FALSE(IsUpdateUrlOverridden(kTargetExtension));
}

// Verify that update url is overridden for extensions which are marked as
// 'force_installed' and |override_update_url| is true for them in
// |kExtensionSettings|.
TEST_F(ExtensionManagementServiceTest,
       InstallUpdateUrlEnforcedExtensionSettings) {
  SetExampleDictPref(kExampleForceInstalledDictPreference);

  // Verify that the update URL is overridden for kTargetExtension.
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  EXPECT_TRUE(IsUpdateUrlOverridden(kTargetExtension));

  // Verify that the update URL is not overridden for kTargetExtension2 because
  // |override_update_url| flag is not specified for it in |kExtensionSettings|
  // pref.
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kForced);
  EXPECT_FALSE(IsUpdateUrlOverridden(kTargetExtension2));
}

// Verify that the force-installed extension specified in the preference
// |kInstallUpdateUrlEnforced| is ignored if the update URL is a webstore update
// URL.
TEST_F(ExtensionManagementServiceTest,
       InstallUpdateUrlEnforcedWebstoreUpdateUrl) {
  base::Value::Dict forced_list_pref;
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension,
                                     extension_urls::kChromeWebstoreUpdateURL);
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension2,
                                     kExampleUpdateUrl);

  SetPref(true, pref_names::kInstallForceList, forced_list_pref.Clone());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kForced);

  SetExampleDictPref(kExampleDictPreferenceWithoutInstallationMode);

  // Verify that the update URL is not overridden for kTargetExtension because
  // |update_url| is a Chrome web store URL.
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  EXPECT_FALSE(IsUpdateUrlOverridden(kTargetExtension));
}

// Tests handling of exceeding number of urls
TEST_F(ExtensionManagementServiceTest, HostsMaximumExceeded) {
  const char policy_template[] =
      "{"
      "  \"abcdefghijklmnopabcdefghijklmnop\": {"
      "    \"installation_mode\": \"allowed\","
      "    \"runtime_blocked_hosts\": [%s],"
      "    \"runtime_allowed_hosts\": [%s]"
      "  }"
      "}";

  std::string urls;
  for (size_t i = 0; i < 200; ++i) {
    urls.append("\"*://example" + base::NumberToString(i) + ".com\",");
  }

  std::string policy =
      base::StringPrintf(policy_template, urls.c_str(), urls.c_str());
  SetExampleDictPref(policy);
  EXPECT_EQ(100u, GetPolicyBlockedHosts(kTargetExtension).size());
  EXPECT_EQ(100u, GetPolicyAllowedHosts(kTargetExtension).size());
}

// Tests that multiple entries for a dictionary are all applied.
TEST_F(ExtensionManagementServiceTest, MultipleEntries) {
  SetExampleDictPref(kExampleDictPreferenceWithMultipleEntries);

  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kBlocked);

  EXPECT_FALSE(CheckMinimumVersion(kTargetExtension2, "1.0"));
}

// Tests parsing of new dictionary preference.
TEST_F(ExtensionManagementServiceTest, PreferenceParsing) {
  SetExampleDictPref(kExampleDictPreference);

  // Verifies the installation mode settings.
  EXPECT_TRUE(extension_management_->BlocklistedByDefault());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kForced);
  CheckAutomaticallyInstalledUpdateUrl(kTargetExtension2, kExampleUpdateUrl);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension3),
            ManagedInstallationMode::kRecommended);
  CheckAutomaticallyInstalledUpdateUrl(kTargetExtension3, kExampleUpdateUrl);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kBlocked);
  EXPECT_EQ(GetInstallationModeByUpdateUrl(kExampleUpdateUrl),
            ManagedInstallationMode::kAllowed);
  EXPECT_TRUE(GetPolicyBlockedHosts(kTargetExtension).is_empty());
  EXPECT_TRUE(GetPolicyBlockedHosts(kTargetExtension4)
                  .MatchesURL(GURL("http://test.foo.com/test")));
  EXPECT_TRUE(GetPolicyBlockedHosts(kTargetExtension4)
                  .MatchesURL(GURL("https://bar.org/test")));
  EXPECT_TRUE(GetBlockedInstallMessage(kTargetExtension).empty());
  EXPECT_EQ("Custom Error Extension4",
            GetBlockedInstallMessage(kTargetExtension4));
  EXPECT_EQ("Custom Error Default",
            GetBlockedInstallMessage(kNonExistingExtension));

  // Verifies using multiple extensions as a key.
  EXPECT_EQ(GetInstallationModeById(kTargetExtension5),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension6),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension7),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension8),
            ManagedInstallationMode::kAllowed);

  // Verifies global settings.
  ASSERT_TRUE(ReadGlobalSettings()->install_sources);
  const URLPatternSet& allowed_sites = *ReadGlobalSettings()->install_sources;
  EXPECT_EQ(allowed_sites.size(), 1u);
  EXPECT_TRUE(allowed_sites.MatchesURL(GURL("http://foo.com/entry")));
  EXPECT_FALSE(allowed_sites.MatchesURL(GURL("http://bar.com/entry")));
  EXPECT_TRUE(GetPolicyBlockedHosts(kNonExistingExtension)
                  .MatchesURL(GURL("http://example.com/default")));

  ASSERT_TRUE(ReadGlobalSettings()->allowed_types);
  const std::vector<Manifest::Type>& allowed_types =
      *ReadGlobalSettings()->allowed_types;
  EXPECT_EQ(allowed_types.size(), 2u);
  EXPECT_TRUE(base::Contains(allowed_types, Manifest::TYPE_THEME));
  EXPECT_TRUE(base::Contains(allowed_types, Manifest::TYPE_USER_SCRIPT));

  // Verifies blocked permission allowlist settings.
  APIPermissionSet api_permission_set;
  api_permission_set.clear();
  api_permission_set.insert(APIPermissionID::kFileSystem);
  api_permission_set.insert(APIPermissionID::kDownloads);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissionsById(kNonExistingExtension));

  api_permission_set.clear();
  api_permission_set.insert(APIPermissionID::kFileSystem);
  api_permission_set.insert(APIPermissionID::kDownloads);
  api_permission_set.insert(APIPermissionID::kBookmark);
  EXPECT_EQ(api_permission_set, GetBlockedAPIPermissionsById(kTargetExtension));

  api_permission_set.clear();
  api_permission_set.insert(APIPermissionID::kDownloads);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissionsById(kTargetExtension2));

  api_permission_set.clear();
  api_permission_set.insert(APIPermissionID::kFileSystem);
  api_permission_set.insert(APIPermissionID::kHistory);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissionsById(kTargetExtension3));

  api_permission_set.clear();
  api_permission_set.insert(APIPermissionID::kFileSystem);
  api_permission_set.insert(APIPermissionID::kBookmark);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissionsByUpdateUrl(kExampleUpdateUrl));

  // Verifies minimum version settings.
  EXPECT_FALSE(CheckMinimumVersion(kTargetExtension, "1.0.99"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "1.1"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "1.1.0.1"));

  // Verifies that an extension using the default scope where
  // no custom blocked install message is defined returns an empty string.
  SetExampleDictPref(kExampleDictNoCustomError);
  EXPECT_EQ("", GetBlockedInstallMessage(kNonExistingExtension));
}

// Tests the handling of installation mode in case it's specified in both
// per-extension and per-update-url settings.
TEST_F(ExtensionManagementServiceTest, InstallationModeConflictHandling) {
  SetExampleDictPref(kExampleDictPreference);

  // Per-extension installation mode settings should always override
  // per-update-url settings.
  EXPECT_EQ(GetInstallationMode(kTargetExtension, kExampleUpdateUrl),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationMode(kTargetExtension2, kExampleUpdateUrl),
            ManagedInstallationMode::kForced);
  EXPECT_EQ(GetInstallationMode(kTargetExtension3, kExampleUpdateUrl),
            ManagedInstallationMode::kRecommended);
}

// Tests the handling of blocked permissions in case it's specified in both
// per-extension and per-update-url settings.
TEST_F(ExtensionManagementServiceTest, BlockedPermissionsConflictHandling) {
  SetExampleDictPref(kExampleDictPreference);

  // Both settings should be overridden.
  APIPermissionSet blocked_permissions_for_update_url;
  blocked_permissions_for_update_url.insert(APIPermissionID::kFileSystem);
  blocked_permissions_for_update_url.insert(APIPermissionID::kBookmark);

  APIPermissionSet api_permission_set;

  api_permission_set = blocked_permissions_for_update_url.Clone();
  api_permission_set.insert(APIPermissionID::kFileSystem);
  api_permission_set.insert(APIPermissionID::kDownloads);
  api_permission_set.insert(APIPermissionID::kBookmark);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissions(kTargetExtension, kExampleUpdateUrl));

  api_permission_set = blocked_permissions_for_update_url.Clone();
  api_permission_set.insert(APIPermissionID::kDownloads);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissions(kTargetExtension2, kExampleUpdateUrl));

  api_permission_set = blocked_permissions_for_update_url.Clone();
  api_permission_set.insert(APIPermissionID::kFileSystem);
  api_permission_set.insert(APIPermissionID::kHistory);
  EXPECT_EQ(api_permission_set,
            GetBlockedAPIPermissions(kTargetExtension3, kExampleUpdateUrl));

  // Default blocked permissions will not be inherited.
  EXPECT_EQ(blocked_permissions_for_update_url,
            GetBlockedAPIPermissions(kTargetExtension4, kExampleUpdateUrl));
  EXPECT_EQ(
      APIPermissionSet(),
      GetBlockedAPIPermissions(kTargetExtension4,
                               "https://www.example.com/another_update_url"));
}

TEST_F(ExtensionManagementServiceTest, DefaultHostExtensionsOverride) {
  SetExampleDictPref(base::StringPrintf(
      R"({
    "%s": {
      "runtime_allowed_hosts": ["https://allow.extension.com"],
      "runtime_blocked_hosts": ["https://block.extension.com"],
    },
    "%s": {},
    "*": {
      "runtime_allowed_hosts": ["https://allow.default.com"],
      "runtime_blocked_hosts": ["https://block.default.com"],
    },
  })",
      kTargetExtension, kTargetExtension2));

  // Override allow/block host for the first extension.
  URLPatternSet expected_extension_allowed_set_1;
  URLPatternSet expected_extension_blocked_set_1;
  expected_extension_allowed_set_1.AddPattern(
      {URLPattern::SCHEME_ALL, "https://allow.extension.com/*"});
  expected_extension_blocked_set_1.AddPattern(
      {URLPattern::SCHEME_ALL, "https://block.extension.com/*"});

  EXPECT_EQ(expected_extension_allowed_set_1,
            GetPolicyAllowedHosts(kTargetExtension));
  EXPECT_EQ(expected_extension_blocked_set_1,
            GetPolicyBlockedHosts(kTargetExtension));

  // Empty allow/block host for the second extension.
  EXPECT_EQ(URLPatternSet(), GetPolicyAllowedHosts(kTargetExtension2));
  EXPECT_EQ(URLPatternSet(), GetPolicyBlockedHosts(kTargetExtension2));

  // Default allow/block host for the third extension.
  URLPatternSet expected_extension_allowed_set_3;
  URLPatternSet expected_extension_blocked_set_3;
  expected_extension_allowed_set_3.AddPattern(
      {URLPattern::SCHEME_ALL, "https://allow.default.com/*"});
  expected_extension_blocked_set_3.AddPattern(
      {URLPattern::SCHEME_ALL, "https://block.default.com/*"});

  EXPECT_EQ(expected_extension_allowed_set_3,
            GetPolicyAllowedHosts(kTargetExtension3));
  EXPECT_EQ(expected_extension_blocked_set_3,
            GetPolicyBlockedHosts(kTargetExtension3));
}

// Tests the 'minimum_version_required' settings of extension management.
TEST_F(ExtensionManagementServiceTest, kMinimumVersionRequired) {
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "0.0"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "3.0.0"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "9999.0"));

  {
    PrefUpdater pref(pref_service_.get());
    pref.SetMinimumVersionRequired(kTargetExtension, "3.0");
  }

  EXPECT_FALSE(CheckMinimumVersion(kTargetExtension, "0.0"));
  EXPECT_FALSE(CheckMinimumVersion(kTargetExtension, "2.99"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "3.0.0"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "3.0.1"));
  EXPECT_TRUE(CheckMinimumVersion(kTargetExtension, "4.0"));
}

// Tests functionality of new preference as to deprecate legacy
// ExtensionInstallSources policy.
TEST_F(ExtensionManagementServiceTest, NewInstallSources) {
  // Set the legacy preference, and verifies that it works.
  base::Value::List allowed_sites_pref;
  allowed_sites_pref.Append("https://www.example.com/foo");
  SetPref(true, pref_names::kAllowedInstallSites,
          base::Value(std::move(allowed_sites_pref)));
  ASSERT_TRUE(ReadGlobalSettings()->install_sources);
  EXPECT_TRUE(ReadGlobalSettings()->install_sources->MatchesURL(
      GURL("https://www.example.com/foo")));

  // Set the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.ClearInstallSources();
  }
  // Verifies that the new one overrides the legacy ones.
  ASSERT_TRUE(ReadGlobalSettings()->install_sources);
  EXPECT_FALSE(ReadGlobalSettings()->install_sources->MatchesURL(
      GURL("https://www.example.com/foo")));

  // Updates the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.AddInstallSource("https://corp.mycompany.com/*");
  }
  ASSERT_TRUE(ReadGlobalSettings()->install_sources);
  EXPECT_TRUE(ReadGlobalSettings()->install_sources->MatchesURL(
      GURL("https://corp.mycompany.com/entry")));
}

// Tests functionality of new preference as to deprecate legacy
// ExtensionAllowedTypes policy.
TEST_F(ExtensionManagementServiceTest, NewAllowedTypes) {
  // Set the legacy preference, and verifies that it works.
  base::Value::List allowed_types_pref;
  allowed_types_pref.Append(Manifest::TYPE_USER_SCRIPT);
  SetPref(true, pref_names::kAllowedTypes,
          base::Value(allowed_types_pref.Clone()));
  ASSERT_TRUE(ReadGlobalSettings()->allowed_types);
  EXPECT_EQ(ReadGlobalSettings()->allowed_types->size(), 1u);
  EXPECT_EQ(ReadGlobalSettings()->allowed_types.value()[0],
            Manifest::TYPE_USER_SCRIPT);

  // Set the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.ClearAllowedTypes();
  }
  // Verifies that the new one overrides the legacy ones.
  ASSERT_TRUE(ReadGlobalSettings()->allowed_types);
  EXPECT_EQ(ReadGlobalSettings()->allowed_types->size(), 0u);

  // Updates the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.AddAllowedType("theme");
  }
  ASSERT_TRUE(ReadGlobalSettings()->allowed_types);
  EXPECT_EQ(ReadGlobalSettings()->allowed_types->size(), 1u);
  EXPECT_EQ(ReadGlobalSettings()->allowed_types.value()[0],
            Manifest::TYPE_THEME);
}

// Tests functionality of new preference as to deprecate legacy
// ExtensionInstallBlocklist policy.
TEST_F(ExtensionManagementServiceTest, NewInstallBlocklist) {
  // Set the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.SetBlocklistedByDefault(false);  // Allowed by default.
    updater.SetIndividualExtensionInstallationAllowed(kTargetExtension, false);
    updater.ClearPerExtensionSettings(kTargetExtension2);
  }
  EXPECT_FALSE(extension_management_->BlocklistedByDefault());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kBlocked);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kAllowed);

  // Set legacy preference.
  base::Value::List denied_list_pref;
  denied_list_pref.Append("*");
  denied_list_pref.Append(kTargetExtension2);
  SetPref(true, pref_names::kInstallDenyList,
          base::Value(std::move(denied_list_pref)));

  base::Value::List allowed_list_pref;
  allowed_list_pref.Append(kTargetExtension);
  SetPref(true, pref_names::kInstallAllowList,
          base::Value(std::move(allowed_list_pref)));

  // Verifies that the new one have higher priority over the legacy ones.
  EXPECT_FALSE(extension_management_->BlocklistedByDefault());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kBlocked);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kBlocked);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kAllowed);
}

// Tests functionality of new preference as to deprecate legacy
// ExtensionInstallAllowlist policy.
TEST_F(ExtensionManagementServiceTest, NewAllowlist) {
  // Set the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.SetBlocklistedByDefault(true);  // Disallowed by default.
    updater.SetIndividualExtensionInstallationAllowed(kTargetExtension, true);
    updater.ClearPerExtensionSettings(kTargetExtension2);
  }
  EXPECT_TRUE(extension_management_->BlocklistedByDefault());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kBlocked);

  // Set legacy preference.
  base::Value::List denied_list_pref;
  denied_list_pref.Append(kTargetExtension);
  SetPref(true, pref_names::kInstallDenyList,
          base::Value(std::move(denied_list_pref)));

  base::Value::List allowed_list_pref;
  allowed_list_pref.Append(kTargetExtension2);
  SetPref(true, pref_names::kInstallAllowList,
          base::Value(std::move(allowed_list_pref)));

  // Verifies that the new one have higher priority over the legacy ones.
  EXPECT_TRUE(extension_management_->BlocklistedByDefault());
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kTargetExtension2),
            ManagedInstallationMode::kAllowed);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kBlocked);
}

// Tests functionality of new preference as to deprecate legacy
// ExtensionInstallForcelist policy.
TEST_F(ExtensionManagementServiceTest, NewInstallForcelist) {
  // Set some legacy preferences, to verify that the new one overrides the
  // legacy ones.
  base::Value::List denied_list_pref;
  denied_list_pref.Append(kTargetExtension);
  SetPref(true, pref_names::kInstallDenyList,
          base::Value(std::move(denied_list_pref)));

  // Set the new dictionary preference.
  {
    PrefUpdater updater(pref_service_.get());
    updater.SetIndividualExtensionAutoInstalled(kTargetExtension,
                                                kExampleUpdateUrl, true);
  }
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kForced);
  CheckAutomaticallyInstalledUpdateUrl(kTargetExtension, kExampleUpdateUrl);
  EXPECT_EQ(GetInstallationModeById(kNonExistingExtension),
            ManagedInstallationMode::kAllowed);
}

// Tests the behavior of IsInstallationExplicitlyAllowed().
TEST_F(ExtensionManagementServiceTest, IsInstallationExplicitlyAllowed) {
  SetExampleDictPref(kExampleDictPreference);

  // Constant name indicates the installation_mode of extensions in example
  // preference.
  const char* allowed = kTargetExtension;
  const char* forced = kTargetExtension2;
  const char* recommended = kTargetExtension3;
  const char* blocked = kTargetExtension4;
  const char* removed = kTargetExtension9;
  const char* not_specified = kNonExistingExtension;

  // BlocklistedByDefault() is true in example preference.
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyAllowed(allowed));
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyAllowed(forced));
  EXPECT_TRUE(
      extension_management_->IsInstallationExplicitlyAllowed(recommended));
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyAllowed(blocked));
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyAllowed(removed));
  EXPECT_FALSE(
      extension_management_->IsInstallationExplicitlyAllowed(not_specified));

  // Set BlocklistedByDefault() to false.
  PrefUpdater pref(pref_service_.get());
  pref.SetBlocklistedByDefault(false);

  // The result should remain the same.
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyAllowed(allowed));
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyAllowed(forced));
  EXPECT_TRUE(
      extension_management_->IsInstallationExplicitlyAllowed(recommended));
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyAllowed(blocked));
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyAllowed(removed));
  EXPECT_FALSE(
      extension_management_->IsInstallationExplicitlyAllowed(not_specified));
}

TEST_F(ExtensionManagementServiceTest, IsInstallationExplicitlyBlocked) {
  SetExampleDictPref(kExampleDictPreference);

  // Constant name indicates the installation_mode of extensions in example
  // preference.
  const char* allowed = kTargetExtension;
  const char* forced = kTargetExtension2;
  const char* recommended = kTargetExtension3;
  const char* blocked = kTargetExtension4;
  const char* removed = kTargetExtension9;
  const char* not_specified = kNonExistingExtension;

  // BlocklistedByDefault() is true in example preference.
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyBlocked(allowed));
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyBlocked(forced));
  EXPECT_FALSE(
      extension_management_->IsInstallationExplicitlyBlocked(recommended));
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyBlocked(blocked));
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyBlocked(removed));
  EXPECT_FALSE(
      extension_management_->IsInstallationExplicitlyBlocked(not_specified));

  PrefUpdater pref(pref_service_.get());
  pref.SetBlocklistedByDefault(false);

  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyBlocked(allowed));
  EXPECT_FALSE(extension_management_->IsInstallationExplicitlyBlocked(forced));
  EXPECT_FALSE(
      extension_management_->IsInstallationExplicitlyBlocked(recommended));
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyBlocked(blocked));
  EXPECT_TRUE(extension_management_->IsInstallationExplicitlyBlocked(removed));
  EXPECT_FALSE(
      extension_management_->IsInstallationExplicitlyBlocked(not_specified));
}

TEST_F(ExtensionManagementServiceTest,
       ExtensionsAreBlockedByDefaultForExtensionRequest) {
  // When extension request policy is set to true, all extensions are blocked by
  // default.
  SetPref(true, prefs::kCloudExtensionRequestEnabled,
          std::make_unique<base::Value>(true));
  EXPECT_TRUE(extension_management_->BlocklistedByDefault());
  EXPECT_EQ(ManagedInstallationMode::kBlocked,
            GetInstallationModeById(kTargetExtension));
  // However, it will be overridden by ExtensionSettings
  SetExampleDictPref(R"({
    "*": {
      "installation_mode": "removed",
    }
  })");
  EXPECT_EQ(ManagedInstallationMode::kRemoved,
            GetInstallationModeById(kTargetExtension));
}

TEST_F(ExtensionManagementServiceTest, ManifestV2Default) {
  SetPref(true, pref_names::kManifestV2Availability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::ManifestV2Setting::kDefault)));
  bool is_manifest_v3_only = base::FeatureList::IsEnabled(
      extensions_features::kExtensionsManifestV3Only);
  EXPECT_EQ(!is_manifest_v3_only,
            extension_management_->IsAllowedManifestVersion(
                2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));

  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  // Note: MV3 extension isn't exempt by policy because it's not affected at
  // all. It's not this class's responsibility to know about the rest of the
  // criteria; only whether the extension is exempt by policy.
  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
}

TEST_F(ExtensionManagementServiceTest, ManifestV2Disabled) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndDisableFeature(
      extensions_features::kExtensionsManifestV3Only);
  SetPref(true, pref_names::kManifestV2Availability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::ManifestV2Setting::kDisabled)));
  EXPECT_FALSE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));

  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  // Note: MV3 extension isn't exempt by policy because it's not affected at
  // all. It's not this class's responsibility to know about the rest of the
  // criteria; only whether the extension is exempt by policy.
  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
}

TEST_F(ExtensionManagementServiceTest, ManifestV2Enabled) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      extensions_features::kExtensionsManifestV3Only);
  SetPref(true, pref_names::kManifestV2Availability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::ManifestV2Setting::kEnabled)));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));

  EXPECT_TRUE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  // Note: MV3 extension isn't exempt by policy because it's not affected at
  // all. It's not this class's responsibility to know about the rest of the
  // criteria; only whether the extension is exempt by policy.
  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
}

TEST_F(ExtensionManagementServiceTest, ManifestV2EnabledForForceInstalled) {
  SetPref(
      true, pref_names::kManifestV2Availability,
      base::Value(static_cast<int>(internal::GlobalSettings::ManifestV2Setting::
                                       kEnabledForForceInstalled)));
  EXPECT_FALSE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));

  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  // Note: MV3 extension isn't exempt by policy because it's not affected at
  // all. It's not this class's responsibility to know about the rest of the
  // criteria; only whether the extension is exempt by policy.
  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));

  base::Value::Dict forced_list_pref;
  ExternalPolicyLoader::AddExtension(forced_list_pref, kTargetExtension,
                                     kExampleUpdateUrl);
  SetPref(true, pref_names::kInstallForceList, forced_list_pref.Clone());

  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));

  EXPECT_TRUE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  // Note: MV3 extension isn't exempt by policy because it's not affected at
  // all. It's not this class's responsibility to know about the rest of the
  // criteria; only whether the extension is exempt by policy.
  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      3, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
}

TEST_F(ExtensionManagementServiceTest, ManifestV2EnabledForExtensionOnly) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      extensions_features::kExtensionsManifestV3Only);
  SetPref(true, pref_names::kManifestV2Availability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::ManifestV2Setting::kEnabled)));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_LOGIN_SCREEN_EXTENSION));
  EXPECT_FALSE(extension_management_->IsAllowedManifestVersion(
      2, kTargetExtension, Manifest::Type::TYPE_HOSTED_APP));

  EXPECT_TRUE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_EXTENSION));
  EXPECT_TRUE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_LOGIN_SCREEN_EXTENSION));
  // Despite being force-installed, hosted apps aren't included in the
  // MV2 deprecation, so isn't exempt by policy.
  EXPECT_FALSE(extension_management_->IsExemptFromMV2DeprecationByPolicy(
      2, kTargetExtension, Manifest::Type::TYPE_HOSTED_APP));
}

// Verifies that extensions that do not update CWS are always allowed by
// the ExtensionUnpublishedAvailability policy check function since this policy
// ignores them.
TEST_F(ExtensionManagementServiceTest,
       UnpublishedCheckForNonCWSUpdateExtensions) {
  // Create test extensions that don't update from CWS.
  scoped_refptr<const Extension> offstore_extension =
      CreateOffstoreExtension(kNonExistingExtension);
  scoped_refptr<const Extension> forced_extension =
      CreateForcedExtension(kTargetExtension3);
  // Create mock CWS service. Verify it is not queried for these policy
  // checks.
  testing::NiceMock<MockCWSInfoService> mock_cws_info_service;
  SetCWSInfoService(&mock_cws_info_service);
  EXPECT_CALL(mock_cws_info_service, GetCWSInfo).Times(0);
  // Verify that the extensions are allowed regardless of policy setting.
  SetPref(true, pref_names::kExtensionUnpublishedAvailability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::UnpublishedAvailability::
                  kAllowUnpublished)));
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      offstore_extension.get()));
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      forced_extension.get()));

  SetPref(true, pref_names::kExtensionUnpublishedAvailability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::UnpublishedAvailability::
                  kDisableUnpublished)));
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      offstore_extension.get()));
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      forced_extension.get()));
  SetCWSInfoService(nullptr);
}

// Verifies that a CWS extensions is allowed if the
// ExtensionUnpublishedAvailability policy setting is kAllowUnpublished.
TEST_F(ExtensionManagementServiceTest,
       UnpublishedCheckWithPolicySettingAllowUnpublished) {
  // Configure the policy.
  SetPref(true, pref_names::kExtensionUnpublishedAvailability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::UnpublishedAvailability::
                  kAllowUnpublished)));
  // Create a test extension.
  scoped_refptr<const Extension> normal_extension =
      CreateNormalExtension(kTargetExtension);
  // CWS publish state should not be queried when this extension is checked.
  testing::NiceMock<MockCWSInfoService> mock_cws_info_service;
  SetCWSInfoService(&mock_cws_info_service);
  EXPECT_CALL(mock_cws_info_service, GetCWSInfo).Times(0);
  // Verify that the extension is allowed.
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      normal_extension.get()));
  SetCWSInfoService(nullptr);
}

// If ExtensionUnpublishedAvailability policy setting is
// kDisableUnpublished, verify that:
// - an extension is allowed if it is currently published in CWS or if the
//   CWS publish information is missing
// - an extension is disallowed if it is not currently published in CWS
TEST_F(ExtensionManagementServiceTest,
       UnpublishedCheckWithPolicySettingDisableUnpublished) {
  // Configure the policy.
  SetPref(true, pref_names::kExtensionUnpublishedAvailability,
          base::Value(static_cast<int>(
              internal::GlobalSettings::UnpublishedAvailability::
                  kDisableUnpublished)));
  // Create a test extension.
  scoped_refptr<const Extension> normal_extension =
      CreateNormalExtension(kTargetExtension);
  // Create mock CWSInfoService to verify GetCWSInfo is called.
  testing::NiceMock<MockCWSInfoService> mock_cws_info_service;
  SetCWSInfoService(&mock_cws_info_service);
  // Set up responses to GetCWSInfo calls.
  CWSInfoServiceInterface::CWSInfo cws_info_live = {
      /*is_present=*/true,
      /*is_live=*/true,
      /*last_update_time=*/base::Time::Now(),
      CWSInfoServiceInterface::CWSViolationType::kNone,
      /*unpublished_long_ago=*/false,
      /*no_privacy_practice=*/false};
  CWSInfoServiceInterface::CWSInfo cws_info_not_live = {
      /*is_present=*/true,
      /*is_live=*/false,
      /*last_update_time=*/base::Time::Now(),
      CWSInfoServiceInterface::CWSViolationType::kNone,
      /*unpublished_long_ago=*/false,
      /*no_privacy_practice=*/false};
  CWSInfoServiceInterface::CWSInfo cws_info_malware = {
      /*is_present=*/true,
      /*is_live=*/false,
      /*last_update_time=*/base::Time::Now(),
      CWSInfoServiceInterface::CWSViolationType::kMalware,
      /*unpublished_long_ago=*/false,
      /*no_privacy_practice=*/false};
  EXPECT_CALL(mock_cws_info_service, GetCWSInfo)
      .WillOnce(testing::Return(cws_info_live))
      .WillOnce(testing::Return(cws_info_malware))
      .WillOnce(testing::Return(cws_info_not_live))
      .WillOnce(testing::Return(std::nullopt));
  // Verify that the extension is allowed when it is live in CWS.
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      normal_extension.get()));
  // Verify that the extension is ignored, i.e. allowed, when it is malware.
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      normal_extension.get()));
  // Verify that the extension is disallowed when it is not live in CWS.
  EXPECT_FALSE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      normal_extension.get()));
  // Verify that the extensions is allowed if CWS publish status is missing.
  EXPECT_TRUE(extension_management_->IsAllowedByUnpublishedAvailabilityPolicy(
      normal_extension.get()));
  SetCWSInfoService(nullptr);
}

TEST_F(ExtensionManagementServiceTest, IsFileUrlNavigationAllowed) {
  EXPECT_EQ(IsFileUrlNavigationAllowed(kTargetExtension), false);
  EXPECT_EQ(IsFileUrlNavigationAllowed(kTargetExtension2), false);

  SetExampleDictPref(base::StringPrintf(
      R"({
    "%s": {
      "file_url_navigation_allowed": true
    }
  })",
      kTargetExtension));
  EXPECT_EQ(IsFileUrlNavigationAllowed(kTargetExtension), true);
  EXPECT_EQ(IsFileUrlNavigationAllowed(kTargetExtension2), false);
}

TEST_F(ExtensionManagementServiceTest, ToolbarPinModeParsing) {
  const char kToolbarPinPref[] = R"(
{
  "%s": {
    "toolbar_pin": "%s"
  },
  "%s": {
    "toolbar_pin": "%s"
  },
  "%s": {
    "toolbar_pin": "%s"
  }
})";

  // Test valid values.
  SetExampleDictPref(base::StringPrintf(
      kToolbarPinPref, kTargetExtension, "default_unpinned", kTargetExtension2,
      "default_pinned", kTargetExtension3, "force_pinned"));

  EXPECT_EQ(GetToolbarPinMode(kTargetExtension),
            extensions::ManagedToolbarPinMode::kDefaultUnpinned);
  EXPECT_EQ(GetToolbarPinMode(kTargetExtension2),
            extensions::ManagedToolbarPinMode::kDefaultPinned);
  EXPECT_EQ(GetToolbarPinMode(kTargetExtension3),
            extensions::ManagedToolbarPinMode::kForcePinned);

  // Test with no value set, should default to kDefaultUnpinned.
  SetExampleDictPref(base::StringPrintf(R"({
    "%s": {}
  })",
                                        kTargetExtension5));
  EXPECT_EQ(GetToolbarPinMode(kTargetExtension5),
            extensions::ManagedToolbarPinMode::kDefaultUnpinned);
}

TEST_F(ExtensionManagementServiceTest, ToolbarPinModeParsingFailsForInvalid) {
  // An invalid value for `toolbar_pin` should fail to parse.
  SetExampleDictPref(base::StringPrintf(R"({
    "%s": {
      "toolbar_pin": "invalid_value",
      "installation_mode": "blocked"
    }
  })",
                                        kTargetExtension));
  // Because parsing failed, the installation_mode was not applied, therefore
  // it should fall back to the default (kAllowed).
  EXPECT_EQ(GetInstallationModeById(kTargetExtension),
            ManagedInstallationMode::kAllowed);
}

TEST_F(ExtensionManagementServiceTest, IsAllowedByUnpackedDeveloperModePolicy) {
  base::test::ScopedFeatureList feature_list(
      extensions_features::kExtensionDisableUnsupportedDeveloper);
  scoped_refptr<const Extension> unpacked_extension =
      CreateOffstoreExtension(kNonExistingExtension);

  SetPref(false, prefs::kExtensionsUIDeveloperMode, base::Value(false));
  EXPECT_FALSE(extension_management_->IsAllowedByUnpackedDeveloperModePolicy(
      *unpacked_extension));

  SetPref(false, prefs::kExtensionsUIDeveloperMode, base::Value(true));
  EXPECT_TRUE(extension_management_->IsAllowedByUnpackedDeveloperModePolicy(
      *unpacked_extension));
}

TEST_F(ExtensionManagementServiceTest, IsForceInstalledInLowTrustEnvironment) {
  {
    // Low trust environment. Verify that the extension is considered
    // force-installed in a low-trust environment on Windows and Mac.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::NONE);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    constexpr bool expect_low_trust =
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
        true;
#else
        false;
#endif
    EXPECT_EQ(extension_management_->IsForceInstalledInLowTrustEnvironment(
                  *forced_extension),
              expect_low_trust);
  }
  {
    // High trust environment. Verify that the extension is not considered
    // force-installed in a low-trust environment.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::CLOUD_DOMAIN);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    EXPECT_FALSE(extension_management_->IsForceInstalledInLowTrustEnvironment(
        *forced_extension));
  }
}

TEST_F(ExtensionManagementServiceTest,
       IsGreylistedForceInstalledInLowTrustEnvironment) {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
  base::test::ScopedFeatureList feature_list(
      kDisableForceInstalledExtensionsInLowTrustEnviromentWhenGreylisted);
#endif

  {
    // Greylisted, force-installed in a low-trust environment.

    // Force-install an extension in low-trust environment.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::NONE);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    // Greylist the extension.
    blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
        forced_extension->id(),
        BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED,
        ExtensionPrefs::Get(profile_.get()));

    constexpr bool expect_greylisted_in_low_trust =
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
        true;
#else
        false;
#endif
    EXPECT_EQ(
        extension_management_->IsGreylistedForceInstalledInLowTrustEnvironment(
            forced_extension->id()),
        expect_greylisted_in_low_trust);
  }
  {
    // Greylisted, force-installed in a high-trust environment.

    // Force-install an extension in high-trust environment.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::CLOUD_DOMAIN);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    // Greylist the extension.
    blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
        forced_extension->id(),
        BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED,
        ExtensionPrefs::Get(profile_.get()));

    EXPECT_FALSE(
        extension_management_->IsGreylistedForceInstalledInLowTrustEnvironment(
            forced_extension->id()));
  }
  {
    // Not greylisted.

    // Force-install an extension in low-trust environment.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::NONE);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    // Don't greylist the extension.
    blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
        forced_extension->id(), BitMapBlocklistState::NOT_BLOCKLISTED,
        ExtensionPrefs::Get(profile_.get()));

    EXPECT_FALSE(
        extension_management_->IsGreylistedForceInstalledInLowTrustEnvironment(
            forced_extension->id()));
  }
  {
    // `ExtensionForceInstallWithNonMalwareViolationsEnabled` policy is true.

    // Force-install an extension in low-trust environment.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::NONE);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    // Greylist the extension.
    blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
        forced_extension->id(),
        BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED,
        ExtensionPrefs::Get(profile_.get()));

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

    EXPECT_FALSE(
        extension_management_->IsGreylistedForceInstalledInLowTrustEnvironment(
            forced_extension->id()));
  }
  {
    // Not force-installed.

    // Set up a non-forced extension in a low-trust environment.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::NONE);
    scoped_refptr<const Extension> extension =
        CreateNormalExtension(kTargetExtension3);

    // Greylist the extension.
    blocklist_prefs::SetSafeBrowsingExtensionBlocklistState(
        extension->id(), BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED,
        ExtensionPrefs::Get(profile_.get()));

    EXPECT_FALSE(
        extension_management_->IsGreylistedForceInstalledInLowTrustEnvironment(
            extension->id()));
  }
}

TEST_F(ExtensionManagementServiceTest,
       ShouldBlockForceInstalledOffstoreExtension) {
  {
    // Low trust environment. Verify that extension is not allowed on
    // Windows and Mac.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::NONE);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    bool expect_blocked =
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
        true;
#else
        false;
#endif
    EXPECT_EQ(extension_management_->ShouldBlockForceInstalledOffstoreExtension(
                  *forced_extension),
              expect_blocked);
  }
  {
    // High trust environment. Verify that extension is allowed.
    policy::ScopedManagementServiceOverrideForTesting browser_management(
        policy::ManagementServiceFactory::GetForPlatform(),
        policy::EnterpriseManagementAuthority::CLOUD_DOMAIN);
    scoped_refptr<const Extension> forced_extension =
        CreateForcedExtension(kTargetExtension3, Extension::NO_FLAGS);

    EXPECT_FALSE(
        extension_management_->ShouldBlockForceInstalledOffstoreExtension(
            *forced_extension));
  }
}

// Tests the flag value indicating that extensions are blocklisted by default.
TEST_F(ExtensionAdminPolicyTest, BlocklistedByDefault) {
  EXPECT_FALSE(BlocklistedByDefault(nullptr));

  base::Value::List blocklist;
  blocklist.Append(kNonExistingExtension);
  EXPECT_FALSE(BlocklistedByDefault(&blocklist));
  blocklist.Append("*");
  EXPECT_TRUE(BlocklistedByDefault(&blocklist));

  blocklist.clear();
  blocklist.Append("*");
  EXPECT_TRUE(BlocklistedByDefault(&blocklist));
}

// Tests UserMayLoad for required extensions.
TEST_F(ExtensionAdminPolicyTest, UserMayLoadRequired) {
  CreateExtension(ManifestLocation::kComponent);
  EXPECT_TRUE(
      UserMayLoad(nullptr, nullptr, nullptr, extension_.get(), nullptr));
  std::u16string error;
  EXPECT_TRUE(UserMayLoad(nullptr, nullptr, nullptr, extension_.get(), &error));
  EXPECT_TRUE(error.empty());

  // Required extensions may load even if they're on the blocklist.
  base::Value::List blocklist;
  blocklist.Append(extension_->id());
  EXPECT_TRUE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), nullptr));

  blocklist.Append("*");
  EXPECT_TRUE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), nullptr));
}

// Tests UserMayLoad when no blocklist exists, or it's empty.
TEST_F(ExtensionAdminPolicyTest, UserMayLoadNoBlocklist) {
  CreateExtension(ManifestLocation::kInternal);
  EXPECT_TRUE(
      UserMayLoad(nullptr, nullptr, nullptr, extension_.get(), nullptr));
  base::Value::List blocklist;
  EXPECT_TRUE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), nullptr));
  std::u16string error;
  EXPECT_TRUE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), &error));
  EXPECT_TRUE(error.empty());
}

// Tests UserMayLoad for an extension on the allowlist.
TEST_F(ExtensionAdminPolicyTest, UserMayLoadAllowlisted) {
  CreateExtension(ManifestLocation::kInternal);

  base::Value::List allowlist;
  allowlist.Append(extension_->id());
  EXPECT_TRUE(
      UserMayLoad(nullptr, &allowlist, nullptr, extension_.get(), nullptr));

  base::Value::List blocklist;
  blocklist.Append(extension_->id());
  EXPECT_TRUE(
      UserMayLoad(nullptr, &allowlist, nullptr, extension_.get(), nullptr));
  std::u16string error;
  EXPECT_TRUE(
      UserMayLoad(nullptr, &allowlist, nullptr, extension_.get(), &error));
  EXPECT_TRUE(error.empty());
}

// Tests UserMayLoad for an extension on the blocklist.
TEST_F(ExtensionAdminPolicyTest, UserMayLoadBlocklisted) {
  CreateExtension(ManifestLocation::kInternal);

  // Blocklisted by default.
  base::Value::List blocklist;
  blocklist.Append("*");
  EXPECT_FALSE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), nullptr));
  std::u16string error;
  EXPECT_FALSE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), &error));
  EXPECT_FALSE(error.empty());

  // Extension on the blocklist, with and without wildcard.
  blocklist.Append(extension_->id());
  EXPECT_FALSE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), nullptr));
  blocklist.clear();
  blocklist.Append(extension_->id());
  EXPECT_FALSE(
      UserMayLoad(&blocklist, nullptr, nullptr, extension_.get(), nullptr));

  // With a allowlist. There's no such thing as a allowlist wildcard.
  base::Value::List allowlist;
  allowlist.Append("behllobkkfkfnphdnhnkndlbkcpglgmj");
  EXPECT_FALSE(
      UserMayLoad(&blocklist, &allowlist, nullptr, extension_.get(), nullptr));
  allowlist.Append("*");
  EXPECT_FALSE(
      UserMayLoad(&blocklist, &allowlist, nullptr, extension_.get(), nullptr));
}

TEST_F(ExtensionAdminPolicyTest, UserMayLoadAllowedTypes) {
  CreateExtension(ManifestLocation::kInternal);
  EXPECT_TRUE(
      UserMayLoad(nullptr, nullptr, nullptr, extension_.get(), nullptr));

  base::Value::List allowed_types;
  EXPECT_FALSE(
      UserMayLoad(nullptr, nullptr, &allowed_types, extension_.get(), nullptr));

  allowed_types.Append(Manifest::TYPE_EXTENSION);
  EXPECT_TRUE(
      UserMayLoad(nullptr, nullptr, &allowed_types, extension_.get(), nullptr));

  CreateHostedApp(ManifestLocation::kInternal);
  EXPECT_FALSE(
      UserMayLoad(nullptr, nullptr, &allowed_types, extension_.get(), nullptr));

  CreateHostedApp(ManifestLocation::kExternalPolicyDownload);
  EXPECT_FALSE(
      UserMayLoad(nullptr, nullptr, &allowed_types, extension_.get(), nullptr));
}

TEST_F(ExtensionAdminPolicyTest, UserMayModifySettings) {
  CreateExtension(ManifestLocation::kInternal);
  EXPECT_TRUE(UserMayModifySettings(extension_.get(), nullptr));
  std::u16string error;
  EXPECT_TRUE(UserMayModifySettings(extension_.get(), &error));
  EXPECT_TRUE(error.empty());

  CreateExtension(ManifestLocation::kExternalPolicyDownload);
  error.clear();
  EXPECT_FALSE(UserMayModifySettings(extension_.get(), nullptr));
  EXPECT_FALSE(UserMayModifySettings(extension_.get(), &error));
  EXPECT_FALSE(error.empty());
}

TEST_F(ExtensionAdminPolicyTest, ExtensionMayModifySettings) {
  CreateExtension(ManifestLocation::kExternalPolicyDownload);
  auto external_policy_download = extension_;
  CreateExtension(ManifestLocation::kExternalPolicy);
  auto external_policy = extension_;
  CreateExtension(ManifestLocation::kExternalPref);
  auto external_pref = extension_;
  CreateExtension(ManifestLocation::kComponent);
  auto component = extension_;
  CreateExtension(ManifestLocation::kComponent);
  auto component2 = extension_;
  // Make sure that component/policy/external extensions cannot modify component
  // extensions (no extension may modify a component extension).
  EXPECT_FALSE(ExtensionMayModifySettings(external_policy_download.get(),
                                          component.get(), nullptr));
  EXPECT_FALSE(
      ExtensionMayModifySettings(component2.get(), component.get(), nullptr));
  EXPECT_FALSE(ExtensionMayModifySettings(external_pref.get(), component.get(),
                                          nullptr));

  // Only component/policy extensions *can* modify policy extensions, and eg.
  // external cannot.
  EXPECT_TRUE(ExtensionMayModifySettings(
      external_policy.get(), external_policy_download.get(), nullptr));
  EXPECT_TRUE(ExtensionMayModifySettings(
      component.get(), external_policy_download.get(), nullptr));
  EXPECT_FALSE(ExtensionMayModifySettings(
      external_pref.get(), external_policy_download.get(), nullptr));
}

TEST_F(ExtensionAdminPolicyTest, MustRemainEnabled) {
  CreateExtension(ManifestLocation::kExternalPolicyDownload);
  EXPECT_TRUE(MustRemainEnabled(extension_.get(), nullptr));
  std::u16string error;
  EXPECT_TRUE(MustRemainEnabled(extension_.get(), &error));
  EXPECT_FALSE(error.empty());

  CreateExtension(ManifestLocation::kInternal);
  error.clear();
  EXPECT_FALSE(MustRemainEnabled(extension_.get(), nullptr));
  EXPECT_FALSE(MustRemainEnabled(extension_.get(), &error));
  EXPECT_TRUE(error.empty());
}

#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS)
class ExtensionManagementDesktopAndroidTest : public testing::Test {
 public:
  ExtensionManagementDesktopAndroidTest() = default;
  ExtensionManagementDesktopAndroidTest(
      const ExtensionManagementDesktopAndroidTest&) = delete;
  ExtensionManagementDesktopAndroidTest& operator=(
      const ExtensionManagementDesktopAndroidTest&) = delete;
  ~ExtensionManagementDesktopAndroidTest() override = default;

 private:
  content::BrowserTaskEnvironment task_environment_;
};

// Tests that kEnableExtensionsForCorpDesktopAndroid enables extensions for corp
// accounts.
TEST_F(ExtensionManagementDesktopAndroidTest, FeatureFlagOn) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(
      extensions_features::kEnableExtensionsForCorpDesktopAndroid);

  // Build a profile for a corp dogfood user.
  TestingProfile::Builder builder;
  builder.SetProfileName("sundar@google.com");
  std::unique_ptr<TestingProfile> profile = builder.Build();

  // Use that profile to initialize an ExtensionManagement instance.
  ExtensionManagement management(profile.get());

  // Extensions should be allowed because of the feature flag.
  EXPECT_TRUE(management.ExtensionsEnabledForDesktopAndroid());
}

// Tests that with kEnableExtensionsForCorpDesktopAndroid off, extensions are
// still disabled for corp accounts.
TEST_F(ExtensionManagementDesktopAndroidTest, FeatureFlagOff) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndDisableFeature(
      extensions_features::kEnableExtensionsForCorpDesktopAndroid);

  // Build a profile for a corp dogfood user.
  TestingProfile::Builder builder;
  builder.SetProfileName("sundar@google.com");
  std::unique_ptr<TestingProfile> profile = builder.Build();

  // Use that profile to initialize an ExtensionManagement instance.
  ExtensionManagement management(profile.get());

  // Extensions are blocked because this is a corp dogfood user.
  EXPECT_FALSE(management.ExtensionsEnabledForDesktopAndroid());
}

#endif  // BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS)

}  // namespace extensions
