// Copyright 2012 The Chromium Authors
// 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 <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>

#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted_memory.h"
#include "base/message_loop/message_pump_type.h"
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/string_view_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "base/uuid.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/util/chromium_git_revision.h"
#include "content/browser/devtools/devtools_manager.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_external_agent_proxy_delegate.h"
#include "content/public/browser/devtools_frontend_host.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/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/url_util.h"
#include "net/http/http_request_headers.h"
#include "net/server/http_server.h"
#include "net/server/http_server_request_info.h"
#include "net/server/http_server_response_info.h"
#include "net/socket/server_socket.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "v8/include/v8-version-string.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/apk_info.h"
#endif

#if BUILDFLAG(ENABLE_DEVTOOLS_FRONTEND)
extern const int kCcompressedProtocolJSON;
#endif

namespace content {

namespace {

const char kDevToolsHandlerThreadName[] = "Chrome_DevToolsHandlerThread";

const char kPageUrlPrefix[] = "/devtools/page/";
const char kBrowserUrlPrefix[] = "/devtools/browser";

const char kTargetIdField[] = "id";
const char kTargetParentIdField[] = "parentId";
const char kTargetTypeField[] = "type";
const char kTargetTitleField[] = "title";
const char kTargetDescriptionField[] = "description";
const char kTargetUrlField[] = "url";
const char kTargetFaviconUrlField[] = "faviconUrl";
const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl";
const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl";
const char kMissingGitRevision[] = "@0000000000000000000000000000000000000000";

const int32_t kSendBufferSizeForDevTools = 256 * 1024 * 1024;  // 256Mb
const int32_t kReceiveBufferSizeForDevTools = 100 * 1024 * 1024;  // 100Mb

const char kRemoteUrlPattern[] =
    "https://chrome-devtools-frontend.appspot.com/serve_rev/%s/%s.html";

constexpr net::NetworkTrafficAnnotationTag
    kDevtoolsHttpHandlerTrafficAnnotation =
        net::DefineNetworkTrafficAnnotation("devtools_http_handler", R"(
      semantics {
        sender: "Devtools Http Handler"
        description:
          "This is a remote debugging server, only enabled by "
          "'--remote-debugging-port' switch. It exposes debugging protocol "
          "over websockets."
        trigger: "Run with '--remote-debugging-port' switch."
        data: "Debugging data, including any data on the open pages."
        destination: OTHER
        destination_other: "The data can be sent to any destination."
      }
      policy {
        cookies_allowed: NO
        setting:
          "This request cannot be disabled in settings. However it will never "
          "be made if user does not run with '--remote-debugging-port' switch."
        policy_exception_justification:
          "Not implemented, only used in Devtools and is behind a switch."
      })");

bool RequestIsSafeToServe(const net::HttpServerRequestInfo& info) {
  // For browser-originating requests, serve only those that are coming from
  // pages loaded off localhost or fixed IPs.
  std::string header = info.GetHeaderValue("host");
  if (header.empty())
    return true;
  GURL url = GURL("https://" + header);
  return url.HostIsIPAddress() || net::IsLocalHostname(url.GetHost());
}

// Returns the (incorrectly named, for historical reasons) WebKit version, in
// the form "major.minor (@chromium_git_revision)".
std::string GetWebKitVersion() {
  return base::StringPrintf("537.36 (%s)", CHROMIUM_GIT_REVISION);
}

}  // namespace

// ServerWrapper -------------------------------------------------------------
// All methods in this class are only called on handler thread.
class ServerWrapper : net::HttpServer::Delegate {
 public:
  ServerWrapper(base::WeakPtr<DevToolsHttpHandler> handler,
                std::unique_ptr<net::ServerSocket> socket,
                const base::FilePath& debug_frontend_dir,
                bool bundles_resources);

  int GetLocalAddress(net::IPEndPoint* address);

  void AcceptWebSocket(int connection_id,
                       const net::HttpServerRequestInfo& request);
  void SendOverWebSocket(int connection_id, std::string message);
  void SendResponse(int connection_id,
                    const net::HttpServerResponseInfo& response);
  void Send200(int connection_id,
               std::string_view data,
               std::string_view mime_type);
  void Send404(int connection_id);
  void Send500(int connection_id, const std::string& message);
  void Close(int connection_id);

  ~ServerWrapper() override {}

 private:
  // net::HttpServer::Delegate implementation.
  void OnConnect(int connection_id) override {}
  void OnHttpRequest(int connection_id,
                     const net::HttpServerRequestInfo& info) override;
  void OnWebSocketRequest(int connection_id,
                          const net::HttpServerRequestInfo& info) override;
  void OnWebSocketMessage(int connection_id, std::string data) override;
  void OnClose(int connection_id) override;

  base::WeakPtr<DevToolsHttpHandler> handler_;
  std::unique_ptr<net::HttpServer> server_;
  base::FilePath debug_frontend_dir_;
  bool bundles_resources_;
};

ServerWrapper::ServerWrapper(base::WeakPtr<DevToolsHttpHandler> handler,
                             std::unique_ptr<net::ServerSocket> socket,
                             const base::FilePath& debug_frontend_dir,
                             bool bundles_resources)
    : handler_(handler),
      server_(new net::HttpServer(std::move(socket), this)),
      debug_frontend_dir_(debug_frontend_dir),
      bundles_resources_(bundles_resources) {}

int ServerWrapper::GetLocalAddress(net::IPEndPoint* address) {
  return server_->GetLocalAddress(address);
}

void ServerWrapper::AcceptWebSocket(int connection_id,
                                    const net::HttpServerRequestInfo& request) {
  server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools);
  server_->SetReceiveBufferSize(connection_id, kReceiveBufferSizeForDevTools);
  server_->AcceptWebSocket(connection_id, request,
                           kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::SendOverWebSocket(int connection_id, std::string message) {
  server_->SendOverWebSocket(connection_id, std::move(message),
                             kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::SendResponse(int connection_id,
                                 const net::HttpServerResponseInfo& response) {
  server_->SendResponse(connection_id, response,
                        kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::Send200(int connection_id,
                            std::string_view data,
                            std::string_view mime_type) {
  server_->Send200(connection_id, data, mime_type,
                   kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::Send404(int connection_id) {
  server_->Send404(connection_id, kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::Send500(int connection_id,
                            const std::string& message) {
  server_->Send500(connection_id, message,
                   kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::Close(int connection_id) {
  server_->Close(connection_id);
}

// Thread and ServerWrapper lifetime management ------------------------------

void TerminateOnUI(std::unique_ptr<base::Thread> thread,
                   std::unique_ptr<ServerWrapper> server_wrapper,
                   std::unique_ptr<DevToolsSocketFactory> socket_factory) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (server_wrapper)
    thread->task_runner()->DeleteSoon(FROM_HERE, std::move(server_wrapper));
  if (socket_factory)
    thread->task_runner()->DeleteSoon(FROM_HERE, std::move(socket_factory));
  if (thread) {
    base::ThreadPool::PostTask(
        FROM_HERE,
        {base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT},
        DoNothingWithBoundArgs(std::move(thread)));
  }
}

void ServerStartedOnUI(base::WeakPtr<DevToolsHttpHandler> handler,
                       std::unique_ptr<base::Thread> thread,
                       ServerWrapper* server_wrapper,
                       DevToolsSocketFactory* socket_factory,
                       std::unique_ptr<net::IPEndPoint> ip_address) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (handler && thread && server_wrapper) {
    handler->ServerStarted(
        std::move(thread), std::unique_ptr<ServerWrapper>(server_wrapper),
        std::unique_ptr<DevToolsSocketFactory>(socket_factory),
        std::move(ip_address));
  } else {
    TerminateOnUI(std::move(thread),
                  std::unique_ptr<ServerWrapper>(server_wrapper),
                  std::unique_ptr<DevToolsSocketFactory>(socket_factory));
  }
}

void StartServerOnHandlerThread(
    base::WeakPtr<DevToolsHttpHandler> handler,
    std::unique_ptr<base::Thread> thread,
    std::unique_ptr<DevToolsSocketFactory> socket_factory,
    const base::FilePath& output_directory,
    const base::FilePath& debug_frontend_dir,
    const std::string& browser_guid,
    bool bundles_resources) {
  DCHECK(thread->task_runner()->BelongsToCurrentThread());
  std::unique_ptr<ServerWrapper> server_wrapper;
  std::unique_ptr<net::ServerSocket> server_socket =
      socket_factory->CreateForHttpServer();
  std::unique_ptr<net::IPEndPoint> ip_address(new net::IPEndPoint);
  if (server_socket) {
    server_wrapper =
        std::make_unique<ServerWrapper>(handler, std::move(server_socket),
                                        debug_frontend_dir, bundles_resources);
    if (server_wrapper->GetLocalAddress(ip_address.get()) != net::OK)
      ip_address.reset();
  } else {
    ip_address.reset();
  }

  if (ip_address) {
    std::string message = base::StringPrintf(
        "\nDevTools listening on ws://%s%s\n", ip_address->ToString().c_str(),
        browser_guid.c_str());
    fprintf(stderr, "%s", message.c_str());
    fflush(stderr);

    // Write this port to a well-known file in the profile directory
    // so Telemetry, ChromeDriver, etc. can pick it up.
    if (!output_directory.empty()) {
      base::FilePath path =
          output_directory.Append(kDevToolsActivePortFileName);
      std::string port_target_string = base::StringPrintf(
          "%d\n%s", ip_address->port(), browser_guid.c_str());
      if (!base::WriteFile(path, port_target_string)) {
        PLOG(ERROR) << "Error writing DevTools active port to file " << path;
      }
    }
  } else {
#if !BUILDFLAG(IS_ANDROID)
    // Android uses UNIX domain sockets which don't have an IP address.
    LOG(ERROR) << "Cannot start http server for devtools.";
#endif
  }

  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&ServerStartedOnUI, std::move(handler), std::move(thread),
                     server_wrapper.release(), socket_factory.release(),
                     std::move(ip_address)));
}

// DevToolsAgentHostClientImpl -----------------------------------------------
// An internal implementation of DevToolsAgentHostClient that delegates
// messages sent to a DebuggerShell instance.
class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
 public:
  DevToolsAgentHostClientImpl(
      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
      ServerWrapper* server_wrapper,
      int connection_id,
      scoped_refptr<DevToolsAgentHost> agent_host)
      : task_runner_(std::move(task_runner)),
        server_wrapper_(server_wrapper),
        connection_id_(connection_id),
        agent_host_(agent_host) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    // TODO(dgozman): handle return value of AttachClient.
    agent_host_->AttachClient(this);
  }

  ~DevToolsAgentHostClientImpl() override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (agent_host_)
      agent_host_->DetachClient(this);
  }

  std::string GetTypeForMetrics() override { return "RemoteDebugger"; }

  bool MayAccessAllCookies() override { return true; }

  void AgentHostClosed(DevToolsAgentHost* agent_host) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(agent_host == agent_host_.get());

    constexpr char kMsg[] =
        "{\"method\":\"Inspector.detached\","
        "\"params\":{\"reason\":\"target_closed\"}}";
    DispatchProtocolMessage(agent_host, base::byte_span_from_cstring(kMsg));

    agent_host_ = nullptr;
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&ServerWrapper::Close, base::Unretained(server_wrapper_),
                       connection_id_));
  }

  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
                               base::span<const uint8_t> message) override {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(agent_host == agent_host_.get());
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&ServerWrapper::SendOverWebSocket,
                       base::Unretained(server_wrapper_), connection_id_,
                       std::string(message.begin(), message.end())));
  }

  void OnMessage(base::span<const uint8_t> message) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (agent_host_)
      agent_host_->DispatchProtocolMessage(this, message);
  }

 private:
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  const raw_ptr<ServerWrapper> server_wrapper_;
  const int connection_id_;
  scoped_refptr<DevToolsAgentHost> agent_host_;
};

static bool TimeComparator(scoped_refptr<DevToolsAgentHost> host1,
                           scoped_refptr<DevToolsAgentHost> host2) {
  return host1->GetLastActivityTime() > host2->GetLastActivityTime();
}

// DevToolsHttpHandler -------------------------------------------------------

net::IPEndPoint DevToolsHttpHandler::GetServerIpAddress() const {
  if (server_ip_address_) {
    return *server_ip_address_;
  }
  return net::IPEndPoint();
}

DevToolsHttpHandler::~DevToolsHttpHandler() {
  if (delegate_ &&
      mode_ ==
          DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    delegate_->SetActiveWebSocketConnections(0);
  }
  // Disconnecting sessions might lead to the last minute messages generated
  // by the targets. It is essential that this happens before we issue delete
  // soon for the server wrapper.
  connection_to_client_.clear();
  TerminateOnUI(std::move(thread_), std::move(server_wrapper_),
                std::move(socket_factory_));
  delegate_ = nullptr;
}

static std::string_view PathWithoutParams(std::string_view path) {
  size_t query_position = path.find('?');
  if (query_position != std::string_view::npos) {
    return path.substr(0, query_position);
  }
  return path;
}

static std::string_view GetMimeType(std::string_view filename) {
  if (base::EndsWith(filename, ".html", base::CompareCase::INSENSITIVE_ASCII)) {
    return "text/html";
  } else if (base::EndsWith(filename, ".css",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "text/css";
  } else if (base::EndsWith(filename, ".js",
                            base::CompareCase::INSENSITIVE_ASCII) ||
             base::EndsWith(filename, ".mjs",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "text/javascript";
  } else if (base::EndsWith(filename, ".png",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "image/png";
  } else if (base::EndsWith(filename, ".gif",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "image/gif";
  } else if (base::EndsWith(filename, ".json",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "application/json";
  } else if (base::EndsWith(filename, ".svg",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "image/svg+xml";
  } else if (base::EndsWith(filename, ".avif",
                            base::CompareCase::INSENSITIVE_ASCII)) {
    return "image/avif";
  }
  LOG(ERROR) << "GetMimeType doesn't know mime type for: "
             << filename
             << " text/plain will be returned";
  return "text/plain";
}

void ServerWrapper::OnHttpRequest(int connection_id,
                                  const net::HttpServerRequestInfo& info) {
  if (!RequestIsSafeToServe(info)) {
    Send500(connection_id,
            "Host header is specified and is not an IP address or localhost.");
    return;
  }

  server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools);

  if (base::StartsWith(info.path, "/json", base::CompareCase::SENSITIVE)) {
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnJsonRequest, handler_,
                                  connection_id, info));
    return;
  }

  if (info.path.empty() || info.path == "/") {
    // Discovery page request.
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnDiscoveryPageRequest,
                                  handler_, connection_id));
    return;
  }

  if (!base::StartsWith(info.path, "/devtools/",
                        base::CompareCase::SENSITIVE)) {
    server_->Send404(connection_id, kDevtoolsHttpHandlerTrafficAnnotation);
    return;
  }

  std::string_view filename =
      PathWithoutParams(std::string_view(info.path).substr(10));
  std::string_view mime_type = GetMimeType(filename);

  if (!debug_frontend_dir_.empty()) {
    base::FilePath filepath = debug_frontend_dir_.AppendASCII(filename);
    std::string data;
    base::ReadFileToString(filepath, &data);
    server_->Send200(connection_id, data, mime_type,
                     kDevtoolsHttpHandlerTrafficAnnotation);
    return;
  }

  if (bundles_resources_) {
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&DevToolsHttpHandler::OnFrontendResourceRequest,
                       handler_, connection_id, std::string(filename)));
    return;
  }
  server_->Send404(connection_id, kDevtoolsHttpHandlerTrafficAnnotation);
}

void ServerWrapper::OnWebSocketRequest(
    int connection_id,
    const net::HttpServerRequestInfo& request) {
  if (!RequestIsSafeToServe(request)) {
    Send500(connection_id,
            "Host header is specified and is not an IP address or localhost.");
    return;
  }

  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnWebSocketRequest,
                                handler_, connection_id, request));
}

void ServerWrapper::OnWebSocketMessage(int connection_id, std::string data) {
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(&DevToolsHttpHandler::OnWebSocketMessage,
                                handler_, connection_id, std::move(data)));
}

void ServerWrapper::OnClose(int connection_id) {
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE,
      base::BindOnce(&DevToolsHttpHandler::OnClose, handler_, connection_id));
}

std::string DevToolsHttpHandler::GetFrontendURLInternal(
    scoped_refptr<DevToolsAgentHost> agent_host,
    const std::string& id,
    const std::string& host) {
  std::string frontend_url;
  const std::string git_revision = CHROMIUM_GIT_REVISION;
  if (git_revision == kMissingGitRevision &&
      delegate_->HasBundledFrontendResources()) {
    frontend_url = "/devtools/inspector.html";
  } else {
    std::string type = agent_host->GetType();
    bool is_worker = type == DevToolsAgentHost::kTypeServiceWorker ||
                     type == DevToolsAgentHost::kTypeSharedWorker;
    frontend_url = base::StringPrintf(kRemoteUrlPattern, git_revision.c_str(),
                                      is_worker ? "worker_app" : "inspector");
  }
  return base::StringPrintf("%s?ws=%s%s%s", frontend_url.c_str(), host.c_str(),
                            kPageUrlPrefix, id.c_str());
}

static bool ParseJsonPath(std::string_view path,
                          std::string* command,
                          std::string* target_id) {
  // Fall back to list in case of empty query.
  if (path.empty()) {
    *command = "list";
    return true;
  }

  if (!base::StartsWith(path, "/", base::CompareCase::SENSITIVE)) {
    // Malformed command.
    return false;
  }
  std::string_view command_view = path.substr(1);

  size_t separator_pos = command_view.find("/");
  if (separator_pos != std::string_view::npos) {
    *target_id = command_view.substr(separator_pos + 1);
    command_view = command_view.substr(0, separator_pos);
  }
  *command = command_view;
  return true;
}

void DevToolsHttpHandler::OnJsonRequest(
    int connection_id,
    const net::HttpServerRequestInfo& info) {
  if (mode_ ==
      DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    Send404(connection_id);
    return;
  }
  // Trim /json
  std::string_view path = std::string_view(info.path).substr(5);

  // Trim fragment and query
  std::string_view query;
  size_t query_pos = path.find('?');
  if (query_pos != std::string_view::npos) {
    query = path.substr(query_pos + 1);
    path = path.substr(0, query_pos);
  }

  size_t fragment_pos = path.find('#');
  if (fragment_pos != std::string_view::npos) {
    path = path.substr(0, fragment_pos);
  }

  std::string command;
  std::string target_id;
  if (!ParseJsonPath(path, &command, &target_id)) {
    SendJson(connection_id, net::HTTP_NOT_FOUND, std::nullopt,
             "Malformed query: " + info.path);
    return;
  }

  if (command == "version") {
    base::DictValue version;
    version.Set("Protocol-Version", DevToolsAgentHost::GetProtocolVersion());
    version.Set("WebKit-Version", GetWebKitVersion());
    version.Set("Browser", GetContentClient()->browser()->GetProduct());
    version.Set("User-Agent", GetContentClient()->browser()->GetUserAgent());
    version.Set("V8-Version", V8_VERSION_STRING);
    std::string host = info.GetHeaderValue("host");
    version.Set(
        kTargetWebSocketDebuggerUrlField,
        base::StringPrintf("ws://%s%s", host.c_str(), browser_guid_.c_str()));
#if BUILDFLAG(IS_ANDROID)
    version.Set("Android-Package",
                base::android::apk_info::host_package_name());
#endif
    SendJson(connection_id, net::HTTP_OK, version, "");
    return;
  }

  if (command == "protocol") {
    DecompressAndSendJsonProtocol(connection_id);
    return;
  }
  std::vector<std::string_view> query_components = base::SplitStringPiece(
      query, "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  bool for_tab = std::ranges::contains(query_components, "for_tab");

  if (command == "list") {
    DevToolsManager* manager = DevToolsManager::GetInstance();
    DevToolsAgentHost::List list =
        manager->delegate() ? manager->delegate()->RemoteDebuggingTargets(
                                  for_tab ? DevToolsManagerDelegate::kTab
                                          : DevToolsManagerDelegate::kFrame)
            : DevToolsAgentHost::GetOrCreateAll();

    RespondToJsonList(connection_id, info.GetHeaderValue("host"),
                      std::move(list), for_tab);
    return;
  }

  if (command == "new") {
    if (!base::EqualsCaseInsensitiveASCII(
            info.method, net::HttpRequestHeaders::kPutMethod)) {
      SendJson(
          connection_id, net::HTTP_METHOD_NOT_ALLOWED, std::nullopt,
          base::StringPrintf("Using unsafe HTTP verb %s to invoke /json/new. "
                             "This action supports only PUT verb.",
                             info.method.c_str()));
      return;
    }

    std::string_view escaped_url =
        query_components.empty() ? "" : query_components[0];
    GURL url(base::UnescapeBinaryURLComponent(escaped_url));
    if (!url.is_valid())
      url = GURL(url::kAboutBlankURL);
    // TODO(dsv): Remove for "for_tab" support once DevTools Frontend
    // no longer needs it for e2e tests
    scoped_refptr<DevToolsAgentHost> agent_host =
        delegate_->CreateNewTarget(url,
                                   for_tab ? DevToolsManagerDelegate::kTab
                                           : DevToolsManagerDelegate::kFrame,
                                   /*new_window=*/false);
    if (!agent_host) {
      SendJson(connection_id, net::HTTP_INTERNAL_SERVER_ERROR, std::nullopt,
               "Could not create new page");
      return;
    }
    std::string host = info.GetHeaderValue("host");
    base::DictValue descriptor = SerializeDescriptor(agent_host, host);
    SendJson(connection_id, net::HTTP_OK, descriptor, "");
    return;
  }

  if (command == "activate" || command == "close") {
    scoped_refptr<DevToolsAgentHost> agent_host =
        DevToolsAgentHost::GetForId(target_id);
    if (!agent_host) {
      SendJson(connection_id, net::HTTP_NOT_FOUND, std::nullopt,
               "No such target id: " + target_id);
      return;
    }

    if (command == "activate") {
      if (agent_host->Activate()) {
        SendJson(connection_id, net::HTTP_OK, std::nullopt, "Target activated");
      } else {
        SendJson(connection_id, net::HTTP_INTERNAL_SERVER_ERROR, std::nullopt,
                 "Could not activate target id: " + target_id);
      }
      return;
    }

    if (command == "close") {
      if (agent_host->Close()) {
        SendJson(connection_id, net::HTTP_OK, std::nullopt,
                 "Target is closing");
      } else {
        SendJson(connection_id, net::HTTP_INTERNAL_SERVER_ERROR, std::nullopt,
                 "Could not close target id: " + target_id);
      }
      return;
    }
  }
  SendJson(connection_id, net::HTTP_NOT_FOUND, std::nullopt,
           "Unknown command: " + command);
}

void DevToolsHttpHandler::DecompressAndSendJsonProtocol(int connection_id) {
#if BUILDFLAG(ENABLE_DEVTOOLS_FRONTEND)
  scoped_refptr<base::RefCountedMemory> bytes =
      GetContentClient()->GetDataResourceBytes(kCcompressedProtocolJSON);
  CHECK(bytes) << "Could not load protocol";

  net::HttpServerResponseInfo response(net::HTTP_OK);
  response.SetBody(base::as_string_view(*bytes),
                   "application/json; charset=UTF-8");

  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
                                base::Unretained(server_wrapper_.get()),
                                connection_id, response));
#else
  NOTREACHED();
#endif  // BUILDFLAG(ENABLE_DEVTOOLS_FRONTEND)
}

void DevToolsHttpHandler::RespondToJsonList(int connection_id,
                                            const std::string& host,
                                            DevToolsAgentHost::List hosts,
                                            bool for_tab) {
  DevToolsAgentHost::List agent_hosts = std::move(hosts);
  std::sort(agent_hosts.begin(), agent_hosts.end(), TimeComparator);
  base::ListValue list_value;
  for (auto& agent_host : agent_hosts) {
    if (agent_host->GetType() != DevToolsAgentHost::kTypeTab || for_tab) {
      list_value.Append(SerializeDescriptor(agent_host, host));
    }
  }
  SendJson(connection_id, net::HTTP_OK, list_value, "");
}

void DevToolsHttpHandler::OnDiscoveryPageRequest(int connection_id) {
  if (mode_ ==
      DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    Send404(connection_id);
    return;
  }
  net::HttpServerResponseInfo response(net::HTTP_OK);
  response.AddHeader("X-Frame-Options", "DENY");
  response.SetBody(delegate_->GetDiscoveryPageHTML(),
                   "text/html; charset=UTF-8");

  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
                                base::Unretained(server_wrapper_.get()),
                                connection_id, response));
}

void DevToolsHttpHandler::OnFrontendResourceRequest(int connection_id,
                                                    std::string_view path) {
  if (mode_ ==
      DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    Send404(connection_id);
    return;
  }
#if BUILDFLAG(ENABLE_DEVTOOLS_FRONTEND)
  Send200(connection_id,
          content::DevToolsFrontendHost::GetFrontendResource(path),
          GetMimeType(path));
#else
  Send404(connection_id);
#endif
}

void DevToolsHttpHandler::HandleDebuggingApproval(
    int connection_id,
    const net::HttpServerRequestInfo& request,
    DevToolsManagerDelegate::AcceptConnectionResult result) {
  if (result == DevToolsManagerDelegate::AcceptConnectionResult::kAllow) {
    scoped_refptr<DevToolsAgentHost> browser_agent =
        DevToolsAgentHost::CreateForBrowser(
            thread_->task_runner(),
            base::BindRepeating(&DevToolsSocketFactory::CreateForTethering,
                                base::Unretained(socket_factory_.get())));
    connection_to_client_[connection_id] =
        std::make_unique<DevToolsAgentHostClientImpl>(
            thread_->task_runner(), server_wrapper_.get(), connection_id,
            browser_agent);
    AcceptWebSocket(connection_id, request);
  } else {
    Send403(connection_id, "Connection rejected");
  }
}

void DevToolsHttpHandler::OnWebSocketRequest(
    int connection_id,
    const net::HttpServerRequestInfo& request) {
  if (!thread_)
    return;

  if (request.headers.count("origin") &&
      !remote_allow_origins_.count(request.headers.at("origin")) &&
      !remote_allow_origins_.count("*")) {
    const std::string& origin = request.headers.at("origin");
    const std::string message = base::StringPrintf(
        "Rejected an incoming WebSocket connection from the %s origin. "
        "Use the command line flag --remote-allow-origins=%s to allow "
        "connections from this origin or --remote-allow-origins=* to allow all "
        "origins.",
        origin.c_str(), origin.c_str());
    Send403(connection_id, message);
    LOG(ERROR) << message;
    return;
  }

  // If we require user approval, we do not require guid.
  if (mode_ ==
      DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    if (base::StartsWith(request.path, kBrowserUrlPrefix,
                         base::CompareCase::SENSITIVE)) {
      delegate_->AcceptDebugging(
          base::BindOnce(&DevToolsHttpHandler::HandleDebuggingApproval,
                         weak_factory_.GetWeakPtr(), connection_id, request));

      return;
    }
    Send403(connection_id, "Connection rejected");
    return;
  }

  if (base::StartsWith(request.path, browser_guid_,
                       base::CompareCase::SENSITIVE)) {
    scoped_refptr<DevToolsAgentHost> browser_agent =
        DevToolsAgentHost::CreateForBrowser(
            thread_->task_runner(),
            base::BindRepeating(&DevToolsSocketFactory::CreateForTethering,
                                base::Unretained(socket_factory_.get())));
    connection_to_client_[connection_id] =
        std::make_unique<DevToolsAgentHostClientImpl>(
            thread_->task_runner(), server_wrapper_.get(), connection_id,
            browser_agent);
    AcceptWebSocket(connection_id, request);
    return;
  }

  if (!base::StartsWith(request.path, kPageUrlPrefix,
                        base::CompareCase::SENSITIVE)) {
    Send404(connection_id);
    return;
  }

  std::string target_id = request.path.substr(strlen(kPageUrlPrefix));
  scoped_refptr<DevToolsAgentHost> agent =
      DevToolsAgentHost::GetForId(target_id);
  if (!agent) {
    Send500(connection_id, "No such target id: " + target_id);
    return;
  }

  connection_to_client_[connection_id] =
      std::make_unique<DevToolsAgentHostClientImpl>(
          thread_->task_runner(), server_wrapper_.get(), connection_id, agent);

  AcceptWebSocket(connection_id, request);
}

void DevToolsHttpHandler::OnWebSocketMessage(int connection_id,
                                             std::string data) {
  auto it = connection_to_client_.find(connection_id);
  if (it != connection_to_client_.end()) {
    it->second->OnMessage(base::as_byte_span(data));
  }
}

void DevToolsHttpHandler::OnClose(int connection_id) {
  auto removed_count = connection_to_client_.erase(connection_id);
  if (delegate_ && removed_count > 0 &&
      mode_ ==
          DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    delegate_->SetActiveWebSocketConnections(connection_to_client_.size());
  }
}

DevToolsHttpHandler::DevToolsHttpHandler(
    DevToolsManagerDelegate* delegate,
    std::unique_ptr<DevToolsSocketFactory> socket_factory,
    const base::FilePath& output_directory,
    const base::FilePath& debug_frontend_dir,
    DevToolsAgentHost::RemoteDebuggingServerMode mode)
    : mode_(mode), delegate_(delegate) {
  browser_guid_ =
      delegate_->IsBrowserTargetDiscoverable()
          ? kBrowserUrlPrefix
          : base::StringPrintf(
                "%s/%s", kBrowserUrlPrefix,
                base::Uuid::GenerateRandomV4().AsLowercaseString().c_str());
  std::unique_ptr<base::Thread> thread(
      new base::Thread(kDevToolsHandlerThreadName));
  base::Thread::Options options;
  options.message_pump_type = base::MessagePumpType::IO;
  if (thread->StartWithOptions(std::move(options))) {
    auto task_runner = thread->task_runner();
    task_runner->PostTask(
        FROM_HERE,
        base::BindOnce(&StartServerOnHandlerThread, weak_factory_.GetWeakPtr(),
                       std::move(thread), std::move(socket_factory),
                       output_directory, debug_frontend_dir, browser_guid_,
                       delegate_->HasBundledFrontendResources()));
  }
  std::string remote_allow_origins = base::ToLowerASCII(
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kRemoteAllowOrigins));

  auto origins =
      base::SplitString(remote_allow_origins, ",", base::TRIM_WHITESPACE,
                        base::SPLIT_WANT_NONEMPTY);
  remote_allow_origins_.insert(origins.begin(), origins.end());
}

void DevToolsHttpHandler::ServerStarted(
    std::unique_ptr<base::Thread> thread,
    std::unique_ptr<ServerWrapper> server_wrapper,
    std::unique_ptr<DevToolsSocketFactory> socket_factory,
    std::unique_ptr<net::IPEndPoint> ip_address) {
  thread_ = std::move(thread);
  server_wrapper_ = std::move(server_wrapper);
  socket_factory_ = std::move(socket_factory);
  server_ip_address_ = std::move(ip_address);
}

void DevToolsHttpHandler::SendJson(int connection_id,
                                   net::HttpStatusCode status_code,
                                   std::optional<base::ValueView> value,
                                   std::string_view message) {
  if (!thread_)
    return;

  // Serialize value and message.
  std::string json_value;
  if (value) {
    base::JSONWriter::WriteWithOptions(
        *value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_value);
  }
  std::string json_message = base::WriteJson(message).value_or("");

  net::HttpServerResponseInfo response(status_code);
  response.AddHeader("Content-Security-Policy", "frame-ancestors 'none'");
  response.SetBody(base::StrCat({json_value, message}),
                   "application/json; charset=UTF-8");

  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
                                base::Unretained(server_wrapper_.get()),
                                connection_id, response));
}

void DevToolsHttpHandler::Send200(int connection_id,
                                  std::string_view data,
                                  std::string_view mime_type) {
  if (!thread_)
    return;
  thread_->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServerWrapper::Send200,
                     base::Unretained(server_wrapper_.get()), connection_id,
                     std::string(data), std::string(mime_type)));
}

void DevToolsHttpHandler::Send404(int connection_id) {
  if (!thread_)
    return;
  thread_->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ServerWrapper::Send404,
                     base::Unretained(server_wrapper_.get()), connection_id));
}

void DevToolsHttpHandler::Send403(int connection_id,
                                  const std::string& message) {
  if (!thread_) {
    return;
  }
  net::HttpServerResponseInfo response(net::HTTP_FORBIDDEN);
  response.SetBody(message, "text/html");
  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServerWrapper::SendResponse,
                                base::Unretained(server_wrapper_.get()),
                                connection_id, response));
}

void DevToolsHttpHandler::Send500(int connection_id,
                                  const std::string& message) {
  if (!thread_)
    return;
  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServerWrapper::Send500,
                                base::Unretained(server_wrapper_.get()),
                                connection_id, message));
}

void DevToolsHttpHandler::AcceptWebSocket(
    int connection_id,
    const net::HttpServerRequestInfo& request) {
  if (!thread_)
    return;
  if (mode_ ==
      DevToolsAgentHost::RemoteDebuggingServerMode::kWithApprovalOnly) {
    delegate_->SetActiveWebSocketConnections(connection_to_client_.size());
  }
  thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServerWrapper::AcceptWebSocket,
                                base::Unretained(server_wrapper_.get()),
                                connection_id, request));
}

base::DictValue DevToolsHttpHandler::SerializeDescriptor(
    scoped_refptr<DevToolsAgentHost> agent_host,
    const std::string& host) {
  base::DictValue dictionary;
  std::string id = agent_host->GetId();
  dictionary.Set(kTargetIdField, id);
  std::string parent_id = agent_host->GetParentId();
  if (!parent_id.empty())
    dictionary.Set(kTargetParentIdField, parent_id);
  dictionary.Set(kTargetTypeField, agent_host->GetType());
  dictionary.Set(kTargetTitleField,
                 base::EscapeForHTML(agent_host->GetTitle()));
  dictionary.Set(kTargetDescriptionField, agent_host->GetDescription());

  GURL url = agent_host->GetURL();
  dictionary.Set(kTargetUrlField, url.spec());

  GURL favicon_url = agent_host->GetFaviconURL();
  if (favicon_url.is_valid())
    dictionary.Set(kTargetFaviconUrlField, favicon_url.spec());

  dictionary.Set(kTargetWebSocketDebuggerUrlField,
                 base::StringPrintf("ws://%s%s%s", host.c_str(), kPageUrlPrefix,
                                    id.c_str()));
  dictionary.Set(kTargetDevtoolsFrontendUrlField,
                 GetFrontendURLInternal(agent_host, id, host));

  return dictionary;
}

}  // namespace content
