Commit 389cf84d authored by szager's avatar szager Committed by Commit bot

IntersectionObserver: use post task inside of resume().

Rather than running callbacks immediately, post a task to run the
callbacks, to avoid conflicts while undeferring a page.

R=dcheng@chromium.org
BUG=670092

Review-Url: https://codereview.chromium.org/2565863002
Cr-Commit-Position: refs/heads/master@{#438043}
parent 2e30a3df
......@@ -26,9 +26,7 @@ IntersectionObserverController::IntersectionObserverController(
IntersectionObserverController::~IntersectionObserverController() {}
void IntersectionObserverController::scheduleIntersectionObserverForDelivery(
IntersectionObserver& observer) {
m_pendingIntersectionObservers.add(&observer);
void IntersectionObserverController::postTaskToDeliverObservations() {
if (!m_weakPtrFactory.hasWeakPtrs()) {
// TODO(ojan): These tasks decide whether to throttle a subframe, so they
// need to be unthrottled, but we should throttle all the other tasks
......@@ -41,12 +39,18 @@ void IntersectionObserverController::scheduleIntersectionObserverForDelivery(
}
}
void IntersectionObserverController::scheduleIntersectionObserverForDelivery(
IntersectionObserver& observer) {
m_pendingIntersectionObservers.add(&observer);
postTaskToDeliverObservations();
}
void IntersectionObserverController::resume() {
// If the callback fired while DOM objects were suspended, notifications might
// be late, so deliver them right away (rather than waiting to fire again).
if (m_callbackFiredWhileSuspended) {
m_callbackFiredWhileSuspended = false;
deliverIntersectionObservations();
postTaskToDeliverObservations();
}
}
......
......@@ -39,6 +39,7 @@ class IntersectionObserverController
private:
explicit IntersectionObserverController(Document*);
void postTaskToDeliverObservations();
private:
// IntersectionObservers for which this is the tracking document.
......
......@@ -6,6 +6,7 @@
#include "core/dom/IntersectionObserverCallback.h"
#include "core/dom/IntersectionObserverInit.h"
#include "core/frame/FrameView.h"
#include "platform/testing/UnitTestHelpers.h"
#include "web/WebViewImpl.h"
#include "web/tests/sim/SimCompositor.h"
......@@ -67,4 +68,63 @@ TEST_F(IntersectionObserverTest, ObserveSchedulesFrame) {
EXPECT_TRUE(compositor().needsBeginFrame());
}
TEST_F(IntersectionObserverTest, ResumePostsTask) {
webView().resize(WebSize(800, 600));
SimRequest mainResource("https://example.com/", "text/html");
loadURL("https://example.com/");
mainResource.complete(
"<div id='leading-space' style='height: 700px;'></div>"
"<div id='target'></div>"
"<div id='trailing-space' style='height: 700px;'></div>");
IntersectionObserverInit observerInit;
DummyExceptionStateForTesting exceptionState;
TestIntersectionObserverCallback* observerCallback =
new TestIntersectionObserverCallback(document());
IntersectionObserver* observer = IntersectionObserver::create(
observerInit, *observerCallback, exceptionState);
ASSERT_FALSE(exceptionState.hadException());
Element* target = document().getElementById("target");
ASSERT_TRUE(target);
observer->observe(target, exceptionState);
compositor().beginFrame();
testing::runPendingTasks();
EXPECT_EQ(observerCallback->callCount(), 0);
// When document is not suspended, beginFrame() will generate notifications
// and post a task to deliver them.
document().view()->layoutViewportScrollableArea()->setScrollOffset(
ScrollOffset(0, 300), ProgrammaticScroll);
compositor().beginFrame();
EXPECT_EQ(observerCallback->callCount(), 0);
testing::runPendingTasks();
EXPECT_EQ(observerCallback->callCount(), 1);
// When a document is suspended, beginFrame() will generate a notification,
// but it will not be delivered. The notification will, however, be
// available via takeRecords();
document().suspendScheduledTasks();
document().view()->layoutViewportScrollableArea()->setScrollOffset(
ScrollOffset(0, 0), ProgrammaticScroll);
compositor().beginFrame();
EXPECT_EQ(observerCallback->callCount(), 1);
testing::runPendingTasks();
EXPECT_EQ(observerCallback->callCount(), 1);
EXPECT_FALSE(observer->takeRecords(exceptionState).isEmpty());
// Generate a notification while document is suspended; then resume document.
// Notification should happen in a post task.
document().view()->layoutViewportScrollableArea()->setScrollOffset(
ScrollOffset(0, 300), ProgrammaticScroll);
compositor().beginFrame();
testing::runPendingTasks();
EXPECT_EQ(observerCallback->callCount(), 1);
document().resumeScheduledTasks();
EXPECT_EQ(observerCallback->callCount(), 1);
testing::runPendingTasks();
EXPECT_EQ(observerCallback->callCount(), 2);
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment