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/files/file_util.h"
      9 #include "base/path_service.h"
     10 #include "base/strings/string_util.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/content_settings/host_content_settings_map.h"
     14 #include "chrome/browser/infobars/infobar_service.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/browser/ui/browser.h"
     17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     18 #include "chrome/common/chrome_paths.h"
     19 #include "chrome/common/chrome_switches.h"
     20 #include "chrome/test/base/test_switches.h"
     21 #include "chrome/test/base/ui_test_utils.h"
     22 #include "components/infobars/core/confirm_infobar_delegate.h"
     23 #include "components/infobars/core/infobar.h"
     24 #include "components/nacl/common/nacl_switches.h"
     25 #include "content/public/browser/dom_operation_notification_details.h"
     26 #include "content/public/browser/notification_service.h"
     27 #include "content/public/browser/web_contents.h"
     28 #include "content/public/common/content_switches.h"
     29 #include "media/base/media_switches.h"
     30 #include "net/base/filename_util.h"
     31 #include "net/base/test_data_directory.h"
     32 #include "ppapi/shared_impl/ppapi_switches.h"
     33 #include "ppapi/shared_impl/test_harness_utils.h"
     34 #include "ui/gl/gl_switches.h"
     35 
     36 using content::DomOperationNotificationDetails;
     37 using content::RenderViewHost;
     38 using content::TestMessageHandler;
     39 
     40 namespace {
     41 
     42 void AddPrivateSwitches(base::CommandLine* command_line) {
     43   // For TestRequestOSFileHandle.
     44   command_line->AppendSwitch(switches::kUnlimitedStorage);
     45   command_line->AppendSwitchASCII(switches::kAllowNaClFileHandleAPI,
     46                                   "127.0.0.1");
     47 }
     48 
     49 }  // namespace
     50 
     51 PPAPITestMessageHandler::PPAPITestMessageHandler() {
     52 }
     53 
     54 TestMessageHandler::MessageResponse PPAPITestMessageHandler::HandleMessage(
     55     const std::string& json) {
     56   std::string trimmed;
     57   base::TrimString(json, "\"", &trimmed);
     58   if (trimmed == "...")
     59     return CONTINUE;
     60   message_ = trimmed;
     61   return DONE;
     62 }
     63 
     64 void PPAPITestMessageHandler::Reset() {
     65   TestMessageHandler::Reset();
     66   message_.clear();
     67 }
     68 
     69 PPAPITestBase::InfoBarObserver::InfoBarObserver(PPAPITestBase* test_base)
     70     : test_base_(test_base),
     71       expecting_infobar_(false),
     72       should_accept_(false) {
     73   registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
     74                  content::NotificationService::AllSources());
     75 }
     76 
     77 PPAPITestBase::InfoBarObserver::~InfoBarObserver() {
     78   EXPECT_FALSE(expecting_infobar_) << "Missing an expected infobar";
     79 }
     80 
     81 void PPAPITestBase::InfoBarObserver::ExpectInfoBarAndAccept(
     82     bool should_accept) {
     83   ASSERT_FALSE(expecting_infobar_);
     84   expecting_infobar_ = true;
     85   should_accept_ = should_accept;
     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   // It's not safe to remove the infobar here, since other observers (e.g. the
     94   // InfoBarContainer) may still need to access it.  Instead, post a task to
     95   // do all necessary infobar manipulation as soon as this call stack returns.
     96   base::MessageLoop::current()->PostTask(
     97       FROM_HERE, base::Bind(&InfoBarObserver::VerifyInfoBarState,
     98                             base::Unretained(this)));
     99 }
    100 
    101 void PPAPITestBase::InfoBarObserver::VerifyInfoBarState() {
    102   content::WebContents* web_contents =
    103       test_base_->browser()->tab_strip_model()->GetActiveWebContents();
    104   ASSERT_TRUE(web_contents != NULL);
    105   InfoBarService* infobar_service =
    106       InfoBarService::FromWebContents(web_contents);
    107   ASSERT_TRUE(infobar_service != NULL);
    108 
    109   EXPECT_EQ(expecting_infobar_ ? 1U : 0U, infobar_service->infobar_count());
    110   if (!expecting_infobar_)
    111     return;
    112   expecting_infobar_ = false;
    113 
    114   infobars::InfoBar* infobar = infobar_service->infobar_at(0);
    115   ConfirmInfoBarDelegate* delegate =
    116       infobar->delegate()->AsConfirmInfoBarDelegate();
    117   ASSERT_TRUE(delegate != NULL);
    118   if (should_accept_)
    119     delegate->Accept();
    120   else
    121     delegate->Cancel();
    122 
    123   infobar_service->RemoveInfoBar(infobar);
    124 }
    125 
    126 PPAPITestBase::PPAPITestBase() {
    127 }
    128 
    129 void PPAPITestBase::SetUp() {
    130   EnablePixelOutput();
    131   InProcessBrowserTest::SetUp();
    132 }
    133 
    134 void PPAPITestBase::SetUpCommandLine(base::CommandLine* command_line) {
    135   // The test sends us the result via a cookie.
    136   command_line->AppendSwitch(switches::kEnableFileCookies);
    137 
    138   // Some stuff is hung off of the testing interface which is not enabled
    139   // by default.
    140   command_line->AppendSwitch(switches::kEnablePepperTesting);
    141 
    142   // Smooth scrolling confuses the scrollbar test.
    143   command_line->AppendSwitch(switches::kDisableSmoothScrolling);
    144 }
    145 
    146 void PPAPITestBase::SetUpOnMainThread() {
    147   // Always allow access to the PPAPI broker.
    148   browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
    149       CONTENT_SETTINGS_TYPE_PPAPI_BROKER, CONTENT_SETTING_ALLOW);
    150 }
    151 
    152 GURL PPAPITestBase::GetTestFileUrl(const std::string& test_case) {
    153   base::FilePath test_path;
    154   EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_path));
    155   test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
    156   test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
    157   test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));
    158 
    159   // Sanity check the file name.
    160   EXPECT_TRUE(base::PathExists(test_path));
    161 
    162   GURL test_url = net::FilePathToFileURL(test_path);
    163 
    164   GURL::Replacements replacements;
    165   std::string query = BuildQuery(std::string(), test_case);
    166   replacements.SetQuery(query.c_str(), url::Component(0, query.size()));
    167   return test_url.ReplaceComponents(replacements);
    168 }
    169 
    170 void PPAPITestBase::RunTest(const std::string& test_case) {
    171   GURL url = GetTestFileUrl(test_case);
    172   RunTestURL(url);
    173 }
    174 
    175 void 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 
    187 void 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 
    209 void 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 
    235 void PPAPITestBase::RunTestIfAudioOutputAvailable(
    236     const std::string& test_case) {
    237   RunTest(test_case);
    238 }
    239 
    240 void PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(
    241     const std::string& test_case) {
    242   RunTestViaHTTP(test_case);
    243 }
    244 
    245 void PPAPITestBase::RunTestURL(const GURL& test_url) {
    246 #if defined(OS_WIN) && defined(USE_ASH)
    247   // PPAPITests are broken in Ash browser tests (http://crbug.com/263548).
    248   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
    249           switches::kAshBrowserTests)) {
    250     LOG(WARNING) << "PPAPITests are disabled for Ash browser tests.";
    251     return;
    252   }
    253 #endif
    254 
    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   content::JavascriptTestObserver observer(
    262       browser()->tab_strip_model()->GetActiveWebContents(),
    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 
    271 GURL 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 
    282 PPAPITest::PPAPITest() : in_process_(true) {
    283 }
    284 
    285 void PPAPITest::SetUpCommandLine(base::CommandLine* command_line) {
    286   PPAPITestBase::SetUpCommandLine(command_line);
    287 
    288   base::FilePath plugin_dir;
    289   EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir));
    290 
    291   base::FilePath plugin_lib = plugin_dir.Append(ppapi::GetTestLibraryName());
    292   EXPECT_TRUE(base::PathExists(plugin_lib));
    293 
    294   // Append the switch to register the pepper plugin.
    295   // library path = <out dir>/<test_name>.<library_extension>
    296   // library name = "PPAPI Tests"
    297   // version = "1.2.3"
    298   // MIME type = application/x-ppapi-<test_name>
    299   base::FilePath::StringType pepper_plugin = plugin_lib.value();
    300   pepper_plugin.append(FILE_PATH_LITERAL("#PPAPI Tests"));
    301   pepper_plugin.append(FILE_PATH_LITERAL("#"));  // No description.
    302   pepper_plugin.append(FILE_PATH_LITERAL("#1.2.3"));
    303   pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
    304   command_line->AppendSwitchNative(switches::kRegisterPepperPlugins,
    305                                    pepper_plugin);
    306 
    307   command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
    308   if (in_process_)
    309     command_line->AppendSwitch(switches::kPpapiInProcess);
    310 }
    311 
    312 std::string PPAPITest::BuildQuery(const std::string& base,
    313                                   const std::string& test_case){
    314   return base::StringPrintf("%stestcase=%s", base.c_str(), test_case.c_str());
    315 }
    316 
    317 void PPAPIPrivateTest::SetUpCommandLine(base::CommandLine* command_line) {
    318   PPAPITest::SetUpCommandLine(command_line);
    319   AddPrivateSwitches(command_line);
    320 }
    321 
    322 OutOfProcessPPAPITest::OutOfProcessPPAPITest() {
    323   in_process_ = false;
    324 }
    325 
    326 void OutOfProcessPPAPITest::SetUpCommandLine(base::CommandLine* command_line) {
    327   PPAPITest::SetUpCommandLine(command_line);
    328   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
    329   command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
    330 }
    331 
    332 void OutOfProcessPPAPIPrivateTest::SetUpCommandLine(
    333     base::CommandLine* command_line) {
    334   OutOfProcessPPAPITest::SetUpCommandLine(command_line);
    335   AddPrivateSwitches(command_line);
    336 }
    337 
    338 void PPAPINaClTest::SetUpCommandLine(base::CommandLine* command_line) {
    339 #if !defined(DISABLE_NACL)
    340   PPAPITestBase::SetUpCommandLine(command_line);
    341 
    342   // Enable running (non-portable) NaCl outside of the Chrome web store.
    343   command_line->AppendSwitch(switches::kEnableNaCl);
    344   command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
    345   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
    346   command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
    347 #endif
    348 }
    349 
    350 void PPAPINaClTest::SetUpOnMainThread() {
    351 }
    352 
    353 void PPAPINaClTest::RunTest(const std::string& test_case) {
    354 #if !defined(DISABLE_NACL)
    355   PPAPITestBase::RunTest(test_case);
    356 #endif
    357 }
    358 
    359 void PPAPINaClTest::RunTestViaHTTP(const std::string& test_case) {
    360 #if !defined(DISABLE_NACL)
    361   PPAPITestBase::RunTestViaHTTP(test_case);
    362 #endif
    363 }
    364 
    365 void PPAPINaClTest::RunTestWithSSLServer(const std::string& test_case) {
    366 #if !defined(DISABLE_NACL)
    367   PPAPITestBase::RunTestWithSSLServer(test_case);
    368 #endif
    369 }
    370 
    371 void PPAPINaClTest::RunTestWithWebSocketServer(const std::string& test_case) {
    372 #if !defined(DISABLE_NACL)
    373   PPAPITestBase::RunTestWithWebSocketServer(test_case);
    374 #endif
    375 }
    376 
    377 void PPAPINaClTest::RunTestIfAudioOutputAvailable(
    378     const std::string& test_case) {
    379 #if !defined(DISABLE_NACL)
    380   PPAPITestBase::RunTestIfAudioOutputAvailable(test_case);
    381 #endif
    382 }
    383 
    384 void PPAPINaClTest::RunTestViaHTTPIfAudioOutputAvailable(
    385     const std::string& test_case) {
    386 #if !defined(DISABLE_NACL)
    387   PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(test_case);
    388 #endif
    389 }
    390 
    391 // Append the correct mode and testcase string
    392 std::string PPAPINaClNewlibTest::BuildQuery(const std::string& base,
    393                                             const std::string& test_case) {
    394   return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(),
    395                             test_case.c_str());
    396 }
    397 
    398 void PPAPIPrivateNaClNewlibTest::SetUpCommandLine(
    399     base::CommandLine* command_line) {
    400   PPAPINaClNewlibTest::SetUpCommandLine(command_line);
    401   AddPrivateSwitches(command_line);
    402 }
    403 
    404 // Append the correct mode and testcase string
    405 std::string PPAPINaClGLibcTest::BuildQuery(const std::string& base,
    406                                            const std::string& test_case) {
    407   return base::StringPrintf("%smode=nacl_glibc&testcase=%s", base.c_str(),
    408                             test_case.c_str());
    409 }
    410 
    411 void PPAPIPrivateNaClGLibcTest::SetUpCommandLine(
    412     base::CommandLine* command_line) {
    413   PPAPINaClGLibcTest::SetUpCommandLine(command_line);
    414   AddPrivateSwitches(command_line);
    415 }
    416 
    417 // Append the correct mode and testcase string
    418 std::string PPAPINaClPNaClTest::BuildQuery(const std::string& base,
    419                                            const std::string& test_case) {
    420   return base::StringPrintf("%smode=nacl_pnacl&testcase=%s", base.c_str(),
    421                             test_case.c_str());
    422 }
    423 
    424 void PPAPIPrivateNaClPNaClTest::SetUpCommandLine(
    425     base::CommandLine* command_line) {
    426   PPAPINaClPNaClTest::SetUpCommandLine(command_line);
    427   AddPrivateSwitches(command_line);
    428 }
    429 
    430 void PPAPINaClPNaClNonSfiTest::SetUpCommandLine(
    431     base::CommandLine* command_line) {
    432 #if !defined(DISABLE_NACL)
    433   PPAPINaClTest::SetUpCommandLine(command_line);
    434   command_line->AppendSwitch(switches::kEnableNaClNonSfiMode);
    435 #endif
    436 }
    437 
    438 std::string PPAPINaClPNaClNonSfiTest::BuildQuery(
    439     const std::string& base,
    440     const std::string& test_case) {
    441   return base::StringPrintf("%smode=nacl_pnacl_nonsfi&testcase=%s",
    442                             base.c_str(), test_case.c_str());
    443 }
    444 
    445 void PPAPIPrivateNaClPNaClNonSfiTest::SetUpCommandLine(
    446     base::CommandLine* command_line) {
    447   PPAPINaClPNaClNonSfiTest::SetUpCommandLine(command_line);
    448   AddPrivateSwitches(command_line);
    449 }
    450 
    451 void PPAPINaClTestDisallowedSockets::SetUpCommandLine(
    452     base::CommandLine* command_line) {
    453   PPAPITestBase::SetUpCommandLine(command_line);
    454 
    455   // Enable running (non-portable) NaCl outside of the Chrome web store.
    456   command_line->AppendSwitch(switches::kEnableNaCl);
    457 }
    458 
    459 // Append the correct mode and testcase string
    460 std::string PPAPINaClTestDisallowedSockets::BuildQuery(
    461     const std::string& base,
    462     const std::string& test_case) {
    463   return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(),
    464                             test_case.c_str());
    465 }
    466 
    467 void PPAPIBrokerInfoBarTest::SetUpOnMainThread() {
    468   // The default content setting for the PPAPI broker is ASK. We purposefully
    469   // don't call PPAPITestBase::SetUpOnMainThread() to keep it that way.
    470 }
    471