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/geometry/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 // In-process windowless plugin tests that create canvas break on Windows since
37 // Win32k Renderer Lockdown was enabled in M42.
39 #define MAYBE_INPROC_WINDOWLESS(x) DISABLED_##x
41 #define MAYBE_INPROC_WINDOWLESS(x) x
44 using base::ASCIIToUTF16
;
49 void SetUrlRequestMock(const base::FilePath
& path
) {
50 net::URLRequestMockHTTPJob::AddUrlHandlers(
51 path
, content::BrowserThread::GetBlockingPool());
56 class PluginTest
: public ContentBrowserTest
{
60 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
61 // Some NPAPI tests schedule garbage collection to force object tear-down.
62 command_line
->AppendSwitchASCII(switches::kJavaScriptFlags
, "--expose_gc");
65 const testing::TestInfo
* const test_info
=
66 testing::UnitTest::GetInstance()->current_test_info();
67 if (strcmp(test_info
->name(), "MediaPlayerNew") == 0) {
68 // The installer adds our process names to the registry key below. Since
69 // the installer might not have run on this machine, add it manually.
70 base::win::RegKey regkey
;
71 if (regkey
.Open(HKEY_LOCAL_MACHINE
,
72 L
"Software\\Microsoft\\MediaPlayer\\ShimInclusionList",
73 KEY_WRITE
) == ERROR_SUCCESS
) {
74 regkey
.CreateKey(L
"BROWSER_TESTS.EXE", KEY_READ
);
77 #elif defined(OS_MACOSX)
78 base::FilePath plugin_dir
;
79 PathService::Get(base::DIR_MODULE
, &plugin_dir
);
80 plugin_dir
= plugin_dir
.AppendASCII("plugins");
81 // The plugins directory isn't read by default on the Mac, so it needs to be
82 // explicitly registered.
83 command_line
->AppendSwitchPath(switches::kExtraPluginDir
, plugin_dir
);
85 command_line
->AppendSwitch(switches::kEnableNpapiForTesting
);
88 void SetUpOnMainThread() override
{
89 base::FilePath path
= GetTestFilePath("", "");
90 BrowserThread::PostTask(
91 BrowserThread::IO
, FROM_HERE
, base::Bind(&SetUrlRequestMock
, path
));
94 static void LoadAndWaitInWindow(Shell
* window
, const GURL
& url
) {
95 base::string16
expected_title(ASCIIToUTF16("OK"));
96 TitleWatcher
title_watcher(window
->web_contents(), expected_title
);
97 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
98 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found"));
99 NavigateToURL(window
, url
);
100 base::string16 title
= title_watcher
.WaitAndGetTitle();
101 if (title
== ASCIIToUTF16("plugin_not_found")) {
102 const testing::TestInfo
* const test_info
=
103 testing::UnitTest::GetInstance()->current_test_info();
104 VLOG(0) << "PluginTest." << test_info
->name()
105 << " not running because plugin not installed.";
107 EXPECT_EQ(expected_title
, title
);
111 void LoadAndWait(const GURL
& url
) {
112 LoadAndWaitInWindow(shell(), url
);
115 GURL
GetURL(const char* filename
) {
116 return GetTestUrl("npapi", filename
);
119 void NavigateAway() {
120 GURL url
= GetTestUrl("", "simple_page.html");
124 void TestPlugin(const char* filename
) {
125 base::FilePath path
= GetTestFilePath("plugin", filename
);
126 if (!base::PathExists(path
)) {
127 const testing::TestInfo
* const test_info
=
128 testing::UnitTest::GetInstance()->current_test_info();
129 VLOG(0) << "PluginTest." << test_info
->name()
130 << " not running because test data wasn't found.";
134 GURL url
= GetTestUrl("plugin", filename
);
139 // Make sure that navigating away from a plugin referenced by JS doesn't
141 IN_PROC_BROWSER_TEST_F(PluginTest
, UnloadNoCrash
) {
142 LoadAndWait(GetURL("layout_test_plugin.html"));
146 // Tests if a plugin executing a self deleting script using NPN_GetURL
147 // works without crashing or hanging
148 // Flaky: http://crbug.com/59327
149 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginGetUrl
)) {
150 LoadAndWait(GetURL("self_delete_plugin_geturl.html"));
153 // Tests if a plugin executing a self deleting script using Invoke
154 // works without crashing or hanging
155 // Flaky. See http://crbug.com/30702
156 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInvoke
)) {
157 LoadAndWait(GetURL("self_delete_plugin_invoke.html"));
160 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectReleasedOnDestruction
)) {
161 NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html"));
165 // Test that a dialog is properly created when a plugin throws an
166 // exception. Should be run for in and out of process plugins, but
167 // the more interesting case is out of process, where we must route
168 // the exception to the correct renderer.
169 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectSetException
)) {
170 LoadAndWait(GetURL("npobject_set_exception.html"));
174 // Tests if a plugin executing a self deleting script in the context of
175 // a synchronous mouseup works correctly.
176 // This was never ported to Mac. The only thing remaining is to make
177 // SimulateMouseClick get to Mac plugins, currently it doesn't work.
178 IN_PROC_BROWSER_TEST_F(
180 MAYBE_INPROC_WINDOWLESS(SelfDeletePluginInvokeInSynchronousMouseUp
)) {
181 NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html"));
183 base::string16
expected_title(ASCIIToUTF16("OK"));
184 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
185 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
186 SimulateMouseClick(shell()->web_contents(), 0,
187 blink::WebMouseEvent::ButtonLeft
);
188 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
192 // Flaky, http://crbug.com/302274.
193 #if defined(OS_MACOSX)
194 #define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response
196 #define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response)
199 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_GetURLRequest404Response
) {
200 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(
201 base::FilePath().AppendASCII("npapi").AppendASCII(
202 "plugin_url_request_404.html")));
206 // Tests if a plugin executing a self deleting script using Invoke with
207 // a modal dialog showing works without crashing or hanging
208 // Disabled, flakily exceeds timeout, http://crbug.com/46257.
209 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInvokeAlert
)) {
210 // Navigate asynchronously because if we waitd until it completes, there's a
211 // race condition where the alert can come up before we start watching for it.
212 shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html"));
214 base::string16
expected_title(ASCIIToUTF16("OK"));
215 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
216 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
218 WaitForAppModalDialog(shell());
220 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
223 // Test passing arguments to a plugin.
225 #if !defined(OS_LINUX)
226 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Arguments
)) {
227 LoadAndWait(GetURL("arguments.html"));
231 // Test invoking many plugins within a single page.
232 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ManyPlugins
)) {
233 LoadAndWait(GetURL("many_plugins.html"));
236 #if !defined(OS_MACOSX) // http://crbug.com/402164
237 // Test various calls to GetURL from a plugin.
238 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetURL
)) {
239 LoadAndWait(GetURL("geturl.html"));
243 // Test various calls to GetURL for javascript URLs with
244 // non NULL targets from a plugin.
245 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetJavaScriptURL
)) {
246 LoadAndWait(GetURL("get_javascript_url.html"));
249 // Test that calling GetURL with a javascript URL and target=_self
250 // works properly when the plugin is embedded in a subframe.
251 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetJavaScriptURL2
)) {
252 LoadAndWait(GetURL("get_javascript_url2.html"));
255 // Test is flaky on linux/cros/win builders. http://crbug.com/71904
256 IN_PROC_BROWSER_TEST_F(PluginTest
, GetURLRedirectNotification
) {
257 LoadAndWait(GetURL("geturl_redirect_notify.html"));
260 // Tests that identity is preserved for NPObjects passed from a plugin
262 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectIdentity
)) {
263 LoadAndWait(GetURL("npobject_identity.html"));
266 // Tests that if an NPObject is proxies back to its original process, the
267 // original pointer is returned and not a proxy. If this fails the plugin
269 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectProxy
)) {
270 LoadAndWait(GetURL("npobject_proxy.html"));
273 #if defined(OS_WIN) || defined(OS_MACOSX)
274 // Tests if a plugin executing a self deleting script in the context of
275 // a synchronous paint event works correctly
276 // http://crbug.com/44960
277 IN_PROC_BROWSER_TEST_F(
279 MAYBE_INPROC_WINDOWLESS(SelfDeletePluginInvokeInSynchronousPaint
)) {
280 LoadAndWait(GetURL("execute_script_delete_in_paint.html"));
284 // Tests that if a plugin executes a self resizing script in the context of a
285 // synchronous paint, the plugin doesn't use deallocated memory.
286 // http://crbug.com/139462
287 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_INPROC_WINDOWLESS(ResizeDuringPaint
)) {
288 LoadAndWait(GetURL("resize_during_paint.html"));
291 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInNewStream
)) {
292 LoadAndWait(GetURL("self_delete_plugin_stream.html"));
295 // On Mac this test asserts in plugin_host: http://crbug.com/95558
296 // On all platforms it flakes in ~URLRequestContext: http://crbug.com/310336
298 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_DeletePluginInDeallocate
) {
299 LoadAndWait(GetURL("plugin_delete_in_deallocate.html"));
305 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(VerifyPluginWindowRect
)) {
306 LoadAndWait(GetURL("verify_plugin_window_rect.html"));
309 // Tests that creating a new instance of a plugin while another one is handling
310 // a paint message doesn't cause deadlock.
311 // http://crbug.com/406184
312 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_CreateInstanceInPaint
) {
313 LoadAndWait(GetURL("create_instance_in_paint.html"));
316 // Tests that putting up an alert in response to a paint doesn't deadlock.
317 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_AlertInWindowMessage
) {
318 NavigateToURL(shell(), GetURL("alert_in_window_message.html"));
320 WaitForAppModalDialog(shell());
321 WaitForAppModalDialog(shell());
324 // http://crbug.com/406184
325 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_VerifyNPObjectLifetimeTest
) {
326 LoadAndWait(GetURL("npobject_lifetime_test.html"));
329 // Tests that we don't crash or assert if NPP_New fails
330 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NewFails
)) {
331 LoadAndWait(GetURL("new_fails.html"));
334 IN_PROC_BROWSER_TEST_F(PluginTest
,
335 MAYBE_INPROC_WINDOWLESS(SelfDeletePluginInNPNEvaluate
)) {
336 LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html"));
339 IN_PROC_BROWSER_TEST_F(
341 MAYBE_INPROC_WINDOWLESS(SelfDeleteCreatePluginInNPNEvaluate
)) {
342 LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html"));
347 // If this flakes, reopen http://crbug.com/17645
348 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out).
349 #if !defined(OS_MACOSX) && !defined(OS_LINUX)
350 // Disabled on Mac because the plugin side isn't implemented yet, see
351 // "TODO(port)" in plugin_javascript_open_popup.cc.
352 // Disabled on Linux because we don't support NPAPI any more.
353 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(OpenPopupWindowWithPlugin
)) {
354 LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html"));
358 // Test checking the privacy mode is off.
359 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PrivateDisabled
)) {
360 LoadAndWait(GetURL("private.html"));
363 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ScheduleTimer
)) {
364 LoadAndWait(GetURL("schedule_timer.html"));
367 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PluginThreadAsyncCall
)) {
368 LoadAndWait(GetURL("plugin_thread_async_call.html"));
371 IN_PROC_BROWSER_TEST_F(PluginTest
, PluginSingleRangeRequest
) {
372 LoadAndWait(GetURL("plugin_single_range_request.html"));
375 #if !defined(OS_WIN) // http://crbug.com/396373
376 // Test checking the privacy mode is on.
377 // If this flakes on Linux, use http://crbug.com/104380
378 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PrivateEnabled
)) {
379 GURL url
= GetURL("private.html");
380 url
= GURL(url
.spec() + "?private");
381 LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url
);
385 // These used to run on Windows: http://crbug.com/396373
386 #if defined(OS_MACOSX)
387 // Test a browser hang due to special case of multiple
388 // plugin instances indulged in sync calls across renderer.
389 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(MultipleInstancesSyncCalls
)) {
390 LoadAndWait(GetURL("multiple_instances_sync_calls.html"));
393 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetURLRequestFailWrite
)) {
394 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(
395 base::FilePath().AppendASCII("npapi").AppendASCII(
396 "plugin_url_request_fail_write.html")));
402 // Flaky on Windows x86. http://crbug.com/388245
403 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_EnsureScriptingWorksInDestroy
) {
404 LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html"));
407 // This test uses a Windows Event to signal to the plugin that it should crash
409 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NoHangIfInitCrashes
)) {
410 HANDLE crash_event
= CreateEvent(NULL
, TRUE
, FALSE
, L
"TestPluginCrashOnInit");
411 SetEvent(crash_event
);
412 LoadAndWait(GetURL("no_hang_if_init_crashes.html"));
413 CloseHandle(crash_event
);
417 // If this flakes on Mac, use http://crbug.com/111508
418 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PluginReferrerTest
)) {
419 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(
420 base::FilePath().AppendASCII("npapi").AppendASCII(
421 "plugin_url_request_referrer_test.html")));
425 #if defined(OS_MACOSX)
426 // Test is flaky, see http://crbug.com/134515.
427 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_PluginConvertPointTest
) {
428 gfx::Rect
bounds(50, 50, 400, 400);
429 SetWindowBounds(shell()->window(), bounds
);
431 NavigateToURL(shell(), GetURL("convert_point.html"));
433 base::string16
expected_title(ASCIIToUTF16("OK"));
434 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
435 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
436 // TODO(stuartmorgan): When the automation system supports sending clicks,
437 // change the test to trigger on mouse-down rather than window focus.
439 // TODO: is this code still needed? It was here when it used to run in
441 //static_cast<WebContentsDelegate*>(shell())->
442 // ActivateContents(shell()->web_contents());
443 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
447 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Flash
)) {
448 TestPlugin("flash.html");
453 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_FlashSecurity
) {
454 TestPlugin("flash.html");
456 #endif // defined(OS_WIN)
459 // TODO(port) Port the following tests to platforms that have the required
461 // Flaky: http://crbug.com/55915
462 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Quicktime
) {
463 TestPlugin("quicktime.html");
466 // Disabled - http://crbug.com/44662
467 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(MediaPlayerNew
)) {
468 TestPlugin("wmp_new.html");
471 // Disabled - http://crbug.com/44673
472 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Real
)) {
473 TestPlugin("real.html");
476 // http://crbug.com/320041
477 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
478 (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
479 #define MAYBE_FlashOctetStream DISABLED_FlashOctetStream
481 #define MAYBE_FlashOctetStream FlashOctetStream
483 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_FlashOctetStream
) {
484 TestPlugin("flash-octet-stream.html");
488 // http://crbug.com/53926
489 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_FlashLayoutWhilePainting
) {
491 IN_PROC_BROWSER_TEST_F(PluginTest
, FlashLayoutWhilePainting
) {
493 TestPlugin("flash-layout-while-painting.html");
496 // http://crbug.com/8690
497 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Java
) {
498 TestPlugin("Java.html");
501 // Flaky: http://crbug.com/55915
502 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Silverlight
) {
503 TestPlugin("silverlight.html");
505 #endif // defined(OS_WIN)
507 class TestResourceDispatcherHostDelegate
508 : public ResourceDispatcherHostDelegate
{
510 TestResourceDispatcherHostDelegate() : found_cookie_(false) {}
512 bool found_cookie() { return found_cookie_
; }
514 void WaitForPluginRequest() {
518 runner_
= new MessageLoopRunner
;
523 // ResourceDispatcherHostDelegate implementation:
524 void OnResponseStarted(net::URLRequest
* request
,
525 ResourceContext
* resource_context
,
526 ResourceResponse
* response
,
527 IPC::Sender
* sender
) override
{
528 // The URL below comes from plugin_geturl_test.cc.
529 if (!base::EndsWith(request
->url().spec(),
530 "npapi/plugin_ref_target_page.html",
534 net::HttpRequestHeaders headers
;
535 bool found_cookie
= false;
536 if (request
->GetFullRequestHeaders(&headers
) &&
537 headers
.ToString().find("Cookie: blah") != std::string::npos
) {
540 BrowserThread::PostTask(
543 base::Bind(&TestResourceDispatcherHostDelegate::GotCookie
,
544 base::Unretained(this), found_cookie
));
547 void GotCookie(bool found_cookie
) {
548 found_cookie_
= found_cookie
;
550 runner_
->QuitClosure().Run();
553 scoped_refptr
<MessageLoopRunner
> runner_
;
556 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate
);
559 // Ensure that cookies get sent with plugin requests.
560 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Cookies
)) {
561 // Create a new browser just to ensure that the plugin process' child_id is
562 // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which
564 NavigateToURL(CreateBrowser(), GURL("about:blank"));
566 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
567 GURL
url(embedded_test_server()->GetURL("/npapi/cookies.html"));
569 TestResourceDispatcherHostDelegate test_delegate
;
570 ResourceDispatcherHostDelegate
* old_delegate
=
571 ResourceDispatcherHostImpl::Get()->delegate();
572 ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate
);
574 test_delegate
.WaitForPluginRequest();
575 ASSERT_TRUE(test_delegate
.found_cookie());
576 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate
);
579 } // namespace content