blob: 850d2831fd8e1b23406e069122179f472a6e8bae [file] [log] [blame]
/*
* Copyright (C) 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:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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/InspectorOverlay.h"
#include <memory>
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8InspectorOverlayHost.h"
#include "core/dom/Node.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameClient.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/input/EventHandler.h"
#include "core/inspector/InspectorOverlayHost.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/loader/EmptyClients.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/paint/CullRect.h"
#include "platform/wtf/AutoReset.h"
#include "public/platform/Platform.h"
#include "public/platform/WebData.h"
#include "v8/include/v8.h"
#include "web/ChromeClientImpl.h"
#include "web/PageOverlay.h"
#include "web/WebInputEventConversion.h"
#include "web/WebLocalFrameImpl.h"
namespace blink {
namespace {
Node* HoveredNodeForPoint(LocalFrame* frame,
const IntPoint& point_in_root_frame,
bool ignore_pointer_events_none) {
HitTestRequest::HitTestRequestType hit_type =
HitTestRequest::kMove | HitTestRequest::kReadOnly |
HitTestRequest::kAllowChildFrameContent;
if (ignore_pointer_events_none)
hit_type |= HitTestRequest::kIgnorePointerEventsNone;
HitTestRequest request(hit_type);
HitTestResult result(request,
frame->View()->RootFrameToContents(point_in_root_frame));
frame->ContentLayoutItem().HitTest(result);
Node* node = result.InnerPossiblyPseudoNode();
while (node && node->getNodeType() == Node::kTextNode)
node = node->parentNode();
return node;
}
Node* HoveredNodeForEvent(LocalFrame* frame,
const WebGestureEvent& event,
bool ignore_pointer_events_none) {
return HoveredNodeForPoint(frame,
RoundedIntPoint(event.PositionInRootFrame()),
ignore_pointer_events_none);
}
Node* HoveredNodeForEvent(LocalFrame* frame,
const WebMouseEvent& event,
bool ignore_pointer_events_none) {
return HoveredNodeForPoint(frame,
RoundedIntPoint(event.PositionInRootFrame()),
ignore_pointer_events_none);
}
Node* HoveredNodeForEvent(LocalFrame* frame,
const WebTouchEvent& event,
bool ignore_pointer_events_none) {
if (!event.touches_length)
return nullptr;
WebTouchPoint transformed_point = event.TouchPointInRootFrame(0);
return HoveredNodeForPoint(frame, RoundedIntPoint(transformed_point.position),
ignore_pointer_events_none);
}
} // namespace
class InspectorOverlay::InspectorPageOverlayDelegate final
: public PageOverlay::Delegate {
public:
explicit InspectorPageOverlayDelegate(InspectorOverlay& overlay)
: overlay_(&overlay) {}
void PaintPageOverlay(const PageOverlay&,
GraphicsContext& graphics_context,
const WebSize& web_view_size) const override {
if (overlay_->IsEmpty())
return;
FrameView* view = overlay_->OverlayMainFrame()->View();
DCHECK(!view->NeedsLayout());
view->Paint(graphics_context,
CullRect(IntRect(0, 0, view->Width(), view->Height())));
}
private:
Persistent<InspectorOverlay> overlay_;
};
class InspectorOverlay::InspectorOverlayChromeClient final
: public EmptyChromeClient {
public:
static InspectorOverlayChromeClient* Create(ChromeClient& client,
InspectorOverlay& overlay) {
return new InspectorOverlayChromeClient(client, overlay);
}
DEFINE_INLINE_VIRTUAL_TRACE() {
visitor->Trace(client_);
visitor->Trace(overlay_);
EmptyChromeClient::Trace(visitor);
}
void SetCursor(const Cursor& cursor, LocalFrame* local_root) override {
ToChromeClientImpl(client_)->SetCursorOverridden(false);
ToChromeClientImpl(client_)->SetCursor(cursor,
overlay_->frame_impl_->GetFrame());
ToChromeClientImpl(client_)->SetCursorOverridden(false);
}
void SetToolTip(LocalFrame& frame,
const String& tooltip,
TextDirection direction) override {
DCHECK_EQ(&frame, overlay_->OverlayMainFrame());
client_->SetToolTip(*overlay_->frame_impl_->GetFrame(), tooltip, direction);
}
void InvalidateRect(const IntRect&) override { overlay_->Invalidate(); }
void ScheduleAnimation(LocalFrame* frame) override {
if (overlay_->in_layout_)
return;
client_->ScheduleAnimation(frame);
}
private:
InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay& overlay)
: client_(&client), overlay_(&overlay) {}
Member<ChromeClient> client_;
Member<InspectorOverlay> overlay_;
};
InspectorOverlay::InspectorOverlay(WebLocalFrameImpl* frame_impl)
: frame_impl_(frame_impl),
overlay_host_(InspectorOverlayHost::Create()),
draw_view_size_(false),
resize_timer_active_(false),
omit_tooltip_(false),
timer_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer,
frame_impl->GetFrame()),
this,
&InspectorOverlay::OnTimer),
suspended_(false),
show_reloading_blanket_(false),
in_layout_(false),
needs_update_(false),
swallow_next_mouse_up_(false),
inspect_mode_(InspectorDOMAgent::kNotSearching) {}
InspectorOverlay::~InspectorOverlay() {
DCHECK(!overlay_page_);
}
DEFINE_TRACE(InspectorOverlay) {
visitor->Trace(frame_impl_);
visitor->Trace(highlight_node_);
visitor->Trace(event_target_node_);
visitor->Trace(overlay_page_);
visitor->Trace(overlay_chrome_client_);
visitor->Trace(overlay_host_);
visitor->Trace(dom_agent_);
visitor->Trace(hovered_node_for_inspect_mode_);
}
void InspectorOverlay::Init(v8_inspector::V8InspectorSession* v8_session,
InspectorDOMAgent* dom_agent) {
v8_session_ = v8_session;
dom_agent_ = dom_agent;
overlay_host_->SetListener(this);
}
void InspectorOverlay::Invalidate() {
if (!page_overlay_) {
page_overlay_ = PageOverlay::Create(
frame_impl_, WTF::WrapUnique(new InspectorPageOverlayDelegate(*this)));
}
page_overlay_->Update();
}
void InspectorOverlay::UpdateAllLifecyclePhases() {
if (IsEmpty())
return;
AutoReset<bool> scoped(&in_layout_, true);
if (needs_update_) {
needs_update_ = false;
RebuildOverlayPage();
}
OverlayMainFrame()->View()->UpdateAllLifecyclePhases();
}
bool InspectorOverlay::HandleInputEvent(const WebInputEvent& input_event) {
bool handled = false;
if (IsEmpty())
return false;
if (input_event.GetType() == WebInputEvent::kGestureTap) {
// We only have a use for gesture tap.
WebGestureEvent transformed_event = TransformWebGestureEvent(
frame_impl_->GetFrameView(),
static_cast<const WebGestureEvent&>(input_event));
handled = HandleGestureEvent(transformed_event);
if (handled)
return true;
OverlayMainFrame()->GetEventHandler().HandleGestureEvent(transformed_event);
}
if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
WebMouseEvent mouse_event =
TransformWebMouseEvent(frame_impl_->GetFrameView(),
static_cast<const WebMouseEvent&>(input_event));
if (mouse_event.GetType() == WebInputEvent::kMouseMove)
handled = HandleMouseMove(mouse_event);
else if (mouse_event.GetType() == WebInputEvent::kMouseDown)
handled = HandleMouseDown();
else if (mouse_event.GetType() == WebInputEvent::kMouseUp)
handled = HandleMouseUp();
if (handled)
return true;
if (mouse_event.GetType() == WebInputEvent::kMouseMove) {
handled = OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
mouse_event, TransformWebMouseEventVector(
frame_impl_->GetFrameView(),
std::vector<const WebInputEvent*>())) !=
WebInputEventResult::kNotHandled;
}
if (mouse_event.GetType() == WebInputEvent::kMouseDown)
handled = OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
mouse_event) != WebInputEventResult::kNotHandled;
if (mouse_event.GetType() == WebInputEvent::kMouseUp)
handled = OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
mouse_event) != WebInputEventResult::kNotHandled;
}
if (WebInputEvent::IsTouchEventType(input_event.GetType())) {
WebTouchEvent transformed_event =
TransformWebTouchEvent(frame_impl_->GetFrameView(),
static_cast<const WebTouchEvent&>(input_event));
handled = HandleTouchEvent(transformed_event);
if (handled)
return true;
OverlayMainFrame()->GetEventHandler().HandleTouchEvent(
transformed_event, Vector<WebTouchEvent>());
}
if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
OverlayMainFrame()->GetEventHandler().KeyEvent(
static_cast<const WebKeyboardEvent&>(input_event));
}
if (input_event.GetType() == WebInputEvent::kMouseWheel) {
WebMouseWheelEvent transformed_event = TransformWebMouseWheelEvent(
frame_impl_->GetFrameView(),
static_cast<const WebMouseWheelEvent&>(input_event));
handled = OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
transformed_event) != WebInputEventResult::kNotHandled;
}
return handled;
}
void InspectorOverlay::SetPausedInDebuggerMessage(const String& message) {
paused_in_debugger_message_ = message;
ScheduleUpdate();
}
void InspectorOverlay::ShowReloadingBlanket() {
show_reloading_blanket_ = true;
ScheduleUpdate();
}
void InspectorOverlay::HideReloadingBlanket() {
if (!show_reloading_blanket_)
return;
show_reloading_blanket_ = false;
if (suspended_)
ClearInternal();
else
ScheduleUpdate();
}
void InspectorOverlay::HideHighlight() {
highlight_node_.Clear();
event_target_node_.Clear();
highlight_quad_.reset();
ScheduleUpdate();
}
void InspectorOverlay::HighlightNode(
Node* node,
const InspectorHighlightConfig& highlight_config,
bool omit_tooltip) {
HighlightNode(node, nullptr, highlight_config, omit_tooltip);
}
void InspectorOverlay::HighlightNode(
Node* node,
Node* event_target,
const InspectorHighlightConfig& highlight_config,
bool omit_tooltip) {
node_highlight_config_ = highlight_config;
highlight_node_ = node;
event_target_node_ = event_target;
omit_tooltip_ = omit_tooltip;
ScheduleUpdate();
}
void InspectorOverlay::SetInspectMode(
InspectorDOMAgent::SearchMode search_mode,
std::unique_ptr<InspectorHighlightConfig> highlight_config) {
inspect_mode_ = search_mode;
ScheduleUpdate();
if (search_mode != InspectorDOMAgent::kNotSearching) {
inspect_mode_highlight_config_ = std::move(highlight_config);
} else {
hovered_node_for_inspect_mode_.Clear();
HideHighlight();
}
}
void InspectorOverlay::HighlightQuad(
std::unique_ptr<FloatQuad> quad,
const InspectorHighlightConfig& highlight_config) {
quad_highlight_config_ = highlight_config;
highlight_quad_ = std::move(quad);
omit_tooltip_ = false;
ScheduleUpdate();
}
bool InspectorOverlay::IsEmpty() {
if (show_reloading_blanket_)
return false;
if (suspended_)
return true;
bool has_visible_elements = highlight_node_ || event_target_node_ ||
highlight_quad_ ||
(resize_timer_active_ && draw_view_size_) ||
!paused_in_debugger_message_.IsNull();
return !has_visible_elements &&
inspect_mode_ == InspectorDOMAgent::kNotSearching;
}
void InspectorOverlay::ScheduleUpdate() {
if (IsEmpty()) {
if (page_overlay_)
page_overlay_.reset();
return;
}
needs_update_ = true;
LocalFrame* frame = frame_impl_->GetFrame();
if (frame) {
frame->GetPage()->GetChromeClient().ScheduleAnimation(frame);
}
}
void InspectorOverlay::RebuildOverlayPage() {
FrameView* view = frame_impl_->GetFrameView();
LocalFrame* frame = frame_impl_->GetFrame();
if (!view || !frame)
return;
IntRect visible_rect_in_document =
view->GetScrollableArea()->VisibleContentRect();
IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
OverlayMainFrame()->View()->Resize(viewport_size);
OverlayPage()->GetVisualViewport().SetSize(viewport_size);
OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale());
Reset(viewport_size, visible_rect_in_document.Location());
if (show_reloading_blanket_) {
EvaluateInOverlay("showReloadingBlanket", "");
return;
}
DrawNodeHighlight();
DrawQuadHighlight();
DrawPausedInDebuggerMessage();
DrawViewSize();
}
static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
const IntSize& size) {
std::unique_ptr<protocol::DictionaryValue> result =
protocol::DictionaryValue::create();
result->setInteger("width", size.Width());
result->setInteger("height", size.Height());
return result;
}
void InspectorOverlay::DrawNodeHighlight() {
if (!highlight_node_)
return;
String selectors = node_highlight_config_.selector_list;
StaticElementList* elements = nullptr;
DummyExceptionStateForTesting exception_state;
ContainerNode* query_base = highlight_node_->ContainingShadowRoot();
if (!query_base)
query_base = highlight_node_->ownerDocument();
if (selectors.length())
elements =
query_base->QuerySelectorAll(AtomicString(selectors), exception_state);
if (elements && !exception_state.HadException()) {
for (unsigned i = 0; i < elements->length(); ++i) {
Element* element = elements->item(i);
InspectorHighlight highlight(element, node_highlight_config_, false);
std::unique_ptr<protocol::DictionaryValue> highlight_json =
highlight.AsProtocolValue();
EvaluateInOverlay("drawHighlight", std::move(highlight_json));
}
}
bool append_element_info =
highlight_node_->IsElementNode() && !omit_tooltip_ &&
node_highlight_config_.show_info && highlight_node_->GetLayoutObject() &&
highlight_node_->GetDocument().GetFrame();
InspectorHighlight highlight(highlight_node_.Get(), node_highlight_config_,
append_element_info);
if (event_target_node_)
highlight.AppendEventTargetQuads(event_target_node_.Get(),
node_highlight_config_);
std::unique_ptr<protocol::DictionaryValue> highlight_json =
highlight.AsProtocolValue();
EvaluateInOverlay("drawHighlight", std::move(highlight_json));
}
void InspectorOverlay::DrawQuadHighlight() {
if (!highlight_quad_)
return;
InspectorHighlight highlight(WindowToViewportScale());
highlight.AppendQuad(*highlight_quad_, quad_highlight_config_.content,
quad_highlight_config_.content_outline);
EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue());
}
void InspectorOverlay::DrawPausedInDebuggerMessage() {
if (inspect_mode_ == InspectorDOMAgent::kNotSearching &&
!paused_in_debugger_message_.IsNull())
EvaluateInOverlay("drawPausedInDebuggerMessage",
paused_in_debugger_message_);
}
void InspectorOverlay::DrawViewSize() {
if (resize_timer_active_ && draw_view_size_)
EvaluateInOverlay("drawViewSize", "");
}
float InspectorOverlay::WindowToViewportScale() const {
LocalFrame* frame = frame_impl_->GetFrame();
if (!frame)
return 1.0f;
return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f);
}
Page* InspectorOverlay::OverlayPage() {
if (overlay_page_)
return overlay_page_.Get();
ScriptForbiddenScope::AllowUserAgentScript allow_script;
DEFINE_STATIC_LOCAL(LocalFrameClient, dummy_local_frame_client,
(EmptyLocalFrameClient::Create()));
Page::PageClients page_clients;
FillWithEmptyClients(page_clients);
DCHECK(!overlay_chrome_client_);
overlay_chrome_client_ = InspectorOverlayChromeClient::Create(
frame_impl_->GetFrame()->GetPage()->GetChromeClient(), *this);
page_clients.chrome_client = overlay_chrome_client_.Get();
overlay_page_ = Page::Create(page_clients);
Settings& settings = frame_impl_->GetFrame()->GetPage()->GetSettings();
Settings& overlay_settings = overlay_page_->GetSettings();
overlay_settings.GetGenericFontFamilySettings().UpdateStandard(
settings.GetGenericFontFamilySettings().Standard());
overlay_settings.GetGenericFontFamilySettings().UpdateSerif(
settings.GetGenericFontFamilySettings().Serif());
overlay_settings.GetGenericFontFamilySettings().UpdateSansSerif(
settings.GetGenericFontFamilySettings().SansSerif());
overlay_settings.GetGenericFontFamilySettings().UpdateCursive(
settings.GetGenericFontFamilySettings().Cursive());
overlay_settings.GetGenericFontFamilySettings().UpdateFantasy(
settings.GetGenericFontFamilySettings().Fantasy());
overlay_settings.GetGenericFontFamilySettings().UpdatePictograph(
settings.GetGenericFontFamilySettings().Pictograph());
overlay_settings.SetMinimumFontSize(settings.GetMinimumFontSize());
overlay_settings.SetMinimumLogicalFontSize(
settings.GetMinimumLogicalFontSize());
overlay_settings.SetScriptEnabled(true);
overlay_settings.SetPluginsEnabled(false);
overlay_settings.SetLoadsImagesAutomatically(true);
// FIXME: http://crbug.com/363843. Inspector should probably create its
// own graphics layers and attach them to the tree rather than going
// through some non-composited paint function.
overlay_settings.SetAcceleratedCompositingEnabled(false);
LocalFrame* frame =
LocalFrame::Create(&dummy_local_frame_client, *overlay_page_, 0);
frame->SetView(FrameView::Create(*frame));
frame->Init();
FrameLoader& loader = frame->Loader();
frame->View()->SetCanHaveScrollbars(false);
frame->View()->SetBaseBackgroundColor(Color::kTransparent);
const WebData& overlay_page_html_resource =
Platform::Current()->LoadResource("InspectorOverlayPage.html");
loader.Load(
FrameLoadRequest(0, ResourceRequest(BlankURL()),
SubstituteData(overlay_page_html_resource, "text/html",
"UTF-8", KURL(), kForceSynchronousLoad)));
v8::Isolate* isolate = ToIsolate(frame);
ScriptState* script_state = ToScriptStateForMainWorld(frame);
DCHECK(script_state);
ScriptState::Scope scope(script_state);
v8::Local<v8::Object> global = script_state->GetContext()->Global();
v8::Local<v8::Value> overlay_host_obj =
ToV8(overlay_host_.Get(), global, isolate);
DCHECK(!overlay_host_obj.IsEmpty());
global
->Set(script_state->GetContext(),
V8AtomicString(isolate, "InspectorOverlayHost"), overlay_host_obj)
.ToChecked();
#if OS(WIN)
EvaluateInOverlay("setPlatform", "windows");
#elif OS(MACOSX)
EvaluateInOverlay("setPlatform", "mac");
#elif OS(POSIX)
EvaluateInOverlay("setPlatform", "linux");
#endif
return overlay_page_.Get();
}
LocalFrame* InspectorOverlay::OverlayMainFrame() {
return ToLocalFrame(OverlayPage()->MainFrame());
}
void InspectorOverlay::Reset(const IntSize& viewport_size,
const IntPoint& document_scroll_offset) {
std::unique_ptr<protocol::DictionaryValue> reset_data =
protocol::DictionaryValue::create();
reset_data->setDouble(
"deviceScaleFactor",
frame_impl_->GetFrame()->GetPage()->DeviceScaleFactorDeprecated());
reset_data->setDouble(
"pageScaleFactor",
frame_impl_->GetFrame()->GetPage()->GetVisualViewport().Scale());
IntRect viewport_in_screen =
frame_impl_->GetFrame()->GetPage()->GetChromeClient().ViewportToScreen(
IntRect(IntPoint(), viewport_size), frame_impl_->GetFrame()->View());
reset_data->setObject("viewportSize",
BuildObjectForSize(viewport_in_screen.Size()));
// The zoom factor in the overlay frame already has been multiplied by the
// window to viewport scale (aka device scale factor), so cancel it.
reset_data->setDouble(
"pageZoomFactor",
frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale());
reset_data->setInteger("scrollX", document_scroll_offset.X());
reset_data->setInteger("scrollY", document_scroll_offset.Y());
EvaluateInOverlay("reset", std::move(reset_data));
}
void InspectorOverlay::EvaluateInOverlay(const String& method,
const String& argument) {
ScriptForbiddenScope::AllowUserAgentScript allow_script;
std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
command->pushValue(protocol::StringValue::create(method));
command->pushValue(protocol::StringValue::create(argument));
ToLocalFrame(OverlayPage()->MainFrame())
->GetScriptController()
.ExecuteScriptInMainWorld(
"dispatch(" + command->serialize() + ")",
ScriptController::kExecuteScriptWhenScriptsDisabled);
}
void InspectorOverlay::EvaluateInOverlay(
const String& method,
std::unique_ptr<protocol::Value> argument) {
ScriptForbiddenScope::AllowUserAgentScript allow_script;
std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
command->pushValue(protocol::StringValue::create(method));
command->pushValue(std::move(argument));
ToLocalFrame(OverlayPage()->MainFrame())
->GetScriptController()
.ExecuteScriptInMainWorld(
"dispatch(" + command->serialize() + ")",
ScriptController::kExecuteScriptWhenScriptsDisabled);
}
String InspectorOverlay::EvaluateInOverlayForTest(const String& script) {
ScriptForbiddenScope::AllowUserAgentScript allow_script;
v8::HandleScope handle_scope(ToIsolate(OverlayMainFrame()));
v8::Local<v8::Value> string =
ToLocalFrame(OverlayPage()->MainFrame())
->GetScriptController()
.ExecuteScriptInMainWorldAndReturnValue(
ScriptSourceCode(script),
ScriptController::kExecuteScriptWhenScriptsDisabled);
return ToCoreStringWithUndefinedOrNullCheck(string);
}
void InspectorOverlay::OnTimer(TimerBase*) {
resize_timer_active_ = false;
ScheduleUpdate();
}
void InspectorOverlay::ClearInternal() {
if (overlay_page_) {
overlay_page_->WillBeDestroyed();
overlay_page_.Clear();
overlay_chrome_client_.Clear();
}
resize_timer_active_ = false;
paused_in_debugger_message_ = String();
inspect_mode_ = InspectorDOMAgent::kNotSearching;
timer_.Stop();
HideHighlight();
}
void InspectorOverlay::Clear() {
ClearInternal();
v8_session_ = nullptr;
dom_agent_.Clear();
overlay_host_->SetListener(nullptr);
}
void InspectorOverlay::OverlayResumed() {
if (v8_session_)
v8_session_->resume();
}
void InspectorOverlay::OverlaySteppedOver() {
if (v8_session_)
v8_session_->stepOver();
}
void InspectorOverlay::Suspend() {
if (!suspended_) {
suspended_ = true;
ClearInternal();
}
}
void InspectorOverlay::Resume() {
suspended_ = false;
}
void InspectorOverlay::PageLayoutInvalidated(bool resized) {
if (resized && draw_view_size_) {
resize_timer_active_ = true;
timer_.StartOneShot(1, BLINK_FROM_HERE);
}
ScheduleUpdate();
}
void InspectorOverlay::SetShowViewportSizeOnResize(bool show) {
draw_view_size_ = show;
}
bool InspectorOverlay::HandleMouseMove(const WebMouseEvent& event) {
if (!ShouldSearchForNode())
return false;
LocalFrame* frame = frame_impl_->GetFrame();
if (!frame || !frame->View() || frame->ContentLayoutItem().IsNull())
return false;
Node* node = HoveredNodeForEvent(
frame, event, event.GetModifiers() & WebInputEvent::kShiftKey);
// Do not highlight within user agent shadow root unless requested.
if (inspect_mode_ != InspectorDOMAgent::kSearchingForUAShadow) {
ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node);
if (shadow_root)
node = &shadow_root->host();
}
// Shadow roots don't have boxes - use host element instead.
if (node && node->IsShadowRoot())
node = node->ParentOrShadowHostNode();
if (!node)
return true;
if (node->IsFrameOwnerElement()) {
HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(node);
if (frame_owner->ContentFrame() &&
!frame_owner->ContentFrame()->IsLocalFrame()) {
// Do not consume event so that remote frame can handle it.
HideHighlight();
hovered_node_for_inspect_mode_.Clear();
return false;
}
}
Node* event_target = (event.GetModifiers() & WebInputEvent::kShiftKey)
? HoveredNodeForEvent(frame, event, false)
: nullptr;
if (event_target == node)
event_target = nullptr;
if (node && inspect_mode_highlight_config_) {
hovered_node_for_inspect_mode_ = node;
if (dom_agent_)
dom_agent_->NodeHighlightedInOverlay(node);
HighlightNode(node, event_target, *inspect_mode_highlight_config_,
(event.GetModifiers() &
(WebInputEvent::kControlKey | WebInputEvent::kMetaKey)));
}
return true;
}
bool InspectorOverlay::HandleMouseDown() {
swallow_next_mouse_up_ = false;
if (!ShouldSearchForNode())
return false;
if (hovered_node_for_inspect_mode_) {
swallow_next_mouse_up_ = true;
Inspect(hovered_node_for_inspect_mode_.Get());
hovered_node_for_inspect_mode_.Clear();
return true;
}
return false;
}
bool InspectorOverlay::HandleMouseUp() {
if (swallow_next_mouse_up_) {
swallow_next_mouse_up_ = false;
return true;
}
return false;
}
bool InspectorOverlay::HandleGestureEvent(const WebGestureEvent& event) {
if (!ShouldSearchForNode() || event.GetType() != WebInputEvent::kGestureTap)
return false;
Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
if (node && inspect_mode_highlight_config_) {
HighlightNode(node, *inspect_mode_highlight_config_, false);
Inspect(node);
return true;
}
return false;
}
bool InspectorOverlay::HandleTouchEvent(const WebTouchEvent& event) {
if (!ShouldSearchForNode())
return false;
Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false);
if (node && inspect_mode_highlight_config_) {
HighlightNode(node, *inspect_mode_highlight_config_, false);
Inspect(node);
return true;
}
return false;
}
bool InspectorOverlay::ShouldSearchForNode() {
return inspect_mode_ != InspectorDOMAgent::kNotSearching;
}
void InspectorOverlay::Inspect(Node* node) {
if (dom_agent_)
dom_agent_->Inspect(node);
}
} // namespace blink