<!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>[214893] 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/214893">214893</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2017-04-04 12:59:52 -0700 (Tue, 04 Apr 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Mac] -[WKWebView findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:] invokes the resultCollector with didWrap = NO even when it wraps
https://bugs.webkit.org/show_bug.cgi?id=165801
&lt;rdar://problem/29649535&gt;

Reviewed by Wenson Hsieh.

New API tests: WebKit2.FindInPageWrapping*

Previously, when doing an incremental find that wrapped, we would 
say that it did not, leading NSTextFinder to not provide its usual
wrapping UI, and other clients of the NSTextFinderClient protocol to
get confused by the lack of wrapping.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didFindString):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/API/APIFindClient.h:
(API::FindClient::didFindString):
* UIProcess/API/C/WKPage.cpp:
(WKPageSetPageFindClient):
* UIProcess/Cocoa/FindClient.h:
* UIProcess/Cocoa/FindClient.mm:
(WebKit::FindClient::didFindString):
* WebProcess/WebPage/FindController.cpp:
(WebKit::FindController::updateFindUIAfterPageScroll):
(WebKit::FindController::findString):
* WebProcess/WebPage/FindController.h:
Plumb DidWrap from FindController's call to findString back through
the DidFindString message.

* UIProcess/mac/WKTextFinderClient.mm:
(-[WKTextFinderClient didFindStringMatchesWithRects:didWrapAround:]):
(-[WKTextFinderClient didFindStringMatchesWithRects:]): Deleted.
Make use of the new DidWrap information to stop lying to NSTextFinder
about whether a wrap actually occurred.

* page/FrameTree.cpp:
(WebCore::FrameTree::traverseNextWithWrap):
(WebCore::FrameTree::traversePreviousWithWrap):
(WebCore::FrameTree::traverseNextInPostOrderWithWrap):
* page/FrameTree.h:
Add CanWrap and DidWrap boolean enums, and add an optional out argument
to traverse*WithWrap indicating whether a wrap actually occurred.

* history/CachedPage.cpp:
(WebCore::firePageShowAndPopStateEvents):
* history/PageCache.cpp:
(WebCore::destroyRenderTree):
Adjust to the new CanWrap enum.

* page/Page.cpp:
(WebCore::incrementFrame):
(WebCore::Page::findString):
(WebCore::Page::findStringMatchingRanges):
(WebCore::Page::rangeOfString):
(WebCore::Page::findMatchesForText):
(WebCore::Page::unmarkAllTextMatches):
* page/Page.h:
Adjust to the new CanWrap enum, and optionally plumb DidWrap through
to callers of findString().

* WebView/WebView.mm:
(incrementFrame):
Adjust to the new CanWrap enum.

* TestWebKitAPI/Tests/WebKit2Cocoa/FindInPage.mm:
(TEST):
Add some tests for wrapping finds.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorehistoryCachedPagecpp">trunk/Source/WebCore/history/CachedPage.cpp</a></li>
<li><a href="#trunkSourceWebCorehistoryPageCachecpp">trunk/Source/WebCore/history/PageCache.cpp</a></li>
<li><a href="#trunkSourceWebCorepageFrameTreecpp">trunk/Source/WebCore/page/FrameTree.cpp</a></li>
<li><a href="#trunkSourceWebCorepageFrameTreeh">trunk/Source/WebCore/page/FrameTree.h</a></li>
<li><a href="#trunkSourceWebCorepagePagecpp">trunk/Source/WebCore/page/Page.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePageh">trunk/Source/WebCore/page/Page.h</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewmm">trunk/Source/WebKit/mac/WebView/WebView.mm</a></li>
<li><a href="#trunkSourceWebKitwinWebViewcpp">trunk/Source/WebKit/win/WebView.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIAPIFindClienth">trunk/Source/WebKit2/UIProcess/API/APIFindClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICWKPagecpp">trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaFindClienth">trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaFindClientmm">trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxymessagesin">trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKPDFViewmm">trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacWKTextFinderClientmm">trunk/Source/WebKit2/UIProcess/mac/WKTextFinderClient.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageFindControllercpp">trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageFindControllerh">trunk/Source/WebKit2/WebProcess/WebPage/FindController.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2CocoaFindInPagemm">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FindInPage.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/ChangeLog        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2017-04-04  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        [Mac] -[WKWebView findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:] invokes the resultCollector with didWrap = NO even when it wraps
+        https://bugs.webkit.org/show_bug.cgi?id=165801
+        &lt;rdar://problem/29649535&gt;
+
+        Reviewed by Wenson Hsieh.
+
+        New API tests: WebKit2.FindInPageWrapping*
+
+        * page/FrameTree.cpp:
+        (WebCore::FrameTree::traverseNextWithWrap):
+        (WebCore::FrameTree::traversePreviousWithWrap):
+        (WebCore::FrameTree::traverseNextInPostOrderWithWrap):
+        * page/FrameTree.h:
+        Add CanWrap and DidWrap boolean enums, and add an optional out argument
+        to traverse*WithWrap indicating whether a wrap actually occurred.
+
+        * history/CachedPage.cpp:
+        (WebCore::firePageShowAndPopStateEvents):
+        * history/PageCache.cpp:
+        (WebCore::destroyRenderTree):
+        Adjust to the new CanWrap enum.
+        
+        * page/Page.cpp:
+        (WebCore::incrementFrame):
+        (WebCore::Page::findString):
+        (WebCore::Page::findStringMatchingRanges):
+        (WebCore::Page::rangeOfString):
+        (WebCore::Page::findMatchesForText):
+        (WebCore::Page::unmarkAllTextMatches):
+        * page/Page.h:
+        Adjust to the new CanWrap enum, and optionally plumb DidWrap through
+        to callers of findString().
+
</ins><span class="cx"> 2017-04-04  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] PLATFORM(GTK) &amp;&amp; !USE(COORDINATED_GRAPHICS_THREADED) is no longer possible
</span></span></pre></div>
<a id="trunkSourceWebCorehistoryCachedPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/history/CachedPage.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/history/CachedPage.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/history/CachedPage.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -78,7 +78,7 @@
</span><span class="cx">     // Dispatching JavaScript events can cause frame destruction.
</span><span class="cx">     auto&amp; mainFrame = page.mainFrame();
</span><span class="cx">     Vector&lt;Ref&lt;Frame&gt;&gt; childFrames;
</span><del>-    for (auto* child = mainFrame.tree().traverseNextInPostOrderWithWrap(true); child; child = child-&gt;tree().traverseNextInPostOrderWithWrap(false))
</del><ins>+    for (auto* child = mainFrame.tree().traverseNextInPostOrder(CanWrap::Yes); child; child = child-&gt;tree().traverseNextInPostOrder(CanWrap::No))
</ins><span class="cx">         childFrames.append(*child);
</span><span class="cx"> 
</span><span class="cx">     for (auto&amp; child : childFrames) {
</span></span></pre></div>
<a id="trunkSourceWebCorehistoryPageCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/history/PageCache.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/history/PageCache.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/history/PageCache.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -374,7 +374,7 @@
</span><span class="cx"> // Note that destruction happens bottom-up so that the main frame's tree dies last.
</span><span class="cx"> static void destroyRenderTree(MainFrame&amp; mainFrame)
</span><span class="cx"> {
</span><del>-    for (Frame* frame = mainFrame.tree().traversePreviousWithWrap(true); frame; frame = frame-&gt;tree().traversePreviousWithWrap(false)) {
</del><ins>+    for (Frame* frame = mainFrame.tree().traversePrevious(CanWrap::Yes); frame; frame = frame-&gt;tree().traversePrevious(CanWrap::No)) {
</ins><span class="cx">         if (!frame-&gt;document())
</span><span class="cx">             continue;
</span><span class="cx">         auto&amp; document = *frame-&gt;document();
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameTreecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameTree.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameTree.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/page/FrameTree.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -403,18 +403,21 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Frame* FrameTree::traverseNextWithWrap(bool wrap) const
</del><ins>+Frame* FrameTree::traverseNext(CanWrap canWrap, DidWrap* didWrap) const
</ins><span class="cx"> {
</span><span class="cx">     if (Frame* result = traverseNext())
</span><span class="cx">         return result;
</span><span class="cx"> 
</span><del>-    if (wrap)
</del><ins>+    if (canWrap == CanWrap::Yes) {
+        if (didWrap)
+            *didWrap = DidWrap::Yes;
</ins><span class="cx">         return &amp;m_thisFrame.mainFrame();
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Frame* FrameTree::traversePreviousWithWrap(bool wrap) const
</del><ins>+Frame* FrameTree::traversePrevious(CanWrap canWrap, DidWrap* didWrap) const
</ins><span class="cx"> {
</span><span class="cx">     // FIXME: besides the wrap feature, this is just the traversePreviousNode algorithm
</span><span class="cx"> 
</span><span class="lines">@@ -424,20 +427,23 @@
</span><span class="cx">         return parentFrame;
</span><span class="cx">     
</span><span class="cx">     // no siblings, no parent, self==top
</span><del>-    if (wrap)
</del><ins>+    if (canWrap == CanWrap::Yes) {
+        if (didWrap)
+            *didWrap = DidWrap::Yes;
</ins><span class="cx">         return deepLastChild();
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     // top view is always the last one in this ordering, so prev is nil without wrap
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Frame* FrameTree::traverseNextInPostOrderWithWrap(bool wrap) const
</del><ins>+Frame* FrameTree::traverseNextInPostOrder(CanWrap canWrap) const
</ins><span class="cx"> {
</span><span class="cx">     if (m_nextSibling)
</span><span class="cx">         return m_nextSibling-&gt;tree().deepFirstChild();
</span><span class="cx">     if (m_parent)
</span><span class="cx">         return m_parent;
</span><del>-    if (wrap)
</del><ins>+    if (canWrap == CanWrap::Yes)
</ins><span class="cx">         return deepFirstChild();
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameTreeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameTree.h (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameTree.h        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/page/FrameTree.h        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -23,6 +23,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+enum class CanWrap : bool { No, Yes };
+enum class DidWrap : bool { No, Yes };
+
</ins><span class="cx"> class Frame;
</span><span class="cx"> class TreeScope;
</span><span class="cx"> 
</span><span class="lines">@@ -62,10 +65,10 @@
</span><span class="cx">     WEBCORE_EXPORT Frame* traverseNext(const Frame* stayWithin = nullptr) const;
</span><span class="cx">     // Rendered means being the main frame or having an ownerRenderer. It may not have been parented in the Widget tree yet (see WidgetHierarchyUpdatesSuspensionScope).
</span><span class="cx">     WEBCORE_EXPORT Frame* traverseNextRendered(const Frame* stayWithin = nullptr) const;
</span><del>-    WEBCORE_EXPORT Frame* traverseNextWithWrap(bool) const;
-    WEBCORE_EXPORT Frame* traversePreviousWithWrap(bool) const;
</del><ins>+    WEBCORE_EXPORT Frame* traverseNext(CanWrap, DidWrap* = nullptr) const;
+    WEBCORE_EXPORT Frame* traversePrevious(CanWrap, DidWrap* = nullptr) const;
</ins><span class="cx"> 
</span><del>-    Frame* traverseNextInPostOrderWithWrap(bool) const;
</del><ins>+    Frame* traverseNextInPostOrder(CanWrap) const;
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT void appendChild(Frame&amp;);
</span><span class="cx">     void detachFromParent() { m_parent = nullptr; }
</span></span></pre></div>
<a id="trunkSourceWebCorepagePagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/page/Page.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -647,19 +647,19 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag)
</del><ins>+static Frame* incrementFrame(Frame* curr, bool forward, CanWrap canWrap, DidWrap* didWrap = nullptr)
</ins><span class="cx"> {
</span><span class="cx">     return forward
</span><del>-        ? curr-&gt;tree().traverseNextWithWrap(wrapFlag)
-        : curr-&gt;tree().traversePreviousWithWrap(wrapFlag);
</del><ins>+        ? curr-&gt;tree().traverseNext(canWrap, didWrap)
+        : curr-&gt;tree().traversePrevious(canWrap, didWrap);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Page::findString(const String&amp; target, FindOptions options)
</del><ins>+bool Page::findString(const String&amp; target, FindOptions options, DidWrap* didWrap)
</ins><span class="cx"> {
</span><span class="cx">     if (target.isEmpty())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    bool shouldWrap = options &amp; WrapAround;
</del><ins>+    CanWrap canWrap = options &amp; WrapAround ? CanWrap::Yes : CanWrap::No;
</ins><span class="cx">     Frame* frame = &amp;focusController().focusedOrMainFrame();
</span><span class="cx">     Frame* startFrame = frame;
</span><span class="cx">     do {
</span><span class="lines">@@ -669,12 +669,14 @@
</span><span class="cx">             focusController().setFocusedFrame(frame);
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><del>-        frame = incrementFrame(frame, !(options &amp; Backwards), shouldWrap);
</del><ins>+        frame = incrementFrame(frame, !(options &amp; Backwards), canWrap, didWrap);
</ins><span class="cx">     } while (frame &amp;&amp; frame != startFrame);
</span><span class="cx"> 
</span><span class="cx">     // Search contents of startFrame, on the other side of the selection that we did earlier.
</span><span class="cx">     // We cheat a bit and just research with wrap on
</span><del>-    if (shouldWrap &amp;&amp; !startFrame-&gt;selection().isNone()) {
</del><ins>+    if (canWrap == CanWrap::Yes &amp;&amp; !startFrame-&gt;selection().isNone()) {
+        if (didWrap)
+            *didWrap = DidWrap::Yes;
</ins><span class="cx">         bool found = startFrame-&gt;editor().findString(target, options | WrapAround | StartInSelection);
</span><span class="cx">         focusController().setFocusedFrame(frame);
</span><span class="cx">         return found;
</span><span class="lines">@@ -693,7 +695,7 @@
</span><span class="cx">         frame-&gt;editor().countMatchesForText(target, 0, options, limit ? (limit - matchRanges.size()) : 0, true, &amp;matchRanges);
</span><span class="cx">         if (frame-&gt;selection().isRange())
</span><span class="cx">             frameWithSelection = frame;
</span><del>-        frame = incrementFrame(frame, true, false);
</del><ins>+        frame = incrementFrame(frame, true, CanWrap::No);
</ins><span class="cx">     } while (frame);
</span><span class="cx"> 
</span><span class="cx">     if (matchRanges.isEmpty())
</span><span class="lines">@@ -735,7 +737,7 @@
</span><span class="cx">     if (referenceRange &amp;&amp; referenceRange-&gt;ownerDocument().page() != this)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><del>-    bool shouldWrap = options &amp; WrapAround;
</del><ins>+    CanWrap canWrap = options &amp; WrapAround ? CanWrap::Yes : CanWrap::No;
</ins><span class="cx">     Frame* frame = referenceRange ? referenceRange-&gt;ownerDocument().frame() : &amp;mainFrame();
</span><span class="cx">     Frame* startFrame = frame;
</span><span class="cx">     do {
</span><span class="lines">@@ -742,12 +744,12 @@
</span><span class="cx">         if (RefPtr&lt;Range&gt; resultRange = frame-&gt;editor().rangeOfString(target, frame == startFrame ? referenceRange : 0, options &amp; ~WrapAround))
</span><span class="cx">             return resultRange;
</span><span class="cx"> 
</span><del>-        frame = incrementFrame(frame, !(options &amp; Backwards), shouldWrap);
</del><ins>+        frame = incrementFrame(frame, !(options &amp; Backwards), canWrap);
</ins><span class="cx">     } while (frame &amp;&amp; frame != startFrame);
</span><span class="cx"> 
</span><span class="cx">     // Search contents of startFrame, on the other side of the reference range that we did earlier.
</span><span class="cx">     // We cheat a bit and just search again with wrap on.
</span><del>-    if (shouldWrap &amp;&amp; referenceRange) {
</del><ins>+    if (canWrap == CanWrap::Yes &amp;&amp; referenceRange) {
</ins><span class="cx">         if (RefPtr&lt;Range&gt; resultRange = startFrame-&gt;editor().rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
</span><span class="cx">             return resultRange;
</span><span class="cx">     }
</span><span class="lines">@@ -767,7 +769,7 @@
</span><span class="cx">         if (shouldMarkMatches == MarkMatches)
</span><span class="cx">             frame-&gt;editor().setMarkedTextMatchesAreHighlighted(shouldHighlightMatches == HighlightMatches);
</span><span class="cx">         matchCount += frame-&gt;editor().countMatchesForText(target, 0, options, maxMatchCount ? (maxMatchCount - matchCount) : 0, shouldMarkMatches == MarkMatches, 0);
</span><del>-        frame = incrementFrame(frame, true, false);
</del><ins>+        frame = incrementFrame(frame, true, CanWrap::No);
</ins><span class="cx">     } while (frame);
</span><span class="cx"> 
</span><span class="cx">     return matchCount;
</span><span class="lines">@@ -788,7 +790,7 @@
</span><span class="cx">     Frame* frame = &amp;mainFrame();
</span><span class="cx">     do {
</span><span class="cx">         frame-&gt;document()-&gt;markers().removeMarkers(DocumentMarker::TextMatch);
</span><del>-        frame = incrementFrame(frame, true, false);
</del><ins>+        frame = incrementFrame(frame, true, CanWrap::No);
</ins><span class="cx">     } while (frame);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagePageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.h (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.h        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebCore/page/Page.h        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -145,6 +145,9 @@
</span><span class="cx">     Unresponsive
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum class CanWrap : bool;
+enum class DidWrap : bool;
+
</ins><span class="cx"> class Page : public Supplementable&lt;Page&gt; {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(Page);
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="lines">@@ -264,7 +267,7 @@
</span><span class="cx">     void setTabKeyCyclesThroughElements(bool b) { m_tabKeyCyclesThroughElements = b; }
</span><span class="cx">     bool tabKeyCyclesThroughElements() const { return m_tabKeyCyclesThroughElements; }
</span><span class="cx"> 
</span><del>-    WEBCORE_EXPORT bool findString(const String&amp;, FindOptions);
</del><ins>+    WEBCORE_EXPORT bool findString(const String&amp;, FindOptions, DidWrap* = nullptr);
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT RefPtr&lt;Range&gt; rangeOfString(const String&amp;, Range*, FindOptions);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit/mac/ChangeLog        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-04-04  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        [Mac] -[WKWebView findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:] invokes the resultCollector with didWrap = NO even when it wraps
+        https://bugs.webkit.org/show_bug.cgi?id=165801
+        &lt;rdar://problem/29649535&gt;
+
+        Reviewed by Wenson Hsieh.
+
+        * WebView/WebView.mm:
+        (incrementFrame):
+        Adjust to the new CanWrap enum.
+
</ins><span class="cx"> 2017-03-27  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Saving files should not suggest the top level directory
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebView.mm        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -6796,9 +6796,10 @@
</span><span class="cx"> static WebFrame *incrementFrame(WebFrame *frame, WebFindOptions options = 0)
</span><span class="cx"> {
</span><span class="cx">     Frame* coreFrame = core(frame);
</span><ins>+    CanWrap canWrap = options &amp; WebFindOptionsWrapAround ? CanWrap::Yes : CanWrap::No;
</ins><span class="cx">     return kit((options &amp; WebFindOptionsBackwards)
</span><del>-        ? coreFrame-&gt;tree().traversePreviousWithWrap(options &amp; WebFindOptionsWrapAround)
-        : coreFrame-&gt;tree().traverseNextWithWrap(options &amp; WebFindOptionsWrapAround));
</del><ins>+        ? coreFrame-&gt;tree().traversePrevious(canWrap)
+        : coreFrame-&gt;tree().traverseNext(canWrap));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag
</span></span></pre></div>
<a id="trunkSourceWebKitwinWebViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/win/WebView.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/win/WebView.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit/win/WebView.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -3856,9 +3856,10 @@
</span><span class="cx"> 
</span><span class="cx"> static Frame *incrementFrame(Frame *curr, bool forward, bool wrapFlag)
</span><span class="cx"> {
</span><ins>+    CanWrap canWrap = wrapFlag ? CanWrap::Yes : CanWrap::No;
</ins><span class="cx">     return forward
</span><del>-        ? curr-&gt;tree().traverseNextWithWrap(wrapFlag)
-        : curr-&gt;tree().traversePreviousWithWrap(wrapFlag);
</del><ins>+        ? curr-&gt;tree().traverseNext(canWrap)
+        : curr-&gt;tree().traversePrevious(canWrap);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> HRESULT WebView::searchFor(_In_ BSTR str, BOOL forward, BOOL caseFlag, BOOL wrapFlag, _Out_ BOOL* found)
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/ChangeLog        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2017-04-04  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        [Mac] -[WKWebView findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:] invokes the resultCollector with didWrap = NO even when it wraps
+        https://bugs.webkit.org/show_bug.cgi?id=165801
+        &lt;rdar://problem/29649535&gt;
+
+        Reviewed by Wenson Hsieh.
+
+        Previously, when doing an incremental find that wrapped, we would 
+        say that it did not, leading NSTextFinder to not provide its usual
+        wrapping UI, and other clients of the NSTextFinderClient protocol to
+        get confused by the lack of wrapping.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didFindString):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/API/APIFindClient.h:
+        (API::FindClient::didFindString):
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPageFindClient):
+        * UIProcess/Cocoa/FindClient.h:
+        * UIProcess/Cocoa/FindClient.mm:
+        (WebKit::FindClient::didFindString):
+        * WebProcess/WebPage/FindController.cpp:
+        (WebKit::FindController::updateFindUIAfterPageScroll):
+        (WebKit::FindController::findString):
+        * WebProcess/WebPage/FindController.h:
+        Plumb DidWrap from FindController's call to findString back through
+        the DidFindString message.
+
+        * UIProcess/mac/WKTextFinderClient.mm:
+        (-[WKTextFinderClient didFindStringMatchesWithRects:didWrapAround:]):
+        (-[WKTextFinderClient didFindStringMatchesWithRects:]): Deleted.
+        Make use of the new DidWrap information to stop lying to NSTextFinder
+        about whether a wrap actually occurred.
+
</ins><span class="cx"> 2017-04-03  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Data interaction should register type identifiers in order of priority
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIAPIFindClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/APIFindClient.h (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/APIFindClient.h        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/API/APIFindClient.h        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     virtual ~FindClient() { }
</span><span class="cx"> 
</span><span class="cx">     virtual void didCountStringMatches(WebKit::WebPageProxy*, const WTF::String&amp;, uint32_t) { }
</span><del>-    virtual void didFindString(WebKit::WebPageProxy*, const WTF::String&amp;, const Vector&lt;WebCore::IntRect&gt;&amp; matchRects, uint32_t, int32_t) { }
</del><ins>+    virtual void didFindString(WebKit::WebPageProxy*, const WTF::String&amp;, const Vector&lt;WebCore::IntRect&gt;&amp; matchRects, uint32_t, int32_t, bool didWrapAround) { }
</ins><span class="cx">     virtual void didFailToFindString(WebKit::WebPageProxy*, const WTF::String&amp;) { }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICWKPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -931,7 +931,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     private:
</span><del>-        void didFindString(WebPageProxy* page, const String&amp; string, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t) override
</del><ins>+        void didFindString(WebPageProxy* page, const String&amp; string, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t, bool didWrapAround) override
</ins><span class="cx">         {
</span><span class="cx">             if (!m_client.didFindString)
</span><span class="cx">                 return;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaFindClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.h (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.h        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.h        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx"> private:
</span><span class="cx">     // From API::FindClient
</span><span class="cx">     virtual void didCountStringMatches(WebPageProxy*, const String&amp;, uint32_t matchCount);
</span><del>-    virtual void didFindString(WebPageProxy*, const String&amp;, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t matchIndex);
</del><ins>+    virtual void didFindString(WebPageProxy*, const String&amp;, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t matchIndex, bool didWrapAround);
</ins><span class="cx">     virtual void didFailToFindString(WebPageProxy*, const String&amp;);
</span><span class="cx">     
</span><span class="cx">     WKWebView *m_webView;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaFindClientmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.mm (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.mm        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/FindClient.mm        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -57,7 +57,7 @@
</span><span class="cx">         [m_delegate.get() _webView:m_webView didCountMatches:matchCount forString:string];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FindClient::didFindString(WebPageProxy*, const String&amp; string, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t matchIndex)
</del><ins>+void FindClient::didFindString(WebPageProxy*, const String&amp; string, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t matchIndex, bool)
</ins><span class="cx"> {
</span><span class="cx">     if (m_delegateMethods.webviewDidFindString)
</span><span class="cx">         [m_delegate.get() _webView:m_webView didFindMatches:matchCount forString:string withMatchIndex:matchIndex];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -4466,9 +4466,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPageProxy::didFindString(const String&amp; string, const Vector&lt;WebCore::IntRect&gt;&amp; matchRects, uint32_t matchCount, int32_t matchIndex)
</del><ins>+void WebPageProxy::didFindString(const String&amp; string, const Vector&lt;WebCore::IntRect&gt;&amp; matchRects, uint32_t matchCount, int32_t matchIndex, bool didWrapAround)
</ins><span class="cx"> {
</span><del>-    m_findClient-&gt;didFindString(this, string, matchRects, matchCount, matchIndex);
</del><ins>+    m_findClient-&gt;didFindString(this, string, matchRects, matchCount, matchIndex, didWrapAround);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didFindStringMatches(const String&amp; string, const Vector&lt;Vector&lt;WebCore::IntRect&gt;&gt;&amp; matchRects, int32_t firstIndexAfterSelection)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -788,7 +788,7 @@
</span><span class="cx">     void setTextIndicator(const WebCore::TextIndicatorData&amp;, uint64_t /* WebCore::TextIndicatorWindowLifetime */ lifetime = 0 /* Permanent */);
</span><span class="cx">     void setTextIndicatorAnimationProgress(float);
</span><span class="cx">     void clearTextIndicator();
</span><del>-    void didFindString(const String&amp;, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t matchIndex);
</del><ins>+    void didFindString(const String&amp;, const Vector&lt;WebCore::IntRect&gt;&amp;, uint32_t matchCount, int32_t matchIndex, bool didWrapAround);
</ins><span class="cx">     void didFailToFindString(const String&amp;);
</span><span class="cx">     void didFindStringMatches(const String&amp;, const Vector&lt;Vector&lt;WebCore::IntRect&gt;&gt;&amp; matchRects, int32_t firstIndexAfterSelection);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -241,7 +241,7 @@
</span><span class="cx">     DidCountStringMatches(String string, uint32_t matchCount)
</span><span class="cx">     SetTextIndicator(struct WebCore::TextIndicatorData indicator, uint64_t lifetime)
</span><span class="cx">     ClearTextIndicator()
</span><del>-    DidFindString(String string, Vector&lt;WebCore::IntRect&gt; matchRect, uint32_t matchCount, int32_t matchIndex)
</del><ins>+    DidFindString(String string, Vector&lt;WebCore::IntRect&gt; matchRect, uint32_t matchCount, int32_t matchIndex, bool didWrapAround)
</ins><span class="cx">     DidFailToFindString(String string)
</span><span class="cx">     DidFindStringMatches(String string, Vector&lt;Vector&lt;WebCore::IntRect&gt;&gt; matches, int32_t firstIndexAfterSelection)
</span><span class="cx">     DidGetImageForFindMatch(WebKit::ShareableBitmap::Handle contentImageHandle, uint32_t matchIndex)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKPDFViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -614,7 +614,7 @@
</span><span class="cx">                 _currentFindMatchIndex = 0;
</span><span class="cx">                 for (const auto&amp; knownMatch : _cachedFindMatches) {
</span><span class="cx">                     if (match.stringRange.location == [knownMatch stringRange].location &amp;&amp; match.stringRange.length == [knownMatch stringRange].length) {
</span><del>-                        page-&gt;findClient().didFindString(page.get(), string, { }, _cachedFindMatches.size(), _currentFindMatchIndex);
</del><ins>+                        page-&gt;findClient().didFindString(page.get(), string, { }, _cachedFindMatches.size(), _currentFindMatchIndex, false);
</ins><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx">                     _currentFindMatchIndex++;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacWKTextFinderClientmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/WKTextFinderClient.mm (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/WKTextFinderClient.mm        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/UIProcess/mac/WKTextFinderClient.mm        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> @interface WKTextFinderClient ()
</span><span class="cx"> 
</span><del>-- (void)didFindStringMatchesWithRects:(const Vector&lt;Vector&lt;IntRect&gt;&gt;&amp;)rects;
</del><ins>+- (void)didFindStringMatchesWithRects:(const Vector&lt;Vector&lt;IntRect&gt;&gt;&amp;)rects didWrapAround:(BOOL)didWrapAround;
</ins><span class="cx"> 
</span><span class="cx"> - (void)getImageForMatchResult:(id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt;)findMatch completionHandler:(void (^)(NSImage *generatedImage))completionHandler;
</span><span class="cx"> - (void)didGetImageForMatchResult:(WebImage *)string;
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx"> private:
</span><span class="cx">     void didFindStringMatches(WebPageProxy* page, const String&amp;, const Vector&lt;Vector&lt;IntRect&gt;&gt;&amp; matchRects, int32_t) override
</span><span class="cx">     {
</span><del>-        [m_textFinderClient didFindStringMatchesWithRects:matchRects];
</del><ins>+        [m_textFinderClient didFindStringMatchesWithRects:matchRects didWrapAround:NO];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void didGetImageForMatchResult(WebPageProxy* page, WebImage* image, int32_t index) override
</span><span class="lines">@@ -74,14 +74,14 @@
</span><span class="cx">         [m_textFinderClient didGetImageForMatchResult:image];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void didFindString(WebPageProxy*, const String&amp;, const Vector&lt;IntRect&gt;&amp; matchRects, uint32_t, int32_t) override
</del><ins>+    void didFindString(WebPageProxy*, const String&amp;, const Vector&lt;IntRect&gt;&amp; matchRects, uint32_t, int32_t, bool didWrapAround) override
</ins><span class="cx">     {
</span><del>-        [m_textFinderClient didFindStringMatchesWithRects:{ matchRects }];
</del><ins>+        [m_textFinderClient didFindStringMatchesWithRects:{ matchRects } didWrapAround:didWrapAround];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void didFailToFindString(WebPageProxy*, const String&amp; string) override
</span><span class="cx">     {
</span><del>-        [m_textFinderClient didFindStringMatchesWithRects:{ }];
</del><ins>+        [m_textFinderClient didFindStringMatchesWithRects:{ } didWrapAround:NO];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;WKTextFinderClient&gt; m_textFinderClient;
</span><span class="lines">@@ -234,7 +234,7 @@
</span><span class="cx">     return nsMatchRects;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)didFindStringMatchesWithRects:(const Vector&lt;Vector&lt;IntRect&gt;&gt;&amp;)rectsForMatches
</del><ins>+- (void)didFindStringMatchesWithRects:(const Vector&lt;Vector&lt;IntRect&gt;&gt;&amp;)rectsForMatches didWrapAround:(BOOL)didWrapAround
</ins><span class="cx"> {
</span><span class="cx">     if (_findReplyCallbacks.isEmpty())
</span><span class="cx">         return;
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx">         [matchObjects addObject:match.get()];
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    replyCallback(matchObjects.get(), NO);
</del><ins>+    replyCallback(matchObjects.get(), didWrapAround);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)didGetImageForMatchResult:(WebImage *)image
</span><span class="lines">@@ -277,6 +277,9 @@
</span><span class="cx">         Block_release(copiedImageCallback);
</span><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    // FIXME: There is no guarantee that this will ever result in didGetImageForMatchResult
+    // being called (and thus us calling our completion handler); we should harden this
+    // against all of the early returns in FindController::getImageForFindMatch.
</ins><span class="cx">     _page-&gt;getImageForFindMatch(textFinderMatch.index);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageFindControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/WebProcess/WebPage/FindController.cpp        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FindController::updateFindUIAfterPageScroll(bool found, const String&amp; string, FindOptions options, unsigned maxMatchCount)
</del><ins>+void FindController::updateFindUIAfterPageScroll(bool found, const String&amp; string, FindOptions options, unsigned maxMatchCount, DidWrap didWrap)
</ins><span class="cx"> {
</span><span class="cx">     Frame* selectedFrame = frameWithSelection(m_webPage-&gt;corePage());
</span><span class="cx">     
</span><span class="lines">@@ -181,7 +181,7 @@
</span><span class="cx">             m_findMatches.append(range);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        m_webPage-&gt;send(Messages::WebPageProxy::DidFindString(string, matchRects, matchCount, m_foundStringMatchIndex));
</del><ins>+        m_webPage-&gt;send(Messages::WebPageProxy::DidFindString(string, matchRects, matchCount, m_foundStringMatchIndex, didWrap == DidWrap::Yes));
</ins><span class="cx"> 
</span><span class="cx">         if (!(options &amp; FindOptionsShowFindIndicator) || !selectedFrame || !updateFindIndicator(*selectedFrame, shouldShowOverlay))
</span><span class="cx">             hideFindIndicator();
</span><span class="lines">@@ -232,10 +232,11 @@
</span><span class="cx">     m_findMatches.clear();
</span><span class="cx"> 
</span><span class="cx">     bool found;
</span><ins>+    DidWrap didWrap = DidWrap::No;
</ins><span class="cx">     if (pluginView)
</span><span class="cx">         found = pluginView-&gt;findString(string, coreOptions, maxMatchCount);
</span><span class="cx">     else
</span><del>-        found = m_webPage-&gt;corePage()-&gt;findString(string, coreOptions);
</del><ins>+        found = m_webPage-&gt;corePage()-&gt;findString(string, coreOptions, &amp;didWrap);
</ins><span class="cx"> 
</span><span class="cx">     if (found) {
</span><span class="cx">         didFindString();
</span><span class="lines">@@ -249,8 +250,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;WebPage&gt; protectedWebPage = m_webPage;
</span><del>-    m_webPage-&gt;drawingArea()-&gt;dispatchAfterEnsuringUpdatedScrollPosition([protectedWebPage, found, string, options, maxMatchCount] () {
-        protectedWebPage-&gt;findController().updateFindUIAfterPageScroll(found, string, options, maxMatchCount);
</del><ins>+    m_webPage-&gt;drawingArea()-&gt;dispatchAfterEnsuringUpdatedScrollPosition([protectedWebPage, found, string, options, maxMatchCount, didWrap] () {
+        protectedWebPage-&gt;findController().updateFindUIAfterPageScroll(found, string, options, maxMatchCount, didWrap);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageFindControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/FindController.h (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/FindController.h        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Source/WebKit2/WebProcess/WebPage/FindController.h        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -41,6 +41,8 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> class Frame;
</span><span class="cx"> class Range;
</span><ins>+
+enum class DidWrap : bool;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -81,7 +83,7 @@
</span><span class="cx">     Vector&lt;WebCore::IntRect&gt; rectsForTextMatchesInRect(WebCore::IntRect clipRect);
</span><span class="cx">     bool updateFindIndicator(WebCore::Frame&amp; selectedFrame, bool isShowingOverlay, bool shouldAnimate = true);
</span><span class="cx"> 
</span><del>-    void updateFindUIAfterPageScroll(bool found, const String&amp;, FindOptions, unsigned maxMatchCount);
</del><ins>+    void updateFindUIAfterPageScroll(bool found, const String&amp;, FindOptions, unsigned maxMatchCount, WebCore::DidWrap);
</ins><span class="cx"> 
</span><span class="cx">     void willFindString();
</span><span class="cx">     void didFindString();
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Tools/ChangeLog        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-04-04  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        [Mac] -[WKWebView findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:] invokes the resultCollector with didWrap = NO even when it wraps
+        https://bugs.webkit.org/show_bug.cgi?id=165801
+        &lt;rdar://problem/29649535&gt;
+
+        Reviewed by Wenson Hsieh.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/FindInPage.mm:
+        (TEST):
+        Add some tests for wrapping finds.
+
</ins><span class="cx"> 2017-04-03  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add some new patterns to filter-build-webkit
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2CocoaFindInPagemm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FindInPage.mm (214892 => 214893)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FindInPage.mm        2017-04-04 19:43:29 UTC (rev 214892)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FindInPage.mm        2017-04-04 19:59:52 UTC (rev 214893)
</span><span class="lines">@@ -34,24 +34,51 @@
</span><span class="cx"> 
</span><span class="cx"> typedef enum : NSUInteger {
</span><span class="cx">     NSTextFinderAsynchronousDocumentFindOptionsBackwards = 1 &lt;&lt; 0,
</span><ins>+    NSTextFinderAsynchronousDocumentFindOptionsWrap = 1 &lt;&lt; 1,
</ins><span class="cx"> } NSTextFinderAsynchronousDocumentFindOptions;
</span><span class="cx"> 
</span><ins>+NSTextFinderAsynchronousDocumentFindOptions noFindOptions = (NSTextFinderAsynchronousDocumentFindOptions)0;
+NSTextFinderAsynchronousDocumentFindOptions backwardsFindOptions =NSTextFinderAsynchronousDocumentFindOptionsBackwards;
+NSTextFinderAsynchronousDocumentFindOptions wrapFindOptions =NSTextFinderAsynchronousDocumentFindOptionsWrap;
+NSTextFinderAsynchronousDocumentFindOptions wrapBackwardsFindOptions = (NSTextFinderAsynchronousDocumentFindOptions)(NSTextFinderAsynchronousDocumentFindOptionsWrap | NSTextFinderAsynchronousDocumentFindOptionsBackwards);
+
</ins><span class="cx"> @protocol NSTextFinderAsynchronousDocumentFindMatch &lt;NSObject&gt;
</span><span class="cx"> @property (retain, nonatomic, readonly) NSArray *textRects;
</span><span class="cx"> - (void)generateTextImage:(void (^)(NSImage *generatedImage))completionHandler;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+typedef id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt; FindMatch;
+
</ins><span class="cx"> @interface WKWebView (NSTextFinderSupport)
</span><span class="cx"> 
</span><del>-- (void)findMatchesForString:(NSString *)targetString relativeToMatch:(id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt;)relativeMatch findOptions:(NSTextFinderAsynchronousDocumentFindOptions)findOptions maxResults:(NSUInteger)maxResults resultCollector:(void (^)(NSArray *matches, BOOL didWrap))resultCollector;
</del><ins>+- (void)findMatchesForString:(NSString *)targetString relativeToMatch:(FindMatch)relativeMatch findOptions:(NSTextFinderAsynchronousDocumentFindOptions)findOptions maxResults:(NSUInteger)maxResults resultCollector:(void (^)(NSArray *matches, BOOL didWrap))resultCollector;
</ins><span class="cx"> 
</span><span class="cx"> @end
</span><span class="cx"> 
</span><del>-static bool findMatchesDone;
</del><ins>+typedef struct {
+    RetainPtr&lt;NSArray&gt; matches;
+    BOOL didWrap;
+} FindResult;
</ins><span class="cx"> 
</span><ins>+static FindResult findMatches(WKWebView *webView, NSString *findString, NSTextFinderAsynchronousDocumentFindOptions findOptions = noFindOptions, NSUInteger maxResults = NSUIntegerMax)
+{
+    __block FindResult result;
+    __block bool done = false;
+
+    [webView findMatchesForString:findString relativeToMatch:nil findOptions:findOptions maxResults:maxResults resultCollector:^(NSArray *matches, BOOL didWrap) {
+        result.matches = matches;
+        result.didWrap = didWrap;
+        done = true;
+    }];
+
+    TestWebKitAPI::Util::run(&amp;done);
+
+    return result;
+}
+
</ins><span class="cx"> TEST(WebKit2, FindInPage)
</span><span class="cx"> {
</span><del>-    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
</del><ins>+    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)]);
</ins><span class="cx">     [webView _setOverrideDeviceScaleFactor:2];
</span><span class="cx"> 
</span><span class="cx">     NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@&quot;lots-of-text&quot; withExtension:@&quot;html&quot; subdirectory:@&quot;TestWebKitAPI.resources&quot;]];
</span><span class="lines">@@ -58,80 +85,124 @@
</span><span class="cx">     [webView loadRequest:request];
</span><span class="cx">     [webView _test_waitForDidFinishNavigation];
</span><span class="cx"> 
</span><del>-    NSTextFinderAsynchronousDocumentFindOptions noFindOptions = (NSTextFinderAsynchronousDocumentFindOptions)0;
-
</del><span class="cx">     // Find all matches.
</span><del>-    [webView findMatchesForString:@&quot;Birthday&quot; relativeToMatch:nil findOptions:noFindOptions maxResults:NSUIntegerMax resultCollector:^(NSArray *matches, BOOL didWrap) {
-        EXPECT_EQ((NSUInteger)360, matches.count);
</del><ins>+    auto result = findMatches(webView.get(), @&quot;Birthday&quot;);
+    EXPECT_EQ((NSUInteger)360, [result.matches count]);
+    RetainPtr&lt;FindMatch&gt; match = [result.matches objectAtIndex:0];
+    EXPECT_EQ((NSUInteger)1, [match textRects].count);
</ins><span class="cx"> 
</span><del>-        id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt; firstMatch = [matches objectAtIndex:0];
-        EXPECT_EQ((NSUInteger)1, firstMatch.textRects.count);
-
-        findMatchesDone = true;
</del><ins>+    // Ensure that the generated image has the correct DPI.
+    __block bool generateTextImageDone = false;
+    [match generateTextImage:^(NSImage *image) {
+        CGImageRef CGImage = [image CGImageForProposedRect:nil context:nil hints:nil];
+        EXPECT_EQ(image.size.width, CGImageGetWidth(CGImage) / 2);
+        EXPECT_EQ(image.size.height, CGImageGetHeight(CGImage) / 2);
+        generateTextImageDone = true;
</ins><span class="cx">     }];
</span><ins>+    TestWebKitAPI::Util::run(&amp;generateTextImageDone);
</ins><span class="cx"> 
</span><del>-    TestWebKitAPI::Util::run(&amp;findMatchesDone);
-    findMatchesDone = false;
</del><ins>+    // Find one match, doing an incremental search.
+    result = findMatches(webView.get(), @&quot;Birthday&quot;, noFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    RetainPtr&lt;FindMatch&gt; firstMatch = [result.matches firstObject];
+    EXPECT_EQ((NSUInteger)1, [firstMatch textRects].count);
</ins><span class="cx"> 
</span><ins>+    // Find the next match in incremental mode.
+    result = findMatches(webView.get(), @&quot;Birthday&quot;, noFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    RetainPtr&lt;FindMatch&gt; secondMatch = [result.matches firstObject];
+    EXPECT_EQ((NSUInteger)1, [secondMatch textRects].count);
+    EXPECT_FALSE(NSEqualRects([[firstMatch textRects].lastObject rectValue], [[secondMatch textRects].lastObject rectValue]));
+
+    // Find the previous match in incremental mode.
+    result = findMatches(webView.get(), @&quot;Birthday&quot;, backwardsFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    RetainPtr&lt;FindMatch&gt; firstMatchAgain = [result.matches firstObject];
+    EXPECT_EQ((NSUInteger)1, [firstMatchAgain textRects].count);
+    EXPECT_TRUE(NSEqualRects([[firstMatch textRects].lastObject rectValue], [[firstMatchAgain textRects].lastObject rectValue]));
+
+    // Ensure that we cap the number of matches. There are actually 1600, but we only get the first 1000.
+    result = findMatches(webView.get(), @&quot; &quot;);
+    EXPECT_EQ((NSUInteger)1000, [result.matches count]);
+}
+
+TEST(WebKit2, FindInPageWrapping)
+{
+    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
+    [webView _setOverrideDeviceScaleFactor:2];
+
+    [webView loadHTMLString:@&quot;word word&quot; baseURL:nil];
+    [webView _test_waitForDidFinishNavigation];
+
</ins><span class="cx">     // Find one match, doing an incremental search.
</span><del>-    [webView findMatchesForString:@&quot;Birthday&quot; relativeToMatch:nil findOptions:noFindOptions maxResults:1 resultCollector:^(NSArray *matches, BOOL didWrap) {
-        EXPECT_EQ((NSUInteger)1, matches.count);
</del><ins>+    auto result = findMatches(webView.get(), @&quot;word&quot;, wrapFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
</ins><span class="cx"> 
</span><del>-        id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt; firstMatch = [matches objectAtIndex:0];
-        EXPECT_EQ((NSUInteger)1, firstMatch.textRects.count);
</del><ins>+    result = findMatches(webView.get(), @&quot;word&quot;, wrapFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
</ins><span class="cx"> 
</span><del>-        // Find the next match in incremental mode.
-        [webView findMatchesForString:@&quot;Birthday&quot; relativeToMatch:nil findOptions:noFindOptions maxResults:1 resultCollector:^(NSArray *matches, BOOL didWrap) {
-            EXPECT_EQ((NSUInteger)1, matches.count);
</del><ins>+    // The next match should wrap.
+    result = findMatches(webView.get(), @&quot;word&quot;, wrapFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_TRUE(result.didWrap);
</ins><span class="cx"> 
</span><del>-            id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt; secondMatch = [matches objectAtIndex:0];
-            EXPECT_EQ((NSUInteger)1, secondMatch.textRects.count);
</del><ins>+    // Going backward after wrapping should wrap again.
+    result = findMatches(webView.get(), @&quot;word&quot;, wrapBackwardsFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_TRUE(result.didWrap);
+}
</ins><span class="cx"> 
</span><del>-            EXPECT_FALSE(NSEqualRects([firstMatch.textRects.lastObject rectValue], [secondMatch.textRects.lastObject rectValue]));
</del><ins>+TEST(WebKit2, FindInPageWrappingDisabled)
+{
+    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
+    [webView _setOverrideDeviceScaleFactor:2];
</ins><span class="cx"> 
</span><del>-            // Find the previous match in incremental mode.
-            [webView findMatchesForString:@&quot;Birthday&quot; relativeToMatch:nil findOptions:NSTextFinderAsynchronousDocumentFindOptionsBackwards maxResults:1 resultCollector:^(NSArray *matches, BOOL didWrap) {
-                EXPECT_EQ((NSUInteger)1, matches.count);
</del><ins>+    [webView loadHTMLString:@&quot;word word&quot; baseURL:nil];
+    [webView _test_waitForDidFinishNavigation];
</ins><span class="cx"> 
</span><del>-                id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt; firstMatchAgain = [matches objectAtIndex:0];
-                EXPECT_EQ((NSUInteger)1, firstMatchAgain.textRects.count);
</del><ins>+    // Find one match, doing an incremental search.
+    auto result = findMatches(webView.get(), @&quot;word&quot;, noFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
</ins><span class="cx"> 
</span><del>-                EXPECT_TRUE(NSEqualRects([firstMatch.textRects.lastObject rectValue], [firstMatchAgain.textRects.lastObject rectValue]));
-                
-                findMatchesDone = true;
-            }];
-        }];
</del><ins>+    result = findMatches(webView.get(), @&quot;word&quot;, noFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
</ins><span class="cx"> 
</span><del>-    }];
</del><ins>+    // The next match should fail, because wrapping is disabled.
+    result = findMatches(webView.get(), @&quot;word&quot;, noFindOptions, 1);
+    EXPECT_EQ((NSUInteger)0, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
+}
</ins><span class="cx"> 
</span><del>-    TestWebKitAPI::Util::run(&amp;findMatchesDone);
-    findMatchesDone = false;
</del><ins>+TEST(WebKit2, FindInPageWrappingSubframe)
+{
+    RetainPtr&lt;WKWebView&gt; webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]);
+    [webView _setOverrideDeviceScaleFactor:2];
</ins><span class="cx"> 
</span><del>-    // Ensure that the generated image has the correct DPI.
-    [webView findMatchesForString:@&quot;Birthday&quot; relativeToMatch:nil findOptions:noFindOptions maxResults:NSUIntegerMax resultCollector:^(NSArray *matches, BOOL didWrap) {
-        EXPECT_EQ((NSUInteger)360, matches.count);
</del><ins>+    [webView loadHTMLString:@&quot;word &lt;iframe srcdoc='word'&gt;&quot; baseURL:nil];
+    [webView _test_waitForDidFinishNavigation];
</ins><span class="cx"> 
</span><del>-        id &lt;NSTextFinderAsynchronousDocumentFindMatch&gt; firstMatch = [matches objectAtIndex:0];
-        [firstMatch generateTextImage:^(NSImage *image) {
-            CGImageRef CGImage = [image CGImageForProposedRect:nil context:nil hints:nil];
-            EXPECT_EQ(image.size.width, CGImageGetWidth(CGImage) / 2);
-            EXPECT_EQ(image.size.height, CGImageGetHeight(CGImage) / 2);
</del><ins>+    // Find one match, doing an incremental search.
+    auto result = findMatches(webView.get(), @&quot;word&quot;, wrapFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
</ins><span class="cx"> 
</span><del>-            findMatchesDone = true;
-        }];
-    }];
</del><ins>+    result = findMatches(webView.get(), @&quot;word&quot;, wrapFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_FALSE(result.didWrap);
</ins><span class="cx"> 
</span><del>-    TestWebKitAPI::Util::run(&amp;findMatchesDone);
-    findMatchesDone = false;
</del><ins>+    // The next match should wrap.
+    result = findMatches(webView.get(), @&quot;word&quot;, wrapFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_TRUE(result.didWrap);
</ins><span class="cx"> 
</span><del>-    // Ensure that we cap the number of matches. There are actually 1600, but we only get the first 1000.
-    [webView findMatchesForString:@&quot; &quot; relativeToMatch:nil findOptions:noFindOptions maxResults:NSUIntegerMax resultCollector:^(NSArray *matches, BOOL didWrap) {
-        EXPECT_EQ((NSUInteger)1000, matches.count);
-
-        findMatchesDone = true;
-    }];
-    TestWebKitAPI::Util::run(&amp;findMatchesDone);
-    findMatchesDone = false;
</del><ins>+    // Going backward after wrapping should wrap again.
+    result = findMatches(webView.get(), @&quot;word&quot;, wrapBackwardsFindOptions, 1);
+    EXPECT_EQ((NSUInteger)1, [result.matches count]);
+    EXPECT_TRUE(result.didWrap);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre>
</div>
</div>

</body>
</html>