Diff
Modified: branches/safari-612.1.12-branch/LayoutTests/ChangeLog (276902 => 276903)
--- branches/safari-612.1.12-branch/LayoutTests/ChangeLog 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/LayoutTests/ChangeLog 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1,3 +1,126 @@
+2021-05-03 Russell Epstein <[email protected]>
+
+ Cherry-pick r276853. rdar://problem/77458363
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Source/WebCore:
+
+ Add plumbing for a `ChromeClient` hook that's called when a mousedown or mouseup event is either prevented by
+ the page, or handled with a default event handler on the element (e.g. when clicking a link).
+
+ Test: fast/events/ios/did-not-handle-meaningful-click.html
+
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleMousePressEvent):
+ (WebCore::EventHandler::handleMouseDoubleClickEvent):
+ (WebCore::EventHandler::handleMouseReleaseEvent):
+
+ Source/WebKit:
+
+ Add a simple heuristic to inform WKWebView iOS clients when a tap either failed to result in a synthetic click,
+ or resulted in a synthetic click that (probably) didn't have any "meaningful side effects". While this notion of
+ "meaningfulness" isn't well defined, the idea behind the heuristic is that it should distinguish between taps on
+ clickable elements like buttons or links that trigger some noticable change on the page, vs. taps on both
+ clickable or non-clickable elements that do not trigger any changes on the page.
+
+ For instance on a news-article-like page, this delegate method should be invoked when tapping on paragraph text
+ in the article, even if there is a click handler over the entire article or even body element. However, tapping
+ a link or a button on the same page should not cause this delegate method to be invoked. Additionally, if the
+ page explicitly prevents default behavior during a synthetic mouse event, this method should also *not* be
+ invoked.
+
+ This behavior is roughly similar to the existing delegate method `-_webView:didNotHandleTapAsClickAtPoint:`,
+ except that this variant allows for more wiggle room around what constitutes a "meaningful" interaction with the
+ page.
+
+ * UIProcess/API/APIUIClient.h:
+ (API::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+ * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+ * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+ (-[WKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ See Tools/ChangeLog for more details about this testing hook.
+
+ * UIProcess/Cocoa/UIDelegate.h:
+ * UIProcess/Cocoa/UIDelegate.mm:
+ (WebKit::UIDelegate::setDelegate):
+ (WebKit::UIDelegate::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::didNotHandleTapAsMeaningfulClickAtPoint):
+ * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+ (WebKit::WebChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::isProbablyMeaningfulClick):
+
+ Implement the core of the heuristic here. For now, it just examines the size of the click target. This isn't
+ going to satisfy the case where a page installs a click event handler on the body element (or a similar
+ element that encapsulates most of the page) and then performs hit-testing in their script, but it's somewhere to
+ start.
+
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::attemptSyntheticClick):
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ (WebKit::WebPage::handleTwoFingerTapAtPoint):
+ (WebKit::WebPage::commitPotentialTapFailed):
+
+ Tools:
+
+ Add test runner plumbing to test the new heuristic. Note that we can't just utilize the `WKUIDelegatePrivate`
+ method directly, since we end up overriding the web view's `UIClient` via `WKPageSetPageUIClient`, so the call
+ to `m_uiClient->didNotHandleTapAsMeaningfulClickAtPoint(point);` ends up being a no-op.
+
+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+ (WTR::InjectedBundle::didReceiveMessageToPage):
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::installDidNotHandleTapAsMeaningfulClickCallback):
+ (WTR::TestRunner::callDidNotHandleTapAsMeaningfulClickCallback):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestController.h:
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestInvocation.h:
+ * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+ (-[TestRunnerWKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ LayoutTests:
+
+ * fast/events/ios/did-not-handle-meaningful-click-expected.txt: Added.
+ * fast/events/ios/did-not-handle-meaningful-click.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276853 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-30 Wenson Hsieh <[email protected]>
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ * fast/events/ios/did-not-handle-meaningful-click-expected.txt: Added.
+ * fast/events/ios/did-not-handle-meaningful-click.html: Added.
+
2021-04-25 Felipe Erias <[email protected]>
[css-flexbox] Table layout disregards overriding width
Added: branches/safari-612.1.12-branch/LayoutTests/fast/events/ios/did-not-handle-meaningful-click-expected.txt (0 => 276903)
--- branches/safari-612.1.12-branch/LayoutTests/fast/events/ios/did-not-handle-meaningful-click-expected.txt (rev 0)
+++ branches/safari-612.1.12-branch/LayoutTests/fast/events/ios/did-not-handle-meaningful-click-expected.txt 2021-05-03 16:38:55 UTC (rev 276903)
@@ -0,0 +1,13 @@
+This test is intended to exercise the 'meaningful click' heuristic, and requires WebKitTestRunner.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS didNotHandleTapAsMeaningfulClickCallback is true
+PASS clicked on button
+PASS didNotHandleTapAsMeaningfulClickCallback is false
+PASS didNotHandleTapAsMeaningfulClickCallback is true
+PASS didNotHandleTapAsMeaningfulClickCallback is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/safari-612.1.12-branch/LayoutTests/fast/events/ios/did-not-handle-meaningful-click.html (0 => 276903)
--- branches/safari-612.1.12-branch/LayoutTests/fast/events/ios/did-not-handle-meaningful-click.html (rev 0)
+++ branches/safari-612.1.12-branch/LayoutTests/fast/events/ios/did-not-handle-meaningful-click.html 2021-05-03 16:38:55 UTC (rev 276903)
@@ -0,0 +1,65 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+<style>
+body, html {
+ font-size: 18px;
+ font-family: system-ui;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+}
+</style>
+<script src=""
+<script src=""
+<script>
+jsTestIsAsync = true;
+
+addEventListener("load", async () => {
+ description("This test is intended to exercise the 'meaningful click' heuristic, and requires WebKitTestRunner.");
+
+ let text = document.getElementById("text");
+ let button = document.getElementById("target");
+
+ async function simulateTapAndCheckDidNotHandleTapAsMeaningfulClick(element, expectation) {
+ didNotHandleTapAsMeaningfulClickCallback = false;
+ testRunner.installDidNotHandleTapAsMeaningfulClickCallback(() => {
+ didNotHandleTapAsMeaningfulClickCallback = true;
+ });
+
+ await UIHelper.activateElement(element);
+ await UIHelper.waitForDoubleTapDelay();
+ if (expectation)
+ shouldBeTrue("didNotHandleTapAsMeaningfulClickCallback");
+ else
+ shouldBeFalse("didNotHandleTapAsMeaningfulClickCallback");
+
+ testRunner.clearTestRunnerCallbacks();
+ }
+
+ await simulateTapAndCheckDidNotHandleTapAsMeaningfulClick(text, true);
+ await simulateTapAndCheckDidNotHandleTapAsMeaningfulClick(button, false);
+
+ document.body.addEventListener("click", () => { });
+ await simulateTapAndCheckDidNotHandleTapAsMeaningfulClick(text, true);
+
+ document.body.addEventListener("mousedown", (event) => {
+ event.preventDefault();
+ });
+ await simulateTapAndCheckDidNotHandleTapAsMeaningfulClick(text, false);
+
+ text.remove();
+ button.remove();
+
+ finishJSTest();
+});
+</script>
+</head>
+<body>
+ <button id="target" _onclick_="testPassed('clicked on button'); event.stopPropagation();">Hello world</button>
+ <p id="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean laoreet nisi felis, eu scelerisque dolor imperdiet in. Sed at porttitor purus, in placerat justo. Mauris at augue ac purus viverra molestie. Fusce ultrices ante at pellentesque lobortis. Sed pellentesque, ipsum eu semper mollis, arcu lectus dignissim enim, in maximus tortor ligula id ipsum. Nulla dignissim diam a mi tempor porta. Etiam tempor ac augue non dapibus. Donec euismod vel turpis in ultrices. Ut accumsan ultrices arcu vitae venenatis. In urna velit, accumsan sit amet arcu vel, vestibulum pulvinar leo. Aliquam vulputate euismod ultrices. Sed congue vestibulum libero quis ornare.</p>
+ <div id="description"></div>
+ <div id="console"></div>
+</body>
+</html>
\ No newline at end of file
Modified: branches/safari-612.1.12-branch/Source/WebCore/ChangeLog (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebCore/ChangeLog 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebCore/ChangeLog 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1,3 +1,135 @@
+2021-05-03 Russell Epstein <[email protected]>
+
+ Cherry-pick r276853. rdar://problem/77458363
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Source/WebCore:
+
+ Add plumbing for a `ChromeClient` hook that's called when a mousedown or mouseup event is either prevented by
+ the page, or handled with a default event handler on the element (e.g. when clicking a link).
+
+ Test: fast/events/ios/did-not-handle-meaningful-click.html
+
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleMousePressEvent):
+ (WebCore::EventHandler::handleMouseDoubleClickEvent):
+ (WebCore::EventHandler::handleMouseReleaseEvent):
+
+ Source/WebKit:
+
+ Add a simple heuristic to inform WKWebView iOS clients when a tap either failed to result in a synthetic click,
+ or resulted in a synthetic click that (probably) didn't have any "meaningful side effects". While this notion of
+ "meaningfulness" isn't well defined, the idea behind the heuristic is that it should distinguish between taps on
+ clickable elements like buttons or links that trigger some noticable change on the page, vs. taps on both
+ clickable or non-clickable elements that do not trigger any changes on the page.
+
+ For instance on a news-article-like page, this delegate method should be invoked when tapping on paragraph text
+ in the article, even if there is a click handler over the entire article or even body element. However, tapping
+ a link or a button on the same page should not cause this delegate method to be invoked. Additionally, if the
+ page explicitly prevents default behavior during a synthetic mouse event, this method should also *not* be
+ invoked.
+
+ This behavior is roughly similar to the existing delegate method `-_webView:didNotHandleTapAsClickAtPoint:`,
+ except that this variant allows for more wiggle room around what constitutes a "meaningful" interaction with the
+ page.
+
+ * UIProcess/API/APIUIClient.h:
+ (API::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+ * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+ * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+ (-[WKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ See Tools/ChangeLog for more details about this testing hook.
+
+ * UIProcess/Cocoa/UIDelegate.h:
+ * UIProcess/Cocoa/UIDelegate.mm:
+ (WebKit::UIDelegate::setDelegate):
+ (WebKit::UIDelegate::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::didNotHandleTapAsMeaningfulClickAtPoint):
+ * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+ (WebKit::WebChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::isProbablyMeaningfulClick):
+
+ Implement the core of the heuristic here. For now, it just examines the size of the click target. This isn't
+ going to satisfy the case where a page installs a click event handler on the body element (or a similar
+ element that encapsulates most of the page) and then performs hit-testing in their script, but it's somewhere to
+ start.
+
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::attemptSyntheticClick):
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ (WebKit::WebPage::handleTwoFingerTapAtPoint):
+ (WebKit::WebPage::commitPotentialTapFailed):
+
+ Tools:
+
+ Add test runner plumbing to test the new heuristic. Note that we can't just utilize the `WKUIDelegatePrivate`
+ method directly, since we end up overriding the web view's `UIClient` via `WKPageSetPageUIClient`, so the call
+ to `m_uiClient->didNotHandleTapAsMeaningfulClickAtPoint(point);` ends up being a no-op.
+
+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+ (WTR::InjectedBundle::didReceiveMessageToPage):
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::installDidNotHandleTapAsMeaningfulClickCallback):
+ (WTR::TestRunner::callDidNotHandleTapAsMeaningfulClickCallback):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestController.h:
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestInvocation.h:
+ * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+ (-[TestRunnerWKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ LayoutTests:
+
+ * fast/events/ios/did-not-handle-meaningful-click-expected.txt: Added.
+ * fast/events/ios/did-not-handle-meaningful-click.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276853 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-30 Wenson Hsieh <[email protected]>
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Add plumbing for a `ChromeClient` hook that's called when a mousedown or mouseup event is either prevented by
+ the page, or handled with a default event handler on the element (e.g. when clicking a link).
+
+ Test: fast/events/ios/did-not-handle-meaningful-click.html
+
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleMousePressEvent):
+ (WebCore::EventHandler::handleMouseDoubleClickEvent):
+ (WebCore::EventHandler::handleMouseReleaseEvent):
+
2021-04-30 Russell Epstein <[email protected]>
Cherry-pick r276744. rdar://problem/77402549
Modified: branches/safari-612.1.12-branch/Source/WebCore/page/ChromeClient.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebCore/page/ChromeClient.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebCore/page/ChromeClient.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -258,6 +258,8 @@
virtual void didPreventDefaultForEvent() = 0;
#endif
+ virtual void didHandleOrPreventMouseDownOrMouseUpEvent() { }
+
virtual Seconds eventThrottlingDelay() { return 0_s; };
#if PLATFORM(IOS_FAMILY)
Modified: branches/safari-612.1.12-branch/Source/WebCore/page/EventHandler.cpp (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebCore/page/EventHandler.cpp 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebCore/page/EventHandler.cpp 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1770,6 +1770,8 @@
m_frame.selection().setCaretBlinkingSuspended(true);
bool swallowEvent = !dispatchMouseEvent(eventNames().mousedownEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::Yes);
+ if (auto page = m_frame.page(); page && swallowEvent)
+ page->chrome().client().didHandleOrPreventMouseDownOrMouseUpEvent();
m_capturesDragging = !swallowEvent || mouseEvent.scrollbar();
// If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
@@ -1832,6 +1834,8 @@
m_clickCount = platformMouseEvent.clickCount();
bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);
+ if (auto page = m_frame.page(); page && swallowMouseUpEvent)
+ page->chrome().client().didHandleOrPreventMouseDownOrMouseUpEvent();
bool swallowClickEvent = platformMouseEvent.button() != RightButton && mouseEvent.targetNode() == m_clickNode && !dispatchMouseEvent(eventNames().clickEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::Yes);
@@ -2136,6 +2140,8 @@
return true;
bool swallowMouseUpEvent = !dispatchMouseEvent(eventNames().mouseupEvent, mouseEvent.targetNode(), m_clickCount, platformMouseEvent, FireMouseOverOut::No);
+ if (auto page = m_frame.page(); page && swallowMouseUpEvent)
+ page->chrome().client().didHandleOrPreventMouseDownOrMouseUpEvent();
bool contextMenuEvent = platformMouseEvent.button() == RightButton;
Modified: branches/safari-612.1.12-branch/Source/WebKit/ChangeLog (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/ChangeLog 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/ChangeLog 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1,3 +1,179 @@
+2021-05-03 Russell Epstein <[email protected]>
+
+ Cherry-pick r276853. rdar://problem/77458363
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Source/WebCore:
+
+ Add plumbing for a `ChromeClient` hook that's called when a mousedown or mouseup event is either prevented by
+ the page, or handled with a default event handler on the element (e.g. when clicking a link).
+
+ Test: fast/events/ios/did-not-handle-meaningful-click.html
+
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleMousePressEvent):
+ (WebCore::EventHandler::handleMouseDoubleClickEvent):
+ (WebCore::EventHandler::handleMouseReleaseEvent):
+
+ Source/WebKit:
+
+ Add a simple heuristic to inform WKWebView iOS clients when a tap either failed to result in a synthetic click,
+ or resulted in a synthetic click that (probably) didn't have any "meaningful side effects". While this notion of
+ "meaningfulness" isn't well defined, the idea behind the heuristic is that it should distinguish between taps on
+ clickable elements like buttons or links that trigger some noticable change on the page, vs. taps on both
+ clickable or non-clickable elements that do not trigger any changes on the page.
+
+ For instance on a news-article-like page, this delegate method should be invoked when tapping on paragraph text
+ in the article, even if there is a click handler over the entire article or even body element. However, tapping
+ a link or a button on the same page should not cause this delegate method to be invoked. Additionally, if the
+ page explicitly prevents default behavior during a synthetic mouse event, this method should also *not* be
+ invoked.
+
+ This behavior is roughly similar to the existing delegate method `-_webView:didNotHandleTapAsClickAtPoint:`,
+ except that this variant allows for more wiggle room around what constitutes a "meaningful" interaction with the
+ page.
+
+ * UIProcess/API/APIUIClient.h:
+ (API::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+ * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+ * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+ (-[WKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ See Tools/ChangeLog for more details about this testing hook.
+
+ * UIProcess/Cocoa/UIDelegate.h:
+ * UIProcess/Cocoa/UIDelegate.mm:
+ (WebKit::UIDelegate::setDelegate):
+ (WebKit::UIDelegate::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::didNotHandleTapAsMeaningfulClickAtPoint):
+ * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+ (WebKit::WebChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::isProbablyMeaningfulClick):
+
+ Implement the core of the heuristic here. For now, it just examines the size of the click target. This isn't
+ going to satisfy the case where a page installs a click event handler on the body element (or a similar
+ element that encapsulates most of the page) and then performs hit-testing in their script, but it's somewhere to
+ start.
+
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::attemptSyntheticClick):
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ (WebKit::WebPage::handleTwoFingerTapAtPoint):
+ (WebKit::WebPage::commitPotentialTapFailed):
+
+ Tools:
+
+ Add test runner plumbing to test the new heuristic. Note that we can't just utilize the `WKUIDelegatePrivate`
+ method directly, since we end up overriding the web view's `UIClient` via `WKPageSetPageUIClient`, so the call
+ to `m_uiClient->didNotHandleTapAsMeaningfulClickAtPoint(point);` ends up being a no-op.
+
+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+ (WTR::InjectedBundle::didReceiveMessageToPage):
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::installDidNotHandleTapAsMeaningfulClickCallback):
+ (WTR::TestRunner::callDidNotHandleTapAsMeaningfulClickCallback):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestController.h:
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestInvocation.h:
+ * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+ (-[TestRunnerWKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ LayoutTests:
+
+ * fast/events/ios/did-not-handle-meaningful-click-expected.txt: Added.
+ * fast/events/ios/did-not-handle-meaningful-click.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276853 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-30 Wenson Hsieh <[email protected]>
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Add a simple heuristic to inform WKWebView iOS clients when a tap either failed to result in a synthetic click,
+ or resulted in a synthetic click that (probably) didn't have any "meaningful side effects". While this notion of
+ "meaningfulness" isn't well defined, the idea behind the heuristic is that it should distinguish between taps on
+ clickable elements like buttons or links that trigger some noticable change on the page, vs. taps on both
+ clickable or non-clickable elements that do not trigger any changes on the page.
+
+ For instance on a news-article-like page, this delegate method should be invoked when tapping on paragraph text
+ in the article, even if there is a click handler over the entire article or even body element. However, tapping
+ a link or a button on the same page should not cause this delegate method to be invoked. Additionally, if the
+ page explicitly prevents default behavior during a synthetic mouse event, this method should also *not* be
+ invoked.
+
+ This behavior is roughly similar to the existing delegate method `-_webView:didNotHandleTapAsClickAtPoint:`,
+ except that this variant allows for more wiggle room around what constitutes a "meaningful" interaction with the
+ page.
+
+ * UIProcess/API/APIUIClient.h:
+ (API::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+ * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+ * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+ (-[WKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ See Tools/ChangeLog for more details about this testing hook.
+
+ * UIProcess/Cocoa/UIDelegate.h:
+ * UIProcess/Cocoa/UIDelegate.mm:
+ (WebKit::UIDelegate::setDelegate):
+ (WebKit::UIDelegate::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::didNotHandleTapAsMeaningfulClickAtPoint):
+ * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+ (WebKit::WebChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::isProbablyMeaningfulClick):
+
+ Implement the core of the heuristic here. For now, it just examines the size of the click target. This isn't
+ going to satisfy the case where a page installs a click event handler on the body element (or a similar
+ element that encapsulates most of the page) and then performs hit-testing in their script, but it's somewhere to
+ start.
+
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::attemptSyntheticClick):
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ (WebKit::WebPage::handleTwoFingerTapAtPoint):
+ (WebKit::WebPage::commitPotentialTapFailed):
+
2021-04-30 Russell Epstein <[email protected]>
Cherry-pick r276744. rdar://problem/77402549
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/APIUIClient.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/APIUIClient.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/APIUIClient.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -164,6 +164,7 @@
#endif
virtual RetainPtr<NSArray> actionsForElement(_WKActivatedElementInfo *, RetainPtr<NSArray> defaultActions) { return defaultActions; }
virtual void didNotHandleTapAsClick(const WebCore::IntPoint&) { }
+ virtual void didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint&) { }
virtual UIViewController *presentingViewController() { return nullptr; }
#endif
#if PLATFORM(COCOA)
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -164,6 +164,7 @@
- (BOOL)_webView:(WKWebView *)webView shouldIncludeAppLinkActionsForElement:(_WKActivatedElementInfo *)element WK_API_AVAILABLE(ios(9.0));
- (NSArray *)_webView:(WKWebView *)webView actionsForElement:(_WKActivatedElementInfo *)element defaultActions:(NSArray<_WKElementAction *> *)defaultActions;
- (void)_webView:(WKWebView *)webView didNotHandleTapAsClickAtPoint:(CGPoint)point;
+- (void)_webView:(WKWebView *)webView didNotHandleTapAsMeaningfulClickAtPoint:(CGPoint)point WK_API_AVAILABLE(ios(WK_IOS_TBA));
- (void)_webView:(WKWebView *)webView requestGeolocationAuthorizationForURL:(NSURL *)url frame:(WKFrameInfo *)frame decisionHandler:(void (^)(BOOL authorized))decisionHandler WK_API_AVAILABLE(ios(11.0));
- (BOOL)_webView:(WKWebView *)webView fileUploadPanelContentIsManagedWithInitiatingFrame:(WKFrameInfo *)frame;
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -64,6 +64,7 @@
- (void)_didFinishTextInteractionInTextInputContext:(_WKTextInputContext *)context;
- (void)_requestDocumentContext:(UIWKDocumentRequest *)request completionHandler:(void (^)(UIWKDocumentContext *))completionHandler;
- (void)_adjustSelectionWithDelta:(NSRange)deltaRange completionHandler:(void (^)(void))completionHandler;
+- (void)_didNotHandleTapAsMeaningfulClickAtPoint:(CGPoint)point;
- (void)setTimePickerValueToHour:(NSInteger)hour minute:(NSInteger)minute;
- (double)timePickerValueHour;
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm 2021-05-03 16:38:55 UTC (rev 276903)
@@ -96,6 +96,11 @@
#endif
}
+- (void)_didNotHandleTapAsMeaningfulClickAtPoint:(CGPoint)point
+{
+ // For subclasses to override.
+}
+
- (BOOL)_mayContainEditableElementsInRect:(CGRect)rect
{
#if ENABLE(EDITABLE_REGION)
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/UIDelegate.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/UIDelegate.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/UIDelegate.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -144,6 +144,7 @@
#endif
RetainPtr<NSArray> actionsForElement(_WKActivatedElementInfo *, RetainPtr<NSArray> defaultActions) final;
void didNotHandleTapAsClick(const WebCore::IntPoint&) final;
+ void didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint&) final;
UIViewController *presentingViewController() final;
#endif // PLATFORM(IOS_FAMILY)
@@ -237,6 +238,7 @@
#endif
bool webViewActionsForElementDefaultActions : 1;
bool webViewDidNotHandleTapAsClickAtPoint : 1;
+ bool webViewDidNotHandleTapAsMeaningfulClickAtPoint : 1;
bool presentingViewControllerForWebView : 1;
#endif
bool dataDetectionContextForWebView : 1;
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm 2021-05-03 16:38:55 UTC (rev 276903)
@@ -157,6 +157,7 @@
#endif
m_delegateMethods.webViewActionsForElementDefaultActions = [delegate respondsToSelector:@selector(_webView:actionsForElement:defaultActions:)];
m_delegateMethods.webViewDidNotHandleTapAsClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsClickAtPoint:)];
+ m_delegateMethods.webViewDidNotHandleTapAsMeaningfulClickAtPoint = [delegate respondsToSelector:@selector(_webView:didNotHandleTapAsMeaningfulClickAtPoint:)];
m_delegateMethods.presentingViewControllerForWebView = [delegate respondsToSelector:@selector(_presentingViewControllerForWebView:)];
#endif
m_delegateMethods.webViewIsMediaCaptureAuthorizedForFrameDecisionHandler = [delegate respondsToSelector:@selector(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:)] || [delegate respondsToSelector:@selector(_webView:includeSensitiveMediaDeviceDetails:)];
@@ -1411,6 +1412,21 @@
[static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate->m_webView.get().get() didNotHandleTapAsClickAtPoint:point];
}
+void UIDelegate::UIClient::didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint& point)
+{
+ if (!m_uiDelegate)
+ return;
+
+ if (!m_uiDelegate->m_delegateMethods.webViewDidNotHandleTapAsMeaningfulClickAtPoint)
+ return;
+
+ auto delegate = m_uiDelegate->m_delegate.get();
+ if (!delegate)
+ return;
+
+ [static_cast<id <WKUIDelegatePrivate>>(delegate) _webView:m_uiDelegate->m_webView.get().get() didNotHandleTapAsMeaningfulClickAtPoint:point];
+}
+
UIViewController *UIDelegate::UIClient::presentingViewController()
{
if (!m_uiDelegate)
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/PageClient.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/PageClient.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/PageClient.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -331,6 +331,7 @@
#endif
#if PLATFORM(IOS_FAMILY)
virtual void didNotHandleTapAsClick(const WebCore::IntPoint&) = 0;
+ virtual void didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint&) = 0;
virtual void didCompleteSyntheticClick() = 0;
#endif
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -827,6 +827,7 @@
void applicationWillEnterForegroundForMedia();
void commitPotentialTapFailed();
void didNotHandleTapAsClick(const WebCore::IntPoint&);
+ void didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint&);
void didCompleteSyntheticClick();
void disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID);
void handleSmartMagnificationInformationForPotentialTap(uint64_t requestID, const WebCore::FloatRect& renderRect, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale, bool nodeIsRootLevel);
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.messages.in (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.messages.in 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/WebPageProxy.messages.in 2021-05-03 16:38:55 UTC (rev 276903)
@@ -170,6 +170,7 @@
ShowPlaybackTargetPicker(bool hasVideo, WebCore::IntRect elementRect, enum:uint8_t WebCore::RouteSharingPolicy policy, String routingContextUID)
CommitPotentialTapFailed()
DidNotHandleTapAsClick(WebCore::IntPoint point)
+ DidNotHandleTapAsMeaningfulClickAtPoint(WebCore::IntPoint point)
DidCompleteSyntheticClick()
DisableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
HandleSmartMagnificationInformationForPotentialTap(uint64_t requestID, WebCore::FloatRect renderRect, bool fitEntireRect, double viewportMinimumScale, double viewportMaximumScale, bool nodeIsRootLevel)
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -241,6 +241,7 @@
void didFailNavigation(API::Navigation*) override;
void didSameDocumentNavigationForMainFrame(SameDocumentNavigationType) override;
void didNotHandleTapAsClick(const WebCore::IntPoint&) override;
+ void didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint&) final;
void didCompleteSyntheticClick() override;
void didChangeBackgroundColor() override;
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2021-05-03 16:38:55 UTC (rev 276903)
@@ -232,7 +232,12 @@
{
[m_contentView _didNotHandleTapAsClick:point];
}
-
+
+void PageClientImpl::didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint& point)
+{
+ [m_webView _didNotHandleTapAsMeaningfulClickAtPoint:point];
+}
+
void PageClientImpl::didCompleteSyntheticClick()
{
[m_contentView _didCompleteSyntheticClick];
Modified: branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1007,6 +1007,12 @@
pageClient().didNotHandleTapAsClick(point);
m_uiClient->didNotHandleTapAsClick(point);
}
+
+void WebPageProxy::didNotHandleTapAsMeaningfulClickAtPoint(const WebCore::IntPoint& point)
+{
+ pageClient().didNotHandleTapAsMeaningfulClickAtPoint(point);
+ m_uiClient->didNotHandleTapAsMeaningfulClickAtPoint(point);
+}
void WebPageProxy::didCompleteSyntheticClick()
{
Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1485,4 +1485,9 @@
}
#endif
+void WebChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent()
+{
+ m_page.didHandleOrPreventMouseDownOrMouseUpEvent();
+}
+
} // namespace WebKit
Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -164,6 +164,8 @@
void didPreventDefaultForEvent() final;
#endif
+ void didHandleOrPreventMouseDownOrMouseUpEvent() final;
+
#if PLATFORM(IOS_FAMILY)
void didReceiveMobileDocType(bool) final;
void setNeedsScrollNotifications(WebCore::Frame&, bool) final;
Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/WebPage.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1445,6 +1445,8 @@
PlatformXRSystemProxy& xrSystemProxy();
#endif
+ void didHandleOrPreventMouseDownOrMouseUpEvent();
+
private:
WebPage(WebCore::PageIdentifier, WebPageCreationParameters&&);
@@ -2165,6 +2167,7 @@
RefPtr<WebCore::Node> m_potentialTapNode;
WebCore::FloatPoint m_potentialTapLocation;
RefPtr<WebCore::SecurityOrigin> m_potentialTapSecurityOrigin;
+ bool m_didHandleOrPreventMouseDownOrMouseUpEventDuringSyntheticClick { false };
bool m_hasReceivedVisibleContentRectsAfterDidCommitLoad { false };
bool m_hasRestoredExposedContentRectAfterDidCommitLoad { false };
@@ -2333,6 +2336,7 @@
#if !PLATFORM(IOS_FAMILY)
inline void WebPage::platformWillPerformEditingCommand() { }
inline bool WebPage::platformNeedsLayoutForEditorState(const WebCore::Frame&) const { return false; }
+inline void WebPage::didHandleOrPreventMouseDownOrMouseUpEvent() { }
#endif
} // namespace WebKit
Modified: branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (276902 => 276903)
--- branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2021-05-03 16:38:55 UTC (rev 276903)
@@ -834,6 +834,25 @@
m_pendingSyntheticClickPointerId = 0;
}
+static bool isProbablyMeaningfulClick(Node& clickNode)
+{
+ auto frame = makeRefPtr(clickNode.document().frame());
+ if (!is<Element>(clickNode) || !clickNode.isConnected() || !frame)
+ return true;
+
+ if (is<HTMLBodyElement>(clickNode))
+ return false;
+
+ if (auto view = makeRefPtr(frame->mainFrame().view())) {
+ auto elementBounds = WebPage::rootViewBoundsForElement(downcast<Element>(clickNode));
+ auto unobscuredRect = view->unobscuredContentRect();
+ if (elementBounds.width() >= unobscuredRect.width() / 2 && elementBounds.height() >= unobscuredRect.height() / 2)
+ return false;
+ }
+
+ return true;
+}
+
void WebPage::completeSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, SyntheticClickType syntheticClickType, WebCore::PointerID pointerId)
{
IntPoint roundedAdjustedPoint = roundedIntPoint(location);
@@ -853,6 +872,8 @@
bool altKey = modifiers.contains(WebEvent::Modifier::AltKey);
bool metaKey = modifiers.contains(WebEvent::Modifier::MetaKey);
+ m_didHandleOrPreventMouseDownOrMouseUpEventDuringSyntheticClick = false;
+
tapWasHandled |= mainframe.eventHandler().handleMousePressEvent(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, LeftButton, PlatformEvent::MousePressed, 1, shiftKey, ctrlKey, altKey, metaKey, WallTime::now(), WebCore::ForceAtClick, syntheticClickType, pointerId));
if (m_isClosed)
return;
@@ -879,8 +900,13 @@
if (m_isClosed)
return;
+ if (!m_didHandleOrPreventMouseDownOrMouseUpEventDuringSyntheticClick && !isProbablyMeaningfulClick(nodeRespondingToClick))
+ send(Messages::WebPageProxy::DidNotHandleTapAsMeaningfulClickAtPoint(roundedIntPoint(location)));
+
if (!tapWasHandled || !nodeRespondingToClick.isElementNode())
send(Messages::WebPageProxy::DidNotHandleTapAsClick(roundedIntPoint(location)));
+
+ m_didHandleOrPreventMouseDownOrMouseUpEventDuringSyntheticClick = false;
send(Messages::WebPageProxy::DidCompleteSyntheticClick());
}
@@ -892,14 +918,20 @@
Frame* frameRespondingToClick = nodeRespondingToClick ? nodeRespondingToClick->document().frame() : nullptr;
IntPoint adjustedIntPoint = roundedIntPoint(adjustedPoint);
- if (!frameRespondingToClick || lastLayerTreeTransactionId < WebFrame::fromCoreFrame(*frameRespondingToClick)->firstLayerTreeTransactionIDAfterDidCommitLoad())
+ if (!frameRespondingToClick || lastLayerTreeTransactionId < WebFrame::fromCoreFrame(*frameRespondingToClick)->firstLayerTreeTransactionIDAfterDidCommitLoad()) {
+ send(Messages::WebPageProxy::DidNotHandleTapAsMeaningfulClickAtPoint(adjustedIntPoint));
send(Messages::WebPageProxy::DidNotHandleTapAsClick(adjustedIntPoint));
- else if (m_interactionNode == nodeRespondingToClick)
+ } else if (m_interactionNode == nodeRespondingToClick)
completeSyntheticClick(*nodeRespondingToClick, adjustedPoint, modifiers, WebCore::OneFingerTap);
else
handleSyntheticClick(*nodeRespondingToClick, adjustedPoint, modifiers);
}
+void WebPage::didHandleOrPreventMouseDownOrMouseUpEvent()
+{
+ m_didHandleOrPreventMouseDownOrMouseUpEventDuringSyntheticClick = true;
+}
+
void WebPage::handleDoubleTapForDoubleClickAtPoint(const IntPoint& point, OptionSet<WebEvent::Modifier> modifiers, TransactionID lastLayerTreeTransactionId)
{
FloatPoint adjustedPoint;
@@ -1094,7 +1126,9 @@
FloatPoint adjustedPoint;
Node* nodeRespondingToClick = m_page->mainFrame().nodeRespondingToClickEvents(point, adjustedPoint);
if (!nodeRespondingToClick || !nodeRespondingToClick->renderer()) {
- send(Messages::WebPageProxy::DidNotHandleTapAsClick(roundedIntPoint(adjustedPoint)));
+ auto adjustedIntPoint = roundedIntPoint(adjustedPoint);
+ send(Messages::WebPageProxy::DidNotHandleTapAsMeaningfulClickAtPoint(adjustedIntPoint));
+ send(Messages::WebPageProxy::DidNotHandleTapAsClick(adjustedIntPoint));
return;
}
sendTapHighlightForNodeIfNecessary(requestID, nodeRespondingToClick);
@@ -1169,7 +1203,10 @@
clearSelection();
send(Messages::WebPageProxy::CommitPotentialTapFailed());
- send(Messages::WebPageProxy::DidNotHandleTapAsClick(roundedIntPoint(m_potentialTapLocation)));
+
+ auto adjustedIntPoint = roundedIntPoint(m_potentialTapLocation);
+ send(Messages::WebPageProxy::DidNotHandleTapAsMeaningfulClickAtPoint(adjustedIntPoint));
+ send(Messages::WebPageProxy::DidNotHandleTapAsClick(adjustedIntPoint));
}
void WebPage::cancelPotentialTap()
Modified: branches/safari-612.1.12-branch/Tools/ChangeLog (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/ChangeLog 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/ChangeLog 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1,3 +1,143 @@
+2021-05-03 Russell Epstein <[email protected]>
+
+ Cherry-pick r276853. rdar://problem/77458363
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Source/WebCore:
+
+ Add plumbing for a `ChromeClient` hook that's called when a mousedown or mouseup event is either prevented by
+ the page, or handled with a default event handler on the element (e.g. when clicking a link).
+
+ Test: fast/events/ios/did-not-handle-meaningful-click.html
+
+ * page/ChromeClient.h:
+ (WebCore::ChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::handleMousePressEvent):
+ (WebCore::EventHandler::handleMouseDoubleClickEvent):
+ (WebCore::EventHandler::handleMouseReleaseEvent):
+
+ Source/WebKit:
+
+ Add a simple heuristic to inform WKWebView iOS clients when a tap either failed to result in a synthetic click,
+ or resulted in a synthetic click that (probably) didn't have any "meaningful side effects". While this notion of
+ "meaningfulness" isn't well defined, the idea behind the heuristic is that it should distinguish between taps on
+ clickable elements like buttons or links that trigger some noticable change on the page, vs. taps on both
+ clickable or non-clickable elements that do not trigger any changes on the page.
+
+ For instance on a news-article-like page, this delegate method should be invoked when tapping on paragraph text
+ in the article, even if there is a click handler over the entire article or even body element. However, tapping
+ a link or a button on the same page should not cause this delegate method to be invoked. Additionally, if the
+ page explicitly prevents default behavior during a synthetic mouse event, this method should also *not* be
+ invoked.
+
+ This behavior is roughly similar to the existing delegate method `-_webView:didNotHandleTapAsClickAtPoint:`,
+ except that this variant allows for more wiggle room around what constitutes a "meaningful" interaction with the
+ page.
+
+ * UIProcess/API/APIUIClient.h:
+ (API::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+ * UIProcess/API/ios/WKWebViewPrivateForTestingIOS.h:
+ * UIProcess/API/ios/WKWebViewTestingIOS.mm:
+ (-[WKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ See Tools/ChangeLog for more details about this testing hook.
+
+ * UIProcess/Cocoa/UIDelegate.h:
+ * UIProcess/Cocoa/UIDelegate.mm:
+ (WebKit::UIDelegate::setDelegate):
+ (WebKit::UIDelegate::UIClient::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::didNotHandleTapAsMeaningfulClickAtPoint):
+ * UIProcess/ios/WebPageProxyIOS.mm:
+ (WebKit::WebPageProxy::didNotHandleTapAsMeaningfulClickAtPoint):
+ * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+ (WebKit::WebChromeClient::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebCoreSupport/WebChromeClient.h:
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::isProbablyMeaningfulClick):
+
+ Implement the core of the heuristic here. For now, it just examines the size of the click target. This isn't
+ going to satisfy the case where a page installs a click event handler on the body element (or a similar
+ element that encapsulates most of the page) and then performs hit-testing in their script, but it's somewhere to
+ start.
+
+ (WebKit::WebPage::completeSyntheticClick):
+ (WebKit::WebPage::attemptSyntheticClick):
+ (WebKit::WebPage::didHandleOrPreventMouseDownOrMouseUpEvent):
+ (WebKit::WebPage::handleTwoFingerTapAtPoint):
+ (WebKit::WebPage::commitPotentialTapFailed):
+
+ Tools:
+
+ Add test runner plumbing to test the new heuristic. Note that we can't just utilize the `WKUIDelegatePrivate`
+ method directly, since we end up overriding the web view's `UIClient` via `WKPageSetPageUIClient`, so the call
+ to `m_uiClient->didNotHandleTapAsMeaningfulClickAtPoint(point);` ends up being a no-op.
+
+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+ (WTR::InjectedBundle::didReceiveMessageToPage):
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::installDidNotHandleTapAsMeaningfulClickCallback):
+ (WTR::TestRunner::callDidNotHandleTapAsMeaningfulClickCallback):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestController.h:
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestInvocation.h:
+ * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+ (-[TestRunnerWKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
+ LayoutTests:
+
+ * fast/events/ios/did-not-handle-meaningful-click-expected.txt: Added.
+ * fast/events/ios/did-not-handle-meaningful-click.html: Added.
+
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276853 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-04-30 Wenson Hsieh <[email protected]>
+
+ [iOS] Add a heuristic to determine whether a synthetic click triggered any meaningful changes
+ https://bugs.webkit.org/show_bug.cgi?id=225240
+ rdar://77221196
+
+ Reviewed by Tim Horton.
+
+ Add test runner plumbing to test the new heuristic. Note that we can't just utilize the `WKUIDelegatePrivate`
+ method directly, since we end up overriding the web view's `UIClient` via `WKPageSetPageUIClient`, so the call
+ to `m_uiClient->didNotHandleTapAsMeaningfulClickAtPoint(point);` ends up being a no-op.
+
+ * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+ * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
+ (WTR::InjectedBundle::didReceiveMessageToPage):
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::installDidNotHandleTapAsMeaningfulClickCallback):
+ (WTR::TestRunner::callDidNotHandleTapAsMeaningfulClickCallback):
+ * WebKitTestRunner/InjectedBundle/TestRunner.h:
+ * WebKitTestRunner/TestController.cpp:
+ (WTR::TestController::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestController.h:
+ * WebKitTestRunner/TestInvocation.cpp:
+ (WTR::TestInvocation::didNotHandleTapAsMeaningfulClick):
+ * WebKitTestRunner/TestInvocation.h:
+ * WebKitTestRunner/cocoa/TestRunnerWKWebView.mm:
+ (-[TestRunnerWKWebView _didNotHandleTapAsMeaningfulClickAtPoint:]):
+
2021-04-30 Russell Epstein <[email protected]>
Cherry-pick r276744. rdar://problem/77402549
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl 2021-05-03 16:38:55 UTC (rev 276903)
@@ -256,6 +256,9 @@
object numberOfDFGCompiles(object function);
object neverInlineFunction(object function);
+ // UI delegate hooks.
+ undefined installDidNotHandleTapAsMeaningfulClickCallback(object callback);
+
// Swipe gestures
undefined installDidBeginSwipeCallback(object callback);
undefined installWillEndSwipeCallback(object callback);
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp 2021-05-03 16:38:55 UTC (rev 276903)
@@ -275,6 +275,11 @@
return;
}
+ if (WKStringIsEqualToUTF8CString(messageName, "CallDidNotHandleTapAsMeaningfulClickCallback")) {
+ m_testRunner->callDidNotHandleTapAsMeaningfulClickCallback();
+ return;
+ }
+
if (WKStringIsEqualToUTF8CString(messageName, "CallDidBeginSwipeCallback")) {
m_testRunner->callDidBeginSwipeCallback();
return;
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2021-05-03 16:38:55 UTC (rev 276903)
@@ -647,6 +647,7 @@
EnterFullscreenForElementCallbackID,
ExitFullscreenForElementCallbackID,
AppBoundRequestContextDataForDomainCallbackID,
+ DidNotHandleTapAsMeaningfulClickCallbackID,
FirstUIScriptCallbackID = 100
};
@@ -1107,6 +1108,16 @@
}));
}
+void TestRunner::installDidNotHandleTapAsMeaningfulClickCallback(JSValueRef callback)
+{
+ cacheTestRunnerCallback(DidNotHandleTapAsMeaningfulClickCallbackID, callback);
+}
+
+void TestRunner::callDidNotHandleTapAsMeaningfulClickCallback()
+{
+ callTestRunnerCallback(DidNotHandleTapAsMeaningfulClickCallbackID);
+}
+
void TestRunner::installDidBeginSwipeCallback(JSValueRef callback)
{
cacheTestRunnerCallback(DidBeginSwipeCallbackID, callback);
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -343,6 +343,9 @@
void installCustomMenuAction(JSStringRef name, bool dismissesAutomatically, JSValueRef callback);
void performCustomMenuAction();
+ void installDidNotHandleTapAsMeaningfulClickCallback(JSValueRef);
+ void callDidNotHandleTapAsMeaningfulClickCallback();
+
void installDidBeginSwipeCallback(JSValueRef);
void installWillEndSwipeCallback(JSValueRef);
void installDidEndSwipeCallback(JSValueRef);
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestController.cpp (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestController.cpp 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestController.cpp 2021-05-03 16:38:55 UTC (rev 276903)
@@ -2167,6 +2167,11 @@
exit(1);
}
+void TestController::didNotHandleTapAsMeaningfulClick()
+{
+ m_currentInvocation->didNotHandleTapAsMeaningfulClick();
+}
+
void TestController::didBeginNavigationGesture(WKPageRef)
{
m_currentInvocation->didBeginSwipe();
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestController.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestController.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestController.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -361,6 +361,8 @@
void completeMediaKeySystemPermissionCheck(WKMediaKeySystemPermissionCallbackRef);
void setIsMediaKeySystemPermissionGranted(bool);
+ void didNotHandleTapAsMeaningfulClick();
+
private:
WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(const TestOptions&);
WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration(const TestOptions&) const;
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestInvocation.cpp (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestInvocation.cpp 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestInvocation.cpp 2021-05-03 16:38:55 UTC (rev 276903)
@@ -1439,6 +1439,11 @@
m_textOutput.append(text);
}
+void TestInvocation::didNotHandleTapAsMeaningfulClick()
+{
+ postPageMessage("CallDidNotHandleTapAsMeaningfulClickCallback");
+}
+
void TestInvocation::didBeginSwipe()
{
postPageMessage("CallDidBeginSwipeCallback");
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestInvocation.h (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestInvocation.h 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/TestInvocation.h 2021-05-03 16:38:55 UTC (rev 276903)
@@ -64,6 +64,8 @@
static void dumpWebProcessUnresponsiveness(const char* errorMessage);
void outputText(const String&);
+ void didNotHandleTapAsMeaningfulClick();
+
void didBeginSwipe();
void willEndSwipe();
void didEndSwipe();
Modified: branches/safari-612.1.12-branch/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm (276902 => 276903)
--- branches/safari-612.1.12-branch/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm 2021-05-03 15:58:50 UTC (rev 276902)
+++ branches/safari-612.1.12-branch/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.mm 2021-05-03 16:38:55 UTC (rev 276903)
@@ -26,6 +26,7 @@
#import "config.h"
#import "TestRunnerWKWebView.h"
+#import "TestController.h"
#import "WebKitTestRunnerDraggingInfo.h"
#import <WebKit/WKUIDelegatePrivate.h>
#import <WebKit/WKWebViewPrivateForTesting.h>
@@ -396,6 +397,11 @@
self.didDismissPopoverCallback();
}
+- (void)_didNotHandleTapAsMeaningfulClickAtPoint:(CGPoint)point
+{
+ WTR::TestController::singleton().didNotHandleTapAsMeaningfulClick();
+}
+
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
[super scrollViewWillBeginZooming:scrollView withView:view];