// 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. // Tests for the top plugins to catch regressions in our plugin host code, as // well as in the out of process code. Currently this tests: // Flash // Real // QuickTime // Windows Media Player // -this includes both WMP plugins. npdsplay.dll is the older one that // comes with XP. np-mswmp.dll can be downloaded from Microsoft and // needs SP2 or Vista. #include "build/build_config.h" #if defined(OS_WIN) #include #include #include #include #endif #include #include #include #include #include "base/file_path.h" #include "base/file_util.h" #include "base/message_loop.h" #include "base/path_service.h" #include "base/test/test_timeouts.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/automation/automation_proxy.h" #include "chrome/test/automation/tab_proxy.h" #include "chrome/test/base/ui_test_utils.h" #include "chrome/test/ui/ui_test.h" #include "content/browser/net/url_request_mock_http_job.h" #include "net/base/net_util.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_test_util.h" #include "third_party/npapi/bindings/npapi.h" #include "webkit/plugins/npapi/plugin_constants_win.h" #include "webkit/plugins/npapi/plugin_list.h" #include "webkit/plugins/plugin_switches.h" #if defined(OS_WIN) #include "base/win/registry.h" #include "chrome/browser/plugin_download_helper.h" #endif class PluginTest : public UITest { public: // Generate the URL for testing a particular test. // HTML for the tests is all located in test_directory\plugin\ // Set |mock_http| to true to use mock HTTP server. static GURL GetTestUrl(const std::string& test_case, const std::string& query, bool mock_http) { static const FilePath::CharType kPluginPath[] = FILE_PATH_LITERAL("plugin"); if (mock_http) { FilePath plugin_path = FilePath(kPluginPath).AppendASCII(test_case); GURL url = URLRequestMockHTTPJob::GetMockUrl(plugin_path); if (!query.empty()) { GURL::Replacements replacements; replacements.SetQueryStr(query); return url.ReplaceComponents(replacements); } return url; } FilePath path; PathService::Get(chrome::DIR_TEST_DATA, &path); path = path.Append(kPluginPath).AppendASCII(test_case); return ui_test_utils::GetFileUrlWithQuery(path, query); } protected: virtual void SetUp() { #if defined(OS_WIN) const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); if (strcmp(test_info->name(), "MediaPlayerNew") == 0) { // The installer adds our process names to the registry key below. Since // the installer might not have run on this machine, add it manually. base::win::RegKey regkey; if (regkey.Open(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList", KEY_WRITE) == ERROR_SUCCESS) { regkey.CreateKey(L"CHROME.EXE", KEY_READ); } } else if (strcmp(test_info->name(), "MediaPlayerOld") == 0) { // When testing the old WMP plugin, we need to force Chrome to not load // the new plugin. launch_arguments_.AppendSwitch(switches::kUseOldWMPPlugin); } else if (strcmp(test_info->name(), "FlashSecurity") == 0) { launch_arguments_.AppendSwitchASCII(switches::kTestSandbox, "security_tests.dll"); } #endif // defined(OS_WIN) launch_arguments_.AppendSwitch(switches::kAllowOutdatedPlugins); launch_arguments_.AppendSwitch(switches::kAlwaysAuthorizePlugins); // TODO(rsesek): Remove after done debugging. launch_arguments_.AppendSwitch(switches::kDebugPluginLoading); UITest::SetUp(); } void TestPlugin(const std::string& test_case, const std::string& query, int timeout, bool mock_http) { GURL url = GetTestUrl(test_case, query, mock_http); NavigateToURL(url); WaitForFinish(timeout, mock_http); } // Waits for the test case to finish. void WaitForFinish(const int wait_time, bool mock_http) { static const char kTestCompleteCookie[] = "status"; static const char kTestCompleteSuccess[] = "OK"; GURL url = GetTestUrl("done", "", mock_http); scoped_refptr tab(GetActiveTab()); const std::string result = WaitUntilCookieNonEmpty(tab, url, kTestCompleteCookie, wait_time); ASSERT_EQ(kTestCompleteSuccess, result); } }; TEST_F(PluginTest, Flash) { // Note: This does not work with the npwrapper on 64-bit Linux. Install the // native 64-bit Flash to run the test. // TODO(thestig) Update this list if we decide to only test against internal // Flash plugin in the future? std::string kFlashQuery = #if defined(OS_WIN) "npswf32.dll" #elif defined(OS_MACOSX) "Flash Player.plugin" #elif defined(OS_POSIX) "libflashplayer.so" #endif ; TestPlugin("flash.html", kFlashQuery, TestTimeouts::action_max_timeout_ms(), false); } class ClickToPlayPluginTest : public PluginTest { public: ClickToPlayPluginTest() { dom_automation_enabled_ = true; } }; TEST_F(ClickToPlayPluginTest, Flash) { scoped_refptr browser(automation()->GetBrowserWindow(0)); ASSERT_TRUE(browser.get()); ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK)); GURL url = GetTestUrl("flash-clicktoplay.html", "", true); NavigateToURL(url); scoped_refptr tab(browser->GetTab(0)); ASSERT_TRUE(tab.get()); ASSERT_TRUE(tab->LoadBlockedPlugins()); WaitForFinish(TestTimeouts::action_max_timeout_ms(), true); } TEST_F(ClickToPlayPluginTest, FlashDocument) { scoped_refptr browser(automation()->GetBrowserWindow(0)); ASSERT_TRUE(browser.get()); ASSERT_TRUE(browser->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK)); scoped_refptr tab(browser->GetTab(0)); ASSERT_TRUE(tab.get()); GURL url = GetTestUrl("js-invoker.swf", "callback=done", true); NavigateToURL(url); // Inject the callback function into the HTML page generated by the browser. ASSERT_TRUE(tab->ExecuteJavaScript("window.done = function() {" " window.location = \"done.html\";" "}")); ASSERT_TRUE(tab->LoadBlockedPlugins()); WaitForFinish(TestTimeouts::action_max_timeout_ms(), true); } #if defined(OS_WIN) // Windows only test TEST_F(PluginTest, DISABLED_FlashSecurity) { TestPlugin("flash.html", "", TestTimeouts::action_max_timeout_ms(), false); } #endif // defined(OS_WIN) #if defined(OS_WIN) // TODO(port) Port the following tests to platforms that have the required // plugins. // Flaky: http://crbug.com/55915 TEST_F(PluginTest, FLAKY_Quicktime) { TestPlugin("quicktime.html", "", TestTimeouts::action_max_timeout_ms(), false); } // Disabled - http://crbug.com/44662 TEST_F(PluginTest, DISABLED_MediaPlayerNew) { TestPlugin("wmp_new.html", "", TestTimeouts::action_max_timeout_ms(), false); } // http://crbug.com/4809 TEST_F(PluginTest, DISABLED_MediaPlayerOld) { TestPlugin("wmp_old.html", "", TestTimeouts::action_max_timeout_ms(), false); } // Disabled - http://crbug.com/44673 TEST_F(PluginTest, DISABLED_Real) { TestPlugin("real.html", "", TestTimeouts::action_max_timeout_ms(), false); } TEST_F(PluginTest, FlashOctetStream) { TestPlugin("flash-octet-stream.html", "", TestTimeouts::action_max_timeout_ms(), false); } #if defined(OS_WIN) // http://crbug.com/53926 TEST_F(PluginTest, FLAKY_FlashLayoutWhilePainting) { #else TEST_F(PluginTest, FlashLayoutWhilePainting) { #endif TestPlugin("flash-layout-while-painting.html", "", TestTimeouts::action_max_timeout_ms(), true); } // http://crbug.com/8690 TEST_F(PluginTest, DISABLED_Java) { TestPlugin("Java.html", "", TestTimeouts::action_max_timeout_ms(), false); } TEST_F(PluginTest, Silverlight) { TestPlugin("silverlight.html", "", TestTimeouts::action_max_timeout_ms(), false); } namespace { class TestURLRequestContextGetter : public net::URLRequestContextGetter { public: explicit TestURLRequestContextGetter() { io_message_loop_proxy_ = base::MessageLoopProxy::current(); } virtual net::URLRequestContext* GetURLRequestContext() { if (!context_) context_ = new TestURLRequestContext(); return context_; } virtual scoped_refptr GetIOMessageLoopProxy() const { return io_message_loop_proxy_; } protected: scoped_refptr io_message_loop_proxy_; private: virtual ~TestURLRequestContextGetter() {} scoped_refptr context_; }; } // namespace // This class provides functionality to test the plugin installer download // file functionality. class PluginInstallerDownloadTest : public PluginDownloadUrlHelper::DownloadDelegate, public testing::Test { public: PluginInstallerDownloadTest() : success_(false), download_helper_(NULL) {} ~PluginInstallerDownloadTest() {} void Start() { initial_download_path_ = PluginTest::GetTestUrl("flash.html", "", false); download_helper_ = new PluginDownloadUrlHelper( initial_download_path_.spec(), NULL, static_cast(this)); TestURLRequestContextGetter* context_getter = new TestURLRequestContextGetter; download_helper_->InitiateDownload(context_getter, context_getter->GetIOMessageLoopProxy()); MessageLoop::current()->PostDelayedTask( FROM_HERE, new MessageLoop::QuitTask, TestTimeouts::action_max_timeout_ms()); } virtual void OnDownloadCompleted(const FilePath& download_path, bool success) { success_ = success; final_download_path_ = download_path; MessageLoop::current()->Quit(); download_helper_ = NULL; } FilePath final_download_path() const { return final_download_path_; } FilePath initial_download_path() const { return final_download_path_; } bool success() const { return success_; } private: FilePath final_download_path_; PluginDownloadUrlHelper* download_helper_; bool success_; GURL initial_download_path_; }; // This test validates that the plugin downloader downloads the specified file // to a temporary path with the same file name. TEST_F(PluginInstallerDownloadTest, PluginInstallerDownloadPathTest) { MessageLoop loop(MessageLoop::TYPE_IO); Start(); loop.Run(); EXPECT_TRUE(success()); EXPECT_TRUE(initial_download_path().BaseName().value() == final_download_path().BaseName().value()); } #endif // defined(OS_WIN)