910e62b5创建于 1月15日历史提交
// 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.

#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_AGENT_HOST_IMPL_H_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_AGENT_HOST_IMPL_H_

#include <stdint.h>

#include <string>

#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/process/kill.h"
#include "base/process/process_handle.h"
#include "content/browser/devtools/devtools_io_context.h"
#include "content/browser/devtools/devtools_renderer_channel.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/common/content_export.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_manager_delegate.h"
#include "net/cookies/site_for_cookies.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
#include "services/network/public/cpp/cross_origin_opener_policy.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"

namespace content {

class BrowserContext;

namespace protocol {
class TargetAutoAttacher;
}  // namespace protocol

// Describes interface for managing devtools agents from the browser process.
class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
 public:
  // Returns DevToolsAgentHost with a given |id| or nullptr of it doesn't exist.
  static scoped_refptr<DevToolsAgentHostImpl> GetForId(const std::string& id);

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

  // DevToolsAgentHost implementation.
  bool AttachClient(DevToolsAgentHostClient* client) override;
  bool DetachClient(DevToolsAgentHostClient* client) override;
  void DispatchProtocolMessage(DevToolsAgentHostClient* client,
                               base::span<const uint8_t> message) override;
  bool IsAttached() override;
  void InspectElement(RenderFrameHost* frame_host, int x, int y) override;
  std::string GetId() override;
  std::string CreateIOStreamFromData(
      scoped_refptr<base::RefCountedMemory> data) override;
  std::string GetParentId() override;
  std::string GetOpenerId() override;
  std::string GetOpenerFrameId() override;
  std::string GetParentFrameId() override;
  bool CanAccessOpener() override;
  std::string GetDescription() override;
  GURL GetFaviconURL() override;
  std::string GetFrontendURL() override;
  base::TimeTicks GetLastActivityTime() override;
  BrowserContext* GetBrowserContext() override;
  WebContents* GetWebContents() override;
  void DisconnectWebContents() override;
  void ConnectWebContents(WebContents* wc) override;
  RenderProcessHost* GetProcessHost() override;

  struct NetworkLoaderFactoryParamsAndInfo {
    NetworkLoaderFactoryParamsAndInfo();
    NetworkLoaderFactoryParamsAndInfo(
        url::Origin,
        net::SiteForCookies,
        network::mojom::URLLoaderFactoryParamsPtr);
    NetworkLoaderFactoryParamsAndInfo(NetworkLoaderFactoryParamsAndInfo&&);
    ~NetworkLoaderFactoryParamsAndInfo();
    url::Origin origin;
    net::SiteForCookies site_for_cookies;
    network::mojom::URLLoaderFactoryParamsPtr factory_params;
  };
  // Creates network factory parameters for devtools-initiated subresource
  // requests.
  virtual NetworkLoaderFactoryParamsAndInfo
  CreateNetworkFactoryParamsForDevTools();

  virtual DevToolsSession::Mode GetSessionMode();

  bool Inspect();

  scoped_refptr<DevToolsAgentHost> OpenDevTools(
      const content::DevToolsManagerDelegate::DevToolsOptions&
          devtools_options);

  scoped_refptr<DevToolsAgentHost> GetDevToolsAgentHost();

  template <typename Handler>
  std::vector<Handler*> HandlersByName(const std::string& name) {
    std::vector<Handler*> result;
    if (sessions_.empty())
      return result;
    for (DevToolsSession* session : sessions_) {
      auto it = session->handlers().find(name);
      if (it != session->handlers().end())
        result.push_back(static_cast<Handler*>(it->second.get()));
    }
    return result;
  }

  virtual std::optional<network::CrossOriginEmbedderPolicy>
  cross_origin_embedder_policy(const std::string& id);
  virtual std::optional<network::CrossOriginOpenerPolicy>
  cross_origin_opener_policy(const std::string& id);
  virtual std::optional<
      std::vector<network::mojom::ContentSecurityPolicyHeader>>
  content_security_policy(const std::string& id);

  virtual protocol::TargetAutoAttacher* auto_attacher();
  virtual std::string GetSubtype();

  base::ProcessId GetProcessId() const { return process_id_; }

 protected:
  explicit DevToolsAgentHostImpl(const std::string& id);
  ~DevToolsAgentHostImpl() override;

  static bool ShouldForceCreation();

  // Returning |false| will block the attach.
  virtual bool AttachSession(DevToolsSession* session);
  virtual void DetachSession(DevToolsSession* session);
  virtual void UpdateRendererChannel(bool force);

  void NotifyCreated();
  void NotifyNavigated();
  void NotifyCrashed(base::TerminationStatus status);

  void SetProcessId(base::ProcessId process_id);
  void ProcessHostChanged();

  void ForceDetachRestrictedSessions(
      const std::vector<DevToolsSession*>& restricted_sessions);
  DevToolsIOContext* GetIOContext() { return &io_context_; }
  DevToolsRendererChannel* GetRendererChannel() { return &renderer_channel_; }

  const std::vector<raw_ptr<DevToolsSession, VectorExperimental>>& sessions()
      const {
    return sessions_;
  }
  // Returns refptr retaining `this`. All other references may be removed
  // at this point, so `this` will become invalid as soon as returned refptr
  // gets destroyed.
  [[nodiscard]] scoped_refptr<DevToolsAgentHost> ForceDetachAllSessionsImpl();

  // Called when the corresponding renderer process notifies that the main
  // thread debugger is paused or resumed.
  // TODO(crbug.com/40269649): Remove this method when we collect enough
  // data to understand how likely that situation could happen.
  virtual void MainThreadDebuggerPaused();
  virtual void MainThreadDebuggerResumed();

 private:
  // Note that calling this may result in the instance being deleted,
  // as instance may be owned by client sessions. This should not be
  // used by methods of derived classes, use `ForceDetachAllSessionsImpl()`
  // above instead.
  void ForceDetachAllSessions() override;

  friend class DevToolsAgentHost;  // for static methods
  friend class DevToolsSession;
  friend class DevToolsRendererChannel;

  bool AttachInternal(std::unique_ptr<DevToolsSession> session);
  void DetachInternal(DevToolsSession* session);
  void NotifyAttached();
  void NotifyDetached();
  void NotifyDestroyed();
  DevToolsSession* SessionByClient(DevToolsAgentHostClient* client);

  const std::string id_;
  std::vector<raw_ptr<DevToolsSession, VectorExperimental>> sessions_;
  base::flat_map<DevToolsAgentHostClient*, std::unique_ptr<DevToolsSession>>
      session_by_client_;
  DevToolsIOContext io_context_;
  DevToolsRendererChannel renderer_channel_;
  base::ProcessId process_id_ = base::kNullProcessId;

  static int s_force_creation_count_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_AGENT_HOST_IMPL_H_