<!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>[185341] trunk</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>Mouse release on AutoFill button activates it; should only activate on click
https://bugs.webkit.org/show_bug.cgi?id=145774
&lt;rdar://problem/21069245&gt;

Reviewed by Ryosuke Niwa.

Source/WebCore:

Fixes an issue where a click event was dispatched to a shadow tree node regardless of whether
both the mouse press and mouse release were targeted at it. In particular, releasing the mouse
on the AutoFill button activates it regardless of whether the mouse was pressed on it.

Currently we always dispatch a click event to a node n where the mouse was released when n is
in a shadow tree regardless of whether the mouse was pressed on n. Instead we should only
dispatch a click event to n if the mouse was pressed and released on n. If n is a shadow tree
descendant, the mouse was released on n, and n never received a mouse press then we should
dispatch the click event at the shadow host element of n to preserve the illusion to web
developers that the shadow host element is a single element.

Test: fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html

* page/EventHandler.cpp:
(WebCore::targetNodeForClickEvent): Added; returns the target node for the DOM click event.
(WebCore::EventHandler::handleMouseReleaseEvent): Modified to use dispatch the DOM click event
at the node returned by targetNodeForClickEvent().
(WebCore::mouseIsReleasedOnPressedElement): Deleted.

LayoutTests:

Add test to ensure we only dispatch a click event at the HTML input element when pressing
on the editable portion of the input element and releasing the mouse on the AutoFill button.

* fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button-expected.txt: Added.
* fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlercpp">trunk/Source/WebCore/page/EventHandler.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastformsautofillbuttonmousedowninputmousereleaseautofillbuttonexpectedtxt">trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastformsautofillbuttonmousedowninputmousereleaseautofillbuttonhtml">trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (185340 => 185341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-06-09 00:21:05 UTC (rev 185340)
+++ trunk/LayoutTests/ChangeLog        2015-06-09 00:23:45 UTC (rev 185341)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2015-06-08  Daniel Bates  &lt;dabates@apple.com&gt;
+
+        Mouse release on AutoFill button activates it; should only activate on click
+        https://bugs.webkit.org/show_bug.cgi?id=145774
+        &lt;rdar://problem/21069245&gt;
+
+        Reviewed by Ryosuke Niwa.
+
+        Add test to ensure we only dispatch a click event at the HTML input element when pressing
+        on the editable portion of the input element and releasing the mouse on the AutoFill button.
+
+        * fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button-expected.txt: Added.
+        * fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html: Added.
+
</ins><span class="cx"> 2015-06-08  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix up the layouttest situation after r185322.
</span></span></pre></div>
<a id="trunkLayoutTestsfastformsautofillbuttonmousedowninputmousereleaseautofillbuttonexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button-expected.txt (0 => 185341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button-expected.txt        2015-06-09 00:23:45 UTC (rev 185341)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+This test checks that pressing the mouse in an password field and releasing the mouse on the AutoFill button dispatches a DOM click event at the password field and not at the AutoFill button. This test can only be run in the test tool.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+
+PASS event.type is &quot;click&quot;
+PASS event.target is document.getElementById(&quot;password&quot;)
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastformsautofillbuttonmousedowninputmousereleaseautofillbuttonhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html (0 => 185341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html                                (rev 0)
+++ trunk/LayoutTests/fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html        2015-06-09 00:23:45 UTC (rev 185341)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/common.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+window.jsTestIsAsync = true;
+
+var password;
+var event;
+
+window.onload = function ()
+{
+    password = document.getElementById(&quot;password&quot;);
+    password.onclick = checkEventAndDone;
+
+    runTest();
+};
+
+function runTest()
+{
+    if (!window.internals || !window.eventSender)
+        return;
+
+    internals.setShowAutoFillButton(password, true);
+
+    var autoFillButton = getElementByPseudoId(internals.shadowRoot(password), &quot;-webkit-auto-fill-button&quot;);
+    autoFillButton.onclick = checkEventAndDone;
+
+    eventSender.mouseMoveTo(password.offsetLeft + 10, password.offsetTop + password.offsetHeight / 2);
+    eventSender.mouseDown();
+    eventSender.leapForward(100);
+    eventSender.mouseMoveTo(autoFillButton.offsetLeft + autoFillButton.offsetWidth / 2, autoFillButton.offsetTop + autoFillButton.offsetHeight / 2);
+    eventSender.mouseUp();
+}
+
+function checkEventAndDone(e)
+{
+    event = e;
+    shouldBeEqualToString(&quot;event.type&quot;, &quot;click&quot;);
+    shouldBe(&quot;event.target&quot;, 'document.getElementById(&quot;password&quot;)');
+    finishJSTest();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;p id=&quot;description&quot;&gt;&lt;/p&gt;
+&lt;input type=&quot;password&quot; id=&quot;password&quot;&gt;
+&lt;div id=&quot;console&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+description(&quot;This test checks that pressing the mouse in an password field and releasing the mouse on the AutoFill &quot; +
+            &quot;button dispatches a DOM click event at the password field and not at the AutoFill button. This test &quot; +
+            &quot;can only be run in the test tool.&quot;);
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (185340 => 185341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-06-09 00:21:05 UTC (rev 185340)
+++ trunk/Source/WebCore/ChangeLog        2015-06-09 00:23:45 UTC (rev 185341)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-06-08  Daniel Bates  &lt;dabates@apple.com&gt;
+
+        Mouse release on AutoFill button activates it; should only activate on click
+        https://bugs.webkit.org/show_bug.cgi?id=145774
+        &lt;rdar://problem/21069245&gt;
+
+        Reviewed by Ryosuke Niwa.
+
+        Fixes an issue where a click event was dispatched to a shadow tree node regardless of whether
+        both the mouse press and mouse release were targeted at it. In particular, releasing the mouse
+        on the AutoFill button activates it regardless of whether the mouse was pressed on it.
+
+        Currently we always dispatch a click event to a node n where the mouse was released when n is
+        in a shadow tree regardless of whether the mouse was pressed on n. Instead we should only
+        dispatch a click event to n if the mouse was pressed and released on n. If n is a shadow tree
+        descendant, the mouse was released on n, and n never received a mouse press then we should
+        dispatch the click event at the shadow host element of n to preserve the illusion to web
+        developers that the shadow host element is a single element.
+
+        Test: fast/forms/auto-fill-button/mouse-down-input-mouse-release-auto-fill-button.html
+
+        * page/EventHandler.cpp:
+        (WebCore::targetNodeForClickEvent): Added; returns the target node for the DOM click event.
+        (WebCore::EventHandler::handleMouseReleaseEvent): Modified to use dispatch the DOM click event
+        at the node returned by targetNodeForClickEvent().
+        (WebCore::mouseIsReleasedOnPressedElement): Deleted.
+
</ins><span class="cx"> 2015-06-08  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebContent crash in WebCore::Page::sessionID() const + 0 (Page.cpp:1660)
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.cpp (185340 => 185341)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EventHandler.cpp        2015-06-09 00:21:05 UTC (rev 185340)
+++ trunk/Source/WebCore/page/EventHandler.cpp        2015-06-09 00:23:45 UTC (rev 185341)
</span><span class="lines">@@ -2037,28 +2037,22 @@
</span><span class="cx">     m_clickNode = nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline static bool mouseIsReleasedOnPressedElement(Node* targetNode, Node* clickNode)
</del><ins>+static Node* targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNode)
</ins><span class="cx"> {
</span><del>-    if (targetNode == clickNode)
-        return true;
</del><ins>+    if (!mousePressNode || !mouseReleaseNode)
+        return nullptr;
</ins><span class="cx"> 
</span><del>-    if (!targetNode)
-        return false;
</del><ins>+    if (mousePressNode == mouseReleaseNode)
+        return mouseReleaseNode;
</ins><span class="cx"> 
</span><del>-    ShadowRoot* containingShadowRoot = targetNode-&gt;containingShadowRoot();
-    if (!containingShadowRoot)
-        return false;
-
-    // FIXME: When an element in UA ShadowDOM (e.g. inner element in &lt;input&gt;) is clicked,
-    // we assume that the host element is clicked. This is necessary for implementing &lt;input type=&quot;range&quot;&gt; etc.
-    // However, we should not check ShadowRoot type basically.
-    // https://bugs.webkit.org/show_bug.cgi?id=108047
-    if (containingShadowRoot-&gt;type() != ShadowRoot::UserAgentShadowRoot)
-        return false;
-
-    Node* adjustedTargetNode = targetNode-&gt;shadowHost();
-    Node* adjustedClickNode = clickNode ? clickNode-&gt;shadowHost() : 0;
-    return adjustedTargetNode == adjustedClickNode;
</del><ins>+    Element* mouseReleaseShadowHost = mouseReleaseNode-&gt;shadowHost();
+    if (mouseReleaseShadowHost &amp;&amp; mouseReleaseShadowHost == mousePressNode-&gt;shadowHost()) {
+        // We want to dispatch the click to the shadow tree host element to give listeners the illusion that the
+        // shadom tree is a single element. For example, we want to give the illusion that &lt;input type=&quot;range&quot;&gt;
+        // is a single element even though it is a composition of multiple shadom tree elements.
+        return mouseReleaseShadowHost;
+    }
+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent&amp; platformMouseEvent)
</span><span class="lines">@@ -2122,7 +2116,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool contextMenuEvent = platformMouseEvent.button() == RightButton;
</span><span class="cx"> 
</span><del>-    bool swallowClickEvent = m_clickCount &gt; 0 &amp;&amp; !contextMenuEvent &amp;&amp; mouseIsReleasedOnPressedElement(mouseEvent.targetNode(), m_clickNode.get()) &amp;&amp; !dispatchMouseEvent(eventNames().clickEvent, mouseEvent.targetNode(), true, m_clickCount, platformMouseEvent, true);
</del><ins>+    Node* nodeToClick = targetNodeForClickEvent(m_clickNode.get(), mouseEvent.targetNode());
+    bool swallowClickEvent = m_clickCount &gt; 0 &amp;&amp; !contextMenuEvent &amp;&amp; nodeToClick &amp;&amp; !dispatchMouseEvent(eventNames().clickEvent, nodeToClick, true, m_clickCount, platformMouseEvent, true);
</ins><span class="cx"> 
</span><span class="cx">     if (m_resizeLayer) {
</span><span class="cx">         m_resizeLayer-&gt;setInResizeMode(false);
</span></span></pre>
</div>
</div>

</body>
</html>