Skip to content
Permalink
Browse files
[ContentChangeObserver] Move observing logic from DOMTimer to Content…
…ChangeObserver

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):

Canonical link: https://commits.webkit.org/209382@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242058 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
alanbujtas committed Feb 25, 2019
1 parent 0bfbf87 commit ede42b81f8dc07c3f4c80e5c43538662fe3f3d10
Showing 6 changed files with 128 additions and 83 deletions.
@@ -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
@@ -42,10 +42,7 @@
#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);
@@ -149,6 +149,10 @@
#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())
@@ -67,10 +67,6 @@
#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 @@ class Page : public Supplementable<Page>, public CanMakeWeakPtr<Page> {
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 @@ class Page : public Supplementable<Page>, public CanMakeWeakPtr<Page> {

#if PLATFORM(IOS_FAMILY)
bool m_enclosedInScrollableAncestorView { false };
ContentChangeObserver m_contentChangeObserver;
std::unique_ptr<ContentChangeObserver> m_contentChangeObserver;
#endif

bool m_useSystemAppearance { false };
@@ -32,21 +32,23 @@
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();
bool isObservingContentChanges();

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 @@ class ContentChangeObserver {
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;
};

}
@@ -26,24 +26,79 @@
#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();
}

void ContentChangeObserver::stopObservingContentChanges()
{
WKStopObservingContentChanges();
WKStopObservingContentChanges();
}

bool ContentChangeObserver::isObservingContentChanges()
{
return WKObservingContentChanges();
return WKObservingContentChanges();
}

void ContentChangeObserver::startObservingDOMTimerScheduling()
@@ -106,19 +161,19 @@
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));
}

}

0 comments on commit ede42b8

Please sign in to comment.