// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/browser/api/socket/socket_api.h"

#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>

#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/types/optional_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "extensions/browser/api/socket/socket.h"
#include "extensions/browser/api/socket/tcp_socket.h"
#include "extensions/browser/api/socket/tls_socket.h"
#include "extensions/browser/api/socket/udp_socket.h"
#include "extensions/browser/api/socket/write_quota_checker.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/api/sockets/sockets_manifest_data.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/permissions/socket_permission.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_interfaces.h"
#include "net/base/url_util.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/log/net_log_with_source.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "extensions/browser/api/socket/app_firewall_hole_manager.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

using extensions::mojom::APIPermissionID;

namespace extensions {

#if BUILDFLAG(IS_CHROMEOS)
const char kCrOSTerminal[] = "chrome-untrusted://terminal";
#endif  // BUILDFLAG(IS_CHROMEOS)

namespace {

const char kAddressKey[] = "address";
const char kPortKey[] = "port";
const char kBytesWrittenKey[] = "bytesWritten";
const char kDataKey[] = "data";
const char kResultCodeKey[] = "resultCode";
const char kSocketIdKey[] = "socketId";

const char kSocketNotFoundError[] = "Socket not found";
const char kDnsLookupFailedError[] = "DNS resolution failed";
const char kPermissionError[] = "App does not have permission";
const char kPortInvalidError[] = "Port must be a value between 0 and 65535.";
const char kNetworkListError[] = "Network lookup failed or unsupported";
const char kTCPSocketBindError[] =
    "TCP socket does not support bind. For TCP server please use listen.";
const char kMulticastSocketTypeError[] = "Only UDP socket supports multicast.";
const char kSecureSocketTypeError[] = "Only TCP sockets are supported for TLS.";
const char kSocketNotConnectedError[] = "Socket not connected";
const char kWildcardAddress[] = "*";
const uint16_t kWildcardPort = 0;

#if BUILDFLAG(IS_CHROMEOS)
const char kFirewallFailure[] = "Failed to open firewall port";
#endif  // BUILDFLAG(IS_CHROMEOS)

bool IsPortValid(int port) {
  return port >= 0 && port <= 65535;
}

}  // namespace

using content::BrowserThread;
using content::SocketPermissionRequest;

SocketApiFunction::ScopedWriteQuota::ScopedWriteQuota(SocketApiFunction* owner,
                                                      size_t bytes_used)
    : owner_(owner), bytes_used_(bytes_used) {
  DCHECK(owner_);
}

SocketApiFunction::ScopedWriteQuota::~ScopedWriteQuota() {
  WriteQuotaChecker::Get(owner_->browser_context())
      ->ReturnBytes(owner_->GetOriginId(), bytes_used_);
}

SocketApiFunction::SocketApiFunction() = default;

SocketApiFunction::~SocketApiFunction() = default;

int SocketApiFunction::AddSocket(Socket* socket) {
  return manager_->Add(socket);
}

Socket* SocketApiFunction::GetSocket(int api_resource_id) {
  return manager_->Get(GetOriginId(), api_resource_id);
}

void SocketApiFunction::ReplaceSocket(int api_resource_id, Socket* socket) {
  manager_->Replace(GetOriginId(), api_resource_id, socket);
}

std::unordered_set<int>* SocketApiFunction::GetSocketIds() {
  return manager_->GetResourceIds(GetOriginId());
}

void SocketApiFunction::RemoveSocket(int api_resource_id) {
  manager_->Remove(GetOriginId(), api_resource_id);
}

std::unique_ptr<SocketResourceManagerInterface>
SocketApiFunction::CreateSocketResourceManager() {
  return std::make_unique<SocketResourceManager<Socket>>();
}

void SocketApiFunction::OpenFirewallHole(const std::string& address,
                                         int socket_id,
                                         Socket* socket) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(IS_CHROMEOS)
  if (!net::HostStringIsLocalhost(address)) {
    net::IPEndPoint local_address;
    if (!socket->GetLocalAddress(&local_address)) {
      NOTREACHED() << "Cannot get address of recently bound socket.";
    }

    AppFirewallHoleManager* manager =
        AppFirewallHoleManager::Get(browser_context());
    std::unique_ptr<AppFirewallHole> hole =
        manager->Open(socket->GetSocketType() == Socket::TYPE_TCP
                          ? chromeos::FirewallHole::PortType::kTcp
                          : chromeos::FirewallHole::PortType::kUdp,
                      local_address.port(), GetOriginId());
    if (!hole) {
      Respond(ErrorWithCode(-1, kFirewallFailure));
      return;
    }

    socket->set_firewall_hole(std::move(hole));
  }
#endif
}

ExtensionFunction::ResponseAction SocketApiFunction::Run() {
  manager_ = CreateSocketResourceManager();
  manager_->SetBrowserContext(browser_context());
  return Work();
}

ExtensionFunction::ResponseValue SocketApiFunction::ErrorWithCode(
    int error_code,
    const std::string& error) {
  base::Value::List args;
  args.Append(error_code);
  return ErrorWithArgumentsDoNotUse(std::move(args), error);
}

std::string SocketApiFunction::GetOriginId() const {
#if BUILDFLAG(IS_CHROMEOS)
  // Terminal app is the only non-extension to use sockets (crbug.com/1350479).
  if (!extension()) {
    auto origin = url::Origin::Create(source_url()).Serialize();
    CHECK_EQ(origin, kCrOSTerminal);
    return origin;
  }
#endif
  return extension_id();
}

bool SocketApiFunction::CheckPermission(
    const APIPermission::CheckParam& param) const {
#if BUILDFLAG(IS_CHROMEOS)
  // Terminal app is the only non-extension to use sockets (crbug.com/1350479).
  if (!extension()) {
    CHECK_EQ(url::Origin::Create(source_url()).Serialize(), kCrOSTerminal);
    return true;
  }
#endif
  return extension()->permissions_data()->CheckAPIPermissionWithParam(
      APIPermissionID::kSocket, &param);
}

bool SocketApiFunction::CheckRequest(
    const content::SocketPermissionRequest& param) const {
#if BUILDFLAG(IS_CHROMEOS)
  // Terminal app is the only non-extension to use sockets (crbug.com/1350479).
  if (!extension()) {
    CHECK_EQ(url::Origin::Create(source_url()).Serialize(), kCrOSTerminal);
    return true;
  }
#endif
  return SocketsManifestData::CheckRequest(extension(), param);
}

bool SocketApiFunction::TakeWriteQuota(size_t bytes_to_write) {
  if (!WriteQuotaChecker::Get(browser_context())
           ->TakeBytes(GetOriginId(), bytes_to_write)) {
    return false;
  }

  DCHECK(!write_quota_used_.has_value());
  write_quota_used_.emplace(this, bytes_to_write);
  return true;
}

void SocketApiFunction::ReturnWriteQuota() {
  write_quota_used_.reset();
}

SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction() =
    default;

SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() =
    default;

void SocketExtensionWithDnsLookupFunction::StartDnsLookup(
    const net::HostPortPair& host_port_pair,
    net::DnsQueryType dns_query_type) {
  DCHECK(!receiver_.is_bound());

  browser_context()
      ->GetDefaultStoragePartition()
      ->GetNetworkContext()
      ->CreateHostResolver(
          std::nullopt,
          pending_host_resolver_.InitWithNewPipeAndPassReceiver());
  DCHECK(pending_host_resolver_);

  host_resolver_.Bind(std::move(pending_host_resolver_));
  url::Origin origin =
      extension() ? extension()->origin() : url::Origin::Create(source_url());
  network::mojom::ResolveHostParametersPtr params =
      network::mojom::ResolveHostParameters::New();
  params->dns_query_type = dns_query_type;
  // Intentionally using a HostPortPair because scheme isn't specified.
  host_resolver_->ResolveHost(
      network::mojom::HostResolverHost::NewHostPortPair(host_port_pair),
      net::NetworkAnonymizationKey::CreateSameSite(net::SchemefulSite(origin)),
      std::move(params), receiver_.BindNewPipeAndPassRemote());
  receiver_.set_disconnect_handler(base::BindOnce(
      &SocketExtensionWithDnsLookupFunction::OnComplete, base::Unretained(this),
      net::ERR_NAME_NOT_RESOLVED, net::ResolveErrorInfo(net::ERR_FAILED),
      net::AddressList(), net::HostResolverEndpointResults()));

  // Balanced in OnComplete().
  AddRef();
}

void SocketExtensionWithDnsLookupFunction::OnComplete(
    int result,
    const net::ResolveErrorInfo& resolve_error_info,
    const net::AddressList& resolved_addresses,
    const net::HostResolverEndpointResults& alternative_endpoints) {
  host_resolver_.reset();
  receiver_.reset();
  if (result == net::OK) {
    DCHECK(!resolved_addresses.empty());
    addresses_ = resolved_addresses;
  }
  AfterDnsLookup(result);

  Release();  // Added in StartDnsLookup().
}

SocketCreateFunction::SocketCreateFunction() = default;

SocketCreateFunction::~SocketCreateFunction() = default;

ExtensionFunction::ResponseAction SocketCreateFunction::Work() {
  std::optional<api::socket::Create::Params> params =
      api::socket::Create::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = nullptr;
  switch (params->type) {
    case extensions::api::socket::SocketType::kTcp:
      socket = new TCPSocket(browser_context(), GetOriginId());
      break;

    case extensions::api::socket::SocketType::kUdp: {
      mojo::PendingRemote<network::mojom::UDPSocketListener> listener_remote;
      mojo::PendingReceiver<network::mojom::UDPSocketListener>
          socket_listener_receiver =
              listener_remote.InitWithNewPipeAndPassReceiver();
      mojo::PendingRemote<network::mojom::UDPSocket> udp_socket;
      browser_context()
          ->GetDefaultStoragePartition()
          ->GetNetworkContext()
          ->CreateUDPSocket(udp_socket.InitWithNewPipeAndPassReceiver(),
                            std::move(listener_remote));
      socket =
          new UDPSocket(std::move(udp_socket),
                        std::move(socket_listener_receiver), GetOriginId());
      break;
    }
    case extensions::api::socket::SocketType::kNone:
      NOTREACHED();
  }

  DCHECK(socket);

  base::Value::Dict result;
  result.Set(kSocketIdKey, AddSocket(socket));
  return RespondNow(WithArguments(std::move(result)));
}

ExtensionFunction::ResponseAction SocketDestroyFunction::Work() {
  EXTENSION_FUNCTION_VALIDATE(args().size() >= 1);
  const auto& socket_id_value = args()[0];
  EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
  RemoveSocket(socket_id_value.GetInt());
  return RespondNow(NoArguments());
}

SocketConnectFunction::SocketConnectFunction() = default;

SocketConnectFunction::~SocketConnectFunction() = default;

ExtensionFunction::ResponseAction SocketConnectFunction::Work() {
  EXTENSION_FUNCTION_VALIDATE(args().size() >= 3);
  const auto& socket_id_value = args()[0];
  const auto& hostname_value = args()[1];
  const auto& port_value = args()[2];
  EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
  EXTENSION_FUNCTION_VALIDATE(hostname_value.is_string());
  EXTENSION_FUNCTION_VALIDATE(port_value.is_int());
  socket_id_ = socket_id_value.GetInt();
  hostname_ = hostname_value.GetString();
  int port = port_value.GetInt();

  if (!IsPortValid(port)) {
    return RespondNow(Error(kPortInvalidError));
  }
  port_ = static_cast<uint16_t>(port);

  Socket* socket = GetSocket(socket_id_);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  socket->set_hostname(hostname_);

  SocketPermissionRequest::OperationType operation_type;
  switch (socket->GetSocketType()) {
    case Socket::TYPE_TCP:
      operation_type = SocketPermissionRequest::TCP_CONNECT;
      break;
    case Socket::TYPE_UDP:
      operation_type = SocketPermissionRequest::UDP_SEND_TO;
      break;
    default:
      NOTREACHED() << "Unknown socket type.";
  }

  SocketPermission::CheckParam param(operation_type, hostname_, port_);
  if (!CheckPermission(param)) {
    return RespondNow(ErrorWithCode(-1, kPermissionError));
  }

  StartDnsLookup(net::HostPortPair(hostname_, port_),
                 net::DnsQueryType::UNSPECIFIED);
  return RespondLater();
}

void SocketConnectFunction::AfterDnsLookup(int lookup_result) {
  if (lookup_result == net::OK) {
    StartConnect();
  } else {
    Respond(ErrorWithCode(lookup_result, kDnsLookupFailedError));
  }
}

void SocketConnectFunction::StartConnect() {
  Socket* socket = GetSocket(socket_id_);
  if (!socket) {
    Respond(ErrorWithCode(-1, kSocketNotFoundError));
    return;
  }

  socket->Connect(addresses_,
                  base::BindOnce(&SocketConnectFunction::OnConnect, this));
}

void SocketConnectFunction::OnConnect(int result) {
  Respond(WithArguments(result));
}

ExtensionFunction::ResponseAction SocketDisconnectFunction::Work() {
  EXTENSION_FUNCTION_VALIDATE(args().size() >= 1);
  const auto& socket_id_value = args()[0];
  EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
  int socket_id = socket_id_value.GetInt();

  Socket* socket = GetSocket(socket_id);
  if (socket) {
    socket->Disconnect(false /* socket_destroying */);
    return RespondNow(WithArguments(base::Value()));
  } else {
    base::Value::List args;
    args.Append(base::Value());
    return RespondNow(
        ErrorWithArgumentsDoNotUse(std::move(args), kSocketNotFoundError));
  }
}

ExtensionFunction::ResponseAction SocketBindFunction::Work() {
  EXTENSION_FUNCTION_VALIDATE(args().size() >= 3);
  const auto& socket_id_value = args()[0];
  const auto& address_value = args()[1];
  const auto& port_value = args()[2];
  EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
  EXTENSION_FUNCTION_VALIDATE(address_value.is_string());
  EXTENSION_FUNCTION_VALIDATE(port_value.is_int());
  socket_id_ = socket_id_value.GetInt();
  address_ = address_value.GetString();
  int port = port_value.GetInt();

  if (!IsPortValid(port)) {
    return RespondNow(Error(kPortInvalidError));
  }
  port_ = static_cast<uint16_t>(port);

  Socket* socket = GetSocket(socket_id_);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() == Socket::TYPE_TCP) {
    return RespondNow(ErrorWithCode(-1, kTCPSocketBindError));
  }

  CHECK(socket->GetSocketType() == Socket::TYPE_UDP);
  SocketPermission::CheckParam param(SocketPermissionRequest::UDP_BIND,
                                     address_, port_);
  if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
          APIPermissionID::kSocket, &param)) {
    return RespondNow(ErrorWithCode(-1, kPermissionError));
  }

  socket->Bind(address_, port_,
               base::BindOnce(&SocketBindFunction::OnCompleted, this));
  return RespondLater();
}

void SocketBindFunction::OnCompleted(int net_result) {
  Socket* socket = GetSocket(socket_id_);
  if (!socket) {
    Respond(ErrorWithCode(-1, kSocketNotFoundError));
    return;
  }

  if (net_result != net::OK) {
    Respond(WithArguments(net_result));
    return;
  }

  OpenFirewallHole(address_, socket_id_, socket);
  if (!did_respond()) {
    Respond(WithArguments(net_result));
  }
}

SocketListenFunction::SocketListenFunction() = default;

SocketListenFunction::~SocketListenFunction() = default;

ExtensionFunction::ResponseAction SocketListenFunction::Work() {
  params_ = api::socket::Listen::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params_);

  Socket* socket = GetSocket(params_->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  SocketPermission::CheckParam param(SocketPermissionRequest::TCP_LISTEN,
                                     params_->address, params_->port);
  if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
          APIPermissionID::kSocket, &param)) {
    return RespondNow(ErrorWithCode(-1, kPermissionError));
  }

  socket->Listen(params_->address, params_->port, params_->backlog.value_or(5),
                 base::BindOnce(&SocketListenFunction::OnCompleted, this));
  return RespondLater();
}

void SocketListenFunction::OnCompleted(int result,
                                       const std::string& error_msg) {
  DCHECK_NE(net::ERR_IO_PENDING, result);
  Socket* socket = GetSocket(params_->socket_id);
  if (!socket) {
    Respond(ErrorWithCode(-1, kSocketNotFoundError));
    return;
  }

  if (result != net::OK) {
    Respond(ErrorWithCode(result, error_msg));
    return;
  }

  OpenFirewallHole(params_->address, params_->socket_id, socket);
  if (!did_respond()) {
    Respond(WithArguments(result));
  }
}

SocketAcceptFunction::SocketAcceptFunction() = default;

SocketAcceptFunction::~SocketAcceptFunction() = default;

ExtensionFunction::ResponseAction SocketAcceptFunction::Work() {
  std::optional<api::socket::Accept::Params> params =
      api::socket::Accept::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (socket) {
    socket->Accept(base::BindOnce(&SocketAcceptFunction::OnAccept, this));
    return RespondLater();
  } else {
    api::socket::AcceptInfo info;
    info.result_code = net::ERR_FAILED;
    return RespondNow(ErrorWithArgumentsDoNotUse(
        api::socket::Accept::Results::Create(info), kSocketNotFoundError));
  }
}

void SocketAcceptFunction::OnAccept(
    int result_code,
    mojo::PendingRemote<network::mojom::TCPConnectedSocket> socket,
    const std::optional<net::IPEndPoint>& remote_addr,
    mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
    mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
  base::Value::Dict result;
  result.Set(kResultCodeKey, result_code);
  if (result_code == net::OK) {
    Socket* client_socket =
        new TCPSocket(std::move(socket), std::move(receive_pipe_handle),
                      std::move(send_pipe_handle), remote_addr, GetOriginId());
    result.Set(kSocketIdKey, AddSocket(client_socket));
  }
  Respond(WithArguments(std::move(result)));
}

SocketReadFunction::SocketReadFunction() = default;

SocketReadFunction::~SocketReadFunction() = default;

ExtensionFunction::ResponseAction SocketReadFunction::Work() {
  std::optional<api::socket::Read::Params> params =
      api::socket::Read::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    api::socket::ReadInfo info;
    info.result_code = -1;
    return RespondNow(ErrorWithArgumentsDoNotUse(
        api::socket::Read::Results::Create(info), kSocketNotFoundError));
  }

  socket->Read(params->buffer_size.value_or(4096),
               base::BindOnce(&SocketReadFunction::OnCompleted, this));
  return RespondLater();
}

void SocketReadFunction::OnCompleted(int bytes_read,
                                     scoped_refptr<net::IOBuffer> io_buffer,
                                     bool socket_destroying) {
  base::Value::Dict result;
  result.Set(kResultCodeKey, bytes_read);
  base::span<const uint8_t> data_span;
  if (bytes_read > 0) {
    data_span = io_buffer->first(static_cast<size_t>(bytes_read));
  }
  result.Set(kDataKey, base::Value(data_span));
  Respond(WithArguments(std::move(result)));
}

SocketWriteFunction::SocketWriteFunction() = default;

SocketWriteFunction::~SocketWriteFunction() = default;

ExtensionFunction::ResponseAction SocketWriteFunction::Work() {
  EXTENSION_FUNCTION_VALIDATE(args().size() >= 2);
  const auto& socket_id_value = args()[0];
  const auto& data_value = args()[1];
  EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
  EXTENSION_FUNCTION_VALIDATE(data_value.is_blob());

  int socket_id = socket_id_value.GetInt();
  size_t io_buffer_size = data_value.GetBlob().size();
  if (!TakeWriteQuota(io_buffer_size)) {
    return RespondNow(Error(kExceedWriteQuotaError));
  }

  auto io_buffer =
      base::MakeRefCounted<net::IOBufferWithSize>(data_value.GetBlob().size());
  std::ranges::copy(data_value.GetBlob(), io_buffer->data());

  Socket* socket = GetSocket(socket_id);
  if (!socket) {
    api::socket::WriteInfo info;
    info.bytes_written = -1;
    return RespondNow(ErrorWithArgumentsDoNotUse(
        api::socket::Write::Results::Create(info), kSocketNotFoundError));
  }

  socket->Write(io_buffer, io_buffer_size,
                base::BindOnce(&SocketWriteFunction::OnCompleted, this));
  return RespondLater();
}

void SocketWriteFunction::OnCompleted(int bytes_written) {
  ReturnWriteQuota();

  base::Value::Dict result;
  result.Set(kBytesWrittenKey, bytes_written);
  Respond(WithArguments(std::move(result)));
}

SocketRecvFromFunction::SocketRecvFromFunction() = default;

SocketRecvFromFunction::~SocketRecvFromFunction() = default;

ExtensionFunction::ResponseAction SocketRecvFromFunction::Work() {
  std::optional<api::socket::RecvFrom::Params> params =
      api::socket::RecvFrom::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket || socket->GetSocketType() != Socket::TYPE_UDP) {
    api::socket::RecvFromInfo info;
    info.result_code = -1;
    info.port = 0;
    return RespondNow(ErrorWithArgumentsDoNotUse(
        api::socket::RecvFrom::Results::Create(info), kSocketNotFoundError));
  }

  socket->RecvFrom(params->buffer_size.value_or(4096),
                   base::BindOnce(&SocketRecvFromFunction::OnCompleted, this));
  return RespondLater();
}

void SocketRecvFromFunction::OnCompleted(int bytes_read,
                                         scoped_refptr<net::IOBuffer> io_buffer,
                                         bool socket_destroying,
                                         const std::string& address,
                                         uint16_t port) {
  base::Value::Dict result;
  result.Set(kResultCodeKey, bytes_read);
  base::span<const uint8_t> data_span;
  if (bytes_read > 0) {
    data_span = io_buffer->first(static_cast<size_t>(bytes_read));
  }
  result.Set(kDataKey, base::Value(data_span));
  result.Set(kAddressKey, address);
  result.Set(kPortKey, port);
  Respond(WithArguments(std::move(result)));
}

SocketSendToFunction::SocketSendToFunction() = default;

SocketSendToFunction::~SocketSendToFunction() = default;

ExtensionFunction::ResponseAction SocketSendToFunction::Work() {
  EXTENSION_FUNCTION_VALIDATE(args().size() >= 4);
  const auto& socket_id_value = args()[0];
  const auto& data_value = args()[1];
  const auto& hostname_value = args()[2];
  const auto& port_value = args()[3];
  EXTENSION_FUNCTION_VALIDATE(socket_id_value.is_int());
  EXTENSION_FUNCTION_VALIDATE(data_value.is_blob());
  EXTENSION_FUNCTION_VALIDATE(hostname_value.is_string());
  EXTENSION_FUNCTION_VALIDATE(port_value.is_int());

  int port = port_value.GetInt();
  if (!IsPortValid(port)) {
    return RespondNow(Error(kPortInvalidError));
  }
  port_ = static_cast<uint16_t>(port);
  socket_id_ = socket_id_value.GetInt();
  hostname_ = hostname_value.GetString();

  io_buffer_size_ = data_value.GetBlob().size();
  io_buffer_ =
      base::MakeRefCounted<net::IOBufferWithSize>(data_value.GetBlob().size());
  std::ranges::copy(data_value.GetBlob(), io_buffer_->data());

  Socket* socket = GetSocket(socket_id_);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() == Socket::TYPE_UDP) {
    SocketPermission::CheckParam param(SocketPermissionRequest::UDP_SEND_TO,
                                       hostname_, port_);
    if (!CheckPermission(param)) {
      return RespondNow(ErrorWithCode(-1, kPermissionError));
    }
  }

  StartDnsLookup(net::HostPortPair(hostname_, port_),
                 net::DnsQueryType::UNSPECIFIED);
  return RespondLater();
}

void SocketSendToFunction::AfterDnsLookup(int lookup_result) {
  if (lookup_result == net::OK) {
    StartSendTo();
  } else {
    Respond(ErrorWithCode(lookup_result, kDnsLookupFailedError));
  }
}

void SocketSendToFunction::StartSendTo() {
  Socket* socket = GetSocket(socket_id_);
  if (!socket) {
    Respond(ErrorWithCode(-1, kSocketNotFoundError));
    return;
  }

  if (!TakeWriteQuota(io_buffer_size_)) {
    Respond(Error(kExceedWriteQuotaError));
    return;
  }

  socket->SendTo(io_buffer_, io_buffer_size_, addresses_.front(),
                 base::BindOnce(&SocketSendToFunction::OnCompleted, this));
}

void SocketSendToFunction::OnCompleted(int bytes_written) {
  ReturnWriteQuota();

  api::socket::WriteInfo info;
  info.bytes_written = bytes_written;
  Respond(ArgumentList(api::socket::SendTo::Results::Create(info)));
}

SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() = default;

SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() = default;

ExtensionFunction::ResponseAction SocketSetKeepAliveFunction::Work() {
  std::optional<api::socket::SetKeepAlive::Params> params =
      api::socket::SetKeepAlive::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithArgumentsDoNotUse(
        api::socket::SetKeepAlive::Results::Create(false),
        kSocketNotFoundError));
  }
  int delay = 0;
  if (params->delay) {
    delay = *params->delay;
  }
  socket->SetKeepAlive(
      params->enable, delay,
      base::BindOnce(&SocketSetKeepAliveFunction::OnCompleted, this));
  return RespondLater();
}

void SocketSetKeepAliveFunction::OnCompleted(bool success) {
  Respond(WithArguments(success));
}

SocketSetNoDelayFunction::SocketSetNoDelayFunction() = default;

SocketSetNoDelayFunction::~SocketSetNoDelayFunction() = default;

ExtensionFunction::ResponseAction SocketSetNoDelayFunction::Work() {
  std::optional<api::socket::SetNoDelay::Params> params =
      api::socket::SetNoDelay::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithArgumentsDoNotUse(
        api::socket::SetNoDelay::Results::Create(false), kSocketNotFoundError));
  }
  socket->SetNoDelay(
      params->no_delay,
      base::BindOnce(&SocketSetNoDelayFunction::OnCompleted, this));
  return RespondLater();
}

void SocketSetNoDelayFunction::OnCompleted(bool success) {
  Respond(WithArguments(success));
}

SocketGetInfoFunction::SocketGetInfoFunction() = default;

SocketGetInfoFunction::~SocketGetInfoFunction() = default;

ExtensionFunction::ResponseAction SocketGetInfoFunction::Work() {
  std::optional<api::socket::GetInfo::Params> params =
      api::socket::GetInfo::Params::Create(args());

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(Error(kSocketNotFoundError));
  }

  api::socket::SocketInfo info;
  // This represents what we know about the socket, and does not call through
  // to the system.
  if (socket->GetSocketType() == Socket::TYPE_TCP) {
    info.socket_type = extensions::api::socket::SocketType::kTcp;
  } else {
    info.socket_type = extensions::api::socket::SocketType::kUdp;
  }
  info.connected = socket->IsConnected();

  // Grab the peer address as known by the OS. This and the call below will
  // always succeed while the socket is connected, even if the socket has
  // been remotely closed by the peer; only reading the socket will reveal
  // that it should be closed locally.
  net::IPEndPoint peerAddress;
  if (socket->GetPeerAddress(&peerAddress)) {
    info.peer_address = peerAddress.ToStringWithoutPort();
    info.peer_port = peerAddress.port();
  }

  // Grab the local address as known by the OS.
  net::IPEndPoint localAddress;
  if (socket->GetLocalAddress(&localAddress)) {
    info.local_address = localAddress.ToStringWithoutPort();
    info.local_port = localAddress.port();
  }

  return RespondNow(ArgumentList(api::socket::GetInfo::Results::Create(info)));
}

ExtensionFunction::ResponseAction SocketGetNetworkListFunction::Run() {
  content::GetNetworkService()->GetNetworkList(
      net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES,
      base::BindOnce(&SocketGetNetworkListFunction::GotNetworkList, this));
  return RespondLater();
}

void SocketGetNetworkListFunction::GotNetworkList(
    const std::optional<net::NetworkInterfaceList>& interface_list) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (!interface_list.has_value()) {
    Respond(Error(kNetworkListError));
    return;
  }

  std::vector<api::socket::NetworkInterface> create_arg;
  create_arg.reserve(interface_list->size());
  for (const net::NetworkInterface& interface : interface_list.value()) {
    api::socket::NetworkInterface info;
    info.name = interface.name;
    info.address = interface.address.ToString();
    info.prefix_length = interface.prefix_length;
    create_arg.push_back(std::move(info));
  }

  Respond(
      ArgumentList(api::socket::GetNetworkList::Results::Create(create_arg)));
}

SocketJoinGroupFunction::SocketJoinGroupFunction() = default;

SocketJoinGroupFunction::~SocketJoinGroupFunction() = default;

ExtensionFunction::ResponseAction SocketJoinGroupFunction::Work() {
  std::optional<api::socket::JoinGroup::Params> params =
      api::socket::JoinGroup::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() != Socket::TYPE_UDP) {
    return RespondNow(ErrorWithCode(-1, kMulticastSocketTypeError));
  }

  SocketPermission::CheckParam param(
      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, kWildcardAddress,
      kWildcardPort);

  if (!CheckPermission(param)) {
    return RespondNow(ErrorWithCode(-1, kPermissionError));
  }

  static_cast<UDPSocket*>(socket)->JoinGroup(
      params->address,
      base::BindOnce(&SocketJoinGroupFunction::OnCompleted, this));
  return RespondLater();
}

void SocketJoinGroupFunction::OnCompleted(int result) {
  if (result == net::OK) {
    Respond(WithArguments(result));
  } else {
    Respond(ErrorWithCode(result, net::ErrorToString(result)));
  }
}

SocketLeaveGroupFunction::SocketLeaveGroupFunction() = default;

SocketLeaveGroupFunction::~SocketLeaveGroupFunction() = default;

ExtensionFunction::ResponseAction SocketLeaveGroupFunction::Work() {
  std::optional<api::socket::LeaveGroup::Params> params =
      api::socket::LeaveGroup::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);

  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() != Socket::TYPE_UDP) {
    return RespondNow(ErrorWithCode(-1, kMulticastSocketTypeError));
  }

  SocketPermission::CheckParam param(
      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, kWildcardAddress,
      kWildcardPort);
  if (!CheckPermission(param)) {
    return RespondNow(ErrorWithCode(-1, kPermissionError));
  }

  static_cast<UDPSocket*>(socket)->LeaveGroup(
      params->address,
      base::BindOnce(&SocketLeaveGroupFunction::OnCompleted, this));
  return RespondLater();
}

void SocketLeaveGroupFunction::OnCompleted(int result) {
  if (result == net::OK) {
    Respond(WithArguments(result));
  } else {
    Respond(ErrorWithCode(result, net::ErrorToString(result)));
  }
}

SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() =
    default;

SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() =
    default;

ExtensionFunction::ResponseAction SocketSetMulticastTimeToLiveFunction::Work() {
  std::optional<api::socket::SetMulticastTimeToLive::Params> params =
      api::socket::SetMulticastTimeToLive::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() != Socket::TYPE_UDP) {
    return RespondNow(ErrorWithCode(-1, kMulticastSocketTypeError));
  }

  int result =
      static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive(params->ttl);
  if (result == 0) {
    return RespondNow(WithArguments(result));
  } else {
    return RespondNow(ErrorWithCode(result, net::ErrorToString(result)));
  }
}

SocketSetMulticastLoopbackModeFunction::
    SocketSetMulticastLoopbackModeFunction() = default;

SocketSetMulticastLoopbackModeFunction::
    ~SocketSetMulticastLoopbackModeFunction() = default;

ExtensionFunction::ResponseAction
SocketSetMulticastLoopbackModeFunction::Work() {
  std::optional<api::socket::SetMulticastLoopbackMode::Params> params =
      api::socket::SetMulticastLoopbackMode::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() != Socket::TYPE_UDP) {
    return RespondNow(ErrorWithCode(-1, kMulticastSocketTypeError));
  }

  int result = static_cast<UDPSocket*>(socket)->SetMulticastLoopbackMode(
      params->enabled);
  if (result == 0) {
    return RespondNow(WithArguments(result));
  } else {
    return RespondNow(ErrorWithCode(result, net::ErrorToString(result)));
  }
}

SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() = default;

SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() = default;

ExtensionFunction::ResponseAction SocketGetJoinedGroupsFunction::Work() {
  std::optional<api::socket::GetJoinedGroups::Params> params =
      api::socket::GetJoinedGroups::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  Socket* socket = GetSocket(params->socket_id);
  if (!socket) {
    return RespondNow(ErrorWithCode(-1, kSocketNotFoundError));
  }

  if (socket->GetSocketType() != Socket::TYPE_UDP) {
    return RespondNow(ErrorWithCode(-1, kMulticastSocketTypeError));
  }

  SocketPermission::CheckParam param(
      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, kWildcardAddress,
      kWildcardPort);
  if (!CheckPermission(param)) {
    return RespondNow(ErrorWithCode(-1, kPermissionError));
  }

  base::Value::List values;
  auto* udp_socket = static_cast<UDPSocket*>(socket);
  for (const std::string& group : udp_socket->GetJoinedGroups()) {
    values.Append(group);
  }
  return RespondNow(WithArguments(std::move(values)));
}

SocketSecureFunction::SocketSecureFunction() = default;

SocketSecureFunction::~SocketSecureFunction() = default;

ExtensionFunction::ResponseAction SocketSecureFunction::Work() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  params_ = api::socket::Secure::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params_);

  Socket* socket = GetSocket(params_->socket_id);
  if (!socket) {
    return RespondNow(
        ErrorWithCode(net::ERR_INVALID_ARGUMENT, kSocketNotFoundError));
  }

  // Make sure that the socket is a TCP client socket.
  if (socket->GetSocketType() != Socket::TYPE_TCP) {
    return RespondNow(
        ErrorWithCode(net::ERR_INVALID_ARGUMENT, kSecureSocketTypeError));
  }

  if (!socket->IsConnected()) {
    return RespondNow(
        ErrorWithCode(net::ERR_INVALID_ARGUMENT, kSocketNotConnectedError));
  }

  TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket);
  tcp_socket->UpgradeToTLS(
      base::OptionalToPtr(params_->options),
      base::BindOnce(&SocketSecureFunction::TlsConnectDone, this));
  return RespondLater();
}

void SocketSecureFunction::TlsConnectDone(
    int result,
    mojo::PendingRemote<network::mojom::TLSClientSocket> tls_socket,
    const net::IPEndPoint& local_addr,
    const net::IPEndPoint& peer_addr,
    mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
    mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
  if (result != net::OK) {
    RemoveSocket(params_->socket_id);
    Respond(ErrorWithCode(result, net::ErrorToString(result)));
    return;
  }

  auto socket =
      std::make_unique<TLSSocket>(std::move(tls_socket), local_addr, peer_addr,
                                  std::move(receive_pipe_handle),
                                  std::move(send_pipe_handle), GetOriginId());
  ReplaceSocket(params_->socket_id, socket.release());
  Respond(WithArguments(result));
}

}  // namespace extensions
