Commit 22e08cb7 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

[DevTools] Split DevToolsAgent out of WebDevToolsAgentImpl

This is an implementation of mojom::DevToolsAgent which will
be reused for workers in WorkerInspectorController.

After switching workers to mojo, we'll merge InspectorSession
into DevToolsAgent::Session.

Bug: 775132
Change-Id: I180e62df147b6f256e09eeb1a44779151920471a
Reviewed-on: https://chromium-review.googlesource.com/c/1258209
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596075}
parent c683465b
......@@ -34,7 +34,6 @@
#include <memory>
#include <utility>
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_float_rect.h"
......@@ -55,6 +54,7 @@
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h"
#include "third_party/blink/renderer/core/inspector/devtools_agent.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/inspector/inspector_animation_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h"
......@@ -185,295 +185,113 @@ class ClientMessageLoopAdapter : public MainThreadDebugger::ClientMessageLoop {
ClientMessageLoopAdapter* ClientMessageLoopAdapter::instance_ = nullptr;
// --------- WebDevToolsAgentImpl::Session -------------
class WebDevToolsAgentImpl::Session : public GarbageCollectedFinalized<Session>,
public mojom::blink::DevToolsSession,
public InspectorSession::Client {
public:
Session(WebDevToolsAgentImpl*,
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info,
mojom::blink::DevToolsSessionAssociatedRequest main_request,
mojom::blink::DevToolsSessionRequest io_request,
mojom::blink::DevToolsSessionStatePtr reattach_session_state);
~Session() override;
virtual void Trace(blink::Visitor*);
void Detach();
InspectorSession* inspector_session() { return inspector_session_.Get(); }
InspectorNetworkAgent* network_agent() { return network_agent_.Get(); }
InspectorPageAgent* page_agent() { return page_agent_.Get(); }
InspectorOverlayAgent* overlay_agent() { return overlay_agent_.Get(); }
private:
class IOSession;
// mojom::blink::DevToolsSession implementation.
void DispatchProtocolCommand(int call_id,
const String& method,
const String& message) override;
// InspectorSession::Client implementation.
void SendProtocolResponse(
int session_id,
int call_id,
const String& response,
mojom::blink::DevToolsSessionStatePtr updates) override;
void SendProtocolNotification(
int session_id,
const String& message,
mojom::blink::DevToolsSessionStatePtr updates) override;
void DispatchProtocolCommandInternal(int call_id,
const String& method,
const String& message);
void InitializeInspectorSession(
mojom::blink::DevToolsSessionStatePtr reattach_session_state);
Member<WebDevToolsAgentImpl> agent_;
Member<WebLocalFrameImpl> frame_;
mojo::AssociatedBinding<mojom::blink::DevToolsSession> binding_;
mojom::blink::DevToolsSessionHostAssociatedPtr host_ptr_;
IOSession* io_session_;
Member<InspectorSession> inspector_session_;
Member<InspectorNetworkAgent> network_agent_;
Member<InspectorPageAgent> page_agent_;
Member<InspectorOverlayAgent> overlay_agent_;
bool detached_ = false;
DISALLOW_COPY_AND_ASSIGN(Session);
};
// Created and stored in unique_ptr on UI.
// Binds request, receives messages and destroys on IO.
class WebDevToolsAgentImpl::Session::IOSession
: public mojom::blink::DevToolsSession {
public:
IOSession(scoped_refptr<base::SingleThreadTaskRunner> session_task_runner,
scoped_refptr<InspectorTaskRunner> inspector_task_runner,
CrossThreadWeakPersistent<WebDevToolsAgentImpl::Session> session,
mojom::blink::DevToolsSessionRequest request)
: session_task_runner_(session_task_runner),
inspector_task_runner_(inspector_task_runner),
session_(std::move(session)),
binding_(this) {
session_task_runner->PostTask(
FROM_HERE, ConvertToBaseCallback(CrossThreadBind(
&IOSession::BindInterface, CrossThreadUnretained(this),
WTF::Passed(std::move(request)))));
}
~IOSession() override {}
void BindInterface(mojom::blink::DevToolsSessionRequest request) {
binding_.Bind(std::move(request));
}
void DeleteSoon() { session_task_runner_->DeleteSoon(FROM_HERE, this); }
// mojom::blink::DevToolsSession implementation.
void DispatchProtocolCommand(int call_id,
const String& method,
const String& message) override {
DCHECK(InspectorSession::ShouldInterruptForMethod(method));
// Crash renderer.
if (method == "Page.crash")
CHECK(false);
inspector_task_runner_->AppendTask(
CrossThreadBind(&WebDevToolsAgentImpl::Session::DispatchProtocolCommand,
session_, call_id, method, message));
}
private:
scoped_refptr<base::SingleThreadTaskRunner> session_task_runner_;
scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
CrossThreadWeakPersistent<WebDevToolsAgentImpl::Session> session_;
mojo::Binding<mojom::blink::DevToolsSession> binding_;
DISALLOW_COPY_AND_ASSIGN(IOSession);
};
WebDevToolsAgentImpl::Session::Session(
WebDevToolsAgentImpl* agent,
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info,
mojom::blink::DevToolsSessionAssociatedRequest request,
mojom::blink::DevToolsSessionRequest io_request,
mojom::blink::DevToolsSessionStatePtr reattach_session_state)
: agent_(agent),
frame_(agent->web_local_frame_impl_),
binding_(this, std::move(request)) {
io_session_ =
new IOSession(Platform::Current()->GetIOTaskRunner(),
frame_->GetFrame()->GetInspectorTaskRunner(),
WrapCrossThreadWeakPersistent(this), std::move(io_request));
host_ptr_.Bind(std::move(host_ptr_info));
host_ptr_.set_connection_error_handler(WTF::Bind(
&WebDevToolsAgentImpl::Session::Detach, WrapWeakPersistent(this)));
InitializeInspectorSession(std::move(reattach_session_state));
}
WebDevToolsAgentImpl::Session::~Session() {
DCHECK(detached_);
}
void WebDevToolsAgentImpl::Session::Trace(blink::Visitor* visitor) {
visitor->Trace(agent_);
visitor->Trace(frame_);
visitor->Trace(inspector_session_);
visitor->Trace(network_agent_);
visitor->Trace(page_agent_);
visitor->Trace(overlay_agent_);
}
void WebDevToolsAgentImpl::Session::Detach() {
DCHECK(!detached_);
detached_ = true;
agent_->DetachSession(this);
binding_.Close();
host_ptr_.reset();
io_session_->DeleteSoon();
io_session_ = nullptr;
inspector_session_->Dispose();
}
void WebDevToolsAgentImpl::Session::SendProtocolResponse(
int session_id,
int call_id,
const String& response,
mojom::blink::DevToolsSessionStatePtr updates) {
if (detached_)
return;
// Make tests more predictable by flushing all sessions before sending
// protocol response in any of them.
if (LayoutTestSupport::IsRunningLayoutTest())
agent_->FlushProtocolNotifications();
host_ptr_->DispatchProtocolResponse(response, call_id, std::move(updates));
}
void WebDevToolsAgentImpl::Session::SendProtocolNotification(
int session_id,
const String& message,
mojom::blink::DevToolsSessionStatePtr updates) {
host_ptr_->DispatchProtocolNotification(message, std::move(updates));
}
void WebDevToolsAgentImpl::Session::DispatchProtocolCommand(
int call_id,
const String& method,
const String& message) {
// IOSession does not provide ordering guarantees relative to
// Session, so a command may come to IOSession after Session is detached,
// and get posted to main thread to this method.
//
// At the same time, Session may not be garbage collected yet
// (even though already detached), and CrossThreadWeakPersistent<Session>
// will still be valid.
//
// Both these factors combined may lead to this method being called after
// detach, so we have to check a flag here.
if (detached_)
return;
inspector_session_->DispatchProtocolMessage(call_id, method, message);
}
void WebDevToolsAgentImpl::Session::InitializeInspectorSession(
InspectorSession* WebDevToolsAgentImpl::AttachSession(
InspectorSession::Client* session_client,
mojom::blink::DevToolsSessionStatePtr reattach_session_state) {
if (!sessions_.size())
Platform::Current()->CurrentThread()->AddTaskObserver(this);
ClientMessageLoopAdapter::EnsureMainThreadDebuggerCreated();
MainThreadDebugger* main_thread_debugger = MainThreadDebugger::Instance();
v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
InspectedFrames* inspected_frames = agent_->inspected_frames_.Get();
InspectedFrames* inspected_frames = inspected_frames_.Get();
bool should_reattach = !reattach_session_state.is_null();
inspector_session_ = new InspectorSession(
this, agent_->probe_sink_.Get(), 0,
InspectorSession* inspector_session = new InspectorSession(
session_client, probe_sink_.Get(), 0,
main_thread_debugger->GetV8Inspector(),
main_thread_debugger->ContextGroupId(inspected_frames->Root()),
std::move(reattach_session_state));
InspectorDOMAgent* dom_agent = new InspectorDOMAgent(
isolate, inspected_frames, inspector_session_->V8Session());
inspector_session_->Append(dom_agent);
isolate, inspected_frames, inspector_session->V8Session());
inspector_session->Append(dom_agent);
InspectorLayerTreeAgent* layer_tree_agent =
InspectorLayerTreeAgent::Create(inspected_frames, agent_);
inspector_session_->Append(layer_tree_agent);
InspectorLayerTreeAgent::Create(inspected_frames, this);
inspector_session->Append(layer_tree_agent);
network_agent_ = new InspectorNetworkAgent(inspected_frames, nullptr,
inspector_session_->V8Session());
inspector_session_->Append(network_agent_);
InspectorNetworkAgent* network_agent = new InspectorNetworkAgent(
inspected_frames, nullptr, inspector_session->V8Session());
inspector_session->Append(network_agent);
InspectorCSSAgent* css_agent =
InspectorCSSAgent::Create(dom_agent, inspected_frames, network_agent_,
agent_->resource_content_loader_.Get(),
agent_->resource_container_.Get());
inspector_session_->Append(css_agent);
InspectorCSSAgent* css_agent = InspectorCSSAgent::Create(
dom_agent, inspected_frames, network_agent,
resource_content_loader_.Get(), resource_container_.Get());
inspector_session->Append(css_agent);
InspectorDOMDebuggerAgent* dom_debugger_agent = new InspectorDOMDebuggerAgent(
isolate, dom_agent, inspector_session_->V8Session());
inspector_session_->Append(dom_debugger_agent);
isolate, dom_agent, inspector_session->V8Session());
inspector_session->Append(dom_debugger_agent);
inspector_session_->Append(
inspector_session->Append(
InspectorDOMSnapshotAgent::Create(inspected_frames, dom_debugger_agent));
inspector_session_->Append(new InspectorAnimationAgent(
inspected_frames, css_agent, inspector_session_->V8Session()));
inspector_session->Append(new InspectorAnimationAgent(
inspected_frames, css_agent, inspector_session->V8Session()));
inspector_session_->Append(InspectorMemoryAgent::Create(inspected_frames));
inspector_session->Append(InspectorMemoryAgent::Create(inspected_frames));
inspector_session_->Append(
inspector_session->Append(
InspectorPerformanceAgent::Create(inspected_frames));
inspector_session_->Append(
inspector_session->Append(
InspectorApplicationCacheAgent::Create(inspected_frames));
inspector_session_->Append(
inspector_session->Append(
new InspectorWorkerAgent(inspected_frames, nullptr));
page_agent_ = InspectorPageAgent::Create(
inspected_frames, agent_, agent_->resource_content_loader_.Get(),
inspector_session_->V8Session());
inspector_session_->Append(page_agent_);
InspectorPageAgent* page_agent = InspectorPageAgent::Create(
inspected_frames, this, resource_content_loader_.Get(),
inspector_session->V8Session());
inspector_session->Append(page_agent);
inspector_session_->Append(new InspectorLogAgent(
inspector_session->Append(new InspectorLogAgent(
&inspected_frames->Root()->GetPage()->GetConsoleMessageStorage(),
inspected_frames->Root()->GetPerformanceMonitor(),
inspector_session_->V8Session()));
inspector_session->V8Session()));
overlay_agent_ =
new InspectorOverlayAgent(frame_.Get(), inspected_frames,
inspector_session_->V8Session(), dom_agent);
inspector_session_->Append(overlay_agent_);
InspectorOverlayAgent* overlay_agent =
new InspectorOverlayAgent(web_local_frame_impl_.Get(), inspected_frames,
inspector_session->V8Session(), dom_agent);
inspector_session->Append(overlay_agent);
inspector_session_->Append(
new InspectorIOAgent(isolate, inspector_session_->V8Session()));
inspector_session->Append(
new InspectorIOAgent(isolate, inspector_session->V8Session()));
inspector_session_->Append(new InspectorAuditsAgent(network_agent_));
inspector_session->Append(new InspectorAuditsAgent(network_agent));
// TODO(dgozman): we should actually pass the view instead of frame, but
// during remote->local transition we cannot access mainFrameImpl() yet, so
// we have to store the frame which will become the main frame later.
inspector_session_->Append(new InspectorEmulationAgent(frame_.Get()));
inspector_session->Append(
new InspectorEmulationAgent(web_local_frame_impl_.Get()));
inspector_session_->Append(new InspectorTestingAgent(inspected_frames));
inspector_session->Append(new InspectorTestingAgent(inspected_frames));
// Call session init callbacks registered from higher layers
CoreInitializer::GetInstance().InitInspectorAgentSession(
inspector_session_, agent_->include_view_agents_, dom_agent,
inspected_frames, frame_->ViewImpl()->GetPage());
inspector_session, include_view_agents_, dom_agent, inspected_frames,
web_local_frame_impl_->ViewImpl()->GetPage());
if (should_reattach) {
inspector_session_->Restore();
if (agent_->worker_client_)
agent_->worker_client_->ResumeStartup();
inspector_session->Restore();
if (worker_client_)
worker_client_->ResumeStartup();
}
if (node_to_inspect_) {
overlay_agent->Inspect(node_to_inspect_);
node_to_inspect_ = nullptr;
}
}
// --------- WebDevToolsAgentImpl -------------
sessions_.insert(inspector_session);
network_agents_.insert(inspector_session, network_agent);
page_agents_.insert(inspector_session, page_agent);
overlay_agents_.insert(inspector_session, overlay_agent);
return inspector_session;
}
// static
WebDevToolsAgentImpl* WebDevToolsAgentImpl::CreateForFrame(
......@@ -492,8 +310,7 @@ WebDevToolsAgentImpl::WebDevToolsAgentImpl(
WebLocalFrameImpl* web_local_frame_impl,
bool include_view_agents,
WorkerClient* worker_client)
: binding_(this),
worker_client_(worker_client),
: worker_client_(worker_client),
web_local_frame_impl_(web_local_frame_impl),
probe_sink_(web_local_frame_impl_->GetFrame()->GetProbeSink()),
resource_content_loader_(InspectorResourceContentLoader::Create(
......@@ -502,7 +319,9 @@ WebDevToolsAgentImpl::WebDevToolsAgentImpl(
resource_container_(new InspectorResourceContainer(inspected_frames_)),
include_view_agents_(include_view_agents) {
DCHECK(IsMainThread());
DCHECK(web_local_frame_impl_->GetFrame());
agent_ = new DevToolsAgent(
this, web_local_frame_impl_->GetFrame()->GetInspectorTaskRunner(),
Platform::Current()->GetIOTaskRunner());
}
WebDevToolsAgentImpl::~WebDevToolsAgentImpl() {
......@@ -510,7 +329,11 @@ WebDevToolsAgentImpl::~WebDevToolsAgentImpl() {
}
void WebDevToolsAgentImpl::Trace(blink::Visitor* visitor) {
visitor->Trace(agent_);
visitor->Trace(sessions_);
visitor->Trace(network_agents_);
visitor->Trace(page_agents_);
visitor->Trace(overlay_agents_);
visitor->Trace(web_local_frame_impl_);
visitor->Trace(probe_sink_);
visitor->Trace(resource_content_loader_);
......@@ -522,36 +345,23 @@ void WebDevToolsAgentImpl::Trace(blink::Visitor* visitor) {
void WebDevToolsAgentImpl::WillBeDestroyed() {
DCHECK(web_local_frame_impl_->GetFrame());
DCHECK(inspected_frames_->Root()->View());
HeapHashSet<Member<Session>> copy(sessions_);
for (auto& session : copy)
session->Detach();
agent_->WillBeDestroyed();
resource_content_loader_->Dispose();
worker_client_ = nullptr;
binding_.Close();
}
void WebDevToolsAgentImpl::BindRequest(
mojom::blink::DevToolsAgentAssociatedRequest request) {
binding_.Bind(std::move(request));
agent_->BindRequest(std::move(request));
}
void WebDevToolsAgentImpl::AttachDevToolsSession(
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host,
mojom::blink::DevToolsSessionAssociatedRequest session_request,
mojom::blink::DevToolsSessionRequest io_session_request,
mojom::blink::DevToolsSessionStatePtr reattach_session_state) {
void WebDevToolsAgentImpl::DetachSession(InspectorSession* session) {
network_agents_.erase(session);
page_agents_.erase(session);
overlay_agents_.erase(session);
sessions_.erase(session);
if (!sessions_.size())
Platform::Current()->CurrentThread()->AddTaskObserver(this);
Session* session = new Session(
this, std::move(host), std::move(session_request),
std::move(io_session_request), std::move(reattach_session_state));
sessions_.insert(session);
if (node_to_inspect_) {
session->overlay_agent()->Inspect(node_to_inspect_);
node_to_inspect_ = nullptr;
}
Platform::Current()->CurrentThread()->RemoveTaskObserver(this);
}
void WebDevToolsAgentImpl::InspectElement(const WebPoint& point_in_local_root) {
......@@ -589,50 +399,44 @@ void WebDevToolsAgentImpl::InspectElement(const WebPoint& point_in_local_root) {
if (!node && web_local_frame_impl_->GetFrame()->GetDocument())
node = web_local_frame_impl_->GetFrame()->GetDocument()->documentElement();
if (!sessions_.IsEmpty()) {
for (auto& session : sessions_)
session->overlay_agent()->Inspect(node);
if (!overlay_agents_.IsEmpty()) {
for (auto& it : overlay_agents_)
it.value->Inspect(node);
} else {
node_to_inspect_ = node;
}
}
void WebDevToolsAgentImpl::DetachSession(Session* session) {
sessions_.erase(session);
if (!sessions_.size())
Platform::Current()->CurrentThread()->RemoveTaskObserver(this);
}
void WebDevToolsAgentImpl::DidCommitLoadForLocalFrame(LocalFrame* frame) {
resource_container_->DidCommitLoadForLocalFrame(frame);
resource_content_loader_->DidCommitLoadForLocalFrame(frame);
for (auto& session : sessions_)
session->inspector_session()->DidCommitLoadForLocalFrame(frame);
session->DidCommitLoadForLocalFrame(frame);
}
void WebDevToolsAgentImpl::DidStartProvisionalLoad(LocalFrame* frame) {
if (inspected_frames_->Root() == frame) {
for (auto& session : sessions_)
session->inspector_session()->V8Session()->resume();
session->V8Session()->resume();
}
}
bool WebDevToolsAgentImpl::ScreencastEnabled() {
for (auto& session : sessions_) {
if (session->page_agent()->ScreencastEnabled())
for (auto& it : page_agents_) {
if (it.value->ScreencastEnabled())
return true;
}
return false;
}
void WebDevToolsAgentImpl::PageLayoutInvalidated(bool resized) {
for (auto& session : sessions_)
session->overlay_agent()->PageLayoutInvalidated(resized);
for (auto& it : overlay_agents_)
it.value->PageLayoutInvalidated(resized);
}
bool WebDevToolsAgentImpl::IsInspectorLayer(GraphicsLayer* layer) {
for (auto& session : sessions_) {
if (session->overlay_agent()->IsInspectorLayer(layer))
for (auto& it : overlay_agents_) {
if (it.value->IsInspectorLayer(layer))
return true;
}
return false;
......@@ -640,32 +444,32 @@ bool WebDevToolsAgentImpl::IsInspectorLayer(GraphicsLayer* layer) {
String WebDevToolsAgentImpl::EvaluateInOverlayForTesting(const String& script) {
String result;
for (auto& session : sessions_)
result = session->overlay_agent()->EvaluateInOverlayForTest(script);
for (auto& it : overlay_agents_)
result = it.value->EvaluateInOverlayForTest(script);
return result;
}
void WebDevToolsAgentImpl::UpdateOverlays() {
for (auto& session : sessions_)
session->overlay_agent()->UpdateAllOverlayLifecyclePhases();
for (auto& it : overlay_agents_)
it.value->UpdateAllOverlayLifecyclePhases();
}
void WebDevToolsAgentImpl::DispatchBufferedTouchEvents() {
for (auto& session : sessions_)
session->overlay_agent()->DispatchBufferedTouchEvents();
for (auto& it : overlay_agents_)
it.value->DispatchBufferedTouchEvents();
}
bool WebDevToolsAgentImpl::HandleInputEvent(const WebInputEvent& event) {
for (auto& session : sessions_) {
if (session->overlay_agent()->HandleInputEvent(event))
for (auto& it : overlay_agents_) {
if (it.value->HandleInputEvent(event))
return true;
}
return false;
}
String WebDevToolsAgentImpl::NavigationInitiatorInfo(LocalFrame* frame) {
for (auto& session : sessions_) {
String initiator = session->network_agent()->NavigationInitiatorInfo(frame);
for (auto& it : network_agents_) {
String initiator = it.value->NavigationInitiatorInfo(frame);
if (!initiator.IsNull())
return initiator;
}
......@@ -673,8 +477,7 @@ String WebDevToolsAgentImpl::NavigationInitiatorInfo(LocalFrame* frame) {
}
void WebDevToolsAgentImpl::FlushProtocolNotifications() {
for (auto& session : sessions_)
session->inspector_session()->flushProtocolNotifications();
agent_->FlushProtocolNotifications();
}
void WebDevToolsAgentImpl::WillProcessTask() {
......
......@@ -33,11 +33,11 @@
#include <memory>
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/web/devtools_agent.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/inspector/devtools_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_page_agent.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
......@@ -48,6 +48,8 @@ namespace blink {
class ClientMessageLoopAdapter;
class GraphicsLayer;
class InspectedFrames;
class InspectorNetworkAgent;
class InspectorOverlayAgent;
class InspectorResourceContainer;
class InspectorResourceContentLoader;
class LocalFrame;
......@@ -55,7 +57,7 @@ class WebLocalFrameImpl;
class CORE_EXPORT WebDevToolsAgentImpl final
: public GarbageCollectedFinalized<WebDevToolsAgentImpl>,
public mojom::blink::DevToolsAgent,
public DevToolsAgent::Client,
public InspectorPageAgent::Client,
public InspectorLayerTreeAgent::Client,
private WebThread::TaskObserver {
......@@ -88,18 +90,16 @@ class CORE_EXPORT WebDevToolsAgentImpl final
private:
friend class ClientMessageLoopAdapter;
class Session;
WebDevToolsAgentImpl(WebLocalFrameImpl*,
bool include_view_agents,
WorkerClient*);
// mojom::blink::DevToolsAgent implementation.
void AttachDevToolsSession(
mojom::blink::DevToolsSessionHostAssociatedPtrInfo,
mojom::blink::DevToolsSessionAssociatedRequest main_session,
mojom::blink::DevToolsSessionRequest io_session,
// DevToolsAgent::Client implementation.
InspectorSession* AttachSession(
InspectorSession::Client*,
mojom::blink::DevToolsSessionStatePtr reattach_session_state) override;
void DetachSession(InspectorSession*) override;
void InspectElement(const WebPoint& point_in_local_root) override;
// InspectorPageAgent::Client implementation.
......@@ -112,10 +112,14 @@ class CORE_EXPORT WebDevToolsAgentImpl final
void WillProcessTask() override;
void DidProcessTask() override;
void DetachSession(Session*);
mojo::AssociatedBinding<mojom::blink::DevToolsAgent> binding_;
HeapHashSet<Member<Session>> sessions_;
Member<DevToolsAgent> agent_;
HeapHashSet<Member<InspectorSession>> sessions_;
HeapHashMap<Member<InspectorSession>, Member<InspectorNetworkAgent>>
network_agents_;
HeapHashMap<Member<InspectorSession>, Member<InspectorPageAgent>>
page_agents_;
HeapHashMap<Member<InspectorSession>, Member<InspectorOverlayAgent>>
overlay_agents_;
WorkerClient* worker_client_;
Member<WebLocalFrameImpl> web_local_frame_impl_;
Member<CoreProbeSink> probe_sink_;
......
......@@ -23,6 +23,8 @@ blink_core_sources("inspector") {
"dev_tools_emulator.h",
"dev_tools_host.cc",
"dev_tools_host.h",
"devtools_agent.cc",
"devtools_agent.h",
"dom_editor.cc",
"dom_editor.h",
"dom_patch_support.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/inspector/devtools_agent.h"
#include <v8-inspector.h>
#include <memory>
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/renderer/core/inspector/inspector_session.h"
#include "third_party/blink/renderer/core/inspector/inspector_task_runner.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
// --------- DevToolsAgent::Session -------------
class DevToolsAgent::Session : public GarbageCollectedFinalized<Session>,
public mojom::blink::DevToolsSession,
public InspectorSession::Client {
public:
Session(DevToolsAgent*,
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info,
mojom::blink::DevToolsSessionAssociatedRequest main_request,
mojom::blink::DevToolsSessionRequest io_request,
mojom::blink::DevToolsSessionStatePtr reattach_session_state);
~Session() override;
virtual void Trace(blink::Visitor*);
void Detach();
InspectorSession* inspector_session() { return inspector_session_.Get(); }
private:
class IOSession;
// mojom::blink::DevToolsSession implementation.
void DispatchProtocolCommand(int call_id,
const String& method,
const String& message) override;
// InspectorSession::Client implementation.
void SendProtocolResponse(
int session_id,
int call_id,
const String& response,
mojom::blink::DevToolsSessionStatePtr updates) override;
void SendProtocolNotification(
int session_id,
const String& message,
mojom::blink::DevToolsSessionStatePtr updates) override;
void DispatchProtocolCommandInternal(int call_id,
const String& method,
const String& message);
Member<DevToolsAgent> agent_;
mojo::AssociatedBinding<mojom::blink::DevToolsSession> binding_;
mojom::blink::DevToolsSessionHostAssociatedPtr host_ptr_;
IOSession* io_session_;
Member<InspectorSession> inspector_session_;
DISALLOW_COPY_AND_ASSIGN(Session);
};
// Created and stored in unique_ptr on UI.
// Binds request, receives messages and destroys on IO.
class DevToolsAgent::Session::IOSession : public mojom::blink::DevToolsSession {
public:
IOSession(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<InspectorTaskRunner> inspector_task_runner,
CrossThreadWeakPersistent<DevToolsAgent::Session> session,
mojom::blink::DevToolsSessionRequest request)
: io_task_runner_(io_task_runner),
inspector_task_runner_(inspector_task_runner),
session_(std::move(session)),
binding_(this) {
io_task_runner->PostTask(
FROM_HERE, ConvertToBaseCallback(CrossThreadBind(
&IOSession::BindInterface, CrossThreadUnretained(this),
WTF::Passed(std::move(request)))));
}
~IOSession() override {}
void BindInterface(mojom::blink::DevToolsSessionRequest request) {
binding_.Bind(std::move(request));
}
void DeleteSoon() { io_task_runner_->DeleteSoon(FROM_HERE, this); }
// mojom::blink::DevToolsSession implementation.
void DispatchProtocolCommand(int call_id,
const String& method,
const String& message) override {
DCHECK(InspectorSession::ShouldInterruptForMethod(method));
// Crash renderer.
if (method == "Page.crash")
CHECK(false);
inspector_task_runner_->AppendTask(
CrossThreadBind(&DevToolsAgent::Session::DispatchProtocolCommand,
session_, call_id, method, message));
}
private:
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
CrossThreadWeakPersistent<DevToolsAgent::Session> session_;
mojo::Binding<mojom::blink::DevToolsSession> binding_;
DISALLOW_COPY_AND_ASSIGN(IOSession);
};
DevToolsAgent::Session::Session(
DevToolsAgent* agent,
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info,
mojom::blink::DevToolsSessionAssociatedRequest request,
mojom::blink::DevToolsSessionRequest io_request,
mojom::blink::DevToolsSessionStatePtr reattach_session_state)
: agent_(agent), binding_(this, std::move(request)) {
io_session_ =
new IOSession(agent_->io_task_runner_, agent_->inspector_task_runner_,
WrapCrossThreadWeakPersistent(this), std::move(io_request));
host_ptr_.Bind(std::move(host_ptr_info));
host_ptr_.set_connection_error_handler(
WTF::Bind(&DevToolsAgent::Session::Detach, WrapWeakPersistent(this)));
inspector_session_ =
agent_->client_->AttachSession(this, std::move(reattach_session_state));
}
DevToolsAgent::Session::~Session() {
DCHECK(!host_ptr_.is_bound());
}
void DevToolsAgent::Session::Trace(blink::Visitor* visitor) {
visitor->Trace(agent_);
visitor->Trace(inspector_session_);
}
void DevToolsAgent::Session::Detach() {
agent_->client_->DetachSession(inspector_session_.Get());
agent_->sessions_.erase(this);
binding_.Close();
host_ptr_.reset();
io_session_->DeleteSoon();
io_session_ = nullptr;
inspector_session_->Dispose();
}
void DevToolsAgent::Session::SendProtocolResponse(
int session_id,
int call_id,
const String& response,
mojom::blink::DevToolsSessionStatePtr updates) {
if (!host_ptr_.is_bound())
return;
// Make tests more predictable by flushing all sessions before sending
// protocol response in any of them.
if (LayoutTestSupport::IsRunningLayoutTest())
agent_->FlushProtocolNotifications();
host_ptr_->DispatchProtocolResponse(response, call_id, std::move(updates));
}
void DevToolsAgent::Session::SendProtocolNotification(
int session_id,
const String& message,
mojom::blink::DevToolsSessionStatePtr updates) {
if (!host_ptr_.is_bound())
return;
host_ptr_->DispatchProtocolNotification(message, std::move(updates));
}
void DevToolsAgent::Session::DispatchProtocolCommand(int call_id,
const String& method,
const String& message) {
// IOSession does not provide ordering guarantees relative to
// Session, so a command may come to IOSession after Session is detached,
// and get posted to main thread to this method.
//
// At the same time, Session may not be garbage collected yet
// (even though already detached), and CrossThreadWeakPersistent<Session>
// will still be valid.
//
// Both these factors combined may lead to this method being called after
// detach, so we have to check it here.
if (!host_ptr_.is_bound())
return;
inspector_session_->DispatchProtocolMessage(call_id, method, message);
}
// --------- DevToolsAgent -------------
DevToolsAgent::DevToolsAgent(
Client* client,
scoped_refptr<InspectorTaskRunner> inspector_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: client_(client),
binding_(this),
inspector_task_runner_(std::move(inspector_task_runner)),
io_task_runner_(std::move(io_task_runner)) {}
DevToolsAgent::~DevToolsAgent() {}
void DevToolsAgent::Trace(blink::Visitor* visitor) {
visitor->Trace(sessions_);
}
void DevToolsAgent::WillBeDestroyed() {
HeapHashSet<Member<Session>> copy(sessions_);
for (auto& session : copy)
session->Detach();
binding_.Close();
}
void DevToolsAgent::BindRequest(
mojom::blink::DevToolsAgentAssociatedRequest request) {
binding_.Bind(std::move(request));
}
void DevToolsAgent::AttachDevToolsSession(
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host,
mojom::blink::DevToolsSessionAssociatedRequest session_request,
mojom::blink::DevToolsSessionRequest io_session_request,
mojom::blink::DevToolsSessionStatePtr reattach_session_state) {
Session* session = new Session(
this, std::move(host), std::move(session_request),
std::move(io_session_request), std::move(reattach_session_state));
sessions_.insert(session);
}
void DevToolsAgent::InspectElement(const WebPoint& point) {
client_->InspectElement(point);
}
void DevToolsAgent::FlushProtocolNotifications() {
for (auto& session : sessions_)
session->inspector_session()->flushProtocolNotifications();
}
} // namespace blink
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DEVTOOLS_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DEVTOOLS_AGENT_H_
#include <memory>
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "third_party/blink/public/web/devtools_agent.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/inspector/inspector_session.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
class InspectorTaskRunner;
class CORE_EXPORT DevToolsAgent
: public GarbageCollectedFinalized<DevToolsAgent>,
public mojom::blink::DevToolsAgent {
public:
class Client {
public:
virtual ~Client() {}
virtual InspectorSession* AttachSession(
InspectorSession::Client*,
mojom::blink::DevToolsSessionStatePtr reattach_session_state) = 0;
virtual void DetachSession(InspectorSession*) = 0;
virtual void InspectElement(const WebPoint&) = 0;
};
DevToolsAgent(Client*,
scoped_refptr<InspectorTaskRunner> inspector_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~DevToolsAgent() override;
void WillBeDestroyed();
void FlushProtocolNotifications();
void BindRequest(mojom::blink::DevToolsAgentAssociatedRequest);
virtual void Trace(blink::Visitor*);
private:
class Session;
// mojom::blink::DevToolsAgent implementation.
void AttachDevToolsSession(
mojom::blink::DevToolsSessionHostAssociatedPtrInfo,
mojom::blink::DevToolsSessionAssociatedRequest main_session,
mojom::blink::DevToolsSessionRequest io_session,
mojom::blink::DevToolsSessionStatePtr reattach_session_state) override;
void InspectElement(const WebPoint& point) override;
Client* client_;
mojo::AssociatedBinding<mojom::blink::DevToolsAgent> binding_;
HeapHashSet<Member<Session>> sessions_;
scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DEVTOOLS_AGENT_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment