diff options
-rw-r--r-- | chrome/browser/chromeos/gview_request_interceptor_unittest.cc | 29 | ||||
-rw-r--r-- | content/browser/plugin_service_impl.cc | 35 | ||||
-rw-r--r-- | content/browser/plugin_service_impl.h | 9 | ||||
-rw-r--r-- | webkit/plugins/npapi/plugin_list.cc | 25 | ||||
-rw-r--r-- | webkit/plugins/npapi/plugin_list.h | 23 |
5 files changed, 80 insertions, 41 deletions
diff --git a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc index 27ab723..7ec9312 100644 --- a/chrome/browser/chromeos/gview_request_interceptor_unittest.cc +++ b/chrome/browser/chromeos/gview_request_interceptor_unittest.cc @@ -128,29 +128,32 @@ class GViewRequestInterceptorTest : public testing::Test { webkit::WebPluginInfo info; info.path = pdf_path_; plugin_list_.AddPluginToLoad(info); + plugin_list_.RefreshPlugins(); } void UnregisterPDFPlugin() { plugin_list_.ClearPluginsToLoad(); + plugin_list_.RefreshPlugins(); } void SetPDFPluginLoadedState(bool want_loaded) { webkit::WebPluginInfo info; bool is_loaded = PluginService::GetInstance()->GetPluginInfoByPath( pdf_path_, &info); - if (is_loaded && !want_loaded) { - UnregisterPDFPlugin(); - is_loaded = PluginService::GetInstance()->GetPluginInfoByPath( - pdf_path_, &info); - } else if (!is_loaded && want_loaded) { + if (is_loaded == want_loaded) + return; + + if (want_loaded) { // This "loads" the plug-in even if it's not present on the // system - which is OK since we don't actually use it, just // need it to be "enabled" for the test. RegisterPDFPlugin(); - is_loaded = PluginService::GetInstance()->GetPluginInfoByPath( - pdf_path_, &info); + } else { + UnregisterPDFPlugin(); } - EXPECT_EQ(want_loaded, is_loaded); + is_loaded = PluginService::GetInstance()->GetPluginInfoByPath( + pdf_path_, &info); + ASSERT_EQ(want_loaded, is_loaded); } void SetupRequest(net::URLRequest* request) { @@ -196,7 +199,7 @@ TEST_F(GViewRequestInterceptorTest, DoNotInterceptDownload) { } TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) { - SetPDFPluginLoadedState(true); + ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(true)); plugin_prefs_->EnablePlugin(true, pdf_path_, MessageLoop::QuitClosure()); MessageLoop::current()->Run(); @@ -209,7 +212,7 @@ TEST_F(GViewRequestInterceptorTest, DoNotInterceptPdfWhenEnabled) { } TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) { - SetPDFPluginLoadedState(true); + ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(true)); plugin_prefs_->EnablePlugin(false, pdf_path_, MessageLoop::QuitClosure()); MessageLoop::current()->Run(); @@ -226,7 +229,7 @@ TEST_F(GViewRequestInterceptorTest, InterceptPdfWhenDisabled) { // test fails. Since pdf plugin is always present, we don't need to run this // test. TEST_F(GViewRequestInterceptorTest, InterceptPdfWithNoPlugin) { - SetPDFPluginLoadedState(false); + ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false)); net::URLRequest request(GURL(kPdfUrl), &test_delegate_); SetupRequest(&request); @@ -247,7 +250,7 @@ TEST_F(GViewRequestInterceptorTest, InterceptPowerpoint) { } TEST_F(GViewRequestInterceptorTest, DoNotInterceptPost) { - SetPDFPluginLoadedState(false); + ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false)); net::URLRequest request(GURL(kPdfUrl), &test_delegate_); SetupRequest(&request); @@ -259,7 +262,7 @@ TEST_F(GViewRequestInterceptorTest, DoNotInterceptPost) { } TEST_F(GViewRequestInterceptorTest, DoNotInterceptBlob) { - SetPDFPluginLoadedState(false); + ASSERT_NO_FATAL_FAILURE(SetPDFPluginLoadedState(false)); net::URLRequest request(GURL(kPdfBlob), &test_delegate_); SetupRequest(&request); diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc index e7dfead..29873b4 100644 --- a/content/browser/plugin_service_impl.cc +++ b/content/browser/plugin_service_impl.cc @@ -13,7 +13,6 @@ #include "base/path_service.h" #include "base/string_util.h" #include "base/synchronization/waitable_event.h" -#include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -60,13 +59,17 @@ static void GetPluginsForGroupsCallback( // Callback set on the PluginList to assert that plugin loading happens on the // correct thread. -void WillLoadPluginsCallback() { #if defined(OS_WIN) - CHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); +void WillLoadPluginsCallbackWin( + base::SequencedWorkerPool::SequenceToken token) { + CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( + token)); +} #else +void WillLoadPluginsCallbackPosix() { CHECK(false) << "Plugin loading should happen out-of-process."; -#endif } +#endif } // namespace @@ -147,8 +150,14 @@ void PluginServiceImpl::Init() { if (!plugin_list_) plugin_list_ = webkit::npapi::PluginList::Singleton(); +#if defined(OS_WIN) + plugin_list_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); plugin_list_->set_will_load_plugins_callback( - base::Bind(&WillLoadPluginsCallback)); + base::Bind(&WillLoadPluginsCallbackWin, plugin_list_token_)); +#else + plugin_list_->set_will_load_plugins_callback( + base::Bind(&WillLoadPluginsCallbackPosix)); +#endif RegisterPepperPlugins(); @@ -163,6 +172,7 @@ void PluginServiceImpl::Init() { if (!path.empty()) plugin_list_->AddExtraPluginDir(path); + #if defined(OS_MACOSX) // We need to know when the browser comes forward so we can bring modal plugin // windows forward too. @@ -192,7 +202,8 @@ void PluginServiceImpl::StartWatchingPlugins() { hklm_watcher_.StartWatching(hklm_event_.get(), this); } } -#elif defined(OS_POSIX) && !defined(OS_OPENBSD) +#endif +#if defined(OS_POSIX) && !defined(OS_OPENBSD) // On ChromeOS the user can't install plugins anyway and on Windows all // important plugins register themselves in the registry so no need to do that. file_watcher_delegate_ = new PluginDirWatcherDelegate(); @@ -506,12 +517,13 @@ void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) { MessageLoop::current()->message_loop_proxy()); #if defined(OS_WIN) - BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( + BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior( + plugin_list_token_, FROM_HERE, base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this), target_loop, callback), base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); -#else +#elif defined(OS_POSIX) std::vector<webkit::WebPluginInfo> cached_plugins; if (plugin_list_->GetPluginsIfNoRefreshNeeded(&cached_plugins)) { // Can't assume the caller is reentrant. @@ -526,6 +538,8 @@ void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) { base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_, target_loop, callback)); } +#else +#error Not implemented #endif } @@ -534,10 +548,12 @@ void PluginServiceImpl::GetPluginGroups( GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback)); } +#if defined(OS_WIN) void PluginServiceImpl::GetPluginsInternal( base::MessageLoopProxy* target_loop, const PluginService::GetPluginsCallback& callback) { - DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); + DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( + plugin_list_token_)); std::vector<webkit::WebPluginInfo> plugins; plugin_list_->GetPlugins(&plugins); @@ -545,6 +561,7 @@ void PluginServiceImpl::GetPluginsInternal( target_loop->PostTask(FROM_HERE, base::Bind(callback, plugins)); } +#endif void PluginServiceImpl::OnWaitableEventSignaled( base::WaitableEvent* waitable_event) { diff --git a/content/browser/plugin_service_impl.h b/content/browser/plugin_service_impl.h index bc8f112..b3fcbf9 100644 --- a/content/browser/plugin_service_impl.h +++ b/content/browser/plugin_service_impl.h @@ -18,6 +18,7 @@ #include "base/memory/scoped_vector.h" #include "base/memory/singleton.h" #include "base/synchronization/waitable_event_watcher.h" +#include "base/threading/sequenced_worker_pool.h" #include "base/time.h" #include "build/build_config.h" #include "content/browser/plugin_process_host.h" @@ -177,9 +178,11 @@ class CONTENT_EXPORT PluginServiceImpl void RegisterPepperPlugins(); - // Function that is run on the FILE thread to load the plugins synchronously. +#if defined(OS_WIN) + // Run on the blocking pool to load the plugins synchronously. void GetPluginsInternal(base::MessageLoopProxy* target_loop, const GetPluginsCallback& callback); +#endif // Binding directly to GetAllowedPluginForOpenChannelToPlugin() isn't possible // because more arity is needed <http://crbug.com/98542>. This just forwards. @@ -240,6 +243,10 @@ class CONTENT_EXPORT PluginServiceImpl std::set<PluginProcessHost::Client*> pending_plugin_clients_; +#if defined(OS_WIN) + // Used to sequentialize loading plug-ins from disk. + base::SequencedWorkerPool::SequenceToken plugin_list_token_; +#endif #if defined(OS_POSIX) scoped_refptr<PluginLoaderPosix> plugin_loader_; #endif diff --git a/webkit/plugins/npapi/plugin_list.cc b/webkit/plugins/npapi/plugin_list.cc index 0b04b31..6023fee 100644 --- a/webkit/plugins/npapi/plugin_list.cc +++ b/webkit/plugins/npapi/plugin_list.cc @@ -232,7 +232,7 @@ bool PluginList::DebugPluginLoading() { void PluginList::RefreshPlugins() { base::AutoLock lock(lock_); - plugins_need_refresh_ = true; + loading_state_ = LOADING_STATE_NEEDS_REFRESH; } void PluginList::AddExtraPluginPath(const FilePath& plugin_path) { @@ -371,7 +371,7 @@ bool PluginList::ParseMimeTypes( } PluginList::PluginList() - : plugins_need_refresh_(true) { + : loading_state_(LOADING_STATE_NEEDS_REFRESH) { PlatformInit(); AddHardcodedPluginGroups(kGroupDefinitions, ARRAYSIZE_UNSAFE(kGroupDefinitions)); @@ -379,7 +379,7 @@ PluginList::PluginList() PluginList::PluginList(const PluginGroupDefinition* definitions, size_t num_definitions) - : plugins_need_refresh_(true) { + : loading_state_(LOADING_STATE_NEEDS_REFRESH) { // Don't do platform-dependend initialization in unit tests. AddHardcodedPluginGroups(definitions, num_definitions); } @@ -398,12 +398,8 @@ void PluginList::LoadPluginsInternal(ScopedVector<PluginGroup>* plugin_groups) { base::Closure will_load_callback; { base::AutoLock lock(lock_); - // Clear the refresh bit now, because it might get set again before we - // reach the end of the method. - plugins_need_refresh_ = false; will_load_callback = will_load_plugins_callback_; } - if (!will_load_callback.is_null()) will_load_callback.Run(); @@ -421,8 +417,10 @@ void PluginList::LoadPluginsInternal(ScopedVector<PluginGroup>* plugin_groups) { void PluginList::LoadPlugins() { { base::AutoLock lock(lock_); - if (!plugins_need_refresh_) + if (loading_state_ == LOADING_STATE_UP_TO_DATE) return; + + loading_state_ = LOADING_STATE_REFRESHING; } ScopedVector<PluginGroup> new_plugin_groups; @@ -431,6 +429,10 @@ void PluginList::LoadPlugins() { base::AutoLock lock(lock_); plugin_groups_.swap(new_plugin_groups); + // If we haven't been invalidated in the mean time, mark the plug-in list as + // up-to-date. + if (loading_state_ != LOADING_STATE_NEEDS_REFRESH) + loading_state_ = LOADING_STATE_UP_TO_DATE; } bool PluginList::LoadPlugin(const FilePath& path, @@ -504,7 +506,8 @@ const std::vector<PluginGroup*>& PluginList::GetHardcodedPluginGroups() const { void PluginList::SetPlugins(const std::vector<webkit::WebPluginInfo>& plugins) { base::AutoLock lock(lock_); - plugins_need_refresh_ = false; + DCHECK_NE(LOADING_STATE_REFRESHING, loading_state_); + loading_state_ = LOADING_STATE_UP_TO_DATE; plugin_groups_.reset(); for (std::vector<webkit::WebPluginInfo>::const_iterator it = plugins.begin(); @@ -532,7 +535,7 @@ void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) { bool PluginList::GetPluginsIfNoRefreshNeeded( std::vector<webkit::WebPluginInfo>* plugins) { base::AutoLock lock(lock_); - if (plugins_need_refresh_) + if (loading_state_ != LOADING_STATE_UP_TO_DATE) return false; for (size_t i = 0; i < plugin_groups_.size(); ++i) { @@ -557,7 +560,7 @@ void PluginList::GetPluginInfoArray( LoadPlugins(); base::AutoLock lock(lock_); if (use_stale) - *use_stale = plugins_need_refresh_; + *use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE); info->clear(); if (actual_mime_types) actual_mime_types->clear(); diff --git a/webkit/plugins/npapi/plugin_list.h b/webkit/plugins/npapi/plugin_list.h index d01b38f..a948782 100644 --- a/webkit/plugins/npapi/plugin_list.h +++ b/webkit/plugins/npapi/plugin_list.h @@ -121,7 +121,7 @@ class WEBKIT_PLUGINS_EXPORT PluginList { const string16& mime_type_descriptions, std::vector<webkit::WebPluginMimeType>* parsed_mime_types); - // Get all the plugins synchronously. + // Get all the plugins synchronously, loading them if necessary. void GetPlugins(std::vector<webkit::WebPluginInfo>* plugins); // Returns true if the list of plugins is cached and is copied into the out @@ -195,6 +195,17 @@ class WEBKIT_PLUGINS_EXPORT PluginList { ScopedVector<PluginGroup>* plugin_groups); private: + enum LoadingState { + LOADING_STATE_NEEDS_REFRESH, + LOADING_STATE_REFRESHING, + LOADING_STATE_UP_TO_DATE, + }; + + struct InternalPlugin { + webkit::WebPluginInfo info; + PluginEntryPoints entry_points; + }; + friend class PluginListTest; friend struct base::DefaultLazyInstanceTraits<PluginList>; FRIEND_TEST_ALL_PREFIXES(PluginGroupTest, PluginGroupDefinition); @@ -268,8 +279,10 @@ class WEBKIT_PLUGINS_EXPORT PluginList { // Internals // - // If true, we reload plugins even if they've been loaded already. - bool plugins_need_refresh_; + // States whether we will load the plug-in list the next time we try to access + // it, whether we are currently in the process of loading it, or whether we + // consider it up-to-date. + LoadingState loading_state_; // Extra plugin paths that we want to search when loading. std::vector<FilePath> extra_plugin_paths_; @@ -277,10 +290,6 @@ class WEBKIT_PLUGINS_EXPORT PluginList { // Extra plugin directories that we want to search when loading. std::vector<FilePath> extra_plugin_dirs_; - struct InternalPlugin { - webkit::WebPluginInfo info; - PluginEntryPoints entry_points; - }; // Holds information about internal plugins. std::vector<InternalPlugin> internal_plugins_; |