Title: [137220] trunk
Revision
137220
Author
[email protected]
Date
2012-12-10 16:08:09 -0800 (Mon, 10 Dec 2012)

Log Message

Sending multi-touch events to the same Iframe
https://bugs.webkit.org/show_bug.cgi?id=97973

Patch by Min Qin <[email protected]> on 2012-12-10
Reviewed by Dimitri Glazkov.

Source/WebCore:

Multi-Touch in different iframe can give both documents access to each other.
This could cause cross-origin access. To solve this, all the touch events should
be sent to the iframe where the first touchstart happens.

Test: fast/events/touch/multi-touch-inside-iframes.html
      fast/events/touch/multi-touch-inside-nested-iframes.html

* page/EventHandler.cpp:
(WebCore::EventHandler::handleTouchEvent):
* page/EventHandler.h:

LayoutTests:

Check that all multi-touch events are sent to the same iframe.

* fast/events/touch/multi-touch-inside-iframes-expected.txt: Added.
* fast/events/touch/multi-touch-inside-iframes.html: Added.
* fast/events/touch/resources/multi-touch-inside-iframes2.html: Added.
* fast/events/touch/multi-touch-inside-nested-iframes-expected.txt: Added.
* fast/events/touch/multi-touch-inside-nested-iframes.html: Added.
* fast/events/touch/resources/multi-touch-inside-nested-iframes2.html: Added.
* fast/events/touch/resources/multi-touch-inside-nested-iframes3.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (137219 => 137220)


--- trunk/LayoutTests/ChangeLog	2012-12-10 23:56:02 UTC (rev 137219)
+++ trunk/LayoutTests/ChangeLog	2012-12-11 00:08:09 UTC (rev 137220)
@@ -1,3 +1,20 @@
+2012-12-10  Min Qin  <[email protected]>
+
+        Sending multi-touch events to the same Iframe
+        https://bugs.webkit.org/show_bug.cgi?id=97973
+
+        Reviewed by Dimitri Glazkov.
+
+        Check that all multi-touch events are sent to the same iframe.
+
+        * fast/events/touch/multi-touch-inside-iframes-expected.txt: Added.
+        * fast/events/touch/multi-touch-inside-iframes.html: Added.
+        * fast/events/touch/resources/multi-touch-inside-iframes2.html: Added.
+        * fast/events/touch/multi-touch-inside-nested-iframes-expected.txt: Added.
+        * fast/events/touch/multi-touch-inside-nested-iframes.html: Added.
+        * fast/events/touch/resources/multi-touch-inside-nested-iframes2.html: Added.
+        * fast/events/touch/resources/multi-touch-inside-nested-iframes3.html: Added.
+
 2012-12-10  Simon Fraser  <[email protected]>
 
         When converting a layer into a tiled layer, ensure that we update the visible rect

Added: trunk/LayoutTests/fast/events/touch/multi-touch-inside-iframes-expected.txt (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/multi-touch-inside-iframes-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/multi-touch-inside-iframes-expected.txt	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,70 @@
+
+Test multi-touch is sent to the same iframe.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+First touch is on iframe1.
+PASS document.elementFromPoint(101, 101).id is "iframe1"
+PASS ev.type is "touchstart"
+PASS touchreceiver is "iframe1"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 1
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 50
+PASS ev.touches[0].pageY is 50
+PASS ev.touches[0].target.ownerDocument.title is "iframe1"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe1"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe1"
+
+Second touch is on iframe2, nothing should happen.
+PASS document.elementFromPoint(251, 101).id is "iframe2"
+
+Moves the first touch outside iframe1.
+PASS ev.type is "touchmove"
+PASS touchreceiver is "iframe1"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 1
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 150
+PASS ev.touches[0].pageY is 150
+PASS ev.touches[0].target.ownerDocument.title is "iframe1"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe1"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe1"
+
+Release the first touch.
+PASS ev.type is "touchend"
+PASS touchreceiver is "iframe1"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 0
+PASS ev.targetTouches.length is 0
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe1"
+
+Third touch is on iframe2, nothing should happen.
+PASS document.elementFromPoint(261, 101).id is "iframe2"
+
+Release all touches on iframe2, and touch iframe2 again.
+PASS ev.type is "touchstart"
+PASS touchreceiver is "iframe2"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 1
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 50
+PASS ev.touches[0].pageY is 50
+PASS ev.touches[0].target.ownerDocument.title is "iframe2"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe2"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe2"
+
+Touch iframe1, nothing shoud happen.
+
+Release all touches.
+PASS ev.type is "touchend"
+PASS touchreceiver is "iframe2"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 0
+PASS ev.targetTouches.length is 0
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe2"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/events/touch/multi-touch-inside-iframes.html (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/multi-touch-inside-iframes.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/multi-touch-inside-iframes.html	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,173 @@
+<html>
+<script src=""
+<style>
+iframe {
+  width: 100px;
+  height: 100px;
+  margin: 0;
+  padding: 0;
+  border: 1px solid black;
+}
+
+#iframe1
+{
+position:absolute;
+left:50px;
+top:50px;
+}
+
+#iframe2
+{
+position:absolute;
+left:200px;
+top:50px;
+}
+
+#output
+{
+position:absolute;
+top:150px;
+}
+
+</style>
+<body _onload_="runTest()">
+<iframe id="iframe1" src=""
+<iframe id="iframe2" src=""
+<div id="output">
+<p id="description"></p>
+<div id="console"></div>
+</div>
+<script type="text/_javascript_">
+description('Test multi-touch is sent to the same iframe.');
+
+var touchEventCount = 0;
+var title = 0;
+
+function onTouch(event, receiver)
+{
+    ev = event;
+    touchreceiver = receiver;
+    switch (touchEventCount) {
+        case 0:
+            shouldBeEqualToString('ev.type', 'touchstart');
+            shouldBeEqualToString('touchreceiver', 'iframe1');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "1");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "50");
+            shouldBe("ev.touches[0].pageY", "50");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe1');
+            break;
+        case 1:
+            shouldBeEqualToString('ev.type', 'touchmove');
+            shouldBeEqualToString('touchreceiver', 'iframe1');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "1");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "150");
+            shouldBe("ev.touches[0].pageY", "150");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe1');
+            break;
+        case 2:
+            shouldBeEqualToString('ev.type', 'touchend');
+            shouldBeEqualToString('touchreceiver', 'iframe1');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "0");
+            shouldBe("ev.targetTouches.length", "0");
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe1');
+            break;
+        case 3:
+            shouldBeEqualToString('ev.type', 'touchstart');
+            shouldBeEqualToString('touchreceiver', 'iframe2');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "1");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "50");
+            shouldBe("ev.touches[0].pageY", "50");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe2');
+            break;
+        case 4:
+            shouldBeEqualToString('ev.type', 'touchend');
+            shouldBeEqualToString('touchreceiver', 'iframe2');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "0");
+            shouldBe("ev.targetTouches.length", "0");
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe2');
+            isSuccessfullyParsed();
+            testRunner.notifyDone();
+    }
+    touchEventCount++;
+}
+
+function runTest() {
+    if (window.eventSender) {
+        eventSender.clearTouchPoints();
+        // Touch the center of iframe1. 50px is offset to iframe1 in main frame,
+        // 1px for the iframe border, 50px to get to centre.
+        debug('First touch is on iframe1.');
+        shouldBeEqualToString('document.elementFromPoint(101, 101).id', 'iframe1');
+        eventSender.addTouchPoint(101, 101);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Second touch is on iframe2, nothing should happen.');
+        shouldBeEqualToString('document.elementFromPoint(251, 101).id', 'iframe2');
+        eventSender.addTouchPoint(251, 101);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Moves the first touch outside iframe1.');
+        eventSender.updateTouchPoint(0, 201, 201);
+        eventSender.touchMove();
+        debug('');
+
+        debug('Release the first touch.');
+        eventSender.releaseTouchPoint(0);
+        eventSender.touchEnd();
+        debug('');
+
+        debug('Third touch is on iframe2, nothing should happen.');
+        shouldBeEqualToString('document.elementFromPoint(261, 101).id', 'iframe2');
+        eventSender.addTouchPoint(261, 101);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Release all touches on iframe2, and touch iframe2 again.');
+        eventSender.releaseTouchPoint(0);
+        eventSender.releaseTouchPoint(1);
+        eventSender.touchEnd();
+        eventSender.addTouchPoint(251, 101);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Touch iframe1, nothing shoud happen.');
+        eventSender.addTouchPoint(101, 101);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Release all touches.');
+        eventSender.releaseTouchPoint(0);
+        eventSender.releaseTouchPoint(1);
+        eventSender.touchEnd();
+    } else {
+       debug('This test requires DRT.');
+    }
+}
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+}
+
+function getTitle() {
+    title++;
+    return  'iframe' + title;
+}
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/multi-touch-inside-nested-iframes-expected.txt (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/multi-touch-inside-nested-iframes-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/multi-touch-inside-nested-iframes-expected.txt	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,78 @@
+
+Test multi-touch is sent to the same iframe.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+First touch is on inner iframe.
+PASS ev.type is "touchstart"
+PASS touchreceiver is "iframe1"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 1
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 50
+PASS ev.touches[0].pageY is 50
+PASS ev.touches[0].target.ownerDocument.title is "iframe1"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe1"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe1"
+
+Second touch is on outer iframe, nothing should happen.
+
+Moves the first touch outside inner iframe.
+PASS ev.type is "touchmove"
+PASS touchreceiver is "iframe1"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 1
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 200
+PASS ev.touches[0].pageY is 200
+PASS ev.touches[0].target.ownerDocument.title is "iframe1"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe1"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe1"
+
+Release the first touch.
+PASS ev.type is "touchend"
+PASS touchreceiver is "iframe1"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 0
+PASS ev.targetTouches.length is 0
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe1"
+
+Third touch is on outer iframe, nothing should happen.
+
+Release all touches on outer iframe, and touch outer iframe again.
+PASS ev.type is "touchstart"
+PASS touchreceiver is "iframe2"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 1
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 30
+PASS ev.touches[0].pageY is 30
+PASS ev.touches[0].target.ownerDocument.title is "iframe2"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe2"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe2"
+
+Touch inner iframe, this will trigger onTouch as it is inside outer iframe.
+PASS ev.type is "touchstart"
+PASS touchreceiver is "iframe2"
+PASS ev.changedTouches.length is 1
+PASS ev.touches.length is 2
+PASS ev.targetTouches.length is 1
+PASS ev.touches[0].pageX is 30
+PASS ev.touches[0].pageY is 30
+PASS ev.touches[0].target.ownerDocument.title is "iframe2"
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe2"
+PASS ev.targetTouches[0].target.ownerDocument.title is "iframe2"
+
+Release all touches.
+PASS ev.type is "touchend"
+PASS touchreceiver is "iframe2"
+PASS ev.changedTouches.length is 2
+PASS ev.touches.length is 0
+PASS ev.targetTouches.length is 0
+PASS ev.changedTouches[0].target.ownerDocument.title is "iframe2"
+PASS ev.changedTouches[1].target.ownerDocument.title is "iframe2"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/events/touch/multi-touch-inside-nested-iframes.html (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/multi-touch-inside-nested-iframes.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/multi-touch-inside-nested-iframes.html	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,172 @@
+<html>
+<script src=""
+<style>
+#iframe1 {
+  width: 200px;
+  height: 200px;
+  margin: 0;
+  padding: 0;
+  border: 1px solid black;
+  position:absolute;
+  left:50px;
+  top:50px;
+  background: red;
+}
+
+#output
+{
+position:absolute;
+top:250px;
+}
+
+</style>
+<body _onload_="runTest()">
+<iframe id="iframe1" src=""
+<div id="output">
+<p id="description"></p>
+<div id="console"></div>
+</div>
+<script type="text/_javascript_">
+description('Test multi-touch is sent to the same iframe.');
+
+var touchEventCount = 0;
+var title = 0;
+
+function onTouch(event, receiver)
+{
+    ev = event;
+    touchreceiver = receiver;
+    switch (touchEventCount) {
+        case 0:
+            shouldBeEqualToString('ev.type', 'touchstart');
+            shouldBeEqualToString('touchreceiver', 'iframe1');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "1");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "50");
+            shouldBe("ev.touches[0].pageY", "50");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe1');
+            break;
+        case 1:
+            shouldBeEqualToString('ev.type', 'touchmove');
+            shouldBeEqualToString('touchreceiver', 'iframe1');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "1");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "200");
+            shouldBe("ev.touches[0].pageY", "200");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe1');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe1');
+            break;
+        case 2:
+            shouldBeEqualToString('ev.type', 'touchend');
+            shouldBeEqualToString('touchreceiver', 'iframe1');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "0");
+            shouldBe("ev.targetTouches.length", "0");
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe1');
+            break;
+        case 3:
+            shouldBeEqualToString('ev.type', 'touchstart');
+            shouldBeEqualToString('touchreceiver', 'iframe2');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "1");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "30");
+            shouldBe("ev.touches[0].pageY", "30");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe2');
+            break;
+        case 4:
+            shouldBeEqualToString('ev.type', 'touchstart');
+            shouldBeEqualToString('touchreceiver', 'iframe2');
+            shouldBe("ev.changedTouches.length", "1");
+            shouldBe("ev.touches.length", "2");
+            shouldBe("ev.targetTouches.length", "1");
+            shouldBe("ev.touches[0].pageX", "30");
+            shouldBe("ev.touches[0].pageY", "30");
+            shouldBeEqualToString('ev.touches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.targetTouches[0].target.ownerDocument.title', 'iframe2');
+            break;
+        case 5:
+            shouldBeEqualToString('ev.type', 'touchend');
+            shouldBeEqualToString('touchreceiver', 'iframe2');
+            shouldBe("ev.changedTouches.length", "2");
+            shouldBe("ev.touches.length", "0");
+            shouldBe("ev.targetTouches.length", "0");
+            shouldBeEqualToString('ev.changedTouches[0].target.ownerDocument.title', 'iframe2');
+            shouldBeEqualToString('ev.changedTouches[1].target.ownerDocument.title', 'iframe2');
+            isSuccessfullyParsed();
+            testRunner.notifyDone();
+    }
+    touchEventCount++;
+}
+
+function runTest() {
+    if (window.eventSender) {
+        eventSender.clearTouchPoints();
+        // Touch the center of innter iframe. 50px is offset to outer iframe in main frame,
+        // 2px for the iframe borders, 100px to get to centre.
+        debug('First touch is on inner iframe.');
+        eventSender.addTouchPoint(152, 152);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Second touch is on outer iframe, nothing should happen.');
+        eventSender.addTouchPoint(71, 71);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Moves the first touch outside inner iframe.');
+        eventSender.updateTouchPoint(0, 302, 302);
+        eventSender.touchMove();
+        debug('');
+
+        debug('Release the first touch.');
+        eventSender.releaseTouchPoint(0);
+        eventSender.touchEnd();
+        debug('');
+
+        debug('Third touch is on outer iframe, nothing should happen.');
+        eventSender.addTouchPoint(81, 81);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Release all touches on outer iframe, and touch outer iframe again.');
+        eventSender.releaseTouchPoint(0);
+        eventSender.releaseTouchPoint(1);
+        eventSender.touchEnd();
+        eventSender.addTouchPoint(81, 81);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Touch inner iframe, this will trigger onTouch as it is inside outer iframe.');
+        eventSender.addTouchPoint(152, 152);
+        eventSender.touchStart();
+        debug('');
+
+        debug('Release all touches.');
+        eventSender.releaseTouchPoint(0);
+        eventSender.releaseTouchPoint(1);
+        eventSender.touchEnd();
+    } else {
+       debug('This test requires DRT.');
+    }
+}
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+}
+
+function getTitle() {
+    title++;
+    return  'iframe' + title;
+}
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-iframes2.html (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-iframes2.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-iframes2.html	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,11 @@
+<html>
+<head>
+<script type='text/_javascript_'>
+document.addEventListener("touchstart", function() { parent.onTouch(event, document.title); }, false);
+document.addEventListener("touchend", function() { parent.onTouch(event, document.title); }, false);
+document.addEventListener("touchmove", function() { parent.onTouch(event, document.title); }, false);
+</script>
+</head>
+<body _onload_="document.title=parent.getTitle()">
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-nested-iframes2.html (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-nested-iframes2.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-nested-iframes2.html	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,26 @@
+<html>
+<html>
+<style>
+iframe {
+  width: 100px;
+  height: 100px;
+  margin: 0;
+  padding: 0;
+  border: 1px solid black;
+  position:absolute;
+  left:50px;
+  top:50px;
+  background: blue;
+}
+</style>
+<head>
+<script type='text/_javascript_'>
+document.addEventListener("touchstart", function() { parent.onTouch(event, document.title); }, false);
+document.addEventListener("touchend", function() { parent.onTouch(event, document.title); }, false);
+document.addEventListener("touchmove", function() { parent.onTouch(event, document.title); }, false);
+</script>
+</head>
+<body _onload_="document.title=parent.getTitle()">
+<iframe id="iframe2" src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-nested-iframes3.html (0 => 137220)


--- trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-nested-iframes3.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/touch/resources/multi-touch-inside-nested-iframes3.html	2012-12-11 00:08:09 UTC (rev 137220)
@@ -0,0 +1,11 @@
+<html>
+<head>
+<script type='text/_javascript_'>
+document.addEventListener("touchstart", function() { top.onTouch(event, document.title); }, false);
+document.addEventListener("touchend", function() { top.onTouch(event, document.title); }, false);
+document.addEventListener("touchmove", function() { top.onTouch(event, document.title); }, false);
+</script>
+</head>
+<body _onload_="document.title=top.getTitle()">
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (137219 => 137220)


--- trunk/Source/WebCore/ChangeLog	2012-12-10 23:56:02 UTC (rev 137219)
+++ trunk/Source/WebCore/ChangeLog	2012-12-11 00:08:09 UTC (rev 137220)
@@ -1,3 +1,21 @@
+2012-12-10  Min Qin  <[email protected]>
+
+        Sending multi-touch events to the same Iframe
+        https://bugs.webkit.org/show_bug.cgi?id=97973
+
+        Reviewed by Dimitri Glazkov.
+
+        Multi-Touch in different iframe can give both documents access to each other.
+        This could cause cross-origin access. To solve this, all the touch events should
+        be sent to the iframe where the first touchstart happens.
+
+        Test: fast/events/touch/multi-touch-inside-iframes.html
+              fast/events/touch/multi-touch-inside-nested-iframes.html
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleTouchEvent):
+        * page/EventHandler.h:
+
 2012-12-10  KyungTae Kim  <[email protected]>
 
         [soup] Fix build warning in ResourceHandleSoup.cpp

Modified: trunk/Source/WebCore/page/EventHandler.cpp (137219 => 137220)


--- trunk/Source/WebCore/page/EventHandler.cpp	2012-12-10 23:56:02 UTC (rev 137219)
+++ trunk/Source/WebCore/page/EventHandler.cpp	2012-12-11 00:08:09 UTC (rev 137220)
@@ -355,6 +355,7 @@
     , m_activationEventNumber(-1)
 #endif
 #if ENABLE(TOUCH_EVENTS)
+    , m_originatingTouchPointTargetKey(0)
     , m_touchPressed(false)
 #endif
     , m_maxMouseMovedDuration(0)
@@ -407,6 +408,8 @@
     m_previousWheelScrolledNode = 0;
 #if ENABLE(TOUCH_EVENTS)
     m_originatingTouchPointTargets.clear();
+    m_originatingTouchPointDocument.clear();
+    m_originatingTouchPointTargetKey = 0;
 #endif
 #if ENABLE(GESTURE_EVENTS)
     m_scrollGestureHandlingNode = 0;
@@ -3814,6 +3817,22 @@
     }
 }
 
+HitTestResult EventHandler::hitTestResultInFrame(Frame* frame, const LayoutPoint& point, HitTestRequest::HitTestRequestType hitType)
+{
+    HitTestResult result(point);
+
+    if (!frame || !frame->contentRenderer())
+        return result;
+    if (frame->view()) {
+        IntRect rect = frame->view()->visibleContentRect();
+        if (!rect.contains(roundedIntPoint(point)))
+            return result;
+    }
+    frame->contentRenderer()->hitTest(HitTestRequest(hitType), result);
+    result.setToNonShadowAncestor();
+    return result;
+}
+
 bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
 {
     // First build up the lists to use for the 'touches', 'targetTouches' and 'changedTouches' attributes
@@ -3841,8 +3860,19 @@
 
     UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
 
-    for (unsigned i = 0; i < points.size(); ++i) {
+    unsigned i;
+    bool freshTouchEvents = true;
+    bool allTouchReleased = true;
+    for (i = 0; i < points.size(); ++i) {
         const PlatformTouchPoint& point = points[i];
+        if (point.state() != PlatformTouchPoint::TouchPressed)
+            freshTouchEvents = false;
+        if (point.state() != PlatformTouchPoint::TouchReleased && point.state() != PlatformTouchPoint::TouchCancelled)
+            allTouchReleased = false;
+    }
+
+    for (i = 0; i < points.size(); ++i) {
+        const PlatformTouchPoint& point = points[i];
         PlatformTouchPoint::State pointState = point.state();
         LayoutPoint pagePoint = documentPointForWindowPoint(m_frame, point.pos());
 
@@ -3880,7 +3910,17 @@
         unsigned touchPointTargetKey = point.id() + 1;
         RefPtr<EventTarget> touchTarget;
         if (pointState == PlatformTouchPoint::TouchPressed) {
-            HitTestResult result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType);
+            HitTestResult result;
+            if (freshTouchEvents) {
+                result = hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType);
+                m_originatingTouchPointTargetKey = touchPointTargetKey;
+            } else if (m_originatingTouchPointDocument.get() && m_originatingTouchPointDocument->frame()) {
+                LayoutPoint pagePointInOriginatingDocument = documentPointForWindowPoint(m_originatingTouchPointDocument->frame(), point.pos());
+                result = hitTestResultInFrame(m_originatingTouchPointDocument->frame(), pagePointInOriginatingDocument, hitType);
+                if (!result.innerNode())
+                    continue;
+            } else
+                continue;
             Node* node = result.innerNode();
             ASSERT(node);
 
@@ -3892,16 +3932,26 @@
                 return true;
 
             Document* doc = node->document();
+            // Record the originating touch document even if it does not have a touch listener.
+            if (freshTouchEvents) {
+                m_originatingTouchPointDocument = doc;
+                freshTouchEvents = false;
+            }
             if (!doc)
                 continue;
             if (!doc->touchEventHandlerCount())
                 continue;
-
             m_originatingTouchPointTargets.set(touchPointTargetKey, node);
             touchTarget = node;
         } else if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) {
             // We only perform a hittest on release or cancel to unset :active or :hover state.
-            hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType);
+            if (touchPointTargetKey == m_originatingTouchPointTargetKey) {
+                hitTestResultAtPoint(pagePoint, /*allowShadowContent*/ false, false, DontHitTestScrollbars, hitType);
+                m_originatingTouchPointTargetKey = 0;
+            } else if (m_originatingTouchPointDocument.get() && m_originatingTouchPointDocument->frame()) {
+                LayoutPoint pagePointInOriginatingDocument = documentPointForWindowPoint(m_originatingTouchPointDocument->frame(), point.pos());
+                hitTestResultInFrame(m_originatingTouchPointDocument->frame(), pagePointInOriginatingDocument, hitType);
+            }
             // The target should be the original target for this touch, so get it from the hashmap. As it's a release or cancel
             // we also remove it from the map.
             touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey);
@@ -3962,6 +4012,8 @@
         }
     }
     m_touchPressed = touches->length() > 0;
+    if (allTouchReleased)
+        m_originatingTouchPointDocument.clear();
 
     // Now iterate the changedTouches list and m_targets within it, sending events to the targets as required.
     bool swallowedEvent = false;

Modified: trunk/Source/WebCore/page/EventHandler.h (137219 => 137220)


--- trunk/Source/WebCore/page/EventHandler.h	2012-12-10 23:56:02 UTC (rev 137219)
+++ trunk/Source/WebCore/page/EventHandler.h	2012-12-11 00:08:09 UTC (rev 137220)
@@ -294,6 +294,7 @@
 
 #if ENABLE(TOUCH_EVENTS)
     bool dispatchSyntheticTouchEventIfEnabled(const PlatformMouseEvent&);
+    HitTestResult hitTestResultInFrame(Frame*, const LayoutPoint&, HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active);
 #endif
 
     void invalidateClick();
@@ -462,6 +463,8 @@
 #if ENABLE(TOUCH_EVENTS)
     typedef HashMap<int, RefPtr<EventTarget> > TouchTargetMap;
     TouchTargetMap m_originatingTouchPointTargets;
+    RefPtr<Document> m_originatingTouchPointDocument;
+    unsigned m_originatingTouchPointTargetKey;
     bool m_touchPressed;
 #endif
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to