Title: [247161] trunk
Revision
247161
Author
wenson_hs...@apple.com
Date
2019-07-05 09:58:06 -0700 (Fri, 05 Jul 2019)

Log Message

Click events on outer page are not being dispatched correctly after touch-zooming within an iframe
https://bugs.webkit.org/show_bug.cgi?id=185001
<rdar://problem/40569615>

Reviewed by Simon Fraser.

Source/WebKit:

Mitigations introduced in r227759 prevent a touch inside a document of origin A to result in a click event being
dispatched on an element inside a document of origin B. It accomplishes this by keeping track of the security
origin of the last touch via m_potentialTapSecurityOrigin on WebPage. However, there exists a corner case in
which m_potentialTapSecurityOrigin, set after touching a document in a subframe, may persist even after the user
has finished interacting, causing taps in subsequent documents to not result in synthetic click events due to
mismatched potential tap origins.

This may happen if the first user gesture happens inside an element in a subframe with touch event handlers, but
no click event handler (and the touch is additionally not over some clickable element). In this case,
m_potentialTapNode is set to null in WebPage::potentialTapAtPosition, and when we consult it in
WebPage::commitPotentialTap, we just end up calling commitPotentialTapFailed(); and return early. This means
that m_potentialTapNode, m_potentialTapLocation, and (importantly) m_potentialTapSecurityOrigin are not reset.
This causes subsequent taps in the top-level document to never dispatch click events, if the security origin
does not match with that of the subframe.

To fix this, we add a new async IPC message from the UI process to the web process to ensure that our current
security origin is reset before attempting to handle a tap.

Test: http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::resetPotentialTapSecurityOrigin):

Reset any stale potential tap security origin if needed.

* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _webTouchEventsRecognized:]):

Send the new IPC message when starting a touch.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::resetPotentialTapSecurityOrigin):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

LayoutTests:

Add a new layout test to verify that after interacting with an element with touch event handlers in a cross-
origin subframe, the user is still able to click on elements on the top level document.

* http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https-expected.txt: Added.
* http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html: Added.
* http/tests/events/touch/ios/resources/touch-target.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (247160 => 247161)


--- trunk/LayoutTests/ChangeLog	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/LayoutTests/ChangeLog	2019-07-05 16:58:06 UTC (rev 247161)
@@ -1,5 +1,20 @@
 2019-07-05  Wenson Hsieh  <wenson_hs...@apple.com>
 
+        Click events on outer page are not being dispatched correctly after touch-zooming within an iframe
+        https://bugs.webkit.org/show_bug.cgi?id=185001
+        <rdar://problem/40569615>
+
+        Reviewed by Simon Fraser.
+
+        Add a new layout test to verify that after interacting with an element with touch event handlers in a cross-
+        origin subframe, the user is still able to click on elements on the top level document.
+
+        * http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https-expected.txt: Added.
+        * http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html: Added.
+        * http/tests/events/touch/ios/resources/touch-target.html: Added.
+
+2019-07-05  Wenson Hsieh  <wenson_hs...@apple.com>
+
         Touching media controls sometimes shows software keyboard
         https://bugs.webkit.org/show_bug.cgi?id=199490
         <rdar://problem/52076270>

Added: trunk/LayoutTests/http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https-expected.txt (0 => 247161)


--- trunk/LayoutTests/http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https-expected.txt	2019-07-05 16:58:06 UTC (rev 247161)
@@ -0,0 +1,14 @@
+This test verifies that tap in the top document is recognized as a click after touching inside a cross-origin subframe. To manually test, touch anywhere in the top iframe, and then tap the green box on the bottom. The text 'Clicked' should appear.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS touchend
+PASS Clicked
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+Then click here.
+Clicked
+

Added: trunk/LayoutTests/http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html (0 => 247161)


--- trunk/LayoutTests/http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html	2019-07-05 16:58:06 UTC (rev 247161)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+    <script src=""
+    <script src=""
+    <style>
+        iframe, #target {
+            width: 300px;
+            height: 150px;
+        }
+
+        #target {
+            background-color: green;
+            color: white;
+        }
+
+        #result {
+            color: green;
+        }
+    </style>
+    <script>
+        jsTestIsAsync = true;
+        progress = 0;
+
+        function checkProgress() {
+            if (++progress == 2)
+                finishJSTest();
+        }
+
+        description("This test verifies that tap in the top document is recognized as a click after touching inside a cross-origin subframe. To manually test, touch anywhere in the top iframe, and then tap the green box on the bottom. The text 'Clicked' should appear.")
+
+        addEventListener("load", async event => {
+            addEventListener("message", message => testPassed(message.data));
+            document.getElementById("target").addEventListener("click", () => {
+                document.getElementById("result").textContent = "Clicked";
+                testPassed("Clicked");
+                checkProgress();
+            });
+
+            if (!window.testRunner)
+                return;
+
+            await UIHelper.activateElement(document.querySelector("iframe"));
+            await UIHelper.activateElement(document.getElementById("target"));
+            checkProgress();
+        });
+    </script>
+</head>
+<body>
+    <p id="description"></p>
+    <iframe src=""
+    <div id="target">Then click here.</div>
+    <pre id="result"></pre>
+    <pre id="console"></pre>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/http/tests/events/touch/ios/resources/touch-target.html (0 => 247161)


--- trunk/LayoutTests/http/tests/events/touch/ios/resources/touch-target.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/events/touch/ios/resources/touch-target.html	2019-07-05 16:58:06 UTC (rev 247161)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<style>
+    body {
+        margin: 0;
+    }
+
+    div {
+        width: 100vw;
+        height: 100vh;
+    }
+</style>
+<div id="target">Touch this element.</div>
+<script>
+document.getElementById("target").addEventListener("touchend", () => parent.postMessage("touchend", "*"));
+</script>

Modified: trunk/Source/WebKit/ChangeLog (247160 => 247161)


--- trunk/Source/WebKit/ChangeLog	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/ChangeLog	2019-07-05 16:58:06 UTC (rev 247161)
@@ -1,5 +1,49 @@
 2019-07-05  Wenson Hsieh  <wenson_hs...@apple.com>
 
+        Click events on outer page are not being dispatched correctly after touch-zooming within an iframe
+        https://bugs.webkit.org/show_bug.cgi?id=185001
+        <rdar://problem/40569615>
+
+        Reviewed by Simon Fraser.
+
+        Mitigations introduced in r227759 prevent a touch inside a document of origin A to result in a click event being
+        dispatched on an element inside a document of origin B. It accomplishes this by keeping track of the security
+        origin of the last touch via m_potentialTapSecurityOrigin on WebPage. However, there exists a corner case in
+        which m_potentialTapSecurityOrigin, set after touching a document in a subframe, may persist even after the user
+        has finished interacting, causing taps in subsequent documents to not result in synthetic click events due to
+        mismatched potential tap origins.
+
+        This may happen if the first user gesture happens inside an element in a subframe with touch event handlers, but
+        no click event handler (and the touch is additionally not over some clickable element). In this case,
+        m_potentialTapNode is set to null in WebPage::potentialTapAtPosition, and when we consult it in
+        WebPage::commitPotentialTap, we just end up calling commitPotentialTapFailed(); and return early. This means
+        that m_potentialTapNode, m_potentialTapLocation, and (importantly) m_potentialTapSecurityOrigin are not reset.
+        This causes subsequent taps in the top-level document to never dispatch click events, if the security origin
+        does not match with that of the subframe.
+
+        To fix this, we add a new async IPC message from the UI process to the web process to ensure that our current
+        security origin is reset before attempting to handle a tap.
+
+        Test: http/tests/events/touch/ios/click-after-handling-touch-in-cross-origin-frame.https.html
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::resetPotentialTapSecurityOrigin):
+
+        Reset any stale potential tap security origin if needed.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _webTouchEventsRecognized:]):
+
+        Send the new IPC message when starting a touch.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::resetPotentialTapSecurityOrigin):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+2019-07-05  Wenson Hsieh  <wenson_hs...@apple.com>
+
         Touching media controls sometimes shows software keyboard
         https://bugs.webkit.org/show_bug.cgi?id=199490
         <rdar://problem/52076270>

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (247160 => 247161)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-07-05 16:58:06 UTC (rev 247161)
@@ -2657,6 +2657,14 @@
         m_touchAndPointerEventTracking.reset();
 }
 
+void WebPageProxy::resetPotentialTapSecurityOrigin()
+{
+    if (!hasRunningProcess())
+        return;
+
+    m_process->send(Messages::WebPage::ResetPotentialTapSecurityOrigin(), m_pageID);
+}
+
 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
 {
     if (!hasRunningProcess())

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (247160 => 247161)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-07-05 16:58:06 UTC (rev 247161)
@@ -828,6 +828,7 @@
 #endif
 
 #if ENABLE(IOS_TOUCH_EVENTS)
+    void resetPotentialTapSecurityOrigin();
     void handleTouchEventSynchronously(NativeWebTouchEvent&);
     void handleTouchEventAsynchronously(const NativeWebTouchEvent&);
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (247160 => 247161)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2019-07-05 16:58:06 UTC (rev 247161)
@@ -1315,6 +1315,10 @@
         [self _handleDOMPasteRequestWithResult:WebCore::DOMPasteAccessResponse::DeniedForGesture];
         _layerTreeTransactionIdAtLastTouchStart = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).lastCommittedLayerTreeTransactionID();
 
+#if ENABLE(TOUCH_EVENTS)
+        _page->resetPotentialTapSecurityOrigin();
+#endif
+
         WebKit::InteractionInformationRequest positionInformationRequest { WebCore::IntPoint(_lastInteractionLocation) };
         [self doAfterPositionInformationUpdate:[assistant = WeakObjCPtr<WKActionSheetAssistant>(_actionSheetAssistant.get())] (WebKit::InteractionInformationAtPosition information) {
             [assistant interactionDidStartWithPositionInformation:information];

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (247160 => 247161)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2019-07-05 16:58:06 UTC (rev 247161)
@@ -2916,6 +2916,11 @@
         reply(handled);
 }
 
+void WebPage::resetPotentialTapSecurityOrigin()
+{
+    m_potentialTapSecurityOrigin = nullptr;
+}
+
 void WebPage::updatePotentialTapSecurityOrigin(const WebTouchEvent& touchEvent, bool wasHandled)
 {
     if (wasHandled)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (247160 => 247161)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2019-07-05 16:58:06 UTC (rev 247161)
@@ -1320,6 +1320,7 @@
 
 #if ENABLE(IOS_TOUCH_EVENTS)
     void touchEventSync(const WebTouchEvent&, CompletionHandler<void(bool)>&&);
+    void resetPotentialTapSecurityOrigin();
     void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled);
 #elif ENABLE(TOUCH_EVENTS)
     void touchEvent(const WebTouchEvent&);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (247160 => 247161)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-07-05 16:38:40 UTC (rev 247160)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2019-07-05 16:58:06 UTC (rev 247161)
@@ -126,6 +126,7 @@
 #endif
 
 #if ENABLE(IOS_TOUCH_EVENTS)
+    ResetPotentialTapSecurityOrigin()
     TouchEventSync(WebKit::WebTouchEvent event) -> (bool handled) Synchronous
 #endif
 #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to