<!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>[195769] 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/195769">195769</a></dd>
<dt>Author</dt> <dd>enrica@apple.com</dd>
<dt>Date</dt> <dd>2016-01-28 11:40:36 -0800 (Thu, 28 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Should avoid navigation for some data detector urls.
https://bugs.webkit.org/show_bug.cgi?id=153600

Reviewed by Tim Horton.

Source/WebCore:

Adding helper function to decide whether the default action should be performed.

* editing/cocoa/DataDetection.h:
* editing/cocoa/DataDetection.mm:
(WebCore::DataDetection::shouldCancelDefaultAction):

Source/WebKit2:

When a tap is commited, we normally generate a synthetic click if
the node responds to click events.
This patch adds the logic to prevent that from happening if the node
is a data detector link with certain characteristics (calendar event, telephone, etc.).
If this is the case, we compute the interaction information as position, send it
over to the UI process and notify that we did not handle the tap.
The page client is now also notified of this event and can show the data detector sheet if
appropriate.

* UIProcess/PageClient.h:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::toolTipChanged):
(WebKit::PageClientImpl::didNotHandleTapAsClick):
(WebKit::PageClientImpl::decidePolicyForGeolocationPermissionRequest):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView clearSelection]):
(-[WKContentView _didNotHandleTapAsClick:]):
(-[WKContentView _positionInformationDidChange:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::didNotHandleTapAsClick):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::commitPotentialTap):</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="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageClienth">trunk/Source/WebKit2/UIProcess/PageClient.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosPageClientImplIOSh">trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosPageClientImplIOSmm">trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionh">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebCore/ChangeLog        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-01-28  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        Should avoid navigation for some data detector urls.
+        https://bugs.webkit.org/show_bug.cgi?id=153600
+
+        Reviewed by Tim Horton.
+
+        Adding helper function to decide whether the default action should be performed.
+
+        * editing/cocoa/DataDetection.h:
+        * editing/cocoa/DataDetection.mm:
+        (WebCore::DataDetection::shouldCancelDefaultAction):
+
</ins><span class="cx"> 2016-01-28  Dave Hyatt  &lt;hyatt@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Roll out r194555, as it introduced some bad regressions and was not
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingcocoaDataDetectionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/cocoa/DataDetection.h (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/DataDetection.h        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebCore/editing/cocoa/DataDetection.h        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx">     WEBCORE_EXPORT static NSArray *detectContentInRange(RefPtr&lt;Range&gt;&amp; contextRange, DataDetectorTypes);
</span><span class="cx">     WEBCORE_EXPORT static bool isDataDetectorLink(Element*);
</span><span class="cx">     WEBCORE_EXPORT static String dataDetectorIdentifier(Element*);
</span><ins>+    WEBCORE_EXPORT static bool shouldCancelDefaultAction(Element*);
</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 (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/cocoa/DataDetection.mm        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebCore/editing/cocoa/DataDetection.mm        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -61,8 +61,26 @@
</span><span class="cx">     return element-&gt;getAttribute(dataDetectorsAttributeResultKey);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool DataDetection::shouldCancelDefaultAction(Element* element)
+{
</ins><span class="cx"> #if PLATFORM(MAC)
</span><ins>+    UNUSED_PARAM(element);
+    return false;
+#else
+    // FIXME: We should also compute the DDResultRef and check the result category.
+    if (!is&lt;HTMLAnchorElement&gt;(*element))
+        return false;
+    if (element-&gt;getAttribute(dataDetectorsURLScheme) != &quot;true&quot;)
+        return false;
+    String type = element-&gt;getAttribute(dataDetectorsAttributeTypeKey);
+    if (type == &quot;misc&quot; || type == &quot;calendar-event&quot; || type == &quot;telephone&quot;)
+        return true;
+    return false;
+#endif
+}
</ins><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+
</ins><span class="cx"> static RetainPtr&lt;DDActionContext&gt; detectItemAtPositionWithRange(VisiblePosition position, RefPtr&lt;Range&gt; contextRange, FloatRect&amp; detectedDataBoundingBox, RefPtr&lt;Range&gt;&amp; detectedDataRange)
</span><span class="cx"> {
</span><span class="cx">     String fullPlainTextString = plainText(contextRange.get());
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/ChangeLog        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2016-01-28  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        Should avoid navigation for some data detector urls.
+        https://bugs.webkit.org/show_bug.cgi?id=153600
+
+        Reviewed by Tim Horton.
+
+        When a tap is commited, we normally generate a synthetic click if
+        the node responds to click events.
+        This patch adds the logic to prevent that from happening if the node
+        is a data detector link with certain characteristics (calendar event, telephone, etc.).
+        If this is the case, we compute the interaction information as position, send it
+        over to the UI process and notify that we did not handle the tap.
+        The page client is now also notified of this event and can show the data detector sheet if
+        appropriate.
+
+        * UIProcess/PageClient.h:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::toolTipChanged):
+        (WebKit::PageClientImpl::didNotHandleTapAsClick):
+        (WebKit::PageClientImpl::decidePolicyForGeolocationPermissionRequest):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView clearSelection]):
+        (-[WKContentView _didNotHandleTapAsClick:]):
+        (-[WKContentView _positionInformationDidChange:]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::didNotHandleTapAsClick):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::commitPotentialTap):
+
</ins><span class="cx"> 2016-01-28  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS] Update Web Process sandbox profile for audiodeviceclock access
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageClient.h        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -212,6 +212,7 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     virtual WebCore::IntPoint accessibilityScreenToRootView(const WebCore::IntPoint&amp;) = 0;
</span><span class="cx">     virtual WebCore::IntRect rootViewToAccessibilityScreen(const WebCore::IntRect&amp;) = 0;
</span><ins>+    virtual void didNotHandleTapAsClick(const WebCore::IntPoint&amp;) = 0;
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&amp;, bool wasEventHandled) = 0;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosPageClientImplIOSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -185,6 +185,7 @@
</span><span class="cx">     virtual void didFinishLoadForMainFrame() override;
</span><span class="cx">     virtual void didFailLoadForMainFrame() override;
</span><span class="cx">     virtual void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType) override;
</span><ins>+    virtual void didNotHandleTapAsClick(const WebCore::IntPoint&amp;) override;
</ins><span class="cx"> 
</span><span class="cx">     virtual void didChangeBackgroundColor() override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosPageClientImplIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -230,6 +230,11 @@
</span><span class="cx">     notImplemented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PageClientImpl::didNotHandleTapAsClick(const WebCore::IntPoint&amp; point)
+{
+    [m_contentView _didNotHandleTapAsClick:point];
+}
+
</ins><span class="cx"> bool PageClientImpl::decidePolicyForGeolocationPermissionRequest(WebFrameProxy&amp; frame, API::SecurityOrigin&amp; origin, GeolocationPermissionRequestProxy&amp; request)
</span><span class="cx"> {
</span><span class="cx">     [[wrapper(m_webView-&gt;_page-&gt;process().processPool()) _geolocationProvider] decidePolicyForGeolocationRequestFromOrigin:origin.securityOrigin() frame:frame request:request view:m_webView];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -185,6 +185,7 @@
</span><span class="cx"> - (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&amp;)touchEvent preventsNativeGestures:(BOOL)preventsDefault;
</span><span class="cx"> #endif
</span><span class="cx"> - (void)_commitPotentialTapFailed;
</span><ins>+- (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&amp;)point;
</ins><span class="cx"> - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&amp;)color quads:(const Vector&lt;WebCore::FloatQuad&gt;&amp;)highlightedQuads topLeftRadius:(const WebCore::IntSize&amp;)topLeftRadius topRightRadius:(const WebCore::IntSize&amp;)topRightRadius bottomLeftRadius:(const WebCore::IntSize&amp;)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&amp;)bottomRightRadius;
</span><span class="cx"> 
</span><span class="cx"> - (BOOL)_mayDisableDoubleTapGesturesDuringSingleTap;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -1402,6 +1402,14 @@
</span><span class="cx">     _page-&gt;clearSelection();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&amp;)point
+{
+    // FIXME: we should also take into account whether or not the UI delegate
+    // has handled this notification.
+    if (_hasValidPositionInformation &amp;&amp; point == _positionInformation.point &amp;&amp; _positionInformation.isDataDetectorLink)
+        [self _showDataDetectorsSheet];
+}
+
</ins><span class="cx"> - (void)_positionInformationDidChange:(const InteractionInformationAtPosition&amp;)info
</span><span class="cx"> {
</span><span class="cx">     _positionInformation = info;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -932,6 +932,7 @@
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint&amp; point)
</span><span class="cx"> {
</span><ins>+    m_pageClient.didNotHandleTapAsClick(point);
</ins><span class="cx">     m_uiClient-&gt;didNotHandleTapAsClick(point);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (195768 => 195769)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2016-01-28 19:34:36 UTC (rev 195768)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2016-01-28 19:40:36 UTC (rev 195769)
</span><span class="lines">@@ -677,9 +677,13 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_potentialTapNode == nodeRespondingToClick)
-        handleSyntheticClick(nodeRespondingToClick, adjustedPoint);
-    else
</del><ins>+    if (m_potentialTapNode == nodeRespondingToClick) {
+        if (is&lt;Element&gt;(*nodeRespondingToClick) &amp;&amp; DataDetection::shouldCancelDefaultAction(&amp;downcast&lt;Element&gt;(*nodeRespondingToClick))) {
+            requestPositionInformation(roundedIntPoint(m_potentialTapLocation));
+            commitPotentialTapFailed();
+        } else
+            handleSyntheticClick(nodeRespondingToClick, adjustedPoint);
+    } else
</ins><span class="cx">         commitPotentialTapFailed();
</span><span class="cx"> 
</span><span class="cx">     m_potentialTapNode = nullptr;
</span></span></pre>
</div>
</div>

</body>
</html>