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. 4 5 #include "base/command_line.h" 6 #include "base/file_util.h" 7 #include "base/path_service.h" 8 #include "base/strings/utf_string_conversions.h" 9 #include "content/public/browser/browser_thread.h" 10 #include "content/public/common/content_switches.h" 11 #include "content/public/test/browser_test_utils.h" 12 #include "content/shell/common/shell_switches.h" 13 #include "content/shell/shell.h" 14 #include "content/test/content_browser_test.h" 15 #include "content/test/content_browser_test_utils.h" 16 #include "content/test/net/url_request_mock_http_job.h" 17 #include "ui/gfx/rect.h" 18 19 #if defined(OS_WIN) 20 #include "base/win/registry.h" 21 #endif 22 23 // TODO(jschuh): Finish plugins on Win64. crbug.com/180861 24 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64) 25 #define MAYBE(x) DISABLED_##x 26 #else 27 #define MAYBE(x) x 28 #endif 29 30 namespace content { 31 namespace { 32 33 void SetUrlRequestMock(const base::FilePath& path) { 34 URLRequestMockHTTPJob::AddUrlHandler(path); 35 } 36 37 } 38 39 class PluginTest : public ContentBrowserTest { 40 protected: 41 PluginTest() {} 42 43 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 44 // Some NPAPI tests schedule garbage collection to force object tear-down. 45 command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose_gc"); 46 47 #if defined(OS_WIN) 48 const testing::TestInfo* const test_info = 49 testing::UnitTest::GetInstance()->current_test_info(); 50 if (strcmp(test_info->name(), "MediaPlayerNew") == 0) { 51 // The installer adds our process names to the registry key below. Since 52 // the installer might not have run on this machine, add it manually. 53 base::win::RegKey regkey; 54 if (regkey.Open(HKEY_LOCAL_MACHINE, 55 L"Software\\Microsoft\\MediaPlayer\\ShimInclusionList", 56 KEY_WRITE) == ERROR_SUCCESS) { 57 regkey.CreateKey(L"BROWSER_TESTS.EXE", KEY_READ); 58 } 59 } else if (strcmp(test_info->name(), "FlashSecurity") == 0) { 60 command_line->AppendSwitchASCII(switches::kTestSandbox, 61 "security_tests.dll"); 62 } 63 #elif defined(OS_MACOSX) 64 base::FilePath plugin_dir; 65 PathService::Get(base::DIR_MODULE, &plugin_dir); 66 plugin_dir = plugin_dir.AppendASCII("plugins"); 67 // The plugins directory isn't read by default on the Mac, so it needs to be 68 // explicitly registered. 69 command_line->AppendSwitchPath(switches::kExtraPluginDir, plugin_dir); 70 #endif 71 } 72 73 virtual void SetUpOnMainThread() OVERRIDE { 74 base::FilePath path = GetTestFilePath("", ""); 75 BrowserThread::PostTask( 76 BrowserThread::IO, FROM_HERE, base::Bind(&SetUrlRequestMock, path)); 77 } 78 79 static void LoadAndWaitInWindow(Shell* window, const GURL& url) { 80 string16 expected_title(ASCIIToUTF16("OK")); 81 TitleWatcher title_watcher(window->web_contents(), expected_title); 82 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 83 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("plugin_not_found")); 84 NavigateToURL(window, url); 85 string16 title = title_watcher.WaitAndGetTitle(); 86 if (title == ASCIIToUTF16("plugin_not_found")) { 87 const testing::TestInfo* const test_info = 88 testing::UnitTest::GetInstance()->current_test_info(); 89 LOG(INFO) << "PluginTest." << test_info->name() << 90 " not running because plugin not installed."; 91 } else { 92 EXPECT_EQ(expected_title, title); 93 } 94 } 95 96 void LoadAndWait(const GURL& url) { 97 LoadAndWaitInWindow(shell(), url); 98 } 99 100 GURL GetURL(const char* filename) { 101 return GetTestUrl("npapi", filename); 102 } 103 104 void NavigateAway() { 105 GURL url = GetTestUrl("", "simple_page.html"); 106 LoadAndWait(url); 107 } 108 109 void TestPlugin(const char* filename) { 110 base::FilePath path = GetTestFilePath("plugin", filename); 111 if (!base::PathExists(path)) { 112 const testing::TestInfo* const test_info = 113 testing::UnitTest::GetInstance()->current_test_info(); 114 LOG(INFO) << "PluginTest." << test_info->name() << 115 " not running because test data wasn't found."; 116 return; 117 } 118 119 GURL url = GetTestUrl("plugin", filename); 120 LoadAndWait(url); 121 } 122 }; 123 124 // Make sure that navigating away from a plugin referenced by JS doesn't 125 // crash. 126 IN_PROC_BROWSER_TEST_F(PluginTest, UnloadNoCrash) { 127 LoadAndWait(GetURL("layout_test_plugin.html")); 128 NavigateAway(); 129 } 130 131 // Tests if a plugin executing a self deleting script using NPN_GetURL 132 // works without crashing or hanging 133 // Flaky: http://crbug.com/59327 134 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginGetUrl)) { 135 LoadAndWait(GetURL("self_delete_plugin_geturl.html")); 136 } 137 138 // Tests if a plugin executing a self deleting script using Invoke 139 // works without crashing or hanging 140 // Flaky. See http://crbug.com/30702 141 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvoke)) { 142 LoadAndWait(GetURL("self_delete_plugin_invoke.html")); 143 } 144 145 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectReleasedOnDestruction)) { 146 NavigateToURL(shell(), GetURL("npobject_released_on_destruction.html")); 147 NavigateAway(); 148 } 149 150 // Test that a dialog is properly created when a plugin throws an 151 // exception. Should be run for in and out of process plugins, but 152 // the more interesting case is out of process, where we must route 153 // the exception to the correct renderer. 154 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectSetException)) { 155 LoadAndWait(GetURL("npobject_set_exception.html")); 156 } 157 158 #if defined(OS_WIN) 159 // Tests if a plugin executing a self deleting script in the context of 160 // a synchronous mouseup works correctly. 161 // This was never ported to Mac. The only thing remaining is to make 162 // SimulateMouseClick get to Mac plugins, currently it doesn't work. 163 IN_PROC_BROWSER_TEST_F(PluginTest, 164 MAYBE(SelfDeletePluginInvokeInSynchronousMouseUp)) { 165 NavigateToURL(shell(), GetURL("execute_script_delete_in_mouse_up.html")); 166 167 string16 expected_title(ASCIIToUTF16("OK")); 168 TitleWatcher title_watcher(shell()->web_contents(), expected_title); 169 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 170 SimulateMouseClick(shell()->web_contents(), 0, 171 WebKit::WebMouseEvent::ButtonLeft); 172 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); 173 } 174 #endif 175 176 // Flaky, http://crbug.com/60071. 177 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequest404Response)) { 178 GURL url(URLRequestMockHTTPJob::GetMockUrl( 179 base::FilePath().AppendASCII("npapi"). 180 AppendASCII("plugin_url_request_404.html"))); 181 LoadAndWait(url); 182 } 183 184 // Tests if a plugin executing a self deleting script using Invoke with 185 // a modal dialog showing works without crashing or hanging 186 // Disabled, flakily exceeds timeout, http://crbug.com/46257. 187 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInvokeAlert)) { 188 // Navigate asynchronously because if we waitd until it completes, there's a 189 // race condition where the alert can come up before we start watching for it. 190 shell()->LoadURL(GetURL("self_delete_plugin_invoke_alert.html")); 191 192 string16 expected_title(ASCIIToUTF16("OK")); 193 TitleWatcher title_watcher(shell()->web_contents(), expected_title); 194 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 195 196 WaitForAppModalDialog(shell()); 197 198 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); 199 } 200 201 // Test passing arguments to a plugin. 202 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Arguments)) { 203 LoadAndWait(GetURL("arguments.html")); 204 } 205 206 // Test invoking many plugins within a single page. 207 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ManyPlugins)) { 208 LoadAndWait(GetURL("many_plugins.html")); 209 } 210 211 // Test various calls to GetURL from a plugin. 212 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURL)) { 213 LoadAndWait(GetURL("geturl.html")); 214 } 215 216 // Test various calls to GetURL for javascript URLs with 217 // non NULL targets from a plugin. 218 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL)) { 219 LoadAndWait(GetURL("get_javascript_url.html")); 220 } 221 222 // Test that calling GetURL with a javascript URL and target=_self 223 // works properly when the plugin is embedded in a subframe. 224 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetJavaScriptURL2)) { 225 LoadAndWait(GetURL("get_javascript_url2.html")); 226 } 227 228 // Test is flaky on linux/cros/win builders. http://crbug.com/71904 229 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_GetURLRedirectNotification) { 230 LoadAndWait(GetURL("geturl_redirect_notify.html")); 231 } 232 233 // Tests that identity is preserved for NPObjects passed from a plugin 234 // into JavaScript. 235 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectIdentity)) { 236 LoadAndWait(GetURL("npobject_identity.html")); 237 } 238 239 // Tests that if an NPObject is proxies back to its original process, the 240 // original pointer is returned and not a proxy. If this fails the plugin 241 // will crash. 242 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NPObjectProxy)) { 243 LoadAndWait(GetURL("npobject_proxy.html")); 244 } 245 246 #if defined(OS_WIN) || defined(OS_MACOSX) 247 // Tests if a plugin executing a self deleting script in the context of 248 // a synchronous paint event works correctly 249 // http://crbug.com/44960 250 IN_PROC_BROWSER_TEST_F(PluginTest, 251 MAYBE(SelfDeletePluginInvokeInSynchronousPaint)) { 252 LoadAndWait(GetURL("execute_script_delete_in_paint.html")); 253 } 254 #endif 255 256 // Tests that if a plugin executes a self resizing script in the context of a 257 // synchronous paint, the plugin doesn't use deallocated memory. 258 // http://crbug.com/139462 259 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ResizeDuringPaint)) { 260 LoadAndWait(GetURL("resize_during_paint.html")); 261 } 262 263 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNewStream)) { 264 LoadAndWait(GetURL("self_delete_plugin_stream.html")); 265 } 266 267 // This test asserts on Mac in plugin_host in the NPNVWindowNPObject case. 268 #if !(defined(OS_MACOSX) && !defined(NDEBUG)) 269 // If this test flakes use http://crbug.com/95558. 270 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(DeletePluginInDeallocate)) { 271 LoadAndWait(GetURL("plugin_delete_in_deallocate.html")); 272 } 273 #endif 274 275 #if defined(OS_WIN) 276 277 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyPluginWindowRect)) { 278 LoadAndWait(GetURL("verify_plugin_window_rect.html")); 279 } 280 281 // Tests that creating a new instance of a plugin while another one is handling 282 // a paint message doesn't cause deadlock. 283 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(CreateInstanceInPaint)) { 284 LoadAndWait(GetURL("create_instance_in_paint.html")); 285 } 286 287 // Tests that putting up an alert in response to a paint doesn't deadlock. 288 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_AlertInWindowMessage) { 289 NavigateToURL(shell(), GetURL("alert_in_window_message.html")); 290 291 WaitForAppModalDialog(shell()); 292 WaitForAppModalDialog(shell()); 293 } 294 295 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyNPObjectLifetimeTest)) { 296 LoadAndWait(GetURL("npobject_lifetime_test.html")); 297 } 298 299 // Tests that we don't crash or assert if NPP_New fails 300 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NewFails)) { 301 LoadAndWait(GetURL("new_fails.html")); 302 } 303 304 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(SelfDeletePluginInNPNEvaluate)) { 305 LoadAndWait(GetURL("execute_script_delete_in_npn_evaluate.html")); 306 } 307 308 IN_PROC_BROWSER_TEST_F(PluginTest, 309 MAYBE(SelfDeleteCreatePluginInNPNEvaluate)) { 310 LoadAndWait(GetURL("npn_plugin_delete_create_in_evaluate.html")); 311 } 312 313 #endif // OS_WIN 314 315 // If this flakes, reopen http://crbug.com/17645 316 // As of 6 July 2011, this test is flaky on Windows (perhaps due to timing out). 317 #if !defined(OS_MACOSX) 318 // Disabled on Mac because the plugin side isn't implemented yet, see 319 // "TODO(port)" in plugin_javascript_open_popup.cc. 320 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(OpenPopupWindowWithPlugin)) { 321 LoadAndWait(GetURL("get_javascript_open_popup_with_plugin.html")); 322 } 323 #endif 324 325 // Test checking the privacy mode is off. 326 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateDisabled)) { 327 LoadAndWait(GetURL("private.html")); 328 } 329 330 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ScheduleTimer)) { 331 LoadAndWait(GetURL("schedule_timer.html")); 332 } 333 334 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginThreadAsyncCall)) { 335 LoadAndWait(GetURL("plugin_thread_async_call.html")); 336 } 337 338 IN_PROC_BROWSER_TEST_F(PluginTest, PluginSingleRangeRequest) { 339 LoadAndWait(GetURL("plugin_single_range_request.html")); 340 } 341 342 // Test checking the privacy mode is on. 343 // If this flakes on Linux, use http://crbug.com/104380 344 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateEnabled)) { 345 GURL url = GetURL("private.html"); 346 url = GURL(url.spec() + "?private"); 347 LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url); 348 } 349 350 #if defined(OS_WIN) || defined(OS_MACOSX) 351 // Test a browser hang due to special case of multiple 352 // plugin instances indulged in sync calls across renderer. 353 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MultipleInstancesSyncCalls)) { 354 LoadAndWait(GetURL("multiple_instances_sync_calls.html")); 355 } 356 #endif 357 358 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequestFailWrite)) { 359 GURL url(URLRequestMockHTTPJob::GetMockUrl( 360 base::FilePath().AppendASCII("npapi"). 361 AppendASCII("plugin_url_request_fail_write.html"))); 362 LoadAndWait(url); 363 } 364 365 #if defined(OS_WIN) 366 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(EnsureScriptingWorksInDestroy)) { 367 LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html")); 368 } 369 370 // This test uses a Windows Event to signal to the plugin that it should crash 371 // on NP_Initialize. 372 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NoHangIfInitCrashes)) { 373 HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit"); 374 SetEvent(crash_event); 375 LoadAndWait(GetURL("no_hang_if_init_crashes.html")); 376 CloseHandle(crash_event); 377 } 378 #endif 379 380 // If this flakes on Mac, use http://crbug.com/111508 381 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginReferrerTest)) { 382 GURL url(URLRequestMockHTTPJob::GetMockUrl( 383 base::FilePath().AppendASCII("npapi"). 384 AppendASCII("plugin_url_request_referrer_test.html"))); 385 LoadAndWait(url); 386 } 387 388 #if defined(OS_MACOSX) 389 // Test is flaky, see http://crbug.com/134515. 390 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_PluginConvertPointTest) { 391 gfx::Rect bounds(50, 50, 400, 400); 392 SetWindowBounds(shell()->window(), bounds); 393 394 NavigateToURL(shell(), GetURL("convert_point.html")); 395 396 string16 expected_title(ASCIIToUTF16("OK")); 397 TitleWatcher title_watcher(shell()->web_contents(), expected_title); 398 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("FAIL")); 399 // TODO(stuartmorgan): When the automation system supports sending clicks, 400 // change the test to trigger on mouse-down rather than window focus. 401 402 // TODO: is this code still needed? It was here when it used to run in 403 // browser_tests. 404 //static_cast<WebContentsDelegate*>(shell())-> 405 // ActivateContents(shell()->web_contents()); 406 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); 407 } 408 #endif 409 410 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Flash)) { 411 TestPlugin("flash.html"); 412 } 413 414 #if defined(OS_WIN) 415 // Windows only test 416 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashSecurity) { 417 TestPlugin("flash.html"); 418 } 419 #endif // defined(OS_WIN) 420 421 #if defined(OS_WIN) 422 // TODO(port) Port the following tests to platforms that have the required 423 // plugins. 424 // Flaky: http://crbug.com/55915 425 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Quicktime)) { 426 TestPlugin("quicktime.html"); 427 } 428 429 // Disabled - http://crbug.com/44662 430 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MediaPlayerNew)) { 431 TestPlugin("wmp_new.html"); 432 } 433 434 // Disabled - http://crbug.com/44673 435 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Real)) { 436 TestPlugin("real.html"); 437 } 438 439 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(FlashOctetStream)) { 440 TestPlugin("flash-octet-stream.html"); 441 } 442 443 #if defined(OS_WIN) 444 // http://crbug.com/53926 445 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashLayoutWhilePainting) { 446 #else 447 IN_PROC_BROWSER_TEST_F(PluginTest, FlashLayoutWhilePainting) { 448 #endif 449 TestPlugin("flash-layout-while-painting.html"); 450 } 451 452 // http://crbug.com/8690 453 IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Java) { 454 TestPlugin("Java.html"); 455 } 456 457 IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Silverlight)) { 458 TestPlugin("silverlight.html"); 459 } 460 #endif // defined(OS_WIN) 461 462 } // namespace content 463