Skip to content
Permalink
Browse files
[iOS] DOM click event may not be dispatched when page has :active sty…
…le and <input type="search">

https://bugs.webkit.org/show_bug.cgi?id=144451
<rdar://problem/23099482>

Patch by Daniel Bates <dabates@apple.com> on 2015-12-14
Reviewed by Simon Fraser.

Source/WebCore:

Fixes an issue where a DOM click event is not dispatched to an element in a subframe on a page
that has a <input type="search"> and defines a CSS :active pseudo-class for the HTML body element.

On iOS we only dispatch a DOM click event if the content of the page does not change as part of
dispatching a DOM mousemove event at the tapped element as a means of providing a good user
experience on web pages that reveal or hide content based on mouse hover. Currently we consider
the content of the page to have changed if the visibility of any element on the page changes.
In particular we consider the content of the page to have changed if the visibility of a user
agent shadow DOM element changes (e.g. the search field cancel button). Instead we should only
consider visibility changes to the actual web page content and ignore visibility changes to
user agent shadow DOM elements.

Tests: fast/events/can-click-element-on-page-with-active-pseudo-class-and-search-field.html
       fast/forms/search/search-cancel-button-visible-when-input-becomes-disabled.html
       fast/forms/search/search-cancel-button-visible-when-input-becomes-readonly.html
       fast/forms/search/search-cancel-in-formerly-invisible-element.html
       fast/forms/search/search-cancel-toggle-visibility-initially-hidden.html
       fast/forms/search/search-cancel-toggle-visibility-initially-visible.html

* style/StyleResolveTree.cpp:
(WebCore::Style::CheckForVisibilityChangeOnRecalcStyle::~CheckForVisibilityChangeOnRecalcStyle):
Ignore visibility changes to user agent shadow DOM elements.

LayoutTests:

Add a test to ensure that a DOM click event is dispatched to an element in a subframe on a page
with a search field and that specifies a CSS :active pseudo-class that changes the tap highlight
color.

Additionally, add tests to ensure we update the cancel button visibility whenever the visibility
of the search field changes.

* fast/events/can-click-element-on-page-with-active-pseudo-class-and-search-field-expected.txt: Added.
* fast/events/can-click-element-on-page-with-active-pseudo-class-and-search-field.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-disabled-expected.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-disabled.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-readonly-expected.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-readonly.html: Added.
* fast/forms/search/search-cancel-in-formerly-invisible-element-expected.html: Added.
* fast/forms/search/search-cancel-in-formerly-invisible-element.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-hidden-expected.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-hidden.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-visible-expected.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-visible.html: Added.

Canonical link: https://commits.webkit.org/170360@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@194038 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
dydz authored and webkit-commit-queue committed Dec 14, 2015
1 parent 999f49f commit 70bc0584644420f735bfedc4a1e7a6eb580b571b
Showing 15 changed files with 309 additions and 0 deletions.
@@ -1,3 +1,31 @@
2015-12-14 Daniel Bates <dabates@apple.com>

[iOS] DOM click event may not be dispatched when page has :active style and <input type="search">
https://bugs.webkit.org/show_bug.cgi?id=144451
<rdar://problem/23099482>

Reviewed by Simon Fraser.

Add a test to ensure that a DOM click event is dispatched to an element in a subframe on a page
with a search field and that specifies a CSS :active pseudo-class that changes the tap highlight
color.

Additionally, add tests to ensure we update the cancel button visibility whenever the visibility
of the search field changes.

* fast/events/can-click-element-on-page-with-active-pseudo-class-and-search-field-expected.txt: Added.
* fast/events/can-click-element-on-page-with-active-pseudo-class-and-search-field.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-disabled-expected.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-disabled.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-readonly-expected.html: Added.
* fast/forms/search/search-cancel-button-visible-when-input-becomes-readonly.html: Added.
* fast/forms/search/search-cancel-in-formerly-invisible-element-expected.html: Added.
* fast/forms/search/search-cancel-in-formerly-invisible-element.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-hidden-expected.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-hidden.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-visible-expected.html: Added.
* fast/forms/search/search-cancel-toggle-visibility-initially-visible.html: Added.

2015-12-14 Chris Dumez <cdumez@apple.com>

Roll out r193974 and follow-up fixes as it caused JSC crashes
@@ -0,0 +1,9 @@
Test that an element, with an onclick handler and an empty ontouchstart attribute, in an <iframe> on a page with a search field and specifies an :active pseudo-class for <body> receives a DOM click event when tapped. To run this test by hand, click the blue square below.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

PASS clicked blue square
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
<style>
body:active {
/* Must be non-empty. */
-webkit-tap-highlight-color: yellow;
}
</style>
<script>
window.jsTestIsAsync = true;

function notifyPass()
{
testPassed("clicked blue square");

var testContainer = document.getElementById("test-container");
testContainer.parentNode.removeChild(testContainer);
finishJSTest();
}

function runTest()
{
if (!window.testRunner)
return;
var iframe = document.getElementById("iframe");
var square = iframe.contentDocument.getElementById("square");
var x = iframe.offsetLeft + square.offsetLeft + Math.floor(square.offsetWidth / 2);
var y = iframe.offsetTop + square.offsetTop + Math.floor(square.offsetHeight / 2);
if (testRunner.runUIScript && window.TouchEvent)
testRunner.runUIScript("(function() { uiController.singleTapAtPoint(" + x + ", " + y + "); })()");
else if (window.eventSender) {
eventSender.mouseMoveTo(x, y);
eventSender.mouseDown();
eventSender.mouseUp();
}
}
</script>
</head>
<body>
<div id="description"></div>
<div id="test-container">
<p><input type="search" placeholder="Do not click me"></p>
<iframe id="iframe" width="128" height="128" onload="runTest()" srcdoc='
<style>
body {
margin: 0;
padding 0;
}
#square {
-webkit-box-align: center;
-webkit-box-pack: center;
-webkit-user-select: none;
background-color: blue;
color: white;
cursor: pointer;
display: -webkit-box;
height: 128px;
width: 128px;
}
</style>
<div id="square" ontouchstart="" onclick="window.parent.notifyPass()">Click me</div><!-- Intentionally empty attribute ontouchstart. -->
'></iframe>
</div>
<div id="console"></div>
<script>
description("Test that an element, with an onclick handler and an empty ontouchstart attribute, in an &lt;iframe&gt; on a page with a search field and specifies an <code>:active</code> pseudo-class for &lt;body&gt; receives a DOM click event when tapped. To run this test by hand, click the blue square below.");
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<body>
<p>This tests that the search cancel button renders when the field becomes disabled (no change).</p>
<input type="search" value="search" disabled>
</body>
</html>
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<body>
<p>This tests that the search cancel button renders when the field becomes disabled (no change).</p>
<input type="search" id="search" value="search">
<script>
if (window.testRunner)
testRunner.waitUntilDone();

var search = document.getElementById("search");

function makeFieldDisabledAndNotifyDone()
{
search.disabled = true;
if (window.internals)
internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
if (window.testRunner)
testRunner.notifyDone();
}

window.setTimeout(makeFieldDisabledAndNotifyDone, 0);
</script>
</body>
</html>
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<body>
<p>This tests that the search cancel button renders when the field becomes read only (no change).</p>
<input type="search" value="search" readonly>
</body>
</html>
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<body>
<p>This tests that the search cancel button renders when the field becomes read only (no change).</p>
<input type="search" id="search" value="search">
<script>
if (window.testRunner)
testRunner.waitUntilDone();

var search = document.getElementById("search");

function makeFieldReadOnlyAndNotifyDone()
{
search.readOnly = true;
if (window.internals)
internals.updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks();
if (window.testRunner)
testRunner.notifyDone();
}

window.setTimeout(makeFieldReadOnlyAndNotifyDone, 0);
</script>
</body>
</html>
@@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<input type="search" value="search">
</body>
</html>
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<body>
<input type="search" id="search" value="search" style="visibility: hidden">
<script>
document.getElementById("search").style.visibility = "visible";
</script>
</body>
</html>
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<style>
.width-200px {
width: 200px;
}
</style>
<body>
<p>Tests that the search cancel button is not shown after changing the visibility of &lt;input type=&quot;search&quot;&gt; from hidden to visible to hidden. This test passed if you do not see the search cancel button in the blue outlined box (below).</p>
<div class="width-200px" style="border: 1px solid blue">
<input type="search" value="search" class="width-200px" style="visibility: hidden">
</div>
</body>
</html>
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<style>
.width-200px {
width: 200px;
}
</style>
<script>
if (window.testRunner)
testRunner.waitUntilDone();
</script>
</head>
<body>
<p>Tests that the search cancel button is not shown after changing the visibility of &lt;input type=&quot;search&quot;&gt; from hidden to visible to hidden. This test passed if you do not see the search cancel button in the blue outlined box (below).</p>
<div class="width-200px" style="border: 1px solid blue">
<input type="search" id="search" value="search" class="width-200px" style="visibility: hidden">
</div>
<script>
var search = document.getElementById("search");
search.style.visibility = "visible";
function done() {
search.style.visibility = "hidden";
if (window.testRunner)
testRunner.notifyDone();
}
window.setTimeout(done, 0);
</script>
</body>
</html>
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<style>
.width-200px {
width: 200px;
}
</style>
<body>
<p>Tests that the search cancel button is not shown after changing the visibility of &lt;input type=&quot;search&quot;&gt; from visible to hidden to visible. This test passed if you see the search cancel button in the blue outlined box (below).</p>
<div class="width-200px" style="border: 1px solid blue">
<input type="search" value="search" class="width-200px">
</div>
</body>
</html>
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<style>
.width-200px {
width: 200px;
}
</style>
<script>
if (window.testRunner)
testRunner.waitUntilDone();
</script>
</head>
<body>
<p>Tests that the search cancel button is not shown after changing the visibility of &lt;input type=&quot;search&quot;&gt; from visible to hidden to visible. This test passed if you see the search cancel button in the blue outlined box (below).</p>
<div class="width-200px" style="border: 1px solid blue">
<input type="search" id="search" value="search" class="width-200px">
</div>
<script>
var search = document.getElementById("search");
search.style.visibility = "hidden";
function done() {
search.style.visibility = "visible";
if (window.testRunner)
testRunner.notifyDone();
}
window.setTimeout(done, 0);
</script>
</body>
</html>
@@ -1,3 +1,34 @@
2015-12-14 Daniel Bates <dabates@apple.com>

[iOS] DOM click event may not be dispatched when page has :active style and <input type="search">
https://bugs.webkit.org/show_bug.cgi?id=144451
<rdar://problem/23099482>

Reviewed by Simon Fraser.

Fixes an issue where a DOM click event is not dispatched to an element in a subframe on a page
that has a <input type="search"> and defines a CSS :active pseudo-class for the HTML body element.

On iOS we only dispatch a DOM click event if the content of the page does not change as part of
dispatching a DOM mousemove event at the tapped element as a means of providing a good user
experience on web pages that reveal or hide content based on mouse hover. Currently we consider
the content of the page to have changed if the visibility of any element on the page changes.
In particular we consider the content of the page to have changed if the visibility of a user
agent shadow DOM element changes (e.g. the search field cancel button). Instead we should only
consider visibility changes to the actual web page content and ignore visibility changes to
user agent shadow DOM elements.

Tests: fast/events/can-click-element-on-page-with-active-pseudo-class-and-search-field.html
fast/forms/search/search-cancel-button-visible-when-input-becomes-disabled.html
fast/forms/search/search-cancel-button-visible-when-input-becomes-readonly.html
fast/forms/search/search-cancel-in-formerly-invisible-element.html
fast/forms/search/search-cancel-toggle-visibility-initially-hidden.html
fast/forms/search/search-cancel-toggle-visibility-initially-visible.html

* style/StyleResolveTree.cpp:
(WebCore::Style::CheckForVisibilityChangeOnRecalcStyle::~CheckForVisibilityChangeOnRecalcStyle):
Ignore visibility changes to user agent shadow DOM elements.

2015-12-14 Youenn Fablet <youenn.fablet@crf.canon.fr>

[Streams API] Directly use @then as much as possible
@@ -757,6 +757,8 @@ class CheckForVisibilityChangeOnRecalcStyle {
{
if (!WKObservingContentChanges())
return;
if (m_element->isInUserAgentShadowTree())
return;
RenderStyle* style = m_element->renderStyle();
if (!style)
return;

0 comments on commit 70bc058

Please sign in to comment.