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/files/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 "net/test/embedded_test_server/embedded_test_server.h"
21 #include "net/test/url_request/url_request_mock_http_job.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 net::URLRequestMockHTTPJob::AddUrlHandler(
43 path
, content::BrowserThread::GetBlockingPool());
48 class PluginTest
: public ContentBrowserTest
{
52 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
53 // Some NPAPI tests schedule garbage collection to force object tear-down.
54 command_line
->AppendSwitchASCII(switches::kJavaScriptFlags
, "--expose_gc");
57 const testing::TestInfo
* const test_info
=
58 testing::UnitTest::GetInstance()->current_test_info();
59 if (strcmp(test_info
->name(), "MediaPlayerNew") == 0) {
60 // The installer adds our process names to the registry key below. Since
61 // the installer might not have run on this machine, add it manually.
62 base::win::RegKey regkey
;
63 if (regkey
.Open(HKEY_LOCAL_MACHINE
,
64 L
"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
65 KEY_WRITE
) == ERROR_SUCCESS
) {
66 regkey
.CreateKey(L
"BROWSER_TESTS.EXE", KEY_READ
);
69 #elif defined(OS_MACOSX)
70 base::FilePath plugin_dir
;
71 PathService::Get(base::DIR_MODULE
, &plugin_dir
);
72 plugin_dir
= plugin_dir
.AppendASCII("plugins");
73 // The plugins directory isn't read by default on the Mac, so it needs to be
74 // explicitly registered.
75 command_line
->AppendSwitchPath(switches::kExtraPluginDir
, plugin_dir
);
79 virtual void SetUpOnMainThread() OVERRIDE
{
80 base::FilePath path
= GetTestFilePath("", "");
81 BrowserThread::PostTask(
82 BrowserThread::IO
, FROM_HERE
, base::Bind(&SetUrlRequestMock
, path
));
85 static void LoadAndWaitInWindow(Shell
* window
, const GURL
& url
) {
86 base::string16
expected_title(ASCIIToUTF16("OK"));
87 TitleWatcher
title_watcher(window
->web_contents(), expected_title
);
88 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
89 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found"));
90 NavigateToURL(window
, url
);
91 base::string16 title
= title_watcher
.WaitAndGetTitle();
92 if (title
== ASCIIToUTF16("plugin_not_found")) {
93 const testing::TestInfo
* const test_info
=
94 testing::UnitTest::GetInstance()->current_test_info();
95 VLOG(0) << "PluginTest." << test_info
->name()
96 << " not running because plugin not installed.";
98 EXPECT_EQ(expected_title
, title
);
102 void LoadAndWait(const GURL
& url
) {
103 LoadAndWaitInWindow(shell(), url
);
106 GURL
GetURL(const char* filename
) {
107 return GetTestUrl("npapi", filename
);
110 void NavigateAway() {
111 GURL url
= GetTestUrl("", "simple_page.html");
115 void TestPlugin(const char* filename
) {
116 base::FilePath path
= GetTestFilePath("plugin", filename
);
117 if (!base::PathExists(path
)) {
118 const testing::TestInfo
* const test_info
=
119 testing::UnitTest::GetInstance()->current_test_info();
120 VLOG(0) << "PluginTest." << test_info
->name()
121 << " not running because test data wasn't found.";
125 GURL url
= GetTestUrl("plugin", filename
);
130 // Make sure that navigating away from a plugin referenced by JS doesn't
132 IN_PROC_BROWSER_TEST_F(PluginTest
, UnloadNoCrash
) {
133 LoadAndWait(GetURL("layout_test_plugin.html"));
137 // Tests if a plugin executing a self deleting script using NPN_GetURL
138 // works without crashing or hanging
139 // Flaky: http://crbug.com/59327
140 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginGetUrl
)) {
141 LoadAndWait(GetURL("self_delete_plugin_geturl.html"));
144 // Tests if a plugin executing a self deleting script using Invoke
145 // works without crashing or hanging
146 // Flaky. See http://crbug.com/30702
147 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInvoke
)) {
148 LoadAndWait(GetURL("self_delete_plugin_invoke.html"));
151 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectReleasedOnDestruction
)) {
152 NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html"));
156 // Test that a dialog is properly created when a plugin throws an
157 // exception. Should be run for in and out of process plugins, but
158 // the more interesting case is out of process, where we must route
159 // the exception to the correct renderer.
160 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectSetException
)) {
161 LoadAndWait(GetURL("npobject_set_exception.html"));
165 // Tests if a plugin executing a self deleting script in the context of
166 // a synchronous mouseup works correctly.
167 // This was never ported to Mac. The only thing remaining is to make
168 // SimulateMouseClick get to Mac plugins, currently it doesn't work.
169 IN_PROC_BROWSER_TEST_F(PluginTest
,
170 MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp
)) {
171 NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html"));
173 base::string16
expected_title(ASCIIToUTF16("OK"));
174 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
175 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
176 SimulateMouseClick(shell()->web_contents(), 0,
177 blink::WebMouseEvent::ButtonLeft
);
178 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
182 // Flaky, http://crbug.com/302274.
183 #if defined(OS_MACOSX)
184 #define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response
186 #define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response)
189 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_GetURLRequest404Response
) {
190 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(
191 base::FilePath().AppendASCII("npapi").AppendASCII(
192 "plugin_url_request_404.html")));
196 // Tests if a plugin executing a self deleting script using Invoke with
197 // a modal dialog showing works without crashing or hanging
198 // Disabled, flakily exceeds timeout, http://crbug.com/46257.
199 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInvokeAlert
)) {
200 // Navigate asynchronously because if we waitd until it completes, there's a
201 // race condition where the alert can come up before we start watching for it.
202 shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html"));
204 base::string16
expected_title(ASCIIToUTF16("OK"));
205 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
206 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
208 WaitForAppModalDialog(shell());
210 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
213 // Test passing arguments to a plugin.
215 #if !defined(OS_LINUX)
216 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Arguments
)) {
217 LoadAndWait(GetURL("arguments.html"));
221 // Test invoking many plugins within a single page.
222 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ManyPlugins
)) {
223 LoadAndWait(GetURL("many_plugins.html"));
226 #if !defined(OS_MACOSX) // http://crbug.com/402164
227 // Test various calls to GetURL from a plugin.
228 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetURL
)) {
229 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 // http://crbug.com/406184
301 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_CreateInstanceInPaint
) {
302 LoadAndWait(GetURL("create_instance_in_paint.html"));
305 // Tests that putting up an alert in response to a paint doesn't deadlock.
306 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_AlertInWindowMessage
) {
307 NavigateToURL(shell(), GetURL("alert_in_window_message.html"));
309 WaitForAppModalDialog(shell());
310 WaitForAppModalDialog(shell());
313 // http://crbug.com/406184
314 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_VerifyNPObjectLifetimeTest
) {
315 LoadAndWait(GetURL("npobject_lifetime_test.html"));
318 // Tests that we don't crash or assert if NPP_New fails
319 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NewFails
)) {
320 LoadAndWait(GetURL("new_fails.html"));
323 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInNPNEvaluate
)) {
324 LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html"));
327 IN_PROC_BROWSER_TEST_F(PluginTest
,
328 MAYBE(SelfDeleteCreatePluginInNPNEvaluate
)) {
329 LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html"));
334 // If this flakes, reopen http://crbug.com/17645
335 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out).
336 #if !defined(OS_MACOSX) && !defined(OS_LINUX)
337 // Disabled on Mac because the plugin side isn't implemented yet, see
338 // "TODO(port)" in plugin_javascript_open_popup.cc.
339 // Disabled on Linux because we don't support NPAPI any more.
340 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(OpenPopupWindowWithPlugin
)) {
341 LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html"));
345 // Test checking the privacy mode is off.
346 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PrivateDisabled
)) {
347 LoadAndWait(GetURL("private.html"));
350 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ScheduleTimer
)) {
351 LoadAndWait(GetURL("schedule_timer.html"));
354 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PluginThreadAsyncCall
)) {
355 LoadAndWait(GetURL("plugin_thread_async_call.html"));
358 IN_PROC_BROWSER_TEST_F(PluginTest
, PluginSingleRangeRequest
) {
359 LoadAndWait(GetURL("plugin_single_range_request.html"));
362 #if !defined(OS_WIN) // http://crbug.com/396373
363 // Test checking the privacy mode is on.
364 // If this flakes on Linux, use http://crbug.com/104380
365 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PrivateEnabled
)) {
366 GURL url
= GetURL("private.html");
367 url
= GURL(url
.spec() + "?private");
368 LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url
);
372 // These used to run on Windows: http://crbug.com/396373
373 #if defined(OS_MACOSX)
374 // Test a browser hang due to special case of multiple
375 // plugin instances indulged in sync calls across renderer.
376 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(MultipleInstancesSyncCalls
)) {
377 LoadAndWait(GetURL("multiple_instances_sync_calls.html"));
380 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetURLRequestFailWrite
)) {
381 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(
382 base::FilePath().AppendASCII("npapi").AppendASCII(
383 "plugin_url_request_fail_write.html")));
389 // Flaky on Windows x86. http://crbug.com/388245
390 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_EnsureScriptingWorksInDestroy
) {
391 LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html"));
394 // This test uses a Windows Event to signal to the plugin that it should crash
396 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NoHangIfInitCrashes
)) {
397 HANDLE crash_event
= CreateEvent(NULL
, TRUE
, FALSE
, L
"TestPluginCrashOnInit");
398 SetEvent(crash_event
);
399 LoadAndWait(GetURL("no_hang_if_init_crashes.html"));
400 CloseHandle(crash_event
);
404 // If this flakes on Mac, use http://crbug.com/111508
405 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PluginReferrerTest
)) {
406 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(
407 base::FilePath().AppendASCII("npapi").AppendASCII(
408 "plugin_url_request_referrer_test.html")));
412 #if defined(OS_MACOSX)
413 // Test is flaky, see http://crbug.com/134515.
414 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_PluginConvertPointTest
) {
415 gfx::Rect
bounds(50, 50, 400, 400);
416 SetWindowBounds(shell()->window(), bounds
);
418 NavigateToURL(shell(), GetURL("convert_point.html"));
420 base::string16
expected_title(ASCIIToUTF16("OK"));
421 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
422 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
423 // TODO(stuartmorgan): When the automation system supports sending clicks,
424 // change the test to trigger on mouse-down rather than window focus.
426 // TODO: is this code still needed? It was here when it used to run in
428 //static_cast<WebContentsDelegate*>(shell())->
429 // ActivateContents(shell()->web_contents());
430 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
434 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Flash
)) {
435 TestPlugin("flash.html");
440 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_FlashSecurity
) {
441 TestPlugin("flash.html");
443 #endif // defined(OS_WIN)
446 // TODO(port) Port the following tests to platforms that have the required
448 // Flaky: http://crbug.com/55915
449 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Quicktime
) {
450 TestPlugin("quicktime.html");
453 // Disabled - http://crbug.com/44662
454 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(MediaPlayerNew
)) {
455 TestPlugin("wmp_new.html");
458 // Disabled - http://crbug.com/44673
459 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Real
)) {
460 TestPlugin("real.html");
463 // http://crbug.com/320041
464 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
465 (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
466 #define MAYBE_FlashOctetStream DISABLED_FlashOctetStream
468 #define MAYBE_FlashOctetStream FlashOctetStream
470 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_FlashOctetStream
) {
471 TestPlugin("flash-octet-stream.html");
475 // http://crbug.com/53926
476 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_FlashLayoutWhilePainting
) {
478 IN_PROC_BROWSER_TEST_F(PluginTest
, FlashLayoutWhilePainting
) {
480 TestPlugin("flash-layout-while-painting.html");
483 // http://crbug.com/8690
484 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Java
) {
485 TestPlugin("Java.html");
488 // Flaky: http://crbug.com/55915
489 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Silverlight
) {
490 TestPlugin("silverlight.html");
492 #endif // defined(OS_WIN)
494 class TestResourceDispatcherHostDelegate
495 : public ResourceDispatcherHostDelegate
{
497 TestResourceDispatcherHostDelegate() : found_cookie_(false) {}
499 bool found_cookie() { return found_cookie_
; }
501 void WaitForPluginRequest() {
505 runner_
= new MessageLoopRunner
;
510 // ResourceDispatcherHostDelegate implementation:
511 virtual void OnResponseStarted(
512 net::URLRequest
* request
,
513 ResourceContext
* resource_context
,
514 ResourceResponse
* response
,
515 IPC::Sender
* sender
) OVERRIDE
{
516 // The URL below comes from plugin_geturl_test.cc.
517 if (!EndsWith(request
->url().spec(),
518 "npapi/plugin_ref_target_page.html",
522 net::HttpRequestHeaders headers
;
523 bool found_cookie
= false;
524 if (request
->GetFullRequestHeaders(&headers
) &&
525 headers
.ToString().find("Cookie: blah") != std::string::npos
) {
528 BrowserThread::PostTask(
531 base::Bind(&TestResourceDispatcherHostDelegate::GotCookie
,
532 base::Unretained(this), found_cookie
));
535 void GotCookie(bool found_cookie
) {
536 found_cookie_
= found_cookie
;
538 runner_
->QuitClosure().Run();
541 scoped_refptr
<MessageLoopRunner
> runner_
;
544 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate
);
547 // Ensure that cookies get sent with plugin requests.
548 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Cookies
)) {
549 // Create a new browser just to ensure that the plugin process' child_id is
550 // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which
552 NavigateToURL(CreateBrowser(), GURL("about:blank"));
554 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
555 GURL
url(embedded_test_server()->GetURL("/npapi/cookies.html"));
557 TestResourceDispatcherHostDelegate test_delegate
;
558 ResourceDispatcherHostDelegate
* old_delegate
=
559 ResourceDispatcherHostImpl::Get()->delegate();
560 ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate
);
562 test_delegate
.WaitForPluginRequest();
563 ASSERT_TRUE(test_delegate
.found_cookie());
564 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate
);
567 } // namespace content