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 "chrome/test/ppapi/ppapi_test.h" 6 7 #include "base/command_line.h" 8 #include "base/file_util.h" 9 #include "base/logging.h" 10 #include "base/path_service.h" 11 #include "base/strings/string_util.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/test/test_timeouts.h" 14 #include "build/build_config.h" 15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/content_settings/host_content_settings_map.h" 17 #include "chrome/browser/infobars/confirm_infobar_delegate.h" 18 #include "chrome/browser/infobars/infobar.h" 19 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/ui/browser.h" 21 #include "chrome/browser/ui/browser_tabstrip.h" 22 #include "chrome/browser/ui/tabs/tab_strip_model.h" 23 #include "chrome/common/chrome_paths.h" 24 #include "chrome/common/chrome_switches.h" 25 #include "chrome/test/base/ui_test_utils.h" 26 #include "content/public/browser/dom_operation_notification_details.h" 27 #include "content/public/browser/notification_service.h" 28 #include "content/public/browser/notification_types.h" 29 #include "content/public/browser/web_contents.h" 30 #include "content/public/common/content_paths.h" 31 #include "content/public/common/content_switches.h" 32 #include "content/public/test/browser_test_utils.h" 33 #include "content/public/test/test_renderer_host.h" 34 #include "net/base/net_util.h" 35 #include "net/base/test_data_directory.h" 36 #include "ppapi/shared_impl/ppapi_switches.h" 37 #include "ui/gl/gl_switches.h" 38 39 #if defined(OS_WIN) && defined(USE_ASH) 40 #include "base/win/windows_version.h" 41 #endif 42 43 using content::DomOperationNotificationDetails; 44 using content::RenderViewHost; 45 46 namespace { 47 48 // Platform-specific filename relative to the chrome executable. 49 #if defined(OS_WIN) 50 const wchar_t library_name[] = L"ppapi_tests.dll"; 51 #elif defined(OS_MACOSX) 52 const char library_name[] = "ppapi_tests.plugin"; 53 #elif defined(OS_POSIX) 54 const char library_name[] = "libppapi_tests.so"; 55 #endif 56 57 } // namespace 58 59 PPAPITestMessageHandler::PPAPITestMessageHandler() { 60 } 61 62 TestMessageHandler::MessageResponse PPAPITestMessageHandler::HandleMessage( 63 const std::string& json) { 64 std::string trimmed; 65 TrimString(json, "\"", &trimmed); 66 if (trimmed == "...") { 67 return CONTINUE; 68 } else { 69 message_ = trimmed; 70 return DONE; 71 } 72 } 73 74 void PPAPITestMessageHandler::Reset() { 75 TestMessageHandler::Reset(); 76 message_.clear(); 77 } 78 79 PPAPITestBase::InfoBarObserver::InfoBarObserver() { 80 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, 81 content::NotificationService::AllSources()); 82 } 83 84 PPAPITestBase::InfoBarObserver::~InfoBarObserver() { 85 EXPECT_EQ(0u, expected_infobars_.size()) << "Missing an expected infobar"; 86 } 87 88 void PPAPITestBase::InfoBarObserver::Observe( 89 int type, 90 const content::NotificationSource& source, 91 const content::NotificationDetails& details) { 92 ASSERT_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, type); 93 InfoBarDelegate* infobar = 94 content::Details<InfoBarAddedDetails>(details).ptr(); 95 ConfirmInfoBarDelegate* confirm_infobar_delegate = 96 infobar->AsConfirmInfoBarDelegate(); 97 ASSERT_TRUE(confirm_infobar_delegate); 98 99 ASSERT_FALSE(expected_infobars_.empty()) << "Unexpected infobar"; 100 if (expected_infobars_.front()) 101 confirm_infobar_delegate->Accept(); 102 else 103 confirm_infobar_delegate->Cancel(); 104 expected_infobars_.pop_front(); 105 106 // TODO(bauerb): We should close the infobar. 107 } 108 109 void PPAPITestBase::InfoBarObserver::ExpectInfoBarAndAccept( 110 bool should_accept) { 111 expected_infobars_.push_back(should_accept); 112 } 113 114 PPAPITestBase::PPAPITestBase() { 115 } 116 117 void PPAPITestBase::SetUpCommandLine(CommandLine* command_line) { 118 // The test sends us the result via a cookie. 119 command_line->AppendSwitch(switches::kEnableFileCookies); 120 121 // Some stuff is hung off of the testing interface which is not enabled 122 // by default. 123 command_line->AppendSwitch(switches::kEnablePepperTesting); 124 125 // Smooth scrolling confuses the scrollbar test. 126 command_line->AppendSwitch(switches::kDisableSmoothScrolling); 127 128 // For TestRequestOSFileHandle. 129 command_line->AppendSwitch(switches::kUnlimitedStorage); 130 command_line->AppendSwitchASCII(switches::kAllowNaClFileHandleAPI, 131 "127.0.0.1"); 132 } 133 134 void PPAPITestBase::SetUpOnMainThread() { 135 // Always allow access to the PPAPI broker. 136 browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting( 137 CONTENT_SETTINGS_TYPE_PPAPI_BROKER, CONTENT_SETTING_ALLOW); 138 } 139 140 GURL PPAPITestBase::GetTestFileUrl(const std::string& test_case) { 141 base::FilePath test_path; 142 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_path)); 143 test_path = test_path.Append(FILE_PATH_LITERAL("ppapi")); 144 test_path = test_path.Append(FILE_PATH_LITERAL("tests")); 145 test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html")); 146 147 // Sanity check the file name. 148 EXPECT_TRUE(base::PathExists(test_path)); 149 150 GURL test_url = net::FilePathToFileURL(test_path); 151 152 GURL::Replacements replacements; 153 std::string query = BuildQuery(std::string(), test_case); 154 replacements.SetQuery(query.c_str(), url_parse::Component(0, query.size())); 155 return test_url.ReplaceComponents(replacements); 156 } 157 158 void PPAPITestBase::RunTest(const std::string& test_case) { 159 GURL url = GetTestFileUrl(test_case); 160 RunTestURL(url); 161 } 162 163 void PPAPITestBase::RunTestAndReload(const std::string& test_case) { 164 GURL url = GetTestFileUrl(test_case); 165 RunTestURL(url); 166 // If that passed, we simply run the test again, which navigates again. 167 RunTestURL(url); 168 } 169 170 void PPAPITestBase::RunTestViaHTTP(const std::string& test_case) { 171 base::FilePath document_root; 172 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root)); 173 base::FilePath http_document_root; 174 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root)); 175 net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP, 176 net::SpawnedTestServer::kLocalhost, 177 document_root); 178 ASSERT_TRUE(http_server.Start()); 179 RunTestURL(GetTestURL(http_server, test_case, std::string())); 180 } 181 182 void PPAPITestBase::RunTestWithSSLServer(const std::string& test_case) { 183 base::FilePath http_document_root; 184 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root)); 185 net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP, 186 net::SpawnedTestServer::kLocalhost, 187 http_document_root); 188 net::SpawnedTestServer ssl_server(net::SpawnedTestServer::TYPE_HTTPS, 189 net::BaseTestServer::SSLOptions(), 190 http_document_root); 191 // Start the servers in parallel. 192 ASSERT_TRUE(http_server.StartInBackground()); 193 ASSERT_TRUE(ssl_server.StartInBackground()); 194 // Wait until they are both finished before continuing. 195 ASSERT_TRUE(http_server.BlockUntilStarted()); 196 ASSERT_TRUE(ssl_server.BlockUntilStarted()); 197 198 uint16_t port = ssl_server.host_port_pair().port(); 199 RunTestURL(GetTestURL(http_server, 200 test_case, 201 base::StringPrintf("ssl_server_port=%d", port))); 202 } 203 204 void PPAPITestBase::RunTestWithWebSocketServer(const std::string& test_case) { 205 base::FilePath http_document_root; 206 ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root)); 207 net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP, 208 net::SpawnedTestServer::kLocalhost, 209 http_document_root); 210 net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS, 211 net::SpawnedTestServer::kLocalhost, 212 net::GetWebSocketTestDataDirectory()); 213 // Start the servers in parallel. 214 ASSERT_TRUE(http_server.StartInBackground()); 215 ASSERT_TRUE(ws_server.StartInBackground()); 216 // Wait until they are both finished before continuing. 217 ASSERT_TRUE(http_server.BlockUntilStarted()); 218 ASSERT_TRUE(ws_server.BlockUntilStarted()); 219 220 std::string host = ws_server.host_port_pair().HostForURL(); 221 uint16_t port = ws_server.host_port_pair().port(); 222 RunTestURL(GetTestURL(http_server, 223 test_case, 224 base::StringPrintf( 225 "websocket_host=%s&websocket_port=%d", 226 host.c_str(), 227 port))); 228 } 229 230 void PPAPITestBase::RunTestIfAudioOutputAvailable( 231 const std::string& test_case) { 232 RunTest(test_case); 233 } 234 235 void PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable( 236 const std::string& test_case) { 237 RunTestViaHTTP(test_case); 238 } 239 240 std::string PPAPITestBase::StripPrefixes(const std::string& test_name) { 241 const char* const prefixes[] = { 242 "FAILS_", "FLAKY_", "DISABLED_", "SLOW_" }; 243 for (size_t i = 0; i < sizeof(prefixes)/sizeof(prefixes[0]); ++i) 244 if (test_name.find(prefixes[i]) == 0) 245 return test_name.substr(strlen(prefixes[i])); 246 return test_name; 247 } 248 249 void PPAPITestBase::RunTestURL(const GURL& test_url) { 250 #if defined(OS_WIN) && defined(USE_ASH) 251 // PPAPITests are broken in Ash browser tests (http://crbug.com/263548). 252 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 253 LOG(WARNING) << "PPAPITests are disabled for Ash browser tests."; 254 return; 255 } 256 #endif 257 258 // See comment above TestingInstance in ppapi/test/testing_instance.h. 259 // Basically it sends messages using the DOM automation controller. The 260 // value of "..." means it's still working and we should continue to wait, 261 // any other value indicates completion (in this case it will start with 262 // "PASS" or "FAIL"). This keeps us from timing out on waits for long tests. 263 PPAPITestMessageHandler handler; 264 JavascriptTestObserver observer( 265 browser()->tab_strip_model()->GetActiveWebContents()->GetRenderViewHost(), 266 &handler); 267 268 ui_test_utils::NavigateToURL(browser(), test_url); 269 270 ASSERT_TRUE(observer.Run()) << handler.error_message(); 271 EXPECT_STREQ("PASS", handler.message().c_str()); 272 } 273 274 GURL PPAPITestBase::GetTestURL( 275 const net::SpawnedTestServer& http_server, 276 const std::string& test_case, 277 const std::string& extra_params) { 278 std::string query = BuildQuery("files/test_case.html?", test_case); 279 if (!extra_params.empty()) 280 query = base::StringPrintf("%s&%s", query.c_str(), extra_params.c_str()); 281 282 return http_server.GetURL(query); 283 } 284 285 PPAPITest::PPAPITest() : in_process_(true) { 286 } 287 288 void PPAPITest::SetUpCommandLine(CommandLine* command_line) { 289 PPAPITestBase::SetUpCommandLine(command_line); 290 291 // Append the switch to register the pepper plugin. 292 // library name = <out dir>/<test_name>.<library_extension> 293 // MIME type = application/x-ppapi-<test_name> 294 base::FilePath plugin_dir; 295 EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir)); 296 297 base::FilePath plugin_lib = plugin_dir.Append(library_name); 298 EXPECT_TRUE(base::PathExists(plugin_lib)); 299 base::FilePath::StringType pepper_plugin = plugin_lib.value(); 300 pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests")); 301 command_line->AppendSwitchNative(switches::kRegisterPepperPlugins, 302 pepper_plugin); 303 command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1"); 304 305 if (in_process_) 306 command_line->AppendSwitch(switches::kPpapiInProcess); 307 } 308 309 std::string PPAPITest::BuildQuery(const std::string& base, 310 const std::string& test_case){ 311 return base::StringPrintf("%stestcase=%s", base.c_str(), test_case.c_str()); 312 } 313 314 OutOfProcessPPAPITest::OutOfProcessPPAPITest() { 315 in_process_ = false; 316 } 317 318 void OutOfProcessPPAPITest::SetUpCommandLine(CommandLine* command_line) { 319 PPAPITest::SetUpCommandLine(command_line); 320 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); 321 command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); 322 } 323 324 void PPAPINaClTest::SetUpCommandLine(CommandLine* command_line) { 325 PPAPITestBase::SetUpCommandLine(command_line); 326 327 base::FilePath plugin_lib; 328 EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib)); 329 EXPECT_TRUE(base::PathExists(plugin_lib)); 330 331 // Enable running NaCl outside of the store. 332 command_line->AppendSwitch(switches::kEnableNaCl); 333 command_line->AppendSwitch(switches::kEnablePnacl); 334 command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1"); 335 command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); 336 command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); 337 } 338 339 // Append the correct mode and testcase string 340 std::string PPAPINaClNewlibTest::BuildQuery(const std::string& base, 341 const std::string& test_case) { 342 return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(), 343 test_case.c_str()); 344 } 345 346 // Append the correct mode and testcase string 347 std::string PPAPINaClGLibcTest::BuildQuery(const std::string& base, 348 const std::string& test_case) { 349 return base::StringPrintf("%smode=nacl_glibc&testcase=%s", base.c_str(), 350 test_case.c_str()); 351 } 352 353 // Append the correct mode and testcase string 354 std::string PPAPINaClPNaClTest::BuildQuery(const std::string& base, 355 const std::string& test_case) { 356 return base::StringPrintf("%smode=nacl_pnacl&testcase=%s", base.c_str(), 357 test_case.c_str()); 358 } 359 360 void PPAPINaClTestDisallowedSockets::SetUpCommandLine( 361 CommandLine* command_line) { 362 PPAPITestBase::SetUpCommandLine(command_line); 363 364 base::FilePath plugin_lib; 365 EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib)); 366 EXPECT_TRUE(base::PathExists(plugin_lib)); 367 368 // Enable running NaCl outside of the store. 369 command_line->AppendSwitch(switches::kEnableNaCl); 370 command_line->AppendSwitch(switches::kEnablePnacl); 371 } 372 373 // Append the correct mode and testcase string 374 std::string PPAPINaClTestDisallowedSockets::BuildQuery( 375 const std::string& base, 376 const std::string& test_case) { 377 return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(), 378 test_case.c_str()); 379 } 380 381 void PPAPIBrokerInfoBarTest::SetUpOnMainThread() { 382 // The default content setting for the PPAPI broker is ASK. We purposefully 383 // don't call PPAPITestBase::SetUpOnMainThread() to keep it that way. 384 } 385