1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "base/file_util.h"
7 #include "base/path_service.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/loader/resource_dispatcher_host_impl.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/resource_dispatcher_host_delegate.h"
13 #include "content/public/common/content_switches.h"
14 #include "content/public/test/browser_test_utils.h"
15 #include "content/public/test/content_browser_test.h"
16 #include "content/public/test/content_browser_test_utils.h"
17 #include "content/public/test/test_utils.h"
18 #include "content/shell/browser/shell.h"
19 #include "content/shell/common/shell_switches.h"
20 #include "content/test/net/url_request_mock_http_job.h"
21 #include "net/test/embedded_test_server/embedded_test_server.h"
22 #include "net/url_request/url_request.h"
23 #include "ui/gfx/rect.h"
26 #include "base/win/registry.h"
29 // TODO(jschuh): Finish plugins on Win64. crbug.com/180861
30 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
31 #define MAYBE(x) DISABLED_##x
36 using base::ASCIIToUTF16;
41 void SetUrlRequestMock(const base::FilePath& path) {
42 URLRequestMockHTTPJob::AddUrlHandler(path);
47 class PluginTest : public ContentBrowserTest {
51 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
52 // Some NPAPI tests schedule garbage collection to force object tear-down.
53 command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose_gc");
56 const testing::TestInfo* const test_info =
57 testing::UnitTest::GetInstance()->current_test_info();
58 if (strcmp(test_info->name(), "MediaPlayerNew") == 0) {
59 // The installer adds our process names to the registry key below. Since
60 // the installer might not have run on this machine, add it manually.
61 base::win::RegKey regkey;
62 if (regkey.Open(HKEY_LOCAL_MACHINE,
63 L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
64 KEY_WRITE) == ERROR_SUCCESS) {
65 regkey.CreateKey(L"BROWSER_TESTS.EXE", KEY_READ);
67 } else if (strcmp(test_info->name(), "FlashSecurity") == 0) {
68 command_line->AppendSwitchASCII(switches::kTestSandbox,
69 "security_tests.dll");
71 #elif defined(OS_MACOSX)
72 base::FilePath plugin_dir;
73 PathService::Get(base::DIR_MODULE, &plugin_dir);
74 plugin_dir = plugin_dir.AppendASCII("plugins");
75 // The plugins directory isn't read by default on the Mac, so it needs to be
76 // explicitly registered.
77 command_line->AppendSwitchPath(switches::kExtraPluginDir, plugin_dir);
81 virtual void SetUpOnMainThread() OVERRIDE {
82 base::FilePath path = GetTestFilePath("", "");
83 BrowserThread::PostTask(
84 BrowserThread::IO, FROM_HERE, base::Bind(&SetUrlRequestMock, path));
87 static void LoadAndWaitInWindow(Shell* window, const GURL& url) {
88 base::string16 expected_title(ASCIIToUTF16("OK"));
89 TitleWatcher title_watcher(window->web_contents(), expected_title);
90 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
91 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found"));
92 NavigateToURL(window, url);
93 base::string16 title = title_watcher.WaitAndGetTitle();
94 if (title == ASCIIToUTF16("plugin_not_found")) {
95 const testing::TestInfo* const test_info =
96 testing::UnitTest::GetInstance()->current_test_info();
97 VLOG(0) << "PluginTest." << test_info->name()
98 << " not running because plugin not installed.";
100 EXPECT_EQ(expected_title, title);
104 void LoadAndWait(const GURL& url) {
105 LoadAndWaitInWindow(shell(), url);
108 GURL GetURL(const char* filename) {
109 return GetTestUrl("npapi", filename);
112 void NavigateAway() {
113 GURL url = GetTestUrl("", "simple_page.html");
117 void TestPlugin(const char* filename) {
118 base::FilePath path = GetTestFilePath("plugin", filename);
119 if (!base::PathExists(path)) {
120 const testing::TestInfo* const test_info =
121 testing::UnitTest::GetInstance()->current_test_info();
122 VLOG(0) << "PluginTest." << test_info->name()
123 << " not running because test data wasn't found.";
127 GURL url = GetTestUrl("plugin", filename);
132 // Make sure that navigating away from a plugin referenced by JS doesn't
134 IN_PROC_BROWSER_TEST_F(PluginTest, UnloadNoCrash) {
135 LoadAndWait(GetURL("layout_test_plugin.html"));
139 // Tests if a plugin executing a self deleting script using NPN_GetURL
140 // works without crashing or hanging
141 // Flaky: http://crbug.com/59327
142 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginGetUrl)) {
143 LoadAndWait(GetURL("self_delete_plugin_geturl.html"));
146 // Tests if a plugin executing a self deleting script using Invoke
147 // works without crashing or hanging
148 // Flaky. See http://crbug.com/30702
149 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvoke)) {
150 LoadAndWait(GetURL("self_delete_plugin_invoke.html"));
153 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectReleasedOnDestruction)) {
154 NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html"));
158 // Test that a dialog is properly created when a plugin throws an
159 // exception. Should be run for in and out of process plugins, but
160 // the more interesting case is out of process, where we must route
161 // the exception to the correct renderer.
162 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectSetException)) {
163 LoadAndWait(GetURL("npobject_set_exception.html"));
167 // Tests if a plugin executing a self deleting script in the context of
168 // a synchronous mouseup works correctly.
169 // This was never ported to Mac. The only thing remaining is to make
170 // SimulateMouseClick get to Mac plugins, currently it doesn't work.
171 IN_PROC_BROWSER_TEST_F(PluginTest,
172 MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp)) {
173 NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html"));
175 base::string16 expected_title(ASCIIToUTF16("OK"));
176 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
177 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
178 SimulateMouseClick(shell()->web_contents(), 0,
179 blink::WebMouseEvent::ButtonLeft);
180 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
184 // Flaky, http://crbug.com/302274.
185 #if defined(OS_MACOSX)
186 #define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response
188 #define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response)
191 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_GetURLRequest404Response) {
192 GURL url(URLRequestMockHTTPJob::GetMockUrl(
193 base::FilePath().AppendASCII("npapi").
194 AppendASCII("plugin_url_request_404.html")));
198 // Tests if a plugin executing a self deleting script using Invoke with
199 // a modal dialog showing works without crashing or hanging
200 // Disabled, flakily exceeds timeout, http://crbug.com/46257.
201 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) {
202 // Navigate asynchronously because if we waitd until it completes, there's a
203 // race condition where the alert can come up before we start watching for it.
204 shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html"));
206 base::string16 expected_title(ASCIIToUTF16("OK"));
207 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
208 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
210 WaitForAppModalDialog(shell());
212 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
215 // Test passing arguments to a plugin.
217 #if !defined(OS_LINUX)
218 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Arguments)) {
219 LoadAndWait(GetURL("arguments.html"));
223 // Test invoking many plugins within a single page.
224 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ManyPlugins)) {
225 LoadAndWait(GetURL("many_plugins.html"));
228 // Test various calls to GetURL from a plugin.
229 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURL)) {
230 LoadAndWait(GetURL("geturl.html"));
233 // Test various calls to GetURL for javascript URLs with
234 // non NULL targets from a plugin.
235 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL)) {
236 LoadAndWait(GetURL("get_javascript_url.html"));
239 // Test that calling GetURL with a javascript URL and target=_self
240 // works properly when the plugin is embedded in a subframe.
241 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL2)) {
242 LoadAndWait(GetURL("get_javascript_url2.html"));
245 // Test is flaky on linux/cros/win builders. http://crbug.com/71904
246 IN_PROC_BROWSER_TEST_F(PluginTest, GetURLRedirectNotification) {
247 LoadAndWait(GetURL("geturl_redirect_notify.html"));
250 // Tests that identity is preserved for NPObjects passed from a plugin
252 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectIdentity)) {
253 LoadAndWait(GetURL("npobject_identity.html"));
256 // Tests that if an NPObject is proxies back to its original process, the
257 // original pointer is returned and not a proxy. If this fails the plugin
259 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectProxy)) {
260 LoadAndWait(GetURL("npobject_proxy.html"));
263 #if defined(OS_WIN) || defined(OS_MACOSX)
264 // Tests if a plugin executing a self deleting script in the context of
265 // a synchronous paint event works correctly
266 // http://crbug.com/44960
267 IN_PROC_BROWSER_TEST_F(PluginTest,
268 MAYBE(SelfDeletePluginInvokeInSynchronousPaint)) {
269 LoadAndWait(GetURL("execute_script_delete_in_paint.html"));
273 // Tests that if a plugin executes a self resizing script in the context of a
274 // synchronous paint, the plugin doesn't use deallocated memory.
275 // http://crbug.com/139462
276 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ResizeDuringPaint)) {
277 LoadAndWait(GetURL("resize_during_paint.html"));
280 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNewStream)) {
281 LoadAndWait(GetURL("self_delete_plugin_stream.html"));
284 // On Mac this test asserts in plugin_host: http://crbug.com/95558
285 // On all platforms it flakes in ~URLRequestContext: http://crbug.com/310336
287 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_DeletePluginInDeallocate) {
288 LoadAndWait(GetURL("plugin_delete_in_deallocate.html"));
294 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyPluginWindowRect)) {
295 LoadAndWait(GetURL("verify_plugin_window_rect.html"));
298 // Tests that creating a new instance of a plugin while another one is handling
299 // a paint message doesn't cause deadlock.
300 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(CreateInstanceInPaint)) {
301 LoadAndWait(GetURL("create_instance_in_paint.html"));
304 // Tests that putting up an alert in response to a paint doesn't deadlock.
305 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_AlertInWindowMessage) {
306 NavigateToURL(shell(), GetURL("alert_in_window_message.html"));
308 WaitForAppModalDialog(shell());
309 WaitForAppModalDialog(shell());
312 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyNPObjectLifetimeTest)) {
313 LoadAndWait(GetURL("npobject_lifetime_test.html"));
316 // Tests that we don't crash or assert if NPP_New fails
317 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NewFails)) {
318 LoadAndWait(GetURL("new_fails.html"));
321 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNPNEvaluate)) {
322 LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html"));
325 IN_PROC_BROWSER_TEST_F(PluginTest,
326 MAYBE(SelfDeleteCreatePluginInNPNEvaluate)) {
327 LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html"));
332 // If this flakes, reopen http://crbug.com/17645
333 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out).
334 #if !defined(OS_MACOSX) && !defined(OS_LINUX)
335 // Disabled on Mac because the plugin side isn't implemented yet, see
336 // "TODO(port)" in plugin_javascript_open_popup.cc.
337 // Disabled on Linux because we don't support NPAPI any more.
338 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(OpenPopupWindowWithPlugin)) {
339 LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html"));
343 // Test checking the privacy mode is off.
344 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateDisabled)) {
345 LoadAndWait(GetURL("private.html"));
348 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ScheduleTimer)) {
349 LoadAndWait(GetURL("schedule_timer.html"));
352 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginThreadAsyncCall)) {
353 LoadAndWait(GetURL("plugin_thread_async_call.html"));
356 IN_PROC_BROWSER_TEST_F(PluginTest, PluginSingleRangeRequest) {
357 LoadAndWait(GetURL("plugin_single_range_request.html"));
360 // Test checking the privacy mode is on.
361 // If this flakes on Linux, use http://crbug.com/104380
362 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateEnabled)) {
363 GURL url = GetURL("private.html");
364 url = GURL(url.spec() + "?private");
365 LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url);
368 #if defined(OS_WIN) || defined(OS_MACOSX)
369 // Test a browser hang due to special case of multiple
370 // plugin instances indulged in sync calls across renderer.
371 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MultipleInstancesSyncCalls)) {
372 LoadAndWait(GetURL("multiple_instances_sync_calls.html"));
376 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequestFailWrite)) {
377 GURL url(URLRequestMockHTTPJob::GetMockUrl(
378 base::FilePath().AppendASCII("npapi").
379 AppendASCII("plugin_url_request_fail_write.html")));
384 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(EnsureScriptingWorksInDestroy)) {
385 LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html"));
388 // This test uses a Windows Event to signal to the plugin that it should crash
390 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NoHangIfInitCrashes)) {
391 HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit");
392 SetEvent(crash_event);
393 LoadAndWait(GetURL("no_hang_if_init_crashes.html"));
394 CloseHandle(crash_event);
398 // If this flakes on Mac, use http://crbug.com/111508
399 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginReferrerTest)) {
400 GURL url(URLRequestMockHTTPJob::GetMockUrl(
401 base::FilePath().AppendASCII("npapi").
402 AppendASCII("plugin_url_request_referrer_test.html")));
406 #if defined(OS_MACOSX)
407 // Test is flaky, see http://crbug.com/134515.
408 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_PluginConvertPointTest) {
409 gfx::Rect bounds(50, 50, 400, 400);
410 SetWindowBounds(shell()->window(), bounds);
412 NavigateToURL(shell(), GetURL("convert_point.html"));
414 base::string16 expected_title(ASCIIToUTF16("OK"));
415 TitleWatcher title_watcher(shell()->web_contents(), expected_title);
416 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
417 // TODO(stuartmorgan): When the automation system supports sending clicks,
418 // change the test to trigger on mouse-down rather than window focus.
420 // TODO: is this code still needed? It was here when it used to run in
422 //static_cast<WebContentsDelegate*>(shell())->
423 // ActivateContents(shell()->web_contents());
424 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
428 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Flash)) {
429 TestPlugin("flash.html");
434 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashSecurity) {
435 TestPlugin("flash.html");
437 #endif // defined(OS_WIN)
440 // TODO(port) Port the following tests to platforms that have the required
442 // Flaky: http://crbug.com/55915
443 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Quicktime)) {
444 TestPlugin("quicktime.html");
447 // Disabled - http://crbug.com/44662
448 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MediaPlayerNew)) {
449 TestPlugin("wmp_new.html");
452 // Disabled - http://crbug.com/44673
453 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Real)) {
454 TestPlugin("real.html");
457 // http://crbug.com/320041
458 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
459 (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
460 #define MAYBE_FlashOctetStream DISABLED_FlashOctetStream
462 #define MAYBE_FlashOctetStream FlashOctetStream
464 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_FlashOctetStream) {
465 TestPlugin("flash-octet-stream.html");
469 // http://crbug.com/53926
470 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashLayoutWhilePainting) {
472 IN_PROC_BROWSER_TEST_F(PluginTest, FlashLayoutWhilePainting) {
474 TestPlugin("flash-layout-while-painting.html");
477 // http://crbug.com/8690
478 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Java) {
479 TestPlugin("Java.html");
482 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Silverlight)) {
483 TestPlugin("silverlight.html");
485 #endif // defined(OS_WIN)
487 class TestResourceDispatcherHostDelegate
488 : public ResourceDispatcherHostDelegate {
490 TestResourceDispatcherHostDelegate() : found_cookie_(false) {}
492 bool found_cookie() { return found_cookie_; }
494 void WaitForPluginRequest() {
498 runner_ = new MessageLoopRunner;
503 // ResourceDispatcherHostDelegate implementation:
504 virtual void OnResponseStarted(
505 net::URLRequest* request,
506 ResourceContext* resource_context,
507 ResourceResponse* response,
508 IPC::Sender* sender) OVERRIDE {
509 // The URL below comes from plugin_geturl_test.cc.
510 if (!EndsWith(request->url().spec(),
511 "npapi/plugin_ref_target_page.html",
515 net::HttpRequestHeaders headers;
516 bool found_cookie = false;
517 if (request->GetFullRequestHeaders(&headers) &&
518 headers.ToString().find("Cookie: blah") != std::string::npos) {
521 BrowserThread::PostTask(
524 base::Bind(&TestResourceDispatcherHostDelegate::GotCookie,
525 base::Unretained(this), found_cookie));
528 void GotCookie(bool found_cookie) {
529 found_cookie_ = found_cookie;
531 runner_->QuitClosure().Run();
534 scoped_refptr<MessageLoopRunner> runner_;
537 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate);
540 // Ensure that cookies get sent with plugin requests.
541 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Cookies)) {
542 // Create a new browser just to ensure that the plugin process' child_id is
543 // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which
545 NavigateToURL(CreateBrowser(), GURL("about:blank"));
547 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
548 GURL url(embedded_test_server()->GetURL("/npapi/cookies.html"));
550 TestResourceDispatcherHostDelegate test_delegate;
551 ResourceDispatcherHostDelegate* old_delegate =
552 ResourceDispatcherHostImpl::Get()->delegate();
553 ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate);
555 test_delegate.WaitForPluginRequest();
556 ASSERT_TRUE(test_delegate.found_cookie());
557 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate);
560 } // namespace content