summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb/Page
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-11-29 16:39:56 +0100
committerAndreas Kling <kling@serenityos.org>2020-11-29 16:43:12 +0100
commit2dd03a4200463ca5b2387edc227db4da7071ed5b (patch)
tree2f49e98f75e1fd0abf0bde7dcf3238e1988d917e /Libraries/LibWeb/Page
parent4ebb57298b72e39d6a7439ffaf343d040fa6b2ca (diff)
downloadserenity-2dd03a4200463ca5b2387edc227db4da7071ed5b.zip
LibWeb: Abort event handling if underlying layout tree disappears
We didn't notice that the layout tree had disappeared after dispatching a mousedown event, because we only checked EventHandler::layout_root() which happily returned the *new* layout tree after a window.reload(). This patch fixes that by verifying that the frame is still showing the same DOM's layout tree after event dispatch. Fixes #4224.
Diffstat (limited to 'Libraries/LibWeb/Page')
-rw-r--r--Libraries/LibWeb/Page/EventHandler.cpp50
1 files changed, 28 insertions, 22 deletions
diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp
index 8cd28f59dc..0f2ef8951f 100644
--- a/Libraries/LibWeb/Page/EventHandler.cpp
+++ b/Libraries/LibWeb/Page/EventHandler.cpp
@@ -126,34 +126,39 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt
}
NonnullRefPtr document = *m_frame.document();
+ RefPtr<DOM::Node> node;
- auto result = layout_root()->hit_test(position, Layout::HitTestType::Exact);
- if (!result.layout_node)
- return false;
+ {
+ auto result = layout_root()->hit_test(position, Layout::HitTestType::Exact);
+ if (!result.layout_node)
+ return false;
- RefPtr<DOM::Node> node = result.layout_node->dom_node();
- document->set_hovered_node(node);
+ node = result.layout_node->dom_node();
+ document->set_hovered_node(node);
- if (result.layout_node->wants_mouse_events()) {
- result.layout_node->handle_mousedown({}, position, button, modifiers);
- return true;
- }
+ if (result.layout_node->wants_mouse_events()) {
+ result.layout_node->handle_mousedown({}, position, button, modifiers);
+ return true;
+ }
- if (!node)
- return false;
+ if (!node)
+ return false;
- if (is<HTML::HTMLIFrameElement>(*node)) {
- if (auto* subframe = downcast<HTML::HTMLIFrameElement>(*node).content_frame())
- return subframe->event_handler().handle_mousedown(position.translated(compute_mouse_event_offset({}, *result.layout_node)), button, modifiers);
- return false;
- }
+ if (is<HTML::HTMLIFrameElement>(*node)) {
+ if (auto* subframe = downcast<HTML::HTMLIFrameElement>(*node).content_frame())
+ return subframe->event_handler().handle_mousedown(position.translated(compute_mouse_event_offset({}, *result.layout_node)), button, modifiers);
+ return false;
+ }
- if (auto* page = m_frame.page())
- page->set_focused_frame({}, m_frame);
+ if (auto* page = m_frame.page())
+ page->set_focused_frame({}, m_frame);
- auto offset = compute_mouse_event_offset(position, *result.layout_node);
- node->dispatch_event(UIEvents::MouseEvent::create(UIEvents::EventNames::mousedown, offset.x(), offset.y()));
- if (!layout_root())
+ auto offset = compute_mouse_event_offset(position, *result.layout_node);
+ node->dispatch_event(UIEvents::MouseEvent::create(UIEvents::EventNames::mousedown, offset.x(), offset.y()));
+ }
+
+ // NOTE: Dispatching an event may have disturbed the world.
+ if (!layout_root() || layout_root() != node->document().layout_node())
return true;
if (button == GUI::MouseButton::Right && is<HTML::HTMLImageElement>(*node)) {
@@ -255,7 +260,8 @@ bool EventHandler::handle_mousemove(const Gfx::IntPoint& position, unsigned butt
is_hovering_link = true;
auto offset = compute_mouse_event_offset(position, *result.layout_node);
node->dispatch_event(UIEvents::MouseEvent::create(UIEvents::EventNames::mousemove, offset.x(), offset.y()));
- if (!layout_root())
+ // NOTE: Dispatching an event may have disturbed the world.
+ if (!layout_root() || layout_root() != node->document().layout_node())
return true;
}
if (m_in_mouse_selection) {