diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-15 15:33:45 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-15 15:33:45 +0000 |
commit | f7be2cbadb7d6f2f96ea6a836f70961640bdb5e6 (patch) | |
tree | 14a6c5f61d11697047bb0d6a08625271f314fe45 /chrome | |
parent | 411f5d0bcab149cbea4c482a06bfd7c851a71c7d (diff) | |
download | chromium_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.cc | 14 | ||||
-rw-r--r-- | chrome/browser/chromeos/gview_request_interceptor_unittest.cc | 8 | ||||
-rw-r--r-- | chrome/browser/component_updater/pepper_flash_component_installer.cc | 6 | ||||
-rw-r--r-- | chrome/browser/pdf_unsupported_feature.cc | 21 | ||||
-rw-r--r-- | chrome/browser/plugin_exceptions_table_model_unittest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/plugin_prefs.cc | 354 | ||||
-rw-r--r-- | chrome/browser/plugin_prefs.h | 86 | ||||
-rw-r--r-- | chrome/browser/plugin_prefs_unittest.cc | 160 | ||||
-rw-r--r-- | chrome/browser/printing/print_preview_tab_controller.cc | 4 | ||||
-rw-r--r-- | chrome/browser/ui/webui/plugins_ui.cc | 138 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 11 |
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) && |