| /* |
| * 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 "web/WebDevToolsAgentImpl.h" |
| |
| #include <v8-inspector.h> |
| #include <memory> |
| |
| #include "bindings/core/v8/ScriptController.h" |
| #include "bindings/core/v8/V8BindingForCore.h" |
| #include "core/CoreProbeSink.h" |
| #include "core/events/WebInputEventConversion.h" |
| #include "core/exported/WebSettingsImpl.h" |
| #include "core/exported/WebViewBase.h" |
| #include "core/frame/LocalFrame.h" |
| #include "core/frame/LocalFrameView.h" |
| #include "core/frame/Settings.h" |
| #include "core/frame/WebLocalFrameBase.h" |
| #include "core/inspector/DevToolsEmulator.h" |
| #include "core/inspector/InspectedFrames.h" |
| #include "core/inspector/InspectorAnimationAgent.h" |
| #include "core/inspector/InspectorApplicationCacheAgent.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/InspectorInputAgent.h" |
| #include "core/inspector/InspectorLayerTreeAgent.h" |
| #include "core/inspector/InspectorLogAgent.h" |
| #include "core/inspector/InspectorMemoryAgent.h" |
| #include "core/inspector/InspectorNetworkAgent.h" |
| #include "core/inspector/InspectorPageAgent.h" |
| #include "core/inspector/InspectorResourceContainer.h" |
| #include "core/inspector/InspectorResourceContentLoader.h" |
| #include "core/inspector/InspectorTaskRunner.h" |
| #include "core/inspector/InspectorTracingAgent.h" |
| #include "core/inspector/InspectorWorkerAgent.h" |
| #include "core/inspector/MainThreadDebugger.h" |
| #include "core/layout/api/LayoutViewItem.h" |
| #include "core/page/FocusController.h" |
| #include "core/page/Page.h" |
| #include "core/probe/CoreProbes.h" |
| #include "modules/accessibility/InspectorAccessibilityAgent.h" |
| #include "modules/cachestorage/InspectorCacheStorageAgent.h" |
| #include "modules/device_orientation/DeviceOrientationInspectorAgent.h" |
| #include "modules/indexeddb/InspectorIndexedDBAgent.h" |
| #include "modules/storage/InspectorDOMStorageAgent.h" |
| #include "modules/webdatabase/InspectorDatabaseAgent.h" |
| #include "platform/CrossThreadFunctional.h" |
| #include "platform/RuntimeEnabledFeatures.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/Noncopyable.h" |
| #include "platform/wtf/PtrUtil.h" |
| #include "platform/wtf/text/WTFString.h" |
| #include "public/platform/Platform.h" |
| #include "public/platform/WebLayerTreeView.h" |
| #include "public/platform/WebRect.h" |
| #include "public/platform/WebString.h" |
| #include "public/web/WebDevToolsAgentClient.h" |
| #include "public/web/WebSettings.h" |
| #include "web/InspectorOverlayAgent.h" |
| #include "web/WebFrameWidgetImpl.h" |
| |
| namespace blink { |
| |
| namespace { |
| |
| bool IsMainFrame(WebLocalFrameBase* 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(); |
| } |
| } |
| |
| class ClientMessageLoopAdapter : public MainThreadDebugger::ClientMessageLoop { |
| public: |
| ~ClientMessageLoopAdapter() override { instance_ = nullptr; } |
| |
| static void EnsureMainThreadDebuggerCreated(WebDevToolsAgentClient* client) { |
| if (instance_) |
| return; |
| std::unique_ptr<ClientMessageLoopAdapter> instance = |
| WTF::WrapUnique(new ClientMessageLoopAdapter( |
| WTF::WrapUnique(client->CreateClientMessageLoop()))); |
| instance_ = instance.get(); |
| MainThreadDebugger::Instance()->SetClientMessageLoop(std::move(instance)); |
| } |
| |
| static void ContinueProgram() { |
| // Release render thread if necessary. |
| if (instance_) |
| instance_->QuitNow(); |
| } |
| |
| static void PauseForCreateWindow(WebLocalFrameBase* frame) { |
| if (instance_) |
| instance_->RunForCreateWindow(frame); |
| } |
| |
| static bool ResumeForCreateWindow() { |
| return instance_ ? instance_->QuitForCreateWindow() : false; |
| } |
| |
| private: |
| ClientMessageLoopAdapter( |
| std::unique_ptr<WebDevToolsAgentClient::WebKitClientMessageLoop> |
| message_loop) |
| : running_for_debug_break_(false), |
| running_for_create_window_(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; |
| if (!running_for_create_window_) |
| RunLoop(WebLocalFrameBase::FromFrame(frame)); |
| } |
| |
| void RunForCreateWindow(WebLocalFrameBase* frame) { |
| if (running_for_create_window_) |
| return; |
| |
| running_for_create_window_ = true; |
| if (!running_for_debug_break_) |
| RunLoop(frame); |
| } |
| |
| void RunLoop(WebLocalFrameBase* frame) { |
| // 0. Flush pending frontend messages. |
| WebDevToolsAgentImpl* agent = frame->DevToolsAgentImpl(); |
| agent->FlushProtocolNotifications(); |
| |
| // 1. Disable input events. |
| WebFrameWidgetBase::SetIgnoreInputEvents(true); |
| for (const auto view : WebViewBase::AllInstances()) |
| view->GetChromeClient().NotifyPopupOpeningObservers(); |
| |
| // 2. Notify embedder about pausing. |
| if (agent->Client()) |
| agent->Client()->WillEnterDebugLoop(); |
| |
| // 3. Disable active objects |
| WebView::WillEnterModalLoop(); |
| |
| // 4. Process messages until quitNow is called. |
| message_loop_->Run(); |
| |
| // 5. Resume active objects |
| WebView::DidExitModalLoop(); |
| |
| WebFrameWidgetBase::SetIgnoreInputEvents(false); |
| |
| // 7. Notify embedder about resuming. |
| if (agent->Client()) |
| agent->Client()->DidExitDebugLoop(); |
| } |
| |
| void QuitNow() override { |
| if (running_for_debug_break_) { |
| running_for_debug_break_ = false; |
| if (!running_for_create_window_) |
| message_loop_->QuitNow(); |
| } |
| } |
| |
| bool QuitForCreateWindow() { |
| if (running_for_create_window_) { |
| running_for_create_window_ = false; |
| if (!running_for_debug_break_) |
| message_loop_->QuitNow(); |
| return true; |
| } |
| return false; |
| } |
| |
| void RunIfWaitingForDebugger(LocalFrame* frame) override { |
| // If we've paused for createWindow, handle it ourselves. |
| if (QuitForCreateWindow()) |
| return; |
| // Otherwise, pass to the client (embedded workers do it differently). |
| WebDevToolsAgentImpl* agent = |
| WebLocalFrameBase::FromFrame(frame)->DevToolsAgentImpl(); |
| if (agent && agent->Client()) |
| agent->Client()->ResumeStartup(); |
| } |
| |
| bool running_for_debug_break_; |
| bool running_for_create_window_; |
| std::unique_ptr<WebDevToolsAgentClient::WebKitClientMessageLoop> |
| message_loop_; |
| |
| static ClientMessageLoopAdapter* instance_; |
| }; |
| |
| ClientMessageLoopAdapter* ClientMessageLoopAdapter::instance_ = nullptr; |
| |
| // static |
| WebDevToolsAgentImpl* WebDevToolsAgentImpl::Create( |
| WebLocalFrameBase* frame, |
| WebDevToolsAgentClient* client) { |
| if (!IsMainFrame(frame)) { |
| WebDevToolsAgentImpl* agent = |
| new WebDevToolsAgentImpl(frame, client, false); |
| if (frame->FrameWidget()) |
| agent->LayerTreeViewChanged( |
| ToWebFrameWidgetImpl(frame->FrameWidget())->LayerTreeView()); |
| return agent; |
| } |
| |
| WebViewBase* view = frame->ViewImpl(); |
| WebDevToolsAgentImpl* agent = new WebDevToolsAgentImpl(frame, client, true); |
| agent->LayerTreeViewChanged(view->LayerTreeView()); |
| return agent; |
| } |
| |
| WebDevToolsAgentImpl::WebDevToolsAgentImpl( |
| WebLocalFrameBase* web_local_frame_impl, |
| WebDevToolsAgentClient* client, |
| bool include_view_agents) |
| : client_(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_( |
| InspectedFrames::Create(web_local_frame_impl_->GetFrame())), |
| resource_container_(new InspectorResourceContainer(inspected_frames_)), |
| trace_events_(new InspectorTraceEvents()), |
| include_view_agents_(include_view_agents), |
| layer_tree_id_(0) { |
| DCHECK(IsMainThread()); |
| DCHECK(web_local_frame_impl_->GetFrame()); |
| probe_sink_->addInspectorTraceEvents(trace_events_); |
| } |
| |
| WebDevToolsAgentImpl::~WebDevToolsAgentImpl() { |
| DCHECK(!client_); |
| } |
| |
| DEFINE_TRACE(WebDevToolsAgentImpl) { |
| visitor->Trace(web_local_frame_impl_); |
| visitor->Trace(probe_sink_); |
| visitor->Trace(resource_content_loader_); |
| visitor->Trace(inspected_frames_); |
| visitor->Trace(resource_container_); |
| visitor->Trace(trace_events_); |
| visitor->Trace(page_agents_); |
| visitor->Trace(network_agents_); |
| visitor->Trace(layer_tree_agents_); |
| visitor->Trace(tracing_agents_); |
| visitor->Trace(overlay_agents_); |
| visitor->Trace(sessions_); |
| } |
| |
| void WebDevToolsAgentImpl::WillBeDestroyed() { |
| DCHECK(web_local_frame_impl_->GetFrame()); |
| DCHECK(inspected_frames_->Root()->View()); |
| probe_sink_->removeInspectorTraceEvents(trace_events_); |
| trace_events_ = nullptr; |
| |
| Vector<int> session_ids; |
| for (int session_id : sessions_.Keys()) |
| session_ids.push_back(session_id); |
| for (int session_id : session_ids) |
| Detach(session_id); |
| |
| resource_content_loader_->Dispose(); |
| client_ = nullptr; |
| } |
| |
| InspectorSession* WebDevToolsAgentImpl::InitializeSession(int session_id, |
| const String& host_id, |
| String* state) { |
| DCHECK(client_); |
| ClientMessageLoopAdapter::EnsureMainThreadDebuggerCreated(client_); |
| MainThreadDebugger* main_thread_debugger = MainThreadDebugger::Instance(); |
| v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate(); |
| |
| InspectorSession* session = new InspectorSession( |
| this, probe_sink_.Get(), session_id, |
| main_thread_debugger->GetV8Inspector(), |
| main_thread_debugger->ContextGroupId(inspected_frames_->Root()), state); |
| |
| InspectorDOMAgent* dom_agent = new InspectorDOMAgent( |
| isolate, inspected_frames_.Get(), session->V8Session()); |
| session->Append(dom_agent); |
| |
| InspectorLayerTreeAgent* layer_tree_agent = |
| InspectorLayerTreeAgent::Create(inspected_frames_.Get()); |
| layer_tree_agents_.Set(session_id, layer_tree_agent); |
| session->Append(layer_tree_agent); |
| |
| InspectorNetworkAgent* network_agent = |
| InspectorNetworkAgent::Create(inspected_frames_.Get()); |
| network_agents_.Set(session_id, network_agent); |
| session->Append(network_agent); |
| |
| InspectorCSSAgent* css_agent = InspectorCSSAgent::Create( |
| dom_agent, inspected_frames_.Get(), network_agent, |
| resource_content_loader_.Get(), resource_container_.Get()); |
| session->Append(css_agent); |
| |
| session->Append(InspectorDOMSnapshotAgent::Create(inspected_frames_.Get())); |
| |
| session->Append(new InspectorAnimationAgent(inspected_frames_.Get(), |
| css_agent, session->V8Session())); |
| |
| session->Append(InspectorMemoryAgent::Create()); |
| |
| session->Append( |
| InspectorApplicationCacheAgent::Create(inspected_frames_.Get())); |
| |
| session->Append(new InspectorIndexedDBAgent(inspected_frames_.Get(), |
| session->V8Session())); |
| |
| InspectorWorkerAgent* worker_agent = |
| new InspectorWorkerAgent(inspected_frames_.Get()); |
| session->Append(worker_agent); |
| |
| InspectorTracingAgent* tracing_agent = InspectorTracingAgent::Create( |
| this, worker_agent, inspected_frames_.Get()); |
| tracing_agents_.Set(session_id, tracing_agent); |
| session->Append(tracing_agent); |
| |
| session->Append( |
| new InspectorDOMDebuggerAgent(isolate, dom_agent, session->V8Session())); |
| |
| session->Append(InspectorInputAgent::Create(inspected_frames_.Get())); |
| |
| InspectorPageAgent* page_agent = InspectorPageAgent::Create( |
| inspected_frames_.Get(), this, resource_content_loader_.Get(), |
| session->V8Session()); |
| page_agents_.Set(session_id, page_agent); |
| session->Append(page_agent); |
| |
| session->Append(new InspectorLogAgent( |
| &inspected_frames_->Root()->GetPage()->GetConsoleMessageStorage(), |
| inspected_frames_->Root()->GetPerformanceMonitor())); |
| |
| session->Append(new DeviceOrientationInspectorAgent(inspected_frames_.Get())); |
| |
| InspectorOverlayAgent* overlay_agent = |
| new InspectorOverlayAgent(web_local_frame_impl_, inspected_frames_.Get(), |
| session->V8Session(), dom_agent); |
| overlay_agents_.Set(session_id, overlay_agent); |
| session->Append(overlay_agent); |
| |
| tracing_agent->SetLayerTreeId(layer_tree_id_); |
| network_agent->SetHostId(host_id); |
| |
| if (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. |
| session->Append( |
| InspectorEmulationAgent::Create(web_local_frame_impl_, this)); |
| // TODO(dgozman): migrate each of the following agents to frame once module |
| // is ready. |
| Page* page = web_local_frame_impl_->ViewImpl()->GetPage(); |
| session->Append(InspectorDatabaseAgent::Create(page)); |
| session->Append(new InspectorAccessibilityAgent(page, dom_agent)); |
| session->Append(InspectorDOMStorageAgent::Create(page)); |
| session->Append(InspectorCacheStorageAgent::Create()); |
| } |
| |
| if (!sessions_.size()) |
| Platform::Current()->CurrentThread()->AddTaskObserver(this); |
| |
| sessions_.Set(session_id, session); |
| return session; |
| } |
| |
| void WebDevToolsAgentImpl::DestroySession(int session_id) { |
| overlay_agents_.erase(session_id); |
| tracing_agents_.erase(session_id); |
| layer_tree_agents_.erase(session_id); |
| network_agents_.erase(session_id); |
| page_agents_.erase(session_id); |
| |
| auto session_it = sessions_.find(session_id); |
| DCHECK(session_it != sessions_.end()); |
| session_it->value->Dispose(); |
| sessions_.erase(session_it); |
| |
| if (!sessions_.size()) |
| Platform::Current()->CurrentThread()->RemoveTaskObserver(this); |
| } |
| |
| void WebDevToolsAgentImpl::Attach(const WebString& host_id, int session_id) { |
| if (!session_id || sessions_.find(session_id) != sessions_.end()) |
| return; |
| InitializeSession(session_id, host_id, nullptr); |
| } |
| |
| void WebDevToolsAgentImpl::Reattach(const WebString& host_id, |
| int session_id, |
| const WebString& saved_state) { |
| if (!session_id || sessions_.find(session_id) != sessions_.end()) |
| return; |
| String state = saved_state; |
| InspectorSession* session = InitializeSession(session_id, host_id, &state); |
| session->Restore(); |
| } |
| |
| void WebDevToolsAgentImpl::Detach(int session_id) { |
| if (!session_id || sessions_.find(session_id) == sessions_.end()) |
| return; |
| DestroySession(session_id); |
| } |
| |
| void WebDevToolsAgentImpl::ContinueProgram() { |
| ClientMessageLoopAdapter::ContinueProgram(); |
| } |
| |
| void WebDevToolsAgentImpl::DidCommitLoadForLocalFrame(LocalFrame* frame) { |
| resource_container_->DidCommitLoadForLocalFrame(frame); |
| resource_content_loader_->DidCommitLoadForLocalFrame(frame); |
| for (auto& it : sessions_) |
| it.value->DidCommitLoadForLocalFrame(frame); |
| } |
| |
| void WebDevToolsAgentImpl::DidStartProvisionalLoad(LocalFrame* frame) { |
| if (inspected_frames_->Root() == frame) { |
| for (auto& it : sessions_) |
| it.value->V8Session()->resume(); |
| } |
| } |
| |
| bool WebDevToolsAgentImpl::ScreencastEnabled() { |
| for (auto& it : page_agents_) { |
| if (it.value->ScreencastEnabled()) |
| return true; |
| } |
| return false; |
| } |
| |
| void WebDevToolsAgentImpl::WillAddPageOverlay(const GraphicsLayer* layer) { |
| for (auto& it : layer_tree_agents_) |
| it.value->WillAddPageOverlay(layer); |
| } |
| |
| void WebDevToolsAgentImpl::DidRemovePageOverlay(const GraphicsLayer* layer) { |
| for (auto& it : layer_tree_agents_) |
| it.value->DidRemovePageOverlay(layer); |
| } |
| |
| void WebDevToolsAgentImpl::RootLayerCleared() { |
| for (auto& it : tracing_agents_) |
| it.value->RootLayerCleared(); |
| } |
| |
| void WebDevToolsAgentImpl::LayerTreeViewChanged( |
| WebLayerTreeView* layer_tree_view) { |
| layer_tree_id_ = layer_tree_view ? layer_tree_view->LayerTreeId() : 0; |
| for (auto& it : tracing_agents_) |
| it.value->SetLayerTreeId(layer_tree_id_); |
| } |
| |
| void WebDevToolsAgentImpl::EnableTracing(const String& category_filter) { |
| if (client_) |
| client_->EnableTracing(category_filter); |
| } |
| |
| void WebDevToolsAgentImpl::DisableTracing() { |
| if (client_) |
| client_->DisableTracing(); |
| } |
| |
| void WebDevToolsAgentImpl::ShowReloadingBlanket() { |
| for (auto& it : overlay_agents_) |
| it.value->ShowReloadingBlanket(); |
| } |
| |
| void WebDevToolsAgentImpl::HideReloadingBlanket() { |
| for (auto& it : overlay_agents_) |
| it.value->HideReloadingBlanket(); |
| } |
| |
| void WebDevToolsAgentImpl::SetCPUThrottlingRate(double rate) { |
| if (client_) |
| client_->SetCPUThrottlingRate(rate); |
| } |
| |
| void WebDevToolsAgentImpl::DispatchOnInspectorBackend( |
| int session_id, |
| int call_id, |
| const WebString& method, |
| const WebString& message) { |
| if (!Attached()) |
| return; |
| if (WebDevToolsAgent::ShouldInterruptForMethod(method)) |
| MainThreadDebugger::Instance()->TaskRunner()->RunAllTasksDontWait(); |
| else |
| DispatchMessageFromFrontend(session_id, method, message); |
| } |
| |
| void WebDevToolsAgentImpl::DispatchMessageFromFrontend(int session_id, |
| const String& method, |
| const String& message) { |
| if (!session_id) |
| return; |
| auto session_it = sessions_.find(session_id); |
| if (session_it == sessions_.end()) |
| return; |
| InspectorTaskRunner::IgnoreInterruptsScope scope( |
| MainThreadDebugger::Instance()->TaskRunner()); |
| session_it->value->DispatchProtocolMessage(method, message); |
| } |
| |
| void WebDevToolsAgentImpl::InspectElementAt( |
| int session_id, |
| const WebPoint& point_in_root_frame) { |
| if (!session_id) |
| return; |
| auto agent_it = overlay_agents_.find(session_id); |
| if (agent_it == overlay_agents_.end()) |
| return; |
| HitTestRequest::HitTestRequestType hit_type = |
| HitTestRequest::kMove | HitTestRequest::kReadOnly | |
| HitTestRequest::kAllowChildFrameContent; |
| HitTestRequest request(hit_type); |
| WebMouseEvent dummy_event(WebInputEvent::kMouseDown, |
| WebInputEvent::kNoModifiers, |
| WTF::MonotonicallyIncreasingTimeMS()); |
| dummy_event.SetPositionInWidget(point_in_root_frame.x, point_in_root_frame.y); |
| IntPoint transformed_point = FlooredIntPoint( |
| TransformWebMouseEvent(web_local_frame_impl_->GetFrameView(), dummy_event) |
| .PositionInRootFrame()); |
| HitTestResult result( |
| request, web_local_frame_impl_->GetFrameView()->RootFrameToContents( |
| transformed_point)); |
| web_local_frame_impl_->GetFrame()->ContentLayoutItem().HitTest(result); |
| Node* node = result.InnerNode(); |
| if (!node && web_local_frame_impl_->GetFrame()->GetDocument()) |
| node = web_local_frame_impl_->GetFrame()->GetDocument()->documentElement(); |
| agent_it->value->Inspect(node); |
| } |
| |
| void WebDevToolsAgentImpl::FailedToRequestDevTools() { |
| ClientMessageLoopAdapter::ResumeForCreateWindow(); |
| } |
| |
| void WebDevToolsAgentImpl::SendProtocolMessage(int session_id, |
| int call_id, |
| const String& response, |
| const String& state) { |
| DCHECK(Attached()); |
| if (client_) |
| client_->SendProtocolMessage(session_id, call_id, response, state); |
| } |
| |
| void WebDevToolsAgentImpl::PageLayoutInvalidated(bool resized) { |
| for (auto& it : overlay_agents_) |
| it.value->PageLayoutInvalidated(resized); |
| } |
| |
| void WebDevToolsAgentImpl::WaitForCreateWindow(LocalFrame* frame) { |
| if (!Attached()) |
| return; |
| if (client_ && |
| client_->RequestDevToolsForFrame(WebLocalFrameBase::FromFrame(frame))) |
| ClientMessageLoopAdapter::PauseForCreateWindow(web_local_frame_impl_); |
| } |
| |
| WebString WebDevToolsAgentImpl::EvaluateInWebInspectorOverlay( |
| const WebString& script) { |
| WebString result; |
| for (auto& it : overlay_agents_) |
| result = it.value->EvaluateInOverlayForTest(script); |
| return result; |
| } |
| |
| void WebDevToolsAgentImpl::PaintOverlay() { |
| for (auto& it : overlay_agents_) |
| it.value->PaintOverlay(); |
| } |
| |
| void WebDevToolsAgentImpl::LayoutOverlay() { |
| for (auto& it : overlay_agents_) |
| it.value->LayoutOverlay(); |
| } |
| |
| bool WebDevToolsAgentImpl::HandleInputEvent(const WebInputEvent& event) { |
| for (auto& it : overlay_agents_) { |
| if (it.value->HandleInputEvent(event)) |
| return true; |
| } |
| return false; |
| } |
| |
| bool WebDevToolsAgentImpl::CacheDisabled() { |
| for (auto& it : network_agents_) { |
| if (it.value->CacheDisabled()) |
| return true; |
| } |
| return false; |
| } |
| |
| void WebDevToolsAgentImpl::FlushProtocolNotifications() { |
| for (auto& it : sessions_) |
| it.value->flushProtocolNotifications(); |
| } |
| |
| void WebDevToolsAgentImpl::WillProcessTask() { |
| if (!Attached()) |
| return; |
| ThreadDebugger::IdleFinished(V8PerIsolateData::MainThreadIsolate()); |
| } |
| |
| void WebDevToolsAgentImpl::DidProcessTask() { |
| if (!Attached()) |
| return; |
| ThreadDebugger::IdleStarted(V8PerIsolateData::MainThreadIsolate()); |
| FlushProtocolNotifications(); |
| } |
| |
| void WebDevToolsAgentImpl::RunDebuggerTask( |
| int session_id, |
| std::unique_ptr<WebDevToolsAgent::MessageDescriptor> descriptor) { |
| WebDevToolsAgent* webagent = descriptor->Agent(); |
| if (!webagent) |
| return; |
| |
| WebDevToolsAgentImpl* agent_impl = |
| static_cast<WebDevToolsAgentImpl*>(webagent); |
| if (agent_impl->Attached()) |
| agent_impl->DispatchMessageFromFrontend(session_id, descriptor->Method(), |
| descriptor->Message()); |
| } |
| |
| void WebDevToolsAgent::InterruptAndDispatch(int session_id, |
| MessageDescriptor* raw_descriptor) { |
| // rawDescriptor can't be a std::unique_ptr because interruptAndDispatch is a |
| // WebKit API function. |
| MainThreadDebugger::InterruptMainThreadAndRun( |
| CrossThreadBind(WebDevToolsAgentImpl::RunDebuggerTask, session_id, |
| WTF::Passed(WTF::WrapUnique(raw_descriptor)))); |
| } |
| |
| bool WebDevToolsAgent::ShouldInterruptForMethod(const WebString& method) { |
| return method == "Debugger.pause" || method == "Debugger.setBreakpoint" || |
| method == "Debugger.setBreakpointByUrl" || |
| method == "Debugger.removeBreakpoint" || |
| method == "Debugger.setBreakpointsActive"; |
| } |
| |
| } // namespace blink |