| // 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 <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/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/standard_management_policy_provider.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "extensions/browser/extension_prefs.h" |
| #include "extensions/browser/pref_names.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" |
| |
| 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(); |
| } |
| |
| ExtensionManagement::InstallationMode GetInstallationModeById( |
| const std::string& id) { |
| return GetInstallationMode(id, kNonExistingUpdateUrl); |
| } |
| |
| ExtensionManagement::InstallationMode 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 == |
| ExtensionManagement::INSTALLATION_FORCED) || |
| (iter->second->installation_mode == |
| ExtensionManagement::INSTALLATION_RECOMMENDED)); |
| 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(const base::StringPiece 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. |
| ExtensionManagement::InstallationMode 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::string 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) { |
| scoped_refptr<const Extension> extension = |
| CreateExtensionHelper(ManifestLocation::kExternalPolicy, "0.1", id, |
| kExampleUpdateUrl, Extension::FROM_WEBSTORE); |
| 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); |
| } |
| |
| 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() {} |
| ~ExtensionAdminPolicyTest() override {} |
| |
| 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::string 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), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| } |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| } |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| CheckAutomaticallyInstalledUpdateUrl(kTargetExtension, kExampleUpdateUrl); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| } |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension2), |
| ExtensionManagement::INSTALLATION_FORCED); |
| |
| SetExampleDictPref(kExampleDictPreferenceWithoutInstallationMode); |
| |
| // Verify that the update URL is overridden for kTargetExtension. |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension), |
| ExtensionManagement::INSTALLATION_FORCED); |
| 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| |
| SetExampleDictPref(kExampleDictPreferenceWithoutInstallationMode); |
| |
| // Verify that the update URL is not overridden for kTargetExtension as it is |
| // not listed in |kInstallForcelist| pref. |
| EXPECT_NE(GetInstallationModeById(kTargetExtension), |
| ExtensionManagement::INSTALLATION_FORCED); |
| 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension2), |
| ExtensionManagement::INSTALLATION_FORCED); |
| |
| 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| 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), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| |
| 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension2), |
| ExtensionManagement::INSTALLATION_FORCED); |
| CheckAutomaticallyInstalledUpdateUrl(kTargetExtension2, kExampleUpdateUrl); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension3), |
| ExtensionManagement::INSTALLATION_RECOMMENDED); |
| CheckAutomaticallyInstalledUpdateUrl(kTargetExtension3, kExampleUpdateUrl); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| EXPECT_EQ(GetInstallationModeByUpdateUrl(kExampleUpdateUrl), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension6), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension7), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension8), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationMode(kTargetExtension2, kExampleUpdateUrl), |
| ExtensionManagement::INSTALLATION_FORCED); |
| EXPECT_EQ(GetInstallationMode(kTargetExtension3, kExampleUpdateUrl), |
| ExtensionManagement::INSTALLATION_RECOMMENDED); |
| } |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension2), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| } |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kTargetExtension2), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_BLOCKED); |
| } |
| |
| // 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), |
| ExtensionManagement::INSTALLATION_FORCED); |
| CheckAutomaticallyInstalledUpdateUrl(kTargetExtension, kExampleUpdateUrl); |
| EXPECT_EQ(GetInstallationModeById(kNonExistingExtension), |
| ExtensionManagement::INSTALLATION_ALLOWED); |
| } |
| |
| // 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(ExtensionManagement::INSTALLATION_BLOCKED, |
| GetInstallationModeById(kTargetExtension)); |
| // However, it will be overridden by ExtensionSettings |
| SetExampleDictPref(R"({ |
| "*": { |
| "installation_mode": "removed", |
| } |
| })"); |
| EXPECT_EQ(ExtensionManagement::INSTALLATION_REMOVED, |
| 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)); |
| } |
| |
| 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)); |
| } |
| |
| 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)); |
| } |
| |
| 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)); |
| |
| 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)); |
| } |
| |
| 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)); |
| } |
| |
| // 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); |
| } |
| |
| // 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()); |
| } |
| |
| } // namespace extensions |