summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/test/mochitest/helper_fission_animation_styling_in_oopif.html
blob: 12221d07030d2ab65ae13c8bfa32e3474ef93d95 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>Test for scrolled out of view animation optimization in an OOPIF</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 cause any geometric changes and doesn't run on the
    // compositor either
    extraStyle.sheet.insertRule("@keyframes anim { from { color: red; } to { color: blue; } }", 0);

    const div = document.createElement("div");
    // Position an element for animation at top: 20px.
    div.style = "position: absolute; top: 40px; animation: anim 1s infinite; box-shadow: 0px -20px red;";
    div.setAttribute("id", "target");
    div.innerHTML = "hello";
    document.body.appendChild(div);
    script.onload = () => {
      // Force to flush the first style to avoid the first style is observed.
      target.getAnimations()[0];
      // FIXME: Bug 1578309 use anim.ready instead.
      promiseFrame().then(() => {
        FissionTestHelper.fireEventInEmbedder("OOPIF:SetupDone", true);
      });
    }
    return true;
  }

  const iframePromise = promiseOneEvent(window, "OOPIF:SetupDone", null);

  await FissionTestHelper.sendToOopif(testframe, `(${setup})()`);
  await iframePromise;
}

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 clipped out by
  // overflow: hidden style in the out-of-process iframe.
  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 clipped out " +
       "due to 'overflow: hidden' should be throttled");

  // Scroll synchronously to a position where the iframe gets visible.
  scroller.scrollTo(0, 1000);
  await new Promise(resolve => {
    scroller.addEventListener("scroll", resolve, { once: true });
  });

  // Wait for a frame to make sure the notification of the last scroll position
  // from APZC reaches the iframe process
  await observe_styling_in_oopif(1);

  styleCount = await observe_styling_in_oopif(5);
  is(styleCount, 5,
     "Animation in an out-of-process iframe which is no longer clipped out " +
       "should NOT be throttled");

  // Scroll synchronously to a position where the iframe is invisible again.
  scroller.scrollTo(0, 0);
  await new Promise(resolve => {
    scroller.addEventListener("scroll", resolve, { once: true });
  });

  // Wait for a frame to make sure the notification of the last scroll position
  // from APZC reaches the iframe process
  await observe_styling_in_oopif(1);

  styleCount = await observe_styling_in_oopif(5);
  is(styleCount, 0,
     "Animation in an out-of-process iframe which is clipped out again " +
       "should be throttled again");

  // ===== Asyncronous scrolling tests =====
  scroller.style.overflow = "scroll";
  // Scroll asynchronously to a position where the animating element gets
  // visible.
  scroller.scrollTo({ left: 0, top: 750, 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 now visible by " +
       "asynchronous scrolling should NOT be throttled");

  // Scroll asynchronously to a position where the iframe is still visible but
  // the animating element gets invisible.
  scroller.scrollTo({ left: 0, top: 720, 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 by " +
       "asynchronous scrolling should be throttled");

  // Scroll asynchronously to a position where the animating element gets
  // visible again.
  scroller.scrollTo({ left: 0, top: 750, behavior: "smooth"});

  // Wait for the asyncronous scroll finish.
  await observe_styling_in_oopif(60);

  styleCount = await observe_styling_in_oopif(5);
  is(styleCount, 5,
     "Animation in an out-of-process iframe appeared by the asynchronous " +
       "scrolling should be NOT throttled");
}

  </script>
</head>
<div style="width: 300px; height: 300px; overflow: hidden;" id="scroller">
  <div style="width: 100%; height: 1000px;"></div>
  <!-- I am not sure it's worth setting scrolling="no" and pointer-events: none. -->
  <!-- I just want to make sure that HitTestingTreeNode is generated even with these properties. -->
  <iframe scrolling="no" style="pointer-events: none;" id="testframe"></iframe>
</div>
</html>