// Copyright 2018 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_renderer_channel.h"

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/safety_checks.h"
#include "content/browser/devtools/dedicated_worker_devtools_agent_host.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/worker_devtools_manager.h"
#include "content/browser/devtools/worklet_devtools_agent_host.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "third_party/blink/public/common/features.h"
#include "ui/gfx/geometry/point.h"

namespace content {

DevToolsRendererChannel::DevToolsRendererChannel(DevToolsAgentHostImpl* owner)
    : owner_(owner),
      process_id_(ChildProcessHost::kInvalidUniqueID) {}

DevToolsRendererChannel::~DevToolsRendererChannel() = default;

void DevToolsRendererChannel::SetRenderer(
    mojo::PendingRemote<blink::mojom::DevToolsAgent> agent_remote,
    mojo::PendingReceiver<blink::mojom::DevToolsAgentHost> host_receiver,
    int process_id,
    base::OnceClosure connection_error) {
  CleanupConnection();
  blink::mojom::DevToolsAgent* agent = nullptr;
  if (agent_remote.is_valid()) {
    agent_remote_.Bind(std::move(agent_remote));
    agent = agent_remote_.get();
  }
  if (connection_error)
    agent_remote_.set_disconnect_handler(std::move(connection_error));
  if (host_receiver)
    receiver_.Bind(std::move(host_receiver));
  const bool force_using_io = true;
  SetRendererInternal(agent, process_id, nullptr, force_using_io);
}

void DevToolsRendererChannel::SetRendererAssociated(
    mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgent> agent_remote,
    mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgentHost>
        host_receiver,
    int process_id,
    RenderFrameHostImpl* frame_host) {
  CleanupConnection();
  blink::mojom::DevToolsAgent* agent = nullptr;
  if (agent_remote.is_valid()) {
    associated_agent_remote_.Bind(std::move(agent_remote));
    agent = associated_agent_remote_.get();
  }
  if (host_receiver)
    associated_receiver_.Bind(std::move(host_receiver));
  const bool force_using_io = false;
  SetRendererInternal(agent, process_id, frame_host, force_using_io);
}

void DevToolsRendererChannel::CleanupConnection() {
  receiver_.reset();
  associated_receiver_.reset();
  associated_agent_remote_.reset();
  agent_remote_.reset();
}

void DevToolsRendererChannel::ForceDetachWorkerSessions() {
  for (WorkerOrWorkletDevToolsAgentHost* host : child_targets_) {
    host->ForceDetachAllSessions();
  }
}

void DevToolsRendererChannel::SetRendererInternal(
    blink::mojom::DevToolsAgent* agent,
    int process_id,
    RenderFrameHostImpl* frame_host,
    bool force_using_io) {
  ReportChildTargetsCallback();
  process_id_ = process_id;
  frame_host_ = frame_host;
  if (agent && child_target_created_callback_) {
    agent->ReportChildTargets(true /* report */, wait_for_debugger_,
                              base::DoNothing());
  }
  for (DevToolsSession* session : owner_->sessions()) {
    for (auto& pair : session->handlers())
      pair.second->SetRenderer(process_id_, frame_host_);
    session->AttachToAgent(agent, force_using_io);
  }
}

void DevToolsRendererChannel::AttachSession(DevToolsSession* session) {
  if (!agent_remote_ && !associated_agent_remote_)
    owner_->UpdateRendererChannel(true /* force */);
  for (auto& pair : session->handlers())
    pair.second->SetRenderer(process_id_, frame_host_);
  if (agent_remote_)
    session->AttachToAgent(agent_remote_.get(), true);
  else if (associated_agent_remote_)
    session->AttachToAgent(associated_agent_remote_.get(), false);
}

void DevToolsRendererChannel::InspectElement(const gfx::Point& point) {
  if (!agent_remote_ && !associated_agent_remote_)
    owner_->UpdateRendererChannel(true /* force */);
  // Previous call might update |agent_remote_| or |associated_agent_remote_|
  // via SetRenderer(), so we should check them again.
  if (agent_remote_)
    agent_remote_->InspectElement(point);
  else if (associated_agent_remote_)
    associated_agent_remote_->InspectElement(point);
}

void DevToolsRendererChannel::SetReportChildTargets(
    ChildTargetCreatedCallback report_callback,
    bool wait_for_debugger,
    base::OnceClosure completion_callback) {
  DCHECK(report_callback || !wait_for_debugger);
  ReportChildTargetsCallback();
  set_report_completion_callback_ = std::move(completion_callback);

  if (child_target_created_callback_ == report_callback &&
      wait_for_debugger_ == wait_for_debugger) {
    ReportChildTargetsCallback();
    return;
  }
  if (report_callback) {
    for (DevToolsAgentHostImpl* host : child_targets_)
      report_callback.Run(host, false /* waiting_for_debugger */);
  }
  child_target_created_callback_ = std::move(report_callback);
  wait_for_debugger_ = wait_for_debugger;
  if (agent_remote_) {
    agent_remote_->ReportChildTargets(
        !!child_target_created_callback_, wait_for_debugger_,
        base::BindOnce(&DevToolsRendererChannel::ReportChildTargetsCallback,
                       base::Unretained(this)));
  } else if (associated_agent_remote_) {
    associated_agent_remote_->ReportChildTargets(
        !!child_target_created_callback_, wait_for_debugger_,
        base::BindOnce(&DevToolsRendererChannel::ReportChildTargetsCallback,
                       base::Unretained(this)));
  } else {
    ReportChildTargetsCallback();
  }
}

void DevToolsRendererChannel::ReportChildTargetsCallback() {
  if (set_report_completion_callback_)
    std::move(set_report_completion_callback_).Run();
}

void DevToolsRendererChannel::ChildTargetCreated(
    mojo::PendingRemote<blink::mojom::DevToolsAgent> worker_devtools_agent,
    mojo::PendingReceiver<blink::mojom::DevToolsAgentHost> host_receiver,
    const GURL& url,
    const std::string& name,
    const base::UnguessableToken& devtools_worker_token,
    bool waiting_for_debugger,
    blink::mojom::DevToolsExecutionContextType context_type) {
  // This function is known to be heap allocation heavy and performance
  // critical. Extra memory safety checks can introduce regression
  // (https://crbug.com/414710225) and these are disabled here.
  base::ScopedSafetyChecksExclusion scoped_unsafe;

  RenderProcessHost* process = RenderProcessHost::FromID(process_id_);
  if (!process) {
    return;
  }

  GURL filtered_url = url;
  process->FilterURL(/*empty_allowed=*/true, &filtered_url);

  scoped_refptr<WorkerOrWorkletDevToolsAgentHost> agent_host;
  switch (context_type) {
    case blink::mojom::DevToolsExecutionContextType::kDedicatedWorker: {
      // WorkerDevToolsAgentHost for dedicated workers is already created in the
      // browser process.
      DCHECK(content::DevToolsAgentHost::GetForId(
          devtools_worker_token.ToString()));
      DedicatedWorkerDevToolsAgentHost* dedicated_worker_agent_host =
          WorkerDevToolsManager::GetInstance().GetDevToolsHostFromToken(
              devtools_worker_token);
      if (!dedicated_worker_agent_host) {
        // If `dedicated_worker_agent_host` is nullptr, we can assume that
        // `DedicatedWorkerHost` has been destructed while handling
        // `DedicatedWorker::ContinueStart`. We do not need to continue in that
        // case.
        return;
      }
      dedicated_worker_agent_host->ChildWorkerCreated(
          url, name,
          base::BindOnce(&DevToolsRendererChannel::ChildTargetDestroyed,
                         weak_factory_.GetWeakPtr()));

      agent_host = dedicated_worker_agent_host;
      break;
    }
    case blink::mojom::DevToolsExecutionContextType::kWorklet:
      if (content::DevToolsAgentHost::GetForId(
              devtools_worker_token.ToString())) {
        mojo::ReportBadMessage("Workers should have unique tokens.");
        return;
      }

      agent_host = base::MakeRefCounted<WorkletDevToolsAgentHost>(
          process_id_, filtered_url, std::move(name), devtools_worker_token,
          owner_->GetId(),
          base::BindOnce(&DevToolsRendererChannel::ChildTargetDestroyed,
                         weak_factory_.GetWeakPtr()));
      break;
  }
  agent_host->SetRenderer(process_id_, std::move(worker_devtools_agent),
                          std::move(host_receiver));

  child_targets_.insert(agent_host.get());
  if (child_target_created_callback_) {
    child_target_created_callback_.Run(agent_host.get(), waiting_for_debugger);
  }
}

void DevToolsRendererChannel::ChildTargetDestroyed(
    DevToolsAgentHostImpl* host) {
  child_targets_.erase(host);
}

void DevToolsRendererChannel::MainThreadDebuggerPaused() {
  owner_->MainThreadDebuggerPaused();
}

void DevToolsRendererChannel::MainThreadDebuggerResumed() {
  owner_->MainThreadDebuggerResumed();
}

void DevToolsRendererChannel::BringToForeground() {
  DevToolsManager* manager = DevToolsManager::GetInstance();
  if (manager->delegate()) {
    manager->delegate()->Activate(owner_);
  }
}

}  // namespace content
