root/chrome/test/ppapi/ppapi_test.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. AddPrivateSwitches
  2. HandleMessage
  3. Reset
  4. should_accept_
  5. ExpectInfoBarAndAccept
  6. VerifyInfoBarState
  7. SetUp
  8. SetUpCommandLine
  9. SetUpOnMainThread
  10. GetTestFileUrl
  11. RunTest
  12. RunTestAndReload
  13. RunTestViaHTTP
  14. RunTestWithSSLServer
  15. RunTestWithWebSocketServer
  16. RunTestIfAudioOutputAvailable
  17. RunTestViaHTTPIfAudioOutputAvailable
  18. StripPrefixes
  19. RunTestURL
  20. GetTestURL
  21. SetUpCommandLine
  22. BuildQuery
  23. SetUpCommandLine
  24. SetUpCommandLine
  25. SetUpCommandLine
  26. SetUpCommandLine
  27. SetUpOnMainThread
  28. RunTest
  29. RunTestAndReload
  30. RunTestViaHTTP
  31. RunTestWithSSLServer
  32. RunTestWithWebSocketServer
  33. RunTestIfAudioOutputAvailable
  34. RunTestViaHTTPIfAudioOutputAvailable
  35. BuildQuery
  36. SetUpCommandLine
  37. BuildQuery
  38. SetUpCommandLine
  39. BuildQuery
  40. SetUpCommandLine
  41. BuildQuery
  42. SetUpCommandLine
  43. SetUpCommandLine
  44. BuildQuery
  45. SetUpOnMainThread

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/ppapi/ppapi_test.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_manager.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/nacl/common/nacl_switches.h"
#include "content/public/browser/dom_operation_notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "net/base/net_util.h"
#include "net/base/test_data_directory.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/gl/gl_switches.h"

using content::DomOperationNotificationDetails;
using content::RenderViewHost;

namespace {

// Platform-specific filename relative to the chrome executable.
#if defined(OS_WIN)
const wchar_t library_name[] = L"ppapi_tests.dll";
#elif defined(OS_MACOSX)
const char library_name[] = "ppapi_tests.plugin";
#elif defined(OS_POSIX)
const char library_name[] = "libppapi_tests.so";
#endif

void AddPrivateSwitches(base::CommandLine* command_line) {
  // For TestRequestOSFileHandle.
  command_line->AppendSwitch(switches::kUnlimitedStorage);
  command_line->AppendSwitchASCII(switches::kAllowNaClFileHandleAPI,
                                  "127.0.0.1");
}

}  // namespace

PPAPITestMessageHandler::PPAPITestMessageHandler() {
}

TestMessageHandler::MessageResponse PPAPITestMessageHandler::HandleMessage(
    const std::string& json) {
  std::string trimmed;
  base::TrimString(json, "\"", &trimmed);
  if (trimmed == "...")
    return CONTINUE;
  message_ = trimmed;
  return DONE;
}

void PPAPITestMessageHandler::Reset() {
  TestMessageHandler::Reset();
  message_.clear();
}

PPAPITestBase::InfoBarObserver::InfoBarObserver(PPAPITestBase* test_base)
    : test_base_(test_base),
      expecting_infobar_(false),
      should_accept_(false) {
  registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
                 content::NotificationService::AllSources());
}

PPAPITestBase::InfoBarObserver::~InfoBarObserver() {
  EXPECT_FALSE(expecting_infobar_) << "Missing an expected infobar";
}

void PPAPITestBase::InfoBarObserver::ExpectInfoBarAndAccept(
    bool should_accept) {
  ASSERT_FALSE(expecting_infobar_);
  expecting_infobar_ = true;
  should_accept_ = should_accept;
}

void PPAPITestBase::InfoBarObserver::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  ASSERT_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, type);
  // It's not safe to remove the infobar here, since other observers (e.g. the
  // InfoBarContainer) may still need to access it.  Instead, post a task to
  // do all necessary infobar manipulation as soon as this call stack returns.
  base::MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(&InfoBarObserver::VerifyInfoBarState,
                            base::Unretained(this)));
}

void PPAPITestBase::InfoBarObserver::VerifyInfoBarState() {
  content::WebContents* web_contents =
      test_base_->browser()->tab_strip_model()->GetActiveWebContents();
  ASSERT_TRUE(web_contents != NULL);
  InfoBarService* infobar_service =
      InfoBarService::FromWebContents(web_contents);
  ASSERT_TRUE(infobar_service != NULL);

  InfoBarManager* infobar_manager = infobar_service->infobar_manager();
  EXPECT_EQ(expecting_infobar_ ? 1U : 0U, infobar_manager->infobar_count());
  if (!expecting_infobar_)
    return;
  expecting_infobar_ = false;

  InfoBar* infobar = infobar_manager->infobar_at(0);
  ConfirmInfoBarDelegate* delegate =
      infobar->delegate()->AsConfirmInfoBarDelegate();
  ASSERT_TRUE(delegate != NULL);
  if (should_accept_)
    delegate->Accept();
  else
    delegate->Cancel();

  infobar_manager->RemoveInfoBar(infobar);
}

PPAPITestBase::PPAPITestBase() {
}

void PPAPITestBase::SetUp() {
  EnablePixelOutput();
  InProcessBrowserTest::SetUp();
}

void PPAPITestBase::SetUpCommandLine(base::CommandLine* command_line) {
  // The test sends us the result via a cookie.
  command_line->AppendSwitch(switches::kEnableFileCookies);

  // Some stuff is hung off of the testing interface which is not enabled
  // by default.
  command_line->AppendSwitch(switches::kEnablePepperTesting);

  // Smooth scrolling confuses the scrollbar test.
  command_line->AppendSwitch(switches::kDisableSmoothScrolling);
}

void PPAPITestBase::SetUpOnMainThread() {
  // Always allow access to the PPAPI broker.
  browser()->profile()->GetHostContentSettingsMap()->SetDefaultContentSetting(
      CONTENT_SETTINGS_TYPE_PPAPI_BROKER, CONTENT_SETTING_ALLOW);
}

GURL PPAPITestBase::GetTestFileUrl(const std::string& test_case) {
  base::FilePath test_path;
  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_path));
  test_path = test_path.Append(FILE_PATH_LITERAL("ppapi"));
  test_path = test_path.Append(FILE_PATH_LITERAL("tests"));
  test_path = test_path.Append(FILE_PATH_LITERAL("test_case.html"));

  // Sanity check the file name.
  EXPECT_TRUE(base::PathExists(test_path));

  GURL test_url = net::FilePathToFileURL(test_path);

  GURL::Replacements replacements;
  std::string query = BuildQuery(std::string(), test_case);
  replacements.SetQuery(query.c_str(), url_parse::Component(0, query.size()));
  return test_url.ReplaceComponents(replacements);
}

void PPAPITestBase::RunTest(const std::string& test_case) {
  GURL url = GetTestFileUrl(test_case);
  RunTestURL(url);
}

void PPAPITestBase::RunTestAndReload(const std::string& test_case) {
  GURL url = GetTestFileUrl(test_case);
  RunTestURL(url);
  // If that passed, we simply run the test again, which navigates again.
  RunTestURL(url);
}

void PPAPITestBase::RunTestViaHTTP(const std::string& test_case) {
  base::FilePath document_root;
  ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root));
  base::FilePath http_document_root;
  ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root));
  net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP,
                                     net::SpawnedTestServer::kLocalhost,
                                     document_root);
  ASSERT_TRUE(http_server.Start());
  RunTestURL(GetTestURL(http_server, test_case, std::string()));
}

void PPAPITestBase::RunTestWithSSLServer(const std::string& test_case) {
  base::FilePath http_document_root;
  ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root));
  net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP,
                                     net::SpawnedTestServer::kLocalhost,
                                     http_document_root);
  net::SpawnedTestServer ssl_server(net::SpawnedTestServer::TYPE_HTTPS,
                                    net::BaseTestServer::SSLOptions(),
                                    http_document_root);
  // Start the servers in parallel.
  ASSERT_TRUE(http_server.StartInBackground());
  ASSERT_TRUE(ssl_server.StartInBackground());
  // Wait until they are both finished before continuing.
  ASSERT_TRUE(http_server.BlockUntilStarted());
  ASSERT_TRUE(ssl_server.BlockUntilStarted());

  uint16_t port = ssl_server.host_port_pair().port();
  RunTestURL(GetTestURL(http_server,
                        test_case,
                        base::StringPrintf("ssl_server_port=%d", port)));
}

void PPAPITestBase::RunTestWithWebSocketServer(const std::string& test_case) {
  base::FilePath http_document_root;
  ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&http_document_root));
  net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP,
                                     net::SpawnedTestServer::kLocalhost,
                                     http_document_root);
  net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS,
                                   net::SpawnedTestServer::kLocalhost,
                                   net::GetWebSocketTestDataDirectory());
  // Start the servers in parallel.
  ASSERT_TRUE(http_server.StartInBackground());
  ASSERT_TRUE(ws_server.StartInBackground());
  // Wait until they are both finished before continuing.
  ASSERT_TRUE(http_server.BlockUntilStarted());
  ASSERT_TRUE(ws_server.BlockUntilStarted());

  std::string host = ws_server.host_port_pair().HostForURL();
  uint16_t port = ws_server.host_port_pair().port();
  RunTestURL(GetTestURL(http_server,
                        test_case,
                        base::StringPrintf(
                            "websocket_host=%s&websocket_port=%d",
                            host.c_str(),
                            port)));
}

void PPAPITestBase::RunTestIfAudioOutputAvailable(
    const std::string& test_case) {
  RunTest(test_case);
}

void PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(
    const std::string& test_case) {
  RunTestViaHTTP(test_case);
}

std::string PPAPITestBase::StripPrefixes(const std::string& test_name) {
  const char* const prefixes[] = {
      "FAILS_", "FLAKY_", "DISABLED_", "SLOW_" };
  for (size_t i = 0; i < sizeof(prefixes)/sizeof(prefixes[0]); ++i)
    if (test_name.find(prefixes[i]) == 0)
      return test_name.substr(strlen(prefixes[i]));
  return test_name;
}

void PPAPITestBase::RunTestURL(const GURL& test_url) {
#if defined(OS_WIN) && defined(USE_ASH)
  // PPAPITests are broken in Ash browser tests (http://crbug.com/263548).
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kAshBrowserTests)) {
    LOG(WARNING) << "PPAPITests are disabled for Ash browser tests.";
    return;
  }
#endif

  // See comment above TestingInstance in ppapi/test/testing_instance.h.
  // Basically it sends messages using the DOM automation controller. The
  // value of "..." means it's still working and we should continue to wait,
  // any other value indicates completion (in this case it will start with
  // "PASS" or "FAIL"). This keeps us from timing out on waits for long tests.
  PPAPITestMessageHandler handler;
  JavascriptTestObserver observer(
      browser()->tab_strip_model()->GetActiveWebContents(),
      &handler);

  ui_test_utils::NavigateToURL(browser(), test_url);

  ASSERT_TRUE(observer.Run()) << handler.error_message();
  EXPECT_STREQ("PASS", handler.message().c_str());
}

GURL PPAPITestBase::GetTestURL(
    const net::SpawnedTestServer& http_server,
    const std::string& test_case,
    const std::string& extra_params) {
  std::string query = BuildQuery("files/test_case.html?", test_case);
  if (!extra_params.empty())
    query = base::StringPrintf("%s&%s", query.c_str(), extra_params.c_str());

  return http_server.GetURL(query);
}

PPAPITest::PPAPITest() : in_process_(true) {
}

void PPAPITest::SetUpCommandLine(base::CommandLine* command_line) {
  PPAPITestBase::SetUpCommandLine(command_line);

  // Append the switch to register the pepper plugin.
  // library name = <out dir>/<test_name>.<library_extension>
  // MIME type = application/x-ppapi-<test_name>
  base::FilePath plugin_dir;
  EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &plugin_dir));

  base::FilePath plugin_lib = plugin_dir.Append(library_name);
  EXPECT_TRUE(base::PathExists(plugin_lib));
  base::FilePath::StringType pepper_plugin = plugin_lib.value();
  pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests"));
  command_line->AppendSwitchNative(switches::kRegisterPepperPlugins,
                                   pepper_plugin);
  command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");

  if (in_process_)
    command_line->AppendSwitch(switches::kPpapiInProcess);
}

std::string PPAPITest::BuildQuery(const std::string& base,
                                  const std::string& test_case){
  return base::StringPrintf("%stestcase=%s", base.c_str(), test_case.c_str());
}

void PPAPIPrivateTest::SetUpCommandLine(base::CommandLine* command_line) {
  PPAPITest::SetUpCommandLine(command_line);
  AddPrivateSwitches(command_line);
}

OutOfProcessPPAPITest::OutOfProcessPPAPITest() {
  in_process_ = false;
}

void OutOfProcessPPAPITest::SetUpCommandLine(base::CommandLine* command_line) {
  PPAPITest::SetUpCommandLine(command_line);
  command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
  command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
}

void OutOfProcessPPAPIPrivateTest::SetUpCommandLine(
    base::CommandLine* command_line) {
  OutOfProcessPPAPITest::SetUpCommandLine(command_line);
  AddPrivateSwitches(command_line);
}

void PPAPINaClTest::SetUpCommandLine(base::CommandLine* command_line) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::SetUpCommandLine(command_line);

  // Enable running (non-portable) NaCl outside of the Chrome web store.
  command_line->AppendSwitch(switches::kEnableNaCl);
  command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
  command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
  command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
#endif
}

void PPAPINaClTest::SetUpOnMainThread() {
  base::FilePath plugin_lib;
  EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib));
  EXPECT_TRUE(base::PathExists(plugin_lib));
}

void PPAPINaClTest::RunTest(const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTest(test_case);
#endif
}

void PPAPINaClTest::RunTestAndReload(const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTestAndReload(test_case);
#endif
}

void PPAPINaClTest::RunTestViaHTTP(const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTestViaHTTP(test_case);
#endif
}

void PPAPINaClTest::RunTestWithSSLServer(const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTestWithSSLServer(test_case);
#endif
}

void PPAPINaClTest::RunTestWithWebSocketServer(const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTestWithWebSocketServer(test_case);
#endif
}

void PPAPINaClTest::RunTestIfAudioOutputAvailable(
    const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTestIfAudioOutputAvailable(test_case);
#endif
}

void PPAPINaClTest::RunTestViaHTTPIfAudioOutputAvailable(
    const std::string& test_case) {
#if !defined(DISABLE_NACL)
  PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(test_case);
#endif
}

// Append the correct mode and testcase string
std::string PPAPINaClNewlibTest::BuildQuery(const std::string& base,
                                            const std::string& test_case) {
  return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(),
                            test_case.c_str());
}

void PPAPIPrivateNaClNewlibTest::SetUpCommandLine(
    base::CommandLine* command_line) {
  PPAPINaClNewlibTest::SetUpCommandLine(command_line);
  AddPrivateSwitches(command_line);
}

// Append the correct mode and testcase string
std::string PPAPINaClGLibcTest::BuildQuery(const std::string& base,
                                           const std::string& test_case) {
  return base::StringPrintf("%smode=nacl_glibc&testcase=%s", base.c_str(),
                            test_case.c_str());
}

void PPAPIPrivateNaClGLibcTest::SetUpCommandLine(
    base::CommandLine* command_line) {
  PPAPINaClGLibcTest::SetUpCommandLine(command_line);
  AddPrivateSwitches(command_line);
}

// Append the correct mode and testcase string
std::string PPAPINaClPNaClTest::BuildQuery(const std::string& base,
                                           const std::string& test_case) {
  return base::StringPrintf("%smode=nacl_pnacl&testcase=%s", base.c_str(),
                            test_case.c_str());
}

void PPAPINaClPNaClNonSfiTest::SetUpCommandLine(
    base::CommandLine* command_line) {
  PPAPINaClTest::SetUpCommandLine(command_line);
  command_line->AppendSwitch(switches::kEnableNaClNonSfiMode);
}

std::string PPAPINaClPNaClNonSfiTest::BuildQuery(
    const std::string& base,
    const std::string& test_case) {
  return base::StringPrintf("%smode=nacl_pnacl_nonsfi&testcase=%s",
                            base.c_str(), test_case.c_str());
}

void PPAPIPrivateNaClPNaClTest::SetUpCommandLine(
    base::CommandLine* command_line) {
  PPAPINaClPNaClTest::SetUpCommandLine(command_line);
  AddPrivateSwitches(command_line);
}

void PPAPINaClTestDisallowedSockets::SetUpCommandLine(
    base::CommandLine* command_line) {
  PPAPITestBase::SetUpCommandLine(command_line);

  // Enable running (non-portable) NaCl outside of the Chrome web store.
  command_line->AppendSwitch(switches::kEnableNaCl);
}

// Append the correct mode and testcase string
std::string PPAPINaClTestDisallowedSockets::BuildQuery(
    const std::string& base,
    const std::string& test_case) {
  return base::StringPrintf("%smode=nacl_newlib&testcase=%s", base.c_str(),
                            test_case.c_str());
}

void PPAPIBrokerInfoBarTest::SetUpOnMainThread() {
  // The default content setting for the PPAPI broker is ASK. We purposefully
  // don't call PPAPITestBase::SetUpOnMainThread() to keep it that way.

  base::FilePath plugin_lib;
  EXPECT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib));
  EXPECT_TRUE(base::PathExists(plugin_lib));
}

/* [<][>][^][v][top][bottom][index][help] */