summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 15:33:45 +0000
committerbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 15:33:45 +0000
commitf7be2cbadb7d6f2f96ea6a836f70961640bdb5e6 (patch)
tree14a6c5f61d11697047bb0d6a08625271f314fe45 /chrome
parent411f5d0bcab149cbea4c482a06bfd7c851a71c7d (diff)
downloadchromium_src-f7be2cbadb7d6f2f96ea6a836f70961640bdb5e6.zip
chromium_src-f7be2cbadb7d6f2f96ea6a836f70961640bdb5e6.tar.gz
chromium_src-f7be2cbadb7d6f2f96ea6a836f70961640bdb5e6.tar.bz2
Reland r101269: Store plug-in enabled/disabled state in PluginPrefs instead of WebPluginInfo, to allow different sets of enabled/disabled plug-ins to be specified per profile.
The relanded version fixes GViewRequestInterceptorTest on ChromeOS and a memory leak in PluginListTest.GetPluginGroup. Original review URL: http://codereview.chromium.org/7848025 TBR=jam@chromium.org BUG=80794 TEST=Open two profiles, disable different plugins in them. Review URL: http://codereview.chromium.org/7904009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101297 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc14
-rw-r--r--chrome/browser/chromeos/gview_request_interceptor_unittest.cc8
-rw-r--r--chrome/browser/component_updater/pepper_flash_component_installer.cc6
-rw-r--r--chrome/browser/pdf_unsupported_feature.cc21
-rw-r--r--chrome/browser/plugin_exceptions_table_model_unittest.cc4
-rw-r--r--chrome/browser/plugin_prefs.cc354
-rw-r--r--chrome/browser/plugin_prefs.h86
-rw-r--r--chrome/browser/plugin_prefs_unittest.cc160
-rw-r--r--chrome/browser/printing/print_preview_tab_controller.cc4
-rw-r--r--chrome/browser/ui/webui/plugins_ui.cc138
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/renderer/chrome_content_renderer_client.cc11
12 files changed, 601 insertions, 206 deletions
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index 4ad0a90..c3d2fd9 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -3536,12 +3536,9 @@ void TestingAutomationProvider::EnablePlugin(Browser* browser,
if (!args->GetString("path", &path)) {
reply.SendError("path not specified.");
return;
- } else if (!webkit::npapi::PluginList::Singleton()->EnablePlugin(
- FilePath(path))) {
- reply.SendError(StringPrintf("Could not enable plugin for path %s.",
- path.c_str()));
- return;
}
+ PluginPrefs::GetForProfile(browser->profile())->EnablePlugin(
+ true, FilePath(path));
reply.SendSuccess(NULL);
}
@@ -3556,12 +3553,9 @@ void TestingAutomationProvider::DisablePlugin(Browser* browser,
if (!args->GetString("path", &path)) {
reply.SendError("path not specified.");
return;
- } else if (!webkit::npapi::PluginList::Singleton()->DisablePlugin(
- FilePath(path))) {
- reply.SendError(StringPrintf("Could not disable plugin for path %s.",
- path.c_str()));
- return;
}
+ PluginPrefs::GetForProfile(browser->profile())->EnablePlugin(
+ false, FilePath(path));
reply.SendSuccess(NULL);
}
diff --git a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
index 97eb568..33662b7 100644
--- a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
+++ b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc
@@ -71,6 +71,7 @@ class GViewRequestInterceptorTest : public testing::Test {
public:
GViewRequestInterceptorTest()
: ui_thread_(BrowserThread::UI, &message_loop_),
+ file_thread_(BrowserThread::FILE, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_) {}
virtual void SetUp() {
@@ -96,6 +97,7 @@ class GViewRequestInterceptorTest : public testing::Test {
}
virtual void TearDown() {
+ plugin_prefs_->ShutdownOnUIThread();
content::ResourceContext* resource_context =
content::MockResourceContext::GetInstance();
net::URLRequestContext* request_context =
@@ -110,7 +112,6 @@ class GViewRequestInterceptorTest : public testing::Test {
void RegisterPDFPlugin() {
webkit::WebPluginInfo info;
info.path = pdf_path_;
- info.enabled = webkit::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);
webkit::npapi::PluginList::Singleton()->RefreshPlugins();
}
@@ -166,6 +167,7 @@ class GViewRequestInterceptorTest : public testing::Test {
protected:
MessageLoopForIO message_loop_;
BrowserThread ui_thread_;
+ BrowserThread file_thread_;
BrowserThread io_thread_;
TestingPrefService prefs_;
scoped_refptr<PluginPrefs> plugin_prefs_;
@@ -197,7 +199,7 @@ TEST_F(GViewRequestInterceptorTest, DoNotInterceptDownload) {
TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) {
SetPDFPluginLoadedState(true);
- webkit::npapi::PluginList::Singleton()->EnablePlugin(pdf_path_);
+ plugin_prefs_->EnablePlugin(true, pdf_path_);
net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
SetupRequest(&request);
@@ -209,7 +211,7 @@ TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) {
TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) {
SetPDFPluginLoadedState(true);
- webkit::npapi::PluginList::Singleton()->DisablePlugin(pdf_path_);
+ plugin_prefs_->EnablePlugin(false, pdf_path_);
net::URLRequest request(GURL("http://foo.com/file.pdf"), &test_delegate_);
SetupRequest(&request);
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc
index 6c44558..20d7294 100644
--- a/chrome/browser/component_updater/pepper_flash_component_installer.cc
+++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -16,6 +16,7 @@
#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/plugin_prefs.h"
#include "chrome/common/chrome_paths.h"
#include "content/browser/browser_thread.h"
#include "content/common/pepper_plugin_registry.h"
@@ -107,7 +108,6 @@ bool SupportsPepperInterface(const char* interface_name) {
bool MakePepperFlashPluginInfo(const FilePath& flash_path,
const Version& flash_version,
bool out_of_process,
- bool enabled,
PepperPluginInfo* plugin_info) {
if (!flash_version.IsValid())
return false;
@@ -119,7 +119,6 @@ bool MakePepperFlashPluginInfo(const FilePath& flash_path,
plugin_info->is_out_of_process = out_of_process;
plugin_info->path = flash_path;
plugin_info->name = kFlashPluginName;
- plugin_info->enabled = enabled;
// The description is like "Shockwave Flash 10.2 r154".
plugin_info->description = StringPrintf("%s %d.%d r%d",
@@ -143,8 +142,9 @@ void RegisterPepperFlashWithChrome(const FilePath& path,
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
PepperPluginInfo plugin_info;
// Register it as out-of-process and disabled.
- if (!MakePepperFlashPluginInfo(path, version, true, false, &plugin_info))
+ if (!MakePepperFlashPluginInfo(path, version, true, &plugin_info))
return;
+ PluginPrefs::EnablePluginGlobally(false, plugin_info.path);
webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(
plugin_info.ToWebPluginInfo());
webkit::npapi::PluginList::Singleton()->RefreshPlugins();
diff --git a/chrome/browser/pdf_unsupported_feature.cc b/chrome/browser/pdf_unsupported_feature.cc
index 1a91a39..9fb0747 100644
--- a/chrome/browser/pdf_unsupported_feature.cc
+++ b/chrome/browser/pdf_unsupported_feature.cc
@@ -7,9 +7,9 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
+#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/plugin_prefs.h"
-#include "chrome/browser/chrome_plugin_service_filter.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/chrome_interstitial_page.h"
@@ -116,14 +116,13 @@ string16 PDFEnableAdobeReaderInfoBarDelegate::GetMessageText() const {
void PDFEnableAdobeReaderInfoBarDelegate::OnYes() {
UserMetrics::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarOK"));
- webkit::npapi::PluginList::Singleton()->EnableGroup(false,
- ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName));
Profile* profile =
Profile::FromBrowserContext(tab_contents_->browser_context());
PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile);
plugin_prefs->EnablePluginGroup(
true, ASCIIToUTF16(webkit::npapi::PluginGroup::kAdobeReaderGroupName));
- plugin_prefs->UpdatePreferences(0);
+ plugin_prefs->EnablePluginGroup(
+ false, ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName));
}
void PDFEnableAdobeReaderInfoBarDelegate::OnNo() {
@@ -142,11 +141,9 @@ void OpenUsingReader(TabContentsWrapper* tab,
InfoBarDelegate* old_delegate,
InfoBarDelegate* new_delegate) {
WebPluginInfo plugin = reader_plugin;
- // The plugin is disabled, so enable it to get around the renderer check.
- // Also give it a new version so that the renderer doesn't show the blocked
+ // Give the plugin a new version so that the renderer doesn't show the blocked
// plugin UI if it's vulnerable, since we already went through the
// interstitial.
- plugin.enabled = WebPluginInfo::USER_ENABLED;
plugin.version = ASCIIToUTF16("11.0.0.0");
ChromePluginServiceFilter::GetInstance()->OverridePluginForTab(
@@ -284,11 +281,12 @@ PDFUnsupportedFeatureInfoBarDelegate::PDFUnsupportedFeatureInfoBarDelegate(
}
UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarShown"));
- std::vector<WebPluginInfo> plugins = reader_group->web_plugin_infos();
+ const std::vector<WebPluginInfo>& plugins =
+ reader_group->web_plugin_infos();
DCHECK_EQ(plugins.size(), 1u);
reader_webplugininfo_ = plugins[0];
- reader_vulnerable_ = reader_group->IsVulnerable();
+ reader_vulnerable_ = reader_group->IsVulnerable(reader_webplugininfo_);
if (!reader_vulnerable_) {
scoped_ptr<Version> version(PluginGroup::CreateVersionFromString(
reader_webplugininfo_.version));
@@ -382,8 +380,11 @@ void PDFHasUnsupportedFeature(TabContentsWrapper* tab) {
string16 reader_group_name(ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName));
// If the Reader plugin is disabled by policy, don't prompt them.
- if (PluginGroup::IsPluginNameDisabledByPolicy(reader_group_name))
+ PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(tab->profile());
+ if (plugin_prefs->PolicyStatusForPlugin(reader_group_name) ==
+ PluginPrefs::POLICY_DISABLED) {
return;
+ }
PluginGroup* reader_group = NULL;
std::vector<PluginGroup> plugin_groups;
diff --git a/chrome/browser/plugin_exceptions_table_model_unittest.cc b/chrome/browser/plugin_exceptions_table_model_unittest.cc
index 3c59fd7..f37c6c1 100644
--- a/chrome/browser/plugin_exceptions_table_model_unittest.cc
+++ b/chrome/browser/plugin_exceptions_table_model_unittest.cc
@@ -93,8 +93,6 @@ class PluginExceptionsTableModelTest : public testing::Test {
webkit::WebPluginInfo foo_plugin;
foo_plugin.path = FilePath(FILE_PATH_LITERAL("a-foo"));
foo_plugin.name = ASCIIToUTF16("FooPlugin");
- foo_plugin.enabled =
- webkit::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
scoped_ptr<webkit::npapi::PluginGroup> foo_group(
webkit::npapi::PluginGroup::FromWebPluginInfo(foo_plugin));
plugins.push_back(*foo_group);
@@ -102,8 +100,6 @@ class PluginExceptionsTableModelTest : public testing::Test {
webkit::WebPluginInfo bar_plugin;
bar_plugin.path = FilePath(FILE_PATH_LITERAL("b-bar"));
bar_plugin.name = ASCIIToUTF16("BarPlugin");
- bar_plugin.enabled =
- webkit::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
scoped_ptr<webkit::npapi::PluginGroup> bar_group(
webkit::npapi::PluginGroup::FromWebPluginInfo(bar_plugin));
plugins.push_back(*bar_group);
diff --git a/chrome/browser/plugin_prefs.cc b/chrome/browser/plugin_prefs.cc
index 50d1d42..a60a28b 100644
--- a/chrome/browser/plugin_prefs.cc
+++ b/chrome/browser/plugin_prefs.cc
@@ -7,19 +7,23 @@
#include <string>
#include "base/command_line.h"
+#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/message_loop.h"
#include "base/path_service.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_dependency_manager.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
@@ -27,6 +31,7 @@
#include "chrome/common/pref_names.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
+#include "webkit/plugins/npapi/plugin_group.h"
#include "webkit/plugins/npapi/plugin_list.h"
#include "webkit/plugins/webplugininfo.h"
@@ -49,6 +54,11 @@ class PluginPrefsWrapper : public ProfileKeyedService {
scoped_refptr<PluginPrefs> plugin_prefs_;
};
+// Default state for a plug-in (not state of the default plug-in!).
+// Accessed only on the UI thread.
+base::LazyInstance<std::map<FilePath, bool> > g_default_plugin_state(
+ base::LINKER_INITIALIZED);
+
}
// How long to wait to save the plugin enabled information, which might need to
@@ -61,6 +71,10 @@ class PluginPrefs::Factory : public ProfileKeyedServiceFactory {
PluginPrefsWrapper* GetWrapperForProfile(Profile* profile);
+ // Factory function for use with
+ // ProfileKeyedServiceFactory::SetTestingFactory.
+ static ProfileKeyedService* CreateWrapperForProfile(Profile* profile);
+
private:
friend struct DefaultSingletonTraits<Factory>;
@@ -89,31 +103,138 @@ PluginPrefs* PluginPrefs::GetForProfile(Profile* profile) {
return wrapper->plugin_prefs();
}
-DictionaryValue* PluginPrefs::CreatePluginFileSummary(
- const webkit::WebPluginInfo& plugin) {
- DictionaryValue* data = new DictionaryValue();
- data->SetString("path", plugin.path.value());
- data->SetString("name", plugin.name);
- data->SetString("version", plugin.version);
- data->SetBoolean("enabled", IsPluginEnabled(plugin));
- return data;
+// static
+PluginPrefs* PluginPrefs::GetForTestingProfile(Profile* profile) {
+ ProfileKeyedService* wrapper =
+ Factory::GetInstance()->SetTestingFactoryAndUse(
+ profile, &Factory::CreateWrapperForProfile);
+ return static_cast<PluginPrefsWrapper*>(wrapper)->plugin_prefs();
}
-void PluginPrefs::EnablePluginGroup(bool enable, const string16& group_name) {
- webkit::npapi::PluginList::Singleton()->EnableGroup(enable, group_name);
- NotifyPluginStatusChanged();
+void PluginPrefs::EnablePluginGroup(bool enabled, const string16& group_name) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::EnablePluginGroup,
+ enabled, group_name));
+ return;
+ }
+
+ webkit::npapi::PluginList* plugin_list =
+ webkit::npapi::PluginList::Singleton();
+ std::vector<webkit::npapi::PluginGroup> groups;
+ plugin_list->GetPluginGroups(true, &groups);
+
+ base::AutoLock auto_lock(lock_);
+
+ // Set the desired state for the group.
+ plugin_group_state_[group_name] = enabled;
+
+ // Update the state for all plug-ins in the group.
+ for (size_t i = 0; i < groups.size(); ++i) {
+ if (groups[i].GetGroupName() != group_name)
+ continue;
+ const std::vector<webkit::WebPluginInfo>& plugins =
+ groups[i].web_plugin_infos();
+ for (size_t j = 0; j < plugins.size(); ++j)
+ plugin_state_[plugins[j].path] = enabled;
+ break;
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, groups));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::NotifyPluginStatusChanged));
}
-void PluginPrefs::EnablePlugin(bool enable, const FilePath& path) {
- if (enable)
- webkit::npapi::PluginList::Singleton()->EnablePlugin(path);
- else
- webkit::npapi::PluginList::Singleton()->DisablePlugin(path);
+void PluginPrefs::EnablePlugin(bool enabled, const FilePath& path) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::EnablePlugin, enabled, path));
+ return;
+ }
- NotifyPluginStatusChanged();
+ {
+ // Set the desired state for the plug-in.
+ base::AutoLock auto_lock(lock_);
+ plugin_state_[path] = enabled;
+ }
+
+ webkit::npapi::PluginList* plugin_list =
+ webkit::npapi::PluginList::Singleton();
+ std::vector<webkit::npapi::PluginGroup> groups;
+ plugin_list->GetPluginGroups(true, &groups);
+
+ bool found_group = false;
+ for (size_t i = 0; i < groups.size(); ++i) {
+ bool all_disabled = true;
+ const std::vector<webkit::WebPluginInfo>& plugins =
+ groups[i].web_plugin_infos();
+ for (size_t j = 0; j < plugins.size(); ++j) {
+ all_disabled = all_disabled && !IsPluginEnabled(plugins[j]);
+ if (plugins[j].path == path) {
+ found_group = true;
+ DCHECK_EQ(enabled, IsPluginEnabled(plugins[j]));
+ }
+ }
+ if (found_group) {
+ // Update the state for the corresponding plug-in group.
+ base::AutoLock auto_lock(lock_);
+ plugin_group_state_[groups[i].GetGroupName()] = !all_disabled;
+ break;
+ }
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, groups));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::NotifyPluginStatusChanged));
+}
+
+// static
+void PluginPrefs::EnablePluginGlobally(bool enable, const FilePath& file_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ g_default_plugin_state.Get()[file_path] = enable;
+ std::vector<Profile*> profiles =
+ g_browser_process->profile_manager()->GetLoadedProfiles();
+ for (std::vector<Profile*>::iterator it = profiles.begin();
+ it != profiles.end(); ++it) {
+ PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(*it);
+ DCHECK(plugin_prefs);
+ plugin_prefs->EnablePlugin(enable, file_path);
+ }
+}
+
+PluginPrefs::PolicyStatus PluginPrefs::PolicyStatusForPlugin(
+ const string16& name) {
+ base::AutoLock auto_lock(lock_);
+ if (IsStringMatchedInSet(name, policy_enabled_plugin_patterns_)) {
+ return POLICY_ENABLED;
+ } else if (IsStringMatchedInSet(name, policy_disabled_plugin_patterns_) &&
+ !IsStringMatchedInSet(
+ name, policy_disabled_plugin_exception_patterns_)) {
+ return POLICY_DISABLED;
+ } else {
+ return NO_POLICY;
+ }
}
bool PluginPrefs::IsPluginEnabled(const webkit::WebPluginInfo& plugin) {
+ scoped_ptr<webkit::npapi::PluginGroup> group(
+ webkit::npapi::PluginList::Singleton()->GetPluginGroup(plugin));
+ string16 group_name = group->GetGroupName();
+
+ // Check if the plug-in or its group is enabled by policy.
+ PolicyStatus plugin_status = PolicyStatusForPlugin(plugin.name);
+ PolicyStatus group_status = PolicyStatusForPlugin(group_name);
+ if (plugin_status == POLICY_ENABLED || group_status == POLICY_ENABLED)
+ return true;
+
+ // Check if the plug-in or its group is disabled by policy.
+ if (plugin_status == POLICY_DISABLED || group_status == POLICY_DISABLED)
+ return false;
+
// If enabling NaCl, make sure the plugin is also enabled. See bug
// http://code.google.com/p/chromium/issues/detail?id=81010 for more
// information.
@@ -123,12 +244,27 @@ bool PluginPrefs::IsPluginEnabled(const webkit::WebPluginInfo& plugin) {
CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl)) {
return true;
}
- return webkit::IsPluginEnabled(plugin);
+
+ base::AutoLock auto_lock(lock_);
+ // Check user preferences for the plug-in.
+ std::map<FilePath, bool>::iterator plugin_it =
+ plugin_state_.find(plugin.path);
+ if (plugin_it != plugin_state_.end())
+ return plugin_it->second;
+
+ // Check user preferences for the plug-in group.
+ std::map<string16, bool>::iterator group_it(
+ plugin_group_state_.find(plugin.name));
+ if (group_it != plugin_group_state_.end())
+ return group_it->second;
+
+ // Default to enabled.
+ return true;
}
void PluginPrefs::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
+ const NotificationSource& source,
+ const NotificationDetails& details) {
DCHECK_EQ(chrome::NOTIFICATION_PREF_CHANGED, type);
const std::string* pref_name = Details<std::string>(details).ptr();
if (!pref_name) {
@@ -136,39 +272,39 @@ void PluginPrefs::Observe(int type,
return;
}
DCHECK_EQ(prefs_, Source<PrefService>(source).ptr());
- if (*pref_name == prefs::kPluginsDisabledPlugins ||
- *pref_name == prefs::kPluginsDisabledPluginsExceptions ||
- *pref_name == prefs::kPluginsEnabledPlugins) {
- const ListValue* disabled_list =
- prefs_->GetList(prefs::kPluginsDisabledPlugins);
- const ListValue* exceptions_list =
- prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions);
- const ListValue* enabled_list =
- prefs_->GetList(prefs::kPluginsEnabledPlugins);
- UpdatePluginsStateFromPolicy(disabled_list, exceptions_list, enabled_list);
+ if (*pref_name == prefs::kPluginsDisabledPlugins) {
+ base::AutoLock auto_lock(lock_);
+ ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins),
+ &policy_disabled_plugin_patterns_);
+ } else if (*pref_name == prefs::kPluginsDisabledPluginsExceptions) {
+ base::AutoLock auto_lock(lock_);
+ ListValueToStringSet(
+ prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions),
+ &policy_disabled_plugin_exception_patterns_);
+ } else if (*pref_name == prefs::kPluginsEnabledPlugins) {
+ base::AutoLock auto_lock(lock_);
+ ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins),
+ &policy_enabled_plugin_patterns_);
+ } else {
+ NOTREACHED();
}
+ NotifyPluginStatusChanged();
}
-void PluginPrefs::UpdatePluginsStateFromPolicy(
- const ListValue* disabled_list,
- const ListValue* exceptions_list,
- const ListValue* enabled_list) {
- std::set<string16> disabled_plugin_patterns;
- std::set<string16> disabled_plugin_exception_patterns;
- std::set<string16> enabled_plugin_patterns;
-
- ListValueToStringSet(disabled_list, &disabled_plugin_patterns);
- ListValueToStringSet(exceptions_list, &disabled_plugin_exception_patterns);
- ListValueToStringSet(enabled_list, &enabled_plugin_patterns);
-
- webkit::npapi::PluginGroup::SetPolicyEnforcedPluginPatterns(
- disabled_plugin_patterns,
- disabled_plugin_exception_patterns,
- enabled_plugin_patterns);
+/*static*/
+bool PluginPrefs::IsStringMatchedInSet(const string16& name,
+ const std::set<string16>& pattern_set) {
+ std::set<string16>::const_iterator pattern(pattern_set.begin());
+ while (pattern != pattern_set.end()) {
+ if (MatchPattern(name, *pattern))
+ return true;
+ ++pattern;
+ }
- NotifyPluginStatusChanged();
+ return false;
}
+/* static */
void PluginPrefs::ListValueToStringSet(const ListValue* src,
std::set<string16>* dest) {
DCHECK(src);
@@ -277,8 +413,7 @@ void PluginPrefs::SetPrefs(PrefService* prefs) {
}
}
- if (!enabled)
- webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_path);
+ plugin_state_[plugin_path] = enabled;
} else if (!enabled && plugin->GetString("name", &group_name)) {
// Don't disable this group if it's for the pdf or nacl plugins and
// we just forced it on.
@@ -289,7 +424,7 @@ void PluginPrefs::SetPrefs(PrefService* prefs) {
continue;
// Otherwise this is a list of groups.
- EnablePluginGroup(false, group_name);
+ plugin_group_state_[group_name] = false;
}
}
} else {
@@ -304,17 +439,14 @@ void PluginPrefs::SetPrefs(PrefService* prefs) {
// Build the set of policy enabled/disabled plugin patterns once and cache it.
// Don't do this in the constructor, there's no profile available there.
- const ListValue* disabled_plugins =
- prefs_->GetList(prefs::kPluginsDisabledPlugins);
- const ListValue* disabled_exception_plugins =
- prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions);
- const ListValue* enabled_plugins =
- prefs_->GetList(prefs::kPluginsEnabledPlugins);
- UpdatePluginsStateFromPolicy(disabled_plugins,
- disabled_exception_plugins,
- enabled_plugins);
+ ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins),
+ &policy_disabled_plugin_patterns_);
+ ListValueToStringSet(
+ prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions),
+ &policy_disabled_plugin_exception_patterns_);
+ ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins),
+ &policy_enabled_plugin_patterns_);
- registrar_.RemoveAll();
registrar_.Init(prefs_);
registrar_.Add(prefs::kPluginsDisabledPlugins, this);
registrar_.Add(prefs::kPluginsDisabledPluginsExceptions, this);
@@ -322,16 +454,22 @@ void PluginPrefs::SetPrefs(PrefService* prefs) {
if (force_enable_internal_pdf || internal_pdf_enabled) {
// See http://crbug.com/50105 for background.
- EnablePluginGroup(false, ASCIIToUTF16(
- webkit::npapi::PluginGroup::kAdobeReaderGroupName));
+ plugin_group_state_[ASCIIToUTF16(
+ webkit::npapi::PluginGroup::kAdobeReaderGroupName)] = false;
}
if (force_enable_internal_pdf || force_enable_nacl) {
// We want to save this, but doing so requires loading the list of plugins,
// so do it after a minute as to not impact startup performance. Note that
// plugins are loaded after 30s by the metrics service.
- UpdatePreferences(kPluginUpdateDelayMs);
+ BrowserThread::PostDelayedTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ NewRunnableMethod(this, &PluginPrefs::GetPreferencesDataOnFileThread),
+ kPluginUpdateDelayMs);
}
+
+ NotifyPluginStatusChanged();
}
void PluginPrefs::ShutdownOnUIThread() {
@@ -349,47 +487,51 @@ PluginPrefsWrapper* PluginPrefs::Factory::GetWrapperForProfile(
return static_cast<PluginPrefsWrapper*>(GetServiceForProfile(profile, true));
}
+// static
+ProfileKeyedService* PluginPrefs::Factory::CreateWrapperForProfile(
+ Profile* profile) {
+ return GetInstance()->BuildServiceInstanceFor(profile);
+}
+
PluginPrefs::Factory::Factory()
: ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) {
}
ProfileKeyedService* PluginPrefs::Factory::BuildServiceInstanceFor(
- Profile* profile) const {
+ Profile* profile) const {
scoped_refptr<PluginPrefs> plugin_prefs(new PluginPrefs());
plugin_prefs->SetPrefs(profile->GetPrefs());
return new PluginPrefsWrapper(plugin_prefs);
}
-PluginPrefs::PluginPrefs() : prefs_(NULL), notify_pending_(false) {
+PluginPrefs::PluginPrefs() : plugin_state_(g_default_plugin_state.Get()),
+ prefs_(NULL) {
}
PluginPrefs::~PluginPrefs() {
}
-void PluginPrefs::UpdatePreferences(int delay_ms) {
- BrowserThread::PostDelayedTask(
- BrowserThread::FILE,
- FROM_HERE,
- NewRunnableMethod(this, &PluginPrefs::GetPreferencesDataOnFileThread),
- delay_ms);
+void PluginPrefs::SetPolicyEnforcedPluginPatterns(
+ const std::set<string16>& disabled_patterns,
+ const std::set<string16>& disabled_exception_patterns,
+ const std::set<string16>& enabled_patterns) {
+ policy_disabled_plugin_patterns_ = disabled_patterns;
+ policy_disabled_plugin_exception_patterns_ = disabled_exception_patterns;
+ policy_enabled_plugin_patterns_ = enabled_patterns;
}
void PluginPrefs::GetPreferencesDataOnFileThread() {
- std::vector<webkit::WebPluginInfo> plugins;
std::vector<webkit::npapi::PluginGroup> groups;
webkit::npapi::PluginList* plugin_list =
webkit::npapi::PluginList::Singleton();
- plugin_list->GetPlugins(&plugins);
plugin_list->GetPluginGroups(false, &groups);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences,
- plugins, groups));
+ NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, groups));
}
void PluginPrefs::OnUpdatePreferences(
- std::vector<webkit::WebPluginInfo> plugins,
std::vector<webkit::npapi::PluginGroup> groups) {
if (!prefs_)
return;
@@ -402,44 +544,42 @@ void PluginPrefs::OnUpdatePreferences(
if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
prefs_->SetFilePath(prefs::kPluginsLastInternalDirectory, internal_dir);
- // Add the plugin files.
- for (size_t i = 0; i < plugins.size(); ++i) {
- DictionaryValue* summary = CreatePluginFileSummary(plugins[i]);
- // If the plugin is managed by policy, store the user preferred state
- // instead.
- if (plugins[i].enabled & webkit::WebPluginInfo::MANAGED_MASK) {
- bool user_enabled =
- (plugins[i].enabled & webkit::WebPluginInfo::USER_MASK) ==
- webkit::WebPluginInfo::USER_ENABLED;
- summary->SetBoolean("enabled", user_enabled);
- }
- plugins_list->Append(summary);
- }
+ base::AutoLock auto_lock(lock_);
- // Add the groups as well.
+ // Add the plug-in groups.
for (size_t i = 0; i < groups.size(); ++i) {
- DictionaryValue* summary = groups[i].GetSummary();
- // If the plugin is disabled only by policy don't store this state in the
- // user pref store.
- if (!groups[i].Enabled() &&
- webkit::npapi::PluginGroup::IsPluginNameDisabledByPolicy(
- groups[i].GetGroupName()))
- summary->SetBoolean("enabled", true);
+ // Add the plugin files to the same list.
+ const std::vector<webkit::WebPluginInfo>& plugins =
+ groups[i].web_plugin_infos();
+ for (size_t j = 0; j < plugins.size(); ++j) {
+ DictionaryValue* summary = new DictionaryValue();
+ summary->SetString("path", plugins[j].path.value());
+ summary->SetString("name", plugins[j].name);
+ summary->SetString("version", plugins[j].version);
+ bool enabled = true;
+ std::map<FilePath, bool>::iterator it =
+ plugin_state_.find(plugins[j].path);
+ if (it != plugin_state_.end())
+ enabled = it->second;
+ summary->SetBoolean("enabled", enabled);
plugins_list->Append(summary);
+ }
+
+ DictionaryValue* summary = new DictionaryValue();
+ string16 name = groups[i].GetGroupName();
+ summary->SetString("name", name);
+ bool enabled = true;
+ std::map<string16, bool>::iterator it =
+ plugin_group_state_.find(name);
+ if (it != plugin_group_state_.end())
+ enabled = it->second;
+ summary->SetBoolean("enabled", enabled);
+ plugins_list->Append(summary);
}
}
void PluginPrefs::NotifyPluginStatusChanged() {
- if (notify_pending_)
- return;
- notify_pending_ = true;
- MessageLoop::current()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &PluginPrefs::OnNotifyPluginStatusChanged));
-}
-
-void PluginPrefs::OnNotifyPluginStatusChanged() {
- notify_pending_ = false;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NotificationService::current()->Notify(
chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
Source<PluginPrefs>(this),
diff --git a/chrome/browser/plugin_prefs.h b/chrome/browser/plugin_prefs.h
index d55a600..ecfd585 100644
--- a/chrome/browser/plugin_prefs.h
+++ b/chrome/browser/plugin_prefs.h
@@ -6,12 +6,14 @@
#define CHROME_BROWSER_PLUGIN_PREFS_H_
#pragma once
+#include <map>
#include <set>
#include <vector>
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
#include "chrome/browser/prefs/pref_change_registrar.h"
#include "content/common/notification_observer.h"
@@ -37,11 +39,16 @@ class PluginGroup;
// This class stores information about whether a plug-in or a plug-in group is
// enabled or disabled.
-// Except for the |IsPluginEnabled| method, it should only be used on the UI
-// thread.
+// Except where otherwise noted, it can be used on every thread.
class PluginPrefs : public base::RefCountedThreadSafe<PluginPrefs>,
public NotificationObserver {
public:
+ enum PolicyStatus {
+ NO_POLICY = 0, // Neither enabled or disabled by policy.
+ POLICY_ENABLED,
+ POLICY_DISABLED,
+ };
+
// Initializes the factory for this class for dependency tracking.
// This should be called before the first profile is created.
static void Initialize();
@@ -49,77 +56,96 @@ class PluginPrefs : public base::RefCountedThreadSafe<PluginPrefs>,
// Returns the instance associated with |profile|, creating it if necessary.
static PluginPrefs* GetForProfile(Profile* profile);
+ // Usually the PluginPrefs associated with a TestingProfile is NULL.
+ // This method overrides that for a given TestingProfile, returning the newly
+ // created PluginPrefs object.
+ static PluginPrefs* GetForTestingProfile(Profile* profile);
+
// Creates a new instance. This method should only be used for testing.
PluginPrefs();
// Associates this instance with |prefs|. This enables or disables
// plugin groups as defined by the user's preferences.
+ // This method should only be called on the UI thread.
void SetPrefs(PrefService* prefs);
+ // Detaches from the PrefService before it is destroyed.
+ // As the name says, this method should only be called on the UI thread.
+ void ShutdownOnUIThread();
+
// Enable or disable a plugin group.
void EnablePluginGroup(bool enable, const string16& group_name);
// Enable or disable a specific plugin file.
void EnablePlugin(bool enable, const FilePath& file_path);
+ // Enable or disable a plug-in in all profiles. This sets a default for
+ // profiles which are created later as well.
+ // This method should only be called on the UI thread.
+ static void EnablePluginGlobally(bool enable, const FilePath& file_path);
+
+ // Returns whether there is a policy enabling or disabling plug-ins of the
+ // given name.
+ PolicyStatus PolicyStatusForPlugin(const string16& name);
+
// Returns whether the plugin is enabled or not.
bool IsPluginEnabled(const webkit::WebPluginInfo& plugin);
- // Write the enable/disable status to the user's preference file.
- void UpdatePreferences(int delay_ms);
+ // Registers the preferences used by this class.
+ // This method should only be called on the UI thread.
+ static void RegisterPrefs(PrefService* prefs);
- // NotificationObserver method overrides
+ // NotificationObserver method override.
virtual void Observe(int type,
const NotificationSource& source,
- const NotificationDetails& details);
-
- static void RegisterPrefs(PrefService* prefs);
-
- void ShutdownOnUIThread();
+ const NotificationDetails& details) OVERRIDE;
private:
friend class base::RefCountedThreadSafe<PluginPrefs>;
+ friend class PluginPrefsTest;
class Factory;
virtual ~PluginPrefs();
+ // Allows unit tests to directly set enforced plug-in patterns.
+ void SetPolicyEnforcedPluginPatterns(
+ const std::set<string16>& disabled_patterns,
+ const std::set<string16>& disabled_exception_patterns,
+ const std::set<string16>& enabled_patterns);
+
// Called on the file thread to get the data necessary to update the saved
// preferences.
void GetPreferencesDataOnFileThread();
// Called on the UI thread with the plugin data to save the preferences.
- void OnUpdatePreferences(std::vector<webkit::WebPluginInfo> plugins,
- std::vector<webkit::npapi::PluginGroup> groups);
+ void OnUpdatePreferences(std::vector<webkit::npapi::PluginGroup> groups);
- // Queues sending the notification that plugin data has changed. This is done
- // so that if a bunch of changes happen, we only send one notification.
+ // Sends the notification that plugin data has changed.
void NotifyPluginStatusChanged();
- // Used for the post task to notify that plugin enabled status changed.
- void OnNotifyPluginStatusChanged();
+ static void ListValueToStringSet(const base::ListValue* src,
+ std::set<string16>* dest);
+
+ // Checks if |name| matches any of the patterns in |pattern_set|.
+ static bool IsStringMatchedInSet(const string16& name,
+ const std::set<string16>& pattern_set);
- base::DictionaryValue* CreatePluginFileSummary(
- const webkit::WebPluginInfo& plugin);
+ // Guards access to the following data structures.
+ mutable base::Lock lock_;
- // Force plugins to be enabled or disabled due to policy.
- // |disabled_list| contains the list of StringValues of the names of the
- // policy-disabled plugins, |exceptions_list| the policy-allowed plugins,
- // and |enabled_list| the policy-enabled plugins.
- void UpdatePluginsStateFromPolicy(const base::ListValue* disabled_list,
- const base::ListValue* exceptions_list,
- const base::ListValue* enabled_list);
+ std::map<FilePath, bool> plugin_state_;
+ std::map<string16, bool> plugin_group_state_;
- void ListValueToStringSet(const base::ListValue* src,
- std::set<string16>* dest);
+ std::set<string16> policy_disabled_plugin_patterns_;
+ std::set<string16> policy_disabled_plugin_exception_patterns_;
+ std::set<string16> policy_enabled_plugin_patterns_;
- // Weak pointer, owned by the profile.
+ // Weak pointer, owned by the profile (which owns us).
PrefService* prefs_;
PrefChangeRegistrar registrar_;
- bool notify_pending_;
-
DISALLOW_COPY_AND_ASSIGN(PluginPrefs);
};
diff --git a/chrome/browser/plugin_prefs_unittest.cc b/chrome/browser/plugin_prefs_unittest.cc
new file mode 100644
index 0000000..934d478
--- /dev/null
+++ b/chrome/browser/plugin_prefs_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/plugin_prefs.h"
+
+#include "base/utf_string_conversions.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/plugins/webplugininfo.h"
+
+class PluginPrefsTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ plugin_prefs_ = new PluginPrefs();
+ }
+
+ void SetPolicyEnforcedPluginPatterns(
+ const std::set<string16>& disabled,
+ const std::set<string16>& disabled_exceptions,
+ const std::set<string16>& enabled) {
+ plugin_prefs_->SetPolicyEnforcedPluginPatterns(
+ disabled, disabled_exceptions, enabled);
+ }
+
+ protected:
+ scoped_refptr<PluginPrefs> plugin_prefs_;
+};
+
+TEST_F(PluginPrefsTest, DisabledByPolicy) {
+ std::set<string16> disabled_plugins;
+ disabled_plugins.insert(ASCIIToUTF16("Disable this!"));
+ disabled_plugins.insert(ASCIIToUTF16("*Google*"));
+ SetPolicyEnforcedPluginPatterns(disabled_plugins,
+ std::set<string16>(),
+ std::set<string16>());
+
+ EXPECT_EQ(PluginPrefs::NO_POLICY,
+ plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("42")));
+ EXPECT_EQ(PluginPrefs::POLICY_DISABLED,
+ plugin_prefs_->PolicyStatusForPlugin(
+ ASCIIToUTF16("Disable this!")));
+ EXPECT_EQ(PluginPrefs::POLICY_DISABLED,
+ plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("Google Earth")));
+}
+
+TEST_F(PluginPrefsTest, EnabledByPolicy) {
+ std::set<string16> enabled_plugins;
+ enabled_plugins.insert(ASCIIToUTF16("Enable that!"));
+ enabled_plugins.insert(ASCIIToUTF16("PDF*"));
+ SetPolicyEnforcedPluginPatterns(std::set<string16>(),
+ std::set<string16>(),
+ enabled_plugins);
+
+ EXPECT_EQ(PluginPrefs::NO_POLICY,
+ plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("42")));
+ EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
+ plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("Enable that!")));
+ EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
+ plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("PDF Reader")));
+}
+
+TEST_F(PluginPrefsTest, EnabledAndDisabledByPolicy) {
+ const string16 k42(ASCIIToUTF16("42"));
+ const string16 kEnabled(ASCIIToUTF16("Enabled"));
+ const string16 kEnabled2(ASCIIToUTF16("Enabled 2"));
+ const string16 kEnabled3(ASCIIToUTF16("Enabled 3"));
+ const string16 kException(ASCIIToUTF16("Exception"));
+ const string16 kException2(ASCIIToUTF16("Exception 2"));
+ const string16 kGoogleMars(ASCIIToUTF16("Google Mars"));
+ const string16 kGoogleEarth(ASCIIToUTF16("Google Earth"));
+
+ std::set<string16> disabled_plugins;
+ std::set<string16> disabled_plugins_exceptions;
+ std::set<string16> enabled_plugins;
+
+ disabled_plugins.insert(kEnabled);
+ disabled_plugins_exceptions.insert(kEnabled);
+ enabled_plugins.insert(kEnabled);
+
+ disabled_plugins_exceptions.insert(kException);
+
+ disabled_plugins.insert(kEnabled2);
+ enabled_plugins.insert(kEnabled2);
+
+ disabled_plugins.insert(kException2);
+ disabled_plugins_exceptions.insert(kException2);
+
+ disabled_plugins_exceptions.insert(kEnabled3);
+ enabled_plugins.insert(kEnabled3);
+
+ SetPolicyEnforcedPluginPatterns(disabled_plugins,
+ disabled_plugins_exceptions,
+ enabled_plugins);
+
+ EXPECT_EQ(PluginPrefs::NO_POLICY, plugin_prefs_->PolicyStatusForPlugin(k42));
+
+ EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
+ plugin_prefs_->PolicyStatusForPlugin(kEnabled));
+ EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
+ plugin_prefs_->PolicyStatusForPlugin(kEnabled2));
+ EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
+ plugin_prefs_->PolicyStatusForPlugin(kEnabled3));
+
+ EXPECT_EQ(PluginPrefs::NO_POLICY,
+ plugin_prefs_->PolicyStatusForPlugin(kException));
+ EXPECT_EQ(PluginPrefs::NO_POLICY,
+ plugin_prefs_->PolicyStatusForPlugin(kException2));
+
+ disabled_plugins.clear();
+ disabled_plugins_exceptions.clear();
+ enabled_plugins.clear();
+
+ disabled_plugins.insert(ASCIIToUTF16("*"));
+ disabled_plugins_exceptions.insert(ASCIIToUTF16("*Google*"));
+ enabled_plugins.insert(kGoogleEarth);
+
+ SetPolicyEnforcedPluginPatterns(disabled_plugins,
+ disabled_plugins_exceptions,
+ enabled_plugins);
+
+ EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
+ plugin_prefs_->PolicyStatusForPlugin(kGoogleEarth));
+ EXPECT_EQ(PluginPrefs::NO_POLICY,
+ plugin_prefs_->PolicyStatusForPlugin(kGoogleMars));
+ EXPECT_EQ(PluginPrefs::POLICY_DISABLED,
+ plugin_prefs_->PolicyStatusForPlugin(k42));
+}
+
+TEST_F(PluginPrefsTest, DisableGlobally) {
+ MessageLoop message_loop;
+ BrowserThread ui_thread(BrowserThread::UI, &message_loop);
+ BrowserThread file_thread(BrowserThread::FILE, &message_loop);
+
+ TestingBrowserProcess* browser_process =
+ static_cast<TestingBrowserProcess*>(g_browser_process);
+ TestingProfileManager profile_manager(browser_process);
+ ASSERT_TRUE(profile_manager.SetUp());
+
+ TestingProfile* profile_1 =
+ profile_manager.CreateTestingProfile("Profile 1");
+ PluginPrefs* plugin_prefs = PluginPrefs::GetForTestingProfile(profile_1);
+ ASSERT_TRUE(plugin_prefs);
+
+ webkit::WebPluginInfo plugin(ASCIIToUTF16("Foo"),
+ FilePath(FILE_PATH_LITERAL("/path/too/foo")),
+ ASCIIToUTF16("1.0.0"),
+ ASCIIToUTF16("Foo plug-in"));
+ PluginPrefs::EnablePluginGlobally(false, plugin.path);
+
+ EXPECT_FALSE(plugin_prefs->IsPluginEnabled(plugin));
+
+ TestingProfile* profile_2 =
+ profile_manager.CreateTestingProfile("Profile 2");
+ PluginPrefs* plugin_prefs_2 = PluginPrefs::GetForTestingProfile(profile_2);
+ ASSERT_TRUE(plugin_prefs);
+ EXPECT_FALSE(plugin_prefs_2->IsPluginEnabled(plugin));
+}
diff --git a/chrome/browser/printing/print_preview_tab_controller.cc b/chrome/browser/printing/print_preview_tab_controller.cc
index aeb32b9..1557e0d 100644
--- a/chrome/browser/printing/print_preview_tab_controller.cc
+++ b/chrome/browser/printing/print_preview_tab_controller.cc
@@ -52,11 +52,11 @@ void EnableInternalPDFPluginForTab(TabContentsWrapper* preview_tab) {
}
}
if (internal_pdf_group) {
- std::vector<WebPluginInfo> plugins = internal_pdf_group->web_plugin_infos();
+ const std::vector<WebPluginInfo>& plugins =
+ internal_pdf_group->web_plugin_infos();
DCHECK_EQ(plugins.size(), 1U);
webkit::WebPluginInfo plugin = plugins[0];
- plugin.enabled = WebPluginInfo::USER_ENABLED;
ChromePluginServiceFilter::GetInstance()->OverridePluginForTab(
preview_tab->render_view_host()->process()->id(),
preview_tab->render_view_host()->routing_id(),
diff --git a/chrome/browser/ui/webui/plugins_ui.cc b/chrome/browser/ui/webui/plugins_ui.cc
index 710f423..a4f0dfe 100644
--- a/chrome/browser/ui/webui/plugins_ui.cc
+++ b/chrome/browser/ui/webui/plugins_ui.cc
@@ -36,6 +36,9 @@
#include "ui/base/resource/resource_bundle.h"
#include "webkit/plugins/npapi/plugin_list.h"
+using webkit::npapi::PluginGroup;
+using webkit::WebPluginInfo;
+
namespace {
ChromeWebUIDataSource* CreatePluginsUIHTMLSource(bool enable_controls) {
@@ -125,17 +128,17 @@ class PluginsDOMHandler : public WebUIMessageHandler,
private:
// Loads the plugins on the FILE thread.
static void LoadPluginsOnFileThread(
- std::vector<webkit::npapi::PluginGroup>* groups, Task* task);
+ std::vector<PluginGroup>* groups, Task* task);
// Used in conjunction with ListWrapper to avoid any memory leaks.
static void EnsurePluginGroupsDeleted(
- std::vector<webkit::npapi::PluginGroup>* groups);
+ std::vector<PluginGroup>* groups);
// Call this to start getting the plugins on the UI thread.
void LoadPlugins();
// Called on the UI thread when the plugin information is ready.
- void PluginsLoaded(const std::vector<webkit::npapi::PluginGroup>* groups);
+ void PluginsLoaded(const std::vector<PluginGroup>* groups);
NotificationRegistrar registrar_;
@@ -181,13 +184,6 @@ void PluginsDOMHandler::HandleRequestPluginsData(const ListValue* args) {
void PluginsDOMHandler::HandleEnablePluginMessage(const ListValue* args) {
Profile* profile = Profile::FromWebUI(web_ui_);
- // If a non-first-profile user tries to trigger these methods sneakily,
- // forbid it.
-#if !defined(OS_CHROMEOS)
- if (!profile->GetOriginalProfile()->first_launched())
- return;
-#endif
-
// Be robust in accepting badness since plug-ins display HTML (hence
// JavaScript).
if (args->GetSize() != 3)
@@ -209,27 +205,20 @@ void PluginsDOMHandler::HandleEnablePluginMessage(const ListValue* args) {
if (enable) {
// See http://crbug.com/50105 for background.
string16 adobereader = ASCIIToUTF16(
- webkit::npapi::PluginGroup::kAdobeReaderGroupName);
+ PluginGroup::kAdobeReaderGroupName);
string16 internalpdf =
ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName);
- if (group_name == adobereader) {
+ if (group_name == adobereader)
plugin_prefs->EnablePluginGroup(false, internalpdf);
- } else if (group_name == internalpdf) {
+ else if (group_name == internalpdf)
plugin_prefs->EnablePluginGroup(false, adobereader);
- }
}
} else {
FilePath::StringType file_path;
if (!args->GetString(0, &file_path))
return;
-
plugin_prefs->EnablePlugin(enable, FilePath(file_path));
}
-
- // TODO(viettrungluu): We might also want to ensure that the plugins
- // list is always written to prefs even when the user hasn't disabled a
- // plugin. <http://crbug.com/39101>
- plugin_prefs->UpdatePreferences(0);
}
void PluginsDOMHandler::HandleSaveShowDetailsToPrefs(const ListValue* args) {
@@ -254,7 +243,7 @@ void PluginsDOMHandler::Observe(int type,
}
void PluginsDOMHandler::LoadPluginsOnFileThread(
- std::vector<webkit::npapi::PluginGroup>* groups,
+ std::vector<PluginGroup>* groups,
Task* task) {
webkit::npapi::PluginList::Singleton()->GetPluginGroups(true, groups);
@@ -267,7 +256,7 @@ void PluginsDOMHandler::LoadPluginsOnFileThread(
}
void PluginsDOMHandler::EnsurePluginGroupsDeleted(
- std::vector<webkit::npapi::PluginGroup>* groups) {
+ std::vector<PluginGroup>* groups) {
delete groups;
}
@@ -275,8 +264,7 @@ void PluginsDOMHandler::LoadPlugins() {
if (!get_plugins_factory_.empty())
return;
- std::vector<webkit::npapi::PluginGroup>* groups =
- new std::vector<webkit::npapi::PluginGroup>;
+ std::vector<PluginGroup>* groups = new std::vector<PluginGroup>;
Task* task = get_plugins_factory_.NewRunnableMethod(
&PluginsDOMHandler::PluginsLoaded, groups);
@@ -287,13 +275,103 @@ void PluginsDOMHandler::LoadPlugins() {
&PluginsDOMHandler::LoadPluginsOnFileThread, groups, task));
}
-void PluginsDOMHandler::PluginsLoaded(
- const std::vector<webkit::npapi::PluginGroup>* groups) {
+void PluginsDOMHandler::PluginsLoaded(const std::vector<PluginGroup>* groups) {
+ PluginPrefs* plugin_prefs =
+ PluginPrefs::GetForProfile(Profile::FromWebUI(web_ui_));
+
+ bool all_plugins_enabled_by_policy = true;
+ bool all_plugins_disabled_by_policy = true;
+
// Construct DictionaryValues to return to the UI
ListValue* plugin_groups_data = new ListValue();
for (size_t i = 0; i < groups->size(); ++i) {
- plugin_groups_data->Append((*groups)[i].GetDataForUI());
- // TODO(bauerb): Fetch plugin enabled state from PluginPrefs.
+ ListValue* plugin_files = new ListValue();
+ const PluginGroup& group = (*groups)[i];
+ string16 group_name = group.GetGroupName();
+ bool group_enabled = false;
+ const WebPluginInfo* active_plugin = NULL;
+ for (size_t j = 0; j < group.web_plugin_infos().size(); ++j) {
+ const WebPluginInfo& group_plugin = group.web_plugin_infos()[j];
+
+ DictionaryValue* plugin_file = new DictionaryValue();
+ plugin_file->SetString("name", group_plugin.name);
+ plugin_file->SetString("description", group_plugin.desc);
+ plugin_file->SetString("path", group_plugin.path.value());
+ plugin_file->SetString("version", group_plugin.version);
+
+ ListValue* mime_types = new ListValue();
+ const std::vector<webkit::WebPluginMimeType>& plugin_mime_types =
+ group_plugin.mime_types;
+ for (size_t k = 0; k < plugin_mime_types.size(); ++k) {
+ DictionaryValue* mime_type = new DictionaryValue();
+ mime_type->SetString("mimeType", plugin_mime_types[k].mime_type);
+ mime_type->SetString("description", plugin_mime_types[k].description);
+
+ ListValue* file_extensions = new ListValue();
+ const std::vector<std::string>& mime_file_extensions =
+ plugin_mime_types[k].file_extensions;
+ for (size_t l = 0; l < mime_file_extensions.size(); ++l)
+ file_extensions->Append(new StringValue(mime_file_extensions[l]));
+ mime_type->Set("fileExtensions", file_extensions);
+
+ mime_types->Append(mime_type);
+ }
+ plugin_file->Set("mimeTypes", mime_types);
+
+ bool plugin_enabled = plugin_prefs->IsPluginEnabled(group_plugin);
+
+ if (!active_plugin || (plugin_enabled && !group_enabled))
+ active_plugin = &group_plugin;
+ group_enabled = plugin_enabled || group_enabled;
+
+ std::string enabled_mode;
+ PluginPrefs::PolicyStatus plugin_status =
+ plugin_prefs->PolicyStatusForPlugin(group_plugin.name);
+ PluginPrefs::PolicyStatus group_status =
+ plugin_prefs->PolicyStatusForPlugin(group_name);
+ if (plugin_status == PluginPrefs::POLICY_ENABLED ||
+ group_status == PluginPrefs::POLICY_ENABLED) {
+ enabled_mode = "enabledByPolicy";
+ } else {
+ all_plugins_enabled_by_policy = false;
+ if (plugin_status == PluginPrefs::POLICY_DISABLED ||
+ group_status == PluginPrefs::POLICY_DISABLED) {
+ enabled_mode = "disabledByPolicy";
+ } else {
+ all_plugins_disabled_by_policy = false;
+ if (plugin_enabled) {
+ enabled_mode = "enabledByUser";
+ } else {
+ enabled_mode = "disabledByUser";
+ }
+ }
+ }
+ plugin_file->SetString("enabledMode", enabled_mode);
+
+ plugin_files->Append(plugin_file);
+ }
+ DictionaryValue* group_data = new DictionaryValue();
+
+ group_data->Set("plugin_files", plugin_files);
+ group_data->SetString("name", group_name);
+ group_data->SetString("description", active_plugin->desc);
+ group_data->SetString("version", active_plugin->version);
+ group_data->SetBoolean("critical", group.IsVulnerable(*active_plugin));
+ group_data->SetString("update_url", group.GetUpdateURL());
+
+ std::string enabled_mode;
+ if (all_plugins_enabled_by_policy) {
+ enabled_mode = "enabledByPolicy";
+ } else if (all_plugins_disabled_by_policy) {
+ enabled_mode = "disabledByPolicy";
+ } else if (group_enabled) {
+ enabled_mode = "enabledByUser";
+ } else {
+ enabled_mode = "disabledByUser";
+ }
+ group_data->SetString("enabledMode", enabled_mode);
+
+ plugin_groups_data->Append(group_data);
}
DictionaryValue results;
results.Set("plugins", plugin_groups_data);
@@ -312,11 +390,9 @@ PluginsUI::PluginsUI(TabContents* contents) : ChromeWebUI(contents) {
AddMessageHandler((new PluginsDOMHandler())->Attach(this));
// Set up the chrome://plugins/ source.
+ // TODO(bauerb): Remove |enable_controls| & co.
bool enable_controls = true;
Profile* profile = Profile::FromBrowserContext(contents->browser_context());
-#if !defined(OS_CHROMEOS)
- enable_controls = profile->GetOriginalProfile()->first_launched();
-#endif
profile->GetChromeURLDataManager()->AddDataSource(
CreatePluginsUIHTMLSource(enable_controls));
}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 067b18c..380bc4a 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1348,6 +1348,7 @@
'browser/password_manager/password_store_win_unittest.cc',
'browser/password_manager/password_store_x_unittest.cc',
'browser/plugin_exceptions_table_model_unittest.cc',
+ 'browser/plugin_prefs_unittest.cc',
'browser/policy/asynchronous_policy_loader_unittest.cc',
'browser/policy/asynchronous_policy_provider_unittest.cc',
'browser/policy/asynchronous_policy_test_base.cc',
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index e8c6d57..5b64ee4 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -331,9 +331,8 @@ WebPlugin* ChromeContentRendererClient::CreatePluginImpl(
return NULL;
}
- const webkit::npapi::PluginGroup* group =
- webkit::npapi::PluginList::Singleton()->GetPluginGroup(info);
- DCHECK(group != NULL);
+ scoped_ptr<webkit::npapi::PluginGroup> group(
+ webkit::npapi::PluginList::Singleton()->GetPluginGroup(info));
ContentSetting plugin_setting = CONTENT_SETTING_DEFAULT;
std::string resource;
@@ -356,14 +355,14 @@ WebPlugin* ChromeContentRendererClient::CreatePluginImpl(
ContentSetting outdated_policy = CONTENT_SETTING_ASK;
ContentSetting authorize_policy = CONTENT_SETTING_ASK;
- if (group->IsVulnerable() || group->RequiresAuthorization()) {
+ if (group->IsVulnerable(info) || group->RequiresAuthorization(info)) {
// These policies are dynamic and can changed at runtime, so they aren't
// cached here.
render_view->Send(new ChromeViewHostMsg_GetPluginPolicies(
&outdated_policy, &authorize_policy));
}
- if (group->IsVulnerable()) {
+ if (group->IsVulnerable(info)) {
if (outdated_policy == CONTENT_SETTING_ASK ||
outdated_policy == CONTENT_SETTING_BLOCK) {
if (outdated_policy == CONTENT_SETTING_ASK) {
@@ -383,7 +382,7 @@ WebPlugin* ChromeContentRendererClient::CreatePluginImpl(
ContentSetting host_setting =
observer->GetContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
- if (group->RequiresAuthorization() &&
+ if (group->RequiresAuthorization(info) &&
authorize_policy == CONTENT_SETTING_ASK &&
(plugin_setting == CONTENT_SETTING_ALLOW ||
plugin_setting == CONTENT_SETTING_ASK) &&