<!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>[162103] trunk/Source/WebKit2</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/162103">162103</a></dd>
<dt>Author</dt> <dd>enrica@apple.com</dd>
<dt>Date</dt> <dd>2014-01-15 16:52:47 -0800 (Wed, 15 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Support WebSelections in WK2 on iOS.
https://bugs.webkit.org/show_bug.cgi?id=127015

Reviewed by Benjamin Poulain.

This is the first step towards adding support for selections in
non editable content on iOS for WK2.
In particular, this patch adds the basic plumbing to decide which
gesture recognizers are enabled and adds empty stubs for the gestures
that we'll need to support.
There are two separate assistants for selections, one to be used
in editable text (UIWKTextInteractionAssistant) and one for non editable
text (UIWKSelectionAssistant) and they are mutually exclusive.
UIWKSelectionAssistant is created at the time the view is created, 
and swapped with UIWKTextInteraction assistant
only when an editable element is focused and the keyboard appears on screen.

gestureRecognizerShouldBegin is the delegate call used to decide which gestures
should begin based on the position the gesture occurred at.
We want to avoid as much as possible synchronous calls to the WebProcess to
retrieve information about the content and in order to do so, we take advantage
of the order in which the gesture recognizers will trigger, based on the delay
configured at initialization.
The first gesture to trigger is highlightLongPress, followed by longpress in the
active assistant and longpress in the WKInteractionView.
There are two different scenarios for highlighlongpress based on which assistant is
currently active.

UIWKSelectionAssistant is active:
    We send a request to the WebProcess to get information on the position
    and we return YES, allowing the gesture to start.
    We delegate to the WebProcess the proper handling of highlight based on the element.
    When longPress gesture fires for the assistant, we assume we have received the reply to our
    previous request, if not we fetch the information synchronously.
    We are then able to make an informed decision about whether
    or not to start the gesture. If the reply is NO, the third and last long press
    gesture can be evaluated to decide whether to show the action sheet or simply generate
    a click event.

UIWKTextInteractionAssistant is active:
    In this case we must have information about the position immediately and we issue
    a synchronous request to the WebProcess.
    If we are not interacting with the same node, we return NO.
    Then the longpress gesture fires for the assistant which performs the same check.
    If the node is the same, the loupe gesture will start, otherwise the last longpress
    gesture will be evaluated to decide about showing the action sheet or generating a
    click event.

* Scripts/webkit2/messages.py:
* Shared/InteractionInformationAtPosition.cpp: Added.
(WebKit::InteractionInformationAtPosition::encode):
(WebKit::InteractionInformationAtPosition::decode):
* Shared/InteractionInformationAtPosition.h: Added.
(WebKit::InteractionInformationAtPosition::InteractionInformationAtPosition):
* UIProcess/API/ios/PageClientImplIOS.h:
* UIProcess/API/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::positionInformationDidChange):
* UIProcess/API/ios/WKContentView.mm:
(-[WKContentView _positionInformationDidChange:]):
* UIProcess/API/ios/WKContentViewInternal.h:
* UIProcess/API/ios/WKInteractionView.h:
* UIProcess/API/ios/WKInteractionView.mm:
(-[WKInteractionView initWithFrame:]):
(-[WKInteractionView dealloc]):
(-[WKInteractionView gestureRecognizer:canPreventGestureRecognizer:]):
(-[WKInteractionView gestureRecognizer:canBePreventedByGestureRecognizer:]):
(isSamePair):
(-[WKInteractionView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
(-[WKInteractionView _showImageSheet]):
(-[WKInteractionView _showLinkSheet]):
(-[WKInteractionView _actionForLongPress]):
(-[WKInteractionView ensurePositionInformationIsUpToDate:]):
(-[WKInteractionView gestureRecognizerShouldBegin:]):
(-[WKInteractionView hasSelectablePositionAtPoint:]):
(-[WKInteractionView pointIsInAssistedNode:]):
(-[WKInteractionView _longPressRecognized:]):
(-[WKInteractionView _doubleTapRecognized:]):
(-[WKInteractionView _twoFingerDoubleTapRecognized:]):
(-[WKInteractionView _twoFingerPanRecognized:]):
(-[WKInteractionView useSelectionAssistantWithMode:]):
(-[WKInteractionView _positionInformationDidChange:]):
(-[WKInteractionView interactionAssistant]):
(-[WKInteractionView _startAssistingKeyboard]):
(-[WKInteractionView _stopAssistingKeyboard]):
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::didReceivePositionInformation):
(WebKit::WebPageProxy::getPositionInformation):
(WebKit::WebPageProxy::requestPositionInformation):
* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::selectWithGesture):
(WebKit::WebPage::getPositionInformation):
(WebKit::WebPage::requestPositionInformation):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2Scriptswebkit2messagespy">trunk/Source/WebKit2/Scripts/webkit2/messages.py</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSh">trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSmm">trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosWKContentViewmm">trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosWKContentViewInternalh">trunk/Source/WebKit2/UIProcess/API/ios/WKContentViewInternal.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosWKInteractionViewh">trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosWKInteractionViewmm">trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPageClienth">trunk/Source/WebKit2/UIProcess/PageClient.h</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="#trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj">trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPageh">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagemessagesin">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2SharedInteractionInformationAtPositioncpp">trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedInteractionInformationAtPositionh">trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/ChangeLog        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -1,3 +1,104 @@
</span><ins>+2014-01-15  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        Support WebSelections in WK2 on iOS.
+        https://bugs.webkit.org/show_bug.cgi?id=127015
+
+        Reviewed by Benjamin Poulain.
+
+        This is the first step towards adding support for selections in
+        non editable content on iOS for WK2.
+        In particular, this patch adds the basic plumbing to decide which
+        gesture recognizers are enabled and adds empty stubs for the gestures
+        that we'll need to support.
+        There are two separate assistants for selections, one to be used
+        in editable text (UIWKTextInteractionAssistant) and one for non editable
+        text (UIWKSelectionAssistant) and they are mutually exclusive.
+        UIWKSelectionAssistant is created at the time the view is created, 
+        and swapped with UIWKTextInteraction assistant
+        only when an editable element is focused and the keyboard appears on screen.
+
+        gestureRecognizerShouldBegin is the delegate call used to decide which gestures
+        should begin based on the position the gesture occurred at.
+        We want to avoid as much as possible synchronous calls to the WebProcess to
+        retrieve information about the content and in order to do so, we take advantage
+        of the order in which the gesture recognizers will trigger, based on the delay
+        configured at initialization.
+        The first gesture to trigger is highlightLongPress, followed by longpress in the
+        active assistant and longpress in the WKInteractionView.
+        There are two different scenarios for highlighlongpress based on which assistant is
+        currently active.
+
+        UIWKSelectionAssistant is active:
+            We send a request to the WebProcess to get information on the position
+            and we return YES, allowing the gesture to start.
+            We delegate to the WebProcess the proper handling of highlight based on the element.
+            When longPress gesture fires for the assistant, we assume we have received the reply to our
+            previous request, if not we fetch the information synchronously.
+            We are then able to make an informed decision about whether
+            or not to start the gesture. If the reply is NO, the third and last long press
+            gesture can be evaluated to decide whether to show the action sheet or simply generate
+            a click event.
+
+        UIWKTextInteractionAssistant is active:
+            In this case we must have information about the position immediately and we issue
+            a synchronous request to the WebProcess.
+            If we are not interacting with the same node, we return NO.
+            Then the longpress gesture fires for the assistant which performs the same check.
+            If the node is the same, the loupe gesture will start, otherwise the last longpress
+            gesture will be evaluated to decide about showing the action sheet or generating a
+            click event.
+
+        * Scripts/webkit2/messages.py:
+        * Shared/InteractionInformationAtPosition.cpp: Added.
+        (WebKit::InteractionInformationAtPosition::encode):
+        (WebKit::InteractionInformationAtPosition::decode):
+        * Shared/InteractionInformationAtPosition.h: Added.
+        (WebKit::InteractionInformationAtPosition::InteractionInformationAtPosition):
+        * UIProcess/API/ios/PageClientImplIOS.h:
+        * UIProcess/API/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::positionInformationDidChange):
+        * UIProcess/API/ios/WKContentView.mm:
+        (-[WKContentView _positionInformationDidChange:]):
+        * UIProcess/API/ios/WKContentViewInternal.h:
+        * UIProcess/API/ios/WKInteractionView.h:
+        * UIProcess/API/ios/WKInteractionView.mm:
+        (-[WKInteractionView initWithFrame:]):
+        (-[WKInteractionView dealloc]):
+        (-[WKInteractionView gestureRecognizer:canPreventGestureRecognizer:]):
+        (-[WKInteractionView gestureRecognizer:canBePreventedByGestureRecognizer:]):
+        (isSamePair):
+        (-[WKInteractionView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
+        (-[WKInteractionView _showImageSheet]):
+        (-[WKInteractionView _showLinkSheet]):
+        (-[WKInteractionView _actionForLongPress]):
+        (-[WKInteractionView ensurePositionInformationIsUpToDate:]):
+        (-[WKInteractionView gestureRecognizerShouldBegin:]):
+        (-[WKInteractionView hasSelectablePositionAtPoint:]):
+        (-[WKInteractionView pointIsInAssistedNode:]):
+        (-[WKInteractionView _longPressRecognized:]):
+        (-[WKInteractionView _doubleTapRecognized:]):
+        (-[WKInteractionView _twoFingerDoubleTapRecognized:]):
+        (-[WKInteractionView _twoFingerPanRecognized:]):
+        (-[WKInteractionView useSelectionAssistantWithMode:]):
+        (-[WKInteractionView _positionInformationDidChange:]):
+        (-[WKInteractionView interactionAssistant]):
+        (-[WKInteractionView _startAssistingKeyboard]):
+        (-[WKInteractionView _stopAssistingKeyboard]):
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::didReceivePositionInformation):
+        (WebKit::WebPageProxy::getPositionInformation):
+        (WebKit::WebPageProxy::requestPositionInformation):
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::selectWithGesture):
+        (WebKit::WebPage::getPositionInformation):
+        (WebKit::WebPage::requestPositionInformation):
+
</ins><span class="cx"> 2014-01-15  Yongjun Zhang  &lt;yongjun_zhang@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=127066
</span></span></pre></div>
<a id="trunkSourceWebKit2Scriptswebkit2messagespy"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Scripts/webkit2/messages.py (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Scripts/webkit2/messages.py        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/Scripts/webkit2/messages.py        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -207,6 +207,7 @@
</span><span class="cx">         'WebKit::DictionaryPopupInfo',
</span><span class="cx">         'WebKit::DrawingAreaInfo',
</span><span class="cx">         'WebKit::EditorState',
</span><ins>+        'WebKit::InteractionInformationAtPosition',
</ins><span class="cx">         'WebKit::NetworkProcessCreationParameters',
</span><span class="cx">         'WebKit::PlatformPopupMenuData',
</span><span class="cx">         'WebKit::PluginCreationParameters',
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedInteractionInformationAtPositioncpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.cpp (0 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.cpp                                (rev 0)
+++ trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.cpp        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;InteractionInformationAtPosition.h&quot;
+
+#include &quot;Arguments.h&quot;
+#include &quot;WebCoreArgumentCoders.h&quot;
+
+namespace WebKit {
+
+#if PLATFORM(IOS)
+void InteractionInformationAtPosition::encode(IPC::ArgumentEncoder&amp; encoder) const
+{
+    encoder &lt;&lt; point;
+    encoder &lt;&lt; nodeAtPositionIsAssistedNode;
+    encoder &lt;&lt; clickableElementName;
+    encoder &lt;&lt; url;
+    encoder &lt;&lt; selectionRects;
+}
+
+bool InteractionInformationAtPosition::decode(IPC::ArgumentDecoder&amp; decoder, InteractionInformationAtPosition&amp; result)
+{
+    if (!decoder.decode(result.point))
+        return false;
+
+    if (!decoder.decode(result.nodeAtPositionIsAssistedNode))
+        return false;
+
+    if (!decoder.decode(result.clickableElementName))
+        return false;
+
+    if (!decoder.decode(result.url))
+        return false;
+
+    if (!decoder.decode(result.selectionRects))
+        return false;
+
+    return true;
+}
+#endif
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebKit2SharedInteractionInformationAtPositionh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.h (0 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.h                                (rev 0)
+++ trunk/Source/WebKit2/Shared/InteractionInformationAtPosition.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef InteractionInformationAtPosition_h
+#define InteractionInformationAtPosition_h
+
+#include &quot;ArgumentCoders.h&quot;
+#include &lt;WebCore/IntPoint.h&gt;
+#include &lt;WebCore/SelectionRect.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebKit {
+
+#if PLATFORM(IOS)
+struct InteractionInformationAtPosition {
+    InteractionInformationAtPosition()
+        : nodeAtPositionIsAssistedNode(false)
+    {
+    }
+
+    WebCore::IntPoint point;
+    bool nodeAtPositionIsAssistedNode;
+    String clickableElementName;
+    String url;
+    Vector&lt;WebCore::SelectionRect&gt; selectionRects;
+
+    void encode(IPC::ArgumentEncoder&amp;) const;
+    static bool decode(IPC::ArgumentDecoder&amp;, InteractionInformationAtPosition&amp;);
+};
+#endif
+
+}
+
+#endif // InteractionInformationAtPosition_h
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -106,6 +106,7 @@
</span><span class="cx">     virtual void stopAssistingNode() OVERRIDE;
</span><span class="cx">     virtual void selectionDidChange() OVERRIDE;
</span><span class="cx">     virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&amp;, bool isCharEvent) OVERRIDE;
</span><ins>+    virtual void positionInformationDidChange(const InteractionInformationAtPosition&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // Auxiliary Client Creation
</span><span class="cx"> #if ENABLE(FULLSCREEN_API)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosPageClientImplIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #import &quot;PageClientImplIOS.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #import &quot;NativeWebKeyboardEvent.h&quot;
</span><ins>+#import &quot;InteractionInformationAtPosition.h&quot;
</ins><span class="cx"> #import &quot;WKContentViewInternal.h&quot;
</span><span class="cx"> #import &quot;WebContextMenuProxy.h&quot;
</span><span class="cx"> #import &quot;WebEditCommandProxy.h&quot;
</span><span class="lines">@@ -200,7 +201,12 @@
</span><span class="cx"> {
</span><span class="cx">     return [m_view _interpretKeyEvent:event.nativeEvent() isCharEvent:isCharEvent];
</span><span class="cx"> }
</span><del>-    
</del><ins>+
+void PageClientImpl::positionInformationDidChange(const InteractionInformationAtPosition&amp; info)
+{
+    [m_view _positionInformationDidChange:info];
+}
+
</ins><span class="cx"> bool PageClientImpl::executeSavedCommandBySelector(const String&amp;)
</span><span class="cx"> {
</span><span class="cx">     notImplemented();
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosWKContentViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKContentView.mm        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #import &quot;config.h&quot;
</span><span class="cx"> #import &quot;WKContentViewInternal.h&quot;
</span><span class="cx"> 
</span><ins>+#import &quot;InteractionInformationAtPosition.h&quot;
</ins><span class="cx"> #import &quot;PageClientImplIOS.h&quot;
</span><span class="cx"> #import &quot;RemoteLayerTreeDrawingAreaProxy.h&quot;
</span><span class="cx"> #import &quot;WebKit2Initialize.h&quot;
</span><span class="lines">@@ -277,6 +278,11 @@
</span><span class="cx">     return [_interactionView _interpretKeyEvent:theEvent isCharEvent:isCharEvent];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_positionInformationDidChange:(const InteractionInformationAtPosition&amp;)info
+{
+    [_interactionView _positionInformationDidChange:info];
+}
+
</ins><span class="cx"> - (void)_decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin&amp;)origin frame:(WebFrameProxy&amp;)frame request:(GeolocationPermissionRequestProxy&amp;)permissionRequest
</span><span class="cx"> {
</span><span class="cx">     [[wrapper(_page-&gt;process().context()) _geolocationProvider] decidePolicyForGeolocationRequestFromOrigin:toAPI(&amp;origin) frame:toAPI(&amp;frame) request:toAPI(&amp;permissionRequest) window:[self window]];
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosWKContentViewInternalh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKContentViewInternal.h (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/WKContentViewInternal.h        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKContentViewInternal.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> class LayerTreeContext;
</span><span class="cx"> class WebFrameProxy;
</span><span class="cx"> class WebSecurityOrigin;
</span><ins>+struct InteractionInformationAtPosition;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @class WebIOSEvent;
</span><span class="lines">@@ -62,7 +63,7 @@
</span><span class="cx"> - (void)_stopAssistingNode;
</span><span class="cx"> - (void)_selectionChanged;
</span><span class="cx"> - (BOOL)_interpretKeyEvent:(WebIOSEvent *)theEvent isCharEvent:(BOOL)isCharEvent;
</span><del>-
</del><ins>+- (void)_positionInformationDidChange:(const WebKit::InteractionInformationAtPosition&amp;)info;
</ins><span class="cx"> - (void)_decidePolicyForGeolocationRequestFromOrigin:(WebKit::WebSecurityOrigin&amp;)origin frame:(WebKit::WebFrameProxy&amp;)frame request:(WebKit::GeolocationPermissionRequestProxy&amp;)permissionRequest;
</span><span class="cx"> 
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosWKInteractionViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.h (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.h        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #import &lt;UIKit/UITextInput_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIView.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIWebTouchEventsGestureRecognizer.h&gt;
</span><ins>+#import &lt;UIKit/UIWKSelectionAssistant.h&gt;
</ins><span class="cx"> #import &lt;UIKit/UIWKTextInteractionAssistant.h&gt;
</span><span class="cx"> #import &lt;wtf/Forward.h&gt;
</span><span class="cx"> #import &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -41,6 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> class WebPageProxy;
</span><ins>+struct InteractionInformationAtPosition;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @class WebIOSEvent;
</span><span class="lines">@@ -56,4 +58,5 @@
</span><span class="cx"> - (void)_stopAssistingNode;
</span><span class="cx"> - (void)_selectionChanged;
</span><span class="cx"> - (BOOL)_interpretKeyEvent:(WebIOSEvent *)theEvent isCharEvent:(BOOL)isCharEvent;
</span><ins>+- (void)_positionInformationDidChange:(const WebKit::InteractionInformationAtPosition&amp;)info;
</ins><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosWKInteractionViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #import &quot;config.h&quot;
</span><span class="cx"> #import &quot;WKInteractionView.h&quot;
</span><span class="cx"> 
</span><ins>+#import &quot;InteractionInformationAtPosition.h&quot;
</ins><span class="cx"> #import &quot;NativeWebKeyboardEvent.h&quot;
</span><span class="cx"> #import &quot;NativeWebTouchEvent.h&quot;
</span><span class="cx"> #import &quot;WKBase.h&quot;
</span><span class="lines">@@ -35,15 +36,18 @@
</span><span class="cx"> #import &quot;WebPageMessages.h&quot;
</span><span class="cx"> #import &quot;WebProcessProxy.h&quot;
</span><span class="cx"> #import &lt;UIKit/UIFont_Private.h&gt;
</span><ins>+#import &lt;UIKit/UIGestureRecognizer_Private.h&gt;
</ins><span class="cx"> #import &lt;UIKit/UIKeyboardImpl.h&gt;
</span><span class="cx"> #import &lt;UIKit/UILongPressGestureRecognizer_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UITapGestureRecognizer_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UITextInteractionAssistant_Private.h&gt;
</span><ins>+#import &lt;UIKit/UIWebDocumentView.h&gt;
</ins><span class="cx"> #import &lt;UIKit/UIWebScrollView.h&gt;
</span><span class="cx"> #import &lt;UIKit/_UIHighlightView.h&gt;
</span><span class="cx"> #import &lt;UIKit/_UIWebHighlightLongPressGestureRecognizer.h&gt;
</span><span class="cx"> #import &lt;WebCore/Color.h&gt;
</span><span class="cx"> #import &lt;WebCore/FloatQuad.h&gt;
</span><ins>+#import &lt;WebCore/NotImplemented.h&gt;
</ins><span class="cx"> #import &lt;WebCore/WebEvent.h&gt;
</span><span class="cx"> #import &lt;WebKit/WebSelectionRect.h&gt;
</span><span class="cx"> #import &lt;wtf/RetainPtr.h&gt;
</span><span class="lines">@@ -52,6 +56,7 @@
</span><span class="cx"> using namespace WebKit;
</span><span class="cx"> 
</span><span class="cx"> static const float highlightDelay = 0.12;
</span><ins>+static const float tapAndHoldDelay  = 0.75;
</ins><span class="cx"> 
</span><span class="cx"> @interface WKTextRange : UITextRange {
</span><span class="cx">     CGRect _startRect;
</span><span class="lines">@@ -138,8 +143,14 @@
</span><span class="cx">     RetainPtr&lt;UIWebTouchEventsGestureRecognizer&gt; _touchEventGestureRecognizer;
</span><span class="cx">     RetainPtr&lt;UITapGestureRecognizer&gt; _singleTapGestureRecognizer;
</span><span class="cx">     RetainPtr&lt;_UIWebHighlightLongPressGestureRecognizer&gt; _highlightLongPressGestureRecognizer;
</span><ins>+    RetainPtr&lt;UILongPressGestureRecognizer&gt; _longPressGestureRecognizer;
+    RetainPtr&lt;UITapGestureRecognizer&gt; _doubleTapGestureRecognizer;
+    RetainPtr&lt;UITapGestureRecognizer&gt; _twoFingerDoubleTapGestureRecognizer;
+    RetainPtr&lt;UIPanGestureRecognizer&gt; _twoFingerPanGestureRecognizer;
</ins><span class="cx"> 
</span><del>-    UIWKTextInteractionAssistant *_textSelectionAssistant;
</del><ins>+    RetainPtr&lt;UIWKTextInteractionAssistant&gt; _textSelectionAssistant;
+    RetainPtr&lt;UIWKSelectionAssistant&gt; _webSelectionAssistant;
+
</ins><span class="cx">     UITextInputTraits *_traits;
</span><span class="cx">     BOOL _canBeFirstResponder;
</span><span class="cx">     UIWebFormAccessory *_accessory;
</span><span class="lines">@@ -154,6 +165,8 @@
</span><span class="cx">     BOOL _isTapHighlightIDValid;
</span><span class="cx">     WKAutoCorrectionData _autocorrectionData;
</span><span class="cx">     RetainPtr&lt;NSString&gt; _markedText;
</span><ins>+    InteractionInformationAtPosition _positionInformation;
+    BOOL _hasValidPositionInformation;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @synthesize inputDelegate = _inputDelegate;
</span><span class="lines">@@ -163,32 +176,55 @@
</span><span class="cx">     self = [super initWithFrame:frame];
</span><span class="cx">     if (self) {
</span><span class="cx">         _touchEventGestureRecognizer = adoptNS([[UIWebTouchEventsGestureRecognizer alloc] initWithTarget:self action:@selector(_webTouchEventsRecognized:) touchDelegate:self]);
</span><del>-        [_touchEventGestureRecognizer.get() setDelegate:self];
</del><ins>+        [_touchEventGestureRecognizer setDelegate:self];
</ins><span class="cx">         [self addGestureRecognizer:_touchEventGestureRecognizer.get()];
</span><span class="cx"> 
</span><span class="cx">         _singleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_singleTapRecognized:)]);
</span><del>-        [_singleTapGestureRecognizer.get() setDelegate:self];
</del><ins>+        [_singleTapGestureRecognizer setDelegate:self];
</ins><span class="cx">         [self addGestureRecognizer:_singleTapGestureRecognizer.get()];
</span><span class="cx"> 
</span><ins>+        _doubleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_doubleTapRecognized:)]);
+        [_doubleTapGestureRecognizer setNumberOfTapsRequired:2];
+        [_doubleTapGestureRecognizer setDelegate:self];
+        [self addGestureRecognizer:_doubleTapGestureRecognizer.get()];
+        [_singleTapGestureRecognizer requireOtherGestureToFail:_doubleTapGestureRecognizer.get()];
+
</ins><span class="cx">         _highlightLongPressGestureRecognizer = adoptNS([[_UIWebHighlightLongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_highlightLongPressRecognized:)]);
</span><del>-        [_highlightLongPressGestureRecognizer.get() setDelay:highlightDelay];
-        [_highlightLongPressGestureRecognizer.get() setDelegate:self];
</del><ins>+        [_highlightLongPressGestureRecognizer setDelay:highlightDelay];
+        [_highlightLongPressGestureRecognizer setDelegate:self];
</ins><span class="cx">         [self addGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
</span><del>-        
</del><ins>+
+        _longPressGestureRecognizer = adoptNS([[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_longPressRecognized:)]);
+        [_longPressGestureRecognizer setDelay:tapAndHoldDelay];
+        [_longPressGestureRecognizer setDelegate:self];
+        [self addGestureRecognizer:_longPressGestureRecognizer.get()];
+
+        _twoFingerPanGestureRecognizer = adoptNS([[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_twoFingerPanRecognized:)]);
+        [_twoFingerPanGestureRecognizer setMinimumNumberOfTouches:2];
+        [_twoFingerPanGestureRecognizer setMaximumNumberOfTouches:2];
+        [_twoFingerPanGestureRecognizer setDelegate:self];
+        [self addGestureRecognizer:_twoFingerPanGestureRecognizer.get()];
+
</ins><span class="cx">         [self setUserInteractionEnabled:YES];
</span><span class="cx">         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_resetShowingTextStyle:) name:UIMenuControllerDidHideMenuNotification object:nil];
</span><span class="cx">         _showingTextStyleOptions = NO;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // FIXME: This should be called when we get notified that loading has completed.
+    [self useSelectionAssistantWithMode:UIWebSelectionModeWeb];
+
</ins><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)dealloc
</span><span class="cx"> {
</span><del>-    [_touchEventGestureRecognizer.get() setDelegate:nil];
-    [_singleTapGestureRecognizer.get() setDelegate:nil];
-    [_highlightLongPressGestureRecognizer.get() setDelegate:nil];
-    [_textSelectionAssistant release];
</del><ins>+    [_touchEventGestureRecognizer setDelegate:nil];
+    [_singleTapGestureRecognizer setDelegate:nil];
+    [_doubleTapGestureRecognizer setDelegate:nil];
+    [_highlightLongPressGestureRecognizer setDelegate:nil];
+    [_longPressGestureRecognizer setDelegate:nil];
+    [_twoFingerPanGestureRecognizer setDelegate:nil];
+
</ins><span class="cx">     [_accessory release];
</span><span class="cx">     [super dealloc];
</span><span class="cx"> }
</span><span class="lines">@@ -333,12 +369,128 @@
</span><span class="cx">     return YES;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
+{
+    // A long-press gesture can not be recognized while panning, but a pan can be recognized
+    // during a long-press gesture.
+    BOOL shouldNotPreventPanGesture = preventingGestureRecognizer == _highlightLongPressGestureRecognizer || preventingGestureRecognizer == _longPressGestureRecognizer;
+    return !(shouldNotPreventPanGesture &amp;&amp; [preventedGestureRecognizer isKindOfClass:NSClassFromString(@&quot;UIScrollViewPanGestureRecognizer&quot;)]);
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer {
+    // Don't allow the highlight to be prevented by a selection gesture. Press-and-hold on a link should highlight the link, not select it.
+    if ((preventingGestureRecognizer == _textSelectionAssistant.get().loupeGesture || [_webSelectionAssistant isSelectionGestureRecognizer:preventingGestureRecognizer])
+        &amp;&amp; (preventedGestureRecognizer == _highlightLongPressGestureRecognizer || preventedGestureRecognizer == _longPressGestureRecognizer)) {
+        return NO;
+    }
+
+    return YES;
+}
+
+static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UIGestureRecognizer *x, UIGestureRecognizer *y)
+{
+    return (a == x &amp;&amp; b == y) || (b == x &amp;&amp; a == y);
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
+{
+    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _longPressGestureRecognizer.get()))
+        return YES;
+
+    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _webSelectionAssistant.get().selectionLongPressRecognizer))
+        return YES;
+
+    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _singleTapGestureRecognizer.get(), _textSelectionAssistant.get().singleTapGesture))
+        return YES;
+
+    return NO;
+}
+
+- (void)_showImageSheet
+{
+
+}
+
+- (void)_showLinkSheet
+{
+
+}
+
+- (SEL)_actionForLongPress
+{
+    if (_positionInformation.clickableElementName == &quot;IMG&quot;)
+        return @selector(_showImageSheet);
+    else if (_positionInformation.clickableElementName == &quot;A&quot;)
+        return @selector(_showLinkSheet);
+    // FIXME: Add check for links and datadetectors.
+
+    return nil;
+}
+
+- (void)ensurePositionInformationIsUpToDate:(CGPoint)point
+{
+    if (!_hasValidPositionInformation || roundedIntPoint(point) != _positionInformation.point) {
+        _page-&gt;getPositionInformation(roundedIntPoint(point), _positionInformation);
+        _hasValidPositionInformation = YES;
+    }
+}
+
</ins><span class="cx"> - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
</span><span class="cx"> {
</span><del>-    if (_textSelectionAssistant) {
-        if (gestureRecognizer == _highlightLongPressGestureRecognizer || gestureRecognizer == _singleTapGestureRecognizer)
-            return NO;
</del><ins>+    CGPoint point = [gestureRecognizer locationInView:self];
+
+    if (gestureRecognizer == _highlightLongPressGestureRecognizer
+        || gestureRecognizer == _doubleTapGestureRecognizer
+        || gestureRecognizer == _twoFingerDoubleTapGestureRecognizer
+        || gestureRecognizer == _singleTapGestureRecognizer) {
+
+        if (_textSelectionAssistant) {
+            // Request information about the position with sync message.
+            // If the assisted node is the same, prevent the gesture.
+            _page-&gt;getPositionInformation(roundedIntPoint(point), _positionInformation);
+            _hasValidPositionInformation = YES;
+            if (_positionInformation.nodeAtPositionIsAssistedNode)
+                return NO;
+        }
</ins><span class="cx">     }
</span><ins>+
+    if (gestureRecognizer == _highlightLongPressGestureRecognizer) {
+        if (_textSelectionAssistant) {
+            // This is a different node than the assisted one.
+            // Prevent the gesture if there is no node.
+            // Allow the gesture if it is a node that wants highlight or if there is an action for it.
+            if (_positionInformation.clickableElementName.isNull())
+                return NO;
+            return [self _actionForLongPress] != nil;
+        } else {
+            // We still have no idea about what is at the location.
+            // Send and async message to find out.
+            _hasValidPositionInformation = NO;
+            _page-&gt;requestPositionInformation(roundedIntPoint(point));
+            return YES;
+        }
+    }
+
+    if (gestureRecognizer == _longPressGestureRecognizer) {
+        // Use the information retrieved with one of the previous calls
+        // to gestureRecognizerShouldBegin.
+        // Force a sync call if not ready yet.
+        [self ensurePositionInformationIsUpToDate:point];
+
+        if (_textSelectionAssistant) {
+            // Prevent the gesture if it is the same node.
+            if (_positionInformation.nodeAtPositionIsAssistedNode)
+                return NO;
+        } else {
+            // Prevent the gesture if there is no action for the node.
+            return [self _actionForLongPress] != nil;
+        }
+    }
+
+    if (gestureRecognizer == _twoFingerPanGestureRecognizer) {
+        notImplemented();
+    }
+
</ins><span class="cx">     return YES;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -348,6 +500,19 @@
</span><span class="cx">     [_highlightView.get() removeFromSuperview];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (BOOL)hasSelectablePositionAtPoint:(CGPoint)point
+{
+    [self ensurePositionInformationIsUpToDate:point];
+    // FIXME: This check needs to be extended to include other elements.
+    return _positionInformation.clickableElementName != &quot;IMG&quot; &amp;&amp; _positionInformation.clickableElementName != &quot;A&quot; &amp;&amp; !_positionInformation.selectionRects.isEmpty();
+}
+
+- (BOOL)pointIsInAssistedNode:(CGPoint)point
+{
+    [self ensurePositionInformationIsUpToDate:point];
+    return _positionInformation.nodeAtPositionIsAssistedNode;
+}
+
</ins><span class="cx"> - (void)_highlightLongPressRecognized:(UILongPressGestureRecognizer *)gestureRecognizer
</span><span class="cx"> {
</span><span class="cx">     ASSERT(gestureRecognizer == _highlightLongPressGestureRecognizer);
</span><span class="lines">@@ -368,17 +533,45 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_longPressRecognized:(UILongPressGestureRecognizer *)gestureRecognizer
+{
+    ASSERT(gestureRecognizer == _longPressGestureRecognizer);
+
+    switch ([gestureRecognizer state]) {
+    case UIGestureRecognizerStateBegan:
+        // FIXME: add implementation
+        break;
+    case UIGestureRecognizerStateEnded:
+        // FIXME: add implementation
+        break;
+    case UIGestureRecognizerStateCancelled:
+        // FIXME: add implementation
+        break;
+    default:
+        break;
+    }
+}
+
</ins><span class="cx"> - (void)_singleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
</span><span class="cx"> {
</span><span class="cx">     [self _attemptClickAtLocation:[gestureRecognizer location]];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (BOOL)gestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
</del><ins>+- (void)_doubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
</ins><span class="cx"> {
</span><del>-    BOOL shouldNotPreventPanGesture = preventingGestureRecognizer == _highlightLongPressGestureRecognizer;
-    return !(shouldNotPreventPanGesture &amp;&amp; [preventedGestureRecognizer isKindOfClass:NSClassFromString(@&quot;UIScrollViewPanGestureRecognizer&quot;)]);
</del><ins>+    // FIXME: Add implementation.
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_twoFingerDoubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
+{
+    // FIXME: Add implementation.
+}
+
+- (void)_twoFingerPanRecognized:(UIPanGestureRecognizer *)gestureRecognizer
+{
+    // FIXME: Add implementation.
+}
+
</ins><span class="cx"> - (void)_attemptClickAtLocation:(CGPoint)location
</span><span class="cx"> {
</span><span class="cx">     // FIXME: Ideally, we should always provide some visual feedback on click. If a short tap did not trigger the
</span><span class="lines">@@ -391,6 +584,36 @@
</span><span class="cx">     _page-&gt;process().send(Messages::WebPage::HandleTap(IntPoint(location)), _page-&gt;pageID());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)useSelectionAssistantWithMode:(UIWebSelectionMode)selectionMode
+{
+    if (selectionMode == UIWebSelectionModeWeb) {
+        if (_textSelectionAssistant) {
+            [_textSelectionAssistant deactivateSelection];
+            _textSelectionAssistant = nil;
+        }
+        if (!_webSelectionAssistant)
+            _webSelectionAssistant = adoptNS([[UIWKSelectionAssistant alloc] initWithView:self]);
+    } else if (selectionMode == UIWebSelectionModeTextOnly) {
+        if (_webSelectionAssistant)
+            _webSelectionAssistant = nil;
+
+        if (!_textSelectionAssistant)
+            _textSelectionAssistant = adoptNS([[UIWKTextInteractionAssistant alloc] initWithView:self]);
+        else {
+            // Reset the gesture recognizers in case editibility has changed.
+            [_textSelectionAssistant setGestureRecognizers];
+        }
+
+        [_textSelectionAssistant activateSelection];
+    }
+}
+
+- (void)_positionInformationDidChange:(const InteractionInformationAtPosition&amp;)info
+{
+    _positionInformation = info;
+    _hasValidPositionInformation = YES;
+}
+
</ins><span class="cx"> - (UIView *)inputAccessoryView
</span><span class="cx"> {
</span><span class="cx">     if (!_canBeFirstResponder)
</span><span class="lines">@@ -1129,7 +1352,7 @@
</span><span class="cx">     if (!_textSelectionAssistant)
</span><span class="cx">         _textSelectionAssistant = [[UIWKTextInteractionAssistant alloc] initWithView:self];
</span><span class="cx"> 
</span><del>-    return _textSelectionAssistant;
</del><ins>+    return _textSelectionAssistant.get();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -1395,22 +1618,12 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)_startAssistingKeyboard
</span><span class="cx"> {
</span><del>-    if (!_textSelectionAssistant)
-        _textSelectionAssistant = [[UIWKTextInteractionAssistant alloc] initWithView:self];
-    else {
-        // Reset the gesture recognizers in case editibility has changed.
-        [_textSelectionAssistant setGestureRecognizers];
-    }
-    [_textSelectionAssistant activateSelection];
</del><ins>+    [self useSelectionAssistantWithMode:UIWebSelectionModeTextOnly];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_stopAssistingKeyboard
</span><span class="cx"> {
</span><del>-    if (_textSelectionAssistant) {
-        [_textSelectionAssistant deactivateSelection];
-        [_textSelectionAssistant release];
-        _textSelectionAssistant = nil;
-    }
</del><ins>+    [self useSelectionAssistantWithMode:UIWebSelectionModeWeb];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_startAssistingNode
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPageClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/PageClient.h        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -243,6 +243,7 @@
</span><span class="cx">     virtual void stopAssistingNode() = 0;
</span><span class="cx">     virtual void selectionDidChange() = 0;
</span><span class="cx">     virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&amp;, bool isCharEvent) = 0;
</span><ins>+    virtual void positionInformationDidChange(const InteractionInformationAtPosition&amp;) = 0;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     // Auxiliary Client Creation
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;DrawingAreaProxy.h&quot;
</span><span class="cx"> #include &quot;EditorState.h&quot;
</span><span class="cx"> #include &quot;GeolocationPermissionRequestManagerProxy.h&quot;
</span><ins>+#include &quot;InteractionInformationAtPosition.h&quot;
</ins><span class="cx"> #include &quot;LayerTreeContext.h&quot;
</span><span class="cx"> #include &quot;MessageSender.h&quot;
</span><span class="cx"> #include &quot;NotificationPermissionRequestManagerProxy.h&quot;
</span><span class="lines">@@ -444,6 +445,9 @@
</span><span class="cx">     void applyAutocorrection(const String&amp; correction, const String&amp; originalText, PassRefPtr&lt;StringCallback&gt;);
</span><span class="cx">     void requestAutocorrectionContext(PassRefPtr&lt;AutocorrectionContextCallback&gt;);
</span><span class="cx">     void getAutocorrectionContext(String&amp; contextBefore, String&amp; markedText, String&amp; selectedText, String&amp; contextAfter, uint64_t&amp; location, uint64_t&amp; length);
</span><ins>+    void didReceivePositionInformation(const InteractionInformationAtPosition&amp;);
+    void getPositionInformation(const WebCore::IntPoint&amp;, InteractionInformationAtPosition&amp;);
+    void requestPositionInformation(const WebCore::IntPoint&amp;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     const EditorState&amp; editorState() const { return m_editorState; }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -153,6 +153,7 @@
</span><span class="cx">     AutocorrectionDataCallback(Vector&lt;WebCore::FloatRect&gt; textRects, String fontName, double fontSize, uint64_t traits, uint64_t callbackID)
</span><span class="cx">     AutocorrectionContextCallback(String beforeText, String markedText, String selectedText, String afterText, uint64_t location, uint64_t length, uint64_t callbackID)
</span><span class="cx">     InterpretKeyEvent(WebKit::EditorState state, bool isCharEvent) -&gt; (bool handled)
</span><ins>+    DidReceivePositionInformation(WebKit::InteractionInformationAtPosition information)
</ins><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(GTK)
</span><span class="cx">     PrintFinishedCallback(WebCore::ResourceError error, uint64_t callbackID)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -301,6 +301,21 @@
</span><span class="cx">     m_process-&gt;send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::didReceivePositionInformation(const InteractionInformationAtPosition&amp; info)
+{
+    m_pageClient.positionInformationDidChange(info);
+}
+
+void WebPageProxy::getPositionInformation(const WebCore::IntPoint&amp; point, InteractionInformationAtPosition&amp; info)
+{
+    m_process-&gt;sendSync(Messages::WebPage::GetPositionInformation(point), Messages::WebPage::GetPositionInformation::Reply(info), m_pageID);
+}
+
+void WebPageProxy::requestPositionInformation(const WebCore::IntPoint&amp; point)
+{
+    m_process-&gt;send(Messages::WebPage::RequestPositionInformation(point), m_pageID);
+}
+
</ins><span class="cx"> void WebPageProxy::notifyRevealedSelection()
</span><span class="cx"> {
</span><span class="cx">     m_pageClient.selectionDidChange();
</span></span></pre></div>
<a id="trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -1299,6 +1299,9 @@
</span><span class="cx">                 C574A37712E6099D002DFE98 /* WebDragClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C554FFA212E4E8EA002F22C0 /* WebDragClientMac.mm */; };
</span><span class="cx">                 C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = C574A57F12E66681002DFE98 /* PasteboardTypes.h */; };
</span><span class="cx">                 C574A58212E66681002DFE98 /* PasteboardTypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = C574A58012E66681002DFE98 /* PasteboardTypes.mm */; };
</span><ins>+                C58CDF2A1887548B00871536 /* InteractionInformationAtPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = C58CDF281887548B00871536 /* InteractionInformationAtPosition.h */; };
+                C58CDF2D1887609F00871536 /* InteractionInformationAtPosition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C58CDF2B1887609F00871536 /* InteractionInformationAtPosition.cpp */; };
+                C58CDF2E1887609F00871536 /* InteractionInformationAtPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = C58CDF2C1887609F00871536 /* InteractionInformationAtPosition.h */; };
</ins><span class="cx">                 C5E1AFE816B20B67006CC1F2 /* WKWebArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC329DA516ACE5A900316DE2 /* WKWebArchive.cpp */; };
</span><span class="cx">                 C5E1AFE916B20B75006CC1F2 /* WKWebArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = BC329DA616ACE5A900316DE2 /* WKWebArchive.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 C5E1AFEA16B20B7B006CC1F2 /* WKWebArchiveResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC329DA916ACE5BF00316DE2 /* WKWebArchiveResource.cpp */; };
</span><span class="lines">@@ -3021,6 +3024,9 @@
</span><span class="cx">                 C554FFA212E4E8EA002F22C0 /* WebDragClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebDragClientMac.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C574A57F12E66681002DFE98 /* PasteboardTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PasteboardTypes.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C574A58012E66681002DFE98 /* PasteboardTypes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteboardTypes.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                C58CDF281887548B00871536 /* InteractionInformationAtPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractionInformationAtPosition.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                C58CDF2B1887609F00871536 /* InteractionInformationAtPosition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InteractionInformationAtPosition.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                C58CDF2C1887609F00871536 /* InteractionInformationAtPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InteractionInformationAtPosition.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 CD5C669E134B9D36004FE2A8 /* InjectedBundlePageFullScreenClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageFullScreenClient.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CD5C669F134B9D37004FE2A8 /* InjectedBundlePageFullScreenClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundlePageFullScreenClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 CD67D30815C07BE000843ADF /* InjectedBundlePageDiagnosticLoggingClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageDiagnosticLoggingClient.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3694,6 +3700,8 @@
</span><span class="cx">                                 BCCF6B2312C93E7A008F9C35 /* ImageOptions.h */,
</span><span class="cx">                                 BCBCB0CC1215E33A00DE59CA /* ImmutableDictionary.cpp */,
</span><span class="cx">                                 BCBCB0CA1215E32100DE59CA /* ImmutableDictionary.h */,
</span><ins>+                                C58CDF2B1887609F00871536 /* InteractionInformationAtPosition.cpp */,
+                                C58CDF2C1887609F00871536 /* InteractionInformationAtPosition.h */,
</ins><span class="cx">                                 1A92DC1012F8BA460017AF65 /* LayerTreeContext.h */,
</span><span class="cx">                                 BCB0AEE8122F53E300B1341E /* MutableDictionary.cpp */,
</span><span class="cx">                                 BCB0AEE7122F53E300B1341E /* MutableDictionary.h */,
</span><span class="lines">@@ -6039,6 +6047,7 @@
</span><span class="cx">                                 2984F57D164B915F004BC0C6 /* CustomProtocolManagerProxyMessages.h in Headers */,
</span><span class="cx">                                 93FC67BE12D3CCF200A60610 /* DecoderAdapter.h in Headers */,
</span><span class="cx">                                 BCE81D99131AE02100241910 /* DictionaryPopupInfo.h in Headers */,
</span><ins>+                                C58CDF2E1887609F00871536 /* InteractionInformationAtPosition.h in Headers */,
</ins><span class="cx">                                 5167EEA0170377BF007681CA /* DiskCacheMonitor.h in Headers */,
</span><span class="cx">                                 518E8F0816B2093700E91429 /* Download.h in Headers */,
</span><span class="cx">                                 518E8F0A16B2093700E91429 /* DownloadAuthenticationClient.h in Headers */,
</span><span class="lines">@@ -6419,6 +6428,7 @@
</span><span class="cx">                                 51D54A73185BAC42000CAED2 /* IDBTransactionIdentifier.h in Headers */,
</span><span class="cx">                                 D3B9484711FF4B6500032B39 /* WebPopupMenu.h in Headers */,
</span><span class="cx">                                 BC574E631267D080006F0F12 /* WebPopupMenuProxy.h in Headers */,
</span><ins>+                                C58CDF2A1887548B00871536 /* InteractionInformationAtPosition.h in Headers */,
</ins><span class="cx">                                 BC5750971268F3C6006F0F12 /* WebPopupMenuProxyMac.h in Headers */,
</span><span class="cx">                                 BCD597FF112B57BE00EC8C23 /* WebPreferences.h in Headers */,
</span><span class="cx">                                 BCD598AC112B7FDF00EC8C23 /* WebPreferencesStore.h in Headers */,
</span><span class="lines">@@ -7808,6 +7818,7 @@
</span><span class="cx">                                 BC963D6E113DD1A500574BE2 /* WebPageMac.mm in Sources */,
</span><span class="cx">                                 C0CE72A01247E71D00BC0EC4 /* WebPageMessageReceiver.cpp in Sources */,
</span><span class="cx">                                 BC111B0F112F5E4F00337BAB /* WebPageProxy.cpp in Sources */,
</span><ins>+                                C58CDF2D1887609F00871536 /* InteractionInformationAtPosition.cpp in Sources */,
</ins><span class="cx">                                 51B3005112529D0E000B5CA0 /* WebPageProxyCF.cpp in Sources */,
</span><span class="cx">                                 1F7506AD1859161C00EC0FF7 /* WKWebProcessPlugInFrame.mm in Sources */,
</span><span class="cx">                                 BC857E8712B71EBB00EDEB2E /* WebPageProxyMac.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -155,6 +155,7 @@
</span><span class="cx"> class WebWheelEvent;
</span><span class="cx"> struct AttributedString;
</span><span class="cx"> struct EditorState;
</span><ins>+struct InteractionInformationAtPosition;
</ins><span class="cx"> struct PrintInfo;
</span><span class="cx"> struct WebPageCreationParameters;
</span><span class="cx"> struct WebPreferencesStore;
</span><span class="lines">@@ -421,6 +422,8 @@
</span><span class="cx">     void insertText(const String&amp; text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd);
</span><span class="cx">     void setComposition(const String&amp; text, Vector&lt;WebCore::CompositionUnderline&gt; underlines, uint64_t selectionStart, uint64_t selectionEnd);
</span><span class="cx">     void confirmComposition();
</span><ins>+    void getPositionInformation(const WebCore::IntPoint&amp;, InteractionInformationAtPosition&amp;);
+    void requestPositionInformation(const WebCore::IntPoint&amp;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     NotificationPermissionRequestManager* notificationPermissionRequestManager();
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -53,6 +53,8 @@
</span><span class="cx">     InsertText(String text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
</span><span class="cx">     SetComposition(String text, Vector&lt;WebCore::CompositionUnderline&gt; underlines, uint64_t selectionStart, uint64_t selectionEnd)
</span><span class="cx">     ConfirmComposition()
</span><ins>+    GetPositionInformation(WebCore::IntPoint point) -&gt; (WebKit::InteractionInformationAtPosition information)
+    RequestPositionInformation(WebCore::IntPoint point)
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(TOUCH_EVENTS)
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (162102 => 162103)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-01-16 00:27:01 UTC (rev 162102)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-01-16 00:52:47 UTC (rev 162103)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #import &quot;WebPage.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #import &quot;EditorState.h&quot;
</span><ins>+#import &quot;InteractionInformationAtPosition.h&quot;
</ins><span class="cx"> #import &quot;WebChromeClient.h&quot;
</span><span class="cx"> #import &quot;WebCoreArgumentCoders.h&quot;
</span><span class="cx"> #import &quot;WebFrame.h&quot;
</span><span class="lines">@@ -41,11 +42,15 @@
</span><span class="cx"> #import &lt;WebCore/FloatQuad.h&gt;
</span><span class="cx"> #import &lt;WebCore/Frame.h&gt;
</span><span class="cx"> #import &lt;WebCore/FrameView.h&gt;
</span><ins>+#import &lt;WebCore/HitTestResult.h&gt;
+#import &lt;WebCore/HTMLElementTypeHelpers.h&gt;
</ins><span class="cx"> #import &lt;WebCore/MainFrame.h&gt;
</span><ins>+#import &lt;WebCore/Node.h&gt;
</ins><span class="cx"> #import &lt;WebCore/NotImplemented.h&gt;
</span><span class="cx"> #import &lt;WebCore/Page.h&gt;
</span><span class="cx"> #import &lt;WebCore/PlatformKeyboardEvent.h&gt;
</span><span class="cx"> #import &lt;WebCore/PlatformMouseEvent.h&gt;
</span><ins>+#import &lt;WebCore/RenderImage.h&gt;
</ins><span class="cx"> #import &lt;WebCore/SharedBuffer.h&gt;
</span><span class="cx"> #import &lt;WebCore/TextIterator.h&gt;
</span><span class="cx"> #import &lt;WebCore/VisibleUnits.h&gt;
</span><span class="lines">@@ -378,13 +383,8 @@
</span><span class="cx">     Frame&amp; frame = m_page-&gt;focusController().focusedOrMainFrame();
</span><span class="cx">     FloatPoint adjustedPoint(point);
</span><span class="cx">     Node* node = frame.nodeRespondingToClickEvents(FloatPoint(point), adjustedPoint);
</span><del>-    if (node &amp;&amp; node != m_assistedNode.get()) {
-        handleTap(IntPoint(adjustedPoint));
-        if (!m_assistedNode) {
-            send(Messages::WebPageProxy::GestureCallback(point, gestureType, gestureState, 0, callbackID));
-            return;
-        }
-    }
</del><ins>+    ASSERT(!node || node &amp;&amp; node == m_assistedNode.get());
+
</ins><span class="cx">     IntPoint constrainedPoint = constrainPoint(point, &amp;frame, m_assistedNode.get());
</span><span class="cx">     VisiblePosition position = frame.visiblePositionForPoint(constrainedPoint);
</span><span class="cx">     if (position.isNull()) {
</span><span class="lines">@@ -803,6 +803,49 @@
</span><span class="cx">     computeAutocorrectionContext(m_page-&gt;focusController().focusedOrMainFrame(), contextBefore, markedText, selectedText, contextAfter, location, length);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::getPositionInformation(const IntPoint&amp; point, InteractionInformationAtPosition&amp; info)
+{
+    FloatPoint adjustedPoint;
+    Node* hitNode = m_page-&gt;mainFrame().nodeRespondingToClickEvents(point, adjustedPoint);
+
+    info.point = point;
+    info.nodeAtPositionIsAssistedNode = (hitNode == m_assistedNode);
+    if (hitNode) {
+        info.clickableElementName = hitNode-&gt;nodeName();
+
+        const HTMLElement* element = toHTMLElement(hitNode);
+        if (!element)
+            return;
+
+        if (element-&gt;renderer() &amp;&amp; element-&gt;renderer()-&gt;isImage()) {
+            URL url = toRenderImage(element-&gt;renderer())-&gt;cachedImage()-&gt;url();
+            if (!url.string().isNull())
+                info.url = url.string();
+        } else if (element-&gt;isLink())
+            info.url = element-&gt;getAttribute(HTMLNames::hrefAttr).string();
+    } else {
+        Frame&amp; frame = m_page-&gt;mainFrame();
+        hitNode = frame.eventHandler().hitTestResultAtPoint((point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent).innerNode();
+        if (hitNode-&gt;isTextNode()) {
+            VisiblePosition position = frame.visiblePositionForPoint(point);
+            RefPtr&lt;Range&gt; range = wordRangeFromPosition(position);
+            if (range)
+                range-&gt;collectSelectionRects(info.selectionRects);
+        } else {
+            // FIXME: implement the logic for the block selection.
+        }
+
+    }
+}
+
+void WebPage::requestPositionInformation(const IntPoint&amp; point)
+{
+    InteractionInformationAtPosition info;
+
+    getPositionInformation(point, info);
+    send(Messages::WebPageProxy::DidReceivePositionInformation(info));
+}
+
</ins><span class="cx"> void WebPage::elementDidFocus(WebCore::Node* node)
</span><span class="cx"> {
</span><span class="cx">     m_assistedNode = node;
</span></span></pre>
</div>
</div>

</body>
</html>