1 /*
2 * Copyright (c) 2013, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "third_party/blink/renderer/core/animation/animation.h"
32
33 #include <memory>
34
35 #include "base/bits.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h"
39 #include "third_party/blink/renderer/bindings/core/v8/v8_optional_effect_timing.h"
40 #include "third_party/blink/renderer/bindings/core/v8/v8_scroll_timeline_options.h"
41 #include "third_party/blink/renderer/core/animation/animation_clock.h"
42 #include "third_party/blink/renderer/core/animation/css/compositor_keyframe_double.h"
43 #include "third_party/blink/renderer/core/animation/css_number_interpolation_type.h"
44 #include "third_party/blink/renderer/core/animation/document_timeline.h"
45 #include "third_party/blink/renderer/core/animation/element_animations.h"
46 #include "third_party/blink/renderer/core/animation/keyframe_effect.h"
47 #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
48 #include "third_party/blink/renderer/core/animation/pending_animations.h"
49 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
50 #include "third_party/blink/renderer/core/animation/timing.h"
51 #include "third_party/blink/renderer/core/dom/document.h"
52 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
53 #include "third_party/blink/renderer/core/dom/events/event.h"
54 #include "third_party/blink/renderer/core/dom/events/native_event_listener.h"
55 #include "third_party/blink/renderer/core/dom/qualified_name.h"
56 #include "third_party/blink/renderer/core/paint/paint_layer.h"
57 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
58 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
59 #include "third_party/blink/renderer/platform/animation/compositor_animation.h"
60 #include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h"
61 #include "third_party/blink/renderer/platform/animation/compositor_target_property.h"
62 #include "third_party/blink/renderer/platform/bindings/microtask.h"
63 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
64 #include "third_party/blink/renderer/platform/heap/heap.h"
65 #include "third_party/blink/renderer/platform/testing/histogram_tester.h"
66 #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
67 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
68
69 namespace blink {
70
71 namespace {
72
MillisecondsToSeconds(double milliseconds)73 double MillisecondsToSeconds(double milliseconds) {
74 return milliseconds / 1000;
75 }
76
77 } // namespace
78
ExpectRelativeErrorWithinEpsilon(double expected,double observed)79 void ExpectRelativeErrorWithinEpsilon(double expected, double observed) {
80 EXPECT_NEAR(1.0, observed / expected, std::numeric_limits<double>::epsilon());
81 }
82
83 class AnimationAnimationTestNoCompositing : public RenderingTest {
84 public:
AnimationAnimationTestNoCompositing()85 AnimationAnimationTestNoCompositing()
86 : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
87
SetUp()88 void SetUp() override {
89 last_frame_time = 0;
90 RenderingTest::SetUp();
91 SetUpWithoutStartingTimeline();
92 StartTimeline();
93 }
94
SetUpWithoutStartingTimeline()95 void SetUpWithoutStartingTimeline() {
96 GetDocument().GetAnimationClock().ResetTimeForTesting();
97 timeline = GetDocument().Timeline();
98 timeline->ResetForTesting();
99 animation = timeline->Play(nullptr);
100 animation->setStartTime(0);
101 animation->setEffect(MakeAnimation());
102 }
103
StartTimeline()104 void StartTimeline() { SimulateFrame(0); }
105
MakeSimpleEffectModel()106 KeyframeEffectModelBase* MakeSimpleEffectModel() {
107 PropertyHandle PropertyHandleOpacity(GetCSSPropertyOpacity());
108 TransitionKeyframe* start_keyframe =
109 MakeGarbageCollected<TransitionKeyframe>(PropertyHandleOpacity);
110 start_keyframe->SetValue(std::make_unique<TypedInterpolationValue>(
111 CSSNumberInterpolationType(PropertyHandleOpacity),
112 std::make_unique<InterpolableNumber>(1.0)));
113 start_keyframe->SetOffset(0.0);
114 // Egregious hack: Sideload the compositor value.
115 // This is usually set in a part of the rendering process SimulateFrame
116 // doesn't call.
117 start_keyframe->SetCompositorValue(
118 MakeGarbageCollected<CompositorKeyframeDouble>(1.0));
119 TransitionKeyframe* end_keyframe =
120 MakeGarbageCollected<TransitionKeyframe>(PropertyHandleOpacity);
121 end_keyframe->SetValue(std::make_unique<TypedInterpolationValue>(
122 CSSNumberInterpolationType(PropertyHandleOpacity),
123 std::make_unique<InterpolableNumber>(0.0)));
124 end_keyframe->SetOffset(1.0);
125 // Egregious hack: Sideload the compositor value.
126 end_keyframe->SetCompositorValue(
127 MakeGarbageCollected<CompositorKeyframeDouble>(0.0));
128
129 TransitionKeyframeVector keyframes;
130 keyframes.push_back(start_keyframe);
131 keyframes.push_back(end_keyframe);
132
133 return MakeGarbageCollected<TransitionKeyframeEffectModel>(keyframes);
134 }
135
ResetWithCompositedAnimation()136 void ResetWithCompositedAnimation() {
137 // Get rid of the default animation.
138 animation->cancel();
139
140 RunDocumentLifecycle();
141
142 SetBodyInnerHTML("<div id='target'></div>");
143
144 MakeCompositedAnimation();
145 }
146
MakeCompositedAnimation()147 void MakeCompositedAnimation() {
148 // Create a compositable animation; in this case opacity from 1 to 0.
149 Timing timing;
150 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
151
152 Persistent<StringKeyframe> start_keyframe =
153 MakeGarbageCollected<StringKeyframe>();
154 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
155 SecureContextMode::kInsecureContext,
156 nullptr);
157 Persistent<StringKeyframe> end_keyframe =
158 MakeGarbageCollected<StringKeyframe>();
159 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
160 SecureContextMode::kInsecureContext,
161 nullptr);
162
163 StringKeyframeVector keyframes;
164 keyframes.push_back(start_keyframe);
165 keyframes.push_back(end_keyframe);
166
167 Element* element = GetElementById("target");
168 auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
169 animation = timeline->Play(
170 MakeGarbageCollected<KeyframeEffect>(element, model, timing));
171
172 // After creating the animation we need to clean the lifecycle so that the
173 // animation can be pushed to the compositor.
174 UpdateAllLifecyclePhasesForTest();
175
176 GetDocument().GetAnimationClock().UpdateTime(base::TimeTicks());
177 GetDocument().GetPendingAnimations().Update(nullptr, true);
178 }
179
MakeEmptyEffectModel()180 KeyframeEffectModelBase* MakeEmptyEffectModel() {
181 return MakeGarbageCollected<StringKeyframeEffectModel>(
182 StringKeyframeVector());
183 }
184
MakeAnimation(double duration=30,Timing::FillMode fill_mode=Timing::FillMode::AUTO)185 KeyframeEffect* MakeAnimation(
186 double duration = 30,
187 Timing::FillMode fill_mode = Timing::FillMode::AUTO) {
188 Timing timing;
189 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(duration);
190 timing.fill_mode = fill_mode;
191 return MakeGarbageCollected<KeyframeEffect>(nullptr, MakeEmptyEffectModel(),
192 timing);
193 }
194
SimulateFrame(double time_ms)195 bool SimulateFrame(double time_ms) {
196 if (animation->pending())
197 animation->NotifyReady(MillisecondsToSeconds(last_frame_time));
198 SimulateMicrotask();
199
200 last_frame_time = time_ms;
201 const auto* paint_artifact_compositor =
202 GetDocument().GetFrame()->View()->GetPaintArtifactCompositor();
203 GetDocument().GetAnimationClock().UpdateTime(
204 base::TimeTicks() + base::TimeDelta::FromMillisecondsD(time_ms));
205 GetDocument().GetPendingAnimations().Update(paint_artifact_compositor,
206 false);
207 // The timeline does not know about our animation, so we have to explicitly
208 // call update().
209 return animation->Update(kTimingUpdateForAnimationFrame);
210 }
211
SimulateAwaitReady()212 void SimulateAwaitReady() { SimulateFrame(last_frame_time); }
213
SimulateMicrotask()214 void SimulateMicrotask() {
215 Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate());
216 }
217
SimulateFrameForScrollAnimations()218 void SimulateFrameForScrollAnimations() {
219 // Advance time by 100 ms.
220 auto new_time = GetAnimationClock().CurrentTime() +
221 base::TimeDelta::FromMilliseconds(100);
222 GetPage().Animator().ServiceScriptedAnimations(new_time);
223 }
224
225 Persistent<DocumentTimeline> timeline;
226 Persistent<Animation> animation;
227
228 private:
229 double last_frame_time;
230 };
231
232 class AnimationAnimationTestCompositing
233 : public AnimationAnimationTestNoCompositing {
SetUp()234 void SetUp() override {
235 EnableCompositing();
236 AnimationAnimationTestNoCompositing::SetUp();
237 }
238 };
239
240 class AnimationAnimationTestCompositeAfterPaint
241 : public AnimationAnimationTestNoCompositing {
SetUp()242 void SetUp() override {
243 EnableCompositing();
244 AnimationAnimationTestNoCompositing::SetUp();
245 }
246
247 ScopedCompositeAfterPaintForTest enable_cap{true};
248 };
249
TEST_F(AnimationAnimationTestNoCompositing,InitialState)250 TEST_F(AnimationAnimationTestNoCompositing, InitialState) {
251 SetUpWithoutStartingTimeline();
252 animation = timeline->Play(nullptr);
253 EXPECT_EQ(0, animation->currentTime());
254 EXPECT_TRUE(animation->pending());
255 EXPECT_FALSE(animation->Paused());
256 EXPECT_EQ(1, animation->playbackRate());
257 EXPECT_FALSE(animation->startTime().has_value());
258
259 StartTimeline();
260 EXPECT_EQ("finished", animation->playState());
261 EXPECT_EQ(0, timeline->CurrentTimeMilliseconds());
262 EXPECT_EQ(0, animation->currentTime());
263 EXPECT_FALSE(animation->Paused());
264 EXPECT_FALSE(animation->pending());
265 EXPECT_EQ(1, animation->playbackRate());
266 EXPECT_EQ(0, animation->startTime());
267 }
268
TEST_F(AnimationAnimationTestNoCompositing,CurrentTimeDoesNotSetOutdated)269 TEST_F(AnimationAnimationTestNoCompositing, CurrentTimeDoesNotSetOutdated) {
270 EXPECT_FALSE(animation->Outdated());
271 EXPECT_EQ(0, animation->currentTime());
272 EXPECT_FALSE(animation->Outdated());
273 // FIXME: We should split simulateFrame into a version that doesn't update
274 // the animation and one that does, as most of the tests don't require
275 // update() to be called.
276 GetDocument().GetAnimationClock().UpdateTime(
277 base::TimeTicks() + base::TimeDelta::FromMilliseconds(10000));
278 EXPECT_EQ(10000, animation->currentTime());
279 EXPECT_FALSE(animation->Outdated());
280 }
281
TEST_F(AnimationAnimationTestNoCompositing,SetCurrentTime)282 TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTime) {
283 EXPECT_EQ("running", animation->playState());
284 animation->setCurrentTime(10000);
285 EXPECT_EQ("running", animation->playState());
286 EXPECT_EQ(10000, animation->currentTime());
287
288 SimulateFrame(10000);
289 EXPECT_EQ("running", animation->playState());
290 EXPECT_EQ(20000, animation->currentTime());
291 }
292
TEST_F(AnimationAnimationTestNoCompositing,SetCurrentTimeNegative)293 TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeNegative) {
294 animation->setCurrentTime(-10000);
295 EXPECT_EQ("running", animation->playState());
296 EXPECT_EQ(-10000, animation->currentTime());
297
298 SimulateFrame(20000);
299 EXPECT_EQ(10000, animation->currentTime());
300 animation->setPlaybackRate(-2);
301 animation->setCurrentTime(-10000);
302 EXPECT_EQ("finished", animation->playState());
303 // A seek can set current time outside the range [0, EffectEnd()].
304 EXPECT_EQ(-10000, animation->currentTime());
305
306 SimulateFrame(40000);
307 // Hold current time even though outside normal range for the animation.
308 EXPECT_FALSE(animation->pending());
309 EXPECT_EQ("finished", animation->playState());
310 EXPECT_EQ(-10000, animation->currentTime());
311 }
312
TEST_F(AnimationAnimationTestNoCompositing,SetCurrentTimeNegativeWithoutSimultaneousPlaybackRateChange)313 TEST_F(AnimationAnimationTestNoCompositing,
314 SetCurrentTimeNegativeWithoutSimultaneousPlaybackRateChange) {
315 SimulateFrame(20000);
316 EXPECT_EQ(20000, animation->currentTime());
317 EXPECT_EQ("running", animation->playState());
318
319 // Reversing the direction preserves current time.
320 animation->setPlaybackRate(-1);
321 EXPECT_EQ("running", animation->playState());
322 EXPECT_EQ(20000, animation->currentTime());
323 SimulateAwaitReady();
324
325 SimulateFrame(30000);
326 EXPECT_EQ(10000, animation->currentTime());
327 EXPECT_EQ("running", animation->playState());
328
329 animation->setCurrentTime(-10000);
330 EXPECT_EQ("finished", animation->playState());
331 }
332
TEST_F(AnimationAnimationTestNoCompositing,SetCurrentTimePastContentEnd)333 TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimePastContentEnd) {
334 animation->setCurrentTime(50000);
335 EXPECT_EQ("finished", animation->playState());
336 EXPECT_EQ(50000, animation->currentTime());
337
338 SimulateFrame(20000);
339 EXPECT_EQ("finished", animation->playState());
340 EXPECT_EQ(50000, animation->currentTime());
341 // Reversing the play direction changes the play state from finished to
342 // running.
343 animation->setPlaybackRate(-2);
344 animation->setCurrentTime(50000);
345 EXPECT_EQ("running", animation->playState());
346 EXPECT_EQ(50000, animation->currentTime());
347 SimulateAwaitReady();
348
349 SimulateFrame(40000);
350 EXPECT_EQ("running", animation->playState());
351 EXPECT_EQ(10000, animation->currentTime());
352 }
353
TEST_F(AnimationAnimationTestNoCompositing,SetCurrentTimeMax)354 TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeMax) {
355 double limit = std::numeric_limits<double>::max();
356 animation->setCurrentTime(limit);
357 ExpectRelativeErrorWithinEpsilon(limit, animation->currentTime().value());
358
359 SimulateFrame(100000);
360 ExpectRelativeErrorWithinEpsilon(limit, animation->currentTime().value());
361 }
362
TEST_F(AnimationAnimationTestNoCompositing,SetCurrentTimeSetsStartTime)363 TEST_F(AnimationAnimationTestNoCompositing, SetCurrentTimeSetsStartTime) {
364 EXPECT_EQ(0, animation->startTime());
365 animation->setCurrentTime(1000);
366 EXPECT_EQ(-1000, animation->startTime());
367
368 SimulateFrame(1000);
369 EXPECT_EQ(-1000, animation->startTime());
370 EXPECT_EQ(2000, animation->currentTime());
371 }
372
TEST_F(AnimationAnimationTestNoCompositing,SetStartTime)373 TEST_F(AnimationAnimationTestNoCompositing, SetStartTime) {
374 SimulateFrame(20000);
375 EXPECT_EQ("running", animation->playState());
376 EXPECT_EQ(0, animation->startTime());
377 EXPECT_EQ(20000, animation->currentTime());
378 animation->setStartTime(10000);
379 EXPECT_EQ("running", animation->playState());
380 EXPECT_EQ(10000, animation->startTime());
381 EXPECT_EQ(10000, animation->currentTime());
382
383 SimulateFrame(30000);
384 EXPECT_EQ(10000, animation->startTime());
385 EXPECT_EQ(20000, animation->currentTime());
386 animation->setStartTime(-20000);
387 EXPECT_EQ("finished", animation->playState());
388 }
389
TEST_F(AnimationAnimationTestNoCompositing,SetStartTimeLimitsAnimation)390 TEST_F(AnimationAnimationTestNoCompositing, SetStartTimeLimitsAnimation) {
391 // Setting the start time is a seek operation, which is not constrained by the
392 // normal limits on the animation.
393 animation->setStartTime(-50000);
394 EXPECT_EQ("finished", animation->playState());
395 EXPECT_TRUE(animation->Limited());
396 EXPECT_EQ(50000, animation->currentTime());
397 animation->setPlaybackRate(-1);
398 EXPECT_EQ("running", animation->playState());
399 animation->setStartTime(-100000);
400 EXPECT_EQ("finished", animation->playState());
401 EXPECT_EQ(-100000, animation->currentTime());
402 EXPECT_TRUE(animation->Limited());
403 }
404
TEST_F(AnimationAnimationTestNoCompositing,SetStartTimeOnLimitedAnimation)405 TEST_F(AnimationAnimationTestNoCompositing, SetStartTimeOnLimitedAnimation) {
406 // The setStartTime method is a seek and thus not constrained by the normal
407 // limits on the animation.
408 SimulateFrame(30000);
409 animation->setStartTime(-10000);
410 EXPECT_EQ("finished", animation->playState());
411 EXPECT_EQ(40000, animation->currentTime());
412 EXPECT_TRUE(animation->Limited());
413
414 animation->setCurrentTime(50000);
415 EXPECT_EQ(50000, animation->currentTime());
416 animation->setStartTime(-40000);
417 EXPECT_EQ(70000, animation->currentTime());
418 EXPECT_EQ("finished", animation->playState());
419 EXPECT_TRUE(animation->Limited());
420 }
421
TEST_F(AnimationAnimationTestNoCompositing,StartTimePauseFinish)422 TEST_F(AnimationAnimationTestNoCompositing, StartTimePauseFinish) {
423 NonThrowableExceptionState exception_state;
424 animation->pause();
425 EXPECT_EQ("paused", animation->playState());
426 EXPECT_TRUE(animation->pending());
427 SimulateAwaitReady();
428 EXPECT_FALSE(animation->pending());
429 EXPECT_FALSE(animation->startTime().has_value());
430 animation->finish(exception_state);
431 EXPECT_EQ("finished", animation->playState());
432 EXPECT_FALSE(animation->pending());
433 EXPECT_EQ(-30000, animation->startTime());
434 }
435
TEST_F(AnimationAnimationTestNoCompositing,FinishWhenPaused)436 TEST_F(AnimationAnimationTestNoCompositing, FinishWhenPaused) {
437 NonThrowableExceptionState exception_state;
438 animation->pause();
439 EXPECT_EQ("paused", animation->playState());
440 EXPECT_TRUE(animation->pending());
441
442 SimulateFrame(10000);
443 EXPECT_EQ("paused", animation->playState());
444 EXPECT_FALSE(animation->pending());
445 animation->finish(exception_state);
446 EXPECT_EQ("finished", animation->playState());
447 }
448
TEST_F(AnimationAnimationTestNoCompositing,StartTimeFinishPause)449 TEST_F(AnimationAnimationTestNoCompositing, StartTimeFinishPause) {
450 NonThrowableExceptionState exception_state;
451 animation->finish(exception_state);
452 EXPECT_EQ(-30000, animation->startTime());
453 animation->pause();
454 EXPECT_EQ("paused", animation->playState());
455 EXPECT_TRUE(animation->pending());
456 SimulateAwaitReady();
457 EXPECT_FALSE(animation->pending());
458 EXPECT_FALSE(animation->startTime().has_value());
459 }
460
TEST_F(AnimationAnimationTestNoCompositing,StartTimeWithZeroPlaybackRate)461 TEST_F(AnimationAnimationTestNoCompositing, StartTimeWithZeroPlaybackRate) {
462 animation->setPlaybackRate(0);
463 EXPECT_EQ("running", animation->playState());
464 SimulateAwaitReady();
465 EXPECT_TRUE(animation->startTime().has_value());
466
467 SimulateFrame(10000);
468 EXPECT_EQ("running", animation->playState());
469 EXPECT_EQ(0, animation->currentTime());
470 }
471
TEST_F(AnimationAnimationTestNoCompositing,PausePlay)472 TEST_F(AnimationAnimationTestNoCompositing, PausePlay) {
473 // Pause the animation at the 10s mark.
474 SimulateFrame(10000);
475 animation->pause();
476 EXPECT_EQ("paused", animation->playState());
477 EXPECT_TRUE(animation->pending());
478 EXPECT_EQ(10000, animation->currentTime());
479
480 // Resume playing the animation at the 20s mark.
481 SimulateFrame(20000);
482 EXPECT_EQ("paused", animation->playState());
483 EXPECT_FALSE(animation->pending());
484 EXPECT_EQ(10000, animation->currentTime());
485 animation->play();
486 EXPECT_EQ("running", animation->playState());
487 EXPECT_TRUE(animation->pending());
488 SimulateAwaitReady();
489 EXPECT_FALSE(animation->pending());
490
491 // Advance another 10s.
492 SimulateFrame(30000);
493 EXPECT_EQ(20000, animation->currentTime());
494 }
495
TEST_F(AnimationAnimationTestNoCompositing,PlayRewindsToStart)496 TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToStart) {
497 // Auto-replay when starting from limit.
498 animation->setCurrentTime(30000);
499 animation->play();
500 EXPECT_EQ(0, animation->currentTime());
501
502 // Auto-replay when starting past the upper bound.
503 animation->setCurrentTime(40000);
504 animation->play();
505 EXPECT_EQ(0, animation->currentTime());
506 EXPECT_EQ("running", animation->playState());
507 EXPECT_TRUE(animation->pending());
508
509 // Snap to start of the animation if playing in forward direction starting
510 // from a negative value of current time.
511 SimulateFrame(10000);
512 EXPECT_FALSE(animation->pending());
513 animation->setCurrentTime(-10000);
514 EXPECT_EQ("running", animation->playState());
515 EXPECT_FALSE(animation->pending());
516 animation->play();
517 EXPECT_EQ(0, animation->currentTime());
518 EXPECT_EQ("running", animation->playState());
519 EXPECT_TRUE(animation->pending());
520 SimulateAwaitReady();
521 EXPECT_EQ("running", animation->playState());
522 EXPECT_FALSE(animation->pending());
523 }
524
TEST_F(AnimationAnimationTestNoCompositing,PlayRewindsToEnd)525 TEST_F(AnimationAnimationTestNoCompositing, PlayRewindsToEnd) {
526 // Snap to end when playing a reversed animation from the start.
527 animation->setPlaybackRate(-1);
528 animation->play();
529 EXPECT_EQ(30000, animation->currentTime());
530
531 // Snap to end if playing a reversed animation starting past the upper limit.
532 animation->setCurrentTime(40000);
533 EXPECT_EQ("running", animation->playState());
534 EXPECT_TRUE(animation->pending());
535 animation->play();
536 EXPECT_EQ(30000, animation->currentTime());
537 EXPECT_TRUE(animation->pending());
538
539 SimulateFrame(10000);
540 EXPECT_EQ("running", animation->playState());
541 EXPECT_FALSE(animation->pending());
542
543 // Snap to the end if playing a reversed animation starting with a negative
544 // value for current time.
545 animation->setCurrentTime(-10000);
546 animation->play();
547 EXPECT_EQ(30000, animation->currentTime());
548 EXPECT_EQ("running", animation->playState());
549 EXPECT_TRUE(animation->pending());
550
551 SimulateFrame(20000);
552 EXPECT_EQ("running", animation->playState());
553 EXPECT_FALSE(animation->pending());
554 }
555
TEST_F(AnimationAnimationTestNoCompositing,PlayWithPlaybackRateZeroDoesNotSeek)556 TEST_F(AnimationAnimationTestNoCompositing,
557 PlayWithPlaybackRateZeroDoesNotSeek) {
558 // When playback rate is zero, any value set for the current time effectively
559 // becomes the hold time.
560 animation->setPlaybackRate(0);
561 animation->play();
562 EXPECT_EQ(0, animation->currentTime());
563
564 animation->setCurrentTime(40000);
565 animation->play();
566 EXPECT_EQ(40000, animation->currentTime());
567
568 animation->setCurrentTime(-10000);
569 animation->play();
570 EXPECT_EQ(-10000, animation->currentTime());
571 }
572
TEST_F(AnimationAnimationTestNoCompositing,PlayAfterPauseWithPlaybackRateZeroUpdatesPlayState)573 TEST_F(AnimationAnimationTestNoCompositing,
574 PlayAfterPauseWithPlaybackRateZeroUpdatesPlayState) {
575 animation->pause();
576 animation->setPlaybackRate(0);
577
578 SimulateFrame(1000);
579 EXPECT_EQ("paused", animation->playState());
580 animation->play();
581 EXPECT_EQ("running", animation->playState());
582 EXPECT_TRUE(animation->pending());
583 }
584
TEST_F(AnimationAnimationTestNoCompositing,Reverse)585 TEST_F(AnimationAnimationTestNoCompositing, Reverse) {
586 animation->setCurrentTime(10000);
587 animation->pause();
588 animation->reverse();
589 EXPECT_EQ("running", animation->playState());
590 EXPECT_TRUE(animation->pending());
591 // Effective playback rate does not kick in until the animation is ready.
592 EXPECT_EQ(1, animation->playbackRate());
593 EXPECT_EQ(10000, animation->currentTime());
594 SimulateAwaitReady();
595 EXPECT_FALSE(animation->pending());
596 EXPECT_EQ(-1, animation->playbackRate());
597 // Updating the playback rate does not change current time.
598 EXPECT_EQ(10000, animation->currentTime());
599 }
600
TEST_F(AnimationAnimationTestNoCompositing,ReverseHoldsCurrentTimeWithPlaybackRateZero)601 TEST_F(AnimationAnimationTestNoCompositing,
602 ReverseHoldsCurrentTimeWithPlaybackRateZero) {
603 animation->setCurrentTime(10000);
604 animation->setPlaybackRate(0);
605 animation->pause();
606 animation->reverse();
607 SimulateAwaitReady();
608 EXPECT_EQ("running", animation->playState());
609 EXPECT_EQ(0, animation->playbackRate());
610 EXPECT_EQ(10000, animation->currentTime());
611
612 SimulateFrame(20000);
613 EXPECT_EQ(10000, animation->currentTime());
614 }
615
TEST_F(AnimationAnimationTestNoCompositing,ReverseSeeksToStart)616 TEST_F(AnimationAnimationTestNoCompositing, ReverseSeeksToStart) {
617 animation->setCurrentTime(-10000);
618 animation->setPlaybackRate(-1);
619 animation->reverse();
620 EXPECT_EQ(0, animation->currentTime());
621 }
622
TEST_F(AnimationAnimationTestNoCompositing,ReverseSeeksToEnd)623 TEST_F(AnimationAnimationTestNoCompositing, ReverseSeeksToEnd) {
624 animation->setCurrentTime(40000);
625 animation->reverse();
626 EXPECT_EQ(30000, animation->currentTime());
627 }
628
TEST_F(AnimationAnimationTestNoCompositing,ReverseBeyondLimit)629 TEST_F(AnimationAnimationTestNoCompositing, ReverseBeyondLimit) {
630 animation->setCurrentTime(40000);
631 animation->setPlaybackRate(-1);
632 animation->reverse();
633 EXPECT_EQ("running", animation->playState());
634 EXPECT_TRUE(animation->pending());
635 EXPECT_EQ(0, animation->currentTime());
636
637 animation->setCurrentTime(-10000);
638 animation->reverse();
639 EXPECT_EQ("running", animation->playState());
640 EXPECT_TRUE(animation->pending());
641 EXPECT_EQ(30000, animation->currentTime());
642 }
643
TEST_F(AnimationAnimationTestNoCompositing,Finish)644 TEST_F(AnimationAnimationTestNoCompositing, Finish) {
645 NonThrowableExceptionState exception_state;
646 animation->finish(exception_state);
647 // Finished snaps to the end of the animation.
648 EXPECT_EQ(30000, animation->currentTime());
649 EXPECT_EQ("finished", animation->playState());
650 // Finished is a synchronous operation.
651 EXPECT_FALSE(animation->pending());
652
653 animation->setPlaybackRate(-1);
654 animation->finish(exception_state);
655 EXPECT_EQ(0, animation->currentTime());
656 EXPECT_EQ("finished", animation->playState());
657 EXPECT_FALSE(animation->pending());
658 }
659
TEST_F(AnimationAnimationTestNoCompositing,FinishAfterEffectEnd)660 TEST_F(AnimationAnimationTestNoCompositing, FinishAfterEffectEnd) {
661 NonThrowableExceptionState exception_state;
662 // OK to set current time out of bounds.
663 animation->setCurrentTime(40000);
664 animation->finish(exception_state);
665 // The finish method triggers a snap to the upper boundary.
666 EXPECT_EQ(30000, animation->currentTime());
667 }
668
TEST_F(AnimationAnimationTestNoCompositing,FinishBeforeStart)669 TEST_F(AnimationAnimationTestNoCompositing, FinishBeforeStart) {
670 NonThrowableExceptionState exception_state;
671 animation->setCurrentTime(-10000);
672 animation->setPlaybackRate(-1);
673 animation->finish(exception_state);
674 EXPECT_EQ(0, animation->currentTime());
675 }
676
TEST_F(AnimationAnimationTestNoCompositing,FinishDoesNothingWithPlaybackRateZero)677 TEST_F(AnimationAnimationTestNoCompositing,
678 FinishDoesNothingWithPlaybackRateZero) {
679 // Cannot finish an animation that has a playback rate of zero.
680 DummyExceptionStateForTesting exception_state;
681 animation->setCurrentTime(10000);
682 animation->setPlaybackRate(0);
683 animation->finish(exception_state);
684 EXPECT_EQ(10000, animation->currentTime());
685 EXPECT_TRUE(exception_state.HadException());
686 }
687
TEST_F(AnimationAnimationTestNoCompositing,FinishRaisesException)688 TEST_F(AnimationAnimationTestNoCompositing, FinishRaisesException) {
689 // Cannot finish an animation that has an infinite iteration-count and a
690 // non-zero iteration-duration.
691 Timing timing;
692 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
693 timing.iteration_count = std::numeric_limits<double>::infinity();
694 animation->setEffect(MakeGarbageCollected<KeyframeEffect>(
695 nullptr, MakeEmptyEffectModel(), timing));
696 animation->setCurrentTime(10000);
697
698 DummyExceptionStateForTesting exception_state;
699 animation->finish(exception_state);
700 EXPECT_EQ(10000, animation->currentTime());
701 EXPECT_TRUE(exception_state.HadException());
702 EXPECT_EQ(DOMExceptionCode::kInvalidStateError,
703 exception_state.CodeAs<DOMExceptionCode>());
704 }
705
TEST_F(AnimationAnimationTestNoCompositing,LimitingAtEffectEnd)706 TEST_F(AnimationAnimationTestNoCompositing, LimitingAtEffectEnd) {
707 SimulateFrame(30000);
708 EXPECT_EQ(30000, animation->currentTime());
709 EXPECT_TRUE(animation->Limited());
710
711 // Cannot run past the end of the animation without a seek.
712 SimulateFrame(40000);
713 EXPECT_EQ(30000, animation->currentTime());
714 EXPECT_FALSE(animation->Paused());
715 }
716
TEST_F(AnimationAnimationTestNoCompositing,LimitingAtStart)717 TEST_F(AnimationAnimationTestNoCompositing, LimitingAtStart) {
718 SimulateFrame(30000);
719 animation->setPlaybackRate(-2);
720 SimulateAwaitReady();
721
722 SimulateFrame(45000);
723 EXPECT_EQ(0, animation->currentTime());
724 EXPECT_TRUE(animation->Limited());
725
726 SimulateFrame(60000);
727 EXPECT_EQ(0, animation->currentTime());
728 EXPECT_FALSE(animation->Paused());
729 }
730
TEST_F(AnimationAnimationTestNoCompositing,LimitingWithNoEffect)731 TEST_F(AnimationAnimationTestNoCompositing, LimitingWithNoEffect) {
732 animation->setEffect(nullptr);
733 EXPECT_TRUE(animation->Limited());
734 SimulateFrame(30000);
735 EXPECT_EQ(0, animation->currentTime());
736 }
737
TEST_F(AnimationAnimationTestNoCompositing,SetPlaybackRate)738 TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRate) {
739 animation->setPlaybackRate(2);
740 SimulateAwaitReady();
741 EXPECT_EQ(2, animation->playbackRate());
742 EXPECT_EQ(0, animation->currentTime());
743
744 SimulateFrame(10000);
745 EXPECT_EQ(20000, animation->currentTime());
746 }
747
TEST_F(AnimationAnimationTestNoCompositing,SetPlaybackRateWhilePaused)748 TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateWhilePaused) {
749 SimulateFrame(10000);
750 animation->pause();
751 EXPECT_EQ(10000, animation->currentTime());
752 animation->setPlaybackRate(2);
753 EXPECT_EQ(10000, animation->currentTime());
754 SimulateAwaitReady();
755
756 SimulateFrame(20000);
757 animation->play();
758 // Change to playback rate does not alter current time.
759 EXPECT_EQ(10000, animation->currentTime());
760 SimulateAwaitReady();
761
762 SimulateFrame(25000);
763 EXPECT_EQ(20000, animation->currentTime());
764 }
765
TEST_F(AnimationAnimationTestNoCompositing,SetPlaybackRateWhileLimited)766 TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateWhileLimited) {
767 // Animation plays until it hits the upper bound.
768 SimulateFrame(40000);
769 EXPECT_EQ(30000, animation->currentTime());
770 EXPECT_TRUE(animation->Limited());
771 animation->setPlaybackRate(2);
772 SimulateAwaitReady();
773
774 // Already at the end of the animation.
775 SimulateFrame(50000);
776 EXPECT_EQ(30000, animation->currentTime());
777 animation->setPlaybackRate(-2);
778 SimulateAwaitReady();
779
780 SimulateFrame(60000);
781 EXPECT_FALSE(animation->Limited());
782 EXPECT_EQ(10000, animation->currentTime());
783 }
784
TEST_F(AnimationAnimationTestNoCompositing,SetPlaybackRateZero)785 TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateZero) {
786 SimulateFrame(10000);
787 animation->setPlaybackRate(0);
788 EXPECT_EQ(10000, animation->currentTime());
789
790 SimulateFrame(20000);
791 EXPECT_EQ(10000, animation->currentTime());
792 animation->setCurrentTime(20000);
793 EXPECT_EQ(20000, animation->currentTime());
794 }
795
TEST_F(AnimationAnimationTestNoCompositing,SetPlaybackRateMax)796 TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateMax) {
797 animation->setPlaybackRate(std::numeric_limits<double>::max());
798 EXPECT_EQ(std::numeric_limits<double>::max(), animation->playbackRate());
799 EXPECT_EQ(0, animation->currentTime());
800 SimulateAwaitReady();
801
802 SimulateFrame(1);
803 EXPECT_EQ(30000, animation->currentTime());
804 }
805
TEST_F(AnimationAnimationTestNoCompositing,UpdatePlaybackRate)806 TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRate) {
807 animation->updatePlaybackRate(2);
808 EXPECT_EQ(1, animation->playbackRate());
809 SimulateAwaitReady();
810 EXPECT_EQ(2, animation->playbackRate());
811 EXPECT_EQ(0, animation->currentTime());
812
813 SimulateFrame(10000);
814 EXPECT_EQ(20000, animation->currentTime());
815 }
816
TEST_F(AnimationAnimationTestNoCompositing,UpdatePlaybackRateWhilePaused)817 TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhilePaused) {
818 animation->pause();
819
820 // Pending playback rate on pending-paused animation is picked up after async
821 // tick.
822 EXPECT_EQ("paused", animation->playState());
823 EXPECT_TRUE(animation->pending());
824 animation->updatePlaybackRate(2);
825 EXPECT_EQ(1, animation->playbackRate());
826 SimulateAwaitReady();
827 EXPECT_EQ(2, animation->playbackRate());
828 EXPECT_FALSE(animation->pending());
829
830 // Pending playback rate on a paused animation is resolved immediately.
831 animation->updatePlaybackRate(3);
832 EXPECT_FALSE(animation->pending());
833 EXPECT_EQ(3, animation->playbackRate());
834 }
835
TEST_F(AnimationAnimationTestNoCompositing,UpdatePlaybackRateWhileLimited)836 TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileLimited) {
837 NonThrowableExceptionState exception_state;
838 animation->finish(exception_state);
839 EXPECT_EQ(30000, animation->currentTime());
840
841 // Updating playback rate does not affect current time.
842 animation->updatePlaybackRate(2);
843 EXPECT_EQ(30000, animation->currentTime());
844
845 // Updating payback rate is resolved immediately for an animation in the
846 // finished state.
847 EXPECT_EQ(2, animation->playbackRate());
848 }
849
TEST_F(AnimationAnimationTestNoCompositing,UpdatePlaybackRateWhileRunning)850 TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateWhileRunning) {
851 animation->play();
852 SimulateFrame(1000);
853 animation->updatePlaybackRate(2);
854
855 // Updating playback rate triggers pending state for the play state.
856 // Pending playback rate is not resolved until next async tick.
857 EXPECT_TRUE(animation->pending());
858 EXPECT_EQ(1, animation->playbackRate());
859 SimulateAwaitReady();
860 EXPECT_FALSE(animation->pending());
861 EXPECT_EQ(2, animation->playbackRate());
862 }
863
TEST_F(AnimationAnimationTestNoCompositing,SetEffect)864 TEST_F(AnimationAnimationTestNoCompositing, SetEffect) {
865 animation = timeline->Play(nullptr);
866 animation->setStartTime(0);
867 AnimationEffect* effect1 = MakeAnimation();
868 AnimationEffect* effect2 = MakeAnimation();
869 animation->setEffect(effect1);
870 EXPECT_EQ(effect1, animation->effect());
871 EXPECT_EQ(0, animation->currentTime());
872 animation->setCurrentTime(15000);
873 animation->setEffect(effect2);
874 EXPECT_EQ(15000, animation->currentTime());
875 EXPECT_EQ(nullptr, effect1->GetAnimationForTesting());
876 EXPECT_EQ(animation, effect2->GetAnimationForTesting());
877 EXPECT_EQ(effect2, animation->effect());
878 }
879
TEST_F(AnimationAnimationTestNoCompositing,SetEffectLimitsAnimation)880 TEST_F(AnimationAnimationTestNoCompositing, SetEffectLimitsAnimation) {
881 animation->setCurrentTime(20000);
882 animation->setEffect(MakeAnimation(10));
883 EXPECT_EQ(20000, animation->currentTime());
884 EXPECT_TRUE(animation->Limited());
885 SimulateFrame(10000);
886 EXPECT_EQ(20000, animation->currentTime());
887 }
888
TEST_F(AnimationAnimationTestNoCompositing,SetEffectUnlimitsAnimation)889 TEST_F(AnimationAnimationTestNoCompositing, SetEffectUnlimitsAnimation) {
890 animation->setCurrentTime(40000);
891 animation->setEffect(MakeAnimation(60));
892 EXPECT_FALSE(animation->Limited());
893 EXPECT_EQ(40000, animation->currentTime());
894 SimulateFrame(10000);
895 EXPECT_EQ(50000, animation->currentTime());
896 }
897
TEST_F(AnimationAnimationTestNoCompositing,EmptyAnimationsDontUpdateEffects)898 TEST_F(AnimationAnimationTestNoCompositing, EmptyAnimationsDontUpdateEffects) {
899 animation = timeline->Play(nullptr);
900 animation->Update(kTimingUpdateOnDemand);
901 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
902
903 SimulateFrame(1234);
904 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
905 }
906
TEST_F(AnimationAnimationTestNoCompositing,AnimationsDisassociateFromEffect)907 TEST_F(AnimationAnimationTestNoCompositing, AnimationsDisassociateFromEffect) {
908 AnimationEffect* animation_node = animation->effect();
909 Animation* animation2 = timeline->Play(animation_node);
910 EXPECT_EQ(nullptr, animation->effect());
911 animation->setEffect(animation_node);
912 EXPECT_EQ(nullptr, animation2->effect());
913 }
914
TEST_F(AnimationAnimationTestNoCompositing,AnimationsReturnTimeToNextEffect)915 TEST_F(AnimationAnimationTestNoCompositing, AnimationsReturnTimeToNextEffect) {
916 Timing timing;
917 timing.start_delay = 1;
918 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(1);
919 timing.end_delay = 1;
920 auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
921 nullptr, MakeEmptyEffectModel(), timing);
922 animation = timeline->Play(keyframe_effect);
923 animation->setStartTime(0);
924
925 // Next effect change at end of start delay.
926 SimulateFrame(0);
927 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
928 animation->TimeToEffectChange());
929
930 // Next effect change at end of start delay.
931 SimulateFrame(500);
932 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(0.5),
933 animation->TimeToEffectChange());
934
935 // Start of active phase.
936 SimulateFrame(1000);
937 EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
938
939 // Still in active phase.
940 SimulateFrame(1500);
941 EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
942
943 // Start of the after phase. Next effect change at end of after phase.
944 SimulateFrame(2000);
945 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
946 animation->TimeToEffectChange());
947
948 // Still in effect if fillmode = forward|both.
949 SimulateFrame(3000);
950 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
951
952 // Reset to start of animation. Next effect at the end of the start delay.
953 animation->setCurrentTime(0);
954 SimulateFrame(3000);
955 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
956 animation->TimeToEffectChange());
957
958 // Start delay is scaled by playback rate.
959 animation->setPlaybackRate(2);
960 SimulateFrame(3000);
961 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(0.5),
962 animation->TimeToEffectChange());
963
964 // Effectively a paused animation.
965 animation->setPlaybackRate(0);
966 animation->Update(kTimingUpdateOnDemand);
967 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
968
969 // Reversed animation from end time. Next effect after end delay.
970 animation->setCurrentTime(3000);
971 animation->setPlaybackRate(-1);
972 animation->Update(kTimingUpdateOnDemand);
973 SimulateFrame(3000);
974 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(1),
975 animation->TimeToEffectChange());
976
977 // End delay is scaled by playback rate.
978 animation->setPlaybackRate(-2);
979 animation->Update(kTimingUpdateOnDemand);
980 SimulateFrame(3000);
981 EXPECT_EQ(AnimationTimeDelta::FromSecondsD(0.5),
982 animation->TimeToEffectChange());
983 }
984
TEST_F(AnimationAnimationTestNoCompositing,TimeToNextEffectWhenPaused)985 TEST_F(AnimationAnimationTestNoCompositing, TimeToNextEffectWhenPaused) {
986 EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
987 animation->pause();
988 EXPECT_TRUE(animation->pending());
989 EXPECT_EQ("paused", animation->playState());
990 SimulateAwaitReady();
991 EXPECT_FALSE(animation->pending());
992 animation->Update(kTimingUpdateOnDemand);
993 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
994 }
995
TEST_F(AnimationAnimationTestNoCompositing,TimeToNextEffectWhenCancelledBeforeStart)996 TEST_F(AnimationAnimationTestNoCompositing,
997 TimeToNextEffectWhenCancelledBeforeStart) {
998 EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
999 animation->setCurrentTime(-8000);
1000 animation->setPlaybackRate(2);
1001 EXPECT_EQ("running", animation->playState());
1002 animation->cancel();
1003 EXPECT_EQ("idle", animation->playState());
1004 EXPECT_FALSE(animation->pending());
1005 animation->Update(kTimingUpdateOnDemand);
1006 // This frame will fire the finish event event though no start time has been
1007 // received from the compositor yet, as cancel() nukes start times.
1008 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
1009 }
1010
TEST_F(AnimationAnimationTestNoCompositing,TimeToNextEffectWhenCancelledBeforeStartReverse)1011 TEST_F(AnimationAnimationTestNoCompositing,
1012 TimeToNextEffectWhenCancelledBeforeStartReverse) {
1013 EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
1014 animation->setCurrentTime(9000);
1015 animation->setPlaybackRate(-3);
1016 EXPECT_EQ("running", animation->playState());
1017 animation->cancel();
1018 EXPECT_EQ("idle", animation->playState());
1019 EXPECT_FALSE(animation->pending());
1020 animation->Update(kTimingUpdateOnDemand);
1021 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
1022 }
1023
TEST_F(AnimationAnimationTestNoCompositing,TimeToNextEffectSimpleCancelledBeforeStart)1024 TEST_F(AnimationAnimationTestNoCompositing,
1025 TimeToNextEffectSimpleCancelledBeforeStart) {
1026 EXPECT_EQ(AnimationTimeDelta(), animation->TimeToEffectChange());
1027 EXPECT_EQ("running", animation->playState());
1028 animation->cancel();
1029 EXPECT_EQ("idle", animation->playState());
1030 EXPECT_FALSE(animation->pending());
1031 animation->Update(kTimingUpdateOnDemand);
1032 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
1033 }
1034
TEST_F(AnimationAnimationTestNoCompositing,AttachedAnimations)1035 TEST_F(AnimationAnimationTestNoCompositing, AttachedAnimations) {
1036 Persistent<Element> element = GetDocument().CreateElementForBinding("foo");
1037
1038 Timing timing;
1039 auto* keyframe_effect = MakeGarbageCollected<KeyframeEffect>(
1040 element.Get(), MakeEmptyEffectModel(), timing);
1041 Animation* animation = timeline->Play(keyframe_effect);
1042 SimulateFrame(0);
1043 timeline->ServiceAnimations(kTimingUpdateForAnimationFrame);
1044 EXPECT_EQ(
1045 1U, element->GetElementAnimations()->Animations().find(animation)->value);
1046
1047 ThreadState::Current()->CollectAllGarbageForTesting();
1048 EXPECT_TRUE(element->GetElementAnimations()->Animations().IsEmpty());
1049 }
1050
TEST_F(AnimationAnimationTestNoCompositing,HasLowerCompositeOrdering)1051 TEST_F(AnimationAnimationTestNoCompositing, HasLowerCompositeOrdering) {
1052 Animation* animation1 = timeline->Play(nullptr);
1053 Animation* animation2 = timeline->Play(nullptr);
1054 EXPECT_TRUE(Animation::HasLowerCompositeOrdering(
1055 animation1, animation2,
1056 Animation::CompareAnimationsOrdering::kPointerOrder));
1057 }
1058
TEST_F(AnimationAnimationTestNoCompositing,PlayAfterCancel)1059 TEST_F(AnimationAnimationTestNoCompositing, PlayAfterCancel) {
1060 animation->cancel();
1061 EXPECT_EQ("idle", animation->playState());
1062 EXPECT_FALSE(animation->currentTime().has_value());
1063 EXPECT_FALSE(animation->startTime().has_value());
1064 animation->play();
1065 EXPECT_EQ("running", animation->playState());
1066 EXPECT_TRUE(animation->pending());
1067 EXPECT_EQ(0, animation->currentTime());
1068 EXPECT_FALSE(animation->startTime().has_value());
1069 SimulateAwaitReady();
1070 EXPECT_FALSE(animation->pending());
1071 EXPECT_EQ(0, animation->currentTime());
1072 EXPECT_EQ(0, animation->startTime());
1073
1074 SimulateFrame(10000);
1075 EXPECT_EQ("running", animation->playState());
1076 EXPECT_EQ(10000, animation->currentTime());
1077 EXPECT_EQ(0, animation->startTime());
1078 }
1079
TEST_F(AnimationAnimationTestNoCompositing,PlayBackwardsAfterCancel)1080 TEST_F(AnimationAnimationTestNoCompositing, PlayBackwardsAfterCancel) {
1081 animation->setPlaybackRate(-1);
1082 animation->setCurrentTime(15000);
1083 animation->cancel();
1084 EXPECT_EQ("idle", animation->playState());
1085 EXPECT_FALSE(animation->pending());
1086 EXPECT_FALSE(animation->currentTime().has_value());
1087 EXPECT_FALSE(animation->startTime().has_value());
1088
1089 // Snap to the end of the animation.
1090 animation->play();
1091 EXPECT_EQ("running", animation->playState());
1092 EXPECT_TRUE(animation->pending());
1093 EXPECT_EQ(30000, animation->currentTime());
1094 EXPECT_FALSE(animation->startTime().has_value());
1095 SimulateAwaitReady();
1096 EXPECT_FALSE(animation->pending());
1097 EXPECT_EQ(30000, animation->startTime());
1098
1099 SimulateFrame(10000);
1100 EXPECT_EQ("running", animation->playState());
1101 EXPECT_EQ(20000, animation->currentTime());
1102 EXPECT_EQ(30000, animation->startTime());
1103 }
1104
TEST_F(AnimationAnimationTestNoCompositing,ReverseAfterCancel)1105 TEST_F(AnimationAnimationTestNoCompositing, ReverseAfterCancel) {
1106 animation->cancel();
1107 EXPECT_EQ("idle", animation->playState());
1108 EXPECT_FALSE(animation->pending());
1109 EXPECT_FALSE(animation->currentTime().has_value());
1110 EXPECT_FALSE(animation->startTime().has_value());
1111
1112 // Reverse snaps to the end of the animation.
1113 animation->reverse();
1114 EXPECT_EQ("running", animation->playState());
1115 EXPECT_TRUE(animation->pending());
1116 EXPECT_EQ(30000, animation->currentTime());
1117 EXPECT_FALSE(animation->startTime().has_value());
1118 SimulateAwaitReady();
1119 EXPECT_FALSE(animation->pending());
1120 EXPECT_EQ(30000, animation->startTime());
1121
1122 SimulateFrame(10000);
1123 EXPECT_EQ("running", animation->playState());
1124 EXPECT_EQ(20000, animation->currentTime());
1125 EXPECT_EQ(30000, animation->startTime());
1126 }
1127
TEST_F(AnimationAnimationTestNoCompositing,FinishAfterCancel)1128 TEST_F(AnimationAnimationTestNoCompositing, FinishAfterCancel) {
1129 NonThrowableExceptionState exception_state;
1130 animation->cancel();
1131 EXPECT_EQ("idle", animation->playState());
1132 EXPECT_FALSE(animation->currentTime().has_value());
1133 EXPECT_FALSE(animation->startTime().has_value());
1134
1135 animation->finish(exception_state);
1136 EXPECT_EQ("finished", animation->playState());
1137 EXPECT_EQ(30000, animation->currentTime());
1138 EXPECT_EQ(-30000, animation->startTime());
1139 }
1140
TEST_F(AnimationAnimationTestNoCompositing,PauseAfterCancel)1141 TEST_F(AnimationAnimationTestNoCompositing, PauseAfterCancel) {
1142 animation->cancel();
1143 EXPECT_EQ("idle", animation->playState());
1144 EXPECT_FALSE(animation->currentTime().has_value());
1145 EXPECT_FALSE(animation->startTime().has_value());
1146 animation->pause();
1147 EXPECT_EQ("paused", animation->playState());
1148 EXPECT_TRUE(animation->pending());
1149 EXPECT_EQ(0, animation->currentTime());
1150 EXPECT_FALSE(animation->startTime().has_value());
1151 SimulateAwaitReady();
1152 EXPECT_FALSE(animation->pending());
1153 EXPECT_EQ(0, animation->currentTime());
1154 EXPECT_FALSE(animation->startTime().has_value());
1155 }
1156
1157 // crbug.com/1052217
TEST_F(AnimationAnimationTestNoCompositing,SetPlaybackRateAfterFinish)1158 TEST_F(AnimationAnimationTestNoCompositing, SetPlaybackRateAfterFinish) {
1159 animation->setEffect(MakeAnimation(30, Timing::FillMode::FORWARDS));
1160 animation->finish();
1161 animation->Update(kTimingUpdateOnDemand);
1162 EXPECT_EQ("finished", animation->playState());
1163 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
1164
1165 // Reversing a finished animation marks the animation as outdated. Required
1166 // to recompute the time to next interval.
1167 animation->setPlaybackRate(-1);
1168 EXPECT_EQ("running", animation->playState());
1169 EXPECT_EQ(animation->playbackRate(), -1);
1170 EXPECT_TRUE(animation->Outdated());
1171 animation->Update(kTimingUpdateOnDemand);
1172 EXPECT_EQ(0, animation->TimeToEffectChange()->InSecondsF());
1173 EXPECT_FALSE(animation->Outdated());
1174 }
1175
TEST_F(AnimationAnimationTestNoCompositing,UpdatePlaybackRateAfterFinish)1176 TEST_F(AnimationAnimationTestNoCompositing, UpdatePlaybackRateAfterFinish) {
1177 animation->setEffect(MakeAnimation(30, Timing::FillMode::FORWARDS));
1178 animation->finish();
1179 animation->Update(kTimingUpdateOnDemand);
1180 EXPECT_EQ("finished", animation->playState());
1181 EXPECT_EQ(base::nullopt, animation->TimeToEffectChange());
1182
1183 // Reversing a finished animation marks the animation as outdated. Required
1184 // to recompute the time to next interval. The pending playback rate is
1185 // immediately applied when updatePlaybackRate is called on a non-running
1186 // animation.
1187 animation->updatePlaybackRate(-1);
1188 EXPECT_EQ("running", animation->playState());
1189 EXPECT_EQ(animation->playbackRate(), -1);
1190 EXPECT_TRUE(animation->Outdated());
1191 animation->Update(kTimingUpdateOnDemand);
1192 EXPECT_EQ(0, animation->TimeToEffectChange()->InSecondsF());
1193 EXPECT_FALSE(animation->Outdated());
1194 }
1195
TEST_F(AnimationAnimationTestCompositeAfterPaint,NoCompositeWithoutCompositedElementId)1196 TEST_F(AnimationAnimationTestCompositeAfterPaint,
1197 NoCompositeWithoutCompositedElementId) {
1198 SetBodyInnerHTML(
1199 "<div id='foo' style='position: relative; will-change: "
1200 "opacity;'>composited</div>"
1201 "<div id='bar' style='position: relative'>not composited</div>");
1202
1203 LayoutObject* object_composited = GetLayoutObjectByElementId("foo");
1204 LayoutObject* object_not_composited = GetLayoutObjectByElementId("bar");
1205
1206 Timing timing;
1207 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
1208 auto* keyframe_effect_composited = MakeGarbageCollected<KeyframeEffect>(
1209 To<Element>(object_composited->GetNode()), MakeSimpleEffectModel(),
1210 timing);
1211 Animation* animation_composited = timeline->Play(keyframe_effect_composited);
1212 auto* keyframe_effect_not_composited = MakeGarbageCollected<KeyframeEffect>(
1213 To<Element>(object_not_composited->GetNode()), MakeSimpleEffectModel(),
1214 timing);
1215 Animation* animation_not_composited =
1216 timeline->Play(keyframe_effect_not_composited);
1217
1218 SimulateFrame(0);
1219 EXPECT_EQ(animation_composited->CheckCanStartAnimationOnCompositorInternal(),
1220 CompositorAnimations::kNoFailure);
1221 const PaintArtifactCompositor* paint_artifact_compositor =
1222 GetDocument().View()->GetPaintArtifactCompositor();
1223 ASSERT_TRUE(paint_artifact_compositor);
1224 EXPECT_EQ(animation_composited->CheckCanStartAnimationOnCompositor(
1225 paint_artifact_compositor),
1226 CompositorAnimations::kNoFailure);
1227 EXPECT_NE(animation_not_composited->CheckCanStartAnimationOnCompositor(
1228 paint_artifact_compositor),
1229 CompositorAnimations::kNoFailure);
1230 }
1231
1232 // Regression test for http://crbug.com/819591 . If a compositable animation is
1233 // played and then paused before any start time is set (either blink or
1234 // compositor side), the pausing must still set compositor pending or the pause
1235 // won't be synced.
TEST_F(AnimationAnimationTestCompositing,SetCompositorPendingWithUnresolvedStartTimes)1236 TEST_F(AnimationAnimationTestCompositing,
1237 SetCompositorPendingWithUnresolvedStartTimes) {
1238 ResetWithCompositedAnimation();
1239
1240 // At this point, the animation exists on both the compositor and blink side,
1241 // but no start time has arrived on either side. The compositor is currently
1242 // synced, no update is pending.
1243 EXPECT_FALSE(animation->CompositorPendingForTesting());
1244
1245 // However, if we pause the animation then the compositor should still be
1246 // marked pending. This is required because otherwise the compositor will go
1247 // ahead and start playing the animation once it receives a start time (e.g.
1248 // on the next compositor frame).
1249 animation->pause();
1250
1251 EXPECT_TRUE(animation->CompositorPendingForTesting());
1252 }
1253
TEST_F(AnimationAnimationTestCompositing,PreCommitWithUnresolvedStartTimes)1254 TEST_F(AnimationAnimationTestCompositing, PreCommitWithUnresolvedStartTimes) {
1255 ResetWithCompositedAnimation();
1256
1257 // At this point, the animation exists on both the compositor and blink side,
1258 // but no start time has arrived on either side. The compositor is currently
1259 // synced, no update is pending.
1260 EXPECT_FALSE(animation->CompositorPendingForTesting());
1261
1262 // At this point, a call to PreCommit should bail out and tell us to wait for
1263 // next commit because there are no resolved start times.
1264 EXPECT_FALSE(animation->PreCommit(0, nullptr, true));
1265 }
1266
1267 namespace {
GenerateHistogramValue(CompositorAnimations::FailureReason reason)1268 int GenerateHistogramValue(CompositorAnimations::FailureReason reason) {
1269 // The enum values in CompositorAnimations::FailureReasons are stored as 2^i
1270 // as they are a bitmask, but are recorded into the histogram as (i+1) to give
1271 // sequential histogram values. The exception is kNoFailure, which is stored
1272 // as 0 and recorded as 0.
1273 if (reason == CompositorAnimations::kNoFailure)
1274 return CompositorAnimations::kNoFailure;
1275 return base::bits::CountTrailingZeroBits(static_cast<uint32_t>(reason)) + 1;
1276 }
1277 } // namespace
1278
TEST_F(AnimationAnimationTestCompositing,PreCommitRecordsHistograms)1279 TEST_F(AnimationAnimationTestCompositing, PreCommitRecordsHistograms) {
1280 const std::string histogram_name =
1281 "Blink.Animation.CompositedAnimationFailureReason";
1282
1283 // Initially the animation in this test has no target, so it is invalid.
1284 {
1285 HistogramTester histogram;
1286 ASSERT_TRUE(animation->PreCommit(0, nullptr, true));
1287 histogram.ExpectBucketCount(
1288 histogram_name,
1289 GenerateHistogramValue(CompositorAnimations::kInvalidAnimationOrEffect),
1290 1);
1291 }
1292
1293 // Restart the animation with a target and compositing state.
1294 {
1295 HistogramTester histogram;
1296 ResetWithCompositedAnimation();
1297 histogram.ExpectBucketCount(
1298 histogram_name,
1299 GenerateHistogramValue(CompositorAnimations::kNoFailure), 1);
1300 }
1301
1302 // Now make the playback rate 0. This trips both the invalid animation and
1303 // unsupported timing parameter reasons.
1304 animation->setPlaybackRate(0);
1305 animation->NotifyReady(100);
1306 {
1307 HistogramTester histogram;
1308 ASSERT_TRUE(animation->PreCommit(0, nullptr, true));
1309 histogram.ExpectBucketCount(
1310 histogram_name,
1311 GenerateHistogramValue(CompositorAnimations::kInvalidAnimationOrEffect),
1312 1);
1313 histogram.ExpectBucketCount(
1314 histogram_name,
1315 GenerateHistogramValue(
1316 CompositorAnimations::kEffectHasUnsupportedTimingParameters),
1317 1);
1318 }
1319 animation->setPlaybackRate(1);
1320
1321 // Finally, change the keyframes to something unsupported by the compositor.
1322 Persistent<StringKeyframe> start_keyframe =
1323 MakeGarbageCollected<StringKeyframe>();
1324 start_keyframe->SetCSSPropertyValue(
1325 CSSPropertyID::kLeft, "0", SecureContextMode::kInsecureContext, nullptr);
1326 Persistent<StringKeyframe> end_keyframe =
1327 MakeGarbageCollected<StringKeyframe>();
1328 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kLeft, "100px",
1329 SecureContextMode::kInsecureContext,
1330 nullptr);
1331
1332 To<KeyframeEffect>(animation->effect())
1333 ->SetKeyframes({start_keyframe, end_keyframe});
1334 UpdateAllLifecyclePhasesForTest();
1335 {
1336 HistogramTester histogram;
1337 ASSERT_TRUE(animation->PreCommit(0, nullptr, true));
1338 histogram.ExpectBucketCount(
1339 histogram_name,
1340 GenerateHistogramValue(CompositorAnimations::kUnsupportedCSSProperty),
1341 1);
1342 }
1343 }
1344
1345 // crbug.com/990000.
TEST_F(AnimationAnimationTestCompositing,ReplaceCompositedAnimation)1346 TEST_F(AnimationAnimationTestCompositing, ReplaceCompositedAnimation) {
1347 const std::string histogram_name =
1348 "Blink.Animation.CompositedAnimationFailureReason";
1349
1350 // Start with a composited animation.
1351 ResetWithCompositedAnimation();
1352 ASSERT_TRUE(animation->HasActiveAnimationsOnCompositor());
1353
1354 // Replace the animation. The new animation should not be incompatible and
1355 // therefore able to run on the compositor.
1356 animation->cancel();
1357 MakeCompositedAnimation();
1358 ASSERT_TRUE(animation->HasActiveAnimationsOnCompositor());
1359 }
1360
TEST_F(AnimationAnimationTestCompositing,SetKeyframesCausesCompositorPending)1361 TEST_F(AnimationAnimationTestCompositing, SetKeyframesCausesCompositorPending) {
1362 ResetWithCompositedAnimation();
1363
1364 // At this point, the animation exists on both the compositor and blink side,
1365 // but no start time has arrived on either side. The compositor is currently
1366 // synced, no update is pending.
1367 EXPECT_FALSE(animation->CompositorPendingForTesting());
1368
1369 // Now change the keyframes; this should mark the animation as compositor
1370 // pending as we need to sync the compositor side.
1371 Persistent<StringKeyframe> start_keyframe =
1372 MakeGarbageCollected<StringKeyframe>();
1373 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
1374 SecureContextMode::kInsecureContext,
1375 nullptr);
1376 Persistent<StringKeyframe> end_keyframe =
1377 MakeGarbageCollected<StringKeyframe>();
1378 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
1379 SecureContextMode::kInsecureContext,
1380 nullptr);
1381
1382 StringKeyframeVector keyframes;
1383 keyframes.push_back(start_keyframe);
1384 keyframes.push_back(end_keyframe);
1385
1386 To<KeyframeEffect>(animation->effect())->SetKeyframes(keyframes);
1387
1388 EXPECT_TRUE(animation->CompositorPendingForTesting());
1389 }
1390
1391 // crbug.com/1057076
1392 // Infinite duration animations should not run on the compositor.
TEST_F(AnimationAnimationTestCompositing,InfiniteDurationAnimation)1393 TEST_F(AnimationAnimationTestCompositing, InfiniteDurationAnimation) {
1394 ResetWithCompositedAnimation();
1395 EXPECT_EQ(CompositorAnimations::kNoFailure,
1396 animation->CheckCanStartAnimationOnCompositor(nullptr));
1397
1398 OptionalEffectTiming* effect_timing = OptionalEffectTiming::Create();
1399 effect_timing->setDuration(UnrestrictedDoubleOrString::FromUnrestrictedDouble(
1400 std::numeric_limits<double>::infinity()));
1401 animation->effect()->updateTiming(effect_timing);
1402 EXPECT_EQ(CompositorAnimations::kEffectHasUnsupportedTimingParameters,
1403 animation->CheckCanStartAnimationOnCompositor(nullptr));
1404 }
1405
TEST_F(AnimationAnimationTestCompositing,ScrollLinkedAnimationCanBeComposited)1406 TEST_F(AnimationAnimationTestCompositing,
1407 ScrollLinkedAnimationCanBeComposited) {
1408 ResetWithCompositedAnimation();
1409 SetBodyInnerHTML(R"HTML(
1410 <style>
1411 #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
1412 #target { width: 100px; height: 200px; will-change: opacity;}
1413 #spacer { width: 200px; height: 2000px; }
1414 </style>
1415 <div id ='scroller'>
1416 <div id ='target'></div>
1417 <div id ='spacer'></div>
1418 </div>
1419 )HTML");
1420
1421 // Create ScrollTimeline
1422 auto* scroller =
1423 To<LayoutBoxModelObject>(GetLayoutObjectByElementId("scroller"));
1424 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
1425 scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
1426 mojom::blink::ScrollType::kProgrammatic);
1427 ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
1428 DoubleOrScrollTimelineAutoKeyword time_range =
1429 DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
1430 options->setTimeRange(time_range);
1431 options->setScrollSource(GetElementById("scroller"));
1432 ScrollTimeline* scroll_timeline =
1433 ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
1434
1435 // Create KeyframeEffect
1436 Timing timing;
1437 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
1438
1439 Persistent<StringKeyframe> start_keyframe =
1440 MakeGarbageCollected<StringKeyframe>();
1441 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
1442 SecureContextMode::kInsecureContext,
1443 nullptr);
1444 Persistent<StringKeyframe> end_keyframe =
1445 MakeGarbageCollected<StringKeyframe>();
1446 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
1447 SecureContextMode::kInsecureContext,
1448 nullptr);
1449
1450 StringKeyframeVector keyframes;
1451 keyframes.push_back(start_keyframe);
1452 keyframes.push_back(end_keyframe);
1453
1454 Element* element = GetElementById("target");
1455 auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
1456
1457 // Create scroll-linked animation
1458 NonThrowableExceptionState exception_state;
1459 Animation* scroll_animation = Animation::Create(
1460 MakeGarbageCollected<KeyframeEffect>(element, model, timing),
1461 scroll_timeline, exception_state);
1462
1463 model->SnapshotAllCompositorKeyframesIfNecessary(
1464 *element, *ComputedStyle::Create(), nullptr);
1465
1466 UpdateAllLifecyclePhasesForTest();
1467 scroll_animation->play();
1468 EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr),
1469 CompositorAnimations::kNoFailure);
1470 }
1471
TEST_F(AnimationAnimationTestCompositing,StartScrollLinkedAnimationWithStartTimeIfApplicable)1472 TEST_F(AnimationAnimationTestCompositing,
1473 StartScrollLinkedAnimationWithStartTimeIfApplicable) {
1474 ResetWithCompositedAnimation();
1475 SetBodyInnerHTML(R"HTML(
1476 <style>
1477 #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
1478 #target { width: 100px; height: 200px; will-change: opacity;}
1479 #spacer { width: 200px; height: 700px; }
1480 </style>
1481 <div id ='scroller'>
1482 <div id ='target'></div>
1483 <div id ='spacer'></div>
1484 </div>
1485 )HTML");
1486
1487 // Create ScrollTimeline
1488 auto* scroller =
1489 To<LayoutBoxModelObject>(GetLayoutObjectByElementId("scroller"));
1490 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
1491 scrollable_area->SetScrollOffset(ScrollOffset(0, 100),
1492 mojom::blink::ScrollType::kProgrammatic);
1493 ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
1494 DoubleOrScrollTimelineAutoKeyword time_range =
1495 DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
1496 options->setTimeRange(time_range);
1497 options->setScrollSource(GetElementById("scroller"));
1498 ScrollTimeline* scroll_timeline =
1499 ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
1500
1501 // Create KeyframeEffect
1502 Timing timing;
1503 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
1504
1505 Persistent<StringKeyframe> start_keyframe =
1506 MakeGarbageCollected<StringKeyframe>();
1507 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
1508 SecureContextMode::kInsecureContext,
1509 nullptr);
1510 Persistent<StringKeyframe> end_keyframe =
1511 MakeGarbageCollected<StringKeyframe>();
1512 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
1513 SecureContextMode::kInsecureContext,
1514 nullptr);
1515
1516 StringKeyframeVector keyframes;
1517 keyframes.push_back(start_keyframe);
1518 keyframes.push_back(end_keyframe);
1519
1520 Element* element = GetElementById("target");
1521 auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
1522
1523 KeyframeEffect* keyframe_effect =
1524 MakeGarbageCollected<KeyframeEffect>(element, model, timing);
1525
1526 // Create scroll-linked animation
1527 NonThrowableExceptionState exception_state;
1528 Animation* scroll_animation =
1529 Animation::Create(keyframe_effect, scroll_timeline, exception_state);
1530
1531 model->SnapshotAllCompositorKeyframesIfNecessary(
1532 *element, *ComputedStyle::Create(), nullptr);
1533
1534 UpdateAllLifecyclePhasesForTest();
1535 const double TEST_START_TIME = 10;
1536 scroll_animation->setStartTime(TEST_START_TIME);
1537 scroll_animation->play();
1538 EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr),
1539 CompositorAnimations::kNoFailure);
1540 // Start the animation on compositor. The time offset of the compositor
1541 // keyframe should be unset if we start the animation with its start time.
1542 scroll_animation->PreCommit(1, nullptr, true);
1543 cc::KeyframeModel* keyframe_model =
1544 keyframe_effect->GetAnimationForTesting()
1545 ->GetCompositorAnimation()
1546 ->CcAnimation()
1547 ->GetKeyframeModel(compositor_target_property::OPACITY);
1548 EXPECT_EQ(keyframe_model->start_time() - base::TimeTicks(),
1549 base::TimeDelta::FromMilliseconds(TEST_START_TIME));
1550 EXPECT_EQ(keyframe_model->time_offset(), base::TimeDelta());
1551 }
1552
1553 // Verifies correctness of scroll linked animation current and start times in
1554 // various animation states.
TEST_F(AnimationAnimationTestNoCompositing,ScrollLinkedAnimationCreation)1555 TEST_F(AnimationAnimationTestNoCompositing, ScrollLinkedAnimationCreation) {
1556 SetBodyInnerHTML(R"HTML(
1557 <style>
1558 #scroller { overflow: scroll; width: 100px; height: 100px; }
1559 #spacer { width: 200px; height: 200px; }
1560 </style>
1561 <div id='scroller'>
1562 <div id ='spacer'></div>
1563 </div>
1564 )HTML");
1565
1566 auto* scroller =
1567 To<LayoutBoxModelObject>(GetLayoutObjectByElementId("scroller"));
1568 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
1569 scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
1570 mojom::blink::ScrollType::kProgrammatic);
1571 ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
1572 DoubleOrScrollTimelineAutoKeyword time_range =
1573 DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
1574 options->setTimeRange(time_range);
1575 options->setScrollSource(GetElementById("scroller"));
1576 ScrollTimeline* scroll_timeline =
1577 ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
1578
1579 NonThrowableExceptionState exception_state;
1580 Animation* scroll_animation =
1581 Animation::Create(MakeAnimation(), scroll_timeline, exception_state);
1582
1583 // Verify start and current times in Idle state.
1584 EXPECT_FALSE(scroll_animation->startTime().has_value());
1585 EXPECT_FALSE(scroll_animation->currentTime().has_value());
1586
1587 scroll_animation->play();
1588
1589 // Verify start and current times in Pending state.
1590 EXPECT_EQ(0, scroll_animation->startTime());
1591 EXPECT_EQ(20, scroll_animation->currentTime());
1592
1593 UpdateAllLifecyclePhasesForTest();
1594 // Verify start and current times in Playing state.
1595 EXPECT_EQ(0, scroll_animation->startTime());
1596 EXPECT_EQ(20, scroll_animation->currentTime());
1597
1598 // Verify current time after scroll.
1599 scrollable_area->SetScrollOffset(ScrollOffset(0, 40),
1600 mojom::blink::ScrollType::kProgrammatic);
1601 SimulateFrameForScrollAnimations();
1602 EXPECT_EQ(40, scroll_animation->currentTime());
1603 }
1604
1605 // Verifies that finished composited scroll-linked animations restart on
1606 // compositor upon reverse scrolling.
TEST_F(AnimationAnimationTestCompositing,FinishedScrollLinkedAnimationRestartsOnReverseScrolling)1607 TEST_F(AnimationAnimationTestCompositing,
1608 FinishedScrollLinkedAnimationRestartsOnReverseScrolling) {
1609 ResetWithCompositedAnimation();
1610 SetBodyInnerHTML(R"HTML(
1611 <style>
1612 #scroller { will-change: transform; overflow: scroll; width: 100px; height: 100px; }
1613 #target { width: 100px; height: 200px; will-change: opacity;}
1614 #spacer { width: 200px; height: 700px; }
1615 </style>
1616 <div id ='scroller'>
1617 <div id ='target'></div>
1618 <div id ='spacer'></div>
1619 </div>
1620 )HTML");
1621
1622 auto* scroller =
1623 To<LayoutBoxModelObject>(GetLayoutObjectByElementId("scroller"));
1624 ASSERT_TRUE(scroller->UsesCompositedScrolling());
1625
1626 // Create ScrollTimeline
1627 ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
1628 DoubleOrScrollTimelineAutoKeyword time_range =
1629 DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
1630 options->setTimeRange(time_range);
1631 options->setScrollSource(GetElementById("scroller"));
1632 ScrollTimeline* scroll_timeline =
1633 ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
1634
1635 // Create KeyframeEffect
1636 Timing timing;
1637 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
1638 Persistent<StringKeyframe> start_keyframe =
1639 MakeGarbageCollected<StringKeyframe>();
1640 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
1641 SecureContextMode::kInsecureContext,
1642 nullptr);
1643 Persistent<StringKeyframe> end_keyframe =
1644 MakeGarbageCollected<StringKeyframe>();
1645 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
1646 SecureContextMode::kInsecureContext,
1647 nullptr);
1648
1649 StringKeyframeVector keyframes;
1650 keyframes.push_back(start_keyframe);
1651 keyframes.push_back(end_keyframe);
1652
1653 Element* element = GetElementById("target");
1654 auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
1655
1656 KeyframeEffect* keyframe_effect =
1657 MakeGarbageCollected<KeyframeEffect>(element, model, timing);
1658
1659 // Create scroll-linked animation
1660 NonThrowableExceptionState exception_state;
1661 Animation* scroll_animation =
1662 Animation::Create(keyframe_effect, scroll_timeline, exception_state);
1663 model->SnapshotAllCompositorKeyframesIfNecessary(
1664 *element, *ComputedStyle::Create(), nullptr);
1665 UpdateAllLifecyclePhasesForTest();
1666
1667 scroll_animation->play();
1668 EXPECT_EQ(scroll_animation->playState(), "running");
1669 GetDocument().GetPendingAnimations().Update(nullptr, true);
1670 EXPECT_TRUE(scroll_animation->HasActiveAnimationsOnCompositor());
1671
1672 // Advances the animation to "finished" state. The composited animation will
1673 // be destroyed accordingly.
1674 scroll_animation->setCurrentTime(50000);
1675 EXPECT_EQ(scroll_animation->playState(), "finished");
1676 scroll_animation->Update(kTimingUpdateForAnimationFrame);
1677 GetDocument().GetPendingAnimations().Update(nullptr, true);
1678 EXPECT_FALSE(scroll_animation->HasActiveAnimationsOnCompositor());
1679
1680 // Restarting the animation should create a new compositor animation.
1681 scroll_animation->setCurrentTime(100);
1682 UpdateAllLifecyclePhasesForTest();
1683 EXPECT_EQ(scroll_animation->playState(), "running");
1684 scroll_animation->Update(kTimingUpdateForAnimationFrame);
1685 GetDocument().GetPendingAnimations().Update(nullptr, true);
1686 EXPECT_TRUE(scroll_animation->HasActiveAnimationsOnCompositor());
1687 }
1688
TEST_F(AnimationAnimationTestNoCompositing,RemoveCanceledAnimationFromActiveSet)1689 TEST_F(AnimationAnimationTestNoCompositing,
1690 RemoveCanceledAnimationFromActiveSet) {
1691 EXPECT_EQ("running", animation->playState());
1692 EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
1693 SimulateFrame(1000);
1694 EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
1695 animation->cancel();
1696 EXPECT_EQ("idle", animation->playState());
1697 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1698 }
1699
TEST_F(AnimationAnimationTestNoCompositing,RemoveFinishedAnimationFromActiveSet)1700 TEST_F(AnimationAnimationTestNoCompositing,
1701 RemoveFinishedAnimationFromActiveSet) {
1702 EXPECT_EQ("running", animation->playState());
1703 EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
1704 SimulateFrame(1000);
1705 EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
1706
1707 // Synchronous completion.
1708 animation->finish();
1709 EXPECT_EQ("finished", animation->playState());
1710 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1711
1712 // Play creates a new pending finished promise.
1713 animation->play();
1714 EXPECT_EQ("running", animation->playState());
1715 EXPECT_TRUE(animation->Update(kTimingUpdateForAnimationFrame));
1716
1717 // Asynchronous completion.
1718 animation->setCurrentTime(50000);
1719 EXPECT_EQ("finished", animation->playState());
1720 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1721 }
1722
TEST_F(AnimationAnimationTestNoCompositing,PendingActivityWithFinishedPromise)1723 TEST_F(AnimationAnimationTestNoCompositing,
1724 PendingActivityWithFinishedPromise) {
1725 // No pending activity even when running if there is no finished promise
1726 // or event listener.
1727 EXPECT_EQ("running", animation->playState());
1728 SimulateFrame(1000);
1729 EXPECT_FALSE(animation->HasPendingActivity());
1730
1731 // An unresolved finished promise indicates pending activity.
1732 ScriptState* script_state =
1733 ToScriptStateForMainWorld(GetDocument().GetFrame());
1734 animation->finished(script_state);
1735 EXPECT_TRUE(animation->HasPendingActivity());
1736
1737 // Resolving the finished promise clears the pending activity.
1738 animation->setCurrentTime(50000);
1739 EXPECT_EQ("finished", animation->playState());
1740 SimulateMicrotask();
1741 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1742 EXPECT_FALSE(animation->HasPendingActivity());
1743
1744 // Playing an already finished animation creates a new pending finished
1745 // promise.
1746 animation->play();
1747 EXPECT_EQ("running", animation->playState());
1748 SimulateFrame(2000);
1749 EXPECT_TRUE(animation->HasPendingActivity());
1750 // Cancel rejects the finished promise and creates a new pending finished
1751 // promise.
1752 // TODO(crbug.com/960944): Investigate if this should return false to prevent
1753 // holding onto the animation indefinitely.
1754 animation->cancel();
1755 EXPECT_TRUE(animation->HasPendingActivity());
1756 }
1757
1758 class MockEventListener final : public NativeEventListener {
1759 public:
1760 MOCK_METHOD2(Invoke, void(ExecutionContext*, Event*));
1761 };
1762
TEST_F(AnimationAnimationTestNoCompositing,PendingActivityWithFinishedEventListener)1763 TEST_F(AnimationAnimationTestNoCompositing,
1764 PendingActivityWithFinishedEventListener) {
1765 EXPECT_EQ("running", animation->playState());
1766 EXPECT_FALSE(animation->HasPendingActivity());
1767
1768 // Attaching a listener for the finished event indicates pending activity.
1769 Persistent<MockEventListener> event_listener =
1770 MakeGarbageCollected<MockEventListener>();
1771 animation->addEventListener(event_type_names::kFinish, event_listener);
1772 EXPECT_TRUE(animation->HasPendingActivity());
1773
1774 // Synchronous finish clears pending activity.
1775 animation->finish();
1776 EXPECT_EQ("finished", animation->playState());
1777 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1778 EXPECT_TRUE(animation->HasPendingActivity());
1779 animation->pending_finished_event_ = nullptr;
1780 EXPECT_FALSE(animation->HasPendingActivity());
1781
1782 // Playing an already finished animation resets the finished state.
1783 animation->play();
1784 EXPECT_EQ("running", animation->playState());
1785 SimulateFrame(2000);
1786 EXPECT_TRUE(animation->HasPendingActivity());
1787
1788 // Finishing the animation asynchronously clears the pending activity.
1789 animation->setCurrentTime(50000);
1790 EXPECT_EQ("finished", animation->playState());
1791 SimulateMicrotask();
1792 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1793 EXPECT_TRUE(animation->HasPendingActivity());
1794 animation->pending_finished_event_ = nullptr;
1795 EXPECT_FALSE(animation->HasPendingActivity());
1796
1797 // Canceling an animation clears the pending activity.
1798 animation->play();
1799 EXPECT_EQ("running", animation->playState());
1800 SimulateFrame(2000);
1801 animation->cancel();
1802 EXPECT_EQ("idle", animation->playState());
1803 EXPECT_FALSE(animation->Update(kTimingUpdateForAnimationFrame));
1804 EXPECT_FALSE(animation->HasPendingActivity());
1805 }
1806
1807 class AnimationPendingAnimationsTest : public RenderingTest {
1808 public:
AnimationPendingAnimationsTest()1809 AnimationPendingAnimationsTest()
1810 : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()) {}
1811
1812 enum CompositingMode { kComposited, kNonComposited };
1813
SetUp()1814 void SetUp() override {
1815 EnableCompositing();
1816 RenderingTest::SetUp();
1817 GetDocument().GetAnimationClock().ResetTimeForTesting();
1818 timeline = GetDocument().Timeline();
1819 timeline->ResetForTesting();
1820 }
1821
MakeAnimation(const char * target,CompositingMode mode)1822 Animation* MakeAnimation(const char* target, CompositingMode mode) {
1823 Timing timing;
1824 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
1825 Persistent<StringKeyframe> start_keyframe =
1826 MakeGarbageCollected<StringKeyframe>();
1827 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
1828 SecureContextMode::kInsecureContext,
1829 nullptr);
1830 Persistent<StringKeyframe> end_keyframe =
1831 MakeGarbageCollected<StringKeyframe>();
1832 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
1833 SecureContextMode::kInsecureContext,
1834 nullptr);
1835
1836 StringKeyframeVector keyframes;
1837 keyframes.push_back(start_keyframe);
1838 keyframes.push_back(end_keyframe);
1839
1840 Element* element = GetElementById(target);
1841 auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
1842
1843 Animation* animation = timeline->Play(
1844 MakeGarbageCollected<KeyframeEffect>(element, model, timing));
1845
1846 if (mode == kNonComposited) {
1847 // Having a playback rate of zero is one of several ways to force an
1848 // animation to be non-composited.
1849 animation->updatePlaybackRate(0);
1850 }
1851
1852 return animation;
1853 }
1854
Update()1855 bool Update() {
1856 UpdateAllLifecyclePhasesForTest();
1857 GetDocument().GetAnimationClock().UpdateTime(base::TimeTicks());
1858 return GetDocument().GetPendingAnimations().Update(nullptr, true);
1859 }
1860
NotifyAnimationStarted(Animation * animation)1861 void NotifyAnimationStarted(Animation* animation) {
1862 animation->GetDocument()
1863 ->GetPendingAnimations()
1864 .NotifyCompositorAnimationStarted(0, animation->CompositorGroup());
1865 }
1866
restartAnimation(Animation * animation)1867 void restartAnimation(Animation* animation) {
1868 animation->cancel();
1869 animation->play();
1870 }
1871
1872 Persistent<DocumentTimeline> timeline;
1873 };
1874
TEST_F(AnimationPendingAnimationsTest,PendingAnimationStartSynchronization)1875 TEST_F(AnimationPendingAnimationsTest, PendingAnimationStartSynchronization) {
1876 RunDocumentLifecycle();
1877 SetBodyInnerHTML("<div id='foo'></div><div id='bar'></div>");
1878
1879 Persistent<Animation> animA = MakeAnimation("foo", kComposited);
1880 Persistent<Animation> animB = MakeAnimation("bar", kNonComposited);
1881
1882 // B's start time synchronized with A's start time.
1883 EXPECT_TRUE(Update());
1884 EXPECT_TRUE(animA->pending());
1885 EXPECT_TRUE(animB->pending());
1886 EXPECT_TRUE(animA->HasActiveAnimationsOnCompositor());
1887 EXPECT_FALSE(animB->HasActiveAnimationsOnCompositor());
1888 NotifyAnimationStarted(animA);
1889 EXPECT_FALSE(animA->pending());
1890 EXPECT_FALSE(animB->pending());
1891 }
1892
TEST_F(AnimationPendingAnimationsTest,PendingAnimationCancelUnblocksSynchronizedStart)1893 TEST_F(AnimationPendingAnimationsTest,
1894 PendingAnimationCancelUnblocksSynchronizedStart) {
1895 RunDocumentLifecycle();
1896 SetBodyInnerHTML("<div id='foo'></div><div id='bar'></div>");
1897
1898 Persistent<Animation> animA = MakeAnimation("foo", kComposited);
1899 Persistent<Animation> animB = MakeAnimation("bar", kNonComposited);
1900
1901 EXPECT_TRUE(Update());
1902 EXPECT_TRUE(animA->pending());
1903 EXPECT_TRUE(animB->pending());
1904 animA->cancel();
1905
1906 // Animation A no longer blocks B from starting.
1907 EXPECT_FALSE(Update());
1908 EXPECT_FALSE(animB->pending());
1909 }
1910
TEST_F(AnimationPendingAnimationsTest,PendingAnimationOnlySynchronizeStartsOfNewlyPendingAnimations)1911 TEST_F(AnimationPendingAnimationsTest,
1912 PendingAnimationOnlySynchronizeStartsOfNewlyPendingAnimations) {
1913 RunDocumentLifecycle();
1914 SetBodyInnerHTML(
1915 "<div id='foo'></div><div id='bar'></div><div id='baz'></div>");
1916
1917 Persistent<Animation> animA = MakeAnimation("foo", kComposited);
1918 Persistent<Animation> animB = MakeAnimation("bar", kNonComposited);
1919
1920 // This test simulates the conditions in crbug.com/666710. The start of a
1921 // non-composited animation is deferred in order to synchronize with a
1922 // composited animation, which is canceled before it starts. Subsequent frames
1923 // produce new composited animations which prevented the non-composited
1924 // animation from ever starting. Non-composited animations should not be
1925 // synchronize with new composited animations if queued up in a prior call to
1926 // PendingAnimations::Update.
1927 EXPECT_TRUE(Update());
1928 EXPECT_TRUE(animA->pending());
1929 EXPECT_TRUE(animB->pending());
1930 animA->cancel();
1931
1932 Persistent<Animation> animC = MakeAnimation("baz", kComposited);
1933 Persistent<Animation> animD = MakeAnimation("bar", kNonComposited);
1934
1935 EXPECT_TRUE(Update());
1936 // B's is unblocked despite newly created composited animation.
1937 EXPECT_FALSE(animB->pending());
1938 EXPECT_TRUE(animC->pending());
1939 // D's start time is synchronized with C's start.
1940 EXPECT_TRUE(animD->pending());
1941 NotifyAnimationStarted(animC);
1942 EXPECT_FALSE(animC->pending());
1943 EXPECT_FALSE(animD->pending());
1944 }
1945
TEST_F(AnimationAnimationTestCompositing,ScrollLinkedAnimationNotCompositedIfScrollSourceIsNotComposited)1946 TEST_F(AnimationAnimationTestCompositing,
1947 ScrollLinkedAnimationNotCompositedIfScrollSourceIsNotComposited) {
1948 GetDocument().GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
1949 SetBodyInnerHTML(R"HTML(
1950 <style>
1951 #scroller { overflow: scroll; width: 100px; height: 100px; }
1952 /* to prevent the mock overlay scrollbar from affecting compositing. */
1953 #scroller::-webkit-scrollbar { display: none; }
1954 #target { width: 100px; height: 200px; will-change: transform; }
1955 #spacer { width: 200px; height: 2000px; }
1956 </style>
1957 <div id ='scroller'>
1958 <div id ='target'></div>
1959 <div id ='spacer'></div>
1960 </div>
1961 )HTML");
1962
1963 // Create ScrollTimeline
1964 auto* scroller =
1965 To<LayoutBoxModelObject>(GetLayoutObjectByElementId("scroller"));
1966 PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
1967 ASSERT_FALSE(scroller->UsesCompositedScrolling());
1968 scrollable_area->SetScrollOffset(ScrollOffset(0, 20),
1969 mojom::blink::ScrollType::kProgrammatic);
1970 ScrollTimelineOptions* options = ScrollTimelineOptions::Create();
1971 DoubleOrScrollTimelineAutoKeyword time_range =
1972 DoubleOrScrollTimelineAutoKeyword::FromDouble(100);
1973 options->setTimeRange(time_range);
1974 options->setScrollSource(GetElementById("scroller"));
1975 ScrollTimeline* scroll_timeline =
1976 ScrollTimeline::Create(GetDocument(), options, ASSERT_NO_EXCEPTION);
1977
1978 // Create KeyframeEffect
1979 Timing timing;
1980 timing.iteration_duration = AnimationTimeDelta::FromSecondsD(30);
1981
1982 Persistent<StringKeyframe> start_keyframe =
1983 MakeGarbageCollected<StringKeyframe>();
1984 start_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "1.0",
1985 SecureContextMode::kInsecureContext,
1986 nullptr);
1987 Persistent<StringKeyframe> end_keyframe =
1988 MakeGarbageCollected<StringKeyframe>();
1989 end_keyframe->SetCSSPropertyValue(CSSPropertyID::kOpacity, "0.0",
1990 SecureContextMode::kInsecureContext,
1991 nullptr);
1992
1993 StringKeyframeVector keyframes;
1994 keyframes.push_back(start_keyframe);
1995 keyframes.push_back(end_keyframe);
1996
1997 Element* element = GetElementById("target");
1998 auto* model = MakeGarbageCollected<StringKeyframeEffectModel>(keyframes);
1999
2000 // Create scroll-linked animation
2001 NonThrowableExceptionState exception_state;
2002 Animation* scroll_animation = Animation::Create(
2003 MakeGarbageCollected<KeyframeEffect>(element, model, timing),
2004 scroll_timeline, exception_state);
2005
2006 model->SnapshotAllCompositorKeyframesIfNecessary(
2007 *element, *ComputedStyle::Create(), nullptr);
2008
2009 UpdateAllLifecyclePhasesForTest();
2010 scroll_animation->play();
2011 EXPECT_EQ(scroll_animation->CheckCanStartAnimationOnCompositor(nullptr),
2012 CompositorAnimations::kTimelineSourceHasInvalidCompositingState);
2013 }
2014
2015 } // namespace blink
2016