// 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_agent_host_impl.h"

#include <map>
#include <vector>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted_memory.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/observer_list.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_view_util.h"
#include "content/browser/devtools/auction_worklet_devtools_agent_host.h"
#include "content/browser/devtools/dedicated_worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_http_handler.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_pipe_handler.h"
#include "content/browser/devtools/devtools_stream_file.h"
#include "content/browser/devtools/forwarding_agent_host.h"
#include "content/browser/devtools/mojom_devtools_agent_host.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/devtools/service_worker_devtools_agent_host.h"
#include "content/browser/devtools/service_worker_devtools_manager.h"
#include "content/browser/devtools/shared_storage_worklet_devtools_manager.h"
#include "content/browser/devtools/shared_worker_devtools_agent_host.h"
#include "content/browser/devtools/shared_worker_devtools_manager.h"
#include "content/browser/devtools/web_contents_devtools_agent_host.h"
#include "content/browser/devtools/worker_or_worklet_devtools_agent_host.h"
#include "content/browser/renderer_host/render_frame_host_impl.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_manager_delegate.h"
#include "content/public/browser/devtools_socket_factory.h"
#include "content/public/browser/mojom_devtools_agent_host_delegate.h"
#include "content/public/common/content_switches.h"
#include "services/network/public/mojom/network_context.mojom.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include <fcntl.h>
#include <io.h>
#endif

namespace content {

namespace {

typedef std::map<std::string, DevToolsAgentHostImpl*> DevToolsMap;
DevToolsMap& GetDevtoolsInstances() {
  static base::NoDestructor<DevToolsMap> instance;
  return *instance;
}

base::ObserverList<DevToolsAgentHostObserver>::Unchecked&
GetDevtoolsObservers() {
  static base::NoDestructor<
      base::ObserverList<DevToolsAgentHostObserver>::Unchecked>
      instance;
  return *instance;
}

void SetDevToolsHttpHandler(std::unique_ptr<DevToolsHttpHandler> handler) {
  static base::NoDestructor<std::unique_ptr<DevToolsHttpHandler>> instance;
  *instance = std::move(handler);
}

void SetDevToolsPipeHandler(std::unique_ptr<DevToolsPipeHandler> handler) {
  static base::NoDestructor<std::unique_ptr<DevToolsPipeHandler>> instance;
  *instance = std::move(handler);
}

#if BUILDFLAG(IS_WIN)
// Map handle to file descriptor
int AdoptHandle(const std::string& serialized_pipe, int flags) {
  // Deserialize the handle.
  // We use the fact that inherited handles in the child process have the same
  // value and access rights as in the parent process.
  // See:
  // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
  uint32_t handle_as_uint32;
  if (!base::StringToUint(serialized_pipe, &handle_as_uint32)) {
    return -1;
  }
  HANDLE handle = base::win::Uint32ToHandle(handle_as_uint32);
  if (GetFileType(handle) != FILE_TYPE_PIPE) {
    return -1;
  }
  // Map the handle to the file descriptor
  return _open_osfhandle(reinterpret_cast<intptr_t>(handle), flags);
}

// Transform the --remote-debugging-io-pipes switch value to file descriptors.
bool AdoptPipes(const std::string& io_pipes, int& read_fd, int& write_fd) {
  // The parent process is expected to serialize the input and the output pipe
  // handles as unsigned integers, concatenate them with comma and pass this
  // string to the browser via the --remote-debugging-io-pipes argument.
  std::vector<std::string> pipe_names = base::SplitString(
      io_pipes, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (pipe_names.size() != 2) {
    return false;
  }
  const std::string& in_pipe = pipe_names[0];
  const std::string& out_pipe = pipe_names[1];
  // If adoption of the read_fd fails the already adopted write_fd signalizing
  // the remote end that the session is over.
  int tmp_write_fd = AdoptHandle(out_pipe, 0);
  if (tmp_write_fd < 0) {
    return false;
  }
  int tmp_read_fd = AdoptHandle(in_pipe, _O_RDONLY);
  if (tmp_read_fd < 0) {
    _close(tmp_write_fd);
    return false;
  }
  read_fd = tmp_read_fd;
  write_fd = tmp_write_fd;
  return true;
}
#endif

}  // namespace

const char DevToolsAgentHost::kTypeTab[] = "tab";
const char DevToolsAgentHost::kTypePage[] = "page";
const char DevToolsAgentHost::kTypeFrame[] = "iframe";
const char DevToolsAgentHost::kTypeDedicatedWorker[] = "worker";
const char DevToolsAgentHost::kTypeSharedWorker[] = "shared_worker";
const char DevToolsAgentHost::kTypeServiceWorker[] = "service_worker";
const char DevToolsAgentHost::kTypeWorklet[] = "worklet";
const char DevToolsAgentHost::kTypeSharedStorageWorklet[] =
    "shared_storage_worklet";
const char DevToolsAgentHost::kTypeBrowser[] = "browser";
const char DevToolsAgentHost::kTypeGuest[] = "webview";
const char DevToolsAgentHost::kTypeOther[] = "other";
const char DevToolsAgentHost::kTypeAuctionWorklet[] = "auction_worklet";
const char DevToolsAgentHost::kTypeAssistiveTechnology[] =
    "assistive_technology";
const char DevToolsAgentHost::kTypeBrowserUI[] = "browser_ui";
int DevToolsAgentHostImpl::s_force_creation_count_ = 0;

// static
std::string DevToolsAgentHost::GetProtocolVersion() {
  // TODO(dgozman): generate this.
  return "1.3";
}

// static
bool DevToolsAgentHost::IsSupportedProtocolVersion(const std::string& version) {
  // TODO(dgozman): generate this.
  return version == "1.0" || version == "1.1" || version == "1.2" ||
         version == "1.3";
}

// static
DevToolsAgentHost::List DevToolsAgentHost::GetAll() {
  DevToolsAgentHost::List result;
  for (auto& instance : GetDevtoolsInstances()) {
    result.push_back(instance.second);
  }
  return result;
}

// static
DevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() {
  List result;
  SharedWorkerDevToolsAgentHost::List shared_list;
  SharedWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&shared_list);
  for (const auto& host : shared_list)
    result.push_back(host);

  ServiceWorkerDevToolsAgentHost::List service_list;
  ServiceWorkerDevToolsManager::GetInstance()->AddAllAgentHosts(&service_list);
  for (const auto& host : service_list)
    result.push_back(host);

  SharedStorageWorkletDevToolsManager::GetInstance()->AddAllAgentHosts(&result);

  DedicatedWorkerDevToolsAgentHost::AddAllAgentHosts(&result);
  RenderFrameDevToolsAgentHost::AddAllAgentHosts(&result);
  WebContentsDevToolsAgentHost::AddAllAgentHosts(&result);

  AuctionWorkletDevToolsAgentHostManager::GetInstance().GetAll(&result);
  MojomDevToolsAgentHost::GetAll(&result);

#if DCHECK_IS_ON()
  for (auto it : result) {
    DevToolsAgentHostImpl* host = static_cast<DevToolsAgentHostImpl*>(it.get());
    DCHECK(base::Contains(GetDevtoolsInstances(), host->id_));
  }
#endif

  return result;
}

// static
void DevToolsAgentHost::StartRemoteDebuggingServer(
    std::unique_ptr<DevToolsSocketFactory> server_socket_factory,
    const base::FilePath& active_port_output_directory,
    const base::FilePath& debug_frontend_dir) {
  DevToolsManagerDelegate* delegate =
      DevToolsManager::GetInstance()->delegate();
  CHECK(delegate);
  SetDevToolsHttpHandler(std::make_unique<DevToolsHttpHandler>(
      delegate, std::move(server_socket_factory), active_port_output_directory,
      debug_frontend_dir));
}

// static
void DevToolsAgentHost::StartRemoteDebuggingPipeHandler(
    base::OnceClosure on_disconnect) {
  int read_fd = kReadFD;
  int write_fd = kWriteFD;
#if BUILDFLAG(IS_WIN)
  std::string io_pipes =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kRemoteDebuggingIoPipes);
  if (!io_pipes.empty() && !AdoptPipes(io_pipes, read_fd, write_fd)) {
    std::move(on_disconnect).Run();
    return;
  }
#endif
  SetDevToolsPipeHandler(std::make_unique<DevToolsPipeHandler>(
      read_fd, write_fd, std::move(on_disconnect)));
}

// static
void DevToolsAgentHost::StopRemoteDebuggingServer() {
  SetDevToolsHttpHandler(nullptr);
}

// static
void DevToolsAgentHost::StopRemoteDebuggingPipeHandler() {
  SetDevToolsPipeHandler(nullptr);
}

DevToolsAgentHostImpl::DevToolsAgentHostImpl(const std::string& id)
    : id_(id), renderer_channel_(this) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

DevToolsAgentHostImpl::~DevToolsAgentHostImpl() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  NotifyDestroyed();
}

// static
scoped_refptr<DevToolsAgentHostImpl> DevToolsAgentHostImpl::GetForId(
    const std::string& id) {
  auto it = GetDevtoolsInstances().find(id);
  if (it == GetDevtoolsInstances().end())
    return nullptr;
  return it->second;
}

// static
scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForId(
    const std::string& id) {
  return DevToolsAgentHostImpl::GetForId(id);
}

// static
scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::Forward(
    const std::string& id,
    std::unique_ptr<DevToolsExternalAgentProxyDelegate> delegate) {
  scoped_refptr<DevToolsAgentHost> result = DevToolsAgentHost::GetForId(id);
  if (result)
    return result;
  return new ForwardingAgentHost(id, std::move(delegate));
}

// static
scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::CreateForMojomDelegate(
    const std::string& id,
    std::unique_ptr<MojomDevToolsAgentHostDelegate> delegate) {
  scoped_refptr<DevToolsAgentHost> result = DevToolsAgentHost::GetForId(id);
  if (result) {
    return result;
  }
  return new MojomDevToolsAgentHost(id, std::move(delegate));
}

DevToolsSession* DevToolsAgentHostImpl::SessionByClient(
    DevToolsAgentHostClient* client) {
  auto it = session_by_client_.find(client);
  return it == session_by_client_.end() ? nullptr : it->second.get();
}

bool DevToolsAgentHostImpl::AttachInternal(
    std::unique_ptr<DevToolsSession> session_owned) {
  scoped_refptr<DevToolsAgentHostImpl> protect(this);
  DevToolsSession* session = session_owned.get();
  session->SetAgentHost(this);
  if (!AttachSession(session)) {
    return false;
  }
  renderer_channel_.AttachSession(session);
  sessions_.push_back(session);
  DCHECK(!base::Contains(session_by_client_, session->GetClient()));
  session_by_client_.emplace(session->GetClient(), std::move(session_owned));
  if (sessions_.size() == 1)
    NotifyAttached();
  DevToolsManager* manager = DevToolsManager::GetInstance();
  if (manager->delegate())
    manager->delegate()->ClientAttached(session);
  return true;
}

bool DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
  if (SessionByClient(client))
    return false;
  return AttachInternal(
      std::make_unique<DevToolsSession>(client, GetSessionMode()));
}

bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
  DevToolsSession* session = SessionByClient(client);
  if (!session)
    return false;
  scoped_refptr<DevToolsAgentHostImpl> protect(this);
  DetachInternal(session);
  return true;
}

void DevToolsAgentHostImpl::DispatchProtocolMessage(
    DevToolsAgentHostClient* client,
    base::span<const uint8_t> message) {
  DevToolsSession* session = SessionByClient(client);
  if (session)
    session->DispatchProtocolMessage(message);
}

void DevToolsAgentHostImpl::DetachInternal(DevToolsSession* session) {
  std::unique_ptr<DevToolsSession> session_owned =
      std::move(session_by_client_[session->GetClient()]);
  DCHECK_EQ(session, session_owned.get());
  // Make sure we dispose session prior to reporting it to the host.
  session->Dispose();
  std::erase(sessions_, session);
  session_by_client_.erase(session->GetClient());
  DetachSession(session);
  DevToolsManager* manager = DevToolsManager::GetInstance();
  if (manager->delegate())
    manager->delegate()->ClientDetached(session);
  if (sessions_.empty()) {
    io_context_.DiscardAllStreams();
    NotifyDetached();
  }
}

bool DevToolsAgentHostImpl::IsAttached() {
  return !sessions_.empty();
}

void DevToolsAgentHostImpl::InspectElement(RenderFrameHost* frame_host,
                                           int x,
                                           int y) {}

std::string DevToolsAgentHostImpl::GetId() {
  return id_;
}

std::string DevToolsAgentHostImpl::CreateIOStreamFromData(
    scoped_refptr<base::RefCountedMemory> data) {
  scoped_refptr<DevToolsStreamFile> stream =
      DevToolsStreamFile::Create(GetIOContext(), true /* binary */);
  stream->Append(std::make_unique<std::string>(base::as_string_view(*data)));
  return stream->handle();
}

std::string DevToolsAgentHostImpl::GetParentId() {
  return std::string();
}

std::string DevToolsAgentHostImpl::GetOpenerId() {
  return std::string();
}

std::string DevToolsAgentHostImpl::GetOpenerFrameId() {
  return std::string();
}

std::string DevToolsAgentHostImpl::GetParentFrameId() {
  return std::string();
}

bool DevToolsAgentHostImpl::CanAccessOpener() {
  return false;
}

std::string DevToolsAgentHostImpl::GetDescription() {
  return std::string();
}

GURL DevToolsAgentHostImpl::GetFaviconURL() {
  return GURL();
}

std::string DevToolsAgentHostImpl::GetFrontendURL() {
  return std::string();
}

base::TimeTicks DevToolsAgentHostImpl::GetLastActivityTime() {
  return base::TimeTicks();
}

BrowserContext* DevToolsAgentHostImpl::GetBrowserContext() {
  return nullptr;
}

WebContents* DevToolsAgentHostImpl::GetWebContents() {
  return nullptr;
}

void DevToolsAgentHostImpl::DisconnectWebContents() {
}

void DevToolsAgentHostImpl::ConnectWebContents(WebContents* wc) {
}

DevToolsSession::Mode DevToolsAgentHostImpl::GetSessionMode() {
  return DevToolsSession::Mode::kDoesNotSupportTabTarget;
}

bool DevToolsAgentHostImpl::Inspect() {
  if (auto* delegate = DevToolsManager::GetInstance()->delegate()) {
    delegate->Inspect(this);
    return true;
  }
  return false;
}

scoped_refptr<DevToolsAgentHost> DevToolsAgentHostImpl::OpenDevTools(
    const content::DevToolsManagerDelegate::DevToolsOptions& devtools_options) {
  if (auto* delegate = DevToolsManager::GetInstance()->delegate()) {
    return delegate->OpenDevTools(this, devtools_options);
  }
  return nullptr;
}

void DevToolsAgentHostImpl::ForceDetachAllSessions() {
  std::ignore = ForceDetachAllSessionsImpl();
}

scoped_refptr<DevToolsAgentHost>
DevToolsAgentHostImpl::ForceDetachAllSessionsImpl() {
  scoped_refptr<DevToolsAgentHost> retain_this(this);
  while (!sessions_.empty()) {
    DevToolsAgentHostClient* client = (*sessions_.begin())->GetClient();
    DetachClient(client);
    client->AgentHostClosed(this);
  }
  return retain_this;
}

void DevToolsAgentHostImpl::MainThreadDebuggerPaused() {}
void DevToolsAgentHostImpl::MainThreadDebuggerResumed() {}

void DevToolsAgentHostImpl::ForceDetachRestrictedSessions(
    const std::vector<DevToolsSession*>& restricted_sessions) {
  scoped_refptr<DevToolsAgentHostImpl> protect(this);

  for (DevToolsSession* session : restricted_sessions) {
    DevToolsAgentHostClient* client = session->GetClient();
    DetachClient(client);
    client->AgentHostClosed(this);
  }
}

bool DevToolsAgentHostImpl::AttachSession(DevToolsSession* session) {
  return false;
}

void DevToolsAgentHostImpl::DetachSession(DevToolsSession* session) {}

void DevToolsAgentHostImpl::UpdateRendererChannel(bool force) {}

// static
void DevToolsAgentHost::DetachAllClients() {
  // Make a copy, since detaching may lead to agent destruction, which
  // removes it from the instances.
  std::vector<scoped_refptr<DevToolsAgentHostImpl>> copy;
  for (auto& instance : GetDevtoolsInstances()) {
    copy.push_back(instance.second);
  }
  for (auto& instance : copy) {
    instance->ForceDetachAllSessions();
  }
}

// static
void DevToolsAgentHost::AddObserver(DevToolsAgentHostObserver* observer) {
  if (observer->ShouldForceDevToolsAgentHostCreation()) {
    if (!DevToolsAgentHostImpl::s_force_creation_count_) {
      // Force all agent hosts when first observer is added.
      DevToolsAgentHost::GetOrCreateAll();
    }
    DevToolsAgentHostImpl::s_force_creation_count_++;
  }

  GetDevtoolsObservers().AddObserver(observer);
  for (const auto& id_host : GetDevtoolsInstances())
    observer->DevToolsAgentHostCreated(id_host.second);
}

// static
void DevToolsAgentHost::RemoveObserver(DevToolsAgentHostObserver* observer) {
  if (observer->ShouldForceDevToolsAgentHostCreation())
    DevToolsAgentHostImpl::s_force_creation_count_--;
  GetDevtoolsObservers().RemoveObserver(observer);
}

// static
bool DevToolsAgentHostImpl::ShouldForceCreation() {
  return !!s_force_creation_count_;
}

std::string DevToolsAgentHostImpl::GetSubtype() {
  return "";
}

void DevToolsAgentHostImpl::NotifyCreated() {
  DCHECK(!base::Contains(GetDevtoolsInstances(), id_));
  GetDevtoolsInstances()[id_] = this;
  for (auto& observer : GetDevtoolsObservers())
    observer.DevToolsAgentHostCreated(this);
}

void DevToolsAgentHostImpl::NotifyNavigated() {
  for (auto& observer : GetDevtoolsObservers())
    observer.DevToolsAgentHostNavigated(this);
}

void DevToolsAgentHostImpl::NotifyAttached() {
  for (auto& observer : GetDevtoolsObservers())
    observer.DevToolsAgentHostAttached(this);
}

void DevToolsAgentHostImpl::NotifyDetached() {
  for (auto& observer : GetDevtoolsObservers())
    observer.DevToolsAgentHostDetached(this);
}

void DevToolsAgentHostImpl::NotifyCrashed(base::TerminationStatus status) {
  for (auto& observer : GetDevtoolsObservers())
    observer.DevToolsAgentHostCrashed(this, status);
}

void DevToolsAgentHostImpl::NotifyDestroyed() {
  DCHECK(base::Contains(GetDevtoolsInstances(), id_));
  for (auto& observer : GetDevtoolsObservers())
    observer.DevToolsAgentHostDestroyed(this);
  GetDevtoolsInstances().erase(id_);
}

void DevToolsAgentHostImpl::ProcessHostChanged() {
  RenderProcessHost* host = GetProcessHost();
  if (!host) {
    return;
  }
  if (host->IsReady()) {
    SetProcessId(host->GetProcess().Pid());
  } else {
    host->PostTaskWhenProcessIsReady(base::BindOnce(
        &RenderFrameDevToolsAgentHost::ProcessHostChanged, this));
  }
}

void DevToolsAgentHostImpl::SetProcessId(base::ProcessId process_id) {
  CHECK_NE(process_id, base::kNullProcessId);
  if (process_id_ == process_id) {
    return;
  }
  process_id_ = process_id;
  for (auto& observer : GetDevtoolsObservers()) {
    observer.DevToolsAgentHostProcessChanged(this);
  }
}

DevToolsAgentHostImpl::NetworkLoaderFactoryParamsAndInfo::
    NetworkLoaderFactoryParamsAndInfo() = default;
DevToolsAgentHostImpl::NetworkLoaderFactoryParamsAndInfo::
    NetworkLoaderFactoryParamsAndInfo(
        url::Origin origin,
        net::SiteForCookies site_for_cookies,
        network::mojom::URLLoaderFactoryParamsPtr factory_params)
    : origin(std::move(origin)),
      site_for_cookies(std::move(site_for_cookies)),
      factory_params(std::move(factory_params)) {}
DevToolsAgentHostImpl::NetworkLoaderFactoryParamsAndInfo::
    NetworkLoaderFactoryParamsAndInfo(
        DevToolsAgentHostImpl::NetworkLoaderFactoryParamsAndInfo&&) = default;
DevToolsAgentHostImpl::NetworkLoaderFactoryParamsAndInfo::
    ~NetworkLoaderFactoryParamsAndInfo() = default;

DevToolsAgentHostImpl::NetworkLoaderFactoryParamsAndInfo
DevToolsAgentHostImpl::CreateNetworkFactoryParamsForDevTools() {
  return {};
}

RenderProcessHost* DevToolsAgentHostImpl::GetProcessHost() {
  return nullptr;
}

std::optional<network::CrossOriginEmbedderPolicy>
DevToolsAgentHostImpl::cross_origin_embedder_policy(const std::string& id) {
  return std::nullopt;
}

std::optional<network::CrossOriginOpenerPolicy>
DevToolsAgentHostImpl::cross_origin_opener_policy(const std::string& id) {
  return std::nullopt;
}

std::optional<std::vector<network::mojom::ContentSecurityPolicyHeader>>
DevToolsAgentHostImpl::content_security_policy(const std::string& id) {
  return std::nullopt;
}

protocol::TargetAutoAttacher* DevToolsAgentHostImpl::auto_attacher() {
  return nullptr;
}

}  // namespace content
