diff options
author | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-11 14:56:36 +0000 |
---|---|---|
committer | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-11 14:56:36 +0000 |
commit | 306a2bd6e1bdabbe0cb5a70e17fe9a3eee08b5f9 (patch) | |
tree | d4e2239ea87c5552c19a7cd33f2af8d76473a603 /chrome | |
parent | 1bf88f540099cb145757a3572dbab90faff9bf1e (diff) | |
download | chromium_src-306a2bd6e1bdabbe0cb5a70e17fe9a3eee08b5f9.zip chromium_src-306a2bd6e1bdabbe0cb5a70e17fe9a3eee08b5f9.tar.gz chromium_src-306a2bd6e1bdabbe0cb5a70e17fe9a3eee08b5f9.tar.bz2 |
Implement admin control (by policy) over which extensions the user can install and run. Currently we intercept in two locations:
1) When the user tries to install an extension (includes error message).
2) Every time the browser starts up and the currently installed extensions are loaded (silently skips the extension).
I implemented a whitelist and a blacklist approach, calling it a allow/deny list to not clash with the global blacklist we have for extensions. A blacklist of '*' means all extensions are blacklisted. If an extension is on the blacklist it cannot be installed/loaded, unless it also appears on the whitelist.
I also fleshed out the LIST_TYPE support for policy values, so that we don't have to use comma separated REG_SZ values for lists and can instead use ADM support for listboxes.
BUG=47085
TEST=ExtensionsServiceTest.BlacklistedByPolicyWillNotInstall, ConfigurationPolicyProviderWinTest.TestExtensionInstall*
Review URL: http://codereview.chromium.org/3014053
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55727 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/extensions/crx_installer.cc | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.cc | 46 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_prefs.h | 5 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 31 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_pref_store.cc | 4 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_provider.cc | 4 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_provider_win.cc | 105 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_provider_win.h | 19 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_provider_win_unittest.cc | 106 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_store.h | 4 | ||||
-rw-r--r-- | chrome/common/extensions/extension_constants.cc | 4 | ||||
-rw-r--r-- | chrome/common/extensions/extension_constants.h | 3 | ||||
-rw-r--r-- | chrome/common/policy_constants.cc | 2 | ||||
-rw-r--r-- | chrome/common/policy_constants.h | 2 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 8 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 4 |
17 files changed, 304 insertions, 53 deletions
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index ddc1404..b24a02d 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -201,6 +201,12 @@ void CrxInstaller::ConfirmInstall() { return; } + if (!frontend_->extension_prefs()->IsExtensionAllowedByPolicy( + extension_->id())) { + ReportFailureFromUIThread("This extension is blacklisted by admin policy."); + return; + } + GURL overlapping_url; Extension* overlapping_extension = frontend_->GetExtensionByOverlappingWebExtent(extension_->web_extent()); diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc index 1f4f3e8..f8dbc59 100644 --- a/chrome/browser/extensions/extension_prefs.cc +++ b/chrome/browser/extensions/extension_prefs.cc @@ -45,6 +45,13 @@ const wchar_t kExtensionDidEscalatePermissions[] = L"install_warning_on_enable"; // object read from the Preferences file, containing a list of toolstrip URLs. const wchar_t kExtensionShelf[] = L"extensions.shelf"; +// A preference that tracks admin policy regarding which extensions the user +// can and can not install. This preference is a list object, containing +// strings that list extension ids. Denylist can contain "*" meaning all +// extensions. +const wchar_t kExtensionInstallAllowList[] = L"extensions.install.allowlist"; +const wchar_t kExtensionInstallDenyList[] = L"extensions.install.denylist"; + // A preference that tracks browser action toolbar configuration. This is a list // object stored in the Preferences file. The extensions are stored by ID. const wchar_t kExtensionToolbar[] = L"extensions.toolbar"; @@ -233,6 +240,41 @@ bool ExtensionPrefs::IsExtensionBlacklisted(const std::string& extension_id) { return ReadExtensionPrefBoolean(extension_id, kPrefBlacklist); } +bool ExtensionPrefs::IsExtensionAllowedByPolicy( + const std::string& extension_id) { + std::string string_value; + + // Check the whitelist first. + const ListValue* whitelist = prefs_->GetList(kExtensionInstallAllowList); + if (whitelist) { + for (ListValue::const_iterator it = whitelist->begin(); + it != whitelist->end(); ++it) { + if (!(*it)->GetAsString(&string_value)) + LOG(WARNING) << "Failed to read whitelist string."; + else if (string_value == extension_id) + return true; + } + } + + // Then check the blacklist (the admin blacklist, not the Google blacklist). + const ListValue* blacklist = prefs_->GetList(kExtensionInstallDenyList); + if (blacklist) { + for (ListValue::const_iterator it = blacklist->begin(); + it != blacklist->end(); ++it) { + if (!(*it)->GetAsString(&string_value)) { + LOG(WARNING) << "Failed to read blacklist string."; + } else { + if (string_value == "*") + return false; // Only whitelisted extensions are allowed. + if (string_value == extension_id) + return false; + } + } + } + + return true; +} + bool ExtensionPrefs::DidExtensionEscalatePermissions( const std::string& extension_id) { return ReadExtensionPrefBoolean(extension_id, @@ -247,7 +289,7 @@ void ExtensionPrefs::SetDidExtensionEscalatePermissions( } void ExtensionPrefs::UpdateBlacklist( - const std::set<std::string>& blacklist_set) { + const std::set<std::string>& blacklist_set) { std::vector<std::string> remove_pref_ids; std::set<std::string> used_id_set; const DictionaryValue* extensions = prefs_->GetDictionary(kExtensionsPref); @@ -785,4 +827,6 @@ void ExtensionPrefs::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterListPref(kExtensionToolbar); prefs->RegisterIntegerPref(prefs::kExtensionToolbarSize, -1); prefs->RegisterDictionaryPref(kExtensionsBlacklistUpdate); + prefs->RegisterListPref(kExtensionInstallAllowList); + prefs->RegisterListPref(kExtensionInstallDenyList); } diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h index 3ab50ee..f61cdc1 100644 --- a/chrome/browser/extensions/extension_prefs.h +++ b/chrome/browser/extensions/extension_prefs.h @@ -90,6 +90,10 @@ class ExtensionPrefs { // Based on extension id, checks prefs to see if it is blacklisted. bool IsExtensionBlacklisted(const std::string& id); + // Is the extension with |extension_id| allowed by policy (checking both + // whitelist and blacklist). + bool IsExtensionAllowedByPolicy(const std::string& extension_id); + // Returns the last value set via SetLastPingDay. If there isn't such a // pref, the returned Time will return true for is_null(). base::Time LastPingDay(const std::string& extension_id) const; @@ -149,7 +153,6 @@ class ExtensionPrefs { PrefService* pref_service() const { return prefs_; } private: - // Converts absolute paths in the pref to paths relative to the // install_directory_. void MakePathsRelative(); diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index dcfc481..fde71aa 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -567,7 +567,9 @@ void ExtensionsService::LoadInstalledExtension(const ExtensionInfo& info, bool write_to_prefs) { std::string error; Extension* extension = NULL; - if (info.extension_manifest.get()) { + if (!extension_prefs_->IsExtensionAllowedByPolicy(info.extension_id)) { + error = errors::kDisabledByPolicy; + } else if (info.extension_manifest.get()) { scoped_ptr<Extension> tmp(new Extension(info.extension_path)); bool require_key = info.extension_location != Extension::LOAD; if (tmp->InitFromValue(*info.extension_manifest, require_key, &error)) diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 08f8c22..012e8d6 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -1523,6 +1523,37 @@ TEST_F(ExtensionsServiceTest, WillNotLoadBlacklistedExtensionsFromDirectory) { EXPECT_NE(std::string(good0), loaded_[1]->id()); } +// Will not install extension blacklisted by policy. +TEST_F(ExtensionsServiceTest, BlacklistedByPolicyWillNotInstall) { + InitializeEmptyExtensionsService(); + + ListValue* whitelist = prefs_->GetMutableList( + L"extensions.install.allowlist"); + ListValue* blacklist = prefs_->GetMutableList( + L"extensions.install.denylist"); + ASSERT_TRUE(whitelist != NULL && blacklist != NULL); + + // Blacklist everything. + blacklist->Append(Value::CreateStringValue("*")); + + // Blacklist prevents us from installing good_crx. + FilePath extensions_path; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_path)); + extensions_path = extensions_path.AppendASCII("extensions"); + FilePath path = extensions_path.AppendASCII("good.crx"); + service_->InstallExtension(path); + loop_.RunAllPending(); + EXPECT_EQ(0u, service_->extensions()->size()); + + // Now whitelist this particular extension. + whitelist->Append(Value::CreateStringValue(good_crx)); + + // Ensure we can now install good_crx. + service_->InstallExtension(path); + loop_.RunAllPending(); + EXPECT_EQ(1u, service_->extensions()->size()); +} + // Tests disabling extensions TEST_F(ExtensionsServiceTest, DisableExtension) { InitializeEmptyExtensionsService(); diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc index b6fd1e6..744ee70 100644 --- a/chrome/browser/policy/configuration_policy_pref_store.cc +++ b/chrome/browser/policy/configuration_policy_pref_store.cc @@ -43,6 +43,10 @@ const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry prefs::kMetricsReportingEnabled }, { Value::TYPE_STRING, kPolicyApplicationLocale, prefs::kApplicationLocale}, + { Value::TYPE_LIST, kPolicyExtensionInstallAllowList, + prefs::kExtensionInstallAllowList}, + { Value::TYPE_LIST, kPolicyExtensionInstallDenyList, + prefs::kExtensionInstallDenyList}, }; const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry diff --git a/chrome/browser/policy/configuration_policy_provider.cc b/chrome/browser/policy/configuration_policy_provider.cc index 99c61cf..748c3a2 100644 --- a/chrome/browser/policy/configuration_policy_provider.cc +++ b/chrome/browser/policy/configuration_policy_provider.cc @@ -50,6 +50,10 @@ const InternalPolicyValueMapEntry kPolicyValueMap[] = { Value::TYPE_STRING, policy::key::kApplicationLocaleValue }, { ConfigurationPolicyStore::kPolicySyncDisabled, Value::TYPE_BOOLEAN, policy::key::kSyncDisabled }, + { ConfigurationPolicyStore::kPolicyExtensionInstallAllowList, + Value::TYPE_LIST, policy::key::kExtensionInstallAllowList }, + { ConfigurationPolicyStore::kPolicyExtensionInstallDenyList, + Value::TYPE_LIST, policy::key::kExtensionInstallDenyList }, }; } // namespace diff --git a/chrome/browser/policy/configuration_policy_provider_win.cc b/chrome/browser/policy/configuration_policy_provider_win.cc index 4085b14..eb6d92f 100644 --- a/chrome/browser/policy/configuration_policy_provider_win.cc +++ b/chrome/browser/policy/configuration_policy_provider_win.cc @@ -12,7 +12,9 @@ #include "base/object_watcher.h" #include "base/registry.h" #include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" #include "base/string_piece.h" +#include "base/string_util.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -56,53 +58,66 @@ ConfigurationPolicyProviderWin::ConfigurationPolicyProviderWin() { } bool ConfigurationPolicyProviderWin::GetRegistryPolicyString( - const wchar_t* value_name, string16* result) { + const string16& name, int index, string16* result) { DWORD value_size = 0; DWORD key_type = 0; scoped_array<uint8> buffer; - RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, policy::kRegistrySubKey); - if (hkcu_policy_key.ReadValue(value_name, 0, &value_size, &key_type)) { - if (key_type != REG_SZ) - return false; - // According to the Microsoft documentation, the string - // buffer may not be explicitly 0-terminated. Allocate a - // slightly larger buffer and prefill to zeros to guarantee - // the 0-termination. - buffer.reset(new uint8[value_size + 2]); - memset(buffer.get(), 0, value_size + 2); - hkcu_policy_key.ReadValue(value_name, buffer.get(), &value_size); - } else { - RegKey hklm_policy_key(HKEY_CURRENT_USER, policy::kRegistrySubKey); - if (hklm_policy_key.ReadValue(value_name, 0, &value_size, &key_type)) { - if (key_type != REG_SZ) - return false; - // According to the Microsoft documentation, the string - // buffer may not be explicitly 0-terminated. Allocate a - // slightly larger buffer and prefill to zeros to guarantee - // the 0-termination. - buffer.reset(new uint8[value_size + 2]); - memset(buffer.get(), 0, value_size + 2); - hklm_policy_key.ReadValue(value_name, buffer.get(), &value_size); - } else { + RegKey policy_key; + string16 location = string16(policy::kRegistrySubKey); + string16 value_name = name; + + if (index > 0) { + // This is a list value, treat |name| as a subkey. + location += ASCIIToUTF16("\\") + name; + value_name = base::IntToString16(index); + } + + // First try the global policy. + if (!policy_key.Open(HKEY_LOCAL_MACHINE, location.c_str()) || + !policy_key.ReadValue(value_name.c_str(), 0, &value_size, &key_type)) { + policy_key.Close(); + // Fall back on user-specific policy. + if (!policy_key.Open(HKEY_CURRENT_USER, location.c_str()) || + !policy_key.ReadValue(value_name.c_str(), 0, &value_size, &key_type)) { return false; } } + if (key_type != REG_SZ) + return false; + + // According to the Microsoft documentation, the string + // buffer may not be explicitly 0-terminated. Allocate a + // slightly larger buffer and pre-fill to zeros to guarantee + // the 0-termination. + buffer.reset(new uint8[value_size + 2]); + memset(buffer.get(), 0, value_size + 2); + policy_key.ReadValue(value_name.c_str(), buffer.get(), &value_size); result->assign(reinterpret_cast<const wchar_t*>(buffer.get())); return true; } + +bool ConfigurationPolicyProviderWin::GetRegistryPolicyStringList( + const string16& key, ListValue* result) { + int index = 0; + string16 policy_string; + while (GetRegistryPolicyString(key, ++index, &policy_string)) + result->Append(Value::CreateStringValue(policy_string)); + return true; +} + bool ConfigurationPolicyProviderWin::GetRegistryPolicyBoolean( - const wchar_t* value_name, bool* result) { + const string16& value_name, bool* result) { DWORD value; RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, policy::kRegistrySubKey); - if (hkcu_policy_key.ReadValueDW(value_name, &value)) { + if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) { *result = value != 0; return true; } RegKey hklm_policy_key(HKEY_CURRENT_USER, policy::kRegistrySubKey); - if (hklm_policy_key.ReadValueDW(value_name, &value)) { + if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) { *result = value != 0; return true; } @@ -110,16 +125,16 @@ bool ConfigurationPolicyProviderWin::GetRegistryPolicyBoolean( } bool ConfigurationPolicyProviderWin::GetRegistryPolicyInteger( - const wchar_t* value_name, uint32* result) { + const string16& value_name, uint32* result) { DWORD value; RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, policy::kRegistrySubKey); - if (hkcu_policy_key.ReadValueDW(value_name, &value)) { + if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) { *result = value; return true; } RegKey hklm_policy_key(HKEY_CURRENT_USER, policy::kRegistrySubKey); - if (hklm_policy_key.ReadValueDW(value_name, &value)) { + if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) { *result = value; return true; } @@ -133,29 +148,37 @@ bool ConfigurationPolicyProviderWin::Provide( for (PolicyValueMap::const_iterator current = mapping->begin(); current != mapping->end(); ++current) { std::wstring name = UTF8ToWide(current->name); - std::wstring string_value; - uint32 int_value; - bool bool_value; switch (current->value_type) { - case Value::TYPE_STRING: - if (GetRegistryPolicyString(name.c_str(), &string_value)) { - store->Apply( - current->policy_type, - Value::CreateStringValue(string_value)); + case Value::TYPE_STRING: { + std::wstring string_value; + if (GetRegistryPolicyString(name.c_str(), -1, &string_value)) { + store->Apply(current->policy_type, + Value::CreateStringValue(string_value)); } break; - case Value::TYPE_BOOLEAN: + } + case Value::TYPE_LIST: { + scoped_ptr<ListValue> list_value(new ListValue); + if (GetRegistryPolicyStringList(name.c_str(), list_value.get())) + store->Apply(current->policy_type, list_value.release()); + break; + } + case Value::TYPE_BOOLEAN: { + bool bool_value; if (GetRegistryPolicyBoolean(name.c_str(), &bool_value)) { store->Apply(current->policy_type, Value::CreateBooleanValue(bool_value)); } break; - case Value::TYPE_INTEGER: + } + case Value::TYPE_INTEGER: { + uint32 int_value; if (GetRegistryPolicyInteger(name.c_str(), &int_value)) { store->Apply(current->policy_type, Value::CreateIntegerValue(int_value)); } break; + } default: NOTREACHED(); return false; diff --git a/chrome/browser/policy/configuration_policy_provider_win.h b/chrome/browser/policy/configuration_policy_provider_win.h index e2ebbdb..e197e9d 100644 --- a/chrome/browser/policy/configuration_policy_provider_win.h +++ b/chrome/browser/policy/configuration_policy_provider_win.h @@ -51,11 +51,22 @@ class ConfigurationPolicyProviderWin : public ConfigurationPolicyProvider { private: scoped_ptr<GroupPolicyChangeWatcher> watcher_; - // Methods to perfrom type-specific policy lookups in the registry. + // Methods to perform type-specific policy lookups in the registry. // HKLM is checked first, then HKCU. - bool GetRegistryPolicyString(const wchar_t* value_name, string16* result); - bool GetRegistryPolicyBoolean(const wchar_t* value_name, bool* result); - bool GetRegistryPolicyInteger(const wchar_t* value_name, uint32* result); + + // Reads a string registry value |name| and puts the resulting string in + // |result|. If |index| > 0, |name| is the name of a subkey and the value + // read is named |index|. Note: A subkey is used for lists to work around + // a problem with the Group Policy Editor, where one list value overwrites + // another if they appear under the same key (even if they have different + // names). + bool GetRegistryPolicyString(const string16& name, + int index, + string16* result); + // Gets a list value contained under |key| one level below the policy root. + bool GetRegistryPolicyStringList(const string16& key, ListValue* result); + bool GetRegistryPolicyBoolean(const string16& value_name, bool* result); + bool GetRegistryPolicyInteger(const string16& value_name, uint32* result); }; #endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_WIN_H_ diff --git a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc index 221ef83..1614a59 100644 --- a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc +++ b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc @@ -10,6 +10,7 @@ #include "base/registry.h" #include "base/scoped_ptr.h" #include "base/stl_util-inl.h" +#include "base/string_number_conversions.h" #include "base/string_piece.h" #include "base/utf_string_conversions.h" #include "chrome/browser/policy/configuration_policy_provider_win.h" @@ -40,6 +41,8 @@ class TestConfigurationPolicyProviderWin void SetBooleanPolicy(ConfigurationPolicyStore::PolicyType type, HKEY hive, bool value); void SetCookiesMode(HKEY hive, uint32 value); + void AllowExtension(HKEY hive, int index, const wchar_t* id); + void DenyExtension(HKEY hive, int index, const wchar_t* id); typedef std::vector<PolicyValueMapEntry> PolicyValueMap; static const PolicyValueMap* PolicyValueMapping() { @@ -79,6 +82,26 @@ void TestConfigurationPolicyProviderWin::SetHomepageRegistryValueWrongType( 5)); } +void TestConfigurationPolicyProviderWin::AllowExtension(HKEY hive, + int index, + const wchar_t* id) { + RegKey key(hive, + (string16(policy::kRegistrySubKey) + ASCIIToUTF16("\\") + + ASCIIToUTF16(policy::key::kExtensionInstallAllowList)).c_str(), + KEY_ALL_ACCESS); + EXPECT_TRUE(key.WriteValue(base::IntToString16(index).c_str(), id)); +} + +void TestConfigurationPolicyProviderWin::DenyExtension(HKEY hive, + int index, + const wchar_t* id) { + RegKey key(hive, + (string16(policy::kRegistrySubKey) + ASCIIToUTF16("\\") + + ASCIIToUTF16(policy::key::kExtensionInstallDenyList)).c_str(), + KEY_ALL_ACCESS); + EXPECT_TRUE(key.WriteValue(base::IntToString16(index).c_str(), id)); +} + void TestConfigurationPolicyProviderWin::SetBooleanPolicy( ConfigurationPolicyStore::PolicyType type, HKEY hive, @@ -284,6 +307,89 @@ TEST_F(ConfigurationPolicyProviderWinTest, TestBooleanPolicy(ConfigurationPolicyStore::kPolicyHomepageIsNewTabPage); } +TEST_F(ConfigurationPolicyProviderWinTest, TestExtensionInstallWhitelistHKCU) { + MockConfigurationPolicyStore store; + TestConfigurationPolicyProviderWin provider; + provider.AllowExtension(HKEY_CURRENT_USER, 1, L"abc"); + provider.AllowExtension(HKEY_CURRENT_USER, 2, L"def"); + provider.Provide(&store); + + const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map()); + MockConfigurationPolicyStore::PolicyMap::const_iterator i = + map.find(ConfigurationPolicyStore::kPolicyExtensionInstallAllowList); + ASSERT_TRUE(i != map.end()); + ASSERT_TRUE(i->second->IsType(Value::TYPE_LIST)); + ListValue* value = reinterpret_cast<ListValue*>(i->second); + std::string str_value; + EXPECT_EQ(2, value->GetSize()); + EXPECT_TRUE(value->GetString(0, &str_value)); + EXPECT_STREQ("abc", str_value.c_str()); + EXPECT_TRUE(value->GetString(1, &str_value)); + EXPECT_STREQ("def", str_value.c_str()); +} + +TEST_F(ConfigurationPolicyProviderWinTest, TestExtensionInstallWhitelistHKLM) { + MockConfigurationPolicyStore store; + TestConfigurationPolicyProviderWin provider; + provider.AllowExtension(HKEY_LOCAL_MACHINE, 1, L"abc"); + provider.AllowExtension(HKEY_LOCAL_MACHINE, 2, L"def"); + provider.Provide(&store); + + const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map()); + MockConfigurationPolicyStore::PolicyMap::const_iterator i = + map.find(ConfigurationPolicyStore::kPolicyExtensionInstallAllowList); + ASSERT_TRUE(i != map.end()); + ASSERT_TRUE(i->second->IsType(Value::TYPE_LIST)); + ListValue* value = reinterpret_cast<ListValue*>(i->second); + std::string str_value; + EXPECT_EQ(2, value->GetSize()); + EXPECT_TRUE(value->GetString(0, &str_value)); + EXPECT_STREQ("abc", str_value.c_str()); + EXPECT_TRUE(value->GetString(1, &str_value)); + EXPECT_STREQ("def", str_value.c_str()); +} + +TEST_F(ConfigurationPolicyProviderWinTest, + TestExtensionInstallWhitelistHKLMOverHKCU) { + MockConfigurationPolicyStore store; + TestConfigurationPolicyProviderWin provider; + provider.AllowExtension(HKEY_CURRENT_USER, 1, L"abc"); + provider.AllowExtension(HKEY_LOCAL_MACHINE, 1, L"def"); + provider.Provide(&store); + + const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map()); + MockConfigurationPolicyStore::PolicyMap::const_iterator i = + map.find(ConfigurationPolicyStore::kPolicyExtensionInstallAllowList); + ASSERT_TRUE(i != map.end()); + ASSERT_TRUE(i->second->IsType(Value::TYPE_LIST)); + ListValue* value = reinterpret_cast<ListValue*>(i->second); + std::string str_value; + EXPECT_EQ(1, value->GetSize()); + EXPECT_TRUE(value->GetString(0, &str_value)); + EXPECT_STREQ("def", str_value.c_str()); +} + +TEST_F(ConfigurationPolicyProviderWinTest, TestExtensionInstallBlacklistHKLM) { + MockConfigurationPolicyStore store; + TestConfigurationPolicyProviderWin provider; + provider.DenyExtension(HKEY_LOCAL_MACHINE, 1, L"abc"); + provider.DenyExtension(HKEY_LOCAL_MACHINE, 2, L"def"); + provider.Provide(&store); + + const MockConfigurationPolicyStore::PolicyMap& map(store.policy_map()); + MockConfigurationPolicyStore::PolicyMap::const_iterator i = + map.find(ConfigurationPolicyStore::kPolicyExtensionInstallDenyList); + ASSERT_TRUE(i != map.end()); + ASSERT_TRUE(i->second->IsType(Value::TYPE_LIST)); + ListValue* value = reinterpret_cast<ListValue*>(i->second); + std::string str_value; + EXPECT_EQ(2, value->GetSize()); + EXPECT_TRUE(value->GetString(0, &str_value)); + EXPECT_STREQ("abc", str_value.c_str()); + EXPECT_TRUE(value->GetString(1, &str_value)); + EXPECT_STREQ("def", str_value.c_str()); +} + TEST_F(ConfigurationPolicyProviderWinTest, TestPolicyAlternateErrorPagesEnabled) { TestBooleanPolicy( diff --git a/chrome/browser/policy/configuration_policy_store.h b/chrome/browser/policy/configuration_policy_store.h index 80d9a56..4f876fe 100644 --- a/chrome/browser/policy/configuration_policy_store.h +++ b/chrome/browser/policy/configuration_policy_store.h @@ -32,6 +32,8 @@ class ConfigurationPolicyStore { kPolicyPasswordManagerEnabled, kPolicySyncDisabled, kPolicyApplicationLocale, + kPolicyExtensionInstallAllowList, + kPolicyExtensionInstallDenyList, // A policy for allowing administrators to forcibly disable // specific plugins. This policy is a comma-separated list of @@ -45,7 +47,7 @@ class ConfigurationPolicyStore { static const int kPolicyManuallyConfiguredProxyMode = 2; static const int kPolicyUseSystemProxyMode = 3; - // A |ConfigurationPolicyProvider| specifes the value of a policy setting + // A |ConfigurationPolicyProvider| specifies the value of a policy setting // through a call to |Apply|. // The configuration policy pref store takes over the ownership of |value|. virtual void Apply(PolicyType policy, Value* value) = 0; diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc index 4001c9b..ce4d74f 100644 --- a/chrome/common/extensions/extension_constants.cc +++ b/chrome/common/extensions/extension_constants.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -92,6 +92,8 @@ const char* kCannotScriptGallery = "The extensions gallery cannot be scripted."; const char* kChromeVersionTooLow = "This extension requires * version * or greater."; +const char* kDisabledByPolicy = + "This extension has been disabled by your administrator."; const char* kDevToolsExperimental = "You must request the 'experimental' permission in order to use the" " DevTools API."; diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index 4cd9779..bc85b3c 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -101,6 +101,7 @@ namespace extension_manifest_errors { extern const char* kInvalidCssList; extern const char* kInvalidDefaultLocale; extern const char* kInvalidDescription; + extern const char* kDisabledByPolicy; extern const char* kInvalidDevToolsPage; extern const char* kInvalidGlob; extern const char* kInvalidGlobList; diff --git a/chrome/common/policy_constants.cc b/chrome/common/policy_constants.cc index 7c0b5b4..8f56108 100644 --- a/chrome/common/policy_constants.cc +++ b/chrome/common/policy_constants.cc @@ -31,6 +31,8 @@ const char kPasswordManagerEnabled[] = "PasswordManagerEnabled"; const char kDisabledPluginsList[] = "DisabledPluginsList"; const char kApplicationLocaleValue[] = "ApplicationLocaleValue"; const char kSyncDisabled[] = "SyncDisabled"; +const char kExtensionInstallAllowList[] = "ExtensionInstallWhitelist"; +const char kExtensionInstallDenyList[] = "ExtensionInstallBlacklist"; } // namespace key diff --git a/chrome/common/policy_constants.h b/chrome/common/policy_constants.h index 37107db..591a9f1 100644 --- a/chrome/common/policy_constants.h +++ b/chrome/common/policy_constants.h @@ -33,6 +33,8 @@ extern const char kPasswordManagerEnabled[]; extern const char kDisabledPluginsList[]; extern const char kApplicationLocaleValue[]; extern const char kSyncDisabled[]; +extern const char kExtensionInstallAllowList[]; +extern const char kExtensionInstallDenyList[]; } // namespace key diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index cd47625..4a3d79c 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -814,6 +814,14 @@ const char kShowExtensionShelf[] = "extensions.shelf.show_on_all_tabs"; const char kBrowserActionContainerWidth[] = "extensions.browseractions.container.width"; +// A whitelist of extension the user can install. This is controlled by the +// administrator. +const char kExtensionInstallAllowList[] = "extensions.install.allowlist"; +// A blacklist, containing extensions the user cannot install. This is +// controlled by the administrator. This list should not be confused with +// the extension blacklist, which is Google controlled. +const char kExtensionInstallDenyList[] = "extensions.install.denylist"; + // Time of the last, and next scheduled, extensions auto-update checks. const char kLastExtensionsUpdateCheck[] = "extensions.autoupdate.last_check"; const char kNextExtensionsUpdateCheck[] = "extensions.autoupdate.next_check"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 61e87bf..1e20e76 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -299,8 +299,8 @@ extern const char kDisableExtensions[]; extern const char kShowExtensionShelf[]; extern const char kBrowserActionContainerWidth[]; -extern const char kLastExtensionsUpdateCheck[]; -extern const char kNextExtensionsUpdateCheck[]; +extern const char kExtensionInstallAllowList[]; +extern const char kExtensionInstallDenyList[]; extern const char kExtensionBlacklistUpdateVersion[]; |