diff options
author | danno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-15 16:04:49 +0000 |
---|---|---|
committer | danno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-15 16:04:49 +0000 |
commit | e541d9fb2e77ff788bf2353331b34ba841b99ff5 (patch) | |
tree | 3aeb2e2a599c4a73c9b068c4f98c9258a1a68c5f | |
parent | facc6ada0300c8e9a67b0cf283257a2c70fa15c2 (diff) | |
download | chromium_src-e541d9fb2e77ff788bf2353331b34ba841b99ff5.zip chromium_src-e541d9fb2e77ff788bf2353331b34ba841b99ff5.tar.gz chromium_src-e541d9fb2e77ff788bf2353331b34ba841b99ff5.tar.bz2 |
Implement disabling of plugins through policy
TEST=manual testing of plugins page, ConfigurationPolicyPrefStoreTest*
BUG=45856
Review URL: http://codereview.chromium.org/2833034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52487 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 6 | ||||
-rw-r--r-- | chrome/app/policy/mac/app-Manifest.plist | 18 | ||||
-rw-r--r-- | chrome/app/policy/windows/adm/en-US/chrome.adm | 18 | ||||
-rw-r--r-- | chrome/app/policy/windows/admx/chrome.admx | 17 | ||||
-rw-r--r-- | chrome/app/policy/windows/admx/en-US/chrome.adml | 10 | ||||
-rw-r--r-- | chrome/browser/configuration_policy_pref_store.cc | 41 | ||||
-rw-r--r-- | chrome/browser/configuration_policy_pref_store.h | 5 | ||||
-rw-r--r-- | chrome/browser/configuration_policy_pref_store_unittest.cc | 73 | ||||
-rw-r--r-- | chrome/browser/configuration_policy_provider.cc | 2 | ||||
-rw-r--r-- | chrome/browser/configuration_policy_store.h | 8 | ||||
-rw-r--r-- | chrome/browser/dom_ui/plugins_ui.cc | 16 | ||||
-rw-r--r-- | chrome/browser/plugin_updater.cc | 45 | ||||
-rw-r--r-- | chrome/browser/plugin_updater.h | 1 | ||||
-rw-r--r-- | chrome/browser/resources/plugins.html | 83 | ||||
-rw-r--r-- | chrome/common/plugin_group.cc | 54 | ||||
-rw-r--r-- | chrome/common/plugin_group.h | 14 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 3 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 1 |
18 files changed, 372 insertions, 43 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 36beb3b..6c423a8 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3680,6 +3680,12 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_PLUGINS_DISABLED_PLUGIN" desc="Text that signifies that the plug-in is currently disabled."> (Disabled) </message> + <message name="IDS_PLUGINS_DISABLED_BY_POLICY_PLUGIN" desc="Text that signifies that the plug-in is currently disabled by a policy set by an administrator."> + (Disabled by centrally-administered policy) + </message> + <message name="IDS_PLUGINS_CANNOT_ENABLE_DUE_TO_POLICY" desc="Text that indicates a plugin cannot be enabled because it has been disabled by a policy set by an administrator."> + Cannot enable plugins that are disabled by policy + </message> <message name="IDS_PLUGINS_DISABLED_RUNNING_PLUGIN" desc="Text that signifies that the plug-in is disabled but still running, and that it will be fully disabled after a browser restart."> (Still running; will be fully disabled after browser restart) </message> diff --git a/chrome/app/policy/mac/app-Manifest.plist b/chrome/app/policy/mac/app-Manifest.plist index 2e3a1ae..a6bc820 100644 --- a/chrome/app/policy/mac/app-Manifest.plist +++ b/chrome/app/policy/mac/app-Manifest.plist @@ -18,9 +18,9 @@ <key>pfm_name</key> <string>HomepageLocation</string> <key>pfm_description</key> - <string>The homepage URL.</string> - <key>pfm_title</key> <string>This policy setting specifies the location of the default home page for the user. Specify a URL here, or set to the New Tab Page. If the New Tab Page option is choosen, this will override a URL here.</string> + <key>pfm_title</key> + <string>The homepage URL.</string> <key>pfm_targets</key> <array> <string>user-managed</string> @@ -175,6 +175,20 @@ <key>pfm_type</key> <string>boolean</string> </dict> + <dict> + <key>pfm_name</key> + <string>DisabledPlugins</string> + <key>pfm_description</key> + <string>This policy specifies a list of plugins that are disabled. The policy value is a comma-separated list of the names of plugins to be disabled.</string> + <key>pfm_title</key> + <string>The list of disabled plugins.</string> + <key>pfm_targets</key> + <array> + <string>user-managed</string> + </array> + <key>pfm_type</key> + <string>string</string> + </dict> </array> </dict> </plist> diff --git a/chrome/app/policy/windows/adm/en-US/chrome.adm b/chrome/app/policy/windows/adm/en-US/chrome.adm index c302a75..f409aeb 100644 --- a/chrome/app/policy/windows/adm/en-US/chrome.adm +++ b/chrome/app/policy/windows/adm/en-US/chrome.adm @@ -83,6 +83,20 @@ CLASS MACHINE VALUEOFF NUMERIC 0 END POLICY + POLICY !!DisabledPlugins + #if version >= 4 + SUPPORTED !!SUPPORTED_WINXPSP2 + #endif + EXPLAIN !!DisabledPlugins_Explain + VALUENAME "DisabledPlugins" + VALUEON NUMERIC 1 + VALUEOFF NUMERIC 0 + + PART !!DisabledPluginsList EDITTEXT + VALUENAME "DisabledPluginsList" + END PART + END POLICY + POLICY !!Sync #if version >= 4 SUPPORTED !!SUPPORTED_WINXPSP2 @@ -178,6 +192,10 @@ and crash-related data to Google and prevents users from changing this setting.\ If you enable this setting, anonymous reporting of usage and crash-related data will be sent to Google.\n\n\ If you disable this setting, anonymous reporting of usage and crash-related data will never be sent to Google.\n\n\ If you enable or disable this setting, users cannot change or override this setting in Google Chrome." +DisabledPlugins="Specify a list of plugins that are disabled" +DisabledPlugins_Explain="Specifies a list of plugins that are disabled and prevents users from changing this setting.\n\n\ +value is a comma-separated list of the names of plugins to be disabled." +DisabledPluginsList="Comma-separated list of disabled plugins:" Sync="Disallow synchronization of data with Google" Sync_Explain="Disallows data synchronization using Google-hosted sync services and prevents users from changing this setting.\n\n\ If you enable this setting, users cannot change or override this setting in Google Chrome." diff --git a/chrome/app/policy/windows/admx/chrome.admx b/chrome/app/policy/windows/admx/chrome.admx index 1ccf04c..b85b631 100644 --- a/chrome/app/policy/windows/admx/chrome.admx +++ b/chrome/app/policy/windows/admx/chrome.admx @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?>
<policyDefinitions revision="1.0" schemaVersion="1.0">
<policyNamespaces>
- <target prefix="fullarmor" namespace="FullArmor.4dd057b3-7d4f-4b0e-b832-fd4cd2c92884" />
+ <target prefix="fullarmor" namespace="FullArmor.3cca6b27-3c82-4689-8f0b-4ab08f8341da" />
<using prefix="windows" namespace="Microsoft.Policies.Windows" />
</policyNamespaces>
<supersededAdm fileName="C:\Development\src\chrome\app\policy\windows\adm\en-US\chrome.adm" />
@@ -88,6 +88,19 @@ <decimal value="0" />
</disabledValue>
</policy>
+ <policy name="DisabledPlugins" class="Machine" displayName="$(string.DisabledPlugins)" explainText="$(string.DisabledPlugins_Explain)" presentation="$(presentation.DisabledPlugins)" key="Software\Policies\Google\Chrome" valueName="DisabledPlugins">
+ <parentCategory ref="googlechrome" />
+ <supportedOn ref="SUPPORTED_WINXPSP2" />
+ <enabledValue>
+ <decimal value="1" />
+ </enabledValue>
+ <disabledValue>
+ <decimal value="0" />
+ </disabledValue>
+ <elements>
+ <text id="DisabledPluginsList" valueName="DisabledPluginsList" />
+ </elements>
+ </policy>
<policy name="Sync" class="Machine" displayName="$(string.Sync)" explainText="$(string.Sync_Explain)" presentation="$(presentation.Sync)" key="Software\Policies\Google\Chrome" valueName="SyncDisabled">
<parentCategory ref="googlechrome" />
<supportedOn ref="SUPPORTED_WINXPSP2" />
@@ -124,4 +137,4 @@ </elements>
</policy>
</policies>
-</policyDefinitions>
+</policyDefinitions>
\ No newline at end of file diff --git a/chrome/app/policy/windows/admx/en-US/chrome.adml b/chrome/app/policy/windows/admx/en-US/chrome.adml index 116715b..28c58f4 100644 --- a/chrome/app/policy/windows/admx/en-US/chrome.adml +++ b/chrome/app/policy/windows/admx/en-US/chrome.adml @@ -73,6 +73,11 @@ If you enable this setting, anonymous reporting of usage and crash-related data If you disable this setting, anonymous reporting of usage and crash-related data will never be sent to Google.
If you enable or disable this setting, users cannot change or override this setting in Google Chrome.</string>
+ <string id="DisabledPlugins">Specify a list of plugins that are disabled</string>
+ <string id="DisabledPlugins_Explain">Specifies a list of plugins that are disabled and prevents users from changing this setting.
+
+value is a comma-separated list of the names of plugins to be disabled.</string>
+ <string id="DisabledPluginsList">Comma-separated list of disabled plugins:</string>
<string id="Sync">Disallow synchronization of data with Google</string>
<string id="Sync_Explain">Disallows data synchronization using Google-hosted sync services and prevents users from changing this setting.
@@ -92,6 +97,11 @@ If you enable this setting, users cannot change or override this setting in Goog <presentation id="DnsPrefetchingEnabled" />
<presentation id="SafeBrowsingEnabled" />
<presentation id="MetricsReportingEnabled" />
+ <presentation id="DisabledPlugins">
+ <textBox refId="DisabledPluginsList">
+ <label>Comma-separated list of disabled plugins:</label>
+ </textBox>
+ </presentation>
<presentation id="Sync" />
<presentation id="Proxy">
<dropdownList refId="ProxyServerMode">Choose how to specify proxy server settings:</dropdownList>
diff --git a/chrome/browser/configuration_policy_pref_store.cc b/chrome/browser/configuration_policy_pref_store.cc index 43c9caa..2479a67 100644 --- a/chrome/browser/configuration_policy_pref_store.cc +++ b/chrome/browser/configuration_policy_pref_store.cc @@ -6,6 +6,8 @@ #include "base/command_line.h" #include "base/logging.h" +#include "base/string16.h" +#include "base/string_util.h" #include "base/values.h" #include "chrome/browser/configuration_policy_provider.h" #include "chrome/common/chrome_switches.h" @@ -224,6 +226,41 @@ bool ConfigurationPolicyPrefStore::ApplyProxyPolicy(PolicyType policy, return result; } +bool ConfigurationPolicyPrefStore::ApplyPluginPolicy(PolicyType policy, + Value* value) { + if (policy == kPolicyDisabledPlugins) { + string16 plugin_list; + if (value->GetAsUTF16(&plugin_list)) { + std::vector<string16> plugin_names; + // Change commas into tabs so that we can change escaped + // tabs back into commas, leaving non-escaped commas as tabs + // that can be used for splitting the string. Note that plugin + // names must not contain backslashes, since a trailing backslash + // in a plugin name before a comma would get swallowed during the + // splitting. + std::replace(plugin_list.begin(), plugin_list.end(), L',', L'\t'); + ReplaceSubstringsAfterOffset(&plugin_list, 0, + ASCIIToUTF16("\\\t"), ASCIIToUTF16(",")); + SplitString(plugin_list, L'\t', &plugin_names); + bool added_plugin = false; + scoped_ptr<ListValue> list(new ListValue()); + for (std::vector<string16>::const_iterator i(plugin_names.begin()); + i != plugin_names.end(); ++i) { + if (!i->empty()) { + list->Append(Value::CreateStringValueFromUTF16(*i)); + added_plugin = true; + } + } + if (added_plugin) { + prefs_->Set(prefs::kPluginsPluginsBlacklist, list.release()); + delete value; + return true; + } + } + } + return false; +} + bool ConfigurationPolicyPrefStore::ApplySyncPolicy(PolicyType policy, Value* value) { if (policy == ConfigurationPolicyStore::kPolicySyncDisabled) { @@ -255,6 +292,9 @@ void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) { if (ApplyProxyPolicy(policy, value)) return; + if (ApplyPluginPolicy(policy, value)) + return; + if (ApplySyncPolicy(policy, value)) return; @@ -264,4 +304,5 @@ void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) { // Other policy implementations go here. NOTIMPLEMENTED(); + delete value; } diff --git a/chrome/browser/configuration_policy_pref_store.h b/chrome/browser/configuration_policy_pref_store.h index 5035cba..afbb541 100644 --- a/chrome/browser/configuration_policy_pref_store.h +++ b/chrome/browser/configuration_policy_pref_store.h @@ -85,6 +85,11 @@ class ConfigurationPolicyPrefStore : public PrefStore, // of |value| in the case that the policy is proxy-specific. bool ApplyProxyPolicy(PolicyType policy, Value* value); + // Processes plugin policies. Returns true if the specified policy + // is a plugin-related policy. ApplyPluginPolicy assumes the ownership + // of |value| in the case that the policy is plugin-specific. + bool ApplyPluginPolicy(PolicyType policy, Value* value); + // Handles sync-related policies. Returns true if the policy was handled. // Assumes ownership of |value| in that case. bool ApplySyncPolicy(PolicyType policy, Value* value); diff --git a/chrome/browser/configuration_policy_pref_store_unittest.cc b/chrome/browser/configuration_policy_pref_store_unittest.cc index 2311970..56dc576 100644 --- a/chrome/browser/configuration_policy_pref_store_unittest.cc +++ b/chrome/browser/configuration_policy_pref_store_unittest.cc @@ -12,6 +12,12 @@ class ConfigurationPolicyPrefStoreTest : public testing::Test { public: + // Applies a policy that has a string value. + void ApplyStringPolicyValue( + ConfigurationPolicyPrefStore* store, + ConfigurationPolicyStore::PolicyType type, + const wchar_t* policy_value); + // The following three methods test a policy which controls a string // preference. // Checks that by default, it's an empty string. @@ -46,6 +52,13 @@ class ConfigurationPolicyPrefStoreTest : public testing::Test { ConfigurationPolicyStore::PolicyType type); }; +void ConfigurationPolicyPrefStoreTest::ApplyStringPolicyValue( + ConfigurationPolicyPrefStore* store, + ConfigurationPolicyStore::PolicyType type, + const wchar_t* policy_value) { + store->Apply(type, Value::CreateStringValue(policy_value)); +} + void ConfigurationPolicyPrefStoreTest::TestStringPolicyGetDefault( const wchar_t* pref_name) { ConfigurationPolicyPrefStore store(NULL, NULL); @@ -57,7 +70,7 @@ void ConfigurationPolicyPrefStoreTest::TestStringPolicyGetDefault( void ConfigurationPolicyPrefStoreTest::TestStringPolicySetValue( const wchar_t* pref_name, ConfigurationPolicyStore::PolicyType type) { ConfigurationPolicyPrefStore store(NULL, NULL); - store.Apply(type, Value::CreateStringValue("http://chromium.org")); + ApplyStringPolicyValue(&store, type, L"http://chromium.org"); std::wstring result; store.prefs()->GetString(pref_name, &result); EXPECT_EQ(result, L"http://chromium.org"); @@ -391,3 +404,61 @@ TEST_F(ConfigurationPolicyPrefStoreTest, &bool_result)); } +TEST_F(ConfigurationPolicyPrefStoreTest, + TestPolicyProxyDisabledPlugin) { + FilePath unused_path(FILE_PATH_LITERAL("foo.exe")); + CommandLine command_line(unused_path); + scoped_ptr<MockConfigurationPolicyProvider> provider( + new MockConfigurationPolicyProvider()); + + ConfigurationPolicyPrefStore store(&command_line, provider.release()); + ApplyStringPolicyValue(&store, + ConfigurationPolicyStore::kPolicyDisabledPlugins, + L"plugin1"); + EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE); + + ListValue* plugin_blacklist = NULL; + EXPECT_TRUE(store.prefs()->GetList(prefs::kPluginsPluginsBlacklist, + &plugin_blacklist)); + + ListValue::const_iterator current(plugin_blacklist->begin()); + ListValue::const_iterator end(plugin_blacklist->end()); + + ASSERT_TRUE(current != end); + std::string plugin_name; + (*current)->GetAsString(&plugin_name); + EXPECT_EQ("plugin1", plugin_name); + ++current; + EXPECT_TRUE(current == end); +} + +TEST_F(ConfigurationPolicyPrefStoreTest, + TestPolicyProxyDisabledPluginEscapedComma) { + FilePath unused_path(FILE_PATH_LITERAL("foo.exe")); + CommandLine command_line(unused_path); + scoped_ptr<MockConfigurationPolicyProvider> provider( + new MockConfigurationPolicyProvider()); + + ConfigurationPolicyPrefStore store(&command_line, provider.release()); + ApplyStringPolicyValue(&store, + ConfigurationPolicyStore::kPolicyDisabledPlugins, + L"plugin1,plugin2\\,"); + EXPECT_EQ(store.ReadPrefs(), PrefStore::PREF_READ_ERROR_NONE); + + ListValue* plugin_blacklist = NULL; + EXPECT_TRUE(store.prefs()->GetList(prefs::kPluginsPluginsBlacklist, + &plugin_blacklist)); + ListValue::const_iterator current(plugin_blacklist->begin()); + ListValue::const_iterator end(plugin_blacklist->end()); + ASSERT_TRUE(current != end); + std::string plugin_name; + (*current)->GetAsString(&plugin_name); + EXPECT_EQ("plugin1", plugin_name); + ++current; + ASSERT_TRUE(current != end); + (*current)->GetAsString(&plugin_name); + EXPECT_EQ("plugin2,", plugin_name); + ++current; + EXPECT_TRUE(current == end); +} + diff --git a/chrome/browser/configuration_policy_provider.cc b/chrome/browser/configuration_policy_provider.cc index 3156c59..4cdc433 100644 --- a/chrome/browser/configuration_policy_provider.cc +++ b/chrome/browser/configuration_policy_provider.cc @@ -40,6 +40,8 @@ const InternalPolicyValueMapEntry kPolicyValueMap[] = { Value::TYPE_BOOLEAN, "SafeBrowsingEnabled" }, { ConfigurationPolicyStore::kPolicyMetricsReportingEnabled, Value::TYPE_BOOLEAN, "MetricsReportingEnabled" }, + { ConfigurationPolicyStore::kPolicyDisabledPlugins, + Value::TYPE_STRING, "DisabledPluginsList" }, { ConfigurationPolicyStore::kPolicySyncDisabled, Value::TYPE_BOOLEAN, "SyncDisabled" } }; diff --git a/chrome/browser/configuration_policy_store.h b/chrome/browser/configuration_policy_store.h index 8cdbe77..b12e2a5 100644 --- a/chrome/browser/configuration_policy_store.h +++ b/chrome/browser/configuration_policy_store.h @@ -26,7 +26,13 @@ class ConfigurationPolicyStore { kPolicyDnsPrefetchingEnabled, kPolicySafeBrowsingEnabled, kPolicyMetricsReportingEnabled, - kPolicySyncDisabled + kPolicySyncDisabled, + + // A policy for allowing administrators to forcibly disable + // specific plugins. This policy is a comma-separated list of + // plugin names. Plugin names must not include the backslash + // character. + kPolicyDisabledPlugins }; static const int kPolicyNoProxyServerMode = 0; diff --git a/chrome/browser/dom_ui/plugins_ui.cc b/chrome/browser/dom_ui/plugins_ui.cc index 25cec21..158f297 100644 --- a/chrome/browser/dom_ui/plugins_ui.cc +++ b/chrome/browser/dom_ui/plugins_ui.cc @@ -5,6 +5,7 @@ #include "chrome/browser/dom_ui/plugins_ui.h" #include <algorithm> +#include <set> #include <string> #include <vector> @@ -71,6 +72,10 @@ void PluginsUIHTMLSource::StartDataRequest(const std::string& path, l10n_util::GetString(IDS_PLUGINS_NONE_INSTALLED)); localized_strings.SetString(L"pluginDisabled", l10n_util::GetString(IDS_PLUGINS_DISABLED_PLUGIN)); + localized_strings.SetString(L"pluginDisabledByPolicy", + l10n_util::GetString(IDS_PLUGINS_DISABLED_BY_POLICY_PLUGIN)); + localized_strings.SetString(L"pluginCannotBeEnabledDueToPolicy", + l10n_util::GetString(IDS_PLUGINS_CANNOT_ENABLE_DUE_TO_POLICY)); localized_strings.SetString(L"pluginDownload", l10n_util::GetString(IDS_PLUGINS_DOWNLOAD)); localized_strings.SetString(L"pluginName", @@ -143,6 +148,12 @@ class PluginsDOMHandler : public DOMMessageHandler { void HandleShowTermsOfServiceMessage(const Value* value); private: + // Creates a dictionary containing all the information about the given plugin; + // this is put into the list to "return" for the "requestPluginsData" message. + DictionaryValue* CreatePluginDetailValue( + const WebPluginInfo& plugin, + const std::set<string16>& plugin_blacklist_set); + // Creates a dictionary containing the important parts of the information // about the given plugin; this is put into a list and saved in prefs. DictionaryValue* CreatePluginSummaryValue(const WebPluginInfo& plugin); @@ -165,8 +176,6 @@ void PluginsDOMHandler::RegisterMessages() { void PluginsDOMHandler::HandleRequestPluginsData(const Value* value) { DictionaryValue* results = new DictionaryValue(); - - // Grouped plugins. results->Set(L"plugins", plugin_updater::GetPluginGroupsData()); dom_ui_->CallJavascriptFunction(L"returnPluginsData", *results); @@ -193,7 +202,7 @@ void PluginsDOMHandler::HandleEnablePluginMessage(const Value* value) { return; plugin_updater::EnablePluginGroup(enable_str == "true", - WideToUTF16(group_name)); + WideToUTF16(group_name)); } else { FilePath::StringType file_path; if (!list->GetString(0, &file_path)) @@ -251,6 +260,7 @@ void PluginsUI::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterFilePathPref(prefs::kPluginsLastInternalDirectory, internal_dir); + prefs->RegisterListPref(prefs::kPluginsPluginsBlacklist); prefs->RegisterListPref(prefs::kPluginsPluginsList); prefs->RegisterBooleanPref(prefs::kPluginsEnabledInternalPDF, false); } diff --git a/chrome/browser/plugin_updater.cc b/chrome/browser/plugin_updater.cc index 288de87..4c884d7 100644 --- a/chrome/browser/plugin_updater.cc +++ b/chrome/browser/plugin_updater.cc @@ -80,11 +80,12 @@ void EnablePluginGroup(bool enable, const string16& group_name) { } } -void EnablePluginFile(bool enable, const FilePath::StringType& file_path) { - if (enable) - NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(file_path)); +void EnablePluginFile(bool enable, const FilePath::StringType& path) { + FilePath file_path(path); + if (enable && !PluginGroup::IsPluginPathDisabledByPolicy(file_path)) + NPAPI::PluginList::Singleton()->EnablePlugin(file_path); else - NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(file_path)); + NPAPI::PluginList::Singleton()->DisablePlugin(file_path); } #if defined(OS_CHROMEOS) @@ -166,6 +167,42 @@ void DisablePluginGroupsFromPrefs(Profile* profile) { } } + // Build the set of policy-disabled plugins once and cache it. + // Don't do this in the constructor, there's no profile available there. + std::set<string16> policy_disabled_plugins; + const ListValue* plugin_blacklist = + profile->GetPrefs()->GetList(prefs::kPluginsPluginsBlacklist); + if (plugin_blacklist) { + ListValue::const_iterator end(plugin_blacklist->end()); + for (ListValue::const_iterator current(plugin_blacklist->begin()); + current != end; ++current) { + string16 plugin_name; + if ((*current)->GetAsUTF16(&plugin_name)) { + policy_disabled_plugins.insert(plugin_name); + } + } + } + PluginGroup::SetPolicyDisabledPluginSet(policy_disabled_plugins); + + // Disable all of the plugins and plugin groups that are disabled by policy. + std::vector<WebPluginInfo> plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); + for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin(); + it != plugins.end(); + ++it) { + if (PluginGroup::IsPluginNameDisabledByPolicy(it->name)) + NPAPI::PluginList::Singleton()->DisablePlugin(it->path); + } + + std::vector<linked_ptr<PluginGroup> > plugin_groups; + GetPluginGroups(&plugin_groups); + std::vector<linked_ptr<PluginGroup> >::const_iterator it; + for (it = plugin_groups.begin(); it != plugin_groups.end(); ++it) { + string16 current_group_name = (*it)->GetGroupName(); + if (PluginGroup::IsPluginNameDisabledByPolicy(current_group_name)) + EnablePluginGroup(false, current_group_name); + } + if (!enable_internal_pdf_ && !found_internal_pdf) { // The internal PDF plugin is disabled by default, and the user hasn't // overridden the default. diff --git a/chrome/browser/plugin_updater.h b/chrome/browser/plugin_updater.h index ba89b83..fd34b93 100644 --- a/chrome/browser/plugin_updater.h +++ b/chrome/browser/plugin_updater.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_PLUGIN_UPDATER_H_ #define CHROME_BROWSER_PLUGIN_UPDATER_H_ +#include <set> #include <vector> #include "base/basictypes.h" diff --git a/chrome/browser/resources/plugins.html b/chrome/browser/resources/plugins.html index e8b14c5..dbaf7555 100644 --- a/chrome/browser/resources/plugins.html +++ b/chrome/browser/resources/plugins.html @@ -310,7 +310,7 @@ var pluginDataFormat = { 'fileExtensions': [ 'bar','baz' ], 'mimeType': 'application/my-bar' } ], - 'enabled': true + 'enabledMode': 'enabled' }, { 'path': '/foobar/baz/YourGreatPlugin.plugin', @@ -322,7 +322,19 @@ var pluginDataFormat = { 'fileExtensions': [ 'baz' ], 'mimeType': 'application/x-your-baz' } ], - 'enabled': false + 'enabledMode': 'disabledByUser' + }, + { + 'path': '/foobiz/bar/HisGreatPlugin.plugin', + 'name': 'HisGreatPlugin', + 'version': '1.2', + 'description': 'His great plugin', + 'mimeTypes': [ + { 'description': 'More baz Stuff', + 'fileExtensions': [ 'bor' ], + 'mimeType': 'application/x-his-bor' } + ], + 'enabledMode': 'disabledByPolicy' } ] } @@ -506,7 +518,7 @@ document.addEventListener('DOMContentLoaded', requestPluginsData); <div class="plugin" jsselect="plugins"> <table width="100%" cellpadding="2" cellspacing="0"> <tr jsvalues= - ".className:enabled ? 'plugin-enabled' : 'plugin-disabled'"> + ".className:enabledMode == 'enabled' ? 'plugin-enabled' : 'plugin-disabled'"> <td valign="top"> <div class="plugin-text"> <div> @@ -521,8 +533,10 @@ document.addEventListener('DOMContentLoaded', requestPluginsData); </span> <a jsdisplay="critical" jsvalues=".href:update_url" i18n-content="pluginDownload">DOWNLOAD UPDATE</a> - <span jsdisplay="!enabled" + <span jsdisplay="enabledMode == 'disabledByUser'" i18n-content="pluginDisabled">(DISABLED)</span> + <span jsdisplay="enabledMode == 'disabledByPolicy'" + i18n-content="pluginDisabledByPolicy">(DISABLED_BY_POLICY)</span> <div jsdisplay="shouldDisplayPluginDescription($this)"> <span dir="ltr" jsvalues=".innerHTML:description"> </div> @@ -530,17 +544,21 @@ document.addEventListener('DOMContentLoaded', requestPluginsData); <div jsselect="plugin_files" class="plugin-details"> <div class="showInTmiMode"> <div jsvalues= - ".className:enabled ? 'plugin-file-enabled' : 'plugin-file-disabled'"> + ".className:enabledMode == 'enabled' ? 'plugin-file-enabled' : 'plugin-file-disabled'"> <div><table><tr> <td class="plugin-details-label" i18n-content="pluginName">NAME:</td> <td><span dir="ltr" jscontent="name">NAME</span></td> </tr></table></div> - <div><table><tr jsdisplay="shouldDisplayPluginDescription($this)"> - <td class="plugin-details-label" - i18n-content="pluginDescription">DESCRIPTION:</td> - <td><span dir="ltr" jsvalues=".innerHTML:description"></td> - </tr></table></div> + <div><table> + <tr jsdisplay="shouldDisplayPluginDescription($this)"> + <td class="plugin-details-label" + i18n-content="pluginDescription">DESCRIPTION:</td> + <td> + <span dir="ltr" jsvalues=".innerHTML:description"> + </td> + </tr> + </table></div> <div><table><tr> <td class="plugin-details-label" i18n-content="pluginVersion">VERSION:</td> @@ -559,23 +577,30 @@ document.addEventListener('DOMContentLoaded', requestPluginsData); <div><table><tr> <td class="plugin-details-label"> </td> <td> - <span jsdisplay="!enabled" + <span jsdisplay="enabledMode == 'disabledByUser'" i18n-content="pluginDisabled">(DISABLED)</span> <span> - <a - jsvalues=".path:path" - jsdisplay="enabled" - onclick="handleEnablePlugin(this, false, false)" - href="javascript:void(0);" - i18n-content="disable" - >DISABLE</a> - <a - jsvalues=".path:path" - jsdisplay="!enabled" - onclick="handleEnablePlugin(this, true, false)" - href="javascript:void(0);" - i18n-content="enable" - >ENABLE</a> + <span jsdisplay="enabledMode == 'disabledByPolicy'" + i18n-content="pluginDisabled">(DISABLED_BY_POLICY)</span> + <span> + <a + jsvalues=".path:name" + jsdisplay="enabledMode == 'enabled'" + onclick="handleEnablePlugin(this, false, false)" + href="javascript:void(0);" + i18n-content="disable" + >DISABLE</a> + <a + jsvalues=".path:name" + jsdisplay="enabledMode == 'disabledByUser'" + onclick="handleEnablePlugin(this, true, false)" + href="javascript:void(0);" + i18n-content="enable" + >ENABLE</a> + <span + jsdisplay="enabledMode == 'disabledByPolicy'" + i18n-content="pluginCannotBeEnabledDueToPolicy" + >CANNOT_ENABLE</span> </span> </td> </tr></table></div> @@ -613,18 +638,22 @@ document.addEventListener('DOMContentLoaded', requestPluginsData); <span> <a jsvalues=".path:name" - jsdisplay="enabled" + jsdisplay="enabledMode == 'enabled'" onclick="handleEnablePlugin(this, false, true)" href="javascript:void(0);" i18n-content="disable" >DISABLE</a> <a jsvalues=".path:name" - jsdisplay="!enabled" + jsdisplay="enabledMode == 'disabledByUser'" onclick="handleEnablePlugin(this, true, true)" href="javascript:void(0);" i18n-content="enable" >ENABLE</a> + <span + jsdisplay="enabledMode == 'disabledByPolicy'" + i18n-content="pluginCannotBeEnabledDueToPolicy" + >CANNOT_ENABLE</span> </span> </div> </td> diff --git a/chrome/common/plugin_group.cc b/chrome/common/plugin_group.cc index 984aebc..5df39b3 100644 --- a/chrome/common/plugin_group.cc +++ b/chrome/common/plugin_group.cc @@ -68,6 +68,9 @@ static const PluginGroupDefinition kGroupDefinitions[] = {}; #endif /*static*/ +std::set<string16>* PluginGroup::policy_disabled_puglins_; + +/*static*/ const PluginGroupDefinition* PluginGroup::GetPluginGroupDefinitions() { return kGroupDefinitions; } @@ -78,6 +81,36 @@ size_t PluginGroup::GetPluginGroupDefinitionsSize() { return ARRAYSIZE_UNSAFE(kGroupDefinitions); } +/*static*/ +void PluginGroup::SetPolicyDisabledPluginSet(const std::set<string16>& set) { + if (!policy_disabled_puglins_) { + policy_disabled_puglins_ = new std::set<string16>(); + *policy_disabled_puglins_ = set; + } +} + +/*static*/ +bool PluginGroup::IsPluginNameDisabledByPolicy(const string16& plugin_name) { + return policy_disabled_puglins_ && + policy_disabled_puglins_->find(plugin_name) != + policy_disabled_puglins_->end(); +} + +/*static*/ +bool PluginGroup::IsPluginPathDisabledByPolicy(const FilePath& plugin_path) { + std::vector<WebPluginInfo> plugins; + NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins); + for (std::vector<WebPluginInfo>::const_iterator it = plugins.begin(); + it != plugins.end(); + ++it) { + if (FilePath::CompareEqualIgnoreCase(it->path.value(), + plugin_path.value()) && IsPluginNameDisabledByPolicy(it->name)) { + return true; + } + } + return false; +} + PluginGroup::PluginGroup(const string16& group_name, const string16& name_matcher, const std::string& version_range_low, @@ -231,7 +264,14 @@ DictionaryValue* PluginGroup::GetDataForUI() const { result->SetString(L"version", max_version_->GetString()); result->SetString(L"update_url", update_url_); result->SetBoolean(L"critical", IsVulnerable()); - result->SetBoolean(L"enabled", enabled_); + + bool group_disabled_by_policy = IsPluginNameDisabledByPolicy(group_name_); + if (group_disabled_by_policy) { + result->SetString(L"enabledMode", L"disabledByPolicy"); + } else { + result->SetString(L"enabledMode", + enabled_ ? L"enabled" : L"disabledByUser"); + } ListValue* plugin_files = new ListValue(); for (size_t i = 0; i < web_plugin_infos_.size(); ++i) { @@ -242,7 +282,14 @@ DictionaryValue* PluginGroup::GetDataForUI() const { plugin_file->SetStringFromUTF16(L"description", web_plugin.desc); plugin_file->SetString(L"path", web_plugin.path.value()); plugin_file->SetStringFromUTF16(L"version", web_plugin.version); - plugin_file->SetBoolean(L"enabled", web_plugin.enabled); + bool plugin_disabled_by_policy = group_disabled_by_policy || + IsPluginNameDisabledByPolicy(web_plugin.name); + if (plugin_disabled_by_policy) { + result->SetString(L"enabledMode", L"disabledByPolicy"); + } else { + result->SetString(L"enabledMode", + web_plugin.enabled ? L"enabled" : L"disabledByUser"); + } plugin_file->SetInteger(L"priority", priority); ListValue* mime_types = new ListValue(); @@ -286,10 +333,11 @@ void PluginGroup::Enable(bool enable) { for (std::vector<WebPluginInfo>::const_iterator it = web_plugin_infos_.begin(); it != web_plugin_infos_.end(); ++it) { - if (enable) { + if (enable && !IsPluginNameDisabledByPolicy(it->name)) { NPAPI::PluginList::Singleton()->EnablePlugin(FilePath(it->path)); } else { NPAPI::PluginList::Singleton()->DisablePlugin(FilePath(it->path)); } } } + diff --git a/chrome/common/plugin_group.h b/chrome/common/plugin_group.h index dba66ae..f9f6ce3 100644 --- a/chrome/common/plugin_group.h +++ b/chrome/common/plugin_group.h @@ -5,6 +5,7 @@ #ifndef CHROME_COMMON_PLUGIN_GROUP_H_ #define CHROME_COMMON_PLUGIN_GROUP_H_ +#include <set> #include <vector> #include "base/linked_ptr.h" @@ -41,6 +42,17 @@ class PluginGroup { // Find a plugin group matching |info| in the list of hardcoded plugins. static PluginGroup* FindHardcodedPluginGroup(const WebPluginInfo& info); + // Configures the set of plugin names that are disabled by policy. + static void SetPolicyDisabledPluginSet(const std::set<string16>& set); + + // Tests to see if a plugin is on the blacklist using its name as + // the lookup key. + static bool IsPluginNameDisabledByPolicy(const string16& plugin_name); + + // Tests to see if a plugin is on the blacklist using its path as + // the lookup key. + static bool IsPluginPathDisabledByPolicy(const FilePath& plugin_path); + // Find the PluginGroup matching a Plugin in a list of plugin groups. Returns // NULL if no matching PluginGroup is found. static PluginGroup* FindGroupMatchingPlugin( @@ -94,6 +106,8 @@ class PluginGroup { const std::string& min_version, const std::string& update_url); + static std::set<string16>* policy_disabled_puglins_; + string16 group_name_; string16 name_matcher_; std::string version_range_low_str_; diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 424b011..b65a3da 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -413,6 +413,9 @@ const wchar_t kPluginsLastInternalDirectory[] = // List pref containing information (dictionaries) on plugins. const wchar_t kPluginsPluginsList[] = L"plugins.plugins_list"; +// List pref containing names of plugins that are disabled by policy. +const wchar_t kPluginsPluginsBlacklist[] = L"plugins.plugins_blacklist"; + // When first shipped, the pdf plugin will be disabled by default. When we // enable it by default, we'll want to do so only once. const wchar_t kPluginsEnabledInternalPDF[] = L"plugins.enabled_internal_pdf"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 4a00675..7dfc8ff 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -162,6 +162,7 @@ extern const wchar_t kExtensionsUIDeveloperMode[]; extern const wchar_t kExtensionToolbarSize[]; extern const wchar_t kPluginsLastInternalDirectory[]; extern const wchar_t kPluginsPluginsList[]; +extern const wchar_t kPluginsPluginsBlacklist[]; extern const wchar_t kPluginsEnabledInternalPDF[]; extern const wchar_t kCheckDefaultBrowser[]; #if defined(OS_MACOSX) |