Skip to content

Commit

Permalink
Introduce ContentChangeObserver class
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=194977
<rdar://problem/48338115>

Reviewed by Simon Fraser.

Source/WebCore:

This patch is about piping through all the related WK* calls.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::scheduleStyleRecalc):
(WebCore::Document::updateStyleIfNeeded):
(WebCore::Document::platformSuspendOrStopActiveDOMObjects):
* loader/FrameLoader.cpp:
* page/DOMTimer.cpp:
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::fired):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::clearTimeout):
* page/Frame.cpp:
(WebCore::Frame::willDetachPage):
* page/Page.h:
(WebCore::Page::contentChangeObserver):
* page/ios/EventHandlerIOS.mm:
(WebCore::EventHandler::mouseMoved):
* rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::updateElementRenderer):
(WebCore::CheckForVisibilityChange::CheckForVisibilityChange):
(WebCore::CheckForVisibilityChange::~CheckForVisibilityChange):

Source/WebKit:

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::handleSyntheticClick):
(WebKit::WebPage::completePendingSyntheticClickForContentChangeObserver):

Source/WebKitLegacy/ios:

* WebCoreSupport/WebChromeClientIOS.mm:
(WebChromeClientIOS::observedContentChange):
(WebChromeClientIOS::clearContentChangeObservers):


Canonical link: https://commits.webkit.org/209356@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242032 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
alanbaradlay committed Feb 25, 2019
1 parent 23ee917 commit 8cc3390
Show file tree
Hide file tree
Showing 17 changed files with 405 additions and 105 deletions.
33 changes: 33 additions & 0 deletions Source/WebCore/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
2019-02-24 Zalan Bujtas <zalan@apple.com>

Introduce ContentChangeObserver class
https://bugs.webkit.org/show_bug.cgi?id=194977
<rdar://problem/48338115>

Reviewed by Simon Fraser.

This patch is about piping through all the related WK* calls.

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.cpp:
(WebCore::Document::scheduleStyleRecalc):
(WebCore::Document::updateStyleIfNeeded):
(WebCore::Document::platformSuspendOrStopActiveDOMObjects):
* loader/FrameLoader.cpp:
* page/DOMTimer.cpp:
(WebCore::DOMTimer::install):
(WebCore::DOMTimer::fired):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::clearTimeout):
* page/Frame.cpp:
(WebCore::Frame::willDetachPage):
* page/Page.h:
(WebCore::Page::contentChangeObserver):
* page/ios/EventHandlerIOS.mm:
(WebCore::EventHandler::mouseMoved):
* rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::updateElementRenderer):
(WebCore::CheckForVisibilityChange::CheckForVisibilityChange):
(WebCore::CheckForVisibilityChange::~CheckForVisibilityChange):

2019-02-24 Simon Fraser <simon.fraser@apple.com>

Migrate from "fixedPositionRect" to "layoutViewport" in the scrolling tree
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/SourcesCocoa.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ page/cocoa/ResourceUsageOverlayCocoa.mm
page/cocoa/ResourceUsageThreadCocoa.mm
page/cocoa/SettingsBaseCocoa.mm

page/ios/ContentChangeObserver.mm
page/ios/EventHandlerIOS.mm
page/ios/FrameIOS.mm
page/ios/WebEventRegion.mm
Expand Down
6 changes: 6 additions & 0 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2065,6 +2065,7 @@
6F995A3A1A70833700A735F4 /* JSWebGLVertexArrayObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F995A301A70833700A735F4 /* JSWebGLVertexArrayObject.h */; };
6FA4454E898F2FC168BC38C1 /* JSBeforeUnloadEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 29E04A27BED2F81F98E9022B /* JSBeforeUnloadEvent.h */; };
6FB11B5C21783FD000E2A574 /* TextUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FB11B5921783FCF00E2A574 /* TextUtil.h */; settings = {ATTRIBUTES = (Private, ); }; };
6FB5E214221F2453003989CF /* ContentChangeObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FB5E212221F2447003989CF /* ContentChangeObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
6FE198172178397C00446F08 /* InlineLineBreaker.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FE198152178397C00446F08 /* InlineLineBreaker.h */; settings = {ATTRIBUTES = (Private, ); }; };
6FE7CFA22177EEF2005B1573 /* InlineItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FE7CFA02177EEF1005B1573 /* InlineItem.h */; };
6FE7CFA42177EF10005B1573 /* LayoutLineBreakBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FE7CFA32177EF10005B1573 /* LayoutLineBreakBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -9234,13 +9235,15 @@
6F995A301A70833700A735F4 /* JSWebGLVertexArrayObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLVertexArrayObject.h; sourceTree = "<group>"; };
6FB11B5921783FCF00E2A574 /* TextUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextUtil.h; sourceTree = "<group>"; };
6FB11B5B21783FCF00E2A574 /* TextUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextUtil.cpp; sourceTree = "<group>"; };
6FB5E212221F2447003989CF /* ContentChangeObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContentChangeObserver.h; sourceTree = "<group>"; };
6FBB860520B464B600DAD938 /* FormattingContextGeometry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FormattingContextGeometry.cpp; sourceTree = "<group>"; };
6FE198132178397B00446F08 /* InlineLineBreaker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineLineBreaker.cpp; sourceTree = "<group>"; };
6FE198152178397C00446F08 /* InlineLineBreaker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineLineBreaker.h; sourceTree = "<group>"; };
6FE7AA2621C37B6300296DCD /* MarginTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MarginTypes.h; sourceTree = "<group>"; };
6FE7CFA02177EEF1005B1573 /* InlineItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineItem.h; sourceTree = "<group>"; };
6FE7CFA32177EF10005B1573 /* LayoutLineBreakBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutLineBreakBox.h; sourceTree = "<group>"; };
6FE7CFA52177F069005B1573 /* LayoutLineBreakBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutLineBreakBox.cpp; sourceTree = "<group>"; };
6FE9F09222211035004C5082 /* ContentChangeObserver.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContentChangeObserver.mm; sourceTree = "<group>"; };
6FFDC43E212EFF1600A9CA91 /* FloatAvoider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatAvoider.cpp; sourceTree = "<group>"; };
6FFDC440212EFF1600A9CA91 /* FloatAvoider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatAvoider.h; sourceTree = "<group>"; };
709A01FD1E3D0BCC006B0D4C /* ModuleFetchFailureKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleFetchFailureKind.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -16585,6 +16588,8 @@
18A6CD6F0D8F2025001DC3CE /* ios */ = {
isa = PBXGroup;
children = (
6FB5E212221F2447003989CF /* ContentChangeObserver.h */,
6FE9F09222211035004C5082 /* ContentChangeObserver.mm */,
FE6938B51045D67E008EABB6 /* EventHandlerIOS.mm */,
FED13D3B0CEA936A00D89466 /* FrameIOS.mm */,
225A16B30D5C11E900090295 /* WebEventRegion.h */,
Expand Down Expand Up @@ -28687,6 +28692,7 @@
2DAF343D1EA7E0F100382CD3 /* ConstantPropertyMap.h in Headers */,
A818721C0977D3C0005826D9 /* ContainerNode.h in Headers */,
E1A1470811102B1500EEC0F3 /* ContainerNodeAlgorithms.h in Headers */,
6FB5E214221F2453003989CF /* ContentChangeObserver.h in Headers */,
BC5EB9810E82072500B25965 /* ContentData.h in Headers */,
51B45D211AB8D1E200117CD2 /* ContentExtension.h in Headers */,
5CDFA6C81AA4F2DA00EA8746 /* ContentExtensionActions.h in Headers */,
Expand Down
50 changes: 28 additions & 22 deletions Source/WebCore/dom/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
#endif

#if PLATFORM(IOS_FAMILY)
#include "ContentChangeObserver.h"
#include "CSSFontSelector.h"
#include "DeviceMotionClientIOS.h"
#include "DeviceMotionController.h"
Expand All @@ -266,8 +267,6 @@
#include "Geolocation.h"
#include "Navigator.h"
#include "NavigatorGeolocation.h"
#include "WKContentObservation.h"
#include "WKContentObservationInternal.h"
#endif

#if ENABLE(IOS_GESTURE_EVENTS)
Expand Down Expand Up @@ -1812,9 +1811,12 @@ void Document::scheduleStyleRecalc()
ASSERT(childNeedsStyleRecalc() || m_needsFullStyleRebuild);

#if PLATFORM(IOS_FAMILY)
if (WKIsObservingStyleRecalcScheduling()) {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: register this style recalc schedule and observe when it fires.");
WKSetObservedContentChange(WKContentIndeterminateChange);
if (auto* page = this->page()) {
auto& contentChangeObserver = page->contentChangeObserver();
if (contentChangeObserver.isObservingStyleRecalcScheduling()) {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: register this style recalc schedule and observe when it fires.");
contentChangeObserver.setObservedContentChange(WKContentIndeterminateChange);
}
}
#endif

Expand Down Expand Up @@ -2048,11 +2050,15 @@ bool Document::updateStyleIfNeeded()
}

#if PLATFORM(IOS_FAMILY)
auto observingContentChange = WKShouldObserveNextStyleRecalc();
if (observingContentChange) {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: start observing content change.");
WKSetShouldObserveNextStyleRecalc(false);
WKStartObservingContentChanges();
auto observingContentChange = false;
if (auto* page = this->page()) {
auto& contentChangeObserver = page->contentChangeObserver();
observingContentChange = contentChangeObserver.shouldObserveNextStyleRecalc();
if (observingContentChange) {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: start observing content change.");
contentChangeObserver.setShouldObserveNextStyleRecalc(false);
contentChangeObserver.startObservingContentChanges();
}
}
#endif
// The early exit above for !needsStyleRecalc() is needed when updateWidgetPositions() is called in runOrScheduleAsynchronousTasks().
Expand All @@ -2061,15 +2067,15 @@ bool Document::updateStyleIfNeeded()
resolveStyle();

#if PLATFORM(IOS_FAMILY)
if (observingContentChange) {
if (observingContentChange && page()) {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: stop observing content change.");
WKStopObservingContentChanges();
auto& contentChangeObserver = page()->contentChangeObserver();
contentChangeObserver.stopObservingContentChanges();

auto inDeterminedState = WKObservedContentChange() == WKContentVisibilityChange || !WebThreadCountOfObservedDOMTimers();
auto inDeterminedState = contentChangeObserver.observedContentChange() == WKContentVisibilityChange || !contentChangeObserver.countOfObservedDOMTimers();
if (inDeterminedState) {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: notify the pending synthetic click handler.");
if (auto* page = this->page())
page->chrome().client().observedContentChange(*frame());
page()->chrome().client().observedContentChange(*frame());
} else {
LOG_WITH_STREAM(ContentObservation, stream << "Document(" << this << ")::scheduleStyleRecalc: can't decided it yet.");
}
Expand Down Expand Up @@ -2651,13 +2657,13 @@ bool Document::shouldBypassMainWorldContentSecurityPolicy() const
void Document::platformSuspendOrStopActiveDOMObjects()
{
#if PLATFORM(IOS_FAMILY)
if (WebThreadCountOfObservedDOMTimers() > 0) {
LOG_WITH_STREAM(ContentObservation, stream << "Document::platformSuspendOrStopActiveDOMObjects: remove registered timers.");
if (auto* frame = this->frame()) {
if (auto* page = frame->page())
page->chrome().client().clearContentChangeObservers(*frame);
}
}
if (!page() || !frame())
return;
auto& page = *this->page();
if (!page.contentChangeObserver().countOfObservedDOMTimers())
return;
LOG_WITH_STREAM(ContentObservation, stream << "Document::platformSuspendOrStopActiveDOMObjects: remove registered timers.");
page.chrome().client().clearContentChangeObservers(*frame());
#endif
}

Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/loader/FrameLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@
#include "DocumentType.h"
#include "ResourceLoader.h"
#include "RuntimeApplicationChecks.h"
#include "WKContentObservation.h"
#endif

#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - FrameLoader::" fmt, this, ##__VA_ARGS__)
Expand Down
76 changes: 44 additions & 32 deletions Source/WebCore/page/DOMTimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@
#if PLATFORM(IOS_FAMILY)
#include "Chrome.h"
#include "ChromeClient.h"
#include "ContentChangeObserver.h"
#include "Frame.h"
#include "WKContentObservation.h"
#include "WKContentObservationInternal.h"
#endif

namespace WebCore {
Expand Down Expand Up @@ -219,24 +218,32 @@ int DOMTimer::install(ScriptExecutionContext& context, std::unique_ptr<Scheduled
// This reference will be released automatically when a one-shot timer fires, when the context
// is destroyed, or if explicitly cancelled by removeById.
DOMTimer* timer = new DOMTimer(context, WTFMove(action), timeout, singleShot);
#if PLATFORM(IOS_FAMILY)
if (WKIsObservingDOMTimerScheduling() && is<Document>(context)) {
bool didDeferTimeout = context.activeDOMObjectsAreSuspended();
if (!didDeferTimeout && timeout <= 250_ms && singleShot) {
WKSetObservedContentChange(WKContentIndeterminateChange);
WebThreadAddObservedDOMTimer(timer);
LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::install: registed this timer: (" << timer << ") and observe when it fires.");
}
}
#endif

timer->suspendIfNeeded();
InspectorInstrumentation::didInstallTimer(context, timer->m_timeoutId, timeout, singleShot);

// 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: (" << m_timeoutId << ") and observe when it fires.");
};

startObservingThisTimerIfNeeded();
#endif
return timer->m_timeoutId;
}

Expand Down Expand Up @@ -342,18 +349,23 @@ void DOMTimer::fired()
context.removeTimeout(m_timeoutId);

#if PLATFORM(IOS_FAMILY)
auto isObversingLastTimer = false;
auto isObservingLastTimer = false;
auto shouldBeginObservingChanges = false;
if (is<Document>(context)) {
isObversingLastTimer = WebThreadCountOfObservedDOMTimers() == 1;
shouldBeginObservingChanges = WebThreadContainsObservedDOMTimer(this);
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) {
LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::fired: start observing (" << this << ") timer callback.");
WKStartObservingContentChanges();
WKStartObservingStyleRecalcScheduling();
WebThreadRemoveObservedDOMTimer(this);
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

Expand All @@ -366,22 +378,22 @@ void DOMTimer::fired()

#if PLATFORM(IOS_FAMILY)
if (shouldBeginObservingChanges) {
LOG_WITH_STREAM(ContentObservation, stream << "DOMTimer::fired: stop observing (" << this << ") timer callback.");
WKStopObservingStyleRecalcScheduling();
WKStopObservingContentChanges();
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 = WKObservedContentChange();
auto observedContentChange = contentChangeObserver.observedContentChange();
// Check if the timer callback triggered either a sync or async style update.
auto inDeterminedState = observedContentChange == WKContentVisibilityChange || (isObversingLastTimer && observedContentChange == WKContentNoChange);
auto inDeterminedState = observedContentChange == WKContentVisibilityChange || (isObservingLastTimer && observedContentChange == WKContentNoChange);
if (inDeterminedState) {
LOG(ContentObservation, "DOMTimer::fired: in determined state.");
auto& document = downcast<Document>(context);
if (auto* page = document.page())
page->chrome().client().observedContentChange(*document.frame());
LOG_WITH_STREAM(ContentObservation, "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(ContentObservation, "DOMTimer::fired: wait until next style recalc fires.");
WKSetShouldObserveNextStyleRecalc(true);
LOG_WITH_STREAM(ContentObservation, "DOMTimer::fired(" << m_timeoutId << "): wait until next style recalc fires.");
contentChangeObserver.setShouldObserveNextStyleRecalc(true);
}
}
#endif
Expand Down
39 changes: 21 additions & 18 deletions Source/WebCore/page/DOMWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,9 @@
#endif

#if PLATFORM(IOS_FAMILY)
#include "WKContentObservation.h"
#include "WKContentObservationInternal.h"
#include "ContentChangeObserver.h"
#endif


namespace WebCore {
using namespace Inspector;

Expand Down Expand Up @@ -1684,21 +1682,26 @@ ExceptionOr<int> DOMWindow::setTimeout(JSC::ExecState& state, std::unique_ptr<Sc
void DOMWindow::clearTimeout(int timeoutId)
{
#if PLATFORM(IOS_FAMILY)
if (auto* frame = this->frame()) {
Document* document = frame->document();
if (timeoutId > 0 && document) {
DOMTimer* timer = document->findTimeout(timeoutId);
if (timer && WebThreadContainsObservedDOMTimer(timer)) {
LOG_WITH_STREAM(ContentObservation, stream << "DOMWindow::clearTimeout: remove registered timer (" << timer << ")");
WebThreadRemoveObservedDOMTimer(timer);

if (!WebThreadCountOfObservedDOMTimers()) {
if (Page* page = frame->page())
page->chrome().client().observedContentChange(*frame);
}
}
}
}
auto handleObservedTimerCancelIfNeeded = [&] {
if (!frame() || !frame()->document() || !frame()->document()->page())
return;
if (timeoutId <= 0)
return;
auto& document = *frame()->document();
auto* timer = document.findTimeout(timeoutId);
if (!timer)
return;
auto& page = *document.page();
auto& contentChangeObserver = page.contentChangeObserver();
if (!contentChangeObserver.containsObservedDOMTimer(*timer))
return;
LOG_WITH_STREAM(ContentObservation, stream << "DOMWindow::clearTimeout: remove registered timer (" << timer << ")");
contentChangeObserver.removeObservedDOMTimer(*timer);
if (contentChangeObserver.countOfObservedDOMTimers())
return;
page.chrome().client().observedContentChange(*frame());
};
handleObservedTimerCancelIfNeeded();
#endif
ScriptExecutionContext* context = scriptExecutionContext();
if (!context)
Expand Down
Loading

0 comments on commit 8cc3390

Please sign in to comment.