Input element gains focus when a selectstart event listener on document prevents...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Nov 2018 00:12:25 +0000 (00:12 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Nov 2018 00:12:25 +0000 (00:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191714
<rdar://problem/46174389>

Reviewed by Antti Koivisto.

Source/WebCore:

The bug was caused by WebKit keep firing selectstart upon mousemove after the drag had already started
when preventDefault had been called in the previous firings of selectstart event. Because input element
has its own editable element and fires selectstart on the input element itself, which won't be prevented
by selectstart on docuemnt, this allowed the selection to be set inside the input element even though
the mouse cursor was simply passing over the input element after the drag had already started.

Fixed the bug by not firing selectstart if the default action had been prevented by the initial firing
of selectstart by setting m_mouseDownMayStartDrag to false. This also matches the behaviors of Chrome
and Firefox.

Test: fast/events/selectstart-prevent-default-should-not-focus-input.html

* page/EventHandler.cpp:
(WebCore::EventHandler::updateSelectionForMouseDownDispatchingSelectStart):
(WebCore::EventHandler::updateSelectionForMouseDrag):

LayoutTests:

Added a regression test.

* fast/events/selectstart-prevent-default-should-not-focus-input-expected.txt: Added.
* fast/events/selectstart-prevent-default-should-not-focus-input.html: Added.
* platform/ios/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238409 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/events/selectstart-prevent-default-should-not-focus-input-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/selectstart-prevent-default-should-not-focus-input.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp

index 5537332..5696faa 100644 (file)
@@ -1,3 +1,17 @@
+2018-11-20  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Input element gains focus when a selectstart event listener on document prevents the default action
+        https://bugs.webkit.org/show_bug.cgi?id=191714
+        <rdar://problem/46174389>
+
+        Reviewed by Antti Koivisto.
+
+        Added a regression test.
+
+        * fast/events/selectstart-prevent-default-should-not-focus-input-expected.txt: Added.
+        * fast/events/selectstart-prevent-default-should-not-focus-input.html: Added.
+        * platform/ios/TestExpectations:
+
 2018-11-19  Ryosuke Niwa  <rniwa@webkit.org>
 
         Click on node assigned to slot in button's shadow cause loss of button focus
diff --git a/LayoutTests/fast/events/selectstart-prevent-default-should-not-focus-input-expected.txt b/LayoutTests/fast/events/selectstart-prevent-default-should-not-focus-input-expected.txt
new file mode 100644 (file)
index 0000000..9209f43
--- /dev/null
@@ -0,0 +1,6 @@
+This tests that the input element does not get the focus when dragging mouse over it even when document has a selectstart event listener which prevents default.
+To manually test, drag a mouse cursor over the input element. The input element should not gain focus.
+
+
+selectstart event
+PASS - input element was not focused
diff --git a/LayoutTests/fast/events/selectstart-prevent-default-should-not-focus-input.html b/LayoutTests/fast/events/selectstart-prevent-default-should-not-focus-input.html
new file mode 100644 (file)
index 0000000..d3fcdad
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This tests that the input element does not get the focus when dragging mouse over it
+even when document has a selectstart event listener which prevents default.<br>
+To manually test, drag a mouse cursor over the input element.
+The input element should not gain focus.</p>
+<input type="text">
+<pre id="log"></pre>
+<script>
+
+document.addEventListener('selectstart', (event) => {
+    log.textContent += 'selectstart event\n';
+    event.preventDefault();
+});
+
+const input = document.querySelector('input');
+let inputElementWasFocused = false;
+input.addEventListener('focus', () => {
+    inputElementWasFocused = true;
+    log.textContent += 'FAIL - the input element was focused\n';
+});
+
+if (window.eventSender) {
+    testRunner.dumpAsText();
+
+    let x = input.offsetLeft + 5;
+    eventSender.mouseMoveTo(x, input.offsetTop - 5);
+    eventSender.mouseDown();
+    eventSender.leapForward(100);
+    eventSender.mouseMoveTo(x, input.offsetTop + 5);
+    eventSender.leapForward(100);
+    eventSender.mouseMoveTo(x, input.offsetTop + 100);
+    eventSender.mouseUp();
+
+    if (!inputElementWasFocused)
+        log.textContent += 'PASS - input element was not focused';
+
+} else
+    document.write('This test requires eventSender drag & drop support');
+
+</script>
+</body>
+</html>
index 28668e7..f46aece 100644 (file)
@@ -529,6 +529,7 @@ fast/events/selectstart-by-double-triple-clicks.html [ Skip ]
 fast/events/selectstart-by-drag.html [ Skip ]
 fast/events/selectstart-by-single-click-with-shift.html [ Skip ]
 fast/events/selectstart-prevent-selection-on-right-click.html [ Skip ]
+fast/events/selectstart-prevent-default-should-not-focus-input.html [ Skip ]
 fast/events/shadow-event-path-2.html [ Skip ]
 fast/events/shadow-event-path.html [ Skip ]
 fast/events/shift-drag-selection-on-image-triggers-drag-n-drop.html [ Skip ]
index af3210a..8b593a9 100644 (file)
@@ -1,3 +1,27 @@
+2018-11-20  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Input element gains focus when a selectstart event listener on document prevents the default action
+        https://bugs.webkit.org/show_bug.cgi?id=191714
+        <rdar://problem/46174389>
+
+        Reviewed by Antti Koivisto.
+
+        The bug was caused by WebKit keep firing selectstart upon mousemove after the drag had already started
+        when preventDefault had been called in the previous firings of selectstart event. Because input element
+        has its own editable element and fires selectstart on the input element itself, which won't be prevented
+        by selectstart on docuemnt, this allowed the selection to be set inside the input element even though
+        the mouse cursor was simply passing over the input element after the drag had already started.
+
+        Fixed the bug by not firing selectstart if the default action had been prevented by the initial firing
+        of selectstart by setting m_mouseDownMayStartDrag to false. This also matches the behaviors of Chrome
+        and Firefox.
+
+        Test: fast/events/selectstart-prevent-default-should-not-focus-input.html
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::updateSelectionForMouseDownDispatchingSelectStart):
+        (WebCore::EventHandler::updateSelectionForMouseDrag):
+
 2018-11-20  Christopher Reid  <chris.reid@sony.com>
 
         Remove the need for LocalizedStringsWPE.cpp
index 4d4eab5..d6e01be 100644 (file)
@@ -510,8 +510,10 @@ bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targe
     if (Position::nodeIsUserSelectNone(targetNode))
         return false;
 
-    if (!dispatchSelectStart(targetNode))
+    if (!dispatchSelectStart(targetNode)) {
+        m_mouseDownMayStartSelect = false;
         return false;
+    }
 
     if (selection.isRange())
         m_selectionInitiationState = ExtendedSelection;
@@ -953,14 +955,20 @@ void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul
 
     // Special case to limit selection to the containing block for SVG text.
     // FIXME: Isn't there a better non-SVG-specific way to do this?
-    if (Node* selectionBaseNode = newSelection.base().deprecatedNode())
-        if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
-            if (selectionBaseRenderer->isSVGText())
+    if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) {
+        if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer()) {
+            if (selectionBaseRenderer->isSVGText()) {
                 if (target->renderer()->containingBlock() != selectionBaseRenderer->containingBlock())
                     return;
+            }
+        }
+    }
+
 
-    if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target))
+    if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelectStart(target)) {
+        m_mouseDownMayStartSelect = false;
         return;
+    }
 
     if (m_selectionInitiationState != ExtendedSelection) {
         // Always extend selection here because it's caused by a mouse drag