<!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>[195494] trunk/Source</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/195494">195494</a></dd>
<dt>Author</dt> <dd>enrica@apple.com</dd>
<dt>Date</dt> <dd>2016-01-22 16:24:02 -0800 (Fri, 22 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add support for DataDetectors in WK (iOS).
https://bugs.webkit.org/show_bug.cgi?id=152989
rdar://problem/22855960

Reviewed by Tim Horton.

Source/WebCore:

This patch adds the logic to perform data detection and modify
the DOM by adding data detector links as appropriate.
The data detector results returned by detectContentInRange are
stored in the Frame object.

* editing/cocoa/DataDetection.h:
* editing/cocoa/DataDetection.mm:
(WebCore::resultIsURL):
(WebCore::constructURLStringForResult):
(WebCore::removeResultLinksFromAnchor):
(WebCore::searchForLinkRemovingExistingDDLinks):
(WebCore::dataDetectorTypeForCategory):
(WebCore::buildQuery):
(WebCore::DataDetection::detectContentInRange):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::checkLoadCompleteForThisFrame):
* page/Frame.h:
(WebCore::Frame::setDataDetectionResults):
(WebCore::Frame::dataDetectionResults):
* platform/spi/cocoa/DataDetectorsCoreSPI.h:
(DDQueryOffsetCompare):

Source/WebKit2:

* UIProcess/API/Cocoa/WKWebView.mm:
(fromWKDataDetectorTypes): Changed parameter to uint64_t to
successfully compare against WKDataDetectorTypeAll.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreeditingcocoaDataDetectionh">trunk/Source/WebCore/editing/cocoa/DataDetection.h</a></li>
<li><a href="#trunkSourceWebCoreeditingcocoaDataDetectionmm">trunk/Source/WebCore/editing/cocoa/DataDetection.mm</a></li>
<li><a href="#trunkSourceWebCoreloaderFrameLoadercpp">trunk/Source/WebCore/loader/FrameLoader.cpp</a></li>
<li><a href="#trunkSourceWebCorepageFrameh">trunk/Source/WebCore/page/Frame.h</a></li>
<li><a href="#trunkSourceWebCoreplatformspicocoaDataDetectorsCoreSPIh">trunk/Source/WebCore/platform/spi/cocoa/DataDetectorsCoreSPI.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm">trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebCore/ChangeLog        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -1,3 +1,33 @@
</span><ins>+2016-01-22  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        Add support for DataDetectors in WK (iOS).
+        https://bugs.webkit.org/show_bug.cgi?id=152989
+        rdar://problem/22855960
+
+        Reviewed by Tim Horton.
+
+        This patch adds the logic to perform data detection and modify
+        the DOM by adding data detector links as appropriate.
+        The data detector results returned by detectContentInRange are
+        stored in the Frame object.
+
+        * editing/cocoa/DataDetection.h:
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::resultIsURL):
+        (WebCore::constructURLStringForResult):
+        (WebCore::removeResultLinksFromAnchor):
+        (WebCore::searchForLinkRemovingExistingDDLinks):
+        (WebCore::dataDetectorTypeForCategory):
+        (WebCore::buildQuery):
+        (WebCore::DataDetection::detectContentInRange):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::checkLoadCompleteForThisFrame):
+        * page/Frame.h:
+        (WebCore::Frame::setDataDetectionResults):
+        (WebCore::Frame::dataDetectionResults):
+        * platform/spi/cocoa/DataDetectorsCoreSPI.h:
+        (DDQueryOffsetCompare):
+
</ins><span class="cx"> 2016-01-22  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         LayoutTest http/tests/security/xssAuditor/embed-tag-in-path-unterminated.html crashing
</span><span class="lines">@@ -1724,7 +1754,6 @@
</span><span class="cx">         (WebCore::matchesFutureCuePseudoClass):
</span><span class="cx">         (WebCore::matchesPastCuePseudoClass):
</span><span class="cx"> 
</span><del>-&gt;&gt;&gt;&gt;&gt;&gt;&gt; .r195316
</del><span class="cx"> 2016-01-19  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r195179.
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingcocoaDataDetectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/cocoa/DataDetection.h (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/DataDetection.h        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebCore/editing/cocoa/DataDetection.h        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #import &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> 
</span><span class="cx"> OBJC_CLASS DDActionContext;
</span><ins>+OBJC_CLASS NSArray;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -53,7 +54,7 @@
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     WEBCORE_EXPORT static RetainPtr&lt;DDActionContext&gt; detectItemAroundHitTestResult(const HitTestResult&amp;, FloatRect&amp; detectedDataBoundingBox, RefPtr&lt;Range&gt;&amp; detectedDataRange);
</span><span class="cx"> #endif
</span><del>-    WEBCORE_EXPORT static void detectContentInRange(RefPtr&lt;Range&gt;&amp; contextRange, DataDetectorTypes);
</del><ins>+    WEBCORE_EXPORT static NSArray *detectContentInRange(RefPtr&lt;Range&gt;&amp; contextRange, DataDetectorTypes);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingcocoaDataDetectionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/cocoa/DataDetection.mm (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/DataDetection.mm        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebCore/editing/cocoa/DataDetection.mm        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -44,6 +44,12 @@
</span><span class="cx"> #import &quot;VisibleUnits.h&quot;
</span><span class="cx"> #import &quot;htmlediting.h&quot;
</span><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+const char *dataDetectorsURLScheme = &quot;x-apple-data-detectors&quot;;
+const char *dataDetectorsAttributeTypeKey = &quot;x-apple-data-detectors-type&quot;;
+const char *dataDetectorsAttributeResultKey = &quot;x-apple-data-detectors-result&quot;;
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="lines">@@ -138,9 +144,412 @@
</span><span class="cx">     return detectItemAtPositionWithRange(position, contextRange, detectedDataBoundingBox, detectedDataRange);
</span><span class="cx"> }
</span><span class="cx"> #endif // PLATFORM(MAC)
</span><ins>+    
+#if PLATFORM(IOS)
+    
+static BOOL resultIsURL(DDResultRef result)
+{
+    if (!result)
+        return NO;
+    
+    static NSSet *urlTypes = [[NSSet setWithObjects: (NSString *)getDDBinderHttpURLKey(), (NSString *)getDDBinderWebURLKey(), (NSString *)getDDBinderMailURLKey(), (NSString *)getDDBinderGenericURLKey(), (NSString *)getDDBinderEmailKey(), nil] retain];
+    return [urlTypes containsObject:(NSString *)DDResultGetType(result)];
+}
</ins><span class="cx"> 
</span><del>-void DataDetection::detectContentInRange(RefPtr&lt;Range&gt;&amp;, DataDetectorTypes)
</del><ins>+static NSString *constructURLStringForResult(DDResultRef currentResult, NSString *resultIdentifier, NSDate *referenceDate, NSTimeZone *referenceTimeZone, DataDetectorTypes detectionTypes)
</ins><span class="cx"> {
</span><ins>+    if (!DDResultHasProperties(currentResult, DDResultPropertyPassiveDisplay))
+        return nil;
+    
+    DDURLifierPhoneNumberDetectionTypes phoneTypes = (detectionTypes &amp; DataDetectorTypePhoneNumber) ? DDURLifierPhoneNumberDetectionRegular : DDURLifierPhoneNumberDetectionNone;
+    DDResultCategory category = DDResultGetCategory(currentResult);
+    CFStringRef type = DDResultGetType(currentResult);
+    
+    if (((detectionTypes &amp; DataDetectorTypeAddress) &amp;&amp; (DDResultCategoryAddress == category))
+        || ((detectionTypes &amp; DataDetectorTypeTrackingNumber) &amp;&amp; (CFStringCompare(getDDBinderTrackingNumberKey(), type, 0) == kCFCompareEqualTo))
+        || ((detectionTypes &amp; DataDetectorTypeFlight) &amp;&amp; (CFStringCompare(getDDBinderFlightInformationKey(), type, 0) == kCFCompareEqualTo))
+        || ((detectionTypes &amp; DataDetectorTypePhoneNumber) &amp;&amp; (DDResultCategoryPhoneNumber == category))
+        || ((detectionTypes &amp; DataDetectorTypeLink) &amp;&amp; resultIsURL(currentResult))) {
+        
+        return DDURLStringForResult(currentResult, resultIdentifier, phoneTypes, referenceDate, referenceTimeZone);
+    }
+    if ((detectionTypes &amp; DataDetectorTypeCalendarEvent) &amp;&amp; (DDResultCategoryCalendarEvent == category)) {
+        if (!DDResultIsPastDate(currentResult, (CFDateRef)referenceDate, (CFTimeZoneRef)referenceTimeZone))
+            return DDURLStringForResult(currentResult, resultIdentifier, phoneTypes, referenceDate, referenceTimeZone);
+    }
+    return nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void removeResultLinksFromAnchor(Node* node, Node* nodeParent)
+{
+    // Perform a depth-first search for anchor nodes, which have the DDURLScheme attribute set to true,
+    // take their children and insert them before the anchor,
+    // and then remove the anchor.
+    
+    if (!node)
+        return;
+    
+    BOOL nodeIsDDAnchor = is&lt;HTMLAnchorElement&gt;(*node) &amp;&amp; downcast&lt;Element&gt;(*node).getAttribute(getDDURLScheme()) == &quot;true&quot;;
+    
+    RefPtr&lt;NodeList&gt; children = node-&gt;childNodes();
+    unsigned childCount = children-&gt;length();
+    for (size_t i = 0; i &lt; childCount; i++) {
+        Node *child = children-&gt;item(i);
+        if (is&lt;Element&gt;(*child))
+            removeResultLinksFromAnchor(child, node);
+    }
+    
+    if (nodeIsDDAnchor &amp;&amp; nodeParent) {
+        children = node-&gt;childNodes();
+        childCount = children-&gt;length();
+        
+        // Iterate over the children and move them all onto the same level as this anchor.
+        // Remove the anchor afterwards.
+        for (size_t i = 0; i &lt; childCount; i++) {
+            Node *child = children-&gt;item(0);
+            nodeParent-&gt;insertBefore(child, node, ASSERT_NO_EXCEPTION);
+        }
+        nodeParent-&gt;removeChild(node, ASSERT_NO_EXCEPTION);
+    }
+}
+
+static bool searchForLinkRemovingExistingDDLinks(Node* startNode, Node* endNode)
+{
+    Node *node = startNode;
+    while (node) {
+        if (is&lt;HTMLAnchorElement&gt;(*node)) {
+            if (downcast&lt;Element&gt;(*node).getAttribute(getDDURLScheme()) != &quot;true&quot;)
+                return true;
+            removeResultLinksFromAnchor(node, node-&gt;parentElement());
+        }
+        
+        if (node == endNode) {
+            // If we found the end node and no link, return false unless an ancestor node is a link.
+            // The only ancestors not tested at this point are in the direct line from self's parent to the top.
+            node = startNode-&gt;parentNode();
+            while (node) {
+                if (is&lt;HTMLAnchorElement&gt;(*node)) {
+                    if (downcast&lt;Element&gt;(*node).getAttribute(getDDURLScheme()) != &quot;true&quot;)
+                        return true;
+                    removeResultLinksFromAnchor(node, node-&gt;parentElement());
+                }
+                node = node-&gt;parentNode();
+            }
+            return false;
+        }
+        
+        RefPtr&lt;NodeList&gt; childNodes = node-&gt;childNodes();
+        if (childNodes-&gt;length())
+            node = childNodes-&gt;item(0);
+        else {
+            Node *newNode = node-&gt;nextSibling();
+            Node *parentNode = node;
+            while (!newNode) {
+                parentNode = parentNode-&gt;parentNode();
+                if (!parentNode)
+                    return false;
+                newNode = parentNode-&gt;nextSibling();
+            }
+            node = newNode;
+        }
+    }
+    return false;
+}
+
+static NSString *dataDetectorTypeForCategory(DDResultCategory category)
+{
+    switch (category) {
+    case DDResultCategoryPhoneNumber:
+        return @&quot;telephone&quot;;
+    case DDResultCategoryLink:
+        return @&quot;link&quot;;
+    case DDResultCategoryAddress:
+        return @&quot;address&quot;;
+    case DDResultCategoryCalendarEvent:
+        return @&quot;calendar-event&quot;;
+    case DDResultCategoryMisc:
+        return @&quot;misc&quot;;
+    default:
+        return @&quot;&quot;;
+    }
+}
+
+static String dataDetectorStringForPath(NSIndexPath* path)
+{
+    NSUInteger length = path.length;
+    
+    switch (length) {
+    case 0:
+        return String();
+        
+    case 1:
+        return String::format(&quot;%lu&quot;, (unsigned long)[path indexAtPosition:0]);
+        
+    case 2:
+        return String::format(&quot;%lu/%lu&quot;, (unsigned long)[path indexAtPosition:0], (unsigned long)[path indexAtPosition:1]);
+        
+    default:
+        {
+            String componentsString = String::format(&quot;%lu&quot;, (unsigned long)[path indexAtPosition:0]);
+            for (NSUInteger i = 1 ; i &lt; length ; i++) {
+                componentsString.append(&quot;/&quot;);
+                componentsString.append(String::format(&quot;%lu&quot;, (unsigned long)[path indexAtPosition:i]));
+            }
+
+            return componentsString;
+        }
+    }
+}
+
+static void buildQuery(DDScanQueryRef scanQuery, Range* contextRange)
+{
+    // Once we're over this number of fragments, stop at the first hard break.
+    const CFIndex maxFragmentWithHardBreak = 1000;
+    // Once we're over this number of fragments, we stop at the line.
+    const CFIndex maxFragmentWithLinebreak = 5000;
+    // Once we're over this number of fragments, we stop at the space.
+    const CFIndex maxFragmentSpace = 10000;
+
+    CFCharacterSetRef whiteSpacesSet = CFCharacterSetGetPredefined(kCFCharacterSetWhitespaceAndNewline);
+    CFCharacterSetRef newLinesSet = CFCharacterSetGetPredefined(kCFCharacterSetNewline);
+    
+    RefPtr&lt;Range&gt; endRange;
+    CFIndex iteratorCount = 0;
+    CFIndex fragmentCount = 0;
+    
+    // Build the scan query adding separators.
+    // For each fragment the iterator increment is stored as metadata.
+    for (TextIterator iterator(contextRange); !iterator.atEnd(); iterator.advance(), iteratorCount++) {
+        size_t currentTextLength = iterator.text().length();
+        if (!currentTextLength) {
+            DDScanQueryAddSeparator(scanQuery, DDTextCoalescingTypeHardBreak);
+            if (iteratorCount &gt; maxFragmentWithHardBreak)
+                break;
+            continue;
+        }
+        // Test for white space nodes, we're coalescing them.
+        const UniChar *currentCharPtr = iterator.text().upconvertedCharacters();
+        
+        bool containsOnlyWhiteSpace = true;
+        bool hasTab = false;
+        bool hasNewline = false;
+        int nbspCount = 0;
+        for (NSUInteger i = 0; i &lt; currentTextLength; i++) {
+            if (!CFCharacterSetIsCharacterMember(whiteSpacesSet, *currentCharPtr)) {
+                containsOnlyWhiteSpace = false;
+                break;
+            }
+            
+            if (CFCharacterSetIsCharacterMember(newLinesSet, *currentCharPtr))
+                hasNewline = true;
+            else if (*currentCharPtr == '\t')
+                hasTab = true;
+            
+            // Multiple consecutive non breakable spaces are most likely simulated tabs.
+            if (*currentCharPtr == 0xa0) {
+                if (++nbspCount &gt; 2)
+                    hasTab = true;
+            } else
+                nbspCount = 0;
+
+            currentCharPtr++;
+        }
+        if (containsOnlyWhiteSpace) {
+            if (hasNewline) {
+                DDScanQueryAddLineBreak(scanQuery);
+                if (iteratorCount &gt; maxFragmentWithLinebreak)
+                    break;
+            } else {
+                DDScanQueryAddSeparator(scanQuery, hasTab ? DDTextCoalescingTypeTab : DDTextCoalescingTypeSpace);
+                if (iteratorCount &gt; maxFragmentSpace)
+                    break;
+            }
+            continue;
+        }
+        
+        RetainPtr&lt;CFStringRef&gt; currentText = adoptCF(CFStringCreateWithCharacters(kCFAllocatorDefault, iterator.text().upconvertedCharacters(), iterator.text().length()));
+        DDScanQueryAddTextFragment(scanQuery, currentText.get(), CFRangeMake(0, currentTextLength), (void *)iteratorCount, (DDTextFragmentMode)0, DDTextCoalescingTypeNone);
+        fragmentCount++;
+    }
+}
+
+static inline CFComparisonResult queryOffsetCompare(DDQueryOffset o1, DDQueryOffset o2)
+{
+    if (o1.queryIndex &lt; o2.queryIndex)
+        return kCFCompareLessThan;
+    if (o1.queryIndex &gt; o2.queryIndex)
+        return kCFCompareGreaterThan;
+    if (o1.offset &lt; o2.offset)
+        return kCFCompareLessThan;
+    if (o1.offset &gt; o2.offset)
+        return kCFCompareGreaterThan;
+    return kCFCompareEqualTo;
+}
+
+NSArray *DataDetection::detectContentInRange(RefPtr&lt;Range&gt;&amp; contextRange, DataDetectorTypes types)
+{
+    RetainPtr&lt;DDScannerRef&gt; scanner = adoptCF(DDScannerCreate(DDScannerTypeStandard, 0, nullptr));
+    RetainPtr&lt;DDScanQueryRef&gt; scanQuery = adoptCF(DDScanQueryCreate(NULL));
+    buildQuery(scanQuery.get(), contextRange.get());
+    
+    // FIXME: we should add a timeout to this call to make sure it doesn't take too much time.
+    if (!DDScannerScanQuery(scanner.get(), scanQuery.get()))
+        return nil;
+    
+    RetainPtr&lt;CFArrayRef&gt; scannerResults = adoptCF(DDScannerCopyResultsWithOptions(scanner.get(), getDDScannerCopyResultsOptionsForPassiveUse() | DDScannerCopyResultsOptionsCoalesceSignatures));
+    if (!scannerResults)
+        return nil;
+    
+    CFIndex resultCount = CFArrayGetCount(scannerResults.get());
+    if (!resultCount)
+        return nil;
+    
+    Vector&lt;RetainPtr&lt;DDResultRef&gt;&gt; allResults;
+    Vector&lt;RetainPtr&lt;NSIndexPath&gt;&gt; indexPaths;
+    NSInteger currentTopLevelIndex = 0;
+
+    // Iterate through the scanner results to find signatures and extract all the subresults while
+    // populating the array of index paths to use in the href of the anchors being created.
+    for (id resultObject in (NSArray *)scannerResults.get()) {
+        DDResultRef result = (DDResultRef)resultObject;
+        NSIndexPath *indexPath = [NSIndexPath indexPathWithIndex:currentTopLevelIndex];
+        if (CFStringCompare(DDResultGetType(result), getDDBinderSignatureBlockKey(), 0) == kCFCompareEqualTo) {
+            NSArray *subresults = (NSArray *)DDResultGetSubResults(result);
+            
+            for (NSUInteger subResultIndex = 0 ; subResultIndex &lt; [subresults count] ; subResultIndex++) {
+                indexPaths.append([indexPath indexPathByAddingIndex:subResultIndex]);
+                allResults.append((DDResultRef)[subresults objectAtIndex:subResultIndex]);
+            }
+        } else {
+            allResults.append(result);
+            indexPaths.append(indexPath);
+        }
+        currentTopLevelIndex++;
+    }
+
+    Vector&lt;Vector&lt;RefPtr&lt;Range&gt;&gt;&gt; allResultRanges;
+    TextIterator iterator(contextRange.get());
+    CFIndex iteratorCount = 0;
+
+    // Iterate through the array of the expanded results to create a vector of Range objects that indicate
+    // where the DOM needs to be modified.
+    // Each result can be contained all in one text node or can span multiple text nodes.
+    for (auto&amp; result : allResults) {
+        DDQueryRange queryRange = DDResultGetQueryRangeForURLification(result.get());
+        CFIndex iteratorTargetAdvanceCount = (CFIndex)DDScanQueryGetFragmentMetaData(scanQuery.get(), queryRange.start.queryIndex);
+        while (iteratorCount &lt; iteratorTargetAdvanceCount) {
+            iterator.advance();
+            iteratorCount++;
+        }
+
+        Vector&lt;RefPtr&lt;Range&gt;&gt; fragmentRanges;
+        RefPtr&lt;Range&gt; currentRange = iterator.range();
+        CFIndex fragmentIndex = queryRange.start.queryIndex;
+        if (fragmentIndex == queryRange.end.queryIndex)
+            fragmentRanges.append(TextIterator::subrange(currentRange.get(), queryRange.start.offset, queryRange.end.offset - queryRange.start.offset));
+        else
+            fragmentRanges.append(currentRange);
+        
+        while (fragmentIndex &lt; queryRange.end.queryIndex) {
+            fragmentIndex++;
+            iteratorTargetAdvanceCount = (CFIndex)DDScanQueryGetFragmentMetaData(scanQuery.get(), fragmentIndex);
+            while (iteratorCount &lt; iteratorTargetAdvanceCount) {
+                iterator.advance();
+                iteratorCount++;
+            }
+            currentRange = iterator.range();
+            fragmentRanges.append(currentRange);
+        }
+        allResultRanges.append(fragmentRanges);
+    }
+    
+    CFTimeZoneRef tz = CFTimeZoneCopyDefault();
+    NSDate *referenceDate = [NSDate date];
+    Text* lastTextNodeToUpdate = nullptr;
+    String lastNodeContent;
+    size_t contentOffset = 0;
+    DDQueryOffset lastModifiedQueryOffset = {-1, 0};
+    
+    // For each result add the link.
+    // Since there could be multiple results in the same text node, the node is only modified when
+    // we are about to process a different text node.
+    resultCount = allResults.size();
+    
+    for (CFIndex resultIndex = 0; resultIndex &lt; resultCount; resultIndex++) {
+        DDResultRef coreResult = allResults[resultIndex].get();
+        DDQueryRange queryRange = DDResultGetQueryRangeForURLification(coreResult);
+        Vector&lt;RefPtr&lt;Range&gt;&gt; resultRanges = allResultRanges[resultIndex];
+
+        // Compare the query offsets to make sure we don't go backwards
+        if (queryOffsetCompare(lastModifiedQueryOffset, queryRange.start) &gt;= 0)
+            continue;
+
+        if (!resultRanges.size())
+            continue;
+
+        NSString *identifier = dataDetectorStringForPath(indexPaths[resultIndex].get());
+        NSString *correspondingURL = constructURLStringForResult(coreResult, identifier, referenceDate, (NSTimeZone *)tz, types);
+        
+        if (!correspondingURL || searchForLinkRemovingExistingDDLinks(&amp;resultRanges.first()-&gt;startContainer(), &amp;resultRanges.last()-&gt;endContainer()))
+            continue;
+        
+        lastModifiedQueryOffset = queryRange.end;
+
+        for (auto&amp; range : resultRanges) {
+            Node* parentNode = range-&gt;startContainer().parentNode();
+            Text&amp; currentTextNode = downcast&lt;Text&gt;(range-&gt;startContainer());
+            Document&amp; document = currentTextNode.document();
+            String textNodeData;
+            
+            if (lastTextNodeToUpdate != &amp;currentTextNode) {
+                if (lastTextNodeToUpdate)
+                    lastTextNodeToUpdate-&gt;setData(lastNodeContent);
+                contentOffset = 0;
+                if (range-&gt;startOffset() &gt; 0)
+                    textNodeData = currentTextNode.substringData(0, range-&gt;startOffset(), ASSERT_NO_EXCEPTION);
+            } else
+                textNodeData = currentTextNode.substringData(contentOffset, range-&gt;startOffset() - contentOffset, ASSERT_NO_EXCEPTION);
+            
+            if (!textNodeData.isEmpty()) {
+                RefPtr&lt;Node&gt; newNode = Text::create(document, textNodeData);
+                parentNode-&gt;insertBefore(newNode, &amp;currentTextNode, ASSERT_NO_EXCEPTION);
+                contentOffset = range-&gt;startOffset();
+            }
+            
+            // Create the actual anchor node and insert it before the current node.
+            textNodeData = currentTextNode.substringData(range-&gt;startOffset(), range-&gt;endOffset() - range-&gt;startOffset(), ASSERT_NO_EXCEPTION);
+            RefPtr&lt;Node&gt; newNode = Text::create(document, textNodeData);
+            parentNode-&gt;insertBefore(newNode, &amp;currentTextNode, ASSERT_NO_EXCEPTION);
+            
+            RefPtr&lt;HTMLAnchorElement&gt; anchorElement = HTMLAnchorElement::create(document);
+            anchorElement-&gt;setHref(correspondingURL);
+            anchorElement-&gt;setDir(&quot;ltr&quot;);
+            RefPtr&lt;Attr&gt; color = downcast&lt;Element&gt;(parentNode)-&gt;getAttributeNode(&quot;color&quot;);
+            if (color)
+                anchorElement-&gt;setAttribute(HTMLNames::styleAttr, color-&gt;style()-&gt;cssText());
+            
+            anchorElement-&gt;Node::appendChild(newNode, ASSERT_NO_EXCEPTION);
+            parentNode-&gt;insertBefore(anchorElement, &amp;currentTextNode, ASSERT_NO_EXCEPTION);
+            // Add a special attribute to mark this URLification as the result of data detectors.
+            anchorElement-&gt;setAttribute(QualifiedName(nullAtom, dataDetectorsURLScheme, nullAtom), &quot;true&quot;);
+            anchorElement-&gt;setAttribute(QualifiedName(nullAtom, dataDetectorsAttributeTypeKey, nullAtom), dataDetectorTypeForCategory(DDResultGetCategory(coreResult)));
+            anchorElement-&gt;setAttribute(QualifiedName(nullAtom, dataDetectorsAttributeResultKey, nullAtom), identifier);
+            contentOffset = range-&gt;endOffset();
+            
+            lastNodeContent = currentTextNode.substringData(range-&gt;endOffset(), currentTextNode.length() - range-&gt;endOffset(), ASSERT_NO_EXCEPTION);
+            lastTextNodeToUpdate = &amp;currentTextNode;
+        }        
+    }
+    if (lastTextNodeToUpdate)
+        lastTextNodeToUpdate-&gt;setData(lastNodeContent);
+    
+    return [getDDScannerResultClass() resultsFromCoreResults:scannerResults.get()];
+}
+
+#else
+NSArray *DataDetection::detectContentInRange(RefPtr&lt;Range&gt;&amp;, DataDetectorTypes)
+{
+    return nil;
+}
+#endif
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderFrameLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/FrameLoader.cpp        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -2279,14 +2279,14 @@
</span><span class="cx">                 m_client.dispatchDidFailLoad(error);
</span><span class="cx">                 loadingEvent = AXObjectCache::AXLoadingFailed;
</span><span class="cx">             } else {
</span><del>-                m_client.dispatchDidFinishLoad();
-                loadingEvent = AXObjectCache::AXLoadingFinished;
</del><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><span class="cx">                 if (m_frame.settings().dataDetectorTypes() != DataDetectorTypeNone) {
</span><span class="cx">                     RefPtr&lt;Range&gt; documentRange = makeRange(firstPositionInNode(m_frame.document()-&gt;documentElement()), lastPositionInNode(m_frame.document()-&gt;documentElement()));
</span><del>-                    DataDetection::detectContentInRange(documentRange, m_frame.settings().dataDetectorTypes());
</del><ins>+                    m_frame.setDataDetectionResults(DataDetection::detectContentInRange(documentRange, m_frame.settings().dataDetectorTypes()));
</ins><span class="cx">                 }
</span><span class="cx"> #endif
</span><ins>+                m_client.dispatchDidFinishLoad();
+                loadingEvent = AXObjectCache::AXLoadingFinished;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // Notify accessibility.
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Frame.h (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Frame.h        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebCore/page/Frame.h        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -47,10 +47,13 @@
</span><span class="cx"> #include &quot;FrameWin.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if PLATFORM(COCOA)
+OBJC_CLASS NSArray;
+#endif
+
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> OBJC_CLASS DOMCSSStyleDeclaration;
</span><span class="cx"> OBJC_CLASS DOMNode;
</span><del>-OBJC_CLASS NSArray;
</del><span class="cx"> OBJC_CLASS NSString;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -185,6 +188,11 @@
</span><span class="cx">         WEBCORE_EXPORT float frameScaleFactor() const;
</span><span class="cx"> 
</span><span class="cx">         void deviceOrPageScaleFactorChanged();
</span><ins>+        
+#if ENABLE(DATA_DETECTION)
+        void setDataDetectionResults(NSArray *results) { m_dataDetectionResults = results; }
+        NSArray *dataDetectionResults() const { return m_dataDetectionResults.get(); }
+#endif
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">         const ViewportArguments&amp; viewportArguments() const;
</span><span class="lines">@@ -292,6 +300,9 @@
</span><span class="cx">         const std::unique_ptr&lt;EventHandler&gt; m_eventHandler;
</span><span class="cx">         const std::unique_ptr&lt;AnimationController&gt; m_animationController;
</span><span class="cx"> 
</span><ins>+#if ENABLE(DATA_DETECTION)
+        RetainPtr&lt;NSArray&gt; m_dataDetectionResults;
+#endif
</ins><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">         void betterApproximateNode(const IntPoint&amp; testPoint, NodeQualifier, Node*&amp; best, Node* failedNode, IntPoint&amp; bestPoint, IntRect&amp; bestRect, const IntRect&amp; testRect);
</span><span class="cx">         bool hitTestResultAtViewportLocation(const FloatPoint&amp; viewportLocation, HitTestResult&amp;, IntPoint&amp; center);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformspicocoaDataDetectorsCoreSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/spi/cocoa/DataDetectorsCoreSPI.h (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/spi/cocoa/DataDetectorsCoreSPI.h        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebCore/platform/spi/cocoa/DataDetectorsCoreSPI.h        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -23,10 +23,16 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#import &quot;SoftLinking.h&quot;
+
</ins><span class="cx"> #if USE(APPLE_INTERNAL_SDK)
</span><span class="cx"> 
</span><ins>+#import &lt;DataDetectorsCore/DDBinderKeys_Private.h&gt;
+#import &lt;DataDetectorsCore/DDScannerResult.h&gt;
</ins><span class="cx"> #import &lt;DataDetectorsCore/DataDetectorsCore.h&gt;
</span><del>-
</del><ins>+#if PLATFORM(IOS)
+#import &lt;DataDetectorsCore/DDURLifier.h&gt;
+#endif
</ins><span class="cx"> #else // !USE(APPLE_INTERNAL_SDK)
</span><span class="cx"> 
</span><span class="cx"> typedef enum {
</span><span class="lines">@@ -38,8 +44,65 @@
</span><span class="cx"> enum {
</span><span class="cx">     DDScannerCopyResultsOptionsNone = 0,
</span><span class="cx">     DDScannerCopyResultsOptionsNoOverlap = 1 &lt;&lt; 0,
</span><ins>+    DDScannerCopyResultsOptionsCoalesceSignatures = 1 &lt;&lt; 1,
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum {
+    DDURLifierPhoneNumberDetectionNone = 0,
+    DDURLifierPhoneNumberDetectionRegular = 1 &lt;&lt; 1,
+    DDURLifierPhoneNumberDetectionQuotedShorts = 1 &lt;&lt; 2,
+    DDURLifierPhoneNumberDetectionUnquotedShorts = 1 &lt;&lt; 3
+};
+typedef NSUInteger DDURLifierPhoneNumberDetectionTypes;
+
+typedef enum __DDTextCoalescingType {
+    DDTextCoalescingTypeNone = 0,
+    DDTextCoalescingTypeSpace = 1,
+    DDTextCoalescingTypeTab = 2,
+    DDTextCoalescingTypeLineBreak = 3,
+    DDTextCoalescingTypeHardBreak = 4,
+} DDTextCoalescingType;
+
+typedef enum {
+    DDResultCategoryUnknown = 0,
+    DDResultCategoryLink = 1,
+    DDResultCategoryPhoneNumber = 2,
+    DDResultCategoryAddress = 3,
+    DDResultCategoryCalendarEvent = 4,
+    DDResultCategoryMisc = 5,
+} DDResultCategory;
+
+typedef enum __DDTextFragmentType {
+    DDTextFragmentTypeTrimWhiteSpace =  0x1,
+    DDTextFragmentTypeIgnoreCRLF =  0x2,
+} DDTextFragmentMode;
+
+extern CFStringRef const DDBinderHttpURLKey;
+extern CFStringRef const DDBinderWebURLKey;
+extern CFStringRef const DDBinderMailURLKey;
+extern CFStringRef const DDBinderGenericURLKey;
+extern CFStringRef const DDBinderEmailKey;
+extern CFStringRef const DDBinderTrackingNumberKey;
+extern CFStringRef const DDBinderFlightInformationKey;
+extern CFStringRef const DDBinderSignatureBlockKey;
+extern NSString * const DDURLScheme;
+
+@interface DDScannerResult : NSObject &lt;NSCoding, NSSecureCoding&gt;
++ (NSArray *)resultsFromCoreResults:(CFArrayRef)coreResults;
+@end
+
+#define DDResultPropertyPassiveDisplay   (1 &lt;&lt; 0)
+
+typedef struct __DDQueryOffset {
+    CFIndex queryIndex;
+    CFIndex offset;
+} DDQueryOffset;
+
+typedef struct __DDQueryRange {
+    DDQueryOffset start;
+    DDQueryOffset end;
+} DDQueryRange;
+
</ins><span class="cx"> #endif // !USE(APPLE_INTERNAL_SDK)
</span><span class="cx"> 
</span><span class="cx"> typedef struct __DDResult *DDResultRef;
</span><span class="lines">@@ -48,13 +111,56 @@
</span><span class="cx"> 
</span><span class="cx"> typedef CFIndex DDScannerCopyResultsOptions;
</span><span class="cx"> typedef CFIndex DDScannerOptions;
</span><ins>+extern const DDScannerCopyResultsOptions DDScannerCopyResultsOptionsForPassiveUse;
</ins><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; {
</span><span class="cx"> 
</span><span class="cx"> DDScannerRef DDScannerCreate(DDScannerType, DDScannerOptions, CFErrorRef*);
</span><ins>+DDScanQueryRef DDScanQueryCreate(CFAllocatorRef);
</ins><span class="cx"> DDScanQueryRef DDScanQueryCreateFromString(CFAllocatorRef, CFStringRef, CFRange);
</span><span class="cx"> Boolean DDScannerScanQuery(DDScannerRef, DDScanQueryRef);
</span><span class="cx"> CFArrayRef DDScannerCopyResultsWithOptions(DDScannerRef, DDScannerCopyResultsOptions);
</span><span class="cx"> CFRange DDResultGetRange(DDResultRef);
</span><ins>+CFStringRef DDResultGetType(DDResultRef);
+DDResultCategory DDResultGetCategory(DDResultRef);
+Boolean DDResultIsPastDate(DDResultRef, CFDateRef referenceDate, CFTimeZoneRef referenceTimeZone);
+void DDScanQueryAddTextFragment(DDScanQueryRef, CFStringRef, CFRange, void *identifier, DDTextFragmentMode, DDTextCoalescingType);
+void DDScanQueryAddSeparator(DDScanQueryRef, DDTextCoalescingType);
+void DDScanQueryAddLineBreak(DDScanQueryRef);
+void *DDScanQueryGetFragmentMetaData(DDScanQueryRef, CFIndex queryIndex);
+bool DDResultHasProperties(DDResultRef, CFIndex propertySet);
+CFArrayRef DDResultGetSubResults(DDResultRef);
+DDQueryRange DDResultGetQueryRangeForURLification(DDResultRef);
</ins><span class="cx"> 
</span><ins>+#if PLATFORM(IOS)
+SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectorsCore)
+SOFT_LINK_CLASS(DataDetectorsCore, DDScannerResult)
+SOFT_LINK(DataDetectorsCore, DDScannerCreate, DDScannerRef, (DDScannerType type, DDScannerOptions options, CFErrorRef * errorRef), (type, options, errorRef))
+SOFT_LINK(DataDetectorsCore, DDScannerScanQuery, Boolean, (DDScannerRef scanner, DDScanQueryRef query), (scanner, query))
+SOFT_LINK(DataDetectorsCore, DDScanQueryCreate, DDScanQueryRef, (CFAllocatorRef allocator), (allocator))
+SOFT_LINK(DataDetectorsCore, DDScannerCopyResultsWithOptions, CFArrayRef, (DDScannerRef scanner, DDScannerCopyResultsOptions options), (scanner, options))
+SOFT_LINK(DataDetectorsCore, DDResultGetRange, CFRange, (DDResultRef result), (result))
+SOFT_LINK(DataDetectorsCore, DDResultGetType, CFStringRef, (DDResultRef result), (result))
+SOFT_LINK(DataDetectorsCore, DDResultGetCategory, DDResultCategory, (DDResultRef result), (result))
+SOFT_LINK(DataDetectorsCore, DDResultIsPastDate, Boolean, (DDResultRef result, CFDateRef referenceDate, CFTimeZoneRef referenceTimeZone), (result, referenceDate, referenceTimeZone))
+SOFT_LINK(DataDetectorsCore, DDScanQueryAddTextFragment, void, (DDScanQueryRef query, CFStringRef fragment, CFRange range, void *identifier, DDTextFragmentMode mode, DDTextCoalescingType type), (query, fragment, range, identifier, mode, type))
+SOFT_LINK(DataDetectorsCore, DDScanQueryAddSeparator, void, (DDScanQueryRef query, DDTextCoalescingType type), (query, type))
+SOFT_LINK(DataDetectorsCore, DDScanQueryAddLineBreak, void, (DDScanQueryRef query), (query))
+SOFT_LINK(DataDetectorsCore, DDScanQueryGetFragmentMetaData, void *, (DDScanQueryRef query, CFIndex queryIndex), (query, queryIndex))
+SOFT_LINK(DataDetectorsCore, DDResultHasProperties, bool, (DDResultRef result, CFIndex propertySet), (result, propertySet))
+SOFT_LINK(DataDetectorsCore, DDResultGetSubResults, CFArrayRef, (DDResultRef result), (result))
+SOFT_LINK(DataDetectorsCore, DDResultGetQueryRangeForURLification, DDQueryRange, (DDResultRef result), (result))
+SOFT_LINK(DataDetectorsCore, DDURLStringForResult, NSString *, (DDResultRef currentResult, NSString * resultIdentifier, DDURLifierPhoneNumberDetectionTypes includingTelGroups, NSDate * referenceDate, NSTimeZone * referenceTimeZone), (currentResult, resultIdentifier, includingTelGroups, referenceDate, referenceTimeZone))
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderHttpURLKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderWebURLKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderMailURLKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderGenericURLKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderEmailKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderTrackingNumberKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderFlightInformationKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDBinderSignatureBlockKey, CFStringRef)
+SOFT_LINK_POINTER(DataDetectorsCore, DDURLScheme, NSString *)
+SOFT_LINK_CONSTANT(DataDetectorsCore, DDScannerCopyResultsOptionsForPassiveUse, DDScannerCopyResultsOptions)
+#endif
+
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebKit2/ChangeLog        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-01-22  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        Add support for DataDetectors in WK (iOS).
+        https://bugs.webkit.org/show_bug.cgi?id=152989
+        rdar://problem/22855960
+
+        Reviewed by Tim Horton.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (fromWKDataDetectorTypes): Changed parameter to uint64_t to
+        successfully compare against WKDataDetectorTypeAll.
+
</ins><span class="cx"> 2016-01-17  Ada Chan  &lt;adachan@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add a mode parameter to MediaControllerInterface::supportsFullscreen() and ChromeClient::supportsVideoFullscreen().
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaWKWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (195493 => 195494)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-01-23 00:19:02 UTC (rev 195493)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm        2016-01-23 00:24:02 UTC (rev 195494)
</span><span class="lines">@@ -315,7 +315,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><del>-static WebCore::DataDetectorTypes fromWKDataDetectorTypes(uint32_t types)
</del><ins>+static WebCore::DataDetectorTypes fromWKDataDetectorTypes(uint64_t types)
</ins><span class="cx"> {
</span><span class="cx">     if (static_cast&lt;WKDataDetectorTypes&gt;(types) == WKDataDetectorTypeNone)
</span><span class="cx">         return WebCore::DataDetectorTypeNone;
</span></span></pre>
</div>
</div>

</body>
</html>