Activate selection when interacting with editable content
https://bugs.webkit.org/show_bug.cgi?id=185017

Reviewed by Tim Horton.
        
Source/WebKit:

Fixes a regression from r231016 where selection now does not work when interacting with
editable content. When we go into editable content, we should turn on the assistant.
This fulfills the requirement of user interaction as well, so any javascript selections
after this point should be valid.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _startAssistingKeyboard]):
(-[WKContentView _stopAssistingKeyboard]):

LayoutTests:

Fixed double-tap-on-editable-and-noneditable test, as it was not actually written correctly.
Should actually double tap on correct content and check for the correct output now.
Added two more tests to make sure that selections really are happening in editable content. 

* fast/events/touch/ios/double-tap-on-editable-and-noneditable.html:
* fast/events/touch/ios/double-tap-on-editable-content-for-selection-expected.txt: Added.
* fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text-expected.txt: Added.
* fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text.html: Added.
* fast/events/touch/ios/double-tap-on-editable-content-for-selection.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231054 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 3fed954..552cef1 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,20 @@
+2018-04-25  Megan Gardner  <megan_gardner@apple.com>
+
+        Activate selection when interacting with editable content
+        https://bugs.webkit.org/show_bug.cgi?id=185017
+
+        Reviewed by Tim Horton.
+        
+        Fixed double-tap-on-editable-and-noneditable test, as it was not actually written correctly.
+        Should actually double tap on correct content and check for the correct output now.
+        Added two more tests to make sure that selections really are happening in editable content. 
+
+        * fast/events/touch/ios/double-tap-on-editable-and-noneditable.html:
+        * fast/events/touch/ios/double-tap-on-editable-content-for-selection-expected.txt: Added.
+        * fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text-expected.txt: Added.
+        * fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text.html: Added.
+        * fast/events/touch/ios/double-tap-on-editable-content-for-selection.html: Added.
+        
 2018-04-25  Brent Fulgham  <bfulgham@apple.com>
 
         Add port 548 (afpovertcp) to port blacklist
diff --git a/LayoutTests/fast/events/touch/ios/double-tap-on-editable-and-noneditable.html b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-and-noneditable.html
index a23727f..51c3ace 100644
--- a/LayoutTests/fast/events/touch/ios/double-tap-on-editable-and-noneditable.html
+++ b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-and-noneditable.html
@@ -27,13 +27,13 @@
                 output += 'FAIL: Has selection even though we should not. Incorrect Selection: ' + document.getSelection().toString();
             output += '<br>';
 
-            var editableTargetRect = document.getElementById('noneditableTapPoint').getBoundingClientRect();
+            var editableTargetRect = document.getElementById('editable').getBoundingClientRect();
 
             var editableTapPointX = editableTargetRect.x + editableTargetRect.width / 2;
             var editableTapPointY = editableTargetRect.y + editableTargetRect.height / 2;
 
-            await doubleTapAtPoint(noneditableTapPointX, noneditableTapPointY);
-            if (document.getSelection().type == "None")
+            await doubleTapAtPoint(editableTapPointX, editableTapPointY);
+            if (document.getSelection().type != "None")
                 output += 'PASS: Has Selection';
             else
                 output += 'FAIL: No selection even though we should have one.';
@@ -75,7 +75,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=1">
 </head>
 <body>
-
     <div id="noneditable">
         <p>Lorem ipsum dolor sit amet, <span id="noneditableTapPoint">consectetur</span> adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
     </div>
diff --git a/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-expected.txt b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-expected.txt
new file mode 100644
index 0000000..0fbcbb5
--- /dev/null
+++ b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-expected.txt
@@ -0,0 +1,3 @@
+PASS: Has Caret Selection
+PASS: Correct Selection
+
diff --git a/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text-expected.txt b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text-expected.txt
new file mode 100644
index 0000000..e4b6421
--- /dev/null
+++ b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text-expected.txt
@@ -0,0 +1,8 @@
+PASS: Has Caret Selection
+PASS: Correct Selection
+PASS: Correct Selection
+PASS: Correct Selection
+PASS: Correct Selection
+PASS: Correct Selection
+PASS: Correct Selection
+
diff --git a/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text.html b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text.html
new file mode 100644
index 0000000..320190c
--- /dev/null
+++ b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection-then-drag-right-to-change-selected-text.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script src="../../../../resources/basic-gestures.js"></script>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+    
+        async function runTest()
+        {
+            if (!testRunner.runUIScript)
+                return;
+
+            var output = '';
+            var editableTargetRect = document.getElementById('editable').getBoundingClientRect();
+            var firstTargetRect = document.getElementById('firstSelection').getBoundingClientRect();
+            var secondTargetRect = document.getElementById('secondSelection').getBoundingClientRect();
+            var thirdTargetRect = document.getElementById('thirdSelection').getBoundingClientRect();
+            var noneditableToEditableOffset = document.getElementById('editable').getBoundingClientRect().y - document.getElementById('noneditable').getBoundingClientRect().y;
+
+            var tapPointX = editableTargetRect.x + editableTargetRect.width / 2;
+            var tapPointY = editableTargetRect.y + editableTargetRect.height / 2;
+            var doubleTapPointX = firstTargetRect.x + firstTargetRect.width / 2;
+            var doubleTapPointY = firstTargetRect.y + firstTargetRect.height / 2 + noneditableToEditableOffset;
+            var dragY = firstTargetRect.y + firstTargetRect.height + noneditableToEditableOffset;
+            var dragX = firstTargetRect.x + firstTargetRect.width;
+            var dragX2 = secondTargetRect.x;
+            var dragX3 = thirdTargetRect.x;
+            var dragX4 = firstTargetRect.x - firstTargetRect.width;
+        
+            await tapAtPoint(tapPointX, tapPointY);
+            if (document.getSelection().type == "Caret")
+                output += 'PASS: Has Caret Selection';
+            else
+                output += 'FAIL: failed to activate caret as a result of a tap. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            await didShowKeyboard();
+
+            await doubleTapAtPoint(doubleTapPointX, doubleTapPointY);
+            if (document.getSelection().toString() == "magna")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to select a word as a result of a long press. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            await touchAndDragFromPointToPoint(dragX, dragY, dragX2, dragY);
+            if (document.getSelection().toString() == "magna aliqua.")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to select additional word after a drag. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            await touchAndDragFromPointToPoint(dragX2, dragY, dragX3, dragY);
+            if (document.getSelection().toString() == "magna aliqua. Ut")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to select additional word after a drag. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            await touchAndDragFromPointToPoint(dragX3, dragY, dragX2, dragY);
+            if (document.getSelection().toString() == "magna aliqua.")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to deselect word after a drag. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            await touchAndDragFromPointToPoint(dragX2, dragY, dragX, dragY);
+            if (document.getSelection().toString() == "magna")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to deselect word after a drag. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            var result = await touchAndDragFromPointToPoint(dragX, dragY, dragX4, dragY);
+            if (document.getSelection().toString() == "m")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to reduce selection to a single character by dragging left. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+            output += result;
+
+            var noneditableElement = document.getElementById('noneditable');
+            noneditableElement.parentNode.removeChild(noneditableElement);
+            var editableElement = document.getElementById('editable');
+            editableElement.parentNode.removeChild(editableElement);
+            document.getElementById('target').innerHTML = output;
+            testRunner.notifyDone();
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+        <style>
+        #noneditable {
+            height: 200px;
+            width: 300px;
+            background-color: silver;
+            font-family: monospace;
+            font-size: 18px;
+        }
+        #editable {
+            height: 200px;
+            width: 300px;
+            background-color: silver;
+            font-family: monospace;
+            font-size: 18px;
+        }
+        #target {
+            height: 50px;
+            width: 300px;
+            background-color: silver;
+            font-family: monospace;
+            font-size: 18px;
+        }
+    </style>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+    <div id="noneditable">
+        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore <span id="firstSelection">magna</span> aliqua.<span id="secondSelection"></span> Ut<span id="thirdSelection"></span> enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+    </div>
+    <div id="editable" contenteditable>
+        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+    </div> 
+    <div id="target">
+        This test requires UIScriptController to run.
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection.html b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection.html
new file mode 100644
index 0000000..cf6aba2
--- /dev/null
+++ b/LayoutTests/fast/events/touch/ios/double-tap-on-editable-content-for-selection.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script src="../../../../resources/basic-gestures.js"></script>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+    
+        async function runTest()
+        {
+            if (!testRunner.runUIScript)
+                return;
+
+            var output = '';
+            var editableTargetRect = document.getElementById('editable').getBoundingClientRect();
+            var firstTargetRect = document.getElementById('firstSelection').getBoundingClientRect();
+            var noneditableToEditableOffset = document.getElementById('editable').getBoundingClientRect().y - document.getElementById('noneditable').getBoundingClientRect().y;
+
+            var tapPointX = editableTargetRect.x + editableTargetRect.width / 2;
+            var tapPointY = editableTargetRect.y + editableTargetRect.height / 2;
+            var doubleTapPointX = firstTargetRect.x + firstTargetRect.width / 2;
+            var doubleTapPointY = firstTargetRect.y + firstTargetRect.height / 2 + noneditableToEditableOffset;
+        
+            await tapAtPoint(tapPointX, tapPointY);
+            if (document.getSelection().type == "Caret")
+                output += 'PASS: Has Caret Selection';
+            else
+                output += 'FAIL: failed to activate caret as a result of a tap. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            await didShowKeyboard();
+
+            await doubleTapAtPoint(doubleTapPointX, doubleTapPointY);
+            if (document.getSelection().toString() == "magna")
+                output += 'PASS: Correct Selection';
+            else
+                output += 'FAIL: failed to select a word as a result of a long press. Incorrect Selection: ' + document.getSelection().toString();
+            output += '<br>';
+
+            var noneditableElement = document.getElementById('noneditable');
+            noneditableElement.parentNode.removeChild(noneditableElement);
+            var editableElement =document.getElementById('editable');
+            editableElement.parentNode.removeChild(editableElement);
+            document.getElementById('target').innerHTML = output;
+            testRunner.notifyDone();
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+        <style>
+        #noneditable {
+            height: 200px;
+            width: 300px;
+            background-color: silver;
+            font-family: monospace;
+            font-size: 18px;
+        }
+        #editable {
+            height: 200px;
+            width: 300px;
+            background-color: silver;
+            font-family: monospace;
+            font-size: 18px;
+        }
+        #target {
+            height: 50px;
+            width: 300px;
+            background-color: silver;
+            font-family: monospace;
+            font-size: 18px;
+        }
+    </style>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+    <div id="noneditable">
+        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore <span id="firstSelection">magna</span> aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+    </div>
+    <div id="editable" contenteditable>
+        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+    </div> 
+    <div id="target">
+        This test requires UIScriptController to run.
+    </div>
+</body>
+</html>
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 233516b..3d0287d 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,19 @@
+2018-04-25  Megan Gardner  <megan_gardner@apple.com>
+
+        Activate selection when interacting with editable content
+        https://bugs.webkit.org/show_bug.cgi?id=185017
+
+        Reviewed by Tim Horton.
+        
+        Fixes a regression from r231016 where selection now does not work when interacting with
+        editable content. When we go into editable content, we should turn on the assistant.
+        This fulfills the requirement of user interaction as well, so any javascript selections
+        after this point should be valid.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _startAssistingKeyboard]):
+        (-[WKContentView _stopAssistingKeyboard]):
+
 2018-04-26  Per Arne Vollan  <pvollan@apple.com>
 
         Disable content filtering in minimal simulator mode
diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
index c6a35d2..ba1bf5b 100644
--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
@@ -3967,6 +3967,9 @@
 - (void)_startAssistingKeyboard
 {
     [self useSelectionAssistantWithGranularity:WKSelectionGranularityCharacter];
+    
+    if (self.isFirstResponder && !self.suppressAssistantSelectionView)
+        [_textSelectionAssistant activateSelection];
 
 #if !ENABLE(EXTRA_ZOOM_MODE)
     [self reloadInputViews];
@@ -3976,6 +3979,8 @@
 - (void)_stopAssistingKeyboard
 {
     [self useSelectionAssistantWithGranularity:_webView._selectionGranularity];
+    
+    [_textSelectionAssistant deactivateSelection];
 }
 
 - (const AssistedNodeInformation&)assistedNodeInformation