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
);
68 #elif defined(OS_MACOSX)
69 base::FilePath plugin_dir
;
70 PathService::Get(base::DIR_MODULE
, &plugin_dir
);
71 plugin_dir
= plugin_dir
.AppendASCII("plugins");
72 // The plugins directory isn't read by default on the Mac, so it needs to be
73 // explicitly registered.
74 command_line
->AppendSwitchPath(switches::kExtraPluginDir
, plugin_dir
);
78 virtual void SetUpOnMainThread() OVERRIDE
{
79 base::FilePath path
= GetTestFilePath("", "");
80 BrowserThread::PostTask(
81 BrowserThread::IO
, FROM_HERE
, base::Bind(&SetUrlRequestMock
, path
));
84 static void LoadAndWaitInWindow(Shell
* window
, const GURL
& url
) {
85 base::string16
expected_title(ASCIIToUTF16("OK"));
86 TitleWatcher
title_watcher(window
->web_contents(), expected_title
);
87 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
88 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found"));
89 NavigateToURL(window
, url
);
90 base::string16 title
= title_watcher
.WaitAndGetTitle();
91 if (title
== ASCIIToUTF16("plugin_not_found")) {
92 const testing::TestInfo
* const test_info
=
93 testing::UnitTest::GetInstance()->current_test_info();
94 VLOG(0) << "PluginTest." << test_info
->name()
95 << " not running because plugin not installed.";
97 EXPECT_EQ(expected_title
, title
);
101 void LoadAndWait(const GURL
& url
) {
102 LoadAndWaitInWindow(shell(), url
);
105 GURL
GetURL(const char* filename
) {
106 return GetTestUrl("npapi", filename
);
109 void NavigateAway() {
110 GURL url
= GetTestUrl("", "simple_page.html");
114 void TestPlugin(const char* filename
) {
115 base::FilePath path
= GetTestFilePath("plugin", filename
);
116 if (!base::PathExists(path
)) {
117 const testing::TestInfo
* const test_info
=
118 testing::UnitTest::GetInstance()->current_test_info();
119 VLOG(0) << "PluginTest." << test_info
->name()
120 << " not running because test data wasn't found.";
124 GURL url
= GetTestUrl("plugin", filename
);
129 // Make sure that navigating away from a plugin referenced by JS doesn't
131 IN_PROC_BROWSER_TEST_F(PluginTest
, UnloadNoCrash
) {
132 LoadAndWait(GetURL("layout_test_plugin.html"));
136 // Tests if a plugin executing a self deleting script using NPN_GetURL
137 // works without crashing or hanging
138 // Flaky: http://crbug.com/59327
139 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginGetUrl
)) {
140 LoadAndWait(GetURL("self_delete_plugin_geturl.html"));
143 // Tests if a plugin executing a self deleting script using Invoke
144 // works without crashing or hanging
145 // Flaky. See http://crbug.com/30702
146 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInvoke
)) {
147 LoadAndWait(GetURL("self_delete_plugin_invoke.html"));
150 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectReleasedOnDestruction
)) {
151 NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html"));
155 // Test that a dialog is properly created when a plugin throws an
156 // exception. Should be run for in and out of process plugins, but
157 // the more interesting case is out of process, where we must route
158 // the exception to the correct renderer.
159 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectSetException
)) {
160 LoadAndWait(GetURL("npobject_set_exception.html"));
164 // Tests if a plugin executing a self deleting script in the context of
165 // a synchronous mouseup works correctly.
166 // This was never ported to Mac. The only thing remaining is to make
167 // SimulateMouseClick get to Mac plugins, currently it doesn't work.
168 IN_PROC_BROWSER_TEST_F(PluginTest
,
169 MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp
)) {
170 NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html"));
172 base::string16
expected_title(ASCIIToUTF16("OK"));
173 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
174 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
175 SimulateMouseClick(shell()->web_contents(), 0,
176 blink::WebMouseEvent::ButtonLeft
);
177 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
181 // Flaky, http://crbug.com/302274.
182 #if defined(OS_MACOSX)
183 #define MAYBE_GetURLRequest404Response DISABLED_GetURLRequest404Response
185 #define MAYBE_GetURLRequest404Response MAYBE(GetURLRequest404Response)
188 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_GetURLRequest404Response
) {
189 GURL
url(URLRequestMockHTTPJob::GetMockUrl(
190 base::FilePath().AppendASCII("npapi").
191 AppendASCII("plugin_url_request_404.html")));
195 // Tests if a plugin executing a self deleting script using Invoke with
196 // a modal dialog showing works without crashing or hanging
197 // Disabled, flakily exceeds timeout, http://crbug.com/46257.
198 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInvokeAlert
)) {
199 // Navigate asynchronously because if we waitd until it completes, there's a
200 // race condition where the alert can come up before we start watching for it.
201 shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html"));
203 base::string16
expected_title(ASCIIToUTF16("OK"));
204 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
205 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
207 WaitForAppModalDialog(shell());
209 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
212 // Test passing arguments to a plugin.
214 #if !defined(OS_LINUX)
215 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Arguments
)) {
216 LoadAndWait(GetURL("arguments.html"));
220 // Test invoking many plugins within a single page.
221 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ManyPlugins
)) {
222 LoadAndWait(GetURL("many_plugins.html"));
225 #if !defined(OS_MACOSX) // http://crbug.com/402164
226 // Test various calls to GetURL from a plugin.
227 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetURL
)) {
228 LoadAndWait(GetURL("geturl.html"));
232 // Test various calls to GetURL for javascript URLs with
233 // non NULL targets from a plugin.
234 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetJavaScriptURL
)) {
235 LoadAndWait(GetURL("get_javascript_url.html"));
238 // Test that calling GetURL with a javascript URL and target=_self
239 // works properly when the plugin is embedded in a subframe.
240 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetJavaScriptURL2
)) {
241 LoadAndWait(GetURL("get_javascript_url2.html"));
244 // Test is flaky on linux/cros/win builders. http://crbug.com/71904
245 IN_PROC_BROWSER_TEST_F(PluginTest
, GetURLRedirectNotification
) {
246 LoadAndWait(GetURL("geturl_redirect_notify.html"));
249 // Tests that identity is preserved for NPObjects passed from a plugin
251 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectIdentity
)) {
252 LoadAndWait(GetURL("npobject_identity.html"));
255 // Tests that if an NPObject is proxies back to its original process, the
256 // original pointer is returned and not a proxy. If this fails the plugin
258 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NPObjectProxy
)) {
259 LoadAndWait(GetURL("npobject_proxy.html"));
262 #if defined(OS_WIN) || defined(OS_MACOSX)
263 // Tests if a plugin executing a self deleting script in the context of
264 // a synchronous paint event works correctly
265 // http://crbug.com/44960
266 IN_PROC_BROWSER_TEST_F(PluginTest
,
267 MAYBE(SelfDeletePluginInvokeInSynchronousPaint
)) {
268 LoadAndWait(GetURL("execute_script_delete_in_paint.html"));
272 // Tests that if a plugin executes a self resizing script in the context of a
273 // synchronous paint, the plugin doesn't use deallocated memory.
274 // http://crbug.com/139462
275 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ResizeDuringPaint
)) {
276 LoadAndWait(GetURL("resize_during_paint.html"));
279 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInNewStream
)) {
280 LoadAndWait(GetURL("self_delete_plugin_stream.html"));
283 // On Mac this test asserts in plugin_host: http://crbug.com/95558
284 // On all platforms it flakes in ~URLRequestContext: http://crbug.com/310336
286 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_DeletePluginInDeallocate
) {
287 LoadAndWait(GetURL("plugin_delete_in_deallocate.html"));
293 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(VerifyPluginWindowRect
)) {
294 LoadAndWait(GetURL("verify_plugin_window_rect.html"));
297 // Tests that creating a new instance of a plugin while another one is handling
298 // a paint message doesn't cause deadlock.
299 // http://crbug.com/406184
300 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_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 // http://crbug.com/406184
313 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_VerifyNPObjectLifetimeTest
) {
314 LoadAndWait(GetURL("npobject_lifetime_test.html"));
317 // Tests that we don't crash or assert if NPP_New fails
318 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NewFails
)) {
319 LoadAndWait(GetURL("new_fails.html"));
322 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(SelfDeletePluginInNPNEvaluate
)) {
323 LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html"));
326 IN_PROC_BROWSER_TEST_F(PluginTest
,
327 MAYBE(SelfDeleteCreatePluginInNPNEvaluate
)) {
328 LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html"));
333 // If this flakes, reopen http://crbug.com/17645
334 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out).
335 #if !defined(OS_MACOSX) && !defined(OS_LINUX)
336 // Disabled on Mac because the plugin side isn't implemented yet, see
337 // "TODO(port)" in plugin_javascript_open_popup.cc.
338 // Disabled on Linux because we don't support NPAPI any more.
339 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(OpenPopupWindowWithPlugin
)) {
340 LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html"));
344 // Test checking the privacy mode is off.
345 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PrivateDisabled
)) {
346 LoadAndWait(GetURL("private.html"));
349 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(ScheduleTimer
)) {
350 LoadAndWait(GetURL("schedule_timer.html"));
353 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PluginThreadAsyncCall
)) {
354 LoadAndWait(GetURL("plugin_thread_async_call.html"));
357 IN_PROC_BROWSER_TEST_F(PluginTest
, PluginSingleRangeRequest
) {
358 LoadAndWait(GetURL("plugin_single_range_request.html"));
361 #if !defined(OS_WIN) // http://crbug.com/396373
362 // Test checking the privacy mode is on.
363 // If this flakes on Linux, use http://crbug.com/104380
364 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PrivateEnabled
)) {
365 GURL url
= GetURL("private.html");
366 url
= GURL(url
.spec() + "?private");
367 LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url
);
371 // These used to run on Windows: http://crbug.com/396373
372 #if defined(OS_MACOSX)
373 // Test a browser hang due to special case of multiple
374 // plugin instances indulged in sync calls across renderer.
375 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(MultipleInstancesSyncCalls
)) {
376 LoadAndWait(GetURL("multiple_instances_sync_calls.html"));
379 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(GetURLRequestFailWrite
)) {
380 GURL
url(URLRequestMockHTTPJob::GetMockUrl(
381 base::FilePath().AppendASCII("npapi").
382 AppendASCII("plugin_url_request_fail_write.html")));
388 // Flaky on Windows x86. http://crbug.com/388245
389 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_EnsureScriptingWorksInDestroy
) {
390 LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html"));
393 // This test uses a Windows Event to signal to the plugin that it should crash
395 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(NoHangIfInitCrashes
)) {
396 HANDLE crash_event
= CreateEvent(NULL
, TRUE
, FALSE
, L
"TestPluginCrashOnInit");
397 SetEvent(crash_event
);
398 LoadAndWait(GetURL("no_hang_if_init_crashes.html"));
399 CloseHandle(crash_event
);
403 // If this flakes on Mac, use http://crbug.com/111508
404 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(PluginReferrerTest
)) {
405 GURL
url(URLRequestMockHTTPJob::GetMockUrl(
406 base::FilePath().AppendASCII("npapi").
407 AppendASCII("plugin_url_request_referrer_test.html")));
411 #if defined(OS_MACOSX)
412 // Test is flaky, see http://crbug.com/134515.
413 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_PluginConvertPointTest
) {
414 gfx::Rect
bounds(50, 50, 400, 400);
415 SetWindowBounds(shell()->window(), bounds
);
417 NavigateToURL(shell(), GetURL("convert_point.html"));
419 base::string16
expected_title(ASCIIToUTF16("OK"));
420 TitleWatcher
title_watcher(shell()->web_contents(), expected_title
);
421 title_watcher
.AlsoWaitForTitle(ASCIIToUTF16("FAIL"));
422 // TODO(stuartmorgan): When the automation system supports sending clicks,
423 // change the test to trigger on mouse-down rather than window focus.
425 // TODO: is this code still needed? It was here when it used to run in
427 //static_cast<WebContentsDelegate*>(shell())->
428 // ActivateContents(shell()->web_contents());
429 EXPECT_EQ(expected_title
, title_watcher
.WaitAndGetTitle());
433 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Flash
)) {
434 TestPlugin("flash.html");
439 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_FlashSecurity
) {
440 TestPlugin("flash.html");
442 #endif // defined(OS_WIN)
445 // TODO(port) Port the following tests to platforms that have the required
447 // Flaky: http://crbug.com/55915
448 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Quicktime
) {
449 TestPlugin("quicktime.html");
452 // Disabled - http://crbug.com/44662
453 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(MediaPlayerNew
)) {
454 TestPlugin("wmp_new.html");
457 // Disabled - http://crbug.com/44673
458 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Real
)) {
459 TestPlugin("real.html");
462 // http://crbug.com/320041
463 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
464 (defined(GOOGLE_CHROME_BUILD) && defined(OS_WIN))
465 #define MAYBE_FlashOctetStream DISABLED_FlashOctetStream
467 #define MAYBE_FlashOctetStream FlashOctetStream
469 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE_FlashOctetStream
) {
470 TestPlugin("flash-octet-stream.html");
474 // http://crbug.com/53926
475 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_FlashLayoutWhilePainting
) {
477 IN_PROC_BROWSER_TEST_F(PluginTest
, FlashLayoutWhilePainting
) {
479 TestPlugin("flash-layout-while-painting.html");
482 // http://crbug.com/8690
483 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Java
) {
484 TestPlugin("Java.html");
487 // Flaky: http://crbug.com/55915
488 IN_PROC_BROWSER_TEST_F(PluginTest
, DISABLED_Silverlight
) {
489 TestPlugin("silverlight.html");
491 #endif // defined(OS_WIN)
493 class TestResourceDispatcherHostDelegate
494 : public ResourceDispatcherHostDelegate
{
496 TestResourceDispatcherHostDelegate() : found_cookie_(false) {}
498 bool found_cookie() { return found_cookie_
; }
500 void WaitForPluginRequest() {
504 runner_
= new MessageLoopRunner
;
509 // ResourceDispatcherHostDelegate implementation:
510 virtual void OnResponseStarted(
511 net::URLRequest
* request
,
512 ResourceContext
* resource_context
,
513 ResourceResponse
* response
,
514 IPC::Sender
* sender
) OVERRIDE
{
515 // The URL below comes from plugin_geturl_test.cc.
516 if (!EndsWith(request
->url().spec(),
517 "npapi/plugin_ref_target_page.html",
521 net::HttpRequestHeaders headers
;
522 bool found_cookie
= false;
523 if (request
->GetFullRequestHeaders(&headers
) &&
524 headers
.ToString().find("Cookie: blah") != std::string::npos
) {
527 BrowserThread::PostTask(
530 base::Bind(&TestResourceDispatcherHostDelegate::GotCookie
,
531 base::Unretained(this), found_cookie
));
534 void GotCookie(bool found_cookie
) {
535 found_cookie_
= found_cookie
;
537 runner_
->QuitClosure().Run();
540 scoped_refptr
<MessageLoopRunner
> runner_
;
543 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate
);
546 // Ensure that cookies get sent with plugin requests.
547 IN_PROC_BROWSER_TEST_F(PluginTest
, MAYBE(Cookies
)) {
548 // Create a new browser just to ensure that the plugin process' child_id is
549 // not equal to its type (PROCESS_TYPE_PLUGIN), as that was the error which
551 NavigateToURL(CreateBrowser(), GURL("about:blank"));
553 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
554 GURL
url(embedded_test_server()->GetURL("/npapi/cookies.html"));
556 TestResourceDispatcherHostDelegate test_delegate
;
557 ResourceDispatcherHostDelegate
* old_delegate
=
558 ResourceDispatcherHostImpl::Get()->delegate();
559 ResourceDispatcherHostImpl::Get()->SetDelegate(&test_delegate
);
561 test_delegate
.WaitForPluginRequest();
562 ASSERT_TRUE(test_delegate
.found_cookie());
563 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate
);
566 } // namespace content