Source code
Revision control
Copy as Markdown
Other Tools
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<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>
</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>
<script>
async function setup_in_oopif() {
let iframeURL = SimpleTest.getTestFileURL("helper_fission_plain.html");
iframeURL = iframeURL.replace(window.location.origin, "https://example.com");
// We can't use `setupCrossOriginIFrame` directly here since the iframe here
// is clipped out by an overflow: hidden ancestor, thus any APZ stuff
// corresponding to the iframe document hasn't been established.
const iframe = document.querySelector("iframe");
const iframeLoadPromise = promiseOneEvent(iframe, "load", null);
iframe.src = iframeURL;
await iframeLoadPromise;
return await SpecialPowers.spawn(iframe, [], async () => {
// Load utility functions for animation stuff.
const script = content.document.createElement("script");
script.setAttribute("src", "/tests/dom/animation/test/testcommon.js");
content.document.head.appendChild(script);
const extraStyle = content.document.createElement("style");
content.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 = content.document.createElement("div");
animation.style = "animation: anim 1s infinite;";
animation.innerHTML = "hello";
content.document.body.appendChild(animation);
return await new Promise(resolve => {
script.onload = () => {
const rect = animation.getBoundingClientRect();
resolve([rect.right, rect.bottom]);
};
});
});
}
async function observe_styling_in_oopif(aFrameCount) {
const iframe = document.querySelector("iframe");
return await SpecialPowers.spawn(iframe, [aFrameCount], async (frameCount) => {
// Start in a rAF callback.
await content.wrappedJSObject.waitForAnimationFrames(1);
return await content.wrappedJSObject.
observeStylingInTargetWindow(content.window, frameCount);
});
}
// 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 restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 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);
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 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);
restyleCount = await observe_styling_in_oopif(5);
is(restyleCount, 0,
"Animation in an out-of-process iframe which is scrolled out of view " +
"again should be throttled");
}
waitUntilApzStable()
.then(test)
.then(subtestDone, subtestFailed);
</script>
</html>