blob: 7923d2ba9cf7972cec4847fde35db9f0d1c3065e [file] [log] [blame]
// 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.
#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_H_
#include <map>
#include <set>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/devtools_session.h"
#include "content/browser/devtools/devtools_throttle_handle.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/hidden_target_manager.h"
#include "content/browser/devtools/protocol/target.h"
#include "content/browser/devtools/protocol/target_auto_attacher.h"
#include "content/public/browser/devtools_agent_host_observer.h"
#include "net/proxy_resolution/proxy_config.h"
#include "services/network/public/mojom/network_context.mojom.h"
namespace content {
class DevToolsAgentHostImpl;
class DevToolsSession;
namespace protocol {
class TargetHandler : public DevToolsDomainHandler,
public Target::Backend,
public DevToolsAgentHostObserver,
public TargetAutoAttacher::Client {
public:
enum class AccessMode {
// Only setAutoAttach is supported. Any non-related target are not
// accessible.
kAutoAttachOnly,
// Standard mode of operation: both auto-attach and discovery.
kRegular,
// This mode also allows advanced method like Target.exposeDevToolsProtocol,
// which should not be exposed on a non-browser-wide connection.
kBrowser
};
TargetHandler(AccessMode access_mode,
const std::string& owner_target_id,
TargetAutoAttacher* auto_attacher,
DevToolsSession* session);
TargetHandler(const TargetHandler&) = delete;
TargetHandler& operator=(const TargetHandler&) = delete;
~TargetHandler() override;
static std::vector<TargetHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
void Wire(UberDispatcher* dispatcher) override;
Response Disable() override;
bool ShouldThrottlePopups() const;
// This is to support legacy protocol, where an autoattacher on service worker
// targets would not auto-attach service workers.
// TODO(caseq): update front-end logic and get rid of this.
void DisableAutoAttachOfServiceWorkers();
// Domain implementation.
Response SetDiscoverTargets(
bool discover,
std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter)
override;
void 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) override;
void 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) override;
Response SetRemoteLocations(
std::unique_ptr<protocol::Array<Target::RemoteLocation>>) override;
Response AttachToTarget(const std::string& target_id,
std::optional<bool> flatten,
std::string* out_session_id) override;
Response AttachToBrowserTarget(std::string* out_session_id) override;
Response DetachFromTarget(std::optional<std::string> session_id,
std::optional<std::string> target_id) override;
Response SendMessageToTarget(const std::string& message,
std::optional<std::string> session_id,
std::optional<std::string> target_id) override;
Response GetTargetInfo(
std::optional<std::string> target_id,
std::unique_ptr<Target::TargetInfo>* target_info) override;
Response ActivateTarget(const std::string& target_id) override;
Response CloseTarget(const std::string& target_id,
bool* out_success) override;
void ExposeDevToolsProtocol(
const std::string& target_id,
std::optional<std::string> binding_name,
std::optional<bool> inherit_permissions,
std::unique_ptr<ExposeDevToolsProtocolCallback> callback) override;
void 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) override;
void DisposeBrowserContext(
const std::string& context_id,
std::unique_ptr<DisposeBrowserContextCallback> callback) override;
Response GetBrowserContexts(
std::unique_ptr<protocol::Array<String>>* browser_context_ids) override;
Response 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::string* out_target_id) override;
Response GetTargets(
std::unique_ptr<protocol::Array<protocol::Target::FilterEntry>> filter,
std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos)
override;
Response OpenDevTools(const std::string& target_id,
std::string* out_target_id) override;
void ApplyNetworkContextParamsOverrides(
BrowserContext* browser_context,
network::mojom::NetworkContextParams* network_context_params);
// Adds a ServiceWorker or DedicatedWorker throttle for an auto attaching
// session. If none is known for this `agent_host`, is a no-op.
// TODO(crbug.com/40154954): support SharedWorker.
void AddWorkerThrottle(DevToolsAgentHost* agent_host,
scoped_refptr<DevToolsThrottleHandle> throttle_handle);
private:
class Session;
class Throttle;
class RequestThrottle;
class ResponseThrottle;
class TargetFilter;
// TargetAutoAttacher::Delegate implementation.
bool AutoAttach(TargetAutoAttacher* source,
DevToolsAgentHost* host,
bool waiting_for_debugger) override;
void AutoDetach(TargetAutoAttacher* source, DevToolsAgentHost* host) override;
void SetAttachedTargetsOfType(
TargetAutoAttacher* source,
const base::flat_set<scoped_refptr<DevToolsAgentHost>>& new_hosts,
const std::string& type) override;
void MaybeCreateAndAddNavigationThrottle(
TargetAutoAttacher* auto_attacher,
NavigationThrottleRegistry& registry) override;
void TargetInfoChanged(DevToolsAgentHost* host) override;
void AutoAttacherDestroyed(TargetAutoAttacher* auto_attacher) override;
bool ShouldWaitForDebuggerOnStart(
NavigationRequest* navigation_request) const;
Response FindSession(std::optional<std::string> session_id,
std::optional<std::string> target_id,
Session** session);
void ClearThrottles();
void SetAutoAttachInternal(bool auto_attach,
bool wait_for_debugger_on_start,
bool flatten,
base::OnceClosure callback);
void UpdateAgentHostObserver();
// DevToolsAgentHostObserver implementation.
bool ShouldForceDevToolsAgentHostCreation() override;
void DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostNavigated(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostAttached(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostDetached(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostCrashed(DevToolsAgentHost* agent_host,
base::TerminationStatus status) override;
bool discover() const { return !!discover_target_filter_; }
Session* FindWaitingSession(DevToolsAgentHost* host);
const AccessMode access_mode_;
const std::string owner_target_id_;
const DevToolsSession::Mode session_mode_;
const raw_ptr<DevToolsSession> root_session_;
const raw_ptr<TargetAutoAttacher> auto_attacher_;
std::unique_ptr<Target::Frontend> frontend_;
bool flatten_auto_attach_ = false;
bool auto_attach_ = false;
// The below is set iff (auto_attach_ ||
// !auto_attach_related_targets_.empty())
std::unique_ptr<TargetFilter> auto_attach_target_filter_;
bool wait_for_debugger_on_start_ = false;
std::map<DevToolsAgentHost*, raw_ptr<Session, CtnExperimental>>
auto_attached_sessions_;
base::flat_map<TargetAutoAttacher*, bool /* wait_for_debugger_on_start */>
auto_attach_related_targets_;
bool auto_attach_service_workers_ = true;
std::unique_ptr<TargetFilter> discover_target_filter_;
bool observing_agent_hosts_ = false;
std::map<std::string, std::unique_ptr<Session>> attached_sessions_;
std::set<raw_ptr<DevToolsAgentHost, SetExperimental>> reported_hosts_;
base::flat_set<std::string> dispose_on_detach_context_ids_;
base::flat_map<std::string, net::ProxyConfig> contexts_with_overridden_proxy_;
base::flat_set<raw_ptr<Throttle, CtnExperimental>> throttles_;
std::optional<net::ProxyConfig> pending_proxy_config_;
HiddenTargetManager hidden_target_manager_;
base::WeakPtrFactory<TargetHandler> weak_factory_{this};
};
} // namespace protocol
} // namespace content
#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_H_