summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_fission_animation_styling_in_transformed_oopif.html
blob: d85d77f55225ed0246b8b2f2835f02621e7df737 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<!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>