- Revision
- 242403
- Author
- [email protected]
- Date
- 2019-03-04 16:43:41 -0800 (Mon, 04 Mar 2019)
Log Message
[ContentChangeObserver] Introduce fixed duration content observation
https://bugs.webkit.org/show_bug.cgi?id=195295
<rdar://problem/48579913>
Reviewed by Simon Fraser.
Source/WebCore:
Some pages have a runloop-like scheduling setup where the content triggering change happens at a nested timer firing.
This patch helps finding cases like that using a 32ms long fixed window. Currently nested timers get dropped on the floor and
we stop observing for content changes before they even get fired.
Test: fast/events/touch/ios/visibility-change-happens-on-timer-hops.html
* page/ios/ContentChangeObserver.cpp:
(WebCore::ContentChangeObserver::ContentChangeObserver):
(WebCore::ContentChangeObserver::startContentObservationForDuration):
(WebCore::ContentChangeObserver::stopDurationBasedContentObservation):
(WebCore::ContentChangeObserver::hasDeterminateState const):
(WebCore::ContentChangeObserver::adjustObservedState):
* page/ios/ContentChangeObserver.h:
(WebCore::ContentChangeObserver::isObservingContentChanges const):
(WebCore::ContentChangeObserver::hasPendingActivity const):
Source/WebKit:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::handleSyntheticClick):
LayoutTests:
* fast/events/touch/ios/visibility-change-happens-on-timer-hops-expected.txt: Added.
* fast/events/touch/ios/visibility-change-happens-on-timer-hops.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (242402 => 242403)
--- trunk/LayoutTests/ChangeLog 2019-03-05 00:42:33 UTC (rev 242402)
+++ trunk/LayoutTests/ChangeLog 2019-03-05 00:43:41 UTC (rev 242403)
@@ -1,3 +1,14 @@
+2019-03-04 Zalan Bujtas <[email protected]>
+
+ [ContentChangeObserver] Introduce fixed duration content observation
+ https://bugs.webkit.org/show_bug.cgi?id=195295
+ <rdar://problem/48579913>
+
+ Reviewed by Simon Fraser.
+
+ * fast/events/touch/ios/visibility-change-happens-on-timer-hops-expected.txt: Added.
+ * fast/events/touch/ios/visibility-change-happens-on-timer-hops.html: Added.
+
2019-03-04 Wenson Hsieh <[email protected]>
Native text selection UI is incorrectly suppressed in Microsoft Visio
Added: trunk/LayoutTests/fast/events/touch/ios/visibility-change-happens-on-timer-hops-expected.txt (0 => 242403)
--- trunk/LayoutTests/fast/events/touch/ios/visibility-change-happens-on-timer-hops-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/visibility-change-happens-on-timer-hops-expected.txt 2019-03-05 00:43:41 UTC (rev 242403)
@@ -0,0 +1,2 @@
+PASS if 'clicked' text is not shown below.
+
Added: trunk/LayoutTests/fast/events/touch/ios/visibility-change-happens-on-timer-hops.html (0 => 242403)
--- trunk/LayoutTests/fast/events/touch/ios/visibility-change-happens-on-timer-hops.html (rev 0)
+++ trunk/LayoutTests/fast/events/touch/ios/visibility-change-happens-on-timer-hops.html 2019-03-05 00:43:41 UTC (rev 242403)
@@ -0,0 +1,66 @@
+<html>
+<head>
+<title>This tests the case when nested timers trigger visible content change</title>
+<script src=""
+<style>
+#tapthis {
+ width: 400px;
+ height: 400px;
+ border: 1px solid green;
+}
+
+#becomesVisible {
+ visibility: hidden;
+ width: 100px;
+ height: 100px;
+ background-color: green;
+}
+</style>
+<script>
+async function test() {
+ if (!window.testRunner || !testRunner.runUIScript)
+ return;
+
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+
+ let rect = tapthis.getBoundingClientRect();
+ let x = rect.left + rect.width / 2;
+ let y = rect.top + rect.height / 2;
+
+ await tapAtPoint(x, y);
+}
+</script>
+</head>
+<body _onload_="test()">
+<div id=tapthis>PASS if 'clicked' text is not shown below.</div>
+<div id=becomesVisible></div>
+<pre id=result></pre>
+<script>
+tapthis.addEventListener("mouseover", function( event ) {
+ // 1. Install a short timer on hover
+ setTimeout(function() {
+ // 2. Trigger some non-visibility style change with forcing offsetHeight.
+ becomesVisible.style.marginLeft = "5px";
+ document.body.offsetHeight;
+
+ // 3. Install a nested timer with visibility change.
+ setTimeout(function() {
+ becomesVisible.style.visibility = "visible";
+ document.body.offsetHeight;
+ if (window.testRunner)
+ setTimeout(testRunner.notifyDone(), 0);
+ }, 10);
+ }, 0);
+}, false);
+
+becomesVisible.addEventListener("click", function( event ) {
+ result.innerHTML = "clicked hidden";
+}, false);
+
+tapthis.addEventListener("click", function( event ) {
+ result.innerHTML = "clicked";
+}, false);
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (242402 => 242403)
--- trunk/Source/WebCore/ChangeLog 2019-03-05 00:42:33 UTC (rev 242402)
+++ trunk/Source/WebCore/ChangeLog 2019-03-05 00:43:41 UTC (rev 242403)
@@ -1,3 +1,27 @@
+2019-03-04 Zalan Bujtas <[email protected]>
+
+ [ContentChangeObserver] Introduce fixed duration content observation
+ https://bugs.webkit.org/show_bug.cgi?id=195295
+ <rdar://problem/48579913>
+
+ Reviewed by Simon Fraser.
+
+ Some pages have a runloop-like scheduling setup where the content triggering change happens at a nested timer firing.
+ This patch helps finding cases like that using a 32ms long fixed window. Currently nested timers get dropped on the floor and
+ we stop observing for content changes before they even get fired.
+
+ Test: fast/events/touch/ios/visibility-change-happens-on-timer-hops.html
+
+ * page/ios/ContentChangeObserver.cpp:
+ (WebCore::ContentChangeObserver::ContentChangeObserver):
+ (WebCore::ContentChangeObserver::startContentObservationForDuration):
+ (WebCore::ContentChangeObserver::stopDurationBasedContentObservation):
+ (WebCore::ContentChangeObserver::hasDeterminateState const):
+ (WebCore::ContentChangeObserver::adjustObservedState):
+ * page/ios/ContentChangeObserver.h:
+ (WebCore::ContentChangeObserver::isObservingContentChanges const):
+ (WebCore::ContentChangeObserver::hasPendingActivity const):
+
2019-03-04 Wenson Hsieh <[email protected]>
Native text selection UI is incorrectly suppressed in Microsoft Visio
Modified: trunk/Source/WebCore/page/ios/ContentChangeObserver.cpp (242402 => 242403)
--- trunk/Source/WebCore/page/ios/ContentChangeObserver.cpp 2019-03-05 00:42:33 UTC (rev 242402)
+++ trunk/Source/WebCore/page/ios/ContentChangeObserver.cpp 2019-03-05 00:43:41 UTC (rev 242403)
@@ -38,9 +38,26 @@
ContentChangeObserver::ContentChangeObserver(Document& document)
: m_document(document)
+ , m_contentObservationTimer([this] { stopDurationBasedContentObservation(); })
{
}
+void ContentChangeObserver::startContentObservationForDuration(Seconds duration)
+{
+ if (hasVisibleChangeState())
+ return;
+ LOG_WITH_STREAM(ContentObservation, stream << "startContentObservationForDuration: start observing the content for " << duration.milliseconds() << "ms");
+ adjustObservedState(Event::StartedFixedObservationTimeWindow);
+ m_contentObservationTimer.startOneShot(duration);
+}
+
+void ContentChangeObserver::stopDurationBasedContentObservation()
+{
+ LOG_WITH_STREAM(ContentObservation, stream << "stopDurationBasedContentObservation: stop duration based content observing ");
+ adjustObservedState(Event::EndedFixedObservationTimeWindow);
+ notifyContentChangeIfNeeded();
+}
+
void ContentChangeObserver::didInstallDOMTimer(const DOMTimer& timer, Seconds timeout, bool singleShot)
{
if (m_document.activeDOMObjectsAreSuspended())
@@ -179,7 +196,7 @@
{
if (hasVisibleChangeState())
return true;
- return observedContentChange() == WKContentNoChange && !hasObservedDOMTimer() && !m_document.hasPendingStyleRecalc();
+ return observedContentChange() == WKContentNoChange && !hasPendingActivity();
}
void ContentChangeObserver::adjustObservedState(Event event)
@@ -189,6 +206,7 @@
setHasNoChangeState();
break;
case Event::InstalledDOMTimer:
+ case Event::StartedFixedObservationTimeWindow:
// Expecting a timer fire. Promote to an indeterminate state.
ASSERT(!hasVisibleChangeState());
setHasIndeterminateState();
@@ -195,8 +213,9 @@
break;
case Event::RemovedDOMTimer:
case Event::StyleRecalcFinished:
+ case Event::EndedFixedObservationTimeWindow:
// Demote to "no change" when there's no pending activity anymore.
- if (observedContentChange() == WKContentIndeterminateChange && !hasObservedDOMTimer() && !m_document.hasPendingStyleRecalc())
+ if (observedContentChange() == WKContentIndeterminateChange && !hasPendingActivity())
setHasNoChangeState();
break;
case Event::ContentVisibilityChanged:
Modified: trunk/Source/WebCore/page/ios/ContentChangeObserver.h (242402 => 242403)
--- trunk/Source/WebCore/page/ios/ContentChangeObserver.h 2019-03-05 00:42:33 UTC (rev 242402)
+++ trunk/Source/WebCore/page/ios/ContentChangeObserver.h 2019-03-05 00:43:41 UTC (rev 242403)
@@ -27,6 +27,7 @@
#if PLATFORM(IOS_FAMILY)
+#include "Timer.h"
#include "WKContentObservation.h"
namespace WebCore {
@@ -38,6 +39,7 @@
public:
ContentChangeObserver(Document&);
+ WEBCORE_EXPORT void startContentObservationForDuration(Seconds duration);
WEBCORE_EXPORT WKContentChange observedContentChange() const;
void didInstallDOMTimer(const DOMTimer&, Seconds timeout, bool singleShot);
@@ -102,7 +104,7 @@
void setShouldObserveNextStyleRecalc(bool);
bool isObservingStyleRecalc() const { return m_isObservingStyleRecalc; }
- bool isObservingContentChanges() const { return m_domTimerisBeingExecuted || m_styleRecalcIsBeingExecuted; }
+ bool isObservingContentChanges() const { return m_domTimerisBeingExecuted || m_styleRecalcIsBeingExecuted || m_contentObservationTimer.isActive(); }
void clearObservedDOMTimers() { m_DOMTimerList.clear(); }
void clearTimersAndReportContentChange();
@@ -117,16 +119,23 @@
void notifyContentChangeIfNeeded();
+ void stopDurationBasedContentObservation();
+
+ bool hasPendingActivity() const { return hasObservedDOMTimer() || m_document.hasPendingStyleRecalc() || m_contentObservationTimer.isActive(); }
+
enum class Event {
ContentObservationStarted,
InstalledDOMTimer,
RemovedDOMTimer,
StyleRecalcFinished,
- ContentVisibilityChanged
+ ContentVisibilityChanged,
+ StartedFixedObservationTimeWindow,
+ EndedFixedObservationTimeWindow
};
void adjustObservedState(Event);
Document& m_document;
+ Timer m_contentObservationTimer;
HashSet<const DOMTimer*> m_DOMTimerList;
bool m_isObservingStyleRecalc { false };
bool m_styleRecalcIsBeingExecuted { false };
Modified: trunk/Source/WebKit/ChangeLog (242402 => 242403)
--- trunk/Source/WebKit/ChangeLog 2019-03-05 00:42:33 UTC (rev 242402)
+++ trunk/Source/WebKit/ChangeLog 2019-03-05 00:43:41 UTC (rev 242403)
@@ -1,3 +1,14 @@
+2019-03-04 Zalan Bujtas <[email protected]>
+
+ [ContentChangeObserver] Introduce fixed duration content observation
+ https://bugs.webkit.org/show_bug.cgi?id=195295
+ <rdar://problem/48579913>
+
+ Reviewed by Simon Fraser.
+
+ * WebProcess/WebPage/ios/WebPageIOS.mm:
+ (WebKit::WebPage::handleSyntheticClick):
+
2019-03-04 Truitt Savell <[email protected]>
Unreviewed, rolling out r242396.
Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (242402 => 242403)
--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-03-05 00:42:33 UTC (rev 242402)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-03-05 00:43:41 UTC (rev 242403)
@@ -552,6 +552,9 @@
mainframe.document()->updateStyleIfNeeded();
}
+ const Seconds observationDuration = 32_ms;
+ respondingDocument.contentChangeObserver().startContentObservationForDuration(observationDuration);
+
m_pendingSyntheticClickNode = nullptr;
m_pendingSyntheticClickLocation = FloatPoint();
m_pendingSyntheticClickModifiers = { };