Home | History | Annotate | Download | only in ppapi
      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