diff options
author | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-21 17:45:43 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-21 17:45:43 +0000 |
commit | d4af1e727ce10d9f4eda8424e63cbb82b16f22b9 (patch) | |
tree | 9b7db4554d5e7ad414e1f1564ca083f3abb5ee5c /content/browser/plugin_loader_posix_unittest.cc | |
parent | 3cb34b797fe70cec168c0e5824014dcf856ee8e3 (diff) | |
download | chromium_src-d4af1e727ce10d9f4eda8424e63cbb82b16f22b9.zip chromium_src-d4af1e727ce10d9f4eda8424e63cbb82b16f22b9.tar.gz chromium_src-d4af1e727ce10d9f4eda8424e63cbb82b16f22b9.tar.bz2 |
Gracefully handle child process death in out-of-process plugin loading.
This also queues requests to load plugins, based on http://codereview.chromium.org/8243010/.
BUG=100053
TEST=Install Sonix webcam driver on OS X Lion and try to load a Flash video. It plays.
Review URL: http://codereview.chromium.org/8318028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106738 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/plugin_loader_posix_unittest.cc')
-rw-r--r-- | content/browser/plugin_loader_posix_unittest.cc | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/content/browser/plugin_loader_posix_unittest.cc b/content/browser/plugin_loader_posix_unittest.cc new file mode 100644 index 0000000..eb18428 --- /dev/null +++ b/content/browser/plugin_loader_posix_unittest.cc @@ -0,0 +1,278 @@ +// 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 "content/browser/plugin_loader_posix.h" + +#include "base/bind.h" +#include "base/file_path.h" +#include "base/message_loop.h" +#include "base/memory/ref_counted.h" +#include "base/utf_string_conversions.h" +#include "content/browser/browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "webkit/plugins/webplugininfo.h" + +class MockPluginLoaderPosix : public PluginLoaderPosix { + public: + MOCK_METHOD0(LoadPluginsInternal, void(void)); + + size_t number_of_pending_callbacks() { + return callbacks_.size(); + } + + std::vector<FilePath>* canonical_list() { + return &canonical_list_; + } + + size_t next_load_index() { + return next_load_index_; + } + + const std::vector<webkit::WebPluginInfo>& loaded_plugins() { + return loaded_plugins_; + } + + std::vector<webkit::WebPluginInfo>* internal_plugins() { + return &internal_plugins_; + } + + void TestOnPluginLoaded(const webkit::WebPluginInfo& plugin) { + OnPluginLoaded(plugin); + } + + void TestOnPluginLoadFailed(const FilePath& path) { + OnPluginLoadFailed(path); + } +}; + +void VerifyCallback(int* run_count, const std::vector<webkit::WebPluginInfo>&) { + ++(*run_count); +} + +class PluginLoaderPosixTest : public testing::Test { + public: + PluginLoaderPosixTest() + : plugin1_(ASCIIToUTF16("plugin1"), FilePath("/tmp/one.plugin"), + ASCIIToUTF16("1.0"), string16()), + plugin2_(ASCIIToUTF16("plugin2"), FilePath("/tmp/two.plugin"), + ASCIIToUTF16("2.0"), string16()), + plugin3_(ASCIIToUTF16("plugin3"), FilePath("/tmp/three.plugin"), + ASCIIToUTF16("3.0"), string16()), + file_thread_(BrowserThread::FILE, &message_loop_), + io_thread_(BrowserThread::IO, &message_loop_), + plugin_loader_(new MockPluginLoaderPosix) { + } + + MessageLoop* message_loop() { return &message_loop_; } + MockPluginLoaderPosix* plugin_loader() { return plugin_loader_.get(); } + + void AddThreePlugins() { + plugin_loader_->canonical_list()->clear(); + plugin_loader_->canonical_list()->push_back(plugin1_.path); + plugin_loader_->canonical_list()->push_back(plugin2_.path); + plugin_loader_->canonical_list()->push_back(plugin3_.path); + } + + // Data used for testing. + webkit::WebPluginInfo plugin1_; + webkit::WebPluginInfo plugin2_; + webkit::WebPluginInfo plugin3_; + + private: + MessageLoopForIO message_loop_; + BrowserThread file_thread_; + BrowserThread io_thread_; + + scoped_refptr<MockPluginLoaderPosix> plugin_loader_; +}; + +TEST_F(PluginLoaderPosixTest, QueueRequests) { + int did_callback = 0; + PluginService::GetPluginsCallback callback = + base::Bind(&VerifyCallback, base::Unretained(&did_callback)); + + EXPECT_EQ(0u, plugin_loader()->number_of_pending_callbacks()); + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + EXPECT_EQ(1u, plugin_loader()->number_of_pending_callbacks()); + + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + EXPECT_EQ(2u, plugin_loader()->number_of_pending_callbacks()); + + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + message_loop()->RunAllPending(); + + plugin_loader()->canonical_list()->clear(); + plugin_loader()->canonical_list()->push_back(plugin1_.path); + + EXPECT_EQ(0, did_callback); + + plugin_loader()->TestOnPluginLoaded(plugin1_); + message_loop()->RunAllPending(); + + EXPECT_EQ(2, did_callback); + EXPECT_EQ(0u, plugin_loader()->number_of_pending_callbacks()); +} + +TEST_F(PluginLoaderPosixTest, ThreeSuccessfulLoads) { + int did_callback = 0; + PluginService::GetPluginsCallback callback = + base::Bind(&VerifyCallback, base::Unretained(&did_callback)); + + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + message_loop()->RunAllPending(); + + AddThreePlugins(); + + EXPECT_EQ(0u, plugin_loader()->next_load_index()); + + const std::vector<webkit::WebPluginInfo>& plugins( + plugin_loader()->loaded_plugins()); + + plugin_loader()->TestOnPluginLoaded(plugin1_); + EXPECT_EQ(1u, plugin_loader()->next_load_index()); + EXPECT_EQ(1u, plugins.size()); + EXPECT_EQ(plugin1_.name, plugins[0].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + plugin_loader()->TestOnPluginLoaded(plugin2_); + EXPECT_EQ(2u, plugin_loader()->next_load_index()); + EXPECT_EQ(2u, plugins.size()); + EXPECT_EQ(plugin2_.name, plugins[1].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + plugin_loader()->TestOnPluginLoaded(plugin3_); + EXPECT_EQ(3u, plugins.size()); + EXPECT_EQ(plugin3_.name, plugins[2].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(1, did_callback); +} + +TEST_F(PluginLoaderPosixTest, TwoFailures) { + int did_callback = 0; + PluginService::GetPluginsCallback callback = + base::Bind(&VerifyCallback, base::Unretained(&did_callback)); + + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + message_loop()->RunAllPending(); + + AddThreePlugins(); + + EXPECT_EQ(0u, plugin_loader()->next_load_index()); + + const std::vector<webkit::WebPluginInfo>& plugins( + plugin_loader()->loaded_plugins()); + + plugin_loader()->TestOnPluginLoadFailed(plugin1_.path); + EXPECT_EQ(1u, plugin_loader()->next_load_index()); + EXPECT_EQ(0u, plugins.size()); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + plugin_loader()->TestOnPluginLoaded(plugin2_); + EXPECT_EQ(2u, plugin_loader()->next_load_index()); + EXPECT_EQ(1u, plugins.size()); + EXPECT_EQ(plugin2_.name, plugins[0].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + plugin_loader()->TestOnPluginLoadFailed(plugin3_.path); + EXPECT_EQ(1u, plugins.size()); + + message_loop()->RunAllPending(); + EXPECT_EQ(1, did_callback); +} + +TEST_F(PluginLoaderPosixTest, CrashedProcess) { + int did_callback = 0; + PluginService::GetPluginsCallback callback = + base::Bind(&VerifyCallback, base::Unretained(&did_callback)); + + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + message_loop()->RunAllPending(); + + AddThreePlugins(); + + EXPECT_EQ(0u, plugin_loader()->next_load_index()); + + const std::vector<webkit::WebPluginInfo>& plugins( + plugin_loader()->loaded_plugins()); + + plugin_loader()->TestOnPluginLoaded(plugin1_); + EXPECT_EQ(1u, plugin_loader()->next_load_index()); + EXPECT_EQ(1u, plugins.size()); + EXPECT_EQ(plugin1_.name, plugins[0].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + plugin_loader()->OnProcessCrashed(42); + EXPECT_EQ(1u, plugin_loader()->canonical_list()->size()); + EXPECT_EQ(0u, plugin_loader()->next_load_index()); + EXPECT_EQ(plugin3_.path.value(), + plugin_loader()->canonical_list()->at(0).value()); +} + +TEST_F(PluginLoaderPosixTest, InternalPlugin) { + int did_callback = 0; + PluginService::GetPluginsCallback callback = + base::Bind(&VerifyCallback, base::Unretained(&did_callback)); + + plugin_loader()->LoadPlugins(message_loop()->message_loop_proxy(), callback); + + EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1); + message_loop()->RunAllPending(); + + plugin2_.path = FilePath("/internal/plugin.plugin"); + + AddThreePlugins(); + + plugin_loader()->internal_plugins()->clear(); + plugin_loader()->internal_plugins()->push_back(plugin2_); + + EXPECT_EQ(0u, plugin_loader()->next_load_index()); + + const std::vector<webkit::WebPluginInfo>& plugins( + plugin_loader()->loaded_plugins()); + + plugin_loader()->TestOnPluginLoaded(plugin1_); + EXPECT_EQ(1u, plugin_loader()->next_load_index()); + EXPECT_EQ(1u, plugins.size()); + EXPECT_EQ(plugin1_.name, plugins[0].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + // Internal plugins can fail to load if they're built-in with manual + // entrypoint functions. + plugin_loader()->TestOnPluginLoadFailed(plugin2_.path); + EXPECT_EQ(2u, plugin_loader()->next_load_index()); + EXPECT_EQ(2u, plugins.size()); + EXPECT_EQ(plugin2_.name, plugins[1].name); + EXPECT_EQ(0u, plugin_loader()->internal_plugins()->size()); + + message_loop()->RunAllPending(); + EXPECT_EQ(0, did_callback); + + plugin_loader()->TestOnPluginLoaded(plugin3_); + EXPECT_EQ(3u, plugins.size()); + EXPECT_EQ(plugin3_.name, plugins[2].name); + + message_loop()->RunAllPending(); + EXPECT_EQ(1, did_callback); +} |