diff options
-rw-r--r-- | content/browser/plugin_loader_posix.cc | 16 | ||||
-rw-r--r-- | content/browser/plugin_loader_posix.h | 2 | ||||
-rw-r--r-- | content/browser/plugin_loader_posix_unittest.cc | 37 | ||||
-rw-r--r-- | content/browser/plugin_service.cc | 5 |
4 files changed, 52 insertions, 8 deletions
diff --git a/content/browser/plugin_loader_posix.cc b/content/browser/plugin_loader_posix.cc index a1ccaac..14d7c02 100644 --- a/content/browser/plugin_loader_posix.cc +++ b/content/browser/plugin_loader_posix.cc @@ -46,6 +46,7 @@ void PluginLoaderPosix::OnProcessCrashed(int exit_code) { canonical_list_.erase(canonical_list_.begin(), canonical_list_.begin() + next_load_index_ + 1); next_load_index_ = 0; + LoadPluginsInternal(); } @@ -83,6 +84,11 @@ void PluginLoaderPosix::GetPluginsToLoad() { void PluginLoaderPosix::LoadPluginsInternal() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + // Check if the list is empty or all plugins have already been loaded before + // forking. + if (MaybeRunPendingCallbacks()) + return; + if (load_start_time_.is_null()) load_start_time_ = base::TimeTicks::Now(); @@ -107,7 +113,7 @@ void PluginLoaderPosix::OnPluginLoaded(const webkit::WebPluginInfo& plugin) { ++next_load_index_; - RunPendingCallbacks(); + MaybeRunPendingCallbacks(); } void PluginLoaderPosix::OnPluginLoadFailed(const FilePath& plugin_path) { @@ -120,7 +126,7 @@ void PluginLoaderPosix::OnPluginLoadFailed(const FilePath& plugin_path) { ++next_load_index_; MaybeAddInternalPlugin(plugin_path); - RunPendingCallbacks(); + MaybeRunPendingCallbacks(); } bool PluginLoaderPosix::MaybeAddInternalPlugin(const FilePath& plugin_path) { @@ -137,9 +143,9 @@ bool PluginLoaderPosix::MaybeAddInternalPlugin(const FilePath& plugin_path) { return false; } -void PluginLoaderPosix::RunPendingCallbacks() { +bool PluginLoaderPosix::MaybeRunPendingCallbacks() { if (next_load_index_ < canonical_list_.size()) - return; + return false; PluginList::Singleton()->SetPlugins(loaded_plugins_); for (std::vector<PendingCallback>::iterator it = callbacks_.begin(); @@ -154,6 +160,8 @@ void PluginLoaderPosix::RunPendingCallbacks() { (base::TimeTicks::Now() - load_start_time_) * base::Time::kMicrosecondsPerMillisecond); load_start_time_ = base::TimeTicks(); + + return true; } PluginLoaderPosix::PendingCallback::PendingCallback( diff --git a/content/browser/plugin_loader_posix.h b/content/browser/plugin_loader_posix.h index 97fe8bb..0651450 100644 --- a/content/browser/plugin_loader_posix.h +++ b/content/browser/plugin_loader_posix.h @@ -87,7 +87,7 @@ class CONTENT_EXPORT PluginLoaderPosix : public UtilityProcessHost::Client, // Runs all the registered callbacks on each's target loop if the condition // for ending the load process is done (i.e. the |next_load_index_| is outside // the ranage of the |canonical_list_|). - void RunPendingCallbacks(); + bool MaybeRunPendingCallbacks(); // The process host for which this is a client. UtilityProcessHost* process_host_; diff --git a/content/browser/plugin_loader_posix_unittest.cc b/content/browser/plugin_loader_posix_unittest.cc index 5b83ae4..e1345ee 100644 --- a/content/browser/plugin_loader_posix_unittest.cc +++ b/content/browser/plugin_loader_posix_unittest.cc @@ -41,6 +41,10 @@ class MockPluginLoaderPosix : public PluginLoaderPosix { return &internal_plugins_; } + void RealLoadPluginsInternal() { + PluginLoaderPosix::LoadPluginsInternal(); + } + void TestOnPluginLoaded(const webkit::WebPluginInfo& plugin) { OnPluginLoaded(plugin); } @@ -279,3 +283,36 @@ TEST_F(PluginLoaderPosixTest, InternalPlugin) { message_loop()->RunAllPending(); EXPECT_EQ(1, did_callback); } + +TEST_F(PluginLoaderPosixTest, AllCrashed) { + int did_callback = 0; + PluginService::GetPluginsCallback callback = + base::Bind(&VerifyCallback, base::Unretained(&did_callback)); + + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + + // Spin the loop so that the canonical list of plugins can be set. + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + message_loop()->RunAllPending(); + AddThreePlugins(); + + EXPECT_EQ(0u, plugin_loader()->next_load_index()); + + // Mock the first two calls like normal. + testing::Expectation first = + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2); + // On the last call, go through the default impl. + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()) + .After(first) + .WillOnce( + testing::Invoke(plugin_loader(), + &MockPluginLoaderPosix::RealLoadPluginsInternal)); + plugin_loader()->OnProcessCrashed(42); + plugin_loader()->OnProcessCrashed(42); + plugin_loader()->OnProcessCrashed(42); + + message_loop()->RunAllPending(); + EXPECT_EQ(1, did_callback); + + EXPECT_EQ(0u, plugin_loader()->loaded_plugins().size()); +} diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc index 13f52d3..7d2c811 100644 --- a/content/browser/plugin_service.cc +++ b/content/browser/plugin_service.cc @@ -67,8 +67,7 @@ static void GetPluginsForGroupsCallback( // Callback set on the PluginList to assert that plugin loading happens on the // correct thread. void WillLoadPluginsCallback() { - // TODO(rsesek): Change these to CHECKs. -#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) +#if defined(OS_WIN) CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); #else CHECK(false) << "Plugin loading should happen out-of-process."; @@ -500,7 +499,7 @@ void PluginService::GetPlugins(const GetPluginsCallback& callback) { scoped_refptr<base::MessageLoopProxy> target_loop( MessageLoop::current()->message_loop_proxy()); -#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX)) +#if defined(OS_WIN) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(&PluginService::GetPluginsInternal, base::Unretained(this), target_loop, callback)); |