Index: third_party/WebKit/Source/core/input/MouseEventManager.cpp |
diff --git a/third_party/WebKit/Source/core/input/MouseEventManager.cpp b/third_party/WebKit/Source/core/input/MouseEventManager.cpp |
index 966780376fb1bc7464f78fdc74413cb579749d3d..00d486c843cb318e8b153b3c310122f4b098cd3a 100644 |
--- a/third_party/WebKit/Source/core/input/MouseEventManager.cpp |
+++ b/third_party/WebKit/Source/core/input/MouseEventManager.cpp |
@@ -30,6 +30,7 @@ |
#include "core/page/FocusController.h" |
#include "core/paint/PaintLayer.h" |
#include "core/svg/SVGDocumentExtensions.h" |
+#include "platform/Histogram.h" |
#include "platform/geometry/FloatQuad.h" |
namespace blink { |
@@ -95,6 +96,7 @@ void MouseEventManager::Clear() { |
mouse_pressed_ = false; |
click_count_ = 0; |
click_element_ = nullptr; |
+ mouse_down_element_ = nullptr; |
mouse_down_pos_ = IntPoint(); |
mouse_down_timestamp_ = TimeTicks(); |
mouse_down_ = WebMouseEvent(); |
@@ -112,6 +114,7 @@ DEFINE_TRACE(MouseEventManager) { |
visitor->Trace(node_under_mouse_); |
visitor->Trace(mouse_press_node_); |
visitor->Trace(click_element_); |
+ visitor->Trace(mouse_down_element_); |
SynchronousMutationObserver::Trace(visitor); |
} |
@@ -249,9 +252,10 @@ WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded( |
#endif |
const bool should_dispatch_click_event = |
- click_count_ > 0 && !context_menu_event && click_element_ && |
+ click_count_ > 0 && !context_menu_event && mouse_down_element_ && |
mouse_release_target.CanParticipateInFlatTree() && |
- click_element_->CanParticipateInFlatTree() && |
+ mouse_down_element_->CanParticipateInFlatTree() && |
+ mouse_down_element_->isConnected() && |
!(frame_->GetEventHandler() |
.GetSelectionController() |
.HasExtendedSelection() && |
@@ -260,27 +264,45 @@ WebInputEventResult MouseEventManager::DispatchMouseClickIfNeeded( |
return WebInputEventResult::kNotHandled; |
Node* click_target_node = nullptr; |
- if (click_element_ == mouse_release_target) { |
- click_target_node = click_element_; |
- } else if (click_element_->GetDocument() == |
+ if (mouse_down_element_ == mouse_release_target) { |
+ click_target_node = mouse_down_element_; |
+ } else if (mouse_down_element_->GetDocument() == |
mouse_release_target.GetDocument()) { |
// Updates distribution because a 'mouseup' event listener can make the |
// tree dirty at dispatchMouseEvent() invocation above. |
// Unless distribution is updated, commonAncestor would hit ASSERT. |
- click_element_->UpdateDistribution(); |
+ mouse_down_element_->UpdateDistribution(); |
mouse_release_target.UpdateDistribution(); |
click_target_node = mouse_release_target.CommonAncestor( |
- *click_element_, EventHandlingUtil::ParentForClickEvent); |
+ *mouse_down_element_, EventHandlingUtil::ParentForClickEvent); |
} |
if (!click_target_node) |
return WebInputEventResult::kNotHandled; |
- return DispatchMouseEvent( |
- click_target_node, |
- !RuntimeEnabledFeatures::auxclickEnabled() || |
- (mev.Event().button == WebPointerProperties::Button::kLeft) |
- ? EventTypeNames::click |
- : EventTypeNames::auxclick, |
- mev.Event(), mev.CanvasRegionId(), nullptr); |
+ |
+ DEFINE_STATIC_LOCAL(BooleanHistogram, histogram, |
+ ("Event.ClickNotFiredDueToDomManipulation")); |
+ |
+ if (click_element_ && click_element_->CanParticipateInFlatTree() && |
+ click_element_->isConnected()) { |
+ DCHECK(click_element_ == mouse_down_element_); |
+ histogram.Count(false); |
+ } else { |
+ histogram.Count(true); |
+ } |
+ |
+ if ((click_element_ && click_element_->CanParticipateInFlatTree() && |
+ click_element_->isConnected()) || |
+ RuntimeEnabledFeatures::clickRetargettingEnabled()) { |
+ return DispatchMouseEvent( |
+ click_target_node, |
+ !RuntimeEnabledFeatures::auxclickEnabled() || |
+ (mev.Event().button == WebPointerProperties::Button::kLeft) |
+ ? EventTypeNames::click |
+ : EventTypeNames::auxclick, |
+ mev.Event(), mev.CanvasRegionId(), nullptr); |
+ } |
+ |
+ return WebInputEventResult::kNotHandled; |
} |
void MouseEventManager::FakeMouseMoveEventTimerFired(TimerBase* timer) { |
@@ -386,6 +408,9 @@ void MouseEventManager::NodeChildrenWillBeRemoved(ContainerNode& container) { |
if (!container.IsShadowIncludingInclusiveAncestorOf(click_element_.Get())) |
return; |
click_element_ = nullptr; |
+ |
+ // TODO(crbug.com/716694): Do not reset mouse_down_element_ for the purpose of |
+ // gathering data. |
} |
void MouseEventManager::NodeWillBeRemoved(Node& node_to_be_removed) { |
@@ -394,6 +419,9 @@ void MouseEventManager::NodeWillBeRemoved(Node& node_to_be_removed) { |
// We don't dispatch click events if the mousedown node is removed |
// before a mouseup event. It is compatible with IE and Firefox. |
click_element_ = nullptr; |
+ |
+ // TODO(crbug.com/716694): Do not reset mouse_down_element_ for the purpose |
+ // of gathering data. |
} |
} |
@@ -999,6 +1027,7 @@ bool MouseEventManager::HandleSvgPanIfNeeded(bool is_release_event) { |
void MouseEventManager::InvalidateClick() { |
click_count_ = 0; |
click_element_ = nullptr; |
+ mouse_down_element_ = nullptr; |
} |
bool MouseEventManager::MousePressed() { |
@@ -1028,6 +1057,7 @@ void MouseEventManager::SetMousePressNode(Node* node) { |
void MouseEventManager::SetClickElement(Element* element) { |
SetContext(element ? element->ownerDocument() : nullptr); |
click_element_ = element; |
+ mouse_down_element_ = element; |
} |
void MouseEventManager::SetClickCount(int click_count) { |