<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[243354] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/243354">243354</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2019-03-21 19:26:09 -0700 (Thu, 21 Mar 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Adopt UIWKDocumentContext
https://bugs.webkit.org/show_bug.cgi?id=196040
<rdar://problem/48642440>

Reviewed by Ryosuke Niwa.

New API test: WebKit.DocumentEditingContext

* dom/Range.h:
* editing/TextGranularity.h:
Make TextGranularity encodable by providing EnumTraits.

* editing/TextIterator.cpp:
(WebCore::plainTextReplacingNoBreakSpace):
* editing/TextIterator.h:
Expose an nbsp-replacing variant of plainText that takes Positions instead of Ranges.

* Platform/spi/ios/UIKitSPI.h:
* Scripts/webkit/messages.py:
* Shared/DocumentEditingContext.h: Added.
* Shared/DocumentEditingContext.mm: Added.
(WebKit::toNSRange):
(WebKit::DocumentEditingContext::toPlatformContext):
(IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::encode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::decode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::encode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::decode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContext>::encode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContext>::decode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::encode):
(IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::decode):
Add DocumentEditingContext(Request), and coders.
Also expose DocumentEditingContext::toPlatformContext, which populates
a UIWKDocumentContext with the relevant values.

* SourcesCocoa.txt:
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(toWebDocumentRequestOptions):
(toWebRequest):
(-[WKContentView adjustSelectionWithDelta:completionHandler:]):
(-[WKContentView requestDocumentContext:completionHandler:]):
(-[WKContentView selectPositionAtPoint:withContextRequest:completionHandler:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::adjustSelectionWithDelta):
(WebKit::WebPageProxy::requestDocumentEditingContext):
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Plumb DocumentEditingContext(Request) around.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::adjustSelectionWithDelta):
Adjust the current selection given deltas to apply to the location and length.

(WebKit::visiblePositionAdjacentToVisiblePosition):
(WebKit::visiblePositionForPointInRootViewCoordinates):
(WebKit::WebPage::requestDocumentEditingContext):
Retrieve the relevant part of the selection, as well as the context,
given either the selection, or a rect.
If we're collecting context for a rect, we split the context between
before and after (except for the part that intersects the selection).
The three strings will always be directly adjacent, and any of the three
can sometimes be null.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm: Added.
(makeRequest):
(-[TestWKWebView synchronouslyRequestDocumentContext:]):
(-[TestWKWebView synchronouslyAdjustSelectionWithDelta:]):
(applyStyle):
(TEST):
Add tests for UIWKDocumentContext.

* TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm:
(TEST):
(recursiveFindWKContentView): Deleted.
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(recursiveFindWKContentView):
(-[TestWKWebView wkContentView]):
* TestWebKitAPI/ios/UIKitSPI.h:
Share the WKContentView finding code between tests.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomRangeh">trunk/Source/WebCore/dom/Range.h</a></li>
<li><a href="#trunkSourceWebCoreeditingTextGranularityh">trunk/Source/WebCore/editing/TextGranularity.h</a></li>
<li><a href="#trunkSourceWebCoreeditingTextIteratorcpp">trunk/Source/WebCore/editing/TextIterator.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingTextIteratorh">trunk/Source/WebCore/editing/TextIterator.h</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitPlatformspiiosUIKitSPIh">trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h</a></li>
<li><a href="#trunkSourceWebKitScriptswebkitmessagespy">trunk/Source/WebKit/Scripts/webkit/messages.py</a></li>
<li><a href="#trunkSourceWebKitSourcesCocoatxt">trunk/Source/WebKit/SourcesCocoa.txt</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxyh">trunk/Source/WebKit/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWebPageProxyIOSmm">trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKitWebKitxcodeprojprojectpbxproj">trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagecpp">trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoaWKContentViewEditingActionsmm">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm</a></li>
<li><a href="#trunkToolsTestWebKitAPIcocoaTestWKWebViewh">trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h</a></li>
<li><a href="#trunkToolsTestWebKitAPIcocoaTestWKWebViewmm">trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm</a></li>
<li><a href="#trunkToolsTestWebKitAPIiosUIKitSPIh">trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitSharedDocumentEditingContexth">trunk/Source/WebKit/Shared/DocumentEditingContext.h</a></li>
<li><a href="#trunkSourceWebKitSharedDocumentEditingContextmm">trunk/Source/WebKit/Shared/DocumentEditingContext.mm</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoaDocumentEditingContextmm">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/ChangeLog      2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2019-03-21  Tim Horton  <timothy_horton@apple.com>
+
+        Adopt UIWKDocumentContext
+        https://bugs.webkit.org/show_bug.cgi?id=196040
+        <rdar://problem/48642440>
+
+        Reviewed by Ryosuke Niwa.
+
+        New API test: WebKit.DocumentEditingContext
+
+        * dom/Range.h:
+        * editing/TextGranularity.h:
+        Make TextGranularity encodable by providing EnumTraits.
+
+        * editing/TextIterator.cpp:
+        (WebCore::plainTextReplacingNoBreakSpace):
+        * editing/TextIterator.h:
+        Expose an nbsp-replacing variant of plainText that takes Positions instead of Ranges.
+
</ins><span class="cx"> 2019-03-21  Sihui Liu  <sihui_liu@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Fix key path extraction code in IndexedDB to check own property
</span></span></pre></div>
<a id="trunkSourceWebCoredomRangeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Range.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Range.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/dom/Range.h    2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -176,7 +176,7 @@
</span><span class="cx"> WEBCORE_EXPORT Ref<Range> rangeOfContents(Node&);
</span><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT bool areRangesEqual(const Range*, const Range*);
</span><del>-bool rangesOverlap(const Range*, const Range*);
</del><ins>+WEBCORE_EXPORT bool rangesOverlap(const Range*, const Range*);
</ins><span class="cx"> 
</span><span class="cx"> inline bool documentOrderComparator(const Node* a, const Node* b)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTextGranularityh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextGranularity.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextGranularity.h   2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/editing/TextGranularity.h      2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -43,3 +43,23 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><ins>+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::TextGranularity> {
+    using values = EnumValues<
+        WebCore::TextGranularity,
+        WebCore::TextGranularity::CharacterGranularity,
+        WebCore::TextGranularity::WordGranularity,
+        WebCore::TextGranularity::SentenceGranularity,
+        WebCore::TextGranularity::LineGranularity,
+        WebCore::TextGranularity::ParagraphGranularity,
+        WebCore::TextGranularity::DocumentGranularity,
+        WebCore::TextGranularity::SentenceBoundary,
+        WebCore::TextGranularity::LineBoundary,
+        WebCore::TextGranularity::ParagraphBoundary,
+        WebCore::TextGranularity::DocumentBoundary
+    >;
+};
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreeditingTextIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextIterator.cpp (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextIterator.cpp    2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/editing/TextIterator.cpp       2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -2684,6 +2684,11 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String plainTextReplacingNoBreakSpace(Position start, Position end, TextIteratorBehavior defaultBehavior, bool isDisplayString)
+{
+    return plainText(start, end, defaultBehavior, isDisplayString).replace(noBreakSpace, ' ');
+}
+
</ins><span class="cx"> String plainText(const Range* range, TextIteratorBehavior defaultBehavior, bool isDisplayString)
</span><span class="cx"> {
</span><span class="cx">     if (!range)
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTextIteratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TextIterator.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TextIterator.h      2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebCore/editing/TextIterator.h 2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT String plainText(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
</span><ins>+WEBCORE_EXPORT String plainTextReplacingNoBreakSpace(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
</ins><span class="cx"> 
</span><span class="cx"> WEBCORE_EXPORT String plainText(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
</span><span class="cx"> WEBCORE_EXPORT String plainTextReplacingNoBreakSpace(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior, bool isDisplayString = false);
</span><span class="lines">@@ -102,7 +103,7 @@
</span><span class="cx"> class TextIterator {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior);
</del><ins>+    WEBCORE_EXPORT explicit TextIterator(Position start, Position end, TextIteratorBehavior = TextIteratorDefaultBehavior);
</ins><span class="cx">     WEBCORE_EXPORT explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
</span><span class="cx">     WEBCORE_EXPORT ~TextIterator();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/ChangeLog       2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2019-03-21  Tim Horton  <timothy_horton@apple.com>
+
+        Adopt UIWKDocumentContext
+        https://bugs.webkit.org/show_bug.cgi?id=196040
+        <rdar://problem/48642440>
+
+        Reviewed by Ryosuke Niwa.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * Scripts/webkit/messages.py:
+        * Shared/DocumentEditingContext.h: Added.
+        * Shared/DocumentEditingContext.mm: Added.
+        (WebKit::toNSRange):
+        (WebKit::DocumentEditingContext::toPlatformContext):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::encode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContext::Range>::decode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::encode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContext::TextRect>::decode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContext>::encode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContext>::decode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::encode):
+        (IPC::ArgumentCoder<WebKit::DocumentEditingContextRequest>::decode):
+        Add DocumentEditingContext(Request), and coders.
+        Also expose DocumentEditingContext::toPlatformContext, which populates
+        a UIWKDocumentContext with the relevant values.
+
+        * SourcesCocoa.txt:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (toWebDocumentRequestOptions):
+        (toWebRequest):
+        (-[WKContentView adjustSelectionWithDelta:completionHandler:]):
+        (-[WKContentView requestDocumentContext:completionHandler:]):
+        (-[WKContentView selectPositionAtPoint:withContextRequest:completionHandler:]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::adjustSelectionWithDelta):
+        (WebKit::WebPageProxy::requestDocumentEditingContext):
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        Plumb DocumentEditingContext(Request) around.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::adjustSelectionWithDelta):
+        Adjust the current selection given deltas to apply to the location and length.
+
+        (WebKit::visiblePositionAdjacentToVisiblePosition):
+        (WebKit::visiblePositionForPointInRootViewCoordinates):
+        (WebKit::WebPage::requestDocumentEditingContext):
+        Retrieve the relevant part of the selection, as well as the context,
+        given either the selection, or a rect.
+        If we're collecting context for a rect, we split the context between
+        before and after (except for the part that intersects the selection).
+        The three strings will always be directly adjacent, and any of the three
+        can sometimes be null.
+
</ins><span class="cx"> 2019-03-21  James Magahern  <jmagahern@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Long press gesture recognizers in WKWebView are conflicting with internal scroll view long press gesture recognizers
</span></span></pre></div>
<a id="trunkSourceWebKitPlatformspiiosUIKitSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h  2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h     2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -1140,6 +1140,36 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+@interface UIWKDocumentContext : NSObject
+
+@property (nonatomic, copy) NSObject *contextBefore;
+@property (nonatomic, copy) NSObject *selectedText;
+@property (nonatomic, copy) NSObject *contextAfter;
+@property (nonatomic, copy) NSObject *markedText;
+@property (nonatomic, assign) NSRange selectedRangeInMarkedText;
+@property (nonatomic, copy) NSAttributedString *annotatedText;
+
+- (void)addTextRect:(CGRect)rect forCharacterRange:(NSRange)range;
+
+@end
+
+typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) {
+    UIWKDocumentRequestNone = 0,
+    UIWKDocumentRequestText = 1 << 0,
+    UIWKDocumentRequestAttributed = 1 << 1,
+    UIWKDocumentRequestRects = 1 << 2,
+    UIWKDocumentRequestSpatial = 1 << 3,
+    UIWKDocumentRequestAnnotation = 1 << 4,
+};
+
+@interface UIWKDocumentRequest : NSObject
+@property (nonatomic, assign) UIWKDocumentRequestFlags flags;
+@property (nonatomic, assign) UITextGranularity surroundingGranularity;
+@property (nonatomic, assign) NSInteger granularityCount;
+@property (nonatomic, assign) CGRect documentRect;
+@property (nonatomic, retain) id <NSCopying> inputElementIdentifier;
+@end
+
</ins><span class="cx"> WTF_EXTERN_C_BEGIN
</span><span class="cx"> 
</span><span class="cx"> BOOL UIKeyboardEnabledInputModesAllowOneToManyShortcuts(void);
</span></span></pre></div>
<a id="trunkSourceWebKitScriptswebkitmessagespy"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Scripts/webkit/messages.py   2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py      2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -397,6 +397,7 @@
</span><span class="cx">         'PAL::SessionID': ['<pal/SessionID.h>'],
</span><span class="cx">         'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'],
</span><span class="cx">         'WebCore::DOMPasteAccessResponse': ['<WebCore/DOMPasteAccess.h>'],
</span><ins>+        'WebKit::DocumentEditingContextRequest': ['"DocumentEditingContext.h"'],
</ins><span class="cx">         'WebCore::DragHandlingMethod': ['<WebCore/DragActions.h>'],
</span><span class="cx">         'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'],
</span><span class="cx">         'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'],
</span></span></pre></div>
<a id="trunkSourceWebKitSharedDocumentEditingContexth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/Shared/DocumentEditingContext.h (0 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/DocumentEditingContext.h                              (rev 0)
+++ trunk/Source/WebKit/Shared/DocumentEditingContext.h 2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -0,0 +1,110 @@
</span><ins>+/*
+ * Copyright (C) 2019 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
+
+#if PLATFORM(IOS_FAMILY)
+
+#include "ArgumentCoders.h"
+#include "AttributedString.h"
+#include "TextInputContext.h"
+#include <WebCore/FloatRect.h>
+#include <WebCore/TextGranularity.h>
+#include <wtf/OptionSet.h>
+#include <wtf/Optional.h>
+#include <wtf/Vector.h>
+
+OBJC_CLASS UIWKDocumentContext;
+
+namespace WebKit {
+
+struct DocumentEditingContextRequest {
+    enum class Options : uint8_t {
+        Text = 1 << 0,
+        AttributedText = 1 << 1,
+        Rects = 1 << 2,
+        Spatial = 1 << 3,
+        Annotation = 1 << 4,
+    };
+
+    OptionSet<Options> options;
+
+    WebCore::TextGranularity surroundingGranularity { WebCore::CharacterGranularity };
+    int64_t granularityCount { 0 };
+
+    WebCore::FloatRect rect;
+
+    Optional<WebKit::TextInputContext> textInputContext;
+};
+
+struct DocumentEditingContext {
+    UIWKDocumentContext *toPlatformContext(OptionSet<WebKit::DocumentEditingContextRequest::Options>);
+
+    AttributedString contextBefore;
+    AttributedString selectedText;
+    AttributedString contextAfter;
+    AttributedString markedText;
+    AttributedString annotatedText;
+
+    struct Range {
+        uint64_t location { 0 };
+        uint64_t length { 0 };
+    };
+
+    Range selectedRangeInMarkedText;
+
+    struct TextRectAndRange {
+        WebCore::FloatRect rect;
+        Range range;
+    };
+
+    Vector<TextRectAndRange> textRects;
+};
+
+}
+
+namespace IPC {
+template<> struct ArgumentCoder<WebKit::DocumentEditingContext::Range> {
+    static void encode(Encoder&, const WebKit::DocumentEditingContext::Range&);
+    static Optional<WebKit::DocumentEditingContext::Range> decode(Decoder&);
+};
+
+template<> struct ArgumentCoder<WebKit::DocumentEditingContext::TextRectAndRange> {
+    static void encode(Encoder&, const WebKit::DocumentEditingContext::TextRectAndRange&);
+    static Optional<WebKit::DocumentEditingContext::TextRectAndRange> decode(Decoder&);
+};
+
+template<> struct ArgumentCoder<WebKit::DocumentEditingContext> {
+    static void encode(Encoder&, const WebKit::DocumentEditingContext&);
+    static Optional<WebKit::DocumentEditingContext> decode(Decoder&);
+};
+
+template<> struct ArgumentCoder<WebKit::DocumentEditingContextRequest> {
+    static void encode(Encoder&, const WebKit::DocumentEditingContextRequest&);
+    static Optional<WebKit::DocumentEditingContextRequest> decode(Decoder&);
+};
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebKitSharedDocumentEditingContextmm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/Shared/DocumentEditingContext.mm (0 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/DocumentEditingContext.mm                             (rev 0)
+++ trunk/Source/WebKit/Shared/DocumentEditingContext.mm        2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -0,0 +1,208 @@
</span><ins>+/*
+ * Copyright (C) 2019 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 "DocumentEditingContext.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#include "TextInputContext.h"
+#include "UIKitSPI.h"
+#include "WebCoreArgumentCoders.h"
+
+namespace WebKit {
+
+static inline NSRange toNSRange(DocumentEditingContext::Range range)
+{
+    return NSMakeRange(range.location, range.length);
+}
+
+UIWKDocumentContext *DocumentEditingContext::toPlatformContext(OptionSet<DocumentEditingContextRequest::Options> options)
+{
+    RetainPtr<UIWKDocumentContext> platformContext = adoptNS([[NSClassFromString(@"UIWKDocumentContext") alloc] init]);
+
+    if (options.contains(DocumentEditingContextRequest::Options::AttributedText)) {
+        [platformContext setContextBefore:contextBefore.string.get()];
+        [platformContext setSelectedText:selectedText.string.get()];
+        [platformContext setContextAfter:contextAfter.string.get()];
+        [platformContext setMarkedText:markedText.string.get()];
+    } else if (options.contains(DocumentEditingContextRequest::Options::Text)) {
+        [platformContext setContextBefore:[contextBefore.string string]];
+        [platformContext setSelectedText:[selectedText.string string]];
+        [platformContext setContextAfter:[contextAfter.string string]];
+        [platformContext setMarkedText:[markedText.string string]];
+    }
+
+    [platformContext setSelectedRangeInMarkedText:toNSRange(selectedRangeInMarkedText)];
+
+    for (const auto& rect : textRects)
+        [platformContext addTextRect:rect.rect forCharacterRange:toNSRange(rect.range)];
+
+    [platformContext setAnnotatedText:annotatedText.string.get()];
+
+    return platformContext.autorelease();
+}
+
+}
+
+namespace IPC {
+
+void ArgumentCoder<WebKit::DocumentEditingContext::Range>::encode(Encoder& encoder, const WebKit::DocumentEditingContext::Range& range)
+{
+    encoder << range.location;
+    encoder << range.length;
+}
+
+Optional<WebKit::DocumentEditingContext::Range> ArgumentCoder<WebKit::DocumentEditingContext::Range>::decode(Decoder& decoder)
+{
+    WebKit::DocumentEditingContext::Range range;
+
+    if (!decoder.decode(range.location))
+        return WTF::nullopt;
+    if (!decoder.decode(range.length))
+        return WTF::nullopt;
+
+    return range;
+}
+
+void ArgumentCoder<WebKit::DocumentEditingContext::TextRectAndRange>::encode(Encoder& encoder, const WebKit::DocumentEditingContext::TextRectAndRange& rect)
+{
+    encoder << rect.rect;
+    encoder << rect.range;
+}
+
+Optional<WebKit::DocumentEditingContext::TextRectAndRange> ArgumentCoder<WebKit::DocumentEditingContext::TextRectAndRange>::decode(Decoder& decoder)
+{
+    WebKit::DocumentEditingContext::TextRectAndRange rect;
+
+    if (!decoder.decode(rect.rect))
+        return WTF::nullopt;
+
+    Optional<WebKit::DocumentEditingContext::Range> range;
+    decoder >> range;
+    if (!range)
+        return WTF::nullopt;
+    rect.range = *range;
+
+    return rect;
+}
+
+void ArgumentCoder<WebKit::DocumentEditingContext>::encode(Encoder& encoder, const WebKit::DocumentEditingContext& context)
+{
+    encoder << context.contextBefore;
+    encoder << context.selectedText;
+    encoder << context.contextAfter;
+    encoder << context.markedText;
+    encoder << context.annotatedText;
+
+    encoder << context.selectedRangeInMarkedText;
+
+    encoder << context.textRects;
+}
+
+Optional<WebKit::DocumentEditingContext> ArgumentCoder<WebKit::DocumentEditingContext>::decode(Decoder& decoder)
+{
+    WebKit::DocumentEditingContext context;
+
+    Optional<WebKit::AttributedString> contextBefore;
+    decoder >> contextBefore;
+    if (!contextBefore)
+        return WTF::nullopt;
+    context.contextBefore = *contextBefore;
+
+    Optional<WebKit::AttributedString> selectedText;
+    decoder >> selectedText;
+    if (!selectedText)
+        return WTF::nullopt;
+    context.selectedText = *selectedText;
+
+    Optional<WebKit::AttributedString> contextAfter;
+    decoder >> contextAfter;
+    if (!contextAfter)
+        return WTF::nullopt;
+    context.contextAfter = *contextAfter;
+
+    Optional<WebKit::AttributedString> markedText;
+    decoder >> markedText;
+    if (!markedText)
+        return WTF::nullopt;
+    context.markedText = *markedText;
+
+    Optional<WebKit::AttributedString> annotatedText;
+    decoder >> annotatedText;
+    if (!annotatedText)
+        return WTF::nullopt;
+    context.annotatedText = *annotatedText;
+
+    Optional<WebKit::DocumentEditingContext::Range> selectedRangeInMarkedText;
+    decoder >> selectedRangeInMarkedText;
+    if (!selectedRangeInMarkedText)
+        return WTF::nullopt;
+    context.selectedRangeInMarkedText = *selectedRangeInMarkedText;
+
+    if (!decoder.decode(context.textRects))
+        return WTF::nullopt;
+
+    return context;
+}
+
+void ArgumentCoder<WebKit::DocumentEditingContextRequest>::encode(Encoder& encoder, const WebKit::DocumentEditingContextRequest& request)
+{
+    encoder << request.options;
+    encoder << request.surroundingGranularity;
+    encoder << request.granularityCount;
+    encoder << request.rect;
+    encoder << request.textInputContext;
+}
+
+Optional<WebKit::DocumentEditingContextRequest> ArgumentCoder<WebKit::DocumentEditingContextRequest>::decode(Decoder& decoder)
+{
+    WebKit::DocumentEditingContextRequest request;
+
+    if (!decoder.decode(request.options))
+        return WTF::nullopt;
+
+    if (!decoder.decode(request.surroundingGranularity))
+        return WTF::nullopt;
+
+    if (!decoder.decode(request.granularityCount))
+        return WTF::nullopt;
+
+    if (!decoder.decode(request.rect))
+        return WTF::nullopt;
+
+    Optional<Optional<WebKit::TextInputContext>> optionalTextInputContext;
+    decoder >> optionalTextInputContext;
+    if (!optionalTextInputContext)
+        return WTF::nullopt;
+
+    request.textInputContext = optionalTextInputContext.value();
+
+    return request;
+}
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebKitSourcesCocoatxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/SourcesCocoa.txt (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/SourcesCocoa.txt     2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/SourcesCocoa.txt        2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -125,6 +125,7 @@
</span><span class="cx"> 
</span><span class="cx"> Shared/APIWebArchive.mm
</span><span class="cx"> Shared/APIWebArchiveResource.mm
</span><ins>+Shared/DocumentEditingContext.mm
</ins><span class="cx"> Shared/FocusedElementInformation.cpp
</span><span class="cx"> Shared/VisibleContentRectUpdateInfo.cpp
</span><span class="cx"> Shared/WebSQLiteDatabaseTracker.cpp
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.h     2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h        2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -276,6 +276,8 @@
</span><span class="cx"> 
</span><span class="cx"> struct AttributedString;
</span><span class="cx"> struct ColorSpaceData;
</span><ins>+struct DocumentEditingContext;
+struct DocumentEditingContextRequest;
</ins><span class="cx"> struct EditingRange;
</span><span class="cx"> struct EditorState;
</span><span class="cx"> struct FrameInfoData;
</span><span class="lines">@@ -708,6 +710,8 @@
</span><span class="cx">     void hardwareKeyboardAvailabilityChanged(bool keyboardIsAttached);
</span><span class="cx">     bool isScrollingOrZooming() const { return m_isScrollingOrZooming; }
</span><span class="cx">     void requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&&);
</span><ins>+    void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&);
+    void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&);
</ins><span class="cx"> #if ENABLE(DATA_INTERACTION)
</span><span class="cx">     void didHandleDragStartRequest(bool started);
</span><span class="cx">     void didHandleAdditionalDragItemsRequest(bool added);
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm    2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm       2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if PLATFORM(IOS_FAMILY)
</span><span class="cx"> 
</span><span class="cx"> #import "APIUIClient.h"
</span><ins>+#import "DocumentEditingContext.h"
</ins><span class="cx"> #import "EditableImageController.h"
</span><span class="cx"> #import "EditingRange.h"
</span><span class="cx"> #import "InputViewUpdateDeferrer.h"
</span><span class="lines">@@ -73,6 +74,7 @@
</span><span class="cx"> #import "_WKElementAction.h"
</span><span class="cx"> #import "_WKFocusedElementInfo.h"
</span><span class="cx"> #import "_WKInputDelegate.h"
</span><ins>+#import "_WKTextInputContextInternal.h"
</ins><span class="cx"> #import <CoreText/CTFont.h>
</span><span class="cx"> #import <CoreText/CTFontDescriptor.h>
</span><span class="cx"> #import <MobileCoreServices/UTCoreTypes.h>
</span><span class="lines">@@ -6282,6 +6284,68 @@
</span><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+static inline OptionSet<WebKit::DocumentEditingContextRequest::Options> toWebDocumentRequestOptions(UIWKDocumentRequestFlags flags)
+{
+    OptionSet<WebKit::DocumentEditingContextRequest::Options> options;
+
+    if (flags & UIWKDocumentRequestText)
+        options.add(WebKit::DocumentEditingContextRequest::Options::Text);
+    if (flags & UIWKDocumentRequestAttributed)
+        options.add(WebKit::DocumentEditingContextRequest::Options::AttributedText);
+    if (flags & UIWKDocumentRequestRects)
+        options.add(WebKit::DocumentEditingContextRequest::Options::Rects);
+    if (flags & UIWKDocumentRequestSpatial)
+        options.add(WebKit::DocumentEditingContextRequest::Options::Spatial);
+    if (flags & UIWKDocumentRequestAnnotation)
+        options.add(WebKit::DocumentEditingContextRequest::Options::Annotation);
+
+    return options;
+}
+
+static WebKit::DocumentEditingContextRequest toWebRequest(UIWKDocumentRequest *request)
+{
+    WebKit::DocumentEditingContextRequest webRequest = {
+        .options = toWebDocumentRequestOptions(request.flags),
+        .surroundingGranularity = toWKTextGranularity(request.surroundingGranularity),
+        .granularityCount = request.granularityCount,
+        .rect = request.documentRect
+    };
+
+    if (auto textInputContext = dynamic_objc_cast<_WKTextInputContext>(request.inputElementIdentifier))
+        webRequest.textInputContext = [textInputContext _textInputContext];
+
+    return webRequest;
+}
+
+- (void)adjustSelectionWithDelta:(NSRange)deltaRange completionHandler:(void (^)(void))completionHandler
+{
+    // UIKit is putting casted signed integers into NSRange. Cast them back to reveal any negative values.
+    _page->updateSelectionWithDelta(static_cast<int64_t>(deltaRange.location), static_cast<int64_t>(deltaRange.length), [capturedCompletionHandler = makeBlockPtr(completionHandler)] {
+        capturedCompletionHandler();
+    });
+}
+
+- (void)requestDocumentContext:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler
+{
+    auto webRequest = toWebRequest(request);
+    OptionSet<WebKit::DocumentEditingContextRequest::Options> options = webRequest.options;
+    _page->requestDocumentEditingContext(webRequest, [capturedCompletionHandler = makeBlockPtr(completionHandler), options] (WebKit::DocumentEditingContext editingContext) {
+        capturedCompletionHandler(editingContext.toPlatformContext(options));
+    });
+}
+
+- (void)selectPositionAtPoint:(CGPoint)point withContextRequest:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler
+{
+    // FIXME: Reduce to 1 message.
+    [self selectPositionAtPoint:point completionHandler:^{
+        [self requestDocumentContext:request completionHandler:^(UIWKDocumentContext *context) {
+            completionHandler(context);
+        }];
+    }];
+}
+
+
</ins><span class="cx"> #pragma mark - UIDragInteractionDelegate
</span><span class="cx"> 
</span><span class="cx"> - (BOOL)_dragInteraction:(UIDragInteraction *)interaction shouldDelayCompetingGestureRecognizer:(UIGestureRecognizer *)competingGestureRecognizer
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWebPageProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm     2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm        2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #import "APIUIClient.h"
</span><span class="cx"> #import "Connection.h"
</span><span class="cx"> #import "DataReference.h"
</span><ins>+#import "DocumentEditingContext.h"
</ins><span class="cx"> #import "EditingRange.h"
</span><span class="cx"> #import "GlobalFindInPageState.h"
</span><span class="cx"> #import "InteractionInformationAtPosition.h"
</span><span class="lines">@@ -1137,6 +1138,26 @@
</span><span class="cx">     m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestEvasionRectsAboveSelection(), WTFMove(callback), m_pageID);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler)
+{
+    if (!hasRunningProcess()) {
+        completionHandler();
+        return;
+    }
+
+    m_process->connection()->sendWithAsyncReply(Messages::WebPage::UpdateSelectionWithDelta(locationDelta, lengthDelta), WTFMove(completionHandler), m_pageID);
+}
+
+void WebPageProxy::requestDocumentEditingContext(WebKit::DocumentEditingContextRequest request, CompletionHandler<void(WebKit::DocumentEditingContext)>&& completionHandler)
+{
+    if (!hasRunningProcess()) {
+        completionHandler({ });
+        return;
+    }
+
+    m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestDocumentEditingContext(request), WTFMove(completionHandler), m_pageID);
+}
+
</ins><span class="cx"> #if ENABLE(DATA_INTERACTION)
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didHandleDragStartRequest(bool started)
</span></span></pre></div>
<a id="trunkSourceWebKitWebKitxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj     2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -2709,6 +2709,8 @@
</span><span class="cx">          2D7DEE2721269E4E00B9F73C /* UnifiedSource13.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UnifiedSource13.cpp; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource13.cpp"; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="cx">          2D7DEE2E21269E4E00B9F73C /* UnifiedSource57-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource57-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource57-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="cx">          2D7DEE3121269E4E00B9F73C /* UnifiedSource12-mm.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "UnifiedSource12-mm.mm"; path = "DerivedSources/WebKit2/unified-sources/UnifiedSource12-mm.mm"; sourceTree = BUILT_PRODUCTS_DIR; };
</span><ins>+               2D7FD190223C730F007887F1 /* DocumentEditingContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DocumentEditingContext.h; sourceTree = "<group>"; };
+               2D7FD191223C7310007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; };
</ins><span class="cx">           2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewGestureGeometryCollector.cpp; sourceTree = "<group>"; };
</span><span class="cx">          2D819B9A186275B3001F03D1 /* ViewGestureGeometryCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewGestureGeometryCollector.h; sourceTree = "<group>"; };
</span><span class="cx">          2D819B9B186275B3001F03D1 /* ViewGestureGeometryCollector.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ViewGestureGeometryCollector.messages.in; sourceTree = "<group>"; };
</span><span class="lines">@@ -5082,6 +5084,8 @@
</span><span class="cx">                          5106D7BF18BDBE73000AB166 /* ContextMenuContextData.cpp */,
</span><span class="cx">                          5106D7C018BDBE73000AB166 /* ContextMenuContextData.h */,
</span><span class="cx">                          99F642D21FABE378009621E9 /* CoordinateSystem.h */,
</span><ins>+                               2D7FD190223C730F007887F1 /* DocumentEditingContext.h */,
+                               2D7FD191223C7310007887F1 /* DocumentEditingContext.mm */,
</ins><span class="cx">                           C517388012DF8F4F00EE3F47 /* DragControllerAction.h */,
</span><span class="cx">                          0FB659221208B4DB0044816C /* DrawingAreaInfo.h */,
</span><span class="cx">                          2D9CD5EE21FA75EE0029ACFA /* EditingRange.cpp */,
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp       2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp  2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -6587,25 +6587,27 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPage::focusTextInputContext(const TextInputContext& textInputContext, CompletionHandler<void(bool)>&& completionHandler)
</span><span class="cx"> {
</span><del>-    completionHandler([&] {
-        if (textInputContext.webPageIdentifier != m_pageID)
-            return false;
</del><ins>+    RefPtr<Element> element = elementForTextInputContext(textInputContext);
</ins><span class="cx"> 
</span><del>-        auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier);
-        if (!document)
-            return false;
</del><ins>+    if (element)
+        element->focus();
</ins><span class="cx"> 
</span><del>-        if (document->page() != m_page.get())
-            return false;
</del><ins>+    completionHandler(element);
+}
</ins><span class="cx"> 
</span><del>-        auto* element = document->searchForElementByIdentifier(textInputContext.elementIdentifier);
-        if (!element)
-            return false;
</del><ins>+Element* WebPage::elementForTextInputContext(const TextInputContext& textInputContext)
+{
+    if (textInputContext.webPageIdentifier != m_pageID)
+        return nullptr;
</ins><span class="cx"> 
</span><del>-        element->focus();
</del><ins>+    auto* document = Document::allDocumentsMap().get(textInputContext.documentIdentifier);
+    if (!document)
+        return nullptr;
</ins><span class="cx"> 
</span><del>-        return true;
-    }());
</del><ins>+    if (document->page() != m_page.get())
+        return nullptr;
+
+    return document->searchForElementByIdentifier(textInputContext.elementIdentifier);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPage::configureLoggingChannel(const String& channelName, WTFLogChannelState state, WTFLogLevel level)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h    2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -686,6 +686,9 @@
</span><span class="cx"> 
</span><span class="cx">     bool forceAlwaysUserScalable() const { return m_forceAlwaysUserScalable; }
</span><span class="cx">     void setForceAlwaysUserScalable(bool);
</span><ins>+
+    void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&);
+    void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS_FAMILY) && ENABLE(IOS_TOUCH_EVENTS)
</span><span class="lines">@@ -1166,6 +1169,8 @@
</span><span class="cx"> 
</span><span class="cx">     void configureLoggingChannel(const String&, WTFLogChannelState, WTFLogLevel);
</span><span class="cx"> 
</span><ins>+    WebCore::Element* elementForTextInputContext(const TextInputContext&);
+
</ins><span class="cx"> #if ENABLE(APPLE_PAY)
</span><span class="cx">     WebPaymentCoordinator* paymentCoordinator();
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in       2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in  2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -110,6 +110,8 @@
</span><span class="cx">     RequestFocusedElementInformation(WebKit::CallbackID callbackID)
</span><span class="cx">     HardwareKeyboardAvailabilityChanged(bool keyboardIsAttached)
</span><span class="cx">     SetIsShowingInputViewForFocusedElement(bool showingInputView)
</span><ins>+    UpdateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta) -> () Async
+    RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     SetControlledByAutomation(bool controlled)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm    2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #import "AccessibilityIOS.h"
</span><span class="cx"> #import "DataReference.h"
</span><ins>+#import "DocumentEditingContext.h"
</ins><span class="cx"> #import "DrawingArea.h"
</span><span class="cx"> #import "EditingRange.h"
</span><span class="cx"> #import "EditorState.h"
</span><span class="lines">@@ -3312,6 +3313,222 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&& completionHandler)
+{
+    Ref<Frame> frame = corePage()->focusController().focusedOrMainFrame();
+    VisibleSelection selection = frame->selection().selection();
+    if (selection.isNone()) {
+        completionHandler();
+        return;
+    }
+
+    auto root = frame->selection().rootEditableElementOrDocumentElement();
+    auto range = selection.toNormalizedRange();
+    if (!root || !range) {
+        completionHandler();
+        return;
+    }
+
+    size_t selectionLocation;
+    size_t selectionLength;
+    TextIterator::getLocationAndLengthFromRange(root, range.get(), selectionLocation, selectionLength);
+
+    CheckedInt64 newSelectionLocation { selectionLocation };
+    CheckedInt64 newSelectionLength { selectionLength };
+    newSelectionLocation += locationDelta;
+    newSelectionLength += lengthDelta;
+
+    if (newSelectionLocation.hasOverflowed() || newSelectionLength.hasOverflowed()) {
+        completionHandler();
+        return;
+    }
+
+    if (auto range = TextIterator::rangeFromLocationAndLength(root, newSelectionLocation.unsafeGet(), newSelectionLength.unsafeGet()))
+        frame->selection().setSelectedRange(range.get(), DOWNSTREAM, WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
+
+    completionHandler();
+}
+
+static VisiblePosition moveByGranularityRespectingWordBoundary(Frame& frame, VisiblePosition& position, TextGranularity granularity, uint64_t granularityCount, SelectionDirection direction)
+{
+    bool backwards = direction == DirectionBackward;
+    auto farthestPositionInDirection = backwards ? startOfEditableContent(position) : endOfEditableContent(position);
+    if (position == farthestPositionInDirection)
+        return { };
+
+    VisiblePosition currentPosition = position;
+    VisiblePosition nextPosition;
+    for (unsigned i = 0; i < granularityCount + 1; ++i) {
+        nextPosition = positionOfNextBoundaryOfGranularity(currentPosition, granularity, direction);
+        // FIXME (196127): We shouldn't need to do this, but have seen previousParagraphPosition go forwards.
+        if ((backwards && nextPosition > currentPosition) || (!backwards && nextPosition < currentPosition))
+            break;
+        if (nextPosition.isNull())
+            break;
+        currentPosition = nextPosition;
+    }
+
+    return backwards ? startOfWord(currentPosition) : endOfWord(currentPosition);
+}
+
+static VisiblePosition visiblePositionForPointInRootViewCoordinates(Frame& frame, FloatPoint pointInRootViewCoordinates)
+{
+    auto pointInDocument = frame.view()->rootViewToContents(roundedIntPoint(pointInRootViewCoordinates));
+    return frame.visiblePositionForPoint(pointInDocument);
+}
+
+void WebPage::requestDocumentEditingContext(DocumentEditingContextRequest request, CompletionHandler<void(DocumentEditingContext)>&& completionHandler)
+{
+    if (!request.options.contains(DocumentEditingContextRequest::Options::Text) && !request.options.contains(DocumentEditingContextRequest::Options::AttributedText)) {
+        completionHandler({ });
+        return;
+    }
+
+    m_page->focusController().focusedOrMainFrame().document()->updateLayoutIgnorePendingStylesheets();
+
+    Ref<Frame> frame = m_page->focusController().focusedOrMainFrame();
+    VisibleSelection selection = frame->selection().selection();
+
+    VisiblePosition rangeOfInterestStart;
+    VisiblePosition rangeOfInterestEnd;
+    VisiblePosition selectionStart = selection.visibleStart();
+    VisiblePosition selectionEnd = selection.visibleEnd();
+
+    bool isSpatialRequest = request.options.contains(DocumentEditingContextRequest::Options::Spatial);
+    bool wantsRects = request.options.contains(DocumentEditingContextRequest::Options::Rects);
+
+    if (auto textInputContext = request.textInputContext) {
+        RefPtr<Element> element = elementForTextInputContext(*textInputContext);
+        if (!element) {
+            completionHandler({ });
+            return;
+        }
+        if (is<HTMLTextFormControlElement>(element)) {
+            auto& textFormControlElement = downcast<HTMLTextFormControlElement>(*element);
+            rangeOfInterestStart = textFormControlElement.visiblePositionForIndex(0);
+            rangeOfInterestEnd = textFormControlElement.visiblePositionForIndex(textFormControlElement.value().length());
+        } else {
+            rangeOfInterestStart = firstPositionInOrBeforeNode(element.get());
+            rangeOfInterestEnd = lastPositionInOrAfterNode(element.get());
+        }
+    } else if (isSpatialRequest) {
+        // FIXME: We might need to be a bit more careful that we get something useful (test the other corners?).
+        rangeOfInterestStart = visiblePositionForPointInRootViewCoordinates(frame.get(), request.rect.minXMinYCorner());
+        rangeOfInterestEnd = visiblePositionForPointInRootViewCoordinates(frame.get(), request.rect.maxXMaxYCorner());
+        if (rangeOfInterestEnd < rangeOfInterestStart)
+            std::exchange(rangeOfInterestStart, rangeOfInterestEnd);
+    } else if (!selection.isNone()) {
+        rangeOfInterestStart = selectionStart;
+        rangeOfInterestEnd = selectionEnd;
+    }
+
+    if (rangeOfInterestStart.isNull() || rangeOfInterestStart.isOrphan() || rangeOfInterestEnd.isNull() || rangeOfInterestEnd.isOrphan()) {
+        completionHandler({ });
+        return;
+    }
+
+    DocumentEditingContext context;
+
+    // The subset of the selection that is inside the range of interest.
+    VisiblePosition startOfRangeOfInterestInSelection;
+    VisiblePosition endOfRangeOfInterestInSelection;
+
+    auto selectionRange = selection.toNormalizedRange();
+    auto rangeOfInterest = makeRange(rangeOfInterestStart, rangeOfInterestEnd);
+    if (selectionRange && rangesOverlap(rangeOfInterest.get(), selectionRange.get())) {
+        startOfRangeOfInterestInSelection = rangeOfInterestStart > selectionStart ? rangeOfInterestStart : selectionStart;
+        endOfRangeOfInterestInSelection = rangeOfInterestEnd < selectionEnd ? rangeOfInterestEnd : selectionEnd;
+    } else {
+        size_t rangeOfInterestLocation;
+        size_t rangeOfInterestLength;
+        RefPtr<Node> rootNode = rangeOfInterest->commonAncestorContainer();
+        if (!rootNode) {
+            completionHandler({ });
+            return;
+        }
+
+        RefPtr<ContainerNode> rootContainerNode = rootNode->isContainerNode() ? downcast<ContainerNode>(rootNode.get()) : rootNode->parentNode();
+        TextIterator::getLocationAndLengthFromRange(rootContainerNode.get(), rangeOfInterest.get(), rangeOfInterestLocation, rangeOfInterestLength);
+
+        CheckedSize midpointLocation { rangeOfInterestLocation };
+        midpointLocation += rangeOfInterestLength / 2;
+        if (midpointLocation.hasOverflowed()) {
+            completionHandler({ });
+            return;
+        }
+
+        auto midpointRange = TextIterator::rangeFromLocationAndLength(rootContainerNode.get(), midpointLocation.unsafeGet(), 0);
+
+        auto midpoint = midpointRange->startPosition();
+        startOfRangeOfInterestInSelection = startOfWord(midpoint);
+        if (startOfRangeOfInterestInSelection < rangeOfInterestStart) {
+            startOfRangeOfInterestInSelection = endOfWord(midpoint);
+            if (startOfRangeOfInterestInSelection > rangeOfInterestEnd)
+                startOfRangeOfInterestInSelection = midpoint;
+        }
+
+        endOfRangeOfInterestInSelection = startOfRangeOfInterestInSelection;
+    }
+
+    VisiblePosition contextBeforeStart;
+    VisiblePosition contextAfterEnd;
+    if (request.granularityCount) {
+        contextBeforeStart = moveByGranularityRespectingWordBoundary(frame.get(), rangeOfInterestStart, request.surroundingGranularity, request.granularityCount, DirectionBackward);
+        contextAfterEnd = moveByGranularityRespectingWordBoundary(frame.get(), rangeOfInterestEnd, request.surroundingGranularity, request.granularityCount, DirectionForward);
+    } else {
+        contextBeforeStart = rangeOfInterestStart;
+        contextAfterEnd = rangeOfInterestEnd;
+    }
+
+    auto makeString = [&](VisiblePosition& start, VisiblePosition& end) -> NSAttributedString * {
+        if (start.isNull() || end.isNull() || start == end)
+            return nil;
+        // FIXME: This should return editing-offset-compatible attributed strings if that option is requested.
+        return adoptNS([[NSAttributedString alloc] initWithString:plainTextReplacingNoBreakSpace(start.deepEquivalent(), end.deepEquivalent())]).autorelease();
+    };
+
+    context.contextBefore = makeString(contextBeforeStart, startOfRangeOfInterestInSelection);
+    context.selectedText = makeString(startOfRangeOfInterestInSelection, endOfRangeOfInterestInSelection);
+    context.contextAfter = makeString(endOfRangeOfInterestInSelection, contextAfterEnd);
+
+    auto compositionRange = frame->editor().compositionRange();
+    if (compositionRange && rangesOverlap(rangeOfInterest.get(), compositionRange.get())) {
+        VisiblePosition compositionStart(compositionRange->startPosition());
+        VisiblePosition compositionEnd(compositionRange->endPosition());
+
+        VisiblePosition relevantCompositionStart = rangeOfInterestStart > compositionStart ? rangeOfInterestStart : compositionStart;
+        VisiblePosition relevantCompositionEnd = rangeOfInterestEnd < compositionEnd ? rangeOfInterestEnd : compositionEnd;
+
+        context.markedText = makeString(relevantCompositionStart, relevantCompositionEnd);
+        context.selectedRangeInMarkedText.location = distanceBetweenPositions(relevantCompositionStart, startOfRangeOfInterestInSelection);
+        context.selectedRangeInMarkedText.length = [context.selectedText.string length];
+    }
+
+    if (wantsRects) {
+        TextIterator contextIterator(contextBeforeStart.deepEquivalent(), contextAfterEnd.deepEquivalent());
+        unsigned currentLocation = 0;
+        while (!contextIterator.atEnd()) {
+            unsigned length = contextIterator.text().length();
+            if (!length) {
+                contextIterator.advance();
+                continue;
+            }
+
+            DocumentEditingContext::TextRectAndRange rect;
+            rect.rect = contextIterator.range()->absoluteBoundingBox();
+            rect.range = { currentLocation, length };
+            context.textRects.append(rect);
+
+            currentLocation += length;
+            contextIterator.advance();
+        }
+    }
+
+    // FIXME: Support Annotation option.
+
+    completionHandler(context);
+}
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // PLATFORM(IOS_FAMILY)
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/ChangeLog       2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2019-03-21  Tim Horton  <timothy_horton@apple.com>
+
+        Adopt UIWKDocumentContext
+        https://bugs.webkit.org/show_bug.cgi?id=196040
+        <rdar://problem/48642440>
+
+        Reviewed by Ryosuke Niwa.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm: Added.
+        (makeRequest):
+        (-[TestWKWebView synchronouslyRequestDocumentContext:]):
+        (-[TestWKWebView synchronouslyAdjustSelectionWithDelta:]):
+        (applyStyle):
+        (TEST):
+        Add tests for UIWKDocumentContext.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm:
+        (TEST):
+        (recursiveFindWKContentView): Deleted.
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (recursiveFindWKContentView):
+        (-[TestWKWebView wkContentView]):
+        * TestWebKitAPI/ios/UIKitSPI.h:
+        Share the WKContentView finding code between tests.
+
</ins><span class="cx"> 2019-03-21  Simon Fraser  <simon.fraser@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [iOS WK2] Turn on async overflow scrolling by default
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj   2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -98,6 +98,7 @@
</span><span class="cx">          2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
</span><span class="cx">          2D70059621EDA0C6003463CB /* TabOutOfWebView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */; };
</span><span class="cx">          2D70059921EDA4D0003463CB /* OffscreenWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D70059721EDA4D0003463CB /* OffscreenWindow.mm */; };
</span><ins>+               2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D7FD19222419087007887F1 /* DocumentEditingContext.mm */; };
</ins><span class="cx">           2D838B1F1EEF3A5C009B980E /* WKContentViewEditingActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */; };
</span><span class="cx">          2DADF26321CB8F32003D3E3A /* GetResourceData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DADF26221CB8F32003D3E3A /* GetResourceData.mm */; };
</span><span class="cx">          2DB0232F1E4E871800707123 /* InteractionDeadlockAfterCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DB0232E1E4E871800707123 /* InteractionDeadlockAfterCrash.mm */; };
</span><span class="lines">@@ -1453,6 +1454,7 @@
</span><span class="cx">          2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TabOutOfWebView.mm; sourceTree = "<group>"; };
</span><span class="cx">          2D70059721EDA4D0003463CB /* OffscreenWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OffscreenWindow.mm; sourceTree = "<group>"; };
</span><span class="cx">          2D70059821EDA4D0003463CB /* OffscreenWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OffscreenWindow.h; sourceTree = "<group>"; };
</span><ins>+               2D7FD19222419087007887F1 /* DocumentEditingContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DocumentEditingContext.mm; sourceTree = "<group>"; };
</ins><span class="cx">           2D8104CB1BEC13E70020DA46 /* FindInPage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FindInPage.mm; sourceTree = "<group>"; };
</span><span class="cx">          2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKContentViewEditingActions.mm; sourceTree = "<group>"; };
</span><span class="cx">          2D9A53AE1B31FA8D0074D5AA /* ShrinkToFit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ShrinkToFit.mm; sourceTree = "<group>"; };
</span><span class="lines">@@ -2548,6 +2550,7 @@
</span><span class="cx">                          46918EFB2237283500468DFE /* DeviceOrientation.mm */,
</span><span class="cx">                          CEA7F57B20895F5B0078EF6E /* DidResignInputElementStrongPasswordAppearance.mm */,
</span><span class="cx">                          518EE51A20A78CFB00E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm */,
</span><ins>+                               2D7FD19222419087007887F1 /* DocumentEditingContext.mm */,
</ins><span class="cx">                           518EE51620A78CDF00E024F3 /* DoubleDefersLoading.mm */,
</span><span class="cx">                          518EE51720A78CDF00E024F3 /* DoubleDefersLoadingPlugin.mm */,
</span><span class="cx">                          A1A4FE5D18DD3DB700B5EA8A /* Download.mm */,
</span><span class="lines">@@ -4071,6 +4074,7 @@
</span><span class="cx">                          7CCE7EEA1A411AE600447C4C /* DidNotHandleKeyDown.cpp in Sources */,
</span><span class="cx">                          AD57AC211DA7465B00FF1BDE /* DidRemoveFrameFromHiearchyInPageCache.cpp in Sources */,
</span><span class="cx">                          518EE51B20A78D0000E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm in Sources */,
</span><ins>+                               2D7FD19322419087007887F1 /* DocumentEditingContext.mm in Sources */,
</ins><span class="cx">                           7CCE7EEB1A411AE600447C4C /* DocumentStartUserScriptAlertCrash.cpp in Sources */,
</span><span class="cx">                          7CCE7EBB1A411A7E00447C4C /* DOMHTMLTableCellCellAbove.mm in Sources */,
</span><span class="cx">                          2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */,
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoaDocumentEditingContextmm"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm (0 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm                            (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DocumentEditingContext.mm       2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -0,0 +1,239 @@
</span><ins>+/*
+ * Copyright (C) 2019 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"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
+#import "UIKitSPI.h"
+#import <WebKit/WKPreferencesRefPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKTextInputContext.h>
+#import <wtf/RetainPtr.h>
+
+#define EXPECT_NSSTRING_EQ(expected, actual) \
+    EXPECT_TRUE([actual isKindOfClass:[NSString class]]); \
+    EXPECT_WK_STREQ(expected, (NSString *)actual);
+
+#define EXPECT_ATTRIBUTED_STRING_EQ(expected, actual) \
+    EXPECT_TRUE([actual isKindOfClass:[NSAttributedString class]]); \
+    EXPECT_WK_STREQ(expected, [(NSAttributedString *)actual string]);
+
+#define EXPECT_RECT_EQ(xExpected, yExpected, widthExpected, heightExpected, rect) \
+    EXPECT_DOUBLE_EQ(xExpected, rect.origin.x); \
+    EXPECT_DOUBLE_EQ(yExpected, rect.origin.y); \
+    EXPECT_DOUBLE_EQ(widthExpected, rect.size.width); \
+    EXPECT_DOUBLE_EQ(heightExpected, rect.size.height);
+
+@interface WKContentView ()
+- (void)requestDocumentContext:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler;
+- (void)adjustSelectionWithDelta:(NSRange)deltaRange completionHandler:(void (^)(void))completionHandler;
+@end
+
+static UIWKDocumentRequest *makeRequest(UIWKDocumentRequestFlags flags, UITextGranularity granularity, NSInteger granularityCount, CGRect documentRect = CGRectZero, id <NSCopying> inputElementIdentifier = nil)
+{
+    RetainPtr<UIWKDocumentRequest> request = adoptNS([[NSClassFromString(@"UIWKDocumentRequest") alloc] init]);
+    [request setFlags:flags];
+    [request setSurroundingGranularity:granularity];
+    [request setGranularityCount:granularityCount];
+    [request setDocumentRect:documentRect];
+    [request setInputElementIdentifier:inputElementIdentifier];
+    return request.autorelease();
+}
+
+@implementation TestWKWebView (SynchronousDocumentContext)
+
+- (UIWKDocumentContext *)synchronouslyRequestDocumentContext:(UIWKDocumentRequest *)request
+{
+    __block bool finished = false;
+    __block RetainPtr<UIWKDocumentContext> result;
+    [[self wkContentView] requestDocumentContext:request completionHandler:^(UIWKDocumentContext *context) {
+        result = context;
+        finished = true;
+    }];
+    TestWebKitAPI::Util::run(&finished);
+    return result.autorelease();
+}
+
+- (void)synchronouslyAdjustSelectionWithDelta:(NSRange)range
+{
+    __block bool finished = false;
+    [[self wkContentView] adjustSelectionWithDelta:range completionHandler:^() {
+        finished = true;
+    }];
+    TestWebKitAPI::Util::run(&finished);
+}
+
+- (NSArray<_WKTextInputContext *> *)synchronouslyRequestTextInputContextsInRect:(CGRect)rect
+{
+    __block bool finished = false;
+    __block RetainPtr<NSArray<_WKTextInputContext *>> result;
+    [self _requestTextInputContextsInRect:rect completionHandler:^(NSArray<_WKTextInputContext *> *contexts) {
+        result = contexts;
+        finished = true;
+    }];
+    TestWebKitAPI::Util::run(&finished);
+    return result.autorelease();
+}
+
+@end
+
+static NSString *applyStyle(NSString *HTMLString)
+{
+    return [@"<style>body { margin: 0; } iframe { border: none; }</style><meta name='viewport' content='initial-scale=1'>" stringByAppendingString:HTMLString];
+}
+
+static NSString *applyAhemStyle(NSString *HTMLString)
+{
+    return [@"<style>@font-face { font-family: customFont; src: url(Ahem.ttf); } body { margin: 0; font-family: customFont; } iframe { border: none; }</style><meta name='viewport' content='initial-scale=1'>" stringByAppendingString:HTMLString];
+}
+
+TEST(WebKit, DocumentEditingContext)
+{
+    if (!NSClassFromString(@"UIWKDocumentRequest"))
+        return;
+
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+    UIWKDocumentContext *context;
+
+    [webView synchronouslyLoadHTMLString:applyStyle(@"<span id='the'>The</span> quick brown fox <span id='jumps'>jumps</span> over the lazy <span id='dog'>dog.</span>")];
+    [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(jumps, 0, jumps, 1)"];
+
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("fox ", context.contextBefore);
+    EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+    EXPECT_NSSTRING_EQ(" over", context.contextAfter);
+
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 2)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("brown fox ", context.contextBefore);
+    EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+    EXPECT_NSSTRING_EQ(" over the", context.contextAfter);
+
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityParagraph, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("The quick brown fox ", context.contextBefore);
+    EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+    EXPECT_NSSTRING_EQ(" over the lazy dog.", context.contextAfter);
+
+    // Attributed strings.
+    // FIXME: Currently we don't test the attributes... because we don't set any.
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestAttributed, UITextGranularityWord, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_ATTRIBUTED_STRING_EQ("fox ", context.contextBefore);
+    EXPECT_ATTRIBUTED_STRING_EQ("jumps", context.selectedText);
+    EXPECT_ATTRIBUTED_STRING_EQ(" over", context.contextAfter);
+
+    // Extremities of the document.
+    [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(the, 0, the, 1)"];
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NULL(context.contextBefore);
+    EXPECT_NSSTRING_EQ("The", context.selectedText);
+    EXPECT_NSSTRING_EQ(" quick", context.contextAfter);
+
+    [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(dog, 0, dog, 1)"];
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularitySentence, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("The quick brown fox jumps over the lazy ", context.contextBefore);
+    EXPECT_NSSTRING_EQ("dog.", context.selectedText);
+    EXPECT_NULL(context.contextAfter);
+
+    // Spatial requests.
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestSpatial, UITextGranularityWord, 1, CGRectMake(0, 0, 10, 10))];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NULL(context.contextBefore);
+    EXPECT_NULL(context.selectedText);
+    EXPECT_NSSTRING_EQ("The quick", context.contextAfter);
+
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestSpatial, UITextGranularityWord, 1, CGRectMake(0, 0, 800, 600))];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("The quick brown fox jumps over the lazy ", context.contextBefore);
+    EXPECT_NSSTRING_EQ("dog.", context.selectedText);
+    EXPECT_NULL(context.contextAfter);
+
+    [webView stringByEvaluatingJavaScript:@"getSelection().removeAllRanges()"];
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestSpatial, UITextGranularityWord, 1, CGRectMake(0, 0, 800, 600))];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("The quick brown fox ", context.contextBefore);
+    EXPECT_NULL(context.selectedText);
+    EXPECT_NSSTRING_EQ("jumps over the lazy dog.", context.contextAfter);
+
+    // Selection adjustment.
+    [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(jumps, 0, jumps, 1)"];
+    [webView synchronouslyAdjustSelectionWithDelta:NSMakeRange(6, -1)];
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("over", context.selectedText);
+
+    [webView synchronouslyAdjustSelectionWithDelta:NSMakeRange(-6, 1)];
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 1)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NSSTRING_EQ("jumps", context.selectedText);
+
+    // Text rects.
+    [webView synchronouslyLoadHTMLString:applyAhemStyle(@"<span id='four'>MMMM</span> MMM MM M")];
+    [webView stringByEvaluatingJavaScript:@"getSelection().setBaseAndExtent(four, 0, four, 1)"];
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestRects, UITextGranularityWord, 0)];
+    EXPECT_NOT_NULL(context);
+    EXPECT_NULL(context.contextBefore);
+    EXPECT_NSSTRING_EQ("MMMM", context.selectedText);
+    EXPECT_NULL(context.contextAfter);
+
+    NSArray<NSValue *> *rects = [context characterRectsForCharacterRange:NSMakeRange(0, 1)];
+    EXPECT_EQ(1UL, rects.count);
+    EXPECT_RECT_EQ(0, 0, 92, 24, rects.firstObject.CGRectValue);
+    rects = [context characterRectsForCharacterRange:NSMakeRange(5, 1)];
+    EXPECT_EQ(0UL, rects.count);
+
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText | UIWKDocumentRequestRects, UITextGranularityWord, 1)];
+    EXPECT_NSSTRING_EQ(" MMM", context.contextAfter);
+    rects = [context characterRectsForCharacterRange:NSMakeRange(0, 1)];
+    EXPECT_EQ(1UL, rects.count);
+    EXPECT_RECT_EQ(0, 0, 92, 24, rects.firstObject.CGRectValue);
+    rects = [context characterRectsForCharacterRange:NSMakeRange(6, 1)];
+    EXPECT_EQ(1UL, rects.count);
+    EXPECT_RECT_EQ(92, 0, 92, 24, rects.firstObject.CGRectValue);
+
+    // Text Input Context
+    [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;' value='hello, world'>")];
+    NSArray<_WKTextInputContext *> *textInputContexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
+    EXPECT_EQ(1UL, textInputContexts.count);
+    EXPECT_RECT_EQ(0, 0, 50, 50, textInputContexts[0].boundingRect);
+
+    context = [webView synchronouslyRequestDocumentContext:makeRequest(UIWKDocumentRequestText, UITextGranularityWord, 0, CGRectZero, textInputContexts[0])];
+    EXPECT_NSSTRING_EQ("hello,", context.contextBefore);
+    EXPECT_NULL(context.selectedText);
+    EXPECT_NSSTRING_EQ(" world", context.contextAfter);
+}
+
+#endif // PLATFORM(IOS_FAMILY)
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoaWKContentViewEditingActionsmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm       2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKContentViewEditingActions.mm  2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -34,20 +34,6 @@
</span><span class="cx"> #import <WebKit/WebKit.h>
</span><span class="cx"> #import <wtf/RetainPtr.h>
</span><span class="cx"> 
</span><del>-static UIView *recursiveFindWKContentView(UIView *view)
-{
-    if ([view isKindOfClass:NSClassFromString(@"WKContentView")])
-        return view;
-
-    for (UIView *subview in view.subviews) {
-        UIView *contentView = recursiveFindWKContentView(subview);
-        if (contentView)
-            return contentView;
-    }
-
-    return nil;
-}
-
</del><span class="cx"> TEST(WebKit, WKContentViewEditingActions)
</span><span class="cx"> {
</span><span class="cx">     [UIPasteboard generalPasteboard].items = @[];
</span><span class="lines">@@ -58,7 +44,7 @@
</span><span class="cx"> 
</span><span class="cx">     [webView stringByEvaluatingJavaScript:@"selectPlainText()"];
</span><span class="cx"> 
</span><del>-    UIView *contentView = recursiveFindWKContentView(webView.get());
</del><ins>+    UIView *contentView = [webView wkContentView];
</ins><span class="cx"> 
</span><span class="cx">     __block bool done = false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPIcocoaTestWKWebViewh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h  2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h     2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -79,6 +79,9 @@
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS_FAMILY)
</span><ins>+@interface WKContentView : UIView
+@end
+
</ins><span class="cx"> @interface TestWKWebView (IOSOnly)
</span><span class="cx"> @property (nonatomic, readonly) UIView <UITextInputPrivate, UITextInputMultiDocument> *textInputContentView;
</span><span class="cx"> @property (nonatomic, readonly) RetainPtr<NSArray> selectionRectsAfterPresentationUpdate;
</span><span class="lines">@@ -86,6 +89,7 @@
</span><span class="cx"> @property (nonatomic, readonly) NSArray<NSValue *> *selectionViewRectsInContentCoordinates;
</span><span class="cx"> - (_WKActivatedElementInfo *)activatedElementAtPosition:(CGPoint)position;
</span><span class="cx"> - (void)evaluateJavaScriptAndWaitForInputSessionToChange:(NSString *)script;
</span><ins>+- (WKContentView *)wkContentView;
</ins><span class="cx"> @end
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPIcocoaTestWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm    2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -509,6 +509,25 @@
</span><span class="cx">     return info.autorelease();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static WKContentView *recursiveFindWKContentView(UIView *view)
+{
+    if ([view isKindOfClass:NSClassFromString(@"WKContentView")])
+        return (WKContentView *)view;
+
+    for (UIView *subview in view.subviews) {
+        WKContentView *contentView = recursiveFindWKContentView(subview);
+        if (contentView)
+            return contentView;
+    }
+
+    return nil;
+}
+
+- (WKContentView *)wkContentView
+{
+    return recursiveFindWKContentView(self);
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPIiosUIKitSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h (243353 => 243354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h 2019-03-22 01:58:13 UTC (rev 243353)
+++ trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h    2019-03-22 02:26:09 UTC (rev 243354)
</span><span class="lines">@@ -141,4 +141,36 @@
</span><span class="cx"> + (BOOL)isInHardwareKeyboardMode;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+@interface UIWKDocumentContext : NSObject
+
+@property (nonatomic, copy) NSObject *contextBefore;
+@property (nonatomic, copy) NSObject *selectedText;
+@property (nonatomic, copy) NSObject *contextAfter;
+@property (nonatomic, copy) NSObject *markedText;
+@property (nonatomic, assign) NSRange selectedRangeInMarkedText;
+@property (nonatomic, copy) NSAttributedString *annotatedText;
+
+- (NSArray<NSValue *> *)characterRectsForCharacterRange:(NSRange)range;
+
+@end
+
+typedef NS_OPTIONS(NSInteger, UIWKDocumentRequestFlags) {
+    UIWKDocumentRequestNone = 0,
+    UIWKDocumentRequestText = 1 << 0,
+    UIWKDocumentRequestAttributed = 1 << 1,
+    UIWKDocumentRequestRects = 1 << 2,
+    UIWKDocumentRequestSpatial = 1 << 3,
+    UIWKDocumentRequestAnnotation = 1 << 4,
+};
+
+@interface UIWKDocumentRequest : NSObject
+
+@property (nonatomic, assign) UIWKDocumentRequestFlags flags;
+@property (nonatomic, assign) UITextGranularity surroundingGranularity;
+@property (nonatomic, assign) NSInteger granularityCount;
+@property (nonatomic, assign) CGRect documentRect;
+@property (nonatomic, retain) id <NSCopying> inputElementIdentifier;
+
+@end
+
</ins><span class="cx"> #endif // PLATFORM(IOS_FAMILY)
</span></span></pre>
</div>
</div>

</body>
</html>