| // 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 |