[ContentChangeObserver] Move observing logic from DOMTimer to ContentChangeObserver
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2019 23:11:19 +0000 (23:11 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2019 23:11:19 +0000 (23:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194987
<rdar://problem/48342910>

Reviewed by Tim Horton.

Content obvservation logic should all move to the ContentChangeObserver class.

* page/DOMTimer.cpp:
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::fired):
* page/Page.cpp:
(WebCore::Page::Page):
* page/Page.h:
(WebCore::Page::contentChangeObserver):
* page/ios/ContentChangeObserver.h:
* page/ios/ContentChangeObserver.mm:
(WebCore::ContentChangeObserver::ContentChangeObserver):
(WebCore::ContentChangeObserver::registerDOMTimerForContentObservationIfNeeded):
(WebCore::ContentChangeObserver::startObservingDOMTimer):
(WebCore::ContentChangeObserver::stopObservingDOMTimer):
(WebCore::ContentChangeObserver::containsObservedDOMTimer):
(WebCore::ContentChangeObserver::addObservedDOMTimer):
(WebCore::ContentChangeObserver::removeObservedDOMTimer):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242058 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/page/DOMTimer.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/page/ios/ContentChangeObserver.h
Source/WebCore/page/ios/ContentChangeObserver.mm

index f3fbd1d..95920f9 100644 (file)
@@ -1,3 +1,30 @@
+2019-02-25  Zalan Bujtas  <zalan@apple.com>
+
+        [ContentChangeObserver] Move observing logic from DOMTimer to ContentChangeObserver
+        https://bugs.webkit.org/show_bug.cgi?id=194987
+        <rdar://problem/48342910>
+
+        Reviewed by Tim Horton.
+
+        Content obvservation logic should all move to the ContentChangeObserver class.
+
+        * page/DOMTimer.cpp:
+        (WebCore::DOMTimer::install):
+        (WebCore::DOMTimer::fired):
+        * page/Page.cpp:
+        (WebCore::Page::Page):
+        * page/Page.h:
+        (WebCore::Page::contentChangeObserver):
+        * page/ios/ContentChangeObserver.h:
+        * page/ios/ContentChangeObserver.mm:
+        (WebCore::ContentChangeObserver::ContentChangeObserver):
+        (WebCore::ContentChangeObserver::registerDOMTimerForContentObservationIfNeeded):
+        (WebCore::ContentChangeObserver::startObservingDOMTimer):
+        (WebCore::ContentChangeObserver::stopObservingDOMTimer):
+        (WebCore::ContentChangeObserver::containsObservedDOMTimer):
+        (WebCore::ContentChangeObserver::addObservedDOMTimer):
+        (WebCore::ContentChangeObserver::removeObservedDOMTimer):
+
 2019-02-25  John Wilander  <wilander@apple.com>
 
         Introduce and adopt new class RegistrableDomain for eTLD+1
index 8952b89..555890f 100644 (file)
 #include <wtf/StdLibExtras.h>
 
 #if PLATFORM(IOS_FAMILY)
-#include "Chrome.h"
-#include "ChromeClient.h"
 #include "ContentChangeObserver.h"
-#include "Frame.h"
 #endif
 
 namespace WebCore {
@@ -224,25 +221,9 @@ int DOMTimer::install(ScriptExecutionContext& context, std::unique_ptr<Scheduled
     // Keep track of nested timer installs.
     if (NestedTimersMap* nestedTimers = NestedTimersMap::instanceForContext(context))
         nestedTimers->add(timer->m_timeoutId, *timer);
-
 #if PLATFORM(IOS_FAMILY)
-    auto startObservingThisTimerIfNeeded = [&] {
-        if (!is<Document>(context))
-            return;
-        if (context.activeDOMObjectsAreSuspended())
-            return;
-        if (timeout > 250_ms || !singleShot)
-            return;
-        auto& contentChangeObserver = downcast<Document>(context).page()->contentChangeObserver();
-        if (!contentChangeObserver.isObservingDOMTimerScheduling())
-            return;
-
-        contentChangeObserver.setObservedContentChange(WKContentIndeterminateChange);
-        contentChangeObserver.addObservedDOMTimer(*timer);
-        LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::install: register this timer: (" << timer->m_timeoutId << ") and observe when it fires.");
-    };
-
-    startObservingThisTimerIfNeeded();
+    if (is<Document>(context))
+        downcast<Document>(context).page()->contentChangeObserver().registerDOMTimerForContentObservationIfNeeded(*timer, timeout, singleShot);
 #endif
     return timer->m_timeoutId;
 }
@@ -348,54 +329,20 @@ void DOMTimer::fired()
 
     context.removeTimeout(m_timeoutId);
 
-#if PLATFORM(IOS_FAMILY)
-    auto isObservingLastTimer = false;
-    auto shouldBeginObservingChanges = false;
-    Page* page = nullptr;
-    if (is<Document>(context) && downcast<Document>(context).page()) {
-        page = downcast<Document>(context).page();
-        auto& contentChangeObserver = page->contentChangeObserver();
-        isObservingLastTimer = contentChangeObserver.countOfObservedDOMTimers() == 1;
-        shouldBeginObservingChanges = contentChangeObserver.containsObservedDOMTimer(*this);
-    }
-
-    if (shouldBeginObservingChanges) {
-        ASSERT(page);
-        LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::fired: start observing (" << m_timeoutId << ") timer callback.");
-        auto& contentChangeObserver = page->contentChangeObserver();
-        contentChangeObserver.startObservingContentChanges();
-        contentChangeObserver.startObservingStyleRecalcScheduling();
-        contentChangeObserver.removeObservedDOMTimer(*this);
-    }
-#endif
-
     // Keep track nested timer installs.
     NestedTimersMap* nestedTimers = NestedTimersMap::instanceForContext(context);
     if (nestedTimers)
         nestedTimers->startTracking();
 
+#if PLATFORM(IOS_FAMILY)
+    Page* page = is<Document>(context) ? downcast<Document>(context).page() : nullptr;
+    if (page)
+        page->contentChangeObserver().startObservingDOMTimerExecute(*this);
+#endif
     m_action->execute(context);
-
 #if PLATFORM(IOS_FAMILY)
-    if (shouldBeginObservingChanges) {
-        ASSERT(page);
-        LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::fired: stop observing (" << m_timeoutId << ") timer callback.");
-        auto& contentChangeObserver = page->contentChangeObserver();
-        contentChangeObserver.stopObservingStyleRecalcScheduling();
-        contentChangeObserver.stopObservingContentChanges();
-
-        auto observedContentChange = contentChangeObserver.observedContentChange();
-        // Check if the timer callback triggered either a sync or async style update.
-        auto inDeterminedState = observedContentChange == WKContentVisibilityChange || (isObservingLastTimer && observedContentChange == WKContentNoChange);  
-        if (inDeterminedState) {
-            LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::fired(" << m_timeoutId << "): in determined state.");
-            page->chrome().client().observedContentChange(*downcast<Document>(context).frame());
-        } else if (observedContentChange == WKContentIndeterminateChange) {
-            // An async style recalc has been scheduled. Let's observe it.
-            LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::fired(" << m_timeoutId << "): wait until next style recalc fires.");
-            contentChangeObserver.setShouldObserveNextStyleRecalc(true);
-        }
-    }
+    if (page)
+        page->contentChangeObserver().stopObservingDOMTimerExecute(*this);
 #endif
 
     InspectorInstrumentation::didFireTimer(cookie);
index 0e87569..db6638f 100644 (file)
 #include "SelectionRect.h"
 #endif
 
+#if PLATFORM(IOS_FAMILY)
+#include "ContentChangeObserver.h"
+#endif
+
 namespace WebCore {
 
 static HashSet<Page*>& allPages()
@@ -231,6 +235,9 @@ Page::Page(PageConfiguration&& pageConfiguration)
     , m_performanceLoggingClient(WTFMove(pageConfiguration.performanceLoggingClient))
     , m_webGLStateTracker(WTFMove(pageConfiguration.webGLStateTracker))
     , m_libWebRTCProvider(WTFMove(pageConfiguration.libWebRTCProvider))
+#if PLATFORM(IOS_FAMILY)
+    , m_contentChangeObserver(std::make_unique<ContentChangeObserver>(*this))
+#endif
     , m_verticalScrollElasticity(ScrollElasticityAllowed)
     , m_horizontalScrollElasticity(ScrollElasticityAllowed)
     , m_domTimerAlignmentInterval(DOMTimer::defaultAlignmentInterval())
index f43d454..5e285ad 100644 (file)
 #include "MediaPlaybackTargetContext.h"
 #endif
 
-#if PLATFORM(IOS_FAMILY)
-#include "ContentChangeObserver.h"
-#endif
-
 namespace JSC {
 class Debugger;
 }
@@ -90,6 +86,9 @@ class CacheStorageProvider;
 class Chrome;
 class ChromeClient;
 class Color;
+#if PLATFORM(IOS_FAMILY)
+class ContentChangeObserver;
+#endif
 class ContextMenuClient;
 class ContextMenuController;
 class CookieJar;
@@ -257,7 +256,7 @@ public:
     PointerLockController& pointerLockController() const { return *m_pointerLockController; }
 #endif
 #if PLATFORM(IOS_FAMILY)
-    ContentChangeObserver& contentChangeObserver() { return m_contentChangeObserver; }
+    ContentChangeObserver& contentChangeObserver() { return *m_contentChangeObserver; }
 #endif
     LibWebRTCProvider& libWebRTCProvider() { return m_libWebRTCProvider.get(); }
     RTCController& rtcController() { return m_rtcController; }
@@ -816,7 +815,7 @@ private:
 
 #if PLATFORM(IOS_FAMILY)
     bool m_enclosedInScrollableAncestorView { false };
-    ContentChangeObserver m_contentChangeObserver;
+    std::unique_ptr<ContentChangeObserver> m_contentChangeObserver;
 #endif
     
     bool m_useSystemAppearance { false };
index 1189e96..78232b4 100644 (file)
 namespace WebCore {
 
 class DOMTimer;
+class Page;
 
 class ContentChangeObserver {
 public:
-    ContentChangeObserver() = default;
+    ContentChangeObserver(Page&);
+
+    void registerDOMTimerForContentObservationIfNeeded(const DOMTimer&, Seconds timeout, bool singleShot);
+    void startObservingDOMTimerExecute(const DOMTimer&);
+    void stopObservingDOMTimerExecute(const DOMTimer&);
 
     WEBCORE_EXPORT void startObservingContentChanges();
     WEBCORE_EXPORT void stopObservingContentChanges();
@@ -43,10 +48,7 @@ public:
 
     WEBCORE_EXPORT void startObservingDOMTimerScheduling();
     WEBCORE_EXPORT void stopObservingDOMTimerScheduling();
-    bool isObservingDOMTimerScheduling();
 
-    WEBCORE_EXPORT void startObservingStyleRecalcScheduling();
-    WEBCORE_EXPORT void stopObservingStyleRecalcScheduling();
     bool isObservingStyleRecalcScheduling();
 
     void setShouldObserveNextStyleRecalc(bool);
@@ -55,11 +57,19 @@ public:
     void setObservedContentChange(WKContentChange);
     WEBCORE_EXPORT WKContentChange observedContentChange();
 
-    void addObservedDOMTimer(DOMTimer&);
-    void removeObservedDOMTimer(DOMTimer&);
-    bool containsObservedDOMTimer(DOMTimer&);
+    void removeObservedDOMTimer(const DOMTimer&);
+    bool containsObservedDOMTimer(const DOMTimer&);
     WEBCORE_EXPORT unsigned countOfObservedDOMTimers();
     WEBCORE_EXPORT void clearObservedDOMTimers();
+
+private:
+    void addObservedDOMTimer(const DOMTimer&);
+    bool isObservingDOMTimerScheduling();
+
+    void startObservingStyleRecalcScheduling();
+    void stopObservingStyleRecalcScheduling();
+
+    Page& m_page;
 };
 
 }
index 09bb34c..700a6d1 100644 (file)
 #import "ContentChangeObserver.h"
 
 #if PLATFORM(IOS_FAMILY)
+#import "Chrome.h"
+#import "ChromeClient.h"
 #import "DOMTimer.h"
+#import "Logging.h"
+#import "Page.h"
 #import "WKContentObservationInternal.h"
 
 namespace WebCore {
 
+ContentChangeObserver::ContentChangeObserver(Page& page)
+    : m_page(page)
+{
+}
+
+void ContentChangeObserver::registerDOMTimerForContentObservationIfNeeded(const DOMTimer& timer, Seconds timeout, bool singleShot)
+{
+    if (!m_page.mainFrame().document())
+        return;
+    if (m_page.mainFrame().document()->activeDOMObjectsAreSuspended())
+        return;
+    if (timeout > 250_ms || !singleShot)
+        return;
+    if (!isObservingDOMTimerScheduling())
+        return;
+    setObservedContentChange(WKContentIndeterminateChange);
+    addObservedDOMTimer(timer);
+    LOG_WITH_STREAM(ContentObservation, stream << "registerDOMTimerForContentObservationIfNeeded: registed this timer: (" << &timer << ") and observe when it fires.");
+}
+
+void ContentChangeObserver::startObservingDOMTimerExecute(const DOMTimer& timer)
+{
+    if (!containsObservedDOMTimer(timer))
+        return;
+    LOG_WITH_STREAM(ContentObservation, stream << "startObservingDOMTimerExecute: start observing (" << &timer << ") timer callback.");
+    startObservingContentChanges();
+    startObservingStyleRecalcScheduling();
+}
+
+void ContentChangeObserver::stopObservingDOMTimerExecute(const DOMTimer& timer)
+{
+    if (!containsObservedDOMTimer(timer))
+        return;
+    removeObservedDOMTimer(timer);
+    stopObservingStyleRecalcScheduling();
+    stopObservingContentChanges();
+    auto observedContentChange = this->observedContentChange();
+    // Check if the timer callback triggered either a sync or async style update.
+    auto inDeterminedState = observedContentChange == WKContentVisibilityChange || (!countOfObservedDOMTimers() && observedContentChange == WKContentNoChange);  
+
+    LOG_WITH_STREAM(ContentObservation, stream << "stopObservingDOMTimerExecute: stop observing (" << &timer << ") timer callback.");
+    if (inDeterminedState) {
+        LOG_WITH_STREAM(ContentObservation, stream << "stopObservingDOMTimerExecute: (" << &timer << ") in determined state.");
+        m_page.chrome().client().observedContentChange(m_page.mainFrame());
+    } else if (observedContentChange == WKContentIndeterminateChange) {
+        // An async style recalc has been scheduled. Let's observe it.
+        LOG_WITH_STREAM(ContentObservation, stream << "stopObservingDOMTimerExecute: (" << &timer << ") wait until next style recalc fires.");
+        setShouldObserveNextStyleRecalc(true);
+    }
+}
+
 void ContentChangeObserver::startObservingContentChanges()
 {
     WKStartObservingContentChanges();
@@ -38,12 +93,12 @@ void ContentChangeObserver::startObservingContentChanges()
 
 void ContentChangeObserver::stopObservingContentChanges()
 {
-    WKStopObservingContentChanges();   
+    WKStopObservingContentChanges();
 }
 
 bool ContentChangeObserver::isObservingContentChanges()
 {
-    return WKObservingContentChanges();   
+    return WKObservingContentChanges();
 }
 
 void ContentChangeObserver::startObservingDOMTimerScheduling()
@@ -106,19 +161,19 @@ void ContentChangeObserver::setObservedContentChange(WKContentChange change)
     WKSetObservedContentChange(change);
 }
 
-bool ContentChangeObserver::containsObservedDOMTimer(DOMTimer& timer)
+bool ContentChangeObserver::containsObservedDOMTimer(const DOMTimer& timer)
 {
-    return WebThreadContainsObservedDOMTimer(&timer);
+    return WebThreadContainsObservedDOMTimer(const_cast<DOMTimer*>(&timer));
 }
 
-void ContentChangeObserver::addObservedDOMTimer(DOMTimer& timer)
+void ContentChangeObserver::addObservedDOMTimer(const DOMTimer& timer)
 {
-    WebThreadAddObservedDOMTimer(&timer);
+    WebThreadAddObservedDOMTimer(const_cast<DOMTimer*>(&timer));
 }
 
-void ContentChangeObserver::removeObservedDOMTimer(DOMTimer& timer)
+void ContentChangeObserver::removeObservedDOMTimer(const DOMTimer& timer)
 {
-    WebThreadRemoveObservedDOMTimer(&timer);
+    WebThreadRemoveObservedDOMTimer(const_cast<DOMTimer*>(&timer));
 }
 
 }