blob: 9b0ec7152d344ece36db40692e954c7820f34dd6 [file] [log] [blame]
/*
* Copyright (C) 2010-2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "core/exported/WebDevToolsAgentImpl.h"
#include <v8-inspector.h>
#include <memory>
#include <utility>
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "core/CoreInitializer.h"
#include "core/CoreProbeSink.h"
#include "core/events/WebInputEventConversion.h"
#include "core/exported/WebSettingsImpl.h"
#include "core/exported/WebViewImpl.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameView.h"
#include "core/frame/Settings.h"
#include "core/frame/WebLocalFrameImpl.h"
#include "core/inspector/DevToolsEmulator.h"
#include "core/inspector/InspectedFrames.h"
#include "core/inspector/InspectorAnimationAgent.h"
#include "core/inspector/InspectorApplicationCacheAgent.h"
#include "core/inspector/InspectorAuditsAgent.h"
#include "core/inspector/InspectorCSSAgent.h"
#include "core/inspector/InspectorDOMAgent.h"
#include "core/inspector/InspectorDOMDebuggerAgent.h"
#include "core/inspector/InspectorDOMSnapshotAgent.h"
#include "core/inspector/InspectorEmulationAgent.h"
#include "core/inspector/InspectorIOAgent.h"
#include "core/inspector/InspectorLayerTreeAgent.h"
#include "core/inspector/InspectorLogAgent.h"
#include "core/inspector/InspectorMemoryAgent.h"
#include "core/inspector/InspectorNetworkAgent.h"
#include "core/inspector/InspectorOverlayAgent.h"
#include "core/inspector/InspectorPageAgent.h"
#include "core/inspector/InspectorPerformanceAgent.h"
#include "core/inspector/InspectorResourceContainer.h"
#include "core/inspector/InspectorResourceContentLoader.h"
#include "core/inspector/InspectorSession.h"
#include "core/inspector/InspectorTaskRunner.h"
#include "core/inspector/InspectorTracingAgent.h"
#include "core/inspector/InspectorWorkerAgent.h"
#include "core/inspector/MainThreadDebugger.h"
#include "core/layout/LayoutView.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
#include "core/probe/CoreProbes.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "platform/CrossThreadFunctional.h"
#include "platform/LayoutTestSupport.h"
#include "platform/WebTaskRunner.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/paint/PaintController.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/wtf/MathExtras.h"
#include "platform/wtf/PtrUtil.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/text/WTFString.h"
#include "public/platform/Platform.h"
#include "public/platform/WebFloatRect.h"
#include "public/platform/WebLayerTreeView.h"
#include "public/platform/WebRect.h"
#include "public/platform/WebString.h"
#include "public/web/WebSettings.h"
#include "public/web/WebViewClient.h"
namespace blink {
namespace {
bool IsMainFrame(WebLocalFrameImpl* frame) {
// TODO(dgozman): sometimes view->mainFrameImpl() does return null, even
// though |frame| is meant to be main frame. See http://crbug.com/526162.
return frame->ViewImpl() && !frame->Parent();
}
// TODO(dgozman): somehow get this from a mojo config.
// See kMaximumMojoMessageSize in services/service_manager/embedder/main.cc.
const size_t kMaxDevToolsMessageChunkSize = 128 * 1024 * 1024 / 8;
bool ShouldInterruptForMethod(const String& method) {
// Keep in sync with DevToolsSession::ShouldSendOnIO.
// TODO(dgozman): find a way to share this.
return method == "Debugger.pause" || method == "Debugger.setBreakpoint" ||
method == "Debugger.setBreakpointByUrl" ||
method == "Debugger.removeBreakpoint" ||
method == "Debugger.setBreakpointsActive" ||
method == "Performance.getMetrics" || method == "Page.crash";
}
} // namespace
class ClientMessageLoopAdapter : public MainThreadDebugger::ClientMessageLoop {
public:
~ClientMessageLoopAdapter() override { instance_ = nullptr; }
static void EnsureMainThreadDebuggerCreated() {
if (instance_)
return;
std::unique_ptr<ClientMessageLoopAdapter> instance(
new ClientMessageLoopAdapter(
Platform::Current()->CreateNestedMessageLoopRunner()));
instance_ = instance.get();
MainThreadDebugger::Instance()->SetClientMessageLoop(std::move(instance));
}
static void ContinueProgram() {
// Release render thread if necessary.
if (instance_)
instance_->QuitNow();
}
private:
ClientMessageLoopAdapter(
std::unique_ptr<Platform::NestedMessageLoopRunner> message_loop)
: running_for_debug_break_(false),
message_loop_(std::move(message_loop)) {
DCHECK(message_loop_.get());
}
void Run(LocalFrame* frame) override {
if (running_for_debug_break_)
return;
running_for_debug_break_ = true;
RunLoop(WebLocalFrameImpl::FromFrame(frame));
}
void RunLoop(WebLocalFrameImpl* frame) {
// 0. Flush pending frontend messages.
WebDevToolsAgentImpl* agent = frame->DevToolsAgentImpl();
agent->FlushProtocolNotifications();
// 1. Disable input events.
WebFrameWidgetBase::SetIgnoreInputEvents(true);
for (const auto view : WebViewImpl::AllInstances())
view->GetChromeClient().NotifyPopupOpeningObservers();
// 2. Disable active objects
WebView::WillEnterModalLoop();
// 3. Process messages until quitNow is called.
message_loop_->Run();
// 4. Resume active objects
WebView::DidExitModalLoop();
// 5. Enable input events.
WebFrameWidgetBase::SetIgnoreInputEvents(false);
}
void QuitNow() override {
if (running_for_debug_break_) {
running_for_debug_break_ = false;
message_loop_->QuitNow();
}
}
void RunIfWaitingForDebugger(LocalFrame* frame) override {
WebDevToolsAgentImpl* agent =
WebLocalFrameImpl::FromFrame(frame)->DevToolsAgentImpl();
if (agent && agent->worker_client_)
agent->worker_client_->ResumeStartup();
}
bool running_for_debug_break_;
std::unique_ptr<Platform::NestedMessageLoopRunner> message_loop_;
static ClientMessageLoopAdapter* instance_;
};
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,
const String& reattach_state);
~Session() override;
virtual void Trace(blink::Visitor*);
void Detach();
InspectorSession* inspector_session() { return inspector_session_.Get(); }
InspectorPageAgent* page_agent() { return page_agent_.Get(); }
InspectorTracingAgent* tracing_agent() { return tracing_agent_.Get(); }
InspectorOverlayAgent* overlay_agent() { return overlay_agent_.Get(); }
private:
class IOSession;
// mojom::blink::DevToolsSession implementation.
void DispatchProtocolMessage(int call_id,
const String& method,
const String& message) override;
void InspectElement(const WebPoint& point_in_root_frame) override;
// InspectorSession::Client implementation.
void SendProtocolMessage(int session_id,
int call_id,
const String& response,
const String& state) override;
void DispatchProtocolMessageInternal(int call_id,
const String& method,
const String& message);
void InitializeInspectorSession(const String& reattach_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<InspectorPageAgent> page_agent_;
Member<InspectorTracingAgent> tracing_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<WebTaskRunner> agent_task_runner,
CrossThreadWeakPersistent<WebDevToolsAgentImpl::Session> session,
mojom::blink::DevToolsSessionRequest request)
: session_task_runner_(session_task_runner),
agent_task_runner_(agent_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 DispatchProtocolMessage(int call_id,
const String& method,
const String& message) override {
DCHECK(ShouldInterruptForMethod(method));
// Crash renderer.
if (method == "Page.crash")
CHECK(false);
MainThreadDebugger::InterruptMainThreadAndRun(CrossThreadBind(
&WebDevToolsAgentImpl::Session::DispatchProtocolMessageInternal,
session_, call_id, method, message));
PostCrossThreadTask(
*agent_task_runner_, FROM_HERE,
CrossThreadBind(&WebDevToolsAgentImpl::Session::DispatchProtocolMessage,
session_, call_id, method, message));
}
void InspectElement(const WebPoint&) override { NOTREACHED(); }
private:
scoped_refptr<base::SingleThreadTaskRunner> session_task_runner_;
scoped_refptr<WebTaskRunner> agent_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,
const String& reattach_state)
: agent_(agent),
frame_(agent->web_local_frame_impl_),
binding_(this, std::move(request)) {
io_session_ =
new IOSession(Platform::Current()->GetIOTaskRunner(),
frame_->GetFrame()->GetTaskRunner(TaskType::kUnthrottled),
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(reattach_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(page_agent_);
visitor->Trace(tracing_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::DispatchProtocolMessage(
int call_id,
const String& method,
const String& message) {
if (ShouldInterruptForMethod(method))
MainThreadDebugger::Instance()->TaskRunner()->RunAllTasksDontWait();
else
DispatchProtocolMessageInternal(call_id, method, message);
}
void WebDevToolsAgentImpl::Session::InspectElement(
const WebPoint& point_in_root_frame) {
WebPoint point = point_in_root_frame;
if (frame_->ViewImpl() && frame_->ViewImpl()->Client()) {
WebFloatRect rect(point.x, point.y, 0, 0);
frame_->ViewImpl()->Client()->ConvertWindowToViewport(&rect);
point = WebPoint(rect.x, rect.y);
}
HitTestRequest::HitTestRequestType hit_type =
HitTestRequest::kMove | HitTestRequest::kReadOnly |
HitTestRequest::kAllowChildFrameContent;
HitTestRequest request(hit_type);
WebMouseEvent dummy_event(WebInputEvent::kMouseDown,
WebInputEvent::kNoModifiers,
WTF::CurrentTimeTicksInMilliseconds());
dummy_event.SetPositionInWidget(point.x, point.y);
IntPoint transformed_point = FlooredIntPoint(
TransformWebMouseEvent(frame_->GetFrameView(), dummy_event)
.PositionInRootFrame());
HitTestResult result(
request, frame_->GetFrameView()->RootFrameToContents(transformed_point));
frame_->GetFrame()->ContentLayoutObject()->HitTest(result);
Node* node = result.InnerNode();
if (!node && frame_->GetFrame()->GetDocument())
node = frame_->GetFrame()->GetDocument()->documentElement();
overlay_agent_->Inspect(node);
}
void WebDevToolsAgentImpl::Session::SendProtocolMessage(int session_id,
int call_id,
const String& response,
const String& state) {
if (detached_)
return;
// Make tests more predictable by flushing all sessions before sending
// protocol response in any of them.
if (LayoutTestSupport::IsRunningLayoutTest() && call_id)
agent_->FlushProtocolNotifications();
bool single_chunk = response.length() < kMaxDevToolsMessageChunkSize;
for (size_t pos = 0; pos < response.length();
pos += kMaxDevToolsMessageChunkSize) {
mojom::blink::DevToolsMessageChunkPtr chunk =
mojom::blink::DevToolsMessageChunk::New();
chunk->is_first = pos == 0;
chunk->is_last = pos + kMaxDevToolsMessageChunkSize >= response.length();
chunk->call_id = chunk->is_last ? call_id : 0;
chunk->post_state =
chunk->is_last && !state.IsNull() ? state : g_empty_string;
chunk->data = single_chunk
? response
: response.Substring(pos, kMaxDevToolsMessageChunkSize);
host_ptr_->DispatchProtocolMessage(std::move(chunk));
}
}
void WebDevToolsAgentImpl::Session::DispatchProtocolMessageInternal(
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;
InspectorTaskRunner::IgnoreInterruptsScope scope(
MainThreadDebugger::Instance()->TaskRunner());
inspector_session_->DispatchProtocolMessage(method, message);
}
void WebDevToolsAgentImpl::Session::InitializeInspectorSession(
const String& reattach_state) {
String state = reattach_state;
// TODO(dgozman): make InspectorSession check for IsNull() instead.
String* state_ptr = nullptr;
if (!reattach_state.IsNull())
state_ptr = &state;
ClientMessageLoopAdapter::EnsureMainThreadDebuggerCreated();
MainThreadDebugger* main_thread_debugger = MainThreadDebugger::Instance();
v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
InspectedFrames* inspected_frames = agent_->inspected_frames_.Get();
inspector_session_ = new InspectorSession(
this, agent_->probe_sink_.Get(), 0,
main_thread_debugger->GetV8Inspector(),
main_thread_debugger->ContextGroupId(inspected_frames->Root()),
state_ptr);
InspectorDOMAgent* dom_agent = new InspectorDOMAgent(
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);
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);
InspectorDOMDebuggerAgent* dom_debugger_agent = new InspectorDOMDebuggerAgent(
isolate, dom_agent, inspector_session_->V8Session());
inspector_session_->Append(dom_debugger_agent);
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(InspectorMemoryAgent::Create(inspected_frames));
inspector_session_->Append(
InspectorPerformanceAgent::Create(inspected_frames));
inspector_session_->Append(
InspectorApplicationCacheAgent::Create(inspected_frames));
InspectorWorkerAgent* worker_agent =
new InspectorWorkerAgent(inspected_frames);
inspector_session_->Append(worker_agent);
tracing_agent_ =
InspectorTracingAgent::Create(agent_, worker_agent, inspected_frames);
inspector_session_->Append(tracing_agent_);
page_agent_ = InspectorPageAgent::Create(
inspected_frames, agent_, agent_->resource_content_loader_.Get(),
inspector_session_->V8Session());
inspector_session_->Append(page_agent_);
inspector_session_->Append(new InspectorLogAgent(
&inspected_frames->Root()->GetPage()->GetConsoleMessageStorage(),
inspected_frames->Root()->GetPerformanceMonitor(),
inspector_session_->V8Session()));
overlay_agent_ =
new InspectorOverlayAgent(frame_.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 InspectorAuditsAgent(network_agent));
tracing_agent_->SetLayerTreeId(agent_->layer_tree_id_);
if (agent_->include_view_agents_) {
// 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()));
}
// Call session init callbacks registered from higher layers
CoreInitializer::GetInstance().InitInspectorAgentSession(
inspector_session_, agent_->include_view_agents_, dom_agent,
inspected_frames, frame_->ViewImpl()->GetPage());
if (!reattach_state.IsNull())
inspector_session_->Restore();
// TODO(dgozman): do not send empty state from the browser side.
if (agent_->worker_client_ && !reattach_state.IsEmpty())
agent_->worker_client_->ResumeStartup();
}
// --------- WebDevToolsAgentImpl -------------
// static
WebDevToolsAgentImpl* WebDevToolsAgentImpl::CreateForFrame(
WebLocalFrameImpl* frame) {
if (!IsMainFrame(frame)) {
WebDevToolsAgentImpl* agent =
new WebDevToolsAgentImpl(frame, false, nullptr);
if (frame->FrameWidget())
agent->LayerTreeViewChanged(frame->FrameWidget()->GetLayerTreeView());
return agent;
}
WebViewImpl* view = frame->ViewImpl();
WebDevToolsAgentImpl* agent = new WebDevToolsAgentImpl(frame, true, nullptr);
agent->LayerTreeViewChanged(view->LayerTreeView());
return agent;
}
// static
WebDevToolsAgentImpl* WebDevToolsAgentImpl::CreateForWorker(
WebLocalFrameImpl* frame,
WorkerClient* worker_client) {
WebViewImpl* view = frame->ViewImpl();
WebDevToolsAgentImpl* agent =
new WebDevToolsAgentImpl(frame, true, worker_client);
agent->LayerTreeViewChanged(view->LayerTreeView());
return agent;
}
WebDevToolsAgentImpl::WebDevToolsAgentImpl(
WebLocalFrameImpl* web_local_frame_impl,
bool include_view_agents,
WorkerClient* worker_client)
: binding_(this),
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(
web_local_frame_impl_->GetFrame())),
inspected_frames_(new InspectedFrames(
web_local_frame_impl_->GetFrame(),
web_local_frame_impl_->GetFrame()->GetDevToolsFrameToken())),
resource_container_(new InspectorResourceContainer(inspected_frames_)),
include_view_agents_(include_view_agents),
layer_tree_id_(0) {
DCHECK(IsMainThread());
DCHECK(web_local_frame_impl_->GetFrame());
}
WebDevToolsAgentImpl::~WebDevToolsAgentImpl() {
DCHECK(!worker_client_);
}
void WebDevToolsAgentImpl::Trace(blink::Visitor* visitor) {
visitor->Trace(sessions_);
visitor->Trace(web_local_frame_impl_);
visitor->Trace(probe_sink_);
visitor->Trace(resource_content_loader_);
visitor->Trace(inspected_frames_);
visitor->Trace(resource_container_);
}
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();
resource_content_loader_->Dispose();
worker_client_ = nullptr;
binding_.Close();
}
void WebDevToolsAgentImpl::BindRequest(
mojom::blink::DevToolsAgentAssociatedRequest request) {
binding_.Bind(std::move(request));
}
void WebDevToolsAgentImpl::AttachDevToolsSession(
mojom::blink::DevToolsSessionHostAssociatedPtrInfo host,
mojom::blink::DevToolsSessionAssociatedRequest session,
mojom::blink::DevToolsSessionRequest io_session,
const String& reattach_state) {
if (!sessions_.size())
Platform::Current()->CurrentThread()->AddTaskObserver(this);
sessions_.insert(new Session(this, std::move(host), std::move(session),
std::move(io_session), reattach_state));
}
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);
}
void WebDevToolsAgentImpl::DidStartProvisionalLoad(LocalFrame* frame) {
if (inspected_frames_->Root() == frame) {
for (auto& session : sessions_)
session->inspector_session()->V8Session()->resume();
}
}
bool WebDevToolsAgentImpl::ScreencastEnabled() {
for (auto& session : sessions_) {
if (session->page_agent()->ScreencastEnabled())
return true;
}
return false;
}
void WebDevToolsAgentImpl::RootLayerCleared() {
for (auto& session : sessions_)
session->tracing_agent()->RootLayerCleared();
}
void WebDevToolsAgentImpl::LayerTreeViewChanged(
WebLayerTreeView* layer_tree_view) {
layer_tree_id_ = layer_tree_view ? layer_tree_view->LayerTreeId() : 0;
for (auto& session : sessions_)
session->tracing_agent()->SetLayerTreeId(layer_tree_id_);
}
void WebDevToolsAgentImpl::ShowReloadingBlanket() {
for (auto& session : sessions_)
session->overlay_agent()->ShowReloadingBlanket();
}
void WebDevToolsAgentImpl::HideReloadingBlanket() {
for (auto& session : sessions_)
session->overlay_agent()->HideReloadingBlanket();
}
void WebDevToolsAgentImpl::PageLayoutInvalidated(bool resized) {
for (auto& session : sessions_)
session->overlay_agent()->PageLayoutInvalidated(resized);
}
bool WebDevToolsAgentImpl::IsInspectorLayer(GraphicsLayer* layer) {
for (auto& session : sessions_) {
if (session->overlay_agent()->IsInspectorLayer(layer))
return true;
}
return false;
}
String WebDevToolsAgentImpl::EvaluateInOverlayForTesting(const String& script) {
String result;
for (auto& session : sessions_)
result = session->overlay_agent()->EvaluateInOverlayForTest(script);
return result;
}
void WebDevToolsAgentImpl::PaintOverlay() {
for (auto& session : sessions_)
session->overlay_agent()->PaintOverlay();
}
void WebDevToolsAgentImpl::LayoutOverlay() {
for (auto& session : sessions_)
session->overlay_agent()->LayoutOverlay();
}
void WebDevToolsAgentImpl::DispatchBufferedTouchEvents() {
for (auto& session : sessions_)
session->overlay_agent()->DispatchBufferedTouchEvents();
}
bool WebDevToolsAgentImpl::HandleInputEvent(const WebInputEvent& event) {
for (auto& session : sessions_) {
if (session->overlay_agent()->HandleInputEvent(event))
return true;
}
return false;
}
void WebDevToolsAgentImpl::FlushProtocolNotifications() {
for (auto& session : sessions_)
session->inspector_session()->flushProtocolNotifications();
}
void WebDevToolsAgentImpl::WillProcessTask() {
if (sessions_.IsEmpty())
return;
ThreadDebugger::IdleFinished(V8PerIsolateData::MainThreadIsolate());
}
void WebDevToolsAgentImpl::DidProcessTask() {
if (sessions_.IsEmpty())
return;
ThreadDebugger::IdleStarted(V8PerIsolateData::MainThreadIsolate());
FlushProtocolNotifications();
}
} // namespace blink