Source code

Revision control

Copy as Markdown

Other Tools

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for scrolled out of view animation optimization in an OOPIF transformed by rotate(45deg)</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<script src="helper_fission_utils.js"></script>
<script src="apz_test_utils.js"></script>
<script>
fission_subtest_init();
FissionTestHelper.startTestPromise
.then(waitUntilApzStable)
.then(loadOOPIFrame("testframe", "helper_fission_empty.html"))
.then(waitUntilApzStable)
.then(test)
.then(FissionTestHelper.subtestDone, FissionTestHelper.subtestFailed);
async function setup_in_oopif() {
const setup = function() {
// Load utility functions for animation stuff.
const script = document.createElement("script");
script.setAttribute("src", "/tests/dom/animation/test/testcommon.js");
document.head.appendChild(script);
const extraStyle = document.createElement("style");
document.head.appendChild(extraStyle);
// an animation doesn't affect any geometric changes and doesn't run on the
// compositor either
extraStyle.sheet.insertRule("@keyframes anim { from { color: red; } to { color: blue; } }", 0);
const animation = document.createElement("div");
animation.style = "animation: anim 1s infinite;";
animation.innerHTML = "hello";
document.body.appendChild(animation);
script.onload = () => {
const rect = animation.getBoundingClientRect();
FissionTestHelper.fireEventInEmbedder("OOPIF:SetupDone",
[rect.right, rect.bottom]);
}
return true;
}
const iframePromise = promiseOneEvent(window, "OOPIF:SetupDone", null);
await FissionTestHelper.sendToOopif(testframe, `(${setup})()`);
const rectData = await iframePromise;
return rectData.data;
}
async function observe_styling_in_oopif(aFrameCount) {
const observe_styling = function(frameCount) {
// Start in a rAF callback.
waitForAnimationFrames(1).then(() => {
observeStyling(frameCount).then(markers => {
FissionTestHelper.fireEventInEmbedder("OOPIF:StyleCount", markers.length);
});
});
return true;
}
const iframePromise = promiseOneEvent(window, "OOPIF:StyleCount", null);
await FissionTestHelper.sendToOopif(testframe, `(${observe_styling})(${aFrameCount})`);
const styleCountData = await iframePromise;
return styleCountData.data;
}
// The actual test
async function test() {
// Generate an infinite animation which is initially scrolled out of view.
// setup_in_oopif() returns the right bottom position of the animating element
// on the iframe coodinate system.
const [right, bottom] = await setup_in_oopif();
let styleCount = await observe_styling_in_oopif(5);
is(styleCount, 0,
"Animation in an out-of-process iframe which is initially scrolled out " +
"of view should be throttled");
const topPositionOfIFrame = testframe.getBoundingClientRect().top -
scroller.clientHeight;
// Scroll asynchronously to a position where the animating element gets
// visible.
scroller.scrollTo({ left: 0, top: topPositionOfIFrame + 1, behavior: "smooth"});
// Wait for the asyncronous scroll finish. `60` frames is the same number in
// helper_fission_scroll_oopif.html
await observe_styling_in_oopif(60);
styleCount = await observe_styling_in_oopif(5);
is(styleCount, 5,
"Animation in an out-of-process iframe which is no longer scrolled out " +
"of view should NOT be throttled");
// Calculate the right bottom position of the animation which is in an iframe
// rotated by `rotate(45deg)`
const rightBottomPositionOfAnimation =
right / Math.sqrt(2) + bottom / Math.sqrt(2);
// Scroll asynchronously to a position where the animating element gets
// invisible again.
scroller.scrollTo({ left: 0,
top: topPositionOfIFrame + scroller.clientHeight + rightBottomPositionOfAnimation,
behavior: "smooth"});
// Wait for the asyncronous scroll finish.
await observe_styling_in_oopif(60);
styleCount = await observe_styling_in_oopif(5);
is(styleCount, 0,
"Animation in an out-of-process iframe which is scrolled out of view " +
"again should be throttled");
}
</script>
</head>
<div style="width: 300px; height: 300px; overflow: scroll;" id="scroller">
<div style="width: 100%; height: 1000px;"></div>
<div style="transform: rotate(45deg);">
<iframe scrolling="no" style="pointer-events: none;" id="testframe" frameborder="0"></iframe>
</div>
<div style="width: 100%; height: 1000px;"></div>
</div>
</html>