// 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/browser/extensions/extension_apitest.h"

#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/api/test/test_api.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "extensions/common/extension.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/spawned_test_server/spawned_test_server.h"

namespace {

const char kTestCustomArg[] = "customArg";
const char kTestServerPort[] = "testServer.port";
const char kTestDataDirectory[] = "testDataDirectory";
const char kTestWebSocketPort[] = "testWebSocketPort";
const char kSpawnedTestServerPort[] = "spawnedTestServer.port";

scoped_ptr<net::test_server::HttpResponse> HandleServerRedirectRequest(
    const net::test_server::HttpRequest& request) {
  if (!StartsWithASCII(request.relative_url, "/server-redirect?", true))
    return scoped_ptr<net::test_server::HttpResponse>();

  size_t query_string_pos = request.relative_url.find('?');
  std::string redirect_target =
      request.relative_url.substr(query_string_pos + 1);

  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
      new net::test_server::BasicHttpResponse);
  http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
  http_response->AddCustomHeader("Location", redirect_target);
  return http_response.PassAs<net::test_server::HttpResponse>();
}

scoped_ptr<net::test_server::HttpResponse> HandleEchoHeaderRequest(
    const net::test_server::HttpRequest& request) {
  if (!StartsWithASCII(request.relative_url, "/echoheader?", true))
    return scoped_ptr<net::test_server::HttpResponse>();

  size_t query_string_pos = request.relative_url.find('?');
  std::string header_name =
      request.relative_url.substr(query_string_pos + 1);

  std::string header_value;
  std::map<std::string, std::string>::const_iterator it = request.headers.find(
      header_name);
  if (it != request.headers.end())
    header_value = it->second;

  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
      new net::test_server::BasicHttpResponse);
  http_response->set_code(net::HTTP_OK);
  http_response->set_content(header_value);
  return http_response.PassAs<net::test_server::HttpResponse>();
}

scoped_ptr<net::test_server::HttpResponse> HandleSetCookieRequest(
    const net::test_server::HttpRequest& request) {
  if (!StartsWithASCII(request.relative_url, "/set-cookie?", true))
    return scoped_ptr<net::test_server::HttpResponse>();

  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
      new net::test_server::BasicHttpResponse);
  http_response->set_code(net::HTTP_OK);

  size_t query_string_pos = request.relative_url.find('?');
  std::string cookie_value =
      request.relative_url.substr(query_string_pos + 1);

  std::vector<std::string> cookies;
  base::SplitString(cookie_value, '&', &cookies);

  for (size_t i = 0; i < cookies.size(); i++)
    http_response->AddCustomHeader("Set-Cookie", cookies[i]);

  return http_response.PassAs<net::test_server::HttpResponse>();
}

scoped_ptr<net::test_server::HttpResponse> HandleSetHeaderRequest(
    const net::test_server::HttpRequest& request) {
  if (!StartsWithASCII(request.relative_url, "/set-header?", true))
    return scoped_ptr<net::test_server::HttpResponse>();

  size_t query_string_pos = request.relative_url.find('?');
  std::string escaped_header =
      request.relative_url.substr(query_string_pos + 1);

  std::string header =
      net::UnescapeURLComponent(escaped_header,
                                net::UnescapeRule::NORMAL |
                                net::UnescapeRule::SPACES |
                                net::UnescapeRule::URL_SPECIAL_CHARS);

  size_t colon_pos = header.find(':');
  if (colon_pos == std::string::npos)
    return scoped_ptr<net::test_server::HttpResponse>();

  std::string header_name = header.substr(0, colon_pos);
  // Skip space after colon.
  std::string header_value = header.substr(colon_pos + 2);

  scoped_ptr<net::test_server::BasicHttpResponse> http_response(
      new net::test_server::BasicHttpResponse);
  http_response->set_code(net::HTTP_OK);
  http_response->AddCustomHeader(header_name, header_value);
  return http_response.PassAs<net::test_server::HttpResponse>();
}

};  // namespace

ExtensionApiTest::ExtensionApiTest() {
  embedded_test_server()->RegisterRequestHandler(
      base::Bind(&HandleServerRedirectRequest));
  embedded_test_server()->RegisterRequestHandler(
      base::Bind(&HandleEchoHeaderRequest));
  embedded_test_server()->RegisterRequestHandler(
      base::Bind(&HandleSetCookieRequest));
  embedded_test_server()->RegisterRequestHandler(
      base::Bind(&HandleSetHeaderRequest));
}

ExtensionApiTest::~ExtensionApiTest() {}

ExtensionApiTest::ResultCatcher::ResultCatcher()
    : profile_restriction_(NULL),
      waiting_(false) {
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_PASSED,
                 content::NotificationService::AllSources());
  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_FAILED,
                 content::NotificationService::AllSources());
}

ExtensionApiTest::ResultCatcher::~ResultCatcher() {
}

bool ExtensionApiTest::ResultCatcher::GetNextResult() {
  // Depending on the tests, multiple results can come in from a single call
  // to RunMessageLoop(), so we maintain a queue of results and just pull them
  // off as the test calls this, going to the run loop only when the queue is
  // empty.
  if (results_.empty()) {
    waiting_ = true;
    content::RunMessageLoop();
    waiting_ = false;
  }

  if (!results_.empty()) {
    bool ret = results_.front();
    results_.pop_front();
    message_ = messages_.front();
    messages_.pop_front();
    return ret;
  }

  NOTREACHED();
  return false;
}

void ExtensionApiTest::ResultCatcher::Observe(
    int type, const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  if (profile_restriction_ &&
      content::Source<Profile>(source).ptr() != profile_restriction_) {
    return;
  }

  switch (type) {
    case chrome::NOTIFICATION_EXTENSION_TEST_PASSED:
      VLOG(1) << "Got EXTENSION_TEST_PASSED notification.";
      results_.push_back(true);
      messages_.push_back(std::string());
      if (waiting_)
        base::MessageLoopForUI::current()->Quit();
      break;

    case chrome::NOTIFICATION_EXTENSION_TEST_FAILED:
      VLOG(1) << "Got EXTENSION_TEST_FAILED notification.";
      results_.push_back(false);
      messages_.push_back(*(content::Details<std::string>(details).ptr()));
      if (waiting_)
        base::MessageLoopForUI::current()->Quit();
      break;

    default:
      NOTREACHED();
  }
}

void ExtensionApiTest::SetUpInProcessBrowserTestFixture() {
  DCHECK(!test_config_.get()) << "Previous test did not clear config state.";
  test_config_.reset(new DictionaryValue());
  test_config_->SetString(kTestDataDirectory,
                          net::FilePathToFileURL(test_data_dir_).spec());
  test_config_->SetInteger(kTestWebSocketPort, 0);
  extensions::TestGetConfigFunction::set_test_config_state(
      test_config_.get());
}

void ExtensionApiTest::TearDownInProcessBrowserTestFixture() {
  extensions::TestGetConfigFunction::set_test_config_state(NULL);
  test_config_.reset(NULL);
}

bool ExtensionApiTest::RunExtensionTest(const std::string& extension_name) {
  return RunExtensionTestImpl(
      extension_name, std::string(), NULL, kFlagEnableFileAccess);
}

bool ExtensionApiTest::RunExtensionTestIncognito(
    const std::string& extension_name) {
  return RunExtensionTestImpl(extension_name,
                              std::string(),
                              NULL,
                              kFlagEnableIncognito | kFlagEnableFileAccess);
}

bool ExtensionApiTest::RunExtensionTestIgnoreManifestWarnings(
    const std::string& extension_name) {
  return RunExtensionTestImpl(
      extension_name, std::string(), NULL, kFlagIgnoreManifestWarnings);
}

bool ExtensionApiTest::RunExtensionTestAllowOldManifestVersion(
    const std::string& extension_name) {
  return RunExtensionTestImpl(
      extension_name,
      std::string(),
      NULL,
      kFlagEnableFileAccess | kFlagAllowOldManifestVersions);
}

bool ExtensionApiTest::RunComponentExtensionTest(
    const std::string& extension_name) {
  return RunExtensionTestImpl(extension_name,
                              std::string(),
                              NULL,
                              kFlagEnableFileAccess | kFlagLoadAsComponent);
}

bool ExtensionApiTest::RunExtensionTestNoFileAccess(
    const std::string& extension_name) {
  return RunExtensionTestImpl(extension_name, std::string(), NULL, kFlagNone);
}

bool ExtensionApiTest::RunExtensionTestIncognitoNoFileAccess(
    const std::string& extension_name) {
  return RunExtensionTestImpl(
      extension_name, std::string(), NULL, kFlagEnableIncognito);
}

bool ExtensionApiTest::RunExtensionSubtest(const std::string& extension_name,
                                           const std::string& page_url) {
  return RunExtensionSubtest(extension_name, page_url, kFlagEnableFileAccess);
}

bool ExtensionApiTest::RunExtensionSubtest(const std::string& extension_name,
                                           const std::string& page_url,
                                           int flags) {
  DCHECK(!page_url.empty()) << "Argument page_url is required.";
  // See http://crbug.com/177163 for details.
#if defined(OS_WIN) && !defined(NDEBUG)
  LOG(WARNING) << "Workaround for 177163, prematurely returning";
  return true;
#endif
  return RunExtensionTestImpl(extension_name, page_url, NULL, flags);
}


bool ExtensionApiTest::RunPageTest(const std::string& page_url) {
  return RunExtensionSubtest(std::string(), page_url);
}

bool ExtensionApiTest::RunPageTest(const std::string& page_url,
                                   int flags) {
  return RunExtensionSubtest(std::string(), page_url, flags);
}

bool ExtensionApiTest::RunPlatformAppTest(const std::string& extension_name) {
  return RunExtensionTestImpl(
      extension_name, std::string(), NULL, kFlagLaunchPlatformApp);
}

bool ExtensionApiTest::RunPlatformAppTestWithArg(
    const std::string& extension_name, const char* custom_arg) {
  return RunExtensionTestImpl(
      extension_name, std::string(), custom_arg, kFlagLaunchPlatformApp);
}

bool ExtensionApiTest::RunPlatformAppTestWithFlags(
    const std::string& extension_name, int flags) {
  return RunExtensionTestImpl(
      extension_name, std::string(), NULL, flags | kFlagLaunchPlatformApp);
}

// Load |extension_name| extension and/or |page_url| and wait for
// PASSED or FAILED notification.
bool ExtensionApiTest::RunExtensionTestImpl(const std::string& extension_name,
                                            const std::string& page_url,
                                            const char* custom_arg,
                                            int flags) {
  bool load_as_component = (flags & kFlagLoadAsComponent) != 0;
  bool launch_platform_app = (flags & kFlagLaunchPlatformApp) != 0;
  bool use_incognito = (flags & kFlagUseIncognito) != 0;

  if (custom_arg && custom_arg[0])
    test_config_->SetString(kTestCustomArg, custom_arg);

  ResultCatcher catcher;
  DCHECK(!extension_name.empty() || !page_url.empty()) <<
      "extension_name and page_url cannot both be empty";

  const extensions::Extension* extension = NULL;
  if (!extension_name.empty()) {
    base::FilePath extension_path = test_data_dir_.AppendASCII(extension_name);
    if (load_as_component) {
      extension = LoadExtensionAsComponent(extension_path);
    } else {
      int browser_test_flags = ExtensionBrowserTest::kFlagNone;
      if (flags & kFlagEnableIncognito)
        browser_test_flags |= ExtensionBrowserTest::kFlagEnableIncognito;
      if (flags & kFlagEnableFileAccess)
        browser_test_flags |= ExtensionBrowserTest::kFlagEnableFileAccess;
      if (flags & kFlagIgnoreManifestWarnings)
        browser_test_flags |= ExtensionBrowserTest::kFlagIgnoreManifestWarnings;
      if (flags & kFlagAllowOldManifestVersions) {
        browser_test_flags |=
            ExtensionBrowserTest::kFlagAllowOldManifestVersions;
      }
      extension = LoadExtensionWithFlags(extension_path, browser_test_flags);
    }
    if (!extension) {
      message_ = "Failed to load extension.";
      return false;
    }
  }

  // If there is a page_url to load, navigate it.
  if (!page_url.empty()) {
    GURL url = GURL(page_url);

    // Note: We use is_valid() here in the expectation that the provided url
    // may lack a scheme & host and thus be a relative url within the loaded
    // extension.
    if (!url.is_valid()) {
      DCHECK(!extension_name.empty()) <<
          "Relative page_url given with no extension_name";

      url = extension->GetResourceURL(page_url);
    }

    if (use_incognito)
      ui_test_utils::OpenURLOffTheRecord(browser()->profile(), url);
    else
      ui_test_utils::NavigateToURL(browser(), url);
  } else if (launch_platform_app) {
    AppLaunchParams params(browser()->profile(),
                           extension,
                           extensions::LAUNCH_CONTAINER_NONE,
                           NEW_WINDOW);
    params.command_line = CommandLine::ForCurrentProcess();
    OpenApplication(params);
  }

  if (!catcher.GetNextResult()) {
    message_ = catcher.message();
    return false;
  }

  return true;
}

// Test that exactly one extension is loaded, and return it.
const extensions::Extension* ExtensionApiTest::GetSingleLoadedExtension() {
  ExtensionService* service = extensions::ExtensionSystem::Get(
      browser()->profile())->extension_service();

  const extensions::Extension* extension = NULL;
  for (ExtensionSet::const_iterator it = service->extensions()->begin();
       it != service->extensions()->end(); ++it) {
    // Ignore any component extensions. They are automatically loaded into all
    // profiles and aren't the extension we're looking for here.
    if ((*it)->location() == extensions::Manifest::COMPONENT)
      continue;

    if (extension != NULL) {
      // TODO(yoz): this is misleading; it counts component extensions.
      message_ = base::StringPrintf(
          "Expected only one extension to be present.  Found %u.",
          static_cast<unsigned>(service->extensions()->size()));
      return NULL;
    }

    extension = it->get();
  }

  if (!extension) {
    message_ = "extension pointer is NULL.";
    return NULL;
  }
  return extension;
}

bool ExtensionApiTest::StartEmbeddedTestServer() {
  if (!embedded_test_server()->InitializeAndWaitUntilReady())
    return false;

  // Build a dictionary of values that tests can use to build URLs that
  // access the test server and local file system.  Tests can see these values
  // using the extension API function chrome.test.getConfig().
  test_config_->SetInteger(kTestServerPort,
                           embedded_test_server()->port());

  return true;
}

bool ExtensionApiTest::StartWebSocketServer(
    const base::FilePath& root_directory) {
  websocket_server_.reset(new net::SpawnedTestServer(
      net::SpawnedTestServer::TYPE_WS,
      net::SpawnedTestServer::kLocalhost,
      root_directory));

  if (!websocket_server_->Start())
    return false;

  test_config_->SetInteger(kTestWebSocketPort,
                           websocket_server_->host_port_pair().port());

  return true;
}

bool ExtensionApiTest::StartSpawnedTestServer() {
  if (!test_server()->Start())
    return false;

  // Build a dictionary of values that tests can use to build URLs that
  // access the test server and local file system.  Tests can see these values
  // using the extension API function chrome.test.getConfig().
  test_config_->SetInteger(kSpawnedTestServerPort,
                           test_server()->host_port_pair().port());

  return true;
}

void ExtensionApiTest::SetUpCommandLine(CommandLine* command_line) {
  ExtensionBrowserTest::SetUpCommandLine(command_line);
  test_data_dir_ = test_data_dir_.AppendASCII("api_test");
}
