diff options
33 files changed, 525 insertions, 243 deletions
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index c46580a..57fc0c4 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -20,6 +20,7 @@ #include "chrome/browser/browser_main.h" #include "chrome/browser/browser_process_sub_thread.h" #include "chrome/browser/browser_trial.h" +#include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/component_updater/component_updater_configurator.h" #include "chrome/browser/component_updater/component_updater_service.h" #include "chrome/browser/debugger/devtools_protocol_handler.h" @@ -739,7 +740,9 @@ void BrowserProcessImpl::CreateIOThread() { // it is predominantly used from the io thread, but must be created // on the main thread. The service ctor is inexpensive and does not // invoke the io_thread() accessor. - PluginService::GetInstance(); + PluginService* plugin_service = PluginService::GetInstance(); + plugin_service->set_filter(ChromePluginServiceFilter::GetInstance()); + plugin_service->StartWatchingPlugins(); // Add the Chrome specific plugins. chrome::RegisterInternalDefaultPlugin(); diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc index bd05876..6f8a387 100644 --- a/chrome/browser/browsing_data_remover.cc +++ b/chrome/browser/browsing_data_remover.cc @@ -276,7 +276,7 @@ void BrowsingDataRemover::Remove(int remove_mask) { waiting_for_clear_lso_data_ = true; if (!plugin_data_remover_.get()) - plugin_data_remover_ = new PluginDataRemover(); + plugin_data_remover_ = new PluginDataRemover(profile_); base::WaitableEvent* event = plugin_data_remover_->StartRemoving(delete_begin_); watcher_.StartWatching(event, this); diff --git a/chrome/browser/chrome_plugin_service_filter.cc b/chrome/browser/chrome_plugin_service_filter.cc new file mode 100644 index 0000000..23e11c8 --- /dev/null +++ b/chrome/browser/chrome_plugin_service_filter.cc @@ -0,0 +1,139 @@ +// 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/chrome_plugin_service_filter.h" + +#include "base/logging.h" +#include "chrome/browser/plugin_prefs.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_notification_types.h" +#include "content/browser/browser_thread.h" +#include "content/browser/plugin_service.h" +#include "content/browser/renderer_host/render_process_host.h" +#include "content/browser/resource_context.h" +#include "content/common/notification_service.h" +#include "webkit/plugins/npapi/plugin_list.h" + +// static +ChromePluginServiceFilter* ChromePluginServiceFilter::GetInstance() { + return Singleton<ChromePluginServiceFilter>::get(); +} + +void ChromePluginServiceFilter::RegisterResourceContext( + PluginPrefs* plugin_prefs, + const void* context) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + base::AutoLock lock(lock_); + resource_context_map_[context] = plugin_prefs; +} + +void ChromePluginServiceFilter::UnregisterResourceContext( + const void* context) { + base::AutoLock lock(lock_); + resource_context_map_.erase(context); +} + +void ChromePluginServiceFilter::OverridePluginForTab( + int render_process_id, + int render_view_id, + const GURL& url, + const webkit::WebPluginInfo& plugin) { + OverriddenPlugin overridden_plugin; + overridden_plugin.render_process_id = render_process_id; + overridden_plugin.render_view_id = render_view_id; + overridden_plugin.url = url; + overridden_plugin.plugin = plugin; + base::AutoLock auto_lock(lock_); + overridden_plugins_.push_back(overridden_plugin); +} + +void ChromePluginServiceFilter::RestrictPluginToUrl(const FilePath& plugin_path, + const GURL& url) { + base::AutoLock auto_lock(lock_); + if (url.is_empty()) + restricted_plugins_.erase(plugin_path); + else + restricted_plugins_[plugin_path] = url; +} + +bool ChromePluginServiceFilter::ShouldUsePlugin( + int render_process_id, + int render_view_id, + const void* context, + const GURL& url, + const GURL& policy_url, + webkit::WebPluginInfo* plugin) { + base::AutoLock auto_lock(lock_); + // Check whether the plugin is overridden. + for (size_t i = 0; i < overridden_plugins_.size(); ++i) { + if (overridden_plugins_[i].render_process_id == render_process_id && + overridden_plugins_[i].render_view_id == render_view_id && + (overridden_plugins_[i].url == url || + overridden_plugins_[i].url.is_empty())) { + if (overridden_plugins_[i].plugin.path != plugin->path) + return false; + *plugin = overridden_plugins_[i].plugin; + return true; + } + } + + // Check whether the plugin is disabled. + ResourceContextMap::iterator prefs_it = + resource_context_map_.find(context); + if (prefs_it == resource_context_map_.end()) + return false; + + PluginPrefs* plugin_prefs = prefs_it->second.get(); + if (!plugin_prefs->IsPluginEnabled(*plugin)) + return false; + + // Check whether the plugin is restricted to a URL. + RestrictedPluginMap::const_iterator it = + restricted_plugins_.find(plugin->path); + if (it != restricted_plugins_.end() && + (policy_url.scheme() != it->second.scheme() || + policy_url.host() != it->second.host())) { + return false; + } + + return true; +} + +ChromePluginServiceFilter::ChromePluginServiceFilter() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, + NotificationService::AllSources()); + registrar_.Add(this, chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, + NotificationService::AllSources()); +} + +ChromePluginServiceFilter::~ChromePluginServiceFilter() { +} + +void ChromePluginServiceFilter::Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + switch (type) { + case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { + int render_process_id = Source<RenderProcessHost>(source).ptr()->id(); + + base::AutoLock auto_lock(lock_); + for (size_t i = 0; i < overridden_plugins_.size(); ++i) { + if (overridden_plugins_[i].render_process_id == render_process_id) { + overridden_plugins_.erase(overridden_plugins_.begin() + i); + break; + } + } + break; + } + case chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED: { + PluginService::GetInstance()->PurgePluginListCache(false); + break; + } + default: { + NOTREACHED(); + } + } +} diff --git a/chrome/browser/chrome_plugin_service_filter.h b/chrome/browser/chrome_plugin_service_filter.h new file mode 100644 index 0000000..81bbfa1 --- /dev/null +++ b/chrome/browser/chrome_plugin_service_filter.h @@ -0,0 +1,87 @@ +// 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. + +#ifndef CHROME_BROWSER_CHROME_PLUGIN_SERVICE_FILTER_H_ +#define CHROME_BROWSER_CHROME_PLUGIN_SERVICE_FILTER_H_ +#pragma once + +#include <map> +#include <vector> + +#include "base/hash_tables.h" +#include "base/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/singleton.h" +#include "base/synchronization/lock.h" +#include "content/browser/plugin_service_filter.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_registrar.h" +#include "googleurl/src/gurl.h" +#include "webkit/plugins/webplugininfo.h" + +class PluginPrefs; + +// This class must be created (by calling the |GetInstance| method) on the UI +// thread, but is safe to use on any thread after that. +class ChromePluginServiceFilter : public content::PluginServiceFilter, + public NotificationObserver { + public: + static ChromePluginServiceFilter* GetInstance(); + + // This method should be called on the UI thread. + void RegisterResourceContext(PluginPrefs* plugin_prefs, const void* context); + + void UnregisterResourceContext(const void* context); + + // Overrides the plugin lookup mechanism for a given tab and object URL to use + // a specifc plugin. + void OverridePluginForTab(int render_process_id, + int render_view_id, + const GURL& url, + const webkit::WebPluginInfo& plugin); + + // Restricts the given plugin to the the scheme and host of the given url. + // Call with an empty url to reset this. + void RestrictPluginToUrl(const FilePath& plugin_path, const GURL& url); + + // PluginServiceFilter implementation: + virtual bool ShouldUsePlugin( + int render_process_id, + int render_view_id, + const void* context, + const GURL& url, + const GURL& policy_url, + webkit::WebPluginInfo* plugin) OVERRIDE; + + private: + friend struct DefaultSingletonTraits<ChromePluginServiceFilter>; + + struct OverriddenPlugin { + int render_process_id; + int render_view_id; + GURL url; // If empty, the override applies to all urls in render_view. + webkit::WebPluginInfo plugin; + }; + + ChromePluginServiceFilter(); + virtual ~ChromePluginServiceFilter(); + + // NotificationObserver implementation: + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details); + + NotificationRegistrar registrar_; + + base::Lock lock_; // Guards access to member variables. + // Map of plugin paths to the origin they are restricted to. + typedef base::hash_map<FilePath, GURL> RestrictedPluginMap; + RestrictedPluginMap restricted_plugins_; + typedef std::map<const void*, scoped_refptr<PluginPrefs> > ResourceContextMap; + ResourceContextMap resource_context_map_; + + std::vector<OverriddenPlugin> overridden_plugins_; +}; + +#endif // CHROME_BROWSER_CHROME_PLUGIN_SERVICE_FILTER_H_ diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index e9143d0..dc4d403 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -24,6 +24,7 @@ #include "base/values.h" #include "base/version.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/extensions/apps_promo.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_accessibility_api.h" @@ -1502,7 +1503,7 @@ void ExtensionService::NotifyExtensionLoaded(const Extension* extension) { webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(plugin.path); plugins_changed = true; if (!plugin.is_public) { - PluginService::GetInstance()->RestrictPluginToUrl( + ChromePluginServiceFilter::GetInstance()->RestrictPluginToUrl( plugin.path, extension->url()); } } @@ -1597,8 +1598,10 @@ void ExtensionService::NotifyExtensionUnloaded( webkit::npapi::PluginList::Singleton()->RemoveExtraPluginPath( plugin.path); plugins_changed = true; - if (!plugin.is_public) - PluginService::GetInstance()->RestrictPluginToUrl(plugin.path, GURL()); + if (!plugin.is_public) { + ChromePluginServiceFilter::GetInstance()->RestrictPluginToUrl( + plugin.path, GURL()); + } } bool nacl_modules_changed = false; diff --git a/chrome/browser/pdf_unsupported_feature.cc b/chrome/browser/pdf_unsupported_feature.cc index 3f5f6d0..1a91a39 100644 --- a/chrome/browser/pdf_unsupported_feature.cc +++ b/chrome/browser/pdf_unsupported_feature.cc @@ -9,6 +9,7 @@ #include "base/version.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" @@ -140,19 +141,19 @@ void OpenUsingReader(TabContentsWrapper* tab, const WebPluginInfo& reader_plugin, InfoBarDelegate* old_delegate, InfoBarDelegate* new_delegate) { - PluginService::OverriddenPlugin plugin; - plugin.render_process_id = tab->render_view_host()->process()->id(); - plugin.render_view_id = tab->render_view_host()->routing_id(); - plugin.url = tab->tab_contents()->GetURL(); - plugin.plugin = reader_plugin; + 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 // plugin UI if it's vulnerable, since we already went through the // interstitial. - plugin.plugin.enabled = WebPluginInfo::USER_ENABLED; - plugin.plugin.version = ASCIIToUTF16("11.0.0.0"); - - PluginService::GetInstance()->OverridePluginForTab(plugin); + plugin.enabled = WebPluginInfo::USER_ENABLED; + plugin.version = ASCIIToUTF16("11.0.0.0"); + + ChromePluginServiceFilter::GetInstance()->OverridePluginForTab( + tab->render_view_host()->process()->id(), + tab->render_view_host()->routing_id(), + tab->tab_contents()->GetURL(), + plugin); tab->render_view_host()->Send(new ViewMsg_ReloadFrame( tab->render_view_host()->routing_id())); @@ -386,8 +387,7 @@ void PDFHasUnsupportedFeature(TabContentsWrapper* tab) { PluginGroup* reader_group = NULL; std::vector<PluginGroup> plugin_groups; - PluginList::Singleton()->GetPluginGroups( - false, &plugin_groups); + PluginList::Singleton()->GetPluginGroups(false, &plugin_groups); for (size_t i = 0; i < plugin_groups.size(); ++i) { if (plugin_groups[i].GetGroupName() == reader_group_name) { reader_group = &plugin_groups[i]; diff --git a/chrome/browser/plugin_data_remover.cc b/chrome/browser/plugin_data_remover.cc index b547b60..5b06586 100644 --- a/chrome/browser/plugin_data_remover.cc +++ b/chrome/browser/plugin_data_remover.cc @@ -10,6 +10,7 @@ #include "base/synchronization/waitable_event.h" #include "base/version.h" #include "chrome/browser/plugin_prefs.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" #include "content/browser/browser_thread.h" #include "content/browser/plugin_service.h" @@ -31,9 +32,10 @@ const uint64 kClearAllData = 0; } // namespace -PluginDataRemover::PluginDataRemover() +PluginDataRemover::PluginDataRemover(Profile* profile) : mime_type_(kFlashMimeType), is_removing_(false), + context_(profile->GetResourceContext()), event_(new base::WaitableEvent(true, false)), channel_(NULL) { } @@ -55,7 +57,7 @@ base::WaitableEvent* PluginDataRemover::StartRemoving(base::Time begin_time) { // called, so we need to keep this object around until then. AddRef(); PluginService::GetInstance()->OpenChannelToNpapiPlugin( - 0, 0, GURL(), mime_type_, this); + 0, 0, GURL(), GURL(), mime_type_, this); BrowserThread::PostDelayedTask( BrowserThread::IO, @@ -87,6 +89,10 @@ bool PluginDataRemover::OffTheRecord() { return false; } +const content::ResourceContext& PluginDataRemover::GetResourceContext() { + return context_; +} + void PluginDataRemover::SetPluginInfo( const webkit::WebPluginInfo& info) { } diff --git a/chrome/browser/plugin_data_remover.h b/chrome/browser/plugin_data_remover.h index 9cad19b..9ff4235 100644 --- a/chrome/browser/plugin_data_remover.h +++ b/chrome/browser/plugin_data_remover.h @@ -11,6 +11,7 @@ #include "content/browser/plugin_process_host.h" class PluginPrefs; +class Profile; class Task; namespace base { @@ -22,7 +23,7 @@ class PluginDataRemover : public base::RefCountedThreadSafe<PluginDataRemover>, public PluginProcessHost::Client, public IPC::Channel::Listener { public: - PluginDataRemover(); + explicit PluginDataRemover(Profile* profile); // The plug-in whose data should be removed (usually Flash) is specified via // its MIME type. This method sets a different MIME type in order to call a @@ -48,6 +49,7 @@ class PluginDataRemover : public base::RefCountedThreadSafe<PluginDataRemover>, // PluginProcessHost::Client methods. virtual int ID(); virtual bool OffTheRecord(); + virtual const content::ResourceContext& GetResourceContext(); virtual void SetPluginInfo(const webkit::WebPluginInfo& info); virtual void OnChannelOpened(const IPC::ChannelHandle& handle); virtual void OnError(); @@ -78,6 +80,8 @@ class PluginDataRemover : public base::RefCountedThreadSafe<PluginDataRemover>, base::Time remove_start_time_; // The point in time from which on we remove data. base::Time begin_time_; + // The resource context for the profile. + const content::ResourceContext& context_; scoped_ptr<base::WaitableEvent> event_; // We own the channel, but it's used on the IO thread, so it needs to be // deleted there. It's NULL until we have opened a connection to the plug-in diff --git a/chrome/browser/plugin_data_remover_browsertest.cc b/chrome/browser/plugin_data_remover_browsertest.cc index aa85045..5e4a7b2 100644 --- a/chrome/browser/plugin_data_remover_browsertest.cc +++ b/chrome/browser/plugin_data_remover_browsertest.cc @@ -41,7 +41,8 @@ class PluginDataRemoverTest : public InProcessBrowserTest, }; IN_PROC_BROWSER_TEST_F(PluginDataRemoverTest, RemoveData) { - scoped_refptr<PluginDataRemover> plugin_data_remover(new PluginDataRemover()); + scoped_refptr<PluginDataRemover> plugin_data_remover( + new PluginDataRemover(browser()->profile())); plugin_data_remover->set_mime_type(kNPAPITestPluginMimeType); base::WaitableEventWatcher watcher; base::WaitableEvent* event = diff --git a/chrome/browser/plugin_data_remover_helper.cc b/chrome/browser/plugin_data_remover_helper.cc index 9d4e176..df0c907 100644 --- a/chrome/browser/plugin_data_remover_helper.cc +++ b/chrome/browser/plugin_data_remover_helper.cc @@ -11,6 +11,7 @@ #include "chrome/browser/plugin_prefs.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_notification_types.h" #include "content/browser/browser_thread.h" #include "content/common/notification_service.h" @@ -76,7 +77,7 @@ void PluginDataRemoverHelper::Init(const char* pref_name, Profile* profile, NotificationObserver* observer) { pref_.Init(pref_name, profile->GetPrefs(), observer); - registrar_.Add(this, content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, + registrar_.Add(this, chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, NotificationService::AllSources()); internal_ = make_scoped_refptr(new Internal(pref_name, profile)); internal_->StartUpdate(); @@ -85,7 +86,7 @@ void PluginDataRemoverHelper::Init(const char* pref_name, void PluginDataRemoverHelper::Observe(int type, const NotificationSource& source, const NotificationDetails& details) { - if (type == content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED) { + if (type == chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED) { internal_->StartUpdate(); } else { NOTREACHED(); diff --git a/chrome/browser/plugin_prefs.cc b/chrome/browser/plugin_prefs.cc index 9af4c67..7b2ce4d 100644 --- a/chrome/browser/plugin_prefs.cc +++ b/chrome/browser/plugin_prefs.cc @@ -440,7 +440,7 @@ void PluginPrefs::NotifyPluginStatusChanged() { void PluginPrefs::OnNotifyPluginStatusChanged() { notify_pending_ = false; NotificationService::current()->Notify( - content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, + chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, Source<PluginPrefs>(this), NotificationService::NoDetails()); } diff --git a/chrome/browser/printing/print_preview_tab_controller.cc b/chrome/browser/printing/print_preview_tab_controller.cc index 6f5078c..cdcb02c 100644 --- a/chrome/browser/printing/print_preview_tab_controller.cc +++ b/chrome/browser/printing/print_preview_tab_controller.cc @@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/restore_tab_helper.h" @@ -21,7 +22,6 @@ #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" -#include "content/browser/plugin_service.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/navigation_details.h" #include "content/browser/tab_contents/tab_contents.h" @@ -55,13 +55,13 @@ void EnableInternalPDFPluginForTab(TabContentsWrapper* preview_tab) { std::vector<WebPluginInfo> plugins = internal_pdf_group->web_plugin_infos(); DCHECK_EQ(plugins.size(), 1U); - PluginService::OverriddenPlugin plugin; - plugin.render_process_id = preview_tab->render_view_host()->process()->id(); - plugin.render_view_id = preview_tab->render_view_host()->routing_id(); - plugin.plugin = plugins[0]; - plugin.plugin.enabled = WebPluginInfo::USER_ENABLED; - - PluginService::GetInstance()->OverridePluginForTab(plugin); + 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(), + GURL(), + plugin); } } diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 964bc8b..ed0a2f4 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc @@ -16,6 +16,7 @@ #include "build/build_config.h" #include "chrome/browser/background/background_contents_service_factory.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/download/chrome_download_manager_delegate.h" #include "chrome/browser/extensions/extension_info_map.h" @@ -26,6 +27,7 @@ #include "chrome/browser/extensions/extension_special_storage_policy.h" #include "chrome/browser/extensions/extension_webrequest_api.h" #include "chrome/browser/net/pref_proxy_config_service.h" +#include "chrome/browser/plugin_prefs.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/off_the_record_profile_io_data.h" @@ -117,6 +119,9 @@ class OffTheRecordProfileImpl : public Profile, ExtensionIconSource* icon_source = new ExtensionIconSource(real_profile); GetChromeURLDataManager()->AddDataSource(icon_source); + ChromePluginServiceFilter::GetInstance()->RegisterResourceContext( + PluginPrefs::GetForProfile(this), &GetResourceContext()); + BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableFunction(&NotifyOTRProfileCreatedOnIOThread, profile_, this)); @@ -127,6 +132,9 @@ class OffTheRecordProfileImpl : public Profile, chrome::NOTIFICATION_PROFILE_DESTROYED, Source<Profile>(this), NotificationService::NoDetails()); + ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext( + &GetResourceContext()); + ProfileDependencyManager::GetInstance()->DestroyProfileServices(this); BrowserThread::PostTask( diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 1ddbd12..db3a11c 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -21,6 +21,7 @@ #include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data_remover.h" +#include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/defaults.h" @@ -49,6 +50,7 @@ #include "chrome/browser/net/pref_proxy_config_service.h" #include "chrome/browser/net/ssl_config_service_manager.h" #include "chrome/browser/password_manager/password_store_default.h" +#include "chrome/browser/plugin_prefs.h" #include "chrome/browser/policy/configuration_policy_pref_store.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/prefs/pref_value_store.h" @@ -438,6 +440,9 @@ void ProfileImpl::DoFinalInit() { cache_max_size, media_cache_path, media_cache_max_size, extensions_cookie_path, app_path); + ChromePluginServiceFilter::GetInstance()->RegisterResourceContext( + PluginPrefs::GetForProfile(this), &GetResourceContext()); + // Creation has been finished. if (delegate_) delegate_->OnProfileCreated(this, true); @@ -687,6 +692,9 @@ ProfileImpl::~ProfileImpl() { // of the cleanup below. sync_service_.reset(); + ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext( + &GetResourceContext()); + ProfileDependencyManager::GetInstance()->DestroyProfileServices(this); if (db_tracker_) { diff --git a/chrome/browser/ui/webui/plugins_ui.cc b/chrome/browser/ui/webui/plugins_ui.cc index 78a3c18..f2fc958 100644 --- a/chrome/browser/ui/webui/plugins_ui.cc +++ b/chrome/browser/ui/webui/plugins_ui.cc @@ -22,6 +22,7 @@ #include "chrome/browser/ui/webui/chrome_url_data_manager.h" #include "chrome/browser/ui/webui/chrome_web_ui_data_source.h" #include "chrome/common/chrome_content_client.h" +#include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -150,7 +151,7 @@ class PluginsDOMHandler : public WebUIMessageHandler, PluginsDOMHandler::PluginsDOMHandler() : ALLOW_THIS_IN_INITIALIZER_LIST(get_plugins_factory_(this)) { registrar_.Add(this, - content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, + chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, NotificationService::AllSources()); } @@ -248,7 +249,7 @@ void PluginsDOMHandler::HandleGetShowDetails(const ListValue* args) { void PluginsDOMHandler::Observe(int type, const NotificationSource& source, const NotificationDetails& details) { - DCHECK_EQ(content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, type); + DCHECK_EQ(chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, type); LoadPlugins(); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index c221df0..b29075b 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -341,6 +341,8 @@ 'browser/chrome_content_browser_client.h', 'browser/chrome_plugin_message_filter.cc', 'browser/chrome_plugin_message_filter.h', + 'browser/chrome_plugin_service_filter.cc', + 'browser/chrome_plugin_service_filter.h', 'browser/chrome_quota_permission_context.cc', 'browser/chrome_quota_permission_context.h', 'browser/chrome_worker_message_filter.cc', diff --git a/chrome/common/chrome_notification_types.h b/chrome/common/chrome_notification_types.h index b213792..f1101cc 100644 --- a/chrome/common/chrome_notification_types.h +++ b/chrome/common/chrome_notification_types.h @@ -887,6 +887,10 @@ enum NotificationType { // Sent when the browser enters or exits fullscreen mode. NOTIFICATION_FULLSCREEN_CHANGED, + // Sent by the PluginPrefs when there is a change of plugin + // enable/disable status. + NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, + // Note:- // Currently only Content and Chrome define and use notifications. // Custom notifications not belonging to Content and Chrome should start diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 858d5ad..7becf4a 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -298,8 +298,6 @@ WebPlugin* ChromeContentRendererClient::CreatePluginImpl( if (!found) return NULL; - if (!webkit::IsPluginEnabled(info)) - return NULL; *is_default_plugin = info.path.value() == webkit::npapi::kDefaultPluginLibraryName; diff --git a/content/browser/plugin_process_host.h b/content/browser/plugin_process_host.h index 7fdba4d..3c5f116 100644 --- a/content/browser/plugin_process_host.h +++ b/content/browser/plugin_process_host.h @@ -19,6 +19,10 @@ #include "webkit/plugins/webplugininfo.h" #include "ui/gfx/native_widget_types.h" +namespace content { +class ResourceContext; +} + namespace gfx { class Rect; } @@ -41,9 +45,11 @@ class PluginProcessHost : public BrowserChildProcessHost { public: class Client { public: - // Returns a opaque unique identifier for the process requesting + // Returns an opaque unique identifier for the process requesting // the channel. virtual int ID() = 0; + // Returns the resource context for the renderer requesting the channel. + virtual const content::ResourceContext& GetResourceContext() = 0; virtual bool OffTheRecord() = 0; virtual void SetPluginInfo(const webkit::WebPluginInfo& info) = 0; // The client should delete itself when one of these methods is called. diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc index 7ca5b22..86670db 100644 --- a/content/browser/plugin_service.cc +++ b/content/browser/plugin_service.cc @@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/compiler_specific.h" +#include "base/file_path.h" #include "base/path_service.h" #include "base/string_util.h" #include "base/synchronization/waitable_event.h" @@ -14,6 +15,7 @@ #include "base/values.h" #include "content/browser/browser_thread.h" #include "content/browser/content_browser_client.h" +#include "content/browser/plugin_service_filter.h" #include "content/browser/ppapi_plugin_process_host.h" #include "content/browser/renderer_host/render_process_host.h" #include "content/browser/renderer_host/render_view_host.h" @@ -32,6 +34,8 @@ using ::base::files::FilePathWatcher; #endif +using content::PluginServiceFilter; + #if defined(OS_MACOSX) static void NotifyPluginsOfActivation() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); @@ -65,7 +69,8 @@ PluginService* PluginService::GetInstance() { PluginService::PluginService() : ui_locale_( - content::GetContentClient()->browser()->GetApplicationLocale()) { + content::GetContentClient()->browser()->GetApplicationLocale()), + filter_(NULL) { RegisterPepperPlugins(); // Load any specified on the command line as well. @@ -77,6 +82,27 @@ PluginService::PluginService() if (!path.empty()) webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path); +#if defined(OS_MACOSX) + // We need to know when the browser comes forward so we can bring modal plugin + // windows forward too. + registrar_.Add(this, content::NOTIFICATION_APP_ACTIVATED, + NotificationService::AllSources()); +#endif +} + +PluginService::~PluginService() { +#if defined(OS_WIN) + // Release the events since they're owned by RegKey, not WaitableEvent. + hkcu_watcher_.StopWatching(); + hklm_watcher_.StopWatching(); + if (hkcu_event_.get()) + hkcu_event_->Release(); + if (hklm_event_.get()) + hklm_event_->Release(); +#endif +} + +void PluginService::StartWatchingPlugins() { // Start watching for changes in the plugin list. This means watching // for changes in the Windows registry keys and on both Windows and POSIX // watch for changes in the paths that are expected to contain plugins. @@ -97,12 +123,7 @@ PluginService::PluginService() hklm_watcher_.StartWatching(hklm_event_.get(), this); } } -#elif defined(OS_MACOSX) - // We need to know when the browser comes forward so we can bring modal plugin - // windows forward too. - registrar_.Add(this, content::NOTIFICATION_APP_ACTIVATED, - NotificationService::AllSources()); -#elif defined(OS_POSIX) +#elif defined(OS_POSIX) && !defined(OS_MACOSX) // The FilePathWatcher produces too many false positives on MacOS (access time // updates?) which will lead to enforcing updates of the plugins way too often. // On ChromeOS the user can't install plugins anyway and on Windows all @@ -132,23 +153,6 @@ PluginService::PluginService() file_watchers_.push_back(watcher); } #endif - registrar_.Add(this, content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, - NotificationService::AllSources()); - registrar_.Add(this, - content::NOTIFICATION_RENDERER_PROCESS_CLOSED, - NotificationService::AllSources()); -} - -PluginService::~PluginService() { -#if defined(OS_WIN) - // Release the events since they're owned by RegKey, not WaitableEvent. - hkcu_watcher_.StopWatching(); - hklm_watcher_.StopWatching(); - if (hkcu_event_.get()) - hkcu_event_->Release(); - if (hklm_event_.get()) - hklm_event_->Release(); -#endif } const std::string& PluginService::GetUILocale() { @@ -278,6 +282,7 @@ void PluginService::OpenChannelToNpapiPlugin( int render_process_id, int render_view_id, const GURL& url, + const GURL& page_url, const std::string& mime_type, PluginProcessHost::Client* client) { // The PluginList::GetPluginInfo may need to load the plugins. Don't do it on @@ -286,7 +291,8 @@ void PluginService::OpenChannelToNpapiPlugin( BrowserThread::FILE, FROM_HERE, NewRunnableMethod( this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, - render_process_id, render_view_id, url, mime_type, client)); + render_process_id, render_view_id, url, page_url, mime_type, + client)); } void PluginService::OpenChannelToPpapiPlugin( @@ -314,15 +320,19 @@ void PluginService::GetAllowedPluginForOpenChannelToPlugin( int render_process_id, int render_view_id, const GURL& url, + const GURL& page_url, const std::string& mime_type, PluginProcessHost::Client* client) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); webkit::WebPluginInfo info; + bool allow_wildcard = true; bool found = GetPluginInfo( - render_process_id, render_view_id, url, mime_type, &info, NULL); + render_process_id, render_view_id, client->GetResourceContext(), + url, page_url, mime_type, allow_wildcard, + NULL, &info, NULL); FilePath plugin_path; if (found) - plugin_path = FilePath(info.path); + plugin_path = info.path; // Now we jump back to the IO thread to finish opening the channel. BrowserThread::PostTask( @@ -346,34 +356,38 @@ void PluginService::FinishOpenChannelToPlugin( bool PluginService::GetPluginInfo(int render_process_id, int render_view_id, + const content::ResourceContext& context, const GURL& url, + const GURL& page_url, const std::string& mime_type, + bool allow_wildcard, + bool* use_stale, webkit::WebPluginInfo* info, std::string* actual_mime_type) { + webkit::npapi::PluginList* plugin_list = + webkit::npapi::PluginList::Singleton(); // GetPluginInfoArray may need to load the plugins, so we need to be // on the FILE thread. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - { - base::AutoLock auto_lock(overridden_plugins_lock_); - for (size_t i = 0; i < overridden_plugins_.size(); ++i) { - if (overridden_plugins_[i].render_process_id == render_process_id && - overridden_plugins_[i].render_view_id == render_view_id && - (overridden_plugins_[i].url == url || - overridden_plugins_[i].url.is_empty())) { - if (actual_mime_type) - *actual_mime_type = mime_type; - *info = overridden_plugins_[i].plugin; - return true; - } - } - } - bool allow_wildcard = true; + DCHECK(use_stale || BrowserThread::CurrentlyOn(BrowserThread::FILE)); std::vector<webkit::WebPluginInfo> plugins; std::vector<std::string> mime_types; - webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( - url, mime_type, allow_wildcard, NULL, &plugins, &mime_types); + plugin_list->GetPluginInfoArray( + url, mime_type, allow_wildcard, use_stale, &plugins, &mime_types); + if (plugins.size() > 1 && + plugins.back().path == + FilePath(webkit::npapi::kDefaultPluginLibraryName)) { + // If there is at least one plug-in handling the required MIME type (apart + // from the default plug-in), we don't need the default plug-in. + plugins.pop_back(); + } + for (size_t i = 0; i < plugins.size(); ++i) { - if (webkit::IsPluginEnabled(plugins[i])) { + if (!filter_ || filter_->ShouldUsePlugin(render_process_id, + render_view_id, + &context, + url, + page_url, + &plugins[i])) { *info = plugins[i]; if (actual_mime_type) *actual_mime_type = mime_types[i]; @@ -383,6 +397,31 @@ bool PluginService::GetPluginInfo(int render_process_id, return false; } +void PluginService::GetPlugins( + const content::ResourceContext& context, + std::vector<webkit::WebPluginInfo>* plugins) { + // GetPlugins may need to load the plugins, so we need to be + // on the FILE thread. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + webkit::npapi::PluginList* plugin_list = + webkit::npapi::PluginList::Singleton(); + std::vector<webkit::WebPluginInfo> all_plugins; + plugin_list->GetPlugins(&all_plugins); + + int child_process_id = -1; + int routing_id = MSG_ROUTING_NONE; + for (size_t i = 0; i < all_plugins.size(); ++i) { + if (!filter_ || filter_->ShouldUsePlugin(child_process_id, + routing_id, + &context, + GURL(), + GURL(), + &all_plugins[i])) { + plugins->push_back(all_plugins[i]); + } + } +} + void PluginService::OnWaitableEventSignaled( base::WaitableEvent* waitable_event) { #if defined(OS_WIN) @@ -403,40 +442,14 @@ void PluginService::OnWaitableEventSignaled( void PluginService::Observe(int type, const NotificationSource& source, const NotificationDetails& details) { - switch (type) { #if defined(OS_MACOSX) - case content::NOTIFICATION_APP_ACTIVATED: { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - NewRunnableFunction(&NotifyPluginsOfActivation)); - break; - } -#endif - - case content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED: { - webkit::npapi::PluginList::Singleton()->RefreshPlugins(); - PurgePluginListCache(false); - break; - } - case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { - int render_process_id = Source<RenderProcessHost>(source).ptr()->id(); - - base::AutoLock auto_lock(overridden_plugins_lock_); - for (size_t i = 0; i < overridden_plugins_.size(); ++i) { - if (overridden_plugins_[i].render_process_id == render_process_id) { - overridden_plugins_.erase(overridden_plugins_.begin() + i); - break; - } - } - break; - } - default: - NOTREACHED(); + if (type == content::NOTIFICATION_APP_ACTIVATED) { + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + NewRunnableFunction(&NotifyPluginsOfActivation)); + return; } -} - -void PluginService::OverridePluginForTab(const OverriddenPlugin& plugin) { - base::AutoLock auto_lock(overridden_plugins_lock_); - overridden_plugins_.push_back(plugin); +#endif + NOTREACHED(); } void PluginService::PurgePluginListCache(bool reload_pages) { @@ -446,32 +459,6 @@ void PluginService::PurgePluginListCache(bool reload_pages) { } } -void PluginService::RestrictPluginToUrl(const FilePath& plugin_path, - const GURL& url) { - base::AutoLock auto_lock(restricted_plugin_lock_); - if (url.is_empty()) { - restricted_plugin_.erase(plugin_path); - } else { - restricted_plugin_[plugin_path] = url; - } -} - -bool PluginService::PluginAllowedForURL(const FilePath& plugin_path, - const GURL& url) { - if (url.is_empty()) - return true; // Caller wants all plugins. - - base::AutoLock auto_lock(restricted_plugin_lock_); - - RestrictedPluginMap::iterator it = restricted_plugin_.find(plugin_path); - if (it == restricted_plugin_.end()) - return true; // This plugin is not restricted, so it's allowed everywhere. - - const GURL& required_url = it->second; - return (url.scheme() == required_url.scheme() && - url.host() == required_url.host()); -} - void PluginService::RegisterPepperPlugins() { // TODO(abarth): It seems like the PepperPluginRegistry should do this work. PepperPluginRegistry::ComputeList(&ppapi_plugins_); diff --git a/content/browser/plugin_service.h b/content/browser/plugin_service.h index 9cdbcad..8dbef70f 100644 --- a/content/browser/plugin_service.h +++ b/content/browser/plugin_service.h @@ -13,11 +13,8 @@ #include <vector> #include "base/basictypes.h" -#include "base/file_path.h" -#include "base/hash_tables.h" #include "base/memory/scoped_vector.h" #include "base/memory/singleton.h" -#include "base/synchronization/lock.h" #include "base/synchronization/waitable_event_watcher.h" #include "build/build_config.h" #include "content/browser/plugin_process_host.h" @@ -41,6 +38,11 @@ struct PepperPluginInfo; class PluginDirWatcherDelegate; +namespace content { +class ResourceContext; +class PluginServiceFilter; +} + // This must be created on the main thread but it's only called on the IO/file // thread. class PluginService @@ -57,6 +59,9 @@ class PluginService // Returns the PluginService singleton. static PluginService* GetInstance(); + // Starts watching for changes in the list of installed plug-ins. + void StartWatchingPlugins(); + // Gets the browser's UI locale. const std::string& GetUILocale(); @@ -85,6 +90,7 @@ class PluginService void OpenChannelToNpapiPlugin(int render_process_id, int render_view_id, const GURL& url, + const GURL& page_url, const std::string& mime_type, PluginProcessHost::Client* client); void OpenChannelToPpapiPlugin(const FilePath& path, @@ -93,32 +99,32 @@ class PluginService PpapiBrokerProcessHost::Client* client); // Gets the plugin in the list of plugins that matches the given url and mime - // type. Must be called on the FILE thread. + // type. Must be called on the FILE thread if |use_stale| is NULL. bool GetPluginInfo(int render_process_id, int render_view_id, + const content::ResourceContext& context, const GURL& url, + const GURL& page_url, const std::string& mime_type, + bool allow_wildcard, + bool* use_stale, webkit::WebPluginInfo* info, std::string* actual_mime_type); - // Safe to be called from any thread. - void OverridePluginForTab(const OverriddenPlugin& plugin); - - // Restricts the given plugin to the the scheme and host of the given url. - // Call with an empty url to reset this. - // Can be called on any thread. - void RestrictPluginToUrl(const FilePath& plugin_path, const GURL& url); - - // Returns true if the given plugin is allowed to be used by a page with - // the given URL. - // Can be called on any thread. - bool PluginAllowedForURL(const FilePath& plugin_path, const GURL& url); + // Returns a list of all plug-ins available to the resource context. Must be + // called on the FILE thread. + void GetPlugins(const content::ResourceContext& context, + std::vector<webkit::WebPluginInfo>* plugins); // Tells all the renderer processes to throw away their cache of the plugin // list, and optionally also reload all the pages with plugins. // NOTE: can only be called on the UI thread. static void PurgePluginListCache(bool reload_pages); + void set_filter(content::PluginServiceFilter* filter) { + filter_ = filter; + } + private: friend struct DefaultSingletonTraits<PluginService>; @@ -143,6 +149,7 @@ class PluginService int render_process_id, int render_view_id, const GURL& url, + const GURL& page_url, const std::string& mime_type, PluginProcessHost::Client* client); @@ -163,11 +170,6 @@ class PluginService // The browser's UI locale. const std::string ui_locale_; - // Map of plugin paths to the origin they are restricted to. - base::Lock restricted_plugin_lock_; // Guards access to restricted_plugin_. - typedef base::hash_map<FilePath, GURL> RestrictedPluginMap; - RestrictedPluginMap restricted_plugin_; - NotificationRegistrar registrar_; #if defined(OS_WIN) @@ -187,8 +189,8 @@ class PluginService std::vector<PepperPluginInfo> ppapi_plugins_; - std::vector<OverriddenPlugin> overridden_plugins_; - base::Lock overridden_plugins_lock_; + // Weak pointer; outlives us. + content::PluginServiceFilter* filter_; DISALLOW_COPY_AND_ASSIGN(PluginService); }; diff --git a/content/browser/plugin_service_browsertest.cc b/content/browser/plugin_service_browsertest.cc index 95ce4b6..c49a90b 100644 --- a/content/browser/plugin_service_browsertest.cc +++ b/content/browser/plugin_service_browsertest.cc @@ -6,9 +6,12 @@ #include "base/command_line.h" #include "base/path_service.h" +#include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/ui_test_utils.h" #include "content/browser/browser_thread.h" +#include "content/browser/resource_context.h" #include "content/common/content_switches.h" #include "testing/gmock/include/gmock/gmock.h" #include "webkit/plugins/npapi/plugin_list.h" @@ -22,8 +25,9 @@ const char* kNPAPITestPluginMimeType = "application/vnd.npapi-test"; class MockPluginProcessHostClient : public PluginProcessHost::Client, public IPC::Channel::Listener { public: - MockPluginProcessHostClient() - : channel_(NULL), + MockPluginProcessHostClient(const content::ResourceContext& context) + : context_(context), + channel_(NULL), set_plugin_info_called_(false) { } @@ -33,8 +37,11 @@ class MockPluginProcessHostClient : public PluginProcessHost::Client, } // Client implementation. - int ID() { return 42; } - bool OffTheRecord() { return false; } + virtual int ID() OVERRIDE { return 42; } + virtual bool OffTheRecord() OVERRIDE { return false; } + virtual const content::ResourceContext& GetResourceContext() OVERRIDE { + return context_; + } void OnChannelOpened(const IPC::ChannelHandle& handle) { ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); @@ -63,6 +70,7 @@ class MockPluginProcessHostClient : public PluginProcessHost::Client, MOCK_METHOD0(OnChannelListenError, void()); private: + const content::ResourceContext& context_; IPC::Channel* channel_; bool set_plugin_info_called_; DISALLOW_COPY_AND_ASSIGN(MockPluginProcessHostClient); @@ -87,8 +95,9 @@ class PluginServiceTest : public InProcessBrowserTest { // Try to open a channel to the test plugin. Minimal plugin process spawning // test for the PluginService interface. IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) { - MockPluginProcessHostClient mock_client; + ::testing::StrictMock<MockPluginProcessHostClient> mock_client( + browser()->profile()->GetResourceContext()); PluginService::GetInstance()->OpenChannelToNpapiPlugin( - 0, 0, GURL(), kNPAPITestPluginMimeType, &mock_client); + 0, 0, GURL(), GURL(), kNPAPITestPluginMimeType, &mock_client); ui_test_utils::RunMessageLoop(); } diff --git a/content/browser/plugin_service_filter.h b/content/browser/plugin_service_filter.h new file mode 100644 index 0000000..790c501 --- /dev/null +++ b/content/browser/plugin_service_filter.h @@ -0,0 +1,37 @@ +// 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. + +#ifndef CONTENT_BROWSER_PLUGIN_FILTER_H_ +#define CONTENT_BROWSER_PLUGIN_FILTER_H_ +#pragma once + +class GURL; + +namespace webkit { +struct WebPluginInfo; +} + +namespace content { + +class ResourceContext; + +// Callback class to let the client filter the list of all installed plug-ins. +// This class is called on the FILE thread. +class PluginServiceFilter { + public: + virtual ~PluginServiceFilter() {} + // Whether to use |plugin|. The client can return false to disallow the + // plugin, or return true and optionally change the passed in plugin. + virtual bool ShouldUsePlugin( + int render_process_id, + int render_view_id, + const void* context, + const GURL& url, + const GURL& policy_url, + webkit::WebPluginInfo* plugin) = 0; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_PLUGIN_FILTER_H_ diff --git a/content/browser/renderer_host/buffered_resource_handler.cc b/content/browser/renderer_host/buffered_resource_handler.cc index 97b063f..026ce66 100644 --- a/content/browser/renderer_host/buffered_resource_handler.cc +++ b/content/browser/renderer_host/buffered_resource_handler.cc @@ -12,6 +12,7 @@ #include "content/browser/browser_thread.h" #include "content/browser/content_browser_client.h" #include "content/browser/download/download_resource_handler.h" +#include "content/browser/plugin_service.h" #include "content/browser/renderer_host/resource_dispatcher_host.h" #include "content/browser/renderer_host/resource_dispatcher_host_delegate.h" #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" @@ -397,10 +398,15 @@ bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { // Finally, check the plugin list. bool allow_wildcard = false; + ResourceDispatcherHostRequestInfo* info = + ResourceDispatcherHost::InfoForRequest(request_); bool stale = false; - std::vector<webkit::WebPluginInfo> plugins; - webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( - request_->url(), type, allow_wildcard, &stale, &plugins, NULL); + webkit::WebPluginInfo plugin; + bool found = PluginService::GetInstance()->GetPluginInfo( + info->child_id(), info->route_id(), *info->context(), + request_->url(), GURL(), type, allow_wildcard, + &stale, &plugin, NULL); + if (need_plugin_list) { if (stale) { *need_plugin_list = true; @@ -410,11 +416,7 @@ bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) { DCHECK(!stale); } - for (size_t i = 0; i < plugins.size(); ++i) { - if (webkit::IsPluginEnabled(plugins[i])) - return false; - } - return true; + return !found; } void BufferedResourceHandler::UseAlternateResourceHandler( diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 791dc9e..32180e3 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -70,6 +70,7 @@ #endif using net::CookieStore; +using content::PluginServiceFilter; namespace { @@ -121,27 +122,33 @@ class OpenChannelToNpapiPluginCallback : public RenderMessageCompletionCallback, public PluginProcessHost::Client { public: OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter, + const content::ResourceContext& context, IPC::Message* reply_msg) - : RenderMessageCompletionCallback(filter, reply_msg) { + : RenderMessageCompletionCallback(filter, reply_msg), + context_(context) { } - virtual int ID() { + virtual int ID() OVERRIDE { return filter()->render_process_id(); } - virtual bool OffTheRecord() { + virtual const content::ResourceContext& GetResourceContext() OVERRIDE { + return context_; + } + + virtual bool OffTheRecord() OVERRIDE { return filter()->OffTheRecord(); } - virtual void SetPluginInfo(const webkit::WebPluginInfo& info) { + virtual void SetPluginInfo(const webkit::WebPluginInfo& info) OVERRIDE { info_ = info; } - virtual void OnChannelOpened(const IPC::ChannelHandle& handle) { + virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE { WriteReplyAndDeleteThis(handle); } - virtual void OnError() { + virtual void OnError() OVERRIDE { WriteReplyAndDeleteThis(IPC::ChannelHandle()); } @@ -152,6 +159,7 @@ class OpenChannelToNpapiPluginCallback : public RenderMessageCompletionCallback, SendReplyAndDeleteThis(); } + const content::ResourceContext& context_; webkit::WebPluginInfo info_; }; @@ -536,38 +544,36 @@ void RenderMessageFilter::OnGetPlugins( } } - std::vector<webkit::WebPluginInfo> all_plugins; - webkit::npapi::PluginList::Singleton()->GetPlugins(&all_plugins); - for (size_t i = 0; i < all_plugins.size(); ++i) { - if (webkit::IsPluginEnabled(all_plugins[i])) - plugins->push_back(all_plugins[i]); - } + PluginService::GetInstance()->GetPlugins(resource_context_, + plugins); } void RenderMessageFilter::OnGetPluginInfo( int routing_id, const GURL& url, - const GURL& policy_url, + const GURL& page_url, const std::string& mime_type, bool* found, webkit::WebPluginInfo* info, std::string* actual_mime_type) { + bool allow_wildcard = true; *found = plugin_service_->GetPluginInfo( - render_process_id_, routing_id, url, mime_type, info, actual_mime_type); - - if (*found) { - if (!plugin_service_->PluginAllowedForURL(info->path, policy_url)) - info->enabled |= webkit::WebPluginInfo::POLICY_DISABLED; - } + render_process_id_, routing_id, resource_context_, + url, page_url, mime_type, allow_wildcard, + NULL, info, actual_mime_type); } void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id, const GURL& url, + const GURL& policy_url, const std::string& mime_type, IPC::Message* reply_msg) { plugin_service_->OpenChannelToNpapiPlugin( - render_process_id_, routing_id, url, mime_type, - new OpenChannelToNpapiPluginCallback(this, reply_msg)); + render_process_id_, routing_id, + url, policy_url, mime_type, + new OpenChannelToNpapiPluginCallback(this, + resource_context_, + reply_msg)); } void RenderMessageFilter::OnOpenChannelToPepperPlugin( diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 946d144..247571e 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -27,7 +27,6 @@ #include "ui/gfx/surface/transport_dib.h" struct FontDescriptor; -class HostContentSettingsMap; class RenderWidgetHelper; struct ViewHostMsg_CreateWindow_Params; struct ViewHostMsg_CreateWorker_Params; @@ -157,6 +156,7 @@ class RenderMessageFilter : public BrowserMessageFilter { std::string* actual_mime_type); void OnOpenChannelToPlugin(int routing_id, const GURL& url, + const GURL& policy_url, const std::string& mime_type, IPC::Message* reply_msg); void OnOpenChannelToPepperPlugin(const FilePath& path, diff --git a/content/common/content_notification_types.h b/content/common/content_notification_types.h index 144ebb7..a193dac 100644 --- a/content/common/content_notification_types.h +++ b/content/common/content_notification_types.h @@ -412,10 +412,6 @@ enum NotificationType { // in a Details<ChildProcessInfo>. NOTIFICATION_CHILD_INSTANCE_CREATED, - // Sent by the PluginUpdater when there is a change of plugin - // enable/disable status. - NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, - // Download Notifications -------------------------------------------------- // Sent when a page generation to MHTML has finished. diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 395ff9e..c71b244 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -1613,16 +1613,14 @@ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_GetPlugins, std::vector<webkit::WebPluginInfo> /* plugins */) // Return information about a plugin for the given URL and MIME -// type. If there is no matching plugin, |found| is false. If -// |enabled| in the WebPluginInfo struct is false, the plug-in is -// treated as if it was not installed at all. +// type. If there is no matching plugin, |found| is false. // |actual_mime_type| is the actual mime type supported by the // plugin found that match the URL given (one for each item in // |info|). IPC_SYNC_MESSAGE_CONTROL4_3(ViewHostMsg_GetPluginInfo, int /* routing_id */, GURL /* url */, - GURL /* policy_url */, + GURL /* page_url */, std::string /* mime_type */, bool /* found */, webkit::WebPluginInfo /* plugin info */, @@ -1632,9 +1630,10 @@ IPC_SYNC_MESSAGE_CONTROL4_3(ViewHostMsg_GetPluginInfo, // create a plugin. The browser will create the plugin process if // necessary, and will return a handle to the channel on success. // On error an empty string is returned. -IPC_SYNC_MESSAGE_CONTROL3_2(ViewHostMsg_OpenChannelToPlugin, +IPC_SYNC_MESSAGE_CONTROL4_2(ViewHostMsg_OpenChannelToPlugin, int /* routing_id */, GURL /* url */, + GURL /* page_url */, std::string /* mime_type */, IPC::ChannelHandle /* channel_handle */, webkit::WebPluginInfo /* info */) diff --git a/content/content_browser.gypi b/content/content_browser.gypi index a346ffe..60b9e49 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -294,6 +294,7 @@ 'browser/plugin_process_host_mac.cc', 'browser/plugin_service.cc', 'browser/plugin_service.h', + 'browser/plugin_service_filter.h', 'browser/quota_permission_context.h', 'browser/renderer_host/accelerated_surface_container_mac.cc', 'browser/renderer_host/accelerated_surface_container_mac.h', diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 9ea7d42..c783312 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -581,7 +581,7 @@ WebPlugin* RenderView::CreatePluginNoCheck(WebFrame* frame, Send(new ViewHostMsg_GetPluginInfo( routing_id_, params.url, frame->top()->document().url(), params.mimeType.utf8(), &found, &info, &mime_type)); - if (!found || !webkit::IsPluginEnabled(info)) + if (!found) return NULL; bool pepper_plugin_was_registered = false; diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h index 2df1088..cadbc81 100644 --- a/content/renderer/render_view.h +++ b/content/renderer/render_view.h @@ -88,10 +88,6 @@ namespace content { class P2PSocketDispatcher; } // namespace content -namespace chrome { -class ChromeContentRendererClient; -} // namespace chrome - namespace gfx { class Point; class Rect; @@ -99,10 +95,6 @@ class Rect; namespace webkit { -namespace npapi { -class PluginGroup; -} // namespace npapi - namespace ppapi { class PluginInstance; class PluginModule; diff --git a/content/renderer/webplugin_delegate_proxy.cc b/content/renderer/webplugin_delegate_proxy.cc index c9640b3..8ffd930 100644 --- a/content/renderer/webplugin_delegate_proxy.cc +++ b/content/renderer/webplugin_delegate_proxy.cc @@ -283,8 +283,8 @@ bool WebPluginDelegateProxy::Initialize( bool load_manually) { IPC::ChannelHandle channel_handle; if (!RenderThread::current()->Send(new ViewHostMsg_OpenChannelToPlugin( - render_view_->routing_id(), url, mime_type_, &channel_handle, - &info_))) { + render_view_->routing_id(), url, page_url_, mime_type_, + &channel_handle, &info_))) { return false; } diff --git a/webkit/plugins/npapi/plugin_list.cc b/webkit/plugins/npapi/plugin_list.cc index 3f3e4e0..45160fc 100644 --- a/webkit/plugins/npapi/plugin_list.cc +++ b/webkit/plugins/npapi/plugin_list.cc @@ -519,13 +519,12 @@ void PluginList::GetPluginInfoArray( std::set<FilePath> visited_plugins; - // Add in enabled plugins by mime type. + // Add in plugins by mime type. for (size_t i = 0; i < plugin_groups_.size(); ++i) { const std::vector<webkit::WebPluginInfo>& plugins = plugin_groups_[i]->web_plugins_info(); for (size_t i = 0; i < plugins.size(); ++i) { - if (IsPluginEnabled(plugins[i]) && SupportsType(plugins[i], - mime_type, allow_wildcard)) { + if (SupportsType(plugins[i], mime_type, allow_wildcard)) { FilePath path = plugins[i].path; if (path.value() != kDefaultPluginLibraryName && visited_plugins.insert(path).second) { @@ -537,7 +536,7 @@ void PluginList::GetPluginInfoArray( } } - // Add in enabled plugins by url. + // Add in plugins by url. std::string path = url.path(); std::string::size_type last_dot = path.rfind('.'); if (last_dot != std::string::npos) { @@ -547,8 +546,7 @@ void PluginList::GetPluginInfoArray( const std::vector<webkit::WebPluginInfo>& plugins = plugin_groups_[i]->web_plugins_info(); for (size_t i = 0; i < plugins.size(); ++i) { - if (IsPluginEnabled(plugins[i]) && - SupportsExtension(plugins[i], extension, &actual_mime_type)) { + if (SupportsExtension(plugins[i], extension, &actual_mime_type)) { FilePath path = plugins[i].path; if (path.value() != kDefaultPluginLibraryName && visited_plugins.insert(path).second) { @@ -561,24 +559,6 @@ void PluginList::GetPluginInfoArray( } } - // Add in disabled plugins by mime type. - for (size_t i = 0; i < plugin_groups_.size(); ++i) { - const std::vector<webkit::WebPluginInfo>& plugins = - plugin_groups_[i]->web_plugins_info(); - for (size_t i = 0; i < plugins.size(); ++i) { - if (!IsPluginEnabled(plugins[i]) && - SupportsType(plugins[i], mime_type, allow_wildcard)) { - FilePath path = plugins[i].path; - if (path.value() != kDefaultPluginLibraryName && - visited_plugins.insert(path).second) { - info->push_back(plugins[i]); - if (actual_mime_types) - actual_mime_types->push_back(mime_type); - } - } - } - } - // Add the default plugin at the end if it supports the mime type given, // and the default plugin is enabled. for (size_t i = 0; i < plugin_groups_.size(); ++i) { |