// 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 "content/browser/devtools/devtools_http_handler.h"

#include <stdint.h>

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_manager_delegate.h"
#include "content/public/browser/devtools_socket_factory.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "net/base/completion_once_callback.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/socket/server_socket.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {
namespace {

const uint16_t kDummyPort = 4321;
const base::FilePath::CharType kDevToolsActivePortFileName[] =
    FILE_PATH_LITERAL("DevToolsActivePort");

class DummyServerSocket : public net::ServerSocket {
 public:
  DummyServerSocket() {}

  // net::ServerSocket "implementation"
  int Listen(const net::IPEndPoint& address, int backlog) override {
    return net::OK;
  }

  int GetLocalAddress(net::IPEndPoint* address) const override {
    *address = net::IPEndPoint(net::IPAddress::IPv4Localhost(), kDummyPort);
    return net::OK;
  }

  int Accept(std::unique_ptr<net::StreamSocket>* socket,
             net::CompletionOnceCallback callback) override {
    return net::ERR_IO_PENDING;
  }
};

class DummyServerSocketFactory : public DevToolsSocketFactory {
 public:
  DummyServerSocketFactory(base::OnceClosure create_socket_callback,
                           base::OnceClosure shutdown_callback)
      : create_socket_callback_(std::move(create_socket_callback)),
        shutdown_callback_(std::move(shutdown_callback)) {}

  ~DummyServerSocketFactory() override {
    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(shutdown_callback_));
  }

 protected:
  std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(create_socket_callback_));
    return std::make_unique<DummyServerSocket>();
  }

  std::unique_ptr<net::ServerSocket> CreateForTethering(
      std::string* out_name) override {
    return nullptr;
  }

  base::OnceClosure create_socket_callback_;
  base::OnceClosure shutdown_callback_;
};

class FailingServerSocketFactory : public DummyServerSocketFactory {
 public:
  FailingServerSocketFactory(base::OnceClosure create_socket_callback,
                             base::OnceClosure shutdown_callback)
      : DummyServerSocketFactory(std::move(create_socket_callback),
                                 std::move(shutdown_callback)) {}

 private:
  std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
    GetUIThreadTaskRunner({})->PostTask(FROM_HERE,
                                        std::move(create_socket_callback_));
    return nullptr;
  }
};

class BrowserClient : public ContentBrowserClient {
 public:
  BrowserClient() {}
  ~BrowserClient() override {}
  std::unique_ptr<content::DevToolsManagerDelegate>
  CreateDevToolsManagerDelegate() override {
    return std::make_unique<DevToolsManagerDelegate>();
  }
};

}

class DevToolsHttpHandlerTest : public testing::Test {
 public:
  DevToolsHttpHandlerTest() : testing::Test() { }

  void SetUp() override {
    content_client_ = std::make_unique<ContentClient>();
    browser_content_client_ = std::make_unique<BrowserClient>();
    SetBrowserClientForTesting(browser_content_client_.get());
  }

 private:
  std::unique_ptr<ContentClient> content_client_;
  std::unique_ptr<ContentBrowserClient> browser_content_client_;
  content::BrowserTaskEnvironment task_environment_;
};

TEST_F(DevToolsHttpHandlerTest, TestStartStop) {
  base::RunLoop run_loop, run_loop_2;
  auto factory = std::make_unique<DummyServerSocketFactory>(
      run_loop.QuitClosure(), run_loop_2.QuitClosure());
  DevToolsAgentHost::StartRemoteDebuggingServer(
      std::move(factory), base::FilePath(), base::FilePath());
  // Our dummy socket factory will post a quit message once the server will
  // become ready.
  run_loop.Run();
  DevToolsAgentHost::StopRemoteDebuggingServer();
  // Make sure the handler actually stops.
  run_loop_2.Run();
}

TEST_F(DevToolsHttpHandlerTest, TestServerSocketFailed) {
  base::RunLoop run_loop, run_loop_2;
  auto factory = std::make_unique<FailingServerSocketFactory>(
      run_loop.QuitClosure(), run_loop_2.QuitClosure());
  LOG(INFO) << "Following error message is expected:";
  DevToolsAgentHost::StartRemoteDebuggingServer(
      std::move(factory), base::FilePath(), base::FilePath());
  // Our dummy socket factory will post a quit message once the server will
  // become ready.
  run_loop.Run();
  for (int i = 0; i < 5; i++)
    RunAllPendingInMessageLoop(BrowserThread::UI);
  DevToolsAgentHost::StopRemoteDebuggingServer();
  // Make sure the handler actually stops.
  run_loop_2.Run();
}


TEST_F(DevToolsHttpHandlerTest, TestDevToolsActivePort) {
  base::RunLoop run_loop, run_loop_2;
  base::ScopedTempDir temp_dir;
  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
  auto factory = std::make_unique<DummyServerSocketFactory>(
      run_loop.QuitClosure(), run_loop_2.QuitClosure());

  DevToolsAgentHost::StartRemoteDebuggingServer(
      std::move(factory), temp_dir.GetPath(), base::FilePath());
  // Our dummy socket factory will post a quit message once the server will
  // become ready.
  run_loop.Run();
  DevToolsAgentHost::StopRemoteDebuggingServer();
  // Make sure the handler actually stops.
  run_loop_2.Run();

  // Now make sure the DevToolsActivePort was written into the
  // temporary directory and its contents are as expected.
  base::FilePath active_port_file =
      temp_dir.GetPath().Append(kDevToolsActivePortFileName);
  EXPECT_TRUE(base::PathExists(active_port_file));
  std::string file_contents;
  EXPECT_TRUE(base::ReadFileToString(active_port_file, &file_contents));
  std::vector<std::string> tokens = base::SplitString(
      file_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  int port = 0;
  EXPECT_TRUE(base::StringToInt(tokens[0], &port));
  EXPECT_EQ(static_cast<int>(kDummyPort), port);
}

}  // namespace content
