// Copyright 2016 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/protocol/target_handler.h"

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

#include "base/base64.h"
#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/unguessable_token.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/devtools/browser_devtools_agent_host.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/target_auto_attacher.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/devtools/web_contents_devtools_agent_host.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/cors_origin_pattern_setter.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/devtools_manager_delegate.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "url/url_constants.h"

namespace content::protocol {

namespace {

constexpr net::NetworkTrafficAnnotationTag
    kSettingsProxyConfigTrafficAnnotation =
        net::DefineNetworkTrafficAnnotation("devtools_proxy_config", R"(
      semantics {
        sender: "Proxy Configuration over Developer Tools"
        description:
          "Used to fetch HTTP/HTTPS/SOCKS5/PAC proxy configuration when "
          "proxy is configured by DevTools. It is equivalent to the one "
          "configured via the --proxy-server command line flag. "
          "When proxy implies automatic configuration, it can send network "
          "requests in the scope of this annotation."
        trigger:
          "Whenever a network request is made when the system proxy settings "
          "are used, and they indicate to use a proxy server."
        data:
          "Proxy configuration."
        destination: OTHER
        destination_other: "The proxy server specified in the configuration."
      }
      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-*' switches "
          "and does not explicitly send this data over Chrome remote debugging."
        policy_exception_justification:
          "Not implemented, only used in DevTools and is behind a switch."
      })");

static const char kNotAllowedError[] = "Not allowed";
static const char kMethod[] = "method";
static const char kResumeMethod[] = "Runtime.runIfWaitingForDebugger";

static const char kInitializerScript[] = R"(
  (function() {
    const bindingName = "%s";
    const binding = window[bindingName];
    delete window[bindingName];
    if (window.self === window.top) {
      window[bindingName] = {
        onmessage: () => {},
        send: binding
      };
    }
  })();
)";

static const char kTargetNotFound[] = "No target with given id found";

std::unique_ptr<Target::TargetInfo> BuildTargetInfo(
    DevToolsAgentHost* agent_host) {
  auto* host = static_cast<DevToolsAgentHostImpl*>(agent_host);
  std::unique_ptr<Target::TargetInfo> target_info =
      Target::TargetInfo::Create()
          .SetTargetId(host->GetId())
          .SetTitle(host->GetTitle())
          .SetUrl(host->GetURL().spec())
          .SetType(host->GetType())
          .SetAttached(host->IsAttached())
          .SetCanAccessOpener(host->CanAccessOpener())
          .Build();
  if (!host->GetParentId().empty()) {
    target_info->SetParentId(host->GetParentId());
  }
  if (!host->GetOpenerId().empty()) {
    target_info->SetOpenerId(host->GetOpenerId());
  }
  if (!host->GetOpenerFrameId().empty()) {
    target_info->SetOpenerFrameId(host->GetOpenerFrameId());
  }
  if (!host->GetParentFrameId().empty()) {
    target_info->SetParentFrameId(host->GetParentFrameId());
  }
  if (host->GetBrowserContext()) {
    target_info->SetBrowserContextId(host->GetBrowserContext()->UniqueId());
  }
  std::string subtype = host->GetSubtype();
  if (!subtype.empty()) {
    target_info->SetSubtype(subtype);
  }
  return target_info;
}

static std::string TerminationStatusToString(base::TerminationStatus status) {
  switch (status) {
    case base::TERMINATION_STATUS_NORMAL_TERMINATION:
      return "normal";
    case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
      return "abnormal";
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
      return "killed";
    case base::TERMINATION_STATUS_PROCESS_CRASHED:
      return "crashed";
    case base::TERMINATION_STATUS_STILL_RUNNING:
      return "still running";
#if BUILDFLAG(IS_CHROMEOS)
    // Used for the case when oom-killer kills a process on ChromeOS.
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
      return "oom killed";
#endif
#if BUILDFLAG(IS_ANDROID)
    // On Android processes are spawned from the system Zygote and we do not get
    // the termination status.  We can't know if the termination was a crash or
    // an oom kill for sure: but we can use status of the strong process
    // bindings as a hint.
    case base::TERMINATION_STATUS_OOM_PROTECTED:
      return "oom protected";
#endif
    case base::TERMINATION_STATUS_LAUNCH_FAILED:
      return "failed to launch";
    case base::TERMINATION_STATUS_OOM:
      return "oom";
#if BUILDFLAG(IS_WIN)
    case base::TERMINATION_STATUS_INTEGRITY_FAILURE:
      return "integrity failure";
#endif
    case base::TERMINATION_STATUS_EVICTED_FOR_MEMORY:
      return "evicted for memory";
    case base::TERMINATION_STATUS_MAX_ENUM:
      break;
  }
  NOTREACHED() << "Unknown Termination Status.";
}

class BrowserToPageConnector;

// Contains permissions for the instances of BrowserConnectorHostClient.
// Currently, only permissions for
// DevToolsAgentHostClient::AllowUnsafeOperations are implemented.
struct BrowserConnectorHostClientPermissions {
  // Defines what DevToolsAgentHostClient::AllowUnsafeOperations
  // returns for BrowserConnectorHostClient instances. See
  // DevToolsAgentHostClient::AllowUnsafeOperations for more details.
  bool allow_unsafe_operations = false;
};

class BrowserToPageConnector {
 public:
  class BrowserConnectorHostClient : public DevToolsAgentHostClient {
   public:
    BrowserConnectorHostClient(
        BrowserToPageConnector* connector,
        DevToolsAgentHost* host,
        const BrowserConnectorHostClientPermissions& permissions)
        : connector_(connector), permissions_(permissions) {
      // TODO(dgozman): handle return value of AttachClient.
      host->AttachClient(this);
    }

    BrowserConnectorHostClient(const BrowserConnectorHostClient&) = delete;
    BrowserConnectorHostClient& operator=(const BrowserConnectorHostClient&) =
        delete;

    void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
                                 base::span<const uint8_t> message) override {
      connector_->DispatchProtocolMessage(agent_host, message);
    }
    void AgentHostClosed(DevToolsAgentHost* agent_host) override {
      connector_->AgentHostClosed(agent_host);
    }

    bool MayAccessAllCookies() override { return true; }

    bool AllowUnsafeOperations() override {
      return permissions_.allow_unsafe_operations;
    }

   private:
    raw_ptr<BrowserToPageConnector> connector_;
    BrowserConnectorHostClientPermissions permissions_;
  };

  BrowserToPageConnector(
      const std::string& binding_name,
      DevToolsAgentHost* page_host,
      BrowserConnectorHostClientPermissions permissions,
      std::unique_ptr<Target::Backend::ExposeDevToolsProtocolCallback> callback)
      : binding_name_(binding_name),
        page_host_(page_host),
        pending_callback_(std::move(callback)) {
    browser_host_ = BrowserDevToolsAgentHost::CreateForDiscovery();
    browser_host_client_ = std::make_unique<BrowserConnectorHostClient>(
        this, browser_host_.get(), permissions);
    page_host_client_ = std::make_unique<BrowserConnectorHostClient>(
        this, page_host_.get(), BrowserConnectorHostClientPermissions());

    SendProtocolMessageToPage("Page.enable", base::Value());
    SendProtocolMessageToPage("Runtime.enable", base::Value());

    base::DictValue add_binding_params;
    add_binding_params.Set("name", binding_name);
    // Expose to the default execution context only.
    add_binding_params.Set("executionContextName", "");
    SendProtocolMessageToPage("Runtime.addBinding",
                              base::Value(std::move(add_binding_params)));

    std::string initializer_script =
        base::StringPrintf(kInitializerScript, binding_name.c_str());

    base::DictValue params;
    params.Set("source", initializer_script);
    params.Set("worldName", "");
    // Run the initializer script immediately on the current page. This is
    // needed to expose the binding to the current page.
    params.Set("runImmediately", true);
    pending_request_id_ = SendProtocolMessageToPage("Page.addScriptToEvaluateOnNewDocument",
                              base::Value(std::move(params)));
    GetInstanceMap()[page_host_.get()].reset(this);
  }

  BrowserToPageConnector(const BrowserToPageConnector&) = delete;
  BrowserToPageConnector& operator=(const BrowserToPageConnector&) = delete;

  using BrowserToPageConnectorMap =
      base::flat_map<DevToolsAgentHost*,
                     std::unique_ptr<BrowserToPageConnector>>;
  static BrowserToPageConnectorMap& GetInstanceMap() {
    static base::NoDestructor<BrowserToPageConnectorMap> map;
    return *map;
  }

 private:
  int SendProtocolMessageToPage(const char* method, base::Value params) {
    base::DictValue message_dict;
    int id = page_message_id_++;
    message_dict.Set("id", id);
    message_dict.Set("method", method);
    message_dict.Set("params", std::move(params));
    base::Value message(std::move(message_dict));
    std::string json_message = base::WriteJson(message).value_or("");
    page_host_->DispatchProtocolMessage(page_host_client_.get(),
                                        base::as_byte_span(json_message));
    return id;
  }

  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
                               base::span<const uint8_t> message) {
    std::string_view message_sp(reinterpret_cast<const char*>(message.data()),
                                message.size());
    if (agent_host == page_host_.get()) {
      std::optional<base::DictValue> value = base::JSONReader::ReadDict(
          message_sp, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
      if (!value) {
        return;
      }

      std::optional<int> id = value->FindInt("id");
      if (id && *id == pending_request_id_ && pending_callback_) {
        pending_callback_->sendSuccess();
        pending_callback_.reset();
        pending_request_id_ = -1;
        return;
      }

      // Make sure this is a binding call.
      const std::string* method = value->FindString("method");
      if (!method || *method != "Runtime.bindingCalled") {
        return;
      }

      const base::DictValue* params = value->FindDict("params");
      if (!params) {
        return;
      }

      const std::string* name = params->FindString("name");
      if (!name || *name != binding_name_) {
        return;
      }

      const std::string* payload = params->FindString("payload");
      if (!payload) {
        return;
      }
      browser_host_->DispatchProtocolMessage(browser_host_client_.get(),
                                             base::as_byte_span(*payload));
      return;
    }
    DCHECK(agent_host == browser_host_.get());

    std::string encoded = base::Base64Encode(message_sp);
    std::string eval_code =
        "try { window." + binding_name_ + ".onmessage(atob(\"";
    std::string eval_suffix = "\")); } catch(e) { console.error(e); }";
    eval_code.reserve(eval_code.size() + encoded.size() + eval_suffix.size());
    eval_code.append(encoded);
    eval_code.append(eval_suffix);

    base::DictValue params;
    params.Set("expression", std::move(eval_code));
    SendProtocolMessageToPage("Runtime.evaluate",
                              base::Value(std::move(params)));
  }

  void AgentHostClosed(DevToolsAgentHost* agent_host) {
    if (agent_host == browser_host_.get()) {
      page_host_->DetachClient(page_host_client_.get());
    } else {
      DCHECK(agent_host == page_host_.get());
      browser_host_->DetachClient(browser_host_client_.get());
    }
    GetInstanceMap().erase(page_host_.get());
  }

  std::string binding_name_;
  scoped_refptr<DevToolsAgentHost> browser_host_;
  scoped_refptr<DevToolsAgentHost> page_host_;
  std::unique_ptr<BrowserConnectorHostClient> browser_host_client_;
  std::unique_ptr<BrowserConnectorHostClient> page_host_client_;
  int page_message_id_ = 0;
  std::unique_ptr<Target::Backend::ExposeDevToolsProtocolCallback>
      pending_callback_;
  int pending_request_id_ = -1;
};

}  // namespace

// Throttle is owned externally by the navigation subsystem.
class TargetHandler::Throttle : public NavigationThrottle {
 public:
  Throttle(const Throttle&) = delete;
  Throttle& operator=(const Throttle&) = delete;

  ~Throttle() override { CleanupPointers(); }
  TargetAutoAttacher* auto_attacher() const { return auto_attacher_; }
  void Clear();
  // NavigationThrottle implementation:
  const char* GetNameForLogging() override;

 protected:
  Throttle(base::WeakPtr<protocol::TargetHandler> target_handler,
           TargetAutoAttacher* auto_attacher,
           NavigationThrottleRegistry& registry)
      : NavigationThrottle(registry),
        target_handler_(target_handler),
        auto_attacher_(auto_attacher) {
    target_handler->throttles_.insert(this);
  }
  void SetThrottledAgentHost(DevToolsAgentHost* agent_host);

  bool is_deferring_ = false;
  scoped_refptr<DevToolsAgentHost> agent_host_;
  base::WeakPtr<protocol::TargetHandler> target_handler_;

 private:
  void CleanupPointers();
  raw_ptr<TargetAutoAttacher> auto_attacher_;
};

class TargetHandler::ResponseThrottle : public TargetHandler::Throttle {
 public:
  ResponseThrottle(base::WeakPtr<protocol::TargetHandler> target_handler,
                   TargetAutoAttacher* auto_attacher,
                   NavigationThrottleRegistry& registry)
      : Throttle(target_handler, auto_attacher, registry) {}
  ~ResponseThrottle() override = default;

 private:
  // NavigationThrottle implementation:
  ThrottleCheckResult WillProcessResponse() override { return MaybeThrottle(); }

  ThrottleCheckResult WillFailRequest() override { return MaybeThrottle(); }

  ThrottleCheckResult MaybeThrottle() {
    if (target_handler_ && auto_attacher()) {
      NavigationRequest* request = NavigationRequest::From(navigation_handle());
      const bool wait_for_debugger_on_start =
          target_handler_->ShouldWaitForDebuggerOnStart(request);
      scoped_refptr<RenderFrameDevToolsAgentHost> new_host =
          auto_attacher()->HandleNavigation(request,
                                            wait_for_debugger_on_start);
      if (new_host &&
          target_handler_->AutoAttach(auto_attacher(), new_host.get(),
                                      wait_for_debugger_on_start) &&
          wait_for_debugger_on_start) {
        SetThrottledAgentHost(new_host.get());
      } else {
        SetThrottledAgentHost(nullptr);
      }
    }
    is_deferring_ = !!agent_host_;
    return is_deferring_ ? DEFER : PROCEED;
  }
};

class TargetHandler::RequestThrottle : public TargetHandler::Throttle {
 public:
  RequestThrottle(base::WeakPtr<protocol::TargetHandler> target_handler,
                  NavigationThrottleRegistry& registry,
                  DevToolsAgentHost* throttled_agent_host)
      : Throttle(target_handler, target_handler->auto_attacher_, registry) {
    SetThrottledAgentHost(throttled_agent_host);
  }
  ~RequestThrottle() override = default;

 private:
  // NavigationThrottle implementation:
  ThrottleCheckResult WillStartRequest() override {
    is_deferring_ = !!agent_host_;
    return is_deferring_ ? DEFER : PROCEED;
  }
};

class TargetHandler::Session : public DevToolsAgentHostClient {
 public:
  static std::string Attach(TargetHandler* handler,
                            DevToolsAgentHost* agent_host,
                            bool waiting_for_debugger,
                            bool flatten_protocol) {
    std::string id = base::UnguessableToken::Create().ToString();
    // We don't support or allow the non-flattened protocol when in binary mode.
    // So, we coerce the setting to true, as the non-flattened mode is
    // deprecated anyway.
    if (handler->root_session_->GetClient()->UsesBinaryProtocol()) {
      flatten_protocol = true;
    }
    Session* session = new Session(handler, agent_host, id, flatten_protocol);
    handler->attached_sessions_[id].reset(session);
    DevToolsAgentHostImpl* agent_host_impl =
        static_cast<DevToolsAgentHostImpl*>(agent_host);
    if (flatten_protocol) {
      using Mode = DevToolsSession::Mode;
      const Mode mode =
          agent_host_impl->GetSessionMode() == Mode::kSupportsTabTarget
              ? Mode::kSupportsTabTarget
              : handler->session_mode_;

      base::OnceClosure resume_callback;
      if (waiting_for_debugger) {
        resume_callback = base::BindOnce(&Session::ResumeIfThrottled,
                                         base::Unretained(session));
      }
      DevToolsSession* devtools_session =
          handler->root_session_->AttachChildSession(
              id, agent_host_impl, session, mode, std::move(resume_callback));
      session->devtools_session_ = devtools_session;
    } else {
      agent_host_impl->AttachClient(session);
    }
    handler->frontend_->AttachedToTarget(id, BuildTargetInfo(agent_host),
                                         waiting_for_debugger);
    return id;
  }

  Session(const Session&) = delete;
  Session& operator=(const Session&) = delete;

  ~Session() override {
    if (!agent_host_) {
      return;
    }
    if (flatten_protocol_) {
      handler_->root_session_->DetachChildSession(id_);
    }
    agent_host_->DetachClient(this);
  }

  std::string GetTypeForMetrics() override { return "DevTools"; }
  std::optional<url::Origin> GetNavigationInitiatorOrigin() override {
    return GetRootClient()->GetNavigationInitiatorOrigin();
  }

  void Detach(bool host_closed) {
    handler_->frontend_->DetachedFromTarget(id_, agent_host_->GetId());
    if (flatten_protocol_) {
      handler_->root_session_->DetachChildSession(id_);
    }
    if (!host_closed) {
      agent_host_->DetachClient(this);
    }
    handler_->auto_attached_sessions_.erase(agent_host_.get());
    devtools_session_ = nullptr;
    agent_host_ = nullptr;
    handler_->attached_sessions_.erase(id_);
  }

  bool IsWaitingForDebuggerOnStart() const {
    return devtools_session_ &&
           devtools_session_->IsWaitingForDebuggerOnStart();
  }

  void ResumeSendingMessagesToAgent() const {
    if (devtools_session_) {
      devtools_session_->ResumeSendingMessagesToAgent();
    }
  }

  void SetThrottle(Throttle* throttle) { throttle_ = throttle; }
  void SetWorkerThrottle(
      scoped_refptr<DevToolsThrottleHandle> worker_throttle) {
    worker_throttle_ = std::move(worker_throttle);
  }

  void ResumeIfThrottled() {
    if (throttle_) {
      throttle_->Clear();
    }
    worker_throttle_.reset();
  }

  void SendMessageToAgentHost(base::span<const uint8_t> message) {
    // This method is only used in the non-flat mode, it's the implementation
    // for Target.SendMessageToTarget. And since the binary mode implies
    // flatten_protocol_ (we force the flag to true), we can assume in this
    // method that |message| is JSON.
    DCHECK(!flatten_protocol_);

    if (throttle_ || worker_throttle_) {
      std::optional<base::DictValue> value = base::JSONReader::ReadDict(
          std::string_view(reinterpret_cast<const char*>(message.data()),
                           message.size()),
          base::JSON_PARSE_CHROMIUM_EXTENSIONS);
      const std::string* method;
      if (value && (method = value->FindString(kMethod)) &&
          *method == kResumeMethod) {
        ResumeIfThrottled();
      }
    }

    agent_host_->DispatchProtocolMessage(this, message);
  }

  bool IsAttachedTo(const std::string& target_id) {
    return agent_host_->GetId() == target_id;
  }

  bool UsesBinaryProtocol() override {
    return handler_->root_session_->GetClient()->UsesBinaryProtocol();
  }

 private:
  friend class TargetHandler;

  Session(TargetHandler* handler,
          DevToolsAgentHost* agent_host,
          const std::string& id,
          bool flatten_protocol)
      : handler_(handler),
        agent_host_(agent_host),
        id_(id),
        flatten_protocol_(flatten_protocol) {}

  // DevToolsAgentHostClient implementation.
  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
                               base::span<const uint8_t> message) override {
    DCHECK(agent_host == agent_host_.get());
    if (flatten_protocol_) {
      // TODO(johannes): It's not clear that this check is useful, but
      // a similar check has been in the code ever since the flattened protocol
      // was introduced. Try a DCHECK instead and possibly remove the check.
      if (!handler_->root_session_->HasChildSession(id_)) {
        return;
      }
      GetRootClient()->DispatchProtocolMessage(
          handler_->root_session_->GetAgentHost(), message);
      return;
    }
    // TODO(johannes): For now, We need to copy here because
    // ReceivedMessageFromTarget is generated code and we're using const
    // std::string& for such parameters. Perhaps we should switch this to
    // std::string_view?
    std::string message_copy(message.begin(), message.end());
    handler_->frontend_->ReceivedMessageFromTarget(id_, message_copy,
                                                   agent_host_->GetId());
  }

  void AgentHostClosed(DevToolsAgentHost* agent_host) override {
    DCHECK(agent_host == agent_host_.get());
    Detach(true);
  }

  bool MayAccessAllCookies() override { return true; }

  bool MayAttachToURL(const GURL& url, bool is_webui) override {
    return GetRootClient()->MayAttachToURL(url, is_webui);
  }

  bool IsTrusted() override { return GetRootClient()->IsTrusted(); }

  bool MayReadLocalFiles() override {
    return GetRootClient()->MayReadLocalFiles();
  }

  bool MayWriteLocalFiles() override {
    return GetRootClient()->MayWriteLocalFiles();
  }

  bool AllowUnsafeOperations() override {
    return GetRootClient()->AllowUnsafeOperations();
  }

  DevToolsAgentHostClient* GetRootClient() {
    return handler_->root_session_->GetClient();
  }

  raw_ptr<TargetHandler> handler_;
  scoped_refptr<DevToolsAgentHost> agent_host_;
  std::string id_;
  bool flatten_protocol_;
  raw_ptr<DevToolsSession, DanglingUntriaged> devtools_session_ = nullptr;
  raw_ptr<Throttle> throttle_ = nullptr;
  scoped_refptr<DevToolsThrottleHandle> worker_throttle_;
  // This is needed to identify sessions associated with given
  // AutoAttacher to properly support SetAttachedTargetsOfType()
  // for a TargetHandler that serves as a client to multiple
  // different TargetAttachers. We don't want a pointer here,
  // because a session may survive the source AutoAttacher.
  uintptr_t auto_attacher_id_ = 0;
};

void TargetHandler::Throttle::CleanupPointers() {
  if (target_handler_ && agent_host_) {
    auto it = target_handler_->auto_attached_sessions_.find(agent_host_.get());
    if (it != target_handler_->auto_attached_sessions_.end()) {
      it->second->SetThrottle(nullptr);
    }
  }
  if (target_handler_) {
    target_handler_->throttles_.erase(this);
    target_handler_ = nullptr;
  }
}

void TargetHandler::Throttle::SetThrottledAgentHost(
    DevToolsAgentHost* agent_host) {
  agent_host_ = agent_host;
  if (agent_host_) {
    target_handler_->auto_attached_sessions_[agent_host_.get()]->SetThrottle(
        this);
  }
}

const char* TargetHandler::Throttle::GetNameForLogging() {
  return "DevToolsTargetNavigationThrottle";
}

void TargetHandler::Throttle::Clear() {
  CleanupPointers();
  agent_host_ = nullptr;
  auto_attacher_ = nullptr;
  if (is_deferring_) {
    is_deferring_ = false;
    Resume();
    // DO NOT ADD CODE after this. The callback above might have destroyed the
    // NavigationHandle that owns this NavigationThrottle.
  }
}

class TargetHandler::TargetFilter {
 public:
  using Filter = std::vector<std::unique_ptr<protocol::Target::FilterEntry>>;

  static std::unique_ptr<TargetFilter> CreateDefault() {
    Filter default_filter;
    // - Exclude `browser`.
    default_filter.push_back(protocol::Target::FilterEntry::Create()
                                 .SetExclude(true)
                                 .SetType(DevToolsAgentHost::kTypeBrowser)
                                 .Build());
    // - Exclude `tab`.
    default_filter.push_back(protocol::Target::FilterEntry::Create()
                                 .SetExclude(true)
                                 .SetType(DevToolsAgentHost::kTypeTab)
                                 .Build());
    // - Allow everything else.
    default_filter.push_back(protocol::Target::FilterEntry::Create().Build());
    return base::WrapUnique(new TargetFilter(std::move(default_filter)));
  }
  static std::unique_ptr<TargetFilter> Create(std::unique_ptr<Filter> filter) {
    if (!filter) {
      return CreateDefault();
    }
    return base::WrapUnique(new TargetFilter(std::move(*filter)));
  }

  bool Match(DevToolsAgentHost& host) const { return Match(host.GetType()); }

  bool Match(std::string_view type) const {
    for (const auto& entry : entries_) {
      if (!entry->HasType() || entry->GetType("") == type) {
        return !entry->GetExclude(false);
      }
    }
    return false;
  }

 private:
  explicit TargetFilter(Filter entries) : entries_(std::move(entries)) {}

  const Filter entries_;
};

TargetHandler::TargetHandler(AccessMode access_mode,
                             const std::string& owner_target_id,
                             TargetAutoAttacher* auto_attacher,
                             DevToolsSession* session)
    : DevToolsDomainHandler(Target::Metainfo::domainName),
      access_mode_(access_mode),
      owner_target_id_(owner_target_id),
      session_mode_(session->session_mode()),
      root_session_(session->GetRootSession()),
      auto_attacher_(auto_attacher) {}

TargetHandler::~TargetHandler() = default;

// static
std::vector<TargetHandler*> TargetHandler::ForAgentHost(
    DevToolsAgentHostImpl* host) {
  return host->HandlersByName<TargetHandler>(Target::Metainfo::domainName);
}

void TargetHandler::Wire(UberDispatcher* dispatcher) {
  frontend_ = std::make_unique<Target::Frontend>(dispatcher->channel());
  Target::Dispatcher::wire(dispatcher, this);
}

Response TargetHandler::Disable() {
  SetAutoAttachInternal(false, false, false, base::DoNothing());
  SetDiscoverTargets(false, {});
  hidden_target_manager_.Clear();
  auto_attached_sessions_.clear();
  attached_sessions_.clear();

  DevToolsManagerDelegate* delegate =
      DevToolsManager::GetInstance()->delegate();
  if (!delegate) {
    return Response::Success();
  }

  if (dispose_on_detach_context_ids_.size()) {
    for (auto* context : delegate->GetBrowserContexts()) {
      if (!dispose_on_detach_context_ids_.contains(context->UniqueId())) {
        continue;
      }
      delegate->DisposeBrowserContext(context, base::DoNothing());
    }
    dispose_on_detach_context_ids_.clear();
  }
  contexts_with_overridden_proxy_.clear();
  return Response::Success();
}

void TargetHandler::MaybeCreateAndAddNavigationThrottle(
    TargetAutoAttacher* auto_attacher,
    NavigationThrottleRegistry& registry) {
  DCHECK(auto_attach_ || !auto_attach_related_targets_.empty());
  auto* navigation_handle = &registry.GetNavigationHandle();
  FrameTreeNode* frame_tree_node =
      NavigationRequest::From(navigation_handle)->frame_tree_node();
  DCHECK(access_mode_ != AccessMode::kBrowser ||
         !auto_attach_related_targets_.empty() || !frame_tree_node->parent());
  // All child frames start navigating with their parent settings applied and
  // are only throttled at response where we know if they require a new host.
  // Note that fenced frames start as remote frames right away and get a RFDTAH
  // of their own, so they require a RequestThrottle rather than a Response one.
  if (!frame_tree_node->IsMainFrame()) {
    registry.AddThrottle(std::make_unique<ResponseThrottle>(
        weak_factory_.GetWeakPtr(), auto_attacher, registry));
    return;
  }
  // If we got here for main frame, it must be either browser or tab target.
  DCHECK(auto_attacher == auto_attacher_);
  DevToolsAgentHost* host =
      RenderFrameDevToolsAgentHost::GetFor(frame_tree_node);
  TargetHandler::Session* waiting_session = FindWaitingSession(host);
  if (waiting_session) {
    // RFDTAHs created during auto-attach had no renderer allocated originally,
    // and hence have messages paused, but with navigation we're supposed to
    // have a live host, so we can send messages to renderer now.
    DCHECK(frame_tree_node->current_frame_host()->IsRenderFrameLive());
    // Only resume sending messages to frame agents (i.e. skip for WebContents
    // ones).
    waiting_session->ResumeSendingMessagesToAgent();
  } else {
    // Currently, either RFDTAH or WCDTAH may be waiting for debugger (when
    // `waitForDebuggerOnStart` is honored for the Tab target, it is ignored
    // for the Page target), so in case no Page-level sessions are waiting,
    // also check the tab target.
    host = WebContentsDevToolsAgentHost::GetFor(
        WebContentsImpl::FromFrameTreeNode(frame_tree_node));
    waiting_session = FindWaitingSession(host);
    if (!waiting_session) {
      return;
    }
  }
  // window.open() navigations are throttled on the renderer side and the main
  // request will not be sent until runIfWaitingForDebugger is received from
  // the client, so there is no need to throttle the navigation in the
  // browser.
  //
  // New window navigations (such as ctrl+click) should be throttled before
  // the main request is sent to apply user agent and other overrides.
  if (frame_tree_node->opener()) {
    return;
  }
  registry.AddThrottle(std::make_unique<RequestThrottle>(
      weak_factory_.GetWeakPtr(), registry, host));
}

TargetHandler::Session* TargetHandler::FindWaitingSession(
    DevToolsAgentHost* host) {
  if (!host) {
    return nullptr;
  }
  auto it = auto_attached_sessions_.find(host);
  if (it == auto_attached_sessions_.end()) {
    return nullptr;
  }
  if (!it->second->IsWaitingForDebuggerOnStart()) {
    return nullptr;
  }
  return it->second;
}

void TargetHandler::ClearThrottles() {
  base::flat_set<raw_ptr<Throttle, CtnExperimental>> copy(throttles_);
  for (Throttle* throttle : copy) {
    throttle->Clear();
  }
  throttles_.clear();
}

void TargetHandler::SetAutoAttachInternal(bool auto_attach,
                                          bool wait_for_debugger_on_start,
                                          bool flatten,
                                          base::OnceClosure callback) {
  for (auto& entry : auto_attach_related_targets_) {
    entry.first->RemoveClient(this);
  }
  auto_attach_related_targets_.clear();
  flatten_auto_attach_ = flatten;
  if (auto_attach_) {
    auto_attacher_->RemoveClient(this);
  }
  auto_attach_ = auto_attach;
  wait_for_debugger_on_start_ = wait_for_debugger_on_start;
  if (auto_attach_) {
    auto_attacher_->AddClient(this, wait_for_debugger_on_start,
                              std::move(callback));
  } else {
    while (!auto_attached_sessions_.empty()) {
      auto_attached_sessions_.begin()->second->Detach(false);
    }
    ClearThrottles();
    auto_attach_target_filter_.reset();
    std::move(callback).Run();
  }
}

void TargetHandler::UpdateAgentHostObserver() {
  if (discover() == observing_agent_hosts_) {
    return;
  }
  observing_agent_hosts_ = discover();
  if (observing_agent_hosts_) {
    DevToolsAgentHost::AddObserver(this);
  } else {
    DevToolsAgentHost::RemoveObserver(this);
  }
}

bool TargetHandler::AutoAttach(TargetAutoAttacher* source,
                               DevToolsAgentHost* host,
                               bool waiting_for_debugger) {
  DCHECK(host);
  DCHECK(auto_attach_target_filter_);
  if (!auto_attach_target_filter_->Match(*host)) {
    return false;
  }
  if (auto_attached_sessions_.contains(host)) {
    return false;
  }
  if (!auto_attach_service_workers_ &&
      host->GetType() == DevToolsAgentHost::kTypeServiceWorker) {
    return false;
  }
  std::string session_id =
      Session::Attach(this, host, waiting_for_debugger, flatten_auto_attach_);
  Session* session = attached_sessions_[session_id].get();
  session->auto_attacher_id_ = reinterpret_cast<uintptr_t>(source);
  auto_attached_sessions_[host] = session;
  return true;
}

void TargetHandler::AutoDetach(TargetAutoAttacher* source,
                               DevToolsAgentHost* host) {
  auto it = auto_attached_sessions_.find(host);
  if (it == auto_attached_sessions_.end()) {
    return;
  }
  it->second->Detach(false);
}

void TargetHandler::SetAttachedTargetsOfType(
    TargetAutoAttacher* source,
    const base::flat_set<scoped_refptr<DevToolsAgentHost>>& new_hosts,
    const std::string& type) {
  DCHECK(!type.empty());
  auto old_sessions = auto_attached_sessions_;
  for (auto& entry : old_sessions) {
    scoped_refptr<DevToolsAgentHost> host(entry.first);
    if (host->GetType() == type &&
        entry.second->auto_attacher_id_ ==
            reinterpret_cast<uintptr_t>(source) &&
        !new_hosts.contains(host)) {
      AutoDetach(source, host.get());
    }
  }
  for (auto& host : new_hosts) {
    if (!old_sessions.contains(host.get())) {
      AutoAttach(source, host.get(), false);
    }
  }
}

void TargetHandler::TargetInfoChanged(DevToolsAgentHost* host) {
  // Only send target info for targets we reported in any way.
  if (!reported_hosts_.contains(host) &&
      auto_attached_sessions_.find(host) == auto_attached_sessions_.end()) {
    return;
  }
  frontend_->TargetInfoChanged(BuildTargetInfo(host));
}

void TargetHandler::AutoAttacherDestroyed(TargetAutoAttacher* auto_attacher) {
  auto throttles = throttles_;
  for (Throttle* throttle : throttles) {
    if (throttle->auto_attacher() == auto_attacher) {
      throttle->Clear();
    }
  }
  for (auto& entry : auto_attached_sessions_) {
    if (entry.second->auto_attacher_id_ ==
        reinterpret_cast<uintptr_t>(auto_attacher)) {
      entry.second->auto_attacher_id_ = 0;
    }
  }
  auto_attach_related_targets_.erase(auto_attacher);
}

bool TargetHandler::ShouldWaitForDebuggerOnStart(
    NavigationRequest* navigation_request) const {
  if (auto_attach_) {
    return wait_for_debugger_on_start_;
  }
  DCHECK(!auto_attach_related_targets_.empty());
  auto* host = RenderFrameDevToolsAgentHost::GetFor(
      navigation_request->frame_tree_node());
  if (!host) {
    return false;
  }
  auto it = auto_attach_related_targets_.find(host->auto_attacher());
  return it != auto_attach_related_targets_.end() && it->second;
}

bool TargetHandler::ShouldThrottlePopups() const {
  return auto_attach_;
}

void TargetHandler::DisableAutoAttachOfServiceWorkers() {
  auto_attach_service_workers_ = false;
}

Response TargetHandler::FindSession(std::optional<std::string> session_id,
                                    std::optional<std::string> target_id,
                                    Session** session) {
  *session = nullptr;
  if (session_id.has_value()) {
    auto it = attached_sessions_.find(session_id.value());
    if (it == attached_sessions_.end()) {
      return Response::InvalidParams("No session with given id");
    }
    *session = it->second.get();
    return Response::Success();
  }
  if (target_id.has_value()) {
    for (auto& it : attached_sessions_) {
      if (it.second->IsAttachedTo(target_id.value())) {
        if (*session) {
          return Response::ServerError(
              "Multiple sessions attached, specify id.");
        }
        *session = it.second.get();
      }
    }
    if (!*session) {
      return Response::InvalidParams("No session for given target id");
    }
    return Response::Success();
  }
  return Response::InvalidParams("Session id must be specified");
}

// ----------------- Protocol ----------------------

Response TargetHandler::SetDiscoverTargets(
    bool discover,
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter) {
  if (access_mode_ == AccessMode::kAutoAttachOnly) {
    return Response::ServerError(kNotAllowedError);
  }
  if (!discover && filter && !filter->empty()) {
    return Response::InvalidParams(
        "Filter should not be present with `discover` is off");
  }
  const bool old_discover = TargetHandler::discover();
  discover_target_filter_ =
      discover ? TargetFilter::Create(std::move(filter)) : nullptr;
  if (old_discover == discover) {
    // Report the newly matching targets that were not yet reported.
    if (discover) {
      for (const auto& target : DevToolsAgentHost::GetOrCreateAll()) {
        DevToolsAgentHostCreated(target.get());
      }
    }
    return Response::Success();
  }
  UpdateAgentHostObserver();
  if (!TargetHandler::discover()) {
    reported_hosts_.clear();
  }
  return Response::Success();
}

void TargetHandler::SetAutoAttach(
    bool auto_attach,
    bool wait_for_debugger_on_start,
    std::optional<bool> flatten,
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter,
    std::unique_ptr<SetAutoAttachCallback> callback) {
  if (access_mode_ == AccessMode::kBrowser && !flatten.value_or(false)) {
    callback->sendFailure(Response::InvalidParams(
        "Only flatten protocol is supported with browser level auto-attach"));
    return;
  }
  if (!auto_attach && filter && !filter->empty()) {
    callback->sendFailure(Response::InvalidParams(
        "Target filter should be empty when disabling auto-attach"));
    return;
  }
  auto_attach_target_filter_ =
      auto_attach ? TargetFilter::Create(std::move(filter)) : nullptr;
  if (auto_attach_target_filter_ && access_mode_ == AccessMode::kBrowser &&
      auto_attach_target_filter_->Match(DevToolsAgentHost::kTypeTab) &&
      auto_attach_target_filter_->Match(DevToolsAgentHost::kTypePage)) {
    callback->sendFailure(Response::InvalidParams(
        "Filter should not simultaneously allow \"tab\" and \"page\", "
        "page targets are attached via tab targets"));
    return;
  }
  SetAutoAttachInternal(
      auto_attach, wait_for_debugger_on_start, flatten.value_or(false),
      base::BindOnce(&SetAutoAttachCallback::sendSuccess, std::move(callback)));
}

void TargetHandler::AutoAttachRelated(
    const std::string& targetId,
    bool wait_for_debugger_on_start,
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter,
    std::unique_ptr<AutoAttachRelatedCallback> callback) {
  if (access_mode_ != AccessMode::kBrowser) {
    callback->sendFailure(Response::ServerError(
        "Target.autoAttachRelated is only supported on the Browser target"));
    return;
  }
  scoped_refptr<DevToolsAgentHostImpl> host =
      DevToolsAgentHostImpl::GetForId(targetId);
  if (!host) {
    callback->sendFailure(Response::InvalidParams(kTargetNotFound));
    return;
  }
  TargetAutoAttacher* auto_attacher = host->auto_attacher();
  if (!auto_attacher) {
    callback->sendFailure(
        Response::InvalidParams("Target does not support auto-attaching"));
    return;
  }
  if (auto_attach_) {
    DCHECK(auto_attach_related_targets_.empty());
    SetAutoAttachInternal(false, false, true, base::DoNothing());
  }
  flatten_auto_attach_ = true;
  auto_attach_target_filter_ = TargetFilter::Create(std::move(filter));
  AutoAttach(auto_attacher_, host.get(), false);
  auto inserted = auto_attach_related_targets_.insert(
      std::make_pair(auto_attacher, wait_for_debugger_on_start));
  if (!inserted.second) {
    auto_attacher->UpdateWaitForDebuggerOnStart(
        this, wait_for_debugger_on_start,
        base::BindOnce(&AutoAttachRelatedCallback::sendSuccess,
                       std::move(callback)));
    inserted.first->second = wait_for_debugger_on_start;
    return;
  }
  auto_attacher->AddClient(
      this, wait_for_debugger_on_start,
      base::BindOnce(&AutoAttachRelatedCallback::sendSuccess,
                     std::move(callback)));
}

Response TargetHandler::SetRemoteLocations(
    std::unique_ptr<protocol::Array<Target::RemoteLocation>>) {
  return Response::ServerError("Not supported");
}

Response TargetHandler::AttachToTarget(const std::string& target_id,
                                       std::optional<bool> flatten,
                                       std::string* out_session_id) {
  if (access_mode_ == AccessMode::kAutoAttachOnly) {
    return Response::ServerError(kNotAllowedError);
  }
  // TODO(dgozman): only allow reported hosts.
  scoped_refptr<DevToolsAgentHost> agent_host =
      DevToolsAgentHost::GetForId(target_id);
  if (!agent_host) {
    return Response::InvalidParams(kTargetNotFound);
  }
  *out_session_id =
      Session::Attach(this, agent_host.get(), false, flatten.value_or(false));
  return Response::Success();
}

Response TargetHandler::AttachToBrowserTarget(std::string* out_session_id) {
  if (access_mode_ != AccessMode::kBrowser) {
    return Response::ServerError(kNotAllowedError);
  }
  scoped_refptr<DevToolsAgentHost> agent_host =
      DevToolsAgentHost::CreateForBrowser(
          nullptr, DevToolsAgentHost::CreateServerSocketCallback());
  *out_session_id = Session::Attach(this, agent_host.get(), false, true);
  return Response::Success();
}

Response TargetHandler::DetachFromTarget(std::optional<std::string> session_id,
                                         std::optional<std::string> target_id) {
  Session* session = nullptr;
  Response response =
      FindSession(std::move(session_id), std::move(target_id), &session);
  if (!response.IsSuccess()) {
    return response;
  }
  session->Detach(false);
  return Response::Success();
}

Response TargetHandler::SendMessageToTarget(
    const std::string& message,
    std::optional<std::string> session_id,
    std::optional<std::string> target_id) {
  Session* session = nullptr;
  Response response =
      FindSession(std::move(session_id), std::move(target_id), &session);
  if (!response.IsSuccess()) {
    return response;
  }
  if (session->flatten_protocol_) {
    return Response::ServerError(
        "When using flat protocol, messages are routed to the target "
        "via the sessionId attribute.");
  }
  session->SendMessageToAgentHost(base::as_byte_span(message));
  return Response::Success();
}

Response TargetHandler::GetTargetInfo(
    std::optional<std::string> maybe_target_id,
    std::unique_ptr<Target::TargetInfo>* target_info) {
  const std::string& target_id = maybe_target_id.value_or(owner_target_id_);
  if (access_mode_ == AccessMode::kAutoAttachOnly &&
      target_id != owner_target_id_) {
    return Response::ServerError(kNotAllowedError);
  }
  // TODO(dgozman): only allow reported hosts.
  scoped_refptr<DevToolsAgentHost> agent_host(
      DevToolsAgentHost::GetForId(target_id));
  if (!agent_host) {
    return Response::InvalidParams(kTargetNotFound);
  }
  *target_info = BuildTargetInfo(agent_host.get());
  return Response::Success();
}

Response TargetHandler::ActivateTarget(const std::string& target_id) {
  if (access_mode_ == AccessMode::kAutoAttachOnly) {
    return Response::ServerError(kNotAllowedError);
  }
  // TODO(dgozman): only allow reported hosts.
  scoped_refptr<DevToolsAgentHost> agent_host(
      DevToolsAgentHost::GetForId(target_id));
  if (!agent_host) {
    return Response::InvalidParams(kTargetNotFound);
  }
  agent_host->Activate();
  return Response::Success();
}

Response TargetHandler::CloseTarget(const std::string& target_id,
                                    bool* out_success) {
  scoped_refptr<DevToolsAgentHost> agent_host =
      DevToolsAgentHost::GetForId(target_id);
  if (!agent_host) {
    return Response::InvalidParams(kTargetNotFound);
  }
  if (access_mode_ == AccessMode::kAutoAttachOnly) {
    // Only allow to close the targets that we are attached to.
    if (target_id != owner_target_id_ &&
        !auto_attached_sessions_.contains(agent_host.get())) {
      return Response::ServerError(kNotAllowedError);
    }
  }
  if (!agent_host->Close()) {
    return Response::InvalidParams("Specified target doesn't support closing");
  }
  *out_success = true;
  return Response::Success();
}

void TargetHandler::ExposeDevToolsProtocol(
    const std::string& target_id,
    std::optional<std::string> binding_name,
    std::optional<bool> inherit_permissions,
    std::unique_ptr<ExposeDevToolsProtocolCallback> callback) {
  if (access_mode_ != AccessMode::kBrowser) {
    callback->sendFailure(Response::InvalidParams(kNotAllowedError));
    return;
  }
  scoped_refptr<DevToolsAgentHost> agent_host =
      DevToolsAgentHost::GetForId(target_id);
  if (!agent_host) {
    callback->sendFailure(Response::InvalidParams(kTargetNotFound));
    return;
  }

  if (BrowserToPageConnector::GetInstanceMap()[agent_host.get()]) {
    callback->sendFailure(Response::ServerError(base::StringPrintf(
        "Target with id %s is already granted remote debugging bindings.",
        target_id.c_str())));
    return;
  }
  if (!agent_host->GetWebContents()) {
    callback->sendFailure(Response::ServerError(
        "RemoteDebuggingBinding can be granted only to page targets"));
    return;
  }

  BrowserConnectorHostClientPermissions permissions;
  if (inherit_permissions.value_or(false)) {
    permissions.allow_unsafe_operations =
        root_session_->GetClient()->AllowUnsafeOperations();
  }

  new BrowserToPageConnector(binding_name.value_or("cdp"), agent_host.get(),
                             permissions, std::move(callback));
}

Response TargetHandler::CreateTarget(
    const std::string& url,
    std::optional<int> left,
    std::optional<int> top,
    std::optional<int> width,
    std::optional<int> height,
    std::optional<std::string> window_state,
    std::optional<std::string> browser_context_id,
    std::optional<bool> enable_begin_frame_control,
    std::optional<bool> new_window,
    std::optional<bool> background,
    std::optional<bool> for_tab,
    std::optional<bool> hidden,
    std::optional<bool> focus,
    std::string* out_target_id) {
  if (access_mode_ == AccessMode::kAutoAttachOnly) {
    return Response::ServerError(kNotAllowedError);
  }

  GURL gurl(url);
  if (gurl.is_empty()) {
    gurl = GURL(url::kAboutBlankURL);
  }

  GURL inner_url = gurl;
  if (gurl.SchemeIs(content::kViewSourceScheme)) {
    inner_url = GURL(gurl.GetContent());
  }

  // chrome-untrusted:// WebUIs might perform high-privileged actions on
  // navigation, disallow navigation to them unless the client is trusted.
  if ((inner_url.SchemeIs(content::kChromeUIUntrustedScheme) ||
       inner_url.SchemeIs(content::kChromeDevToolsScheme)) &&
      !root_session_->GetClient()->IsTrusted()) {
    return Response::ServerError(
        "Navigating to a URL with a privileged scheme is not allowed");
  }

  if (hidden.value_or(false)) {
    // Hidden target can be created only when remote debugging is enabled.
    DevToolsManagerDelegate* delegate =
        DevToolsManager::GetInstance()->delegate();
    if (!delegate || delegate
                         ->RemoteDebuggingTargets(
                             DevToolsManagerDelegate::TargetType::kFrame)
                         .empty()) {
      return protocol::Response::ServerError(
          "Hidden target can be created only when remote debugging is enabled");
    }
    if (for_tab.value_or(false)) {
      return protocol::Response::InvalidParams(
          "Hidden target cannot be created for tab");
    }
    if (new_window) {
      return protocol::Response::InvalidParams(
          "Hidden target cannot be created in a new window");
    }
    if (!background.value_or(true)) {
      return protocol::Response::InvalidParams(
          "Hidden target can be created only in background");
    }

    BrowserContext* browser_context = nullptr;
    Response response = BrowserHandler::FindBrowserContext(browser_context_id,
                                                           &browser_context);
    if (!response.IsSuccess()) {
      return response;
    }

    *out_target_id =
        hidden_target_manager_.CreateHiddenTarget(gurl, browser_context);
    return Response::Success();
  }

  DevToolsManagerDelegate* delegate =
      DevToolsManager::GetInstance()->delegate();
  if (!delegate) {
    return Response::ServerError("Not supported");
  }
  DevToolsManagerDelegate::TargetType target_type =
      for_tab.value_or(session_mode_ ==
                       DevToolsSession::Mode::kSupportsTabTarget)
          ? DevToolsManagerDelegate::kTab
          : DevToolsManagerDelegate::kFrame;
  scoped_refptr<DevToolsAgentHost> agent_host =
      delegate->CreateNewTarget(gurl, target_type, new_window.value_or(false));
  if (!agent_host) {
    return Response::ServerError("Not supported");
  }
  *out_target_id = agent_host->GetId();
  return Response::Success();
}

Response TargetHandler::GetTargets(
    std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter,
    std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos) {
  if (access_mode_ == AccessMode::kAutoAttachOnly) {
    return Response::ServerError(kNotAllowedError);
  }
  std::unique_ptr<TargetFilter> passed_filter =
      filter || !discover_target_filter_
          ? TargetFilter::Create(std::move(filter))
          : nullptr;
  const TargetFilter* effective_filter =
      passed_filter ? passed_filter.get() : discover_target_filter_.get();
  DCHECK(effective_filter);
  *target_infos = std::make_unique<protocol::Array<Target::TargetInfo>>();
  for (const auto& host : DevToolsAgentHost::GetOrCreateAll()) {
    if (effective_filter->Match(*host)) {
#if !BUILDFLAG(IS_ANDROID)
      // Do not return initial WebUI as the DevTools targets.
      // TODO(crbug.com/444358999): consider adding this into the `filter` when
      // we really need to get the initial WebUI target.
      if (GetContentClient()->browser()->IsInitialWebUIURL(host->GetURL())) {
        continue;
      }
#endif  //  !BUILDFLAG(IS_ANDROID)
      (*target_infos)->emplace_back(BuildTargetInfo(host.get()));
    }
  }
  return Response::Success();
}

// -------------- DevToolsAgentHostObserver -----------------

bool TargetHandler::ShouldForceDevToolsAgentHostCreation() {
  return true;
}

void TargetHandler::DevToolsAgentHostCreated(DevToolsAgentHost* host) {
  DCHECK(discover());
  DCHECK(host);
  if (!discover_target_filter_->Match(*host)) {
    return;
  }
  // If we start discovering late, all existing agent hosts will be reported,
  // but we could have already attached to some.
  if (!reported_hosts_.contains(host)) {
    frontend_->TargetCreated(BuildTargetInfo(host));
    reported_hosts_.insert(host);
  }
}

void TargetHandler::DevToolsAgentHostNavigated(DevToolsAgentHost* host) {
  TargetInfoChanged(host);
}

void TargetHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost* host) {
  if (!reported_hosts_.contains(host)) {
    return;
  }
  frontend_->TargetDestroyed(host->GetId());
  reported_hosts_.erase(host);
}

void TargetHandler::DevToolsAgentHostAttached(DevToolsAgentHost* host) {
  TargetInfoChanged(host);
}

void TargetHandler::DevToolsAgentHostDetached(DevToolsAgentHost* host) {
  TargetInfoChanged(host);
}

void TargetHandler::DevToolsAgentHostCrashed(DevToolsAgentHost* host,
                                             base::TerminationStatus status) {
  if (!reported_hosts_.contains(host)) {
    return;
  }
  frontend_->TargetCrashed(host->GetId(), TerminationStatusToString(status),
                           host->GetWebContents()
                               ? host->GetWebContents()->GetCrashedErrorCode()
                               : 0);
}

// ----------------- More protocol methods -------------------

void TargetHandler::CreateBrowserContext(
    std::optional<bool> in_disposeOnDetach,
    std::optional<String> in_proxyServer,
    std::optional<String> in_proxyBypassList,
    std::unique_ptr<protocol::Array<String>>
        in_originsToGrantUniversalNetworkAccess,
    std::unique_ptr<CreateBrowserContextCallback> callback) {
  if (access_mode_ != AccessMode::kBrowser) {
    callback->sendFailure(Response::ServerError(kNotAllowedError));
    return;
  }
  DevToolsManagerDelegate* delegate =
      DevToolsManager::GetInstance()->delegate();
  if (!delegate) {
    callback->sendFailure(
        Response::ServerError("Browser context management is not supported."));
    return;
  }

  if (in_proxyServer.has_value()) {
    pending_proxy_config_ = net::ProxyConfig();
    pending_proxy_config_->proxy_rules().ParseFromString(
        in_proxyServer.value());
    if (in_proxyBypassList.has_value()) {
      pending_proxy_config_->proxy_rules().bypass_rules.ParseFromString(
          in_proxyBypassList.value());
    }
  }

  // Pre-process universal network access origins before actual context creation
  // in case we need to bail out with error.
  std::vector<url::Origin> originsToGrantUniversalNetworkAccess;
  if (in_originsToGrantUniversalNetworkAccess) {
    for (const auto& origin_str : *in_originsToGrantUniversalNetworkAccess) {
      GURL url(origin_str);
      url::Origin origin = url::Origin::Create(url);
      if (!url.is_valid() || origin.opaque()) {
        callback->sendFailure(
            Response::InvalidParams("Invalid origin " + origin_str));
        return;
      }
      originsToGrantUniversalNetworkAccess.push_back(std::move(origin));
    }
  }

  BrowserContext* context = delegate->CreateBrowserContext();
  if (!context) {
    callback->sendFailure(
        Response::ServerError("Failed to create browser context."));
    pending_proxy_config_.reset();
    return;
  }

  for (const auto& origin : originsToGrantUniversalNetworkAccess) {
    std::vector<network::mojom::CorsOriginPatternPtr> allow_patterns;
    allow_patterns.push_back(network::mojom::CorsOriginPattern::New());
    allow_patterns.back()->protocol = "http";
    allow_patterns.back()->priority =
        network::mojom::CorsOriginAccessMatchPriority::kMaxPriority;
    allow_patterns.push_back(network::mojom::CorsOriginPattern::New());
    allow_patterns.back()->protocol = "https";
    allow_patterns.back()->priority =
        network::mojom::CorsOriginAccessMatchPriority::kMaxPriority;

    // It's fine to not await the completion here -- this is implicitly
    // serialized with the actual URLLoaderFactory / URLLoader creation.
    CorsOriginPatternSetter::Set(
        context, origin, std::move(allow_patterns), {}, base::DoNothing());
  }

  if (pending_proxy_config_) {
    contexts_with_overridden_proxy_[context->UniqueId()] =
        std::move(*pending_proxy_config_);
    pending_proxy_config_.reset();
  }

  if (in_disposeOnDetach.value_or(false)) {
    dispose_on_detach_context_ids_.insert(context->UniqueId());
  }
  callback->sendSuccess(context->UniqueId());
}

protocol::Response TargetHandler::GetBrowserContexts(
    std::unique_ptr<protocol::Array<protocol::String>>* browser_context_ids,
    std::optional<std::string>* default_browser_context_id) {
  if (access_mode_ != AccessMode::kBrowser) {
    return Response::ServerError(kNotAllowedError);
  }
  DevToolsManagerDelegate* delegate =
      DevToolsManager::GetInstance()->delegate();
  if (!delegate) {
    return Response::ServerError(
        "Browser context management is not supported.");
  }
  std::vector<BrowserContext*> contexts =
      delegate->GetBrowserContexts();
  *browser_context_ids = std::make_unique<protocol::Array<protocol::String>>();
  for (auto* context : contexts) {
    (*browser_context_ids)->emplace_back(context->UniqueId());
  }

  BrowserContext* default_context = delegate->GetDefaultBrowserContext();
  if (default_context) {
    *default_browser_context_id = default_context->UniqueId();
  }
  return Response::Success();
}

void TargetHandler::DisposeBrowserContext(
    const std::string& context_id,
    std::unique_ptr<DisposeBrowserContextCallback> callback) {
  if (access_mode_ != AccessMode::kBrowser) {
    callback->sendFailure(Response::ServerError(kNotAllowedError));
    return;
  }
  DevToolsManagerDelegate* delegate =
      DevToolsManager::GetInstance()->delegate();
  if (!delegate) {
    callback->sendFailure(
        Response::ServerError("Browser context management is not supported."));
    return;
  }
  std::vector<BrowserContext*> contexts =
      delegate->GetBrowserContexts();
  auto context_it = std::ranges::find(contexts, context_id,
                                      &BrowserContext::UniqueId);
  if (context_it == contexts.end()) {
    callback->sendFailure(
        Response::ServerError("Failed to find context with id " + context_id));
    return;
  }
  dispose_on_detach_context_ids_.erase(context_id);
  delegate->DisposeBrowserContext(
      *context_it,
      base::BindOnce(
          [](std::unique_ptr<DisposeBrowserContextCallback> callback,
             bool success, const std::string& error) {
            if (success) {
              callback->sendSuccess();
            } else {
              callback->sendFailure(Response::ServerError(error));
            }
          },
          std::move(callback)));
}

void TargetHandler::ApplyNetworkContextParamsOverrides(
    BrowserContext* browser_context,
    network::mojom::NetworkContextParams* context_params) {
  //   Note #1: below we clear the proxy config client receiver,
  // and effectively disable proxy updates based on the OS settings.
  // This way our "initial proxy config" is not overridden by any
  // OS settings and stays the same.
  //   This relies on ApplyNetworkContextParamsOverrides() being called
  // after the client receiver was setup for the network context.
  //
  //   Note #2: Under certain conditions, storage partition is created
  // synchronously for
  // the browser context. Account for this use case.
  if (pending_proxy_config_) {
    context_params->initial_proxy_config =
        net::ProxyConfigWithAnnotation(std::move(*pending_proxy_config_),
                                       kSettingsProxyConfigTrafficAnnotation);
    context_params->proxy_config_client_receiver = mojo::NullReceiver();
    pending_proxy_config_.reset();
    return;
  }
  auto it = contexts_with_overridden_proxy_.find(browser_context->UniqueId());
  if (it != contexts_with_overridden_proxy_.end()) {
    context_params->initial_proxy_config = net::ProxyConfigWithAnnotation(
        std::move(it->second), kSettingsProxyConfigTrafficAnnotation);
    context_params->proxy_config_client_receiver = mojo::NullReceiver();
    contexts_with_overridden_proxy_.erase(browser_context->UniqueId());
  }
}

void TargetHandler::AddWorkerThrottle(
    DevToolsAgentHost* agent_host,
    scoped_refptr<DevToolsThrottleHandle> throttle_handle) {
  if (!agent_host) {
    return;
  }

  if (auto it = auto_attached_sessions_.find(agent_host);
      it != auto_attached_sessions_.end()) {
    if (it->second->IsWaitingForDebuggerOnStart()) {
      it->second->SetWorkerThrottle(std::move(throttle_handle));
    }
  }
}

Response TargetHandler::GetDevToolsTarget(
    const std::string& target_id,
    std::optional<std::string>* out_target_id) {
  if (access_mode_ != AccessMode::kBrowser) {
    return protocol::Response::ServerError(kNotAllowedError);
  }
  scoped_refptr<DevToolsAgentHostImpl> agent_host =
      DevToolsAgentHostImpl::GetForId(target_id);

  if (!agent_host) {
    return protocol::Response::InvalidParams(kTargetNotFound);
  }

  if (scoped_refptr<DevToolsAgentHost> devtools_agent_host =
          agent_host->GetDevToolsAgentHost()) {
    *out_target_id = devtools_agent_host->GetId();
  }

  return protocol::Response::Success();
}

Response TargetHandler::OpenDevTools(const std::string& target_id,
                                     std::optional<std::string> panel_id,
                                     std::string* out_target_id) {
  if (access_mode_ != AccessMode::kBrowser) {
    return protocol::Response::ServerError(kNotAllowedError);
  }
  scoped_refptr<DevToolsAgentHostImpl> agent_host =
      DevToolsAgentHostImpl::GetForId(target_id);

  if (!agent_host) {
    return protocol::Response::InvalidParams(kTargetNotFound);
  }

  scoped_refptr<DevToolsAgentHost> devtools_agent_host =
      agent_host->OpenDevTools(
          content::DevToolsManagerDelegate::DevToolsOptions(panel_id));
  if (!devtools_agent_host) {
    return protocol::Response::ServerError("Failed to create DevTools window");
  }

  *out_target_id = devtools_agent_host->GetId();

  return protocol::Response::Success();
}

}  // namespace content::protocol
