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