Title: [258050] trunk
Revision
258050
Author
[email protected]
Date
2020-03-06 19:04:32 -0800 (Fri, 06 Mar 2020)

Log Message

Add support for inserting and removing a text placeholder
https://bugs.webkit.org/show_bug.cgi?id=208661
<rdar://problem/59371073>

Reviewed by Simon Fraser and Ryosuke Niwa.

Source/WebCore:

Implements the concept of a text placeholder, which is an element that acts like whitespace:
it takes up space in the page layout, but has no visual appearance.

Tests: editing/text-placeholder/insert-and-remove-into-text-field.html
       editing/text-placeholder/insert-into-content-editable.html
       editing/text-placeholder/insert-into-empty-text-field.html
       editing/text-placeholder/insert-into-text-field-in-iframe.html
       editing/text-placeholder/insert-into-text-field.html

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Element.h:
(WebCore::Element::isTextPlaceholderElement const): Added. Defaults to false. I override this
in TextPlaceholderElement.h.

* editing/Editor.cpp:
(WebCore::Editor::insertTextPlaceholder):
(WebCore::Editor::removeTextPlaceholder):
Insert a new placeholder or remove an existing one.

* editing/Editor.h:
* html/shadow/TextPlaceholderElement.cpp: Added.
(WebCore::TextPlaceholderElement::create):
(WebCore::TextPlaceholderElement::TextPlaceholderElement): Set inline styles to size the placeholder.
(WebCore::TextPlaceholderElement::insertedIntoAncestor): If the placeholder is inserted inside an
HTMLTextFormControlElement (e.g. <input> or <textarea>) then hide the HTML placeholder text.
(WebCore::TextPlaceholderElement::removedFromAncestor): If the placeholder was removed from inside
an HTMLTextFormControlElement then show the HTML placeholder text.
* html/shadow/TextPlaceholderElement.h:
(isType):
* testing/Internals.cpp:
(WebCore::Internals::insertTextPlaceholder): Added.
(WebCore::Internals::removeTextPlaceholder): Added.
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit:

Implements the UITextInput protocol functions -insertTextPlaceholderWithSize and -removeTextPlaceholder.

* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView insertTextPlaceholderWithSize:completionHandler:]):
(-[WKContentView removeTextPlaceholder:willInsertText:completionHandler:]):
Implement more of the UITextInput protocol. These functions turn around and call
the corresponding WebPageProxy functions.

* UIProcess/ios/WKTextPlaceholder.h:
* UIProcess/ios/WKTextPlaceholder.mm: Added.
(-[WKTextPlaceholder initWithElementContext:]):
(-[WKTextPlaceholder elementContext]):
(-[WKTextPlaceholder rects]):
* UIProcess/ios/WKTextSelectionRect.h: Remove an unncessary #pragma once since I am here.
This file is only included from Objective-C/C++ files so that #pragma is unnecessary.

* UIProcess/ios/WKTextSelectionRect.mm:
(-[WKTextSelectionRect initWithCGRect:]): Added.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::insertTextPlaceholder): Added
(WebKit::WebPageProxy::removeTextPlaceholder): Added.
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in: Add new messages to insert and remove a placeholder.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::insertTextPlaceholder):
(WebKit::WebPage::removeTextPlaceholder):
Turn around and call the corresponding Editor functions.

LayoutTests:

Add tests to ensure that inserting and removing a placeholder work.

* editing/text-placeholder/insert-and-remove-into-text-field-expected.html: Added.
* editing/text-placeholder/insert-and-remove-into-text-field.html: Added.
* editing/text-placeholder/insert-into-content-editable-expected.html: Added.
* editing/text-placeholder/insert-into-content-editable.html: Added.
* editing/text-placeholder/insert-into-empty-text-field-expected.html: Added.
* editing/text-placeholder/insert-into-empty-text-field.html: Added.
* editing/text-placeholder/insert-into-text-field-expected.html: Added.
* editing/text-placeholder/insert-into-text-field-in-iframe-expected.html: Added.
* editing/text-placeholder/insert-into-text-field-in-iframe.html: Added.
* editing/text-placeholder/insert-into-text-field.html: Added.
* editing/text-placeholder/resources/insert-into-text-field-in-iframe.html: Added.
* editing/text-placeholder/resources/test.css: Added.
(@font-face):
(.test):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (258049 => 258050)


--- trunk/LayoutTests/ChangeLog	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/LayoutTests/ChangeLog	2020-03-07 03:04:32 UTC (rev 258050)
@@ -1,3 +1,28 @@
+2020-03-06  Daniel Bates  <[email protected]>
+
+        Add support for inserting and removing a text placeholder
+        https://bugs.webkit.org/show_bug.cgi?id=208661
+        <rdar://problem/59371073>
+
+        Reviewed by Simon Fraser and Ryosuke Niwa.
+
+        Add tests to ensure that inserting and removing a placeholder work.
+
+        * editing/text-placeholder/insert-and-remove-into-text-field-expected.html: Added.
+        * editing/text-placeholder/insert-and-remove-into-text-field.html: Added.
+        * editing/text-placeholder/insert-into-content-editable-expected.html: Added.
+        * editing/text-placeholder/insert-into-content-editable.html: Added.
+        * editing/text-placeholder/insert-into-empty-text-field-expected.html: Added.
+        * editing/text-placeholder/insert-into-empty-text-field.html: Added.
+        * editing/text-placeholder/insert-into-text-field-expected.html: Added.
+        * editing/text-placeholder/insert-into-text-field-in-iframe-expected.html: Added.
+        * editing/text-placeholder/insert-into-text-field-in-iframe.html: Added.
+        * editing/text-placeholder/insert-into-text-field.html: Added.
+        * editing/text-placeholder/resources/insert-into-text-field-in-iframe.html: Added.
+        * editing/text-placeholder/resources/test.css: Added.
+        (@font-face):
+        (.test):
+
 2020-03-06  Jacob Uphoff  <[email protected]>
 
         [ iOS ] two http/tests/resourceLoadStatistics/third-party-cookie-blocking are flaky timing out

Added: trunk/LayoutTests/editing/text-placeholder/insert-and-remove-into-text-field-expected.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-and-remove-into-text-field-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-and-remove-into-text-field-expected.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,12 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder that is inserted and removed from a text field visually looks as if it never was inserted to begin with. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<input id="input" class="test" type="text" value="Hello from Cupertino!">
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-and-remove-into-text-field.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-and-remove-into-text-field.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-and-remove-into-text-field.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,46 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder that is inserted and removed from a text field visually looks as if it never was inserted to begin with. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<input id="input" class="test" type="text" value="Hello from Cupertino!">
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+async function runTest()
+{
+    let input = document.getElementById("input");
+    if (window.testRunner)
+        await UIHelper.activateElementAndWaitForInputSession(input);
+    else
+        await UIHelper.callFunctionAndWaitForEvent(() => input.focus(), input, "focus");
+
+    let positionOfFrom = input.value.indexOf("from");
+    input.setSelectionRange(positionOfFrom, positionOfFrom);
+
+    let placeholderElement = null;
+    if (window.internals) {
+        // Because we are using the Ahem font almost all glyphs have the same width.
+        let glyphWidth = parseInt(window.getComputedStyle(input, null).fontSize, 10);
+        placeholderElement = internals.insertTextPlaceholder(5 * glyphWidth, 0 /* height */);
+        console.assert(placeholderElement);
+    }
+    
+    // Defocus field to hide the cursor.
+    await UIHelper.callFunctionAndWaitForEvent(() => input.blur(), input, "blur");
+
+    if (window.internals)
+        internals.removeTextPlaceholder(placeholderElement);
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-content-editable-expected.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-content-editable-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-content-editable-expected.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,12 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder is inserted into a <code>contenteditable</code> element. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<div id="test" class="test" style="width: 200px; height: 200px; border: 1px solid black" contenteditable="true">Hello &nbsp;&nbsp;from Cupertino!</div>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-content-editable.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-content-editable.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-content-editable.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,41 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder is inserted into a <code>contenteditable</code> element. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<div id="test" class="test" style="width: 200px; height: 200px; border: 1px solid black" contenteditable="true">Hello from Cupertino!</div>
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+async function runTest()
+{
+    let testElement = document.getElementById("test");
+    if (window.testRunner)
+        await UIHelper.activateElementAndWaitForInputSession(testElement);
+    else
+        await UIHelper.callFunctionAndWaitForEvent(() => testElement.focus(), testElement, "focus");
+
+    let positionOfFrom = testElement.textContent.indexOf("from");
+    window.getSelection().setBaseAndExtent(testElement.firstChild, positionOfFrom, testElement.firstChild, positionOfFrom);
+
+    if (window.internals) {
+        // Because we are using the Ahem font almost all glyphs have the same width.
+        let glyphWidth = parseInt(window.getComputedStyle(testElement, null).fontSize, 10);
+        internals.insertTextPlaceholder(2 * glyphWidth, 0 /* height */);
+    }
+
+    // Defocus field to hide the cursor.
+    await UIHelper.callFunctionAndWaitForEvent(() => testElement.blur(), testElement, "blur");
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-empty-text-field-expected.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-empty-text-field-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-empty-text-field-expected.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,12 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that the placeholder is hidden when a text placeholder is inserted into a text field. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<input id="input" class="test" type="text" value="      ">
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-empty-text-field.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-empty-text-field.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-empty-text-field.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,40 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that the placeholder is hidden when a text placeholder is inserted into a text field. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<input id="input" class="test" type="text" placeholder="FAIL">
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+async function runTest()
+{
+    let input = document.getElementById("input");
+    if (window.testRunner)
+        await UIHelper.activateElementAndWaitForInputSession(input);
+    else
+        await UIHelper.callFunctionAndWaitForEvent(() => input.focus(), input, "focus");
+
+    input.setSelectionRange(0, 0);
+
+    if (window.internals) {
+        // Because we are using the Ahem font almost all glyphs have the same width.
+        let glyphWidth = parseInt(window.getComputedStyle(input, null).fontSize, 10);
+        internals.insertTextPlaceholder(5 * glyphWidth, 0 /* height */);
+    }
+
+    // Defocus field to hide the cursor.
+    await UIHelper.callFunctionAndWaitForEvent(() => input.blur(), input, "blur");
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-expected.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-expected.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,12 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder is inserted into a text field. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<input id="input" class="test" type="text" value="Hello      from Cupertino!">
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-in-iframe-expected.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-in-iframe-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-in-iframe-expected.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,12 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder is inserted into a text field inside an iframe. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<iframe srcdoc='<!DOCTYPE html><html><head><link rel="stylesheet" href="" id="input" class="test" type="text" value="Hello      from Cupertino!"></body></html>' width="600" height="200"></iframe>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-in-iframe.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-in-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-text-field-in-iframe.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,16 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+</script>
+</head>
+<body>
+<p>This tests that a text placeholder is inserted into a text field inside an iframe. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<iframe src="" width="600" height="200"></iframe>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/insert-into-text-field.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/insert-into-text-field.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/insert-into-text-field.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,41 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<p>This tests that a text placeholder is inserted into a text field. This test can only be run in WebKitTestRunner or DumpRenderTree.</p>
+<input id="input" class="test" type="text" value="Hello from Cupertino!">
+<script>
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+async function runTest()
+{
+    let input = document.getElementById("input");
+    if (window.testRunner)
+        await UIHelper.activateElementAndWaitForInputSession(input);
+    else
+        await UIHelper.callFunctionAndWaitForEvent(() => input.focus(), input, "focus");
+
+    let positionOfFrom = input.value.indexOf("from");
+    input.setSelectionRange(positionOfFrom, positionOfFrom);
+
+    if (window.internals) {
+        // Because we are using the Ahem font almost all glyphs have the same width.
+        let glyphWidth = parseInt(window.getComputedStyle(input, null).fontSize, 10);
+        internals.insertTextPlaceholder(5 * glyphWidth, 0 /* height */);
+    }
+
+    // Defocus field to hide the cursor.
+    await UIHelper.callFunctionAndWaitForEvent(() => input.blur(), input, "blur");
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/resources/insert-into-text-field-in-iframe.html (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/resources/insert-into-text-field-in-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/resources/insert-into-text-field-in-iframe.html	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,37 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0">
+<script src=""
+<link rel="stylesheet" href=""
+</head>
+<body>
+<input id="input" class="test" type="text" value="Hello from Cupertino!">
+<pre id="console"></pre>
+<script>
+async function runTest()
+{
+    let input = document.getElementById("input");
+
+    // FIXME: Use UIHelper.activateElementAndWaitForInputSession(input). See <https://bugs.webkit.org/show_bug.cgi?id=208749>.
+    await UIHelper.callFunctionAndWaitForEvent(() => input.focus(), input, "focus");
+
+    let positionOfFrom = input.value.indexOf("from");
+    input.setSelectionRange(positionOfFrom, positionOfFrom);
+
+    if (window.internals) {
+        // Because we are using the Ahem font almost all glyphs have the same width.
+        let glyphWidth = parseInt(window.getComputedStyle(input, null).fontSize, 10);
+        internals.insertTextPlaceholder(5 * glyphWidth, 0 /* height */);
+    }
+
+    // Defocus field to hide the cursor.
+    await UIHelper.callFunctionAndWaitForEvent(() => input.blur(), input, "blur");
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+runTest();
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/editing/text-placeholder/resources/test.css (0 => 258050)


--- trunk/LayoutTests/editing/text-placeholder/resources/test.css	                        (rev 0)
+++ trunk/LayoutTests/editing/text-placeholder/resources/test.css	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,12 @@
+@font-face {
+    font-family: Ahem;
+    src: url("../../../resources/Ahem.ttf");
+}
+
+.test {
+    font: 25px/1 Ahem;
+    -webkit-text-size-adjust: 100%%;
+    /* To make debugging easier, make the caret stand out. */
+    caret-color: blue;
+    color: yellow;
+}

Modified: trunk/Source/WebCore/ChangeLog (258049 => 258050)


--- trunk/Source/WebCore/ChangeLog	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/ChangeLog	2020-03-07 03:04:32 UTC (rev 258050)
@@ -1,3 +1,47 @@
+2020-03-06  Daniel Bates  <[email protected]>
+
+        Add support for inserting and removing a text placeholder
+        https://bugs.webkit.org/show_bug.cgi?id=208661
+        <rdar://problem/59371073>
+
+        Reviewed by Simon Fraser and Ryosuke Niwa.
+
+        Implements the concept of a text placeholder, which is an element that acts like whitespace:
+        it takes up space in the page layout, but has no visual appearance.
+
+        Tests: editing/text-placeholder/insert-and-remove-into-text-field.html
+               editing/text-placeholder/insert-into-content-editable.html
+               editing/text-placeholder/insert-into-empty-text-field.html
+               editing/text-placeholder/insert-into-text-field-in-iframe.html
+               editing/text-placeholder/insert-into-text-field.html
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Element.h:
+        (WebCore::Element::isTextPlaceholderElement const): Added. Defaults to false. I override this
+        in TextPlaceholderElement.h.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::insertTextPlaceholder):
+        (WebCore::Editor::removeTextPlaceholder):
+        Insert a new placeholder or remove an existing one.
+
+        * editing/Editor.h:
+        * html/shadow/TextPlaceholderElement.cpp: Added.
+        (WebCore::TextPlaceholderElement::create):
+        (WebCore::TextPlaceholderElement::TextPlaceholderElement): Set inline styles to size the placeholder.
+        (WebCore::TextPlaceholderElement::insertedIntoAncestor): If the placeholder is inserted inside an
+        HTMLTextFormControlElement (e.g. <input> or <textarea>) then hide the HTML placeholder text.
+        (WebCore::TextPlaceholderElement::removedFromAncestor): If the placeholder was removed from inside
+        an HTMLTextFormControlElement then show the HTML placeholder text.
+        * html/shadow/TextPlaceholderElement.h:
+        (isType):
+        * testing/Internals.cpp:
+        (WebCore::Internals::insertTextPlaceholder): Added.
+        (WebCore::Internals::removeTextPlaceholder): Added.
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2020-03-06  Andres Gonzalez  <[email protected]>
 
         Implementation of AccessibilitySupport AXSIsolatedTreeMode.

Modified: trunk/Source/WebCore/Sources.txt (258049 => 258050)


--- trunk/Source/WebCore/Sources.txt	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/Sources.txt	2020-03-07 03:04:32 UTC (rev 258050)
@@ -1348,6 +1348,7 @@
 html/shadow/SliderThumbElement.cpp
 html/shadow/SpinButtonElement.cpp
 html/shadow/TextControlInnerElements.cpp
+html/shadow/TextPlaceholderElement.cpp
 
 inspector/CommandLineAPIHost.cpp
 inspector/CommandLineAPIModule.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (258049 => 258050)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-03-07 03:04:32 UTC (rev 258050)
@@ -4241,6 +4241,7 @@
 		CE08C3D2152B599A0021B8C2 /* AlternativeTextController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE08C3D0152B599A0021B8C2 /* AlternativeTextController.h */; settings = {ATTRIBUTES = (); }; };
 		CE1866451F72E5B400A0CAB6 /* MarkedText.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1866431F72E5B400A0CAB6 /* MarkedText.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		CE1A501F22D5350900CBC927 /* DOMTimerHoldingTank.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1A501D22D5350900CBC927 /* DOMTimerHoldingTank.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		CE212158240DBEB9006ED443 /* TextPlaceholderElement.h in Headers */ = {isa = PBXBuildFile; fileRef = CE212153240DBD30006ED443 /* TextPlaceholderElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		CE2849871CA360DF00B4A57F /* ContentSecurityPolicyDirectiveNames.h in Headers */ = {isa = PBXBuildFile; fileRef = CE2849861CA360DF00B4A57F /* ContentSecurityPolicyDirectiveNames.h */; };
 		CE5169E721F1B84700EA4F78 /* ColorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5169E521F1B84700EA4F78 /* ColorIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		CE5FA255209E48C50051D700 /* ContentSecurityPolicyClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5FA253209E48C50051D700 /* ContentSecurityPolicyClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -14146,6 +14147,8 @@
 		CE1866431F72E5B400A0CAB6 /* MarkedText.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MarkedText.h; sourceTree = "<group>"; };
 		CE1A501D22D5350900CBC927 /* DOMTimerHoldingTank.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DOMTimerHoldingTank.h; sourceTree = "<group>"; };
 		CE1A501E22D5350900CBC927 /* DOMTimerHoldingTank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DOMTimerHoldingTank.cpp; sourceTree = "<group>"; };
+		CE212153240DBD30006ED443 /* TextPlaceholderElement.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextPlaceholderElement.h; sourceTree = "<group>"; };
+		CE212154240DBD30006ED443 /* TextPlaceholderElement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TextPlaceholderElement.cpp; sourceTree = "<group>"; };
 		CE2849861CA360DF00B4A57F /* ContentSecurityPolicyDirectiveNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyDirectiveNames.h; path = csp/ContentSecurityPolicyDirectiveNames.h; sourceTree = "<group>"; };
 		CE2849881CA3614600B4A57F /* ContentSecurityPolicyDirectiveNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyDirectiveNames.cpp; path = csp/ContentSecurityPolicyDirectiveNames.cpp; sourceTree = "<group>"; };
 		CE5169E521F1B84700EA4F78 /* ColorIOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorIOS.h; sourceTree = "<group>"; };
@@ -18073,6 +18076,8 @@
 				4512502115DCE37D002F84E2 /* SpinButtonElement.h */,
 				142B97C713138943008BEF4B /* TextControlInnerElements.cpp */,
 				142B97C813138943008BEF4B /* TextControlInnerElements.h */,
+				CE212154240DBD30006ED443 /* TextPlaceholderElement.cpp */,
+				CE212153240DBD30006ED443 /* TextPlaceholderElement.h */,
 				A5416FE318810EF80009FC5F /* YouTubeEmbedShadowElement.cpp */,
 				A5416FE418810EF80009FC5F /* YouTubeEmbedShadowElement.h */,
 			);
@@ -32799,6 +32804,7 @@
 				E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */,
 				1C18DA59181AF6A500C4EF22 /* TextPainter.h in Headers */,
 				E4C91A0E1802343100A17F6D /* TextPaintStyle.h in Headers */,
+				CE212158240DBEB9006ED443 /* TextPlaceholderElement.h in Headers */,
 				93F198F608245E59001E9ABC /* TextResourceDecoder.h in Headers */,
 				A824B4650E2EF2EA0081A7B7 /* TextRun.h in Headers */,
 				414460A22412994500814BE7 /* MediaSessionIdentifier.h in Headers */,

Modified: trunk/Source/WebCore/dom/Element.h (258049 => 258050)


--- trunk/Source/WebCore/dom/Element.h	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/dom/Element.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -461,6 +461,7 @@
     virtual bool isSpinButtonElement() const { return false; }
     virtual bool isTextFormControlElement() const { return false; }
     virtual bool isTextField() const { return false; }
+    virtual bool isTextPlaceholderElement() const { return false; }
     virtual bool isOptionalFormControl() const { return false; }
     virtual bool isRequiredFormControl() const { return false; }
     virtual bool isInRange() const { return false; }

Modified: trunk/Source/WebCore/editing/Editor.cpp (258049 => 258050)


--- trunk/Source/WebCore/editing/Editor.cpp	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/editing/Editor.cpp	2020-03-07 03:04:32 UTC (rev 258050)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
  *
  * Redistribution and use in source and binary forms, with or without
@@ -110,6 +110,7 @@
 #include "TextCheckingHelper.h"
 #include "TextEvent.h"
 #include "TextIterator.h"
+#include "TextPlaceholderElement.h"
 #include "TypingCommand.h"
 #include "UserTypingGestureIndicator.h"
 #include "VisibleUnits.h"
@@ -3309,6 +3310,48 @@
     return plainText(selection.start(), selection.end(), behavior).replaceWithLiteral('\0', "");
 }
 
+RefPtr<TextPlaceholderElement> Editor::insertTextPlaceholder(const IntSize& size)
+{
+    if (m_frame.selection().isNone() || !m_frame.selection().selection().isContentEditable())
+        return nullptr;
+
+    Ref<Document> document { this->document() };
+
+    // FIXME: Write in terms of replaceSelectionWithFragment(). See <https://bugs.webkit.org/show_bug.cgi?id=208744>.
+    deleteSelectionWithSmartDelete(false);
+
+    auto range = m_frame.selection().toNormalizedRange();
+    if (!range)
+        return nullptr;
+
+    auto placeholder = TextPlaceholderElement::create(document, size);
+    range->insertNode(placeholder.copyRef());
+
+    VisibleSelection newSelection { positionBeforeNode(placeholder.ptr()), positionAfterNode(placeholder.ptr()) };
+    m_frame.selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(UserTriggered));
+
+    return placeholder;
+}
+
+void Editor::removeTextPlaceholder(TextPlaceholderElement& placeholder)
+{
+    ASSERT(placeholder.isConnected());
+
+    Ref<Document> document { this->document() };
+
+    // Save off state so that we can set the text insertion position to just before the placeholder element after removal.
+    auto savedRootEditableElement = makeRefPtr(placeholder.rootEditableElement());
+    auto savedPositionBeforePlaceholder = positionBeforeNode(&placeholder).parentAnchoredEquivalent();
+
+    // FIXME: Save the current selection if it has changed since the placeholder was inserted
+    // and restore it after text insertion.
+    placeholder.remove();
+
+    // To match the Legacy WebKit implementation, set the text insertion point to be before where the placeholder use to be.
+    if (m_frame.selection().isFocusedAndActive() && document->focusedElement() == savedRootEditableElement)
+        m_frame.selection().setSelection(VisibleSelection { savedPositionBeforePlaceholder, SEL_DEFAULT_AFFINITY }, FrameSelection::defaultSetSelectionOptions(UserTriggered));
+}
+
 static inline void collapseCaretWidth(IntRect& rect)
 {
     // FIXME: Width adjustment doesn't work for rotated text.

Modified: trunk/Source/WebCore/editing/Editor.h (258049 => 258050)


--- trunk/Source/WebCore/editing/Editor.h	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/editing/Editor.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -82,6 +82,7 @@
 class Text;
 class TextCheckerClient;
 class TextEvent;
+class TextPlaceholderElement;
 
 struct CompositionHighlight;
 struct FontAttributes;
@@ -549,6 +550,9 @@
 
     WEBCORE_EXPORT RefPtr<HTMLImageElement> insertEditableImage();
 
+    WEBCORE_EXPORT RefPtr<TextPlaceholderElement> insertTextPlaceholder(const IntSize&);
+    WEBCORE_EXPORT void removeTextPlaceholder(TextPlaceholderElement&);
+
 private:
     Document& document() const;
 

Added: trunk/Source/WebCore/html/shadow/TextPlaceholderElement.cpp (0 => 258050)


--- trunk/Source/WebCore/html/shadow/TextPlaceholderElement.cpp	                        (rev 0)
+++ trunk/Source/WebCore/html/shadow/TextPlaceholderElement.cpp	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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 "config.h"
+#include "TextPlaceholderElement.h"
+
+#include "HTMLNames.h"
+#include "HTMLTextFormControlElement.h"
+#include <wtf/IsoMallocInlines.h>
+
+namespace WebCore {
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(TextPlaceholderElement);
+
+Ref<TextPlaceholderElement> TextPlaceholderElement::create(Document& document, const LayoutSize& size)
+{
+    return adoptRef(*new TextPlaceholderElement { document, size });
+}
+
+TextPlaceholderElement::TextPlaceholderElement(Document& document, const LayoutSize& size)
+    : HTMLDivElement { HTMLNames::divTag, document }
+{
+    // FIXME: Move to User Agent stylesheet. See <https://webkit.org/b/208745>.
+    setInlineStyleProperty(CSSPropertyDisplay, CSSValueInlineBlock, false);
+    setInlineStyleProperty(CSSPropertyVerticalAlign, CSSValueBottom, false);
+    setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden, true);
+    setInlineStyleProperty(CSSPropertyWidth, size.width(), CSSUnitType::CSS_PX);
+    setInlineStyleProperty(CSSPropertyHeight, size.height(), CSSUnitType::CSS_PX);
+}
+
+auto TextPlaceholderElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree) -> InsertedIntoAncestorResult
+{
+    if (insertionType.treeScopeChanged) {
+        if (auto shadowHost = makeRefPtr(parentOfInsertedTree.shadowHost()); is<HTMLTextFormControlElement>(shadowHost))
+            downcast<HTMLTextFormControlElement>(*shadowHost).setCanShowPlaceholder(false);
+    }
+    return HTMLDivElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
+}
+
+void TextPlaceholderElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
+{
+    if (removalType.treeScopeChanged) {
+        if (auto shadowHost = makeRefPtr(oldParentOfRemovedTree.shadowHost()); is<HTMLTextFormControlElement>(shadowHost))
+            downcast<HTMLTextFormControlElement>(*shadowHost).setCanShowPlaceholder(true);
+    }
+    HTMLDivElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
+}
+
+} // namespace WebCore

Copied: trunk/Source/WebCore/html/shadow/TextPlaceholderElement.h (from rev 258049, trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.h) (0 => 258050)


--- trunk/Source/WebCore/html/shadow/TextPlaceholderElement.h	                        (rev 0)
+++ trunk/Source/WebCore/html/shadow/TextPlaceholderElement.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#pragma once
+
+#include "HTMLDivElement.h"
+
+namespace WebCore {
+
+class TextPlaceholderElement final : public HTMLDivElement {
+    WTF_MAKE_ISO_ALLOCATED(TextPlaceholderElement);
+public:
+    static Ref<TextPlaceholderElement> create(Document&, const LayoutSize&);
+
+private:
+    explicit TextPlaceholderElement(Document&, const LayoutSize&);
+
+    bool isTextPlaceholderElement() const final { return true; }
+
+    InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode& parentOfInsertedTree) final;
+    void removedFromAncestor(RemovalType, ContainerNode& oldParentOfRemovedTree) final;
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::TextPlaceholderElement)
+    static bool isType(const WebCore::Element& element) { return element.isTextPlaceholderElement(); }
+    static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
+SPECIALIZE_TYPE_TRAITS_END()

Modified: trunk/Source/WebCore/testing/Internals.cpp (258049 => 258050)


--- trunk/Source/WebCore/testing/Internals.cpp	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/testing/Internals.cpp	2020-03-07 03:04:32 UTC (rev 258050)
@@ -185,6 +185,7 @@
 #include "StyleScope.h"
 #include "StyleSheetContents.h"
 #include "TextIterator.h"
+#include "TextPlaceholderElement.h"
 #include "TreeScope.h"
 #include "TypeConversions.h"
 #include "UserGestureIndicator.h"
@@ -1436,6 +1437,17 @@
         downcast<HTMLTextFormControlElement>(element).setCanShowPlaceholder(canShowPlaceholder);
 }
 
+Element* Internals::insertTextPlaceholder(int width, int height)
+{
+    return frame()->editor().insertTextPlaceholder(IntSize { width, height }).get();
+}
+
+void Internals::removeTextPlaceholder(Element& element)
+{
+    if (is<TextPlaceholderElement>(element))
+        frame()->editor().removeTextPlaceholder(downcast<TextPlaceholderElement>(element));
+}
+
 void Internals::selectColorInColorChooser(HTMLInputElement& element, const String& colorValue)
 {
     element.selectColor(colorValue);

Modified: trunk/Source/WebCore/testing/Internals.h (258049 => 258050)


--- trunk/Source/WebCore/testing/Internals.h	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/testing/Internals.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -238,6 +238,9 @@
     String visiblePlaceholder(Element&);
     void setCanShowPlaceholder(Element&, bool);
 
+    Element* insertTextPlaceholder(int width, int height);
+    void removeTextPlaceholder(Element&);
+
     void selectColorInColorChooser(HTMLInputElement&, const String& colorValue);
     ExceptionOr<Vector<String>> formControlStateOfPreviousHistoryItem();
     ExceptionOr<void> setFormControlStateOfPreviousHistoryItem(const Vector<String>&);

Modified: trunk/Source/WebCore/testing/Internals.idl (258049 => 258050)


--- trunk/Source/WebCore/testing/Internals.idl	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebCore/testing/Internals.idl	2020-03-07 03:04:32 UTC (rev 258050)
@@ -309,6 +309,9 @@
 
     void setCanShowPlaceholder(Element element, boolean canShowPlaceholder);
 
+    Element insertTextPlaceholder(long width, long height);
+    void removeTextPlaceholder(Element element);
+
     [MayThrowException] Range? rangeOfString(DOMString text, Range? referenceRange, sequence<DOMString> findOptions);
     [MayThrowException] unsigned long countMatchesForText(DOMString text, sequence<DOMString> findOptions, DOMString markMatches);
     [MayThrowException] unsigned long countFindMatches(DOMString text, sequence<DOMString> findOptions);

Modified: trunk/Source/WebKit/ChangeLog (258049 => 258050)


--- trunk/Source/WebKit/ChangeLog	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/ChangeLog	2020-03-07 03:04:32 UTC (rev 258050)
@@ -1,3 +1,41 @@
+2020-03-06  Daniel Bates  <[email protected]>
+
+        Add support for inserting and removing a text placeholder
+        https://bugs.webkit.org/show_bug.cgi?id=208661
+        <rdar://problem/59371073>
+
+        Reviewed by Simon Fraser and Ryosuke Niwa.
+
+        Implements the UITextInput protocol functions -insertTextPlaceholderWithSize and -removeTextPlaceholder.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView insertTextPlaceholderWithSize:completionHandler:]):
+        (-[WKContentView removeTextPlaceholder:willInsertText:completionHandler:]):
+        Implement more of the UITextInput protocol. These functions turn around and call
+        the corresponding WebPageProxy functions.
+
+        * UIProcess/ios/WKTextPlaceholder.h:
+        * UIProcess/ios/WKTextPlaceholder.mm: Added.
+        (-[WKTextPlaceholder initWithElementContext:]):
+        (-[WKTextPlaceholder elementContext]):
+        (-[WKTextPlaceholder rects]):
+        * UIProcess/ios/WKTextSelectionRect.h: Remove an unncessary #pragma once since I am here.
+        This file is only included from Objective-C/C++ files so that #pragma is unnecessary.
+
+        * UIProcess/ios/WKTextSelectionRect.mm:
+        (-[WKTextSelectionRect initWithCGRect:]): Added.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::insertTextPlaceholder): Added
+        (WebKit::WebPageProxy::removeTextPlaceholder): Added.
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in: Add new messages to insert and remove a placeholder.
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::insertTextPlaceholder):
+        (WebKit::WebPage::removeTextPlaceholder):
+        Turn around and call the corresponding Editor functions.
+
 2020-03-06  Andres Gonzalez  <[email protected]>
 
         Implementation of AccessibilitySupport AXSIsolatedTreeMode.

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (258049 => 258050)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -711,6 +711,9 @@
 #if PLATFORM(IOS_FAMILY)
     void setShouldRevealCurrentSelectionAfterInsertion(bool);
 
+    void insertTextPlaceholder(const WebCore::IntSize&, CompletionHandler<void(const Optional<WebCore::ElementContext>&)>&&);
+    void removeTextPlaceholder(const WebCore::ElementContext&, CompletionHandler<void()>&&);
+
     double displayedContentScale() const { return m_lastVisibleContentRectUpdate.scale(); }
     const WebCore::FloatRect& exposedContentRect() const { return m_lastVisibleContentRectUpdate.exposedContentRect(); }
     const WebCore::FloatRect& unobscuredContentRect() const { return m_lastVisibleContentRectUpdate.unobscuredContentRect(); }

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (258049 => 258050)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2020-03-07 03:04:32 UTC (rev 258050)
@@ -65,6 +65,7 @@
 #import "WKSelectMenuListViewController.h"
 #import "WKSyntheticFlagsChangedWebEvent.h"
 #import "WKTextInputListViewController.h"
+#import "WKTextPlaceholder.h"
 #import "WKTextSelectionRect.h"
 #import "WKTimePickerViewController.h"
 #import "WKUIDelegatePrivate.h"
@@ -291,7 +292,6 @@
 
 @end
 
-
 @interface WKAutocorrectionRects : UIWKAutocorrectionRects
 + (WKAutocorrectionRects *)autocorrectionRectsWithFirstCGRect:(CGRect)firstRect lastCGRect:(CGRect)lastRect;
 @end
@@ -7436,6 +7436,27 @@
 
 #endif
 
+- (void)insertTextPlaceholderWithSize:(CGSize)size completionHandler:(void (^)(UITextPlaceholder *))completionHandler
+{
+    _page->insertTextPlaceholder(WebCore::IntSize { size }, [weakSelf = WeakObjCPtr<WKContentView>(self), completionHandler = makeBlockPtr(completionHandler)](const Optional<WebCore::ElementContext>& placeholder) {
+        auto strongSelf = weakSelf.get();
+        if (!strongSelf || ![strongSelf webView] || !placeholder) {
+            completionHandler(nil);
+            return;
+        }
+        WebCore::ElementContext placeholderToUse { *placeholder };
+        placeholderToUse.boundingRect = [strongSelf convertRect:placeholderToUse.boundingRect fromView:[strongSelf webView]];
+        completionHandler([[[WKTextPlaceholder alloc] initWithElementContext:placeholderToUse] autorelease]);
+    });
+}
+
+- (void)removeTextPlaceholder:(UITextPlaceholder *)placeholder willInsertText:(BOOL)willInsertText completionHandler:(void (^)(void))completionHandler
+{
+    // FIXME: Implement support for willInsertText. See <https://bugs.webkit.org/show_bug.cgi?id=208747>.
+    if (auto* wkTextPlaceholder = dynamic_objc_cast<WKTextPlaceholder>(placeholder))
+        _page->removeTextPlaceholder(wkTextPlaceholder.elementContext, makeBlockPtr(completionHandler));
+}
+
 static Vector<WebCore::IntSize> sizesOfPlaceholderElementsToInsertWhenDroppingItems(NSArray<NSItemProvider *> *itemProviders)
 {
     Vector<WebCore::IntSize> sizes;

Copied: trunk/Source/WebKit/UIProcess/ios/WKTextPlaceholder.h (from rev 258049, trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.h) (0 => 258050)


--- trunk/Source/WebKit/UIProcess/ios/WKTextPlaceholder.h	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/WKTextPlaceholder.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#if PLATFORM(IOS_FAMILY)
+
+#import <UIKit/UIKit.h>
+
+namespace WebCore {
+struct ElementContext;
+}
+
+@interface WKTextPlaceholder : UITextPlaceholder
+
+- (instancetype)initWithElementContext:(const WebCore::ElementContext&)context;
+
+@property (nonatomic, readonly) const WebCore::ElementContext& elementContext;
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)

Copied: trunk/Source/WebKit/UIProcess/ios/WKTextPlaceholder.mm (from rev 258049, trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.h) (0 => 258050)


--- trunk/Source/WebKit/UIProcess/ios/WKTextPlaceholder.mm	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/WKTextPlaceholder.mm	2020-03-07 03:04:32 UTC (rev 258050)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+#import "config.h"
+#import "WKTextPlaceholder.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "WKTextSelectionRect.h"
+#import <WebCore/ElementContext.h>
+
+@implementation WKTextPlaceholder {
+    WebCore::ElementContext _elementContext;
+}
+
+- (instancetype)initWithElementContext:(const WebCore::ElementContext&)context
+{
+    if (!(self = [self init]))
+        return nil;
+    _elementContext = context;
+    return self;
+}
+
+- (const WebCore::ElementContext&)elementContext
+{
+    return _elementContext;
+}
+
+- (NSArray<UITextSelectionRect *> *)rects
+{
+    return @[ [[[WKTextSelectionRect alloc] initWithCGRect:_elementContext.boundingRect] autorelease] ];
+}
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.h (258049 => 258050)


--- trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.h	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -23,8 +23,6 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#pragma once
-
 #if PLATFORM(IOS_FAMILY)
 
 #import <UIKit/UIKit.h>
@@ -35,6 +33,7 @@
 
 @interface WKTextSelectionRect : UITextSelectionRect
 
+- (instancetype)initWithCGRect:(CGRect)rect;
 - (instancetype)initWithSelectionRect:(const WebCore::SelectionRect&)selectionRect;
 
 @end

Modified: trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.mm (258049 => 258050)


--- trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.mm	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/UIProcess/ios/WKTextSelectionRect.mm	2020-03-07 03:04:32 UTC (rev 258050)
@@ -34,6 +34,13 @@
     WebCore::SelectionRect _selectionRect;
 }
 
+- (instancetype)initWithCGRect:(CGRect)rect
+{
+    WebCore::SelectionRect selectionRect;
+    selectionRect.setRect(WebCore::enclosingIntRect(rect));
+    return [self initWithSelectionRect:WTFMove(selectionRect)];
+}
+
 - (instancetype)initWithSelectionRect:(const WebCore::SelectionRect&)selectionRect
 {
     if (!(self = [super init]))

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (258049 => 258050)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2020-03-07 03:04:32 UTC (rev 258050)
@@ -460,6 +460,24 @@
     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_webPageID);
 }
 
+void WebPageProxy::insertTextPlaceholder(const IntSize& size, CompletionHandler<void(const Optional<ElementContext>&)>&& completionHandler)
+{
+    if (!hasRunningProcess()) {
+        completionHandler({ });
+        return;
+    }
+    m_process->connection()->sendWithAsyncReply(Messages::WebPage::InsertTextPlaceholder { size }, WTFMove(completionHandler), m_webPageID);
+}
+
+void WebPageProxy::removeTextPlaceholder(const ElementContext& placeholder, CompletionHandler<void()>&& completionHandler)
+{
+    if (!hasRunningProcess()) {
+        completionHandler();
+        return;
+    }
+    m_process->connection()->sendWithAsyncReply(Messages::WebPage::RemoveTextPlaceholder { placeholder }, WTFMove(completionHandler), m_webPageID);
+}
+
 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, CompletionHandler<void(WebAutocorrectionData)>&& callback)
 {
     if (!hasRunningProcess()) {

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (258049 => 258050)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2020-03-07 03:04:32 UTC (rev 258050)
@@ -1753,6 +1753,8 @@
 		CE1A0BD21A48E6C60054EF74 /* AssertionServicesSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1A0BCC1A48E6C60054EF74 /* AssertionServicesSPI.h */; };
 		CE1A0BD61A48E6C60054EF74 /* TCCSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1A0BD01A48E6C60054EF74 /* TCCSPI.h */; };
 		CE1A0BD71A48E6C60054EF74 /* TextInputSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1A0BD11A48E6C60054EF74 /* TextInputSPI.h */; };
+		CE21215F240EE571006ED443 /* WKTextPlaceholder.h in Headers */ = {isa = PBXBuildFile; fileRef = CE21215D240EE571006ED443 /* WKTextPlaceholder.h */; };
+		CE212160240EE571006ED443 /* WKTextPlaceholder.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE21215E240EE571006ED443 /* WKTextPlaceholder.mm */; };
 		CE45945C240F88550078019F /* WKTextSelectionRect.h in Headers */ = {isa = PBXBuildFile; fileRef = CE45945A240F85B90078019F /* WKTextSelectionRect.h */; };
 		CE550E152283752200D28791 /* InsertTextOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = CE550E12228373C800D28791 /* InsertTextOptions.h */; };
 		CE5B4C8821B73D870022E64F /* WKSyntheticFlagsChangedWebEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5B4C8621B73D870022E64F /* WKSyntheticFlagsChangedWebEvent.h */; };
@@ -5149,6 +5151,8 @@
 		CE1A0BCC1A48E6C60054EF74 /* AssertionServicesSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssertionServicesSPI.h; sourceTree = "<group>"; };
 		CE1A0BD01A48E6C60054EF74 /* TCCSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCCSPI.h; sourceTree = "<group>"; };
 		CE1A0BD11A48E6C60054EF74 /* TextInputSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextInputSPI.h; sourceTree = "<group>"; };
+		CE21215D240EE571006ED443 /* WKTextPlaceholder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKTextPlaceholder.h; path = ios/WKTextPlaceholder.h; sourceTree = "<group>"; };
+		CE21215E240EE571006ED443 /* WKTextPlaceholder.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKTextPlaceholder.mm; path = ios/WKTextPlaceholder.mm; sourceTree = "<group>"; };
 		CE45945A240F85B90078019F /* WKTextSelectionRect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKTextSelectionRect.h; path = ios/WKTextSelectionRect.h; sourceTree = "<group>"; };
 		CE45945B240F85B90078019F /* WKTextSelectionRect.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKTextSelectionRect.mm; path = ios/WKTextSelectionRect.mm; sourceTree = "<group>"; };
 		CE550E12228373C800D28791 /* InsertTextOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InsertTextOptions.h; sourceTree = "<group>"; };
@@ -6943,6 +6947,8 @@
 				26F10BE719187E2E001D0E68 /* WKSyntheticTapGestureRecognizer.mm */,
 				316B8B622054B55800BD4A62 /* WKSystemPreviewView.h */,
 				316B8B612054B55800BD4A62 /* WKSystemPreviewView.mm */,
+				CE21215D240EE571006ED443 /* WKTextPlaceholder.h */,
+				CE21215E240EE571006ED443 /* WKTextPlaceholder.mm */,
 				CE45945A240F85B90078019F /* WKTextSelectionRect.h */,
 				CE45945B240F85B90078019F /* WKTextSelectionRect.mm */,
 				71A676A422C62318007D6295 /* WKTouchActionGestureRecognizer.h */,
@@ -11539,6 +11545,7 @@
 				2DD67A351BD861060053B251 /* WKTextFinderClient.h in Headers */,
 				F4D5F51D206087A10038BBA8 /* WKTextInputListViewController.h in Headers */,
 				0FCB4E6818BBE3D9000FCFC9 /* WKTextInputWindowController.h in Headers */,
+				CE21215F240EE571006ED443 /* WKTextPlaceholder.h in Headers */,
 				CE45945C240F88550078019F /* WKTextSelectionRect.h in Headers */,
 				2EB6FC01203021960017E619 /* WKTimePickerViewController.h in Headers */,
 				71A676A622C62325007D6295 /* WKTouchActionGestureRecognizer.h in Headers */,
@@ -12841,6 +12848,7 @@
 				5CA26D83217AD1B800F97A35 /* WKSafeBrowsingWarning.mm in Sources */,
 				1DB01944211CF005009FB3E8 /* WKShareSheet.mm in Sources */,
 				7A78FF332241919B0096483E /* WKStorageAccessAlert.mm in Sources */,
+				CE212160240EE571006ED443 /* WKTextPlaceholder.mm in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (258049 => 258050)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2020-03-07 03:04:32 UTC (rev 258050)
@@ -643,6 +643,9 @@
     bool shouldRevealCurrentSelectionAfterInsertion() const { return m_shouldRevealCurrentSelectionAfterInsertion; }
     void setShouldRevealCurrentSelectionAfterInsertion(bool);
 
+    void insertTextPlaceholder(const WebCore::IntSize&, CompletionHandler<void(const Optional<WebCore::ElementContext>&)>&&);
+    void removeTextPlaceholder(const WebCore::ElementContext&, CompletionHandler<void()>&&);
+
     WebCore::FloatSize screenSize() const;
     WebCore::FloatSize availableScreenSize() const;
     WebCore::FloatSize overrideScreenSize() const;

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (258049 => 258050)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2020-03-07 03:04:32 UTC (rev 258050)
@@ -119,6 +119,8 @@
     RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async
 GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType command)
     SetShouldRevealCurrentSelectionAfterInsertion(bool shouldRevealCurrentSelectionAfterInsertion)
+    InsertTextPlaceholder(WebCore::IntSize size) -> (Optional<WebCore::ElementContext> placeholder) Async
+    RemoveTextPlaceholder(struct WebCore::ElementContext placeholder) -> () Async
 #endif
 
     SetControlledByAutomation(bool controlled)

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (258049 => 258050)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2020-03-07 03:02:43 UTC (rev 258049)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2020-03-07 03:04:32 UTC (rev 258050)
@@ -127,6 +127,7 @@
 #import <WebCore/StyleProperties.h>
 #import <WebCore/TextIndicator.h>
 #import <WebCore/TextIterator.h>
+#import <WebCore/TextPlaceholderElement.h>
 #import <WebCore/UserAgent.h>
 #import <WebCore/VisibleUnits.h>
 #import <WebCore/WebEvent.h>
@@ -3981,6 +3982,24 @@
 #endif
 }
 
+void WebPage::insertTextPlaceholder(const IntSize& size, CompletionHandler<void(const Optional<WebCore::ElementContext>&)>&& completionHandler)
+{
+    // Inserting the placeholder may run _javascript_, which can do anything, including frame destruction.
+    Ref<Frame> frame = corePage()->focusController().focusedOrMainFrame();
+    auto placeholder = frame->editor().insertTextPlaceholder(size);
+    completionHandler(placeholder ? contextForElement(*placeholder) : WTF::nullopt);
+}
+
+void WebPage::removeTextPlaceholder(const WebCore::ElementContext& placeholder, CompletionHandler<void()>&& completionHandler)
+{
+    if (RefPtr<Element> element = elementForContext(placeholder)) {
+        RELEASE_ASSERT(is<TextPlaceholderElement>(element));
+        if (RefPtr<Frame> frame = element->document().frame())
+            frame->editor().removeTextPlaceholder(downcast<TextPlaceholderElement>(*element));
+    }
+    completionHandler();
+}
+
 void WebPage::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler)
 {
     Ref<Frame> frame = corePage()->focusController().focusedOrMainFrame();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to