Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / animation / AnimationPlayer.cpp
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 "config.h"
32 #include "core/animation/AnimationPlayer.h"
33
34 #include "core/animation/Animation.h"
35 #include "core/animation/AnimationTimeline.h"
36 #include "core/dom/Document.h"
37 #include "core/events/AnimationPlayerEvent.h"
38 #include "core/frame/UseCounter.h"
39 #include "platform/TraceEvent.h"
40 #include "wtf/MathExtras.h"
41
42 namespace blink {
43
44 namespace {
45
46 static unsigned nextSequenceNumber()
47 {
48     static unsigned next = 0;
49     return ++next;
50 }
51
52 }
53
54 PassRefPtrWillBeRawPtr<AnimationPlayer> AnimationPlayer::create(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationNode* content)
55 {
56     RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeNoop(new AnimationPlayer(executionContext, timeline, content));
57     player->uncancel();
58     timeline.document()->compositorPendingAnimations().add(player.get());
59     player->suspendIfNeeded();
60     return player.release();
61 }
62
63 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationNode* content)
64     : ActiveDOMObject(executionContext)
65     , m_playbackRate(1)
66     , m_startTime(nullValue())
67     , m_holdTime(0)
68     , m_sequenceNumber(nextSequenceNumber())
69     , m_content(content)
70     , m_timeline(&timeline)
71     , m_paused(false)
72     , m_held(true)
73     , m_isPausedForTesting(false)
74     , m_outdated(true)
75     , m_finished(true)
76     , m_compositorState(nullptr)
77     , m_compositorPending(true)
78     , m_currentTimePending(false)
79     , m_idle(true)
80 {
81     if (m_content) {
82         if (m_content->player()) {
83             m_content->player()->cancel();
84             m_content->player()->setSource(0);
85         }
86         m_content->attach(this);
87     }
88 }
89
90 AnimationPlayer::~AnimationPlayer()
91 {
92 #if !ENABLE(OILPAN)
93     if (m_content)
94         m_content->detach();
95     if (m_timeline)
96         m_timeline->playerDestroyed(this);
97 #endif
98 }
99
100 double AnimationPlayer::sourceEnd() const
101 {
102     return m_content ? m_content->endTimeInternal() : 0;
103 }
104
105 bool AnimationPlayer::limited(double currentTime) const
106 {
107     return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && currentTime >= sourceEnd());
108 }
109
110 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdateReason reason)
111 {
112     ASSERT(std::isfinite(newCurrentTime));
113
114     bool oldHeld = m_held;
115     bool outdated = false;
116     bool isLimited = limited(newCurrentTime);
117     m_held = m_paused || !m_playbackRate || isLimited || std::isnan(m_startTime);
118     if (m_held) {
119         if (!oldHeld || m_holdTime != newCurrentTime)
120             outdated = true;
121         m_holdTime = newCurrentTime;
122         if (m_paused || !m_playbackRate) {
123             m_startTime = nullValue();
124         } else if (isLimited && std::isnan(m_startTime) && reason == TimingUpdateForAnimationFrame) {
125             m_startTime = calculateStartTime(newCurrentTime);
126         }
127     } else {
128         m_holdTime = nullValue();
129         m_startTime = calculateStartTime(newCurrentTime);
130         setFinished(false);
131         outdated = true;
132     }
133
134     if (outdated) {
135         setOutdated();
136     }
137 }
138
139 // Update timing to reflect updated animation clock due to tick
140 void AnimationPlayer::updateCurrentTimingState(TimingUpdateReason reason)
141 {
142     if (m_held) {
143         setCurrentTimeInternal(m_holdTime, reason);
144         return;
145     }
146     if (!limited(calculateCurrentTime()))
147         return;
148     m_held = true;
149     m_holdTime = m_playbackRate < 0 ? 0 : sourceEnd();
150 }
151
152 double AnimationPlayer::startTime(bool& isNull) const
153 {
154     double result = startTime();
155     isNull = std::isnan(result);
156     return result;
157 }
158
159 double AnimationPlayer::startTime() const
160 {
161     UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetStartTime);
162     return m_startTime * 1000;
163 }
164
165 double AnimationPlayer::currentTime(bool& isNull)
166 {
167     double result = currentTime();
168     isNull = std::isnan(result);
169     return result;
170 }
171
172 double AnimationPlayer::currentTime()
173 {
174     UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentTime);
175     if (m_currentTimePending || m_idle)
176         return std::numeric_limits<double>::quiet_NaN();
177     return currentTimeInternal() * 1000;
178 }
179
180 double AnimationPlayer::currentTimeInternal()
181 {
182     updateCurrentTimingState(TimingUpdateOnDemand);
183     if (m_held)
184         return m_holdTime;
185     return calculateCurrentTime();
186 }
187
188 void AnimationPlayer::preCommit(bool startOnCompositor)
189 {
190     if (m_compositorState && m_compositorState->pendingAction == Start) {
191         // Still waiting for a start time.
192         return;
193     }
194
195     bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate);
196     bool hardChange = m_compositorState && (m_compositorState->sourceChanged || (m_compositorState->startTime != m_startTime && !std::isnan(m_compositorState->startTime) && !std::isnan(m_startTime)));
197
198     // FIXME: softChange && !hardChange should generate a Pause/ThenStart,
199     // not a Cancel, but we can't communicate these to the compositor yet.
200
201     bool changed = softChange || hardChange;
202     bool shouldCancel = (!playing() && m_compositorState) || changed;
203     bool shouldStart = playing() && (!m_compositorState || changed);
204
205     if (shouldCancel) {
206         cancelAnimationOnCompositor();
207         m_compositorState = nullptr;
208
209     }
210
211     if (!shouldStart) {
212         m_currentTimePending = false;
213     }
214
215     if (shouldStart && startOnCompositor && maybeStartAnimationOnCompositor()) {
216         m_compositorState = adoptPtr(new CompositorState(*this));
217     }
218 }
219
220 void AnimationPlayer::postCommit(double timelineTime)
221 {
222     m_compositorPending = false;
223
224     if (!m_compositorState || m_compositorState->pendingAction == None)
225         return;
226
227     switch (m_compositorState->pendingAction) {
228     case Start:
229         if (!std::isnan(m_compositorState->startTime)) {
230             ASSERT(m_startTime == m_compositorState->startTime);
231             m_compositorState->pendingAction = None;
232         }
233         break;
234     case Pause:
235     case PauseThenStart:
236         ASSERT(std::isnan(m_startTime));
237         m_compositorState->pendingAction = None;
238         setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m_playbackRate, TimingUpdateForAnimationFrame);
239         m_currentTimePending = false;
240         break;
241     default:
242         ASSERT_NOT_REACHED();
243     }
244 }
245
246 void AnimationPlayer::notifyCompositorStartTime(double timelineTime)
247 {
248     if (m_compositorState) {
249         ASSERT(m_compositorState->pendingAction == Start);
250         ASSERT(std::isnan(m_compositorState->startTime));
251
252         double initialCompositorHoldTime = m_compositorState->holdTime;
253         m_compositorState->pendingAction = None;
254         m_compositorState->startTime = timelineTime + currentTimeInternal() / -m_playbackRate;
255
256         if (paused() || m_compositorState->playbackRate != m_playbackRate || m_compositorState->sourceChanged) {
257             // Paused state, playback rate, or source changed while starting.
258             setCompositorPending();
259         }
260
261         if (m_startTime == timelineTime) {
262             // The start time was set to the incoming compositor start time.
263             // Unlikely, but possible.
264             // FIXME: Depending on what changed above this might still be pending.
265             // Maybe...
266             m_currentTimePending = false;
267             return;
268         }
269
270         if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) {
271             // A new start time or current time was set while starting.
272             setCompositorPending();
273             return;
274         }
275     }
276
277     if (playing()) {
278         ASSERT(std::isnan(m_startTime));
279         ASSERT(m_held);
280
281         if (m_playbackRate == 0) {
282             setStartTimeInternal(timelineTime);
283         } else {
284             setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playbackRate);
285         }
286
287         // FIXME: This avoids marking this player as outdated needlessly when a start time
288         // is notified, but we should refactor how outdating works to avoid this.
289         m_outdated = false;
290
291         m_currentTimePending = false;
292     }
293 }
294
295 double AnimationPlayer::calculateStartTime(double currentTime) const
296 {
297     return m_timeline->effectiveTime() - currentTime / m_playbackRate;
298 }
299
300 double AnimationPlayer::calculateCurrentTime() const
301 {
302     ASSERT(!m_held);
303     if (isNull(m_startTime) || !m_timeline)
304         return 0;
305     return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate;
306 }
307
308 void AnimationPlayer::setCurrentTime(double newCurrentTime)
309 {
310     UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentTime);
311     if (!std::isfinite(newCurrentTime))
312         return;
313
314     setCompositorPending();
315     m_currentTimePending = false;
316     setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand);
317 }
318
319 void AnimationPlayer::setStartTime(double startTime)
320 {
321     UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTime);
322     if (m_paused || m_idle)
323         return;
324     if (!std::isfinite(startTime))
325         return;
326     if (startTime == m_startTime)
327         return;
328
329     setCompositorPending();
330     m_currentTimePending = false;
331     setStartTimeInternal(startTime / 1000);
332 }
333
334 void AnimationPlayer::setStartTimeInternal(double newStartTime)
335 {
336     ASSERT(!m_paused);
337     ASSERT(std::isfinite(newStartTime));
338     ASSERT(newStartTime != m_startTime);
339
340     bool hadStartTime = hasStartTime();
341     double previousCurrentTime = currentTimeInternal();
342     m_startTime = newStartTime;
343     if (m_held && m_playbackRate) {
344         // If held, the start time would still be derrived from the hold time.
345         // Force a new, limited, current time.
346         m_held = false;
347         double currentTime = calculateCurrentTime();
348         if (m_playbackRate > 0 && currentTime > sourceEnd()) {
349             currentTime = sourceEnd();
350         } else if (m_playbackRate < 0 && currentTime < 0) {
351             currentTime = 0;
352         }
353         setCurrentTimeInternal(currentTime, TimingUpdateOnDemand);
354     }
355     double newCurrentTime = currentTimeInternal();
356
357     if (previousCurrentTime != newCurrentTime) {
358         setOutdated();
359     } else if (!hadStartTime && m_timeline) {
360         // Even though this player is not outdated, time to effect change is
361         // infinity until start time is set.
362         m_timeline->wake();
363     }
364 }
365
366 void AnimationPlayer::setSource(AnimationNode* newSource)
367 {
368     if (m_content == newSource)
369         return;
370
371     setCompositorPending(true);
372
373     double storedCurrentTime = currentTimeInternal();
374     if (m_content)
375         m_content->detach();
376     m_content = newSource;
377     if (newSource) {
378         // FIXME: This logic needs to be updated once groups are implemented
379         if (newSource->player()) {
380             newSource->player()->cancel();
381             newSource->player()->setSource(0);
382         }
383         newSource->attach(this);
384         setOutdated();
385     }
386     setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand);
387 }
388
389 String AnimationPlayer::playState()
390 {
391     switch (playStateInternal()) {
392     case Idle:
393         return "idle";
394     case Pending:
395         return "pending";
396     case Running:
397         return "running";
398     case Paused:
399         return "paused";
400     case Finished:
401         return "finished";
402     default:
403         ASSERT_NOT_REACHED();
404         return "";
405     }
406 }
407
408 AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal()
409 {
410     if (m_idle)
411         return Idle;
412     if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackRate != 0))
413         return Pending;
414     if (m_paused)
415         return Paused;
416     if (finished())
417         return Finished;
418     return Running;
419 }
420
421 void AnimationPlayer::pause()
422 {
423     if (m_paused)
424         return;
425     if (playing()) {
426         setCompositorPending();
427         m_currentTimePending = true;
428     }
429     m_paused = true;
430     setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand);
431 }
432
433 void AnimationPlayer::unpause()
434 {
435     if (!m_paused)
436         return;
437     setCompositorPending();
438     m_currentTimePending = true;
439     unpauseInternal();
440 }
441
442 void AnimationPlayer::unpauseInternal()
443 {
444     if (!m_paused)
445         return;
446     m_paused = false;
447     setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand);
448 }
449
450 void AnimationPlayer::play()
451 {
452     if (!playing())
453         m_startTime = nullValue();
454
455     setCompositorPending();
456     uncancel();
457     unpauseInternal();
458     if (!m_content)
459         return;
460     double currentTime = this->currentTimeInternal();
461     if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd()))
462         setCurrentTimeInternal(0, TimingUpdateOnDemand);
463     else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd()))
464         setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand);
465     setFinished(false);
466 }
467
468 void AnimationPlayer::reverse()
469 {
470     if (!m_playbackRate) {
471         return;
472     }
473
474     uncancel();
475     setPlaybackRateInternal(-m_playbackRate);
476     play();
477 }
478
479 void AnimationPlayer::finish(ExceptionState& exceptionState)
480 {
481     if (!m_playbackRate || m_idle) {
482         return;
483     }
484     if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infinity()) {
485         exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity.");
486         return;
487     }
488     if (playing()) {
489         setCompositorPending();
490     }
491
492     uncancel();
493
494     double newCurrentTime = m_playbackRate < 0 ? 0 : sourceEnd();
495     setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand);
496     if (!paused()) {
497         m_startTime = calculateStartTime(newCurrentTime);
498     }
499
500     m_currentTimePending = false;
501     ASSERT(finished());
502 }
503
504 const AtomicString& AnimationPlayer::interfaceName() const
505 {
506     return EventTargetNames::AnimationPlayer;
507 }
508
509 ExecutionContext* AnimationPlayer::executionContext() const
510 {
511     return ActiveDOMObject::executionContext();
512 }
513
514 bool AnimationPlayer::hasPendingActivity() const
515 {
516     return m_pendingFinishedEvent || (!m_finished && hasEventListeners(EventTypeNames::finish));
517 }
518
519 void AnimationPlayer::stop()
520 {
521     setFinished(true);
522     m_pendingFinishedEvent = nullptr;
523 }
524
525 bool AnimationPlayer::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
526 {
527     if (m_pendingFinishedEvent == event)
528         m_pendingFinishedEvent = nullptr;
529     return EventTargetWithInlineData::dispatchEvent(event);
530 }
531
532 double AnimationPlayer::playbackRate() const
533 {
534     UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetPlaybackRate);
535     return m_playbackRate;
536 }
537
538 void AnimationPlayer::setPlaybackRate(double playbackRate)
539 {
540     UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetPlaybackRate);
541     if (!std::isfinite(playbackRate))
542         return;
543     if (playbackRate == m_playbackRate)
544         return;
545
546     setPlaybackRateInternal(playbackRate);
547 }
548
549 void AnimationPlayer::setPlaybackRateInternal(double playbackRate)
550 {
551     ASSERT(std::isfinite(playbackRate));
552     ASSERT(playbackRate != m_playbackRate);
553
554     setCompositorPending();
555     if (!finished() && !paused() && hasStartTime())
556         m_currentTimePending = true;
557
558     double storedCurrentTime = currentTimeInternal();
559     if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && playbackRate <= 0))
560         setFinished(false);
561
562     m_playbackRate = playbackRate;
563     m_startTime = std::numeric_limits<double>::quiet_NaN();
564     setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand);
565 }
566
567 void AnimationPlayer::setOutdated()
568 {
569     m_outdated = true;
570     if (m_timeline)
571         m_timeline->setOutdatedAnimationPlayer(this);
572 }
573
574 bool AnimationPlayer::canStartAnimationOnCompositor()
575 {
576     if (m_playbackRate == 0 || (std::isinf(sourceEnd()) && m_playbackRate < 0))
577         return false;
578
579     return m_timeline && m_content && m_content->isAnimation() && playing();
580 }
581
582 bool AnimationPlayer::maybeStartAnimationOnCompositor()
583 {
584     if (!canStartAnimationOnCompositor())
585         return false;
586
587     bool reversed = m_playbackRate < 0;
588
589     double startTime = timeline()->zeroTime() + startTimeInternal();
590     if (reversed) {
591         startTime -= sourceEnd() / fabs(m_playbackRate);
592     }
593
594     double timeOffset = 0;
595     if (std::isnan(startTime)) {
596         timeOffset = reversed ? sourceEnd() - currentTimeInternal() : currentTimeInternal();
597         timeOffset = timeOffset / fabs(m_playbackRate);
598     }
599     return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(startTime, timeOffset, m_playbackRate);
600 }
601
602 void AnimationPlayer::setCompositorPending(bool sourceChanged)
603 {
604     // FIXME: Animation could notify this directly?
605     if (!hasActiveAnimationsOnCompositor()) {
606         m_compositorState.release();
607     }
608     if (!m_compositorPending) {
609         m_compositorPending = true;
610         if (sourceChanged && m_compositorState)
611             m_compositorState->sourceChanged = true;
612         timeline()->document()->compositorPendingAnimations().add(this);
613     }
614 }
615
616 bool AnimationPlayer::hasActiveAnimationsOnCompositor()
617 {
618     if (!m_content || !m_content->isAnimation())
619         return false;
620
621     return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor();
622 }
623
624 void AnimationPlayer::cancelAnimationOnCompositor()
625 {
626     if (hasActiveAnimationsOnCompositor())
627         toAnimation(m_content.get())->cancelAnimationOnCompositor();
628 }
629
630 bool AnimationPlayer::update(TimingUpdateReason reason)
631 {
632     if (!m_timeline)
633         return false;
634
635     updateCurrentTimingState(reason);
636     m_outdated = false;
637
638     if (m_content) {
639         double inheritedTime = m_idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal();
640         // Special case for end-exclusivity when playing backwards.
641         if (inheritedTime == 0 && m_playbackRate < 0)
642             inheritedTime = -1;
643         m_content->updateInheritedTime(inheritedTime, reason);
644     }
645
646     if ((m_idle || finished()) && !m_finished) {
647         if (reason == TimingUpdateForAnimationFrame && (m_idle || hasStartTime())) {
648             const AtomicString& eventType = EventTypeNames::finish;
649             if (executionContext() && hasEventListeners(eventType)) {
650                 double eventCurrentTime = currentTimeInternal() * 1000;
651                 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime());
652                 m_pendingFinishedEvent->setTarget(this);
653                 m_pendingFinishedEvent->setCurrentTarget(this);
654                 m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent);
655             }
656             setFinished(true);
657         }
658     }
659     ASSERT(!m_outdated);
660     return !m_finished;
661 }
662
663 double AnimationPlayer::timeToEffectChange()
664 {
665     ASSERT(!m_outdated);
666     if (m_held || !hasStartTime())
667         return std::numeric_limits<double>::infinity();
668     if (!m_content)
669         return -currentTimeInternal() / m_playbackRate;
670     if (m_playbackRate > 0)
671         return m_content->timeToForwardsEffectChange() / m_playbackRate;
672     return m_content->timeToReverseEffectChange() / -m_playbackRate;
673 }
674
675 void AnimationPlayer::setFinished(bool finished)
676 {
677     if (m_finished && !finished) {
678         if (m_content) {
679             TRACE_EVENT_ASYNC_BEGIN1("blink", "Animation", this, "Name", TRACE_STR_COPY(m_content->name().utf8().data()));
680         } else {
681             TRACE_EVENT_ASYNC_BEGIN0("blink", "Animation", this);
682         }
683     }
684     if (!m_finished && finished) {
685         TRACE_EVENT_ASYNC_END0("blink", "Animation", this);
686     }
687     m_finished = finished;
688 }
689
690 void AnimationPlayer::cancel()
691 {
692     if (m_idle)
693         return;
694
695     m_holdTime = currentTimeInternal();
696     m_held = true;
697     m_idle = true;
698     m_startTime = nullValue();
699     m_currentTimePending = false;
700     setCompositorPending();
701 }
702
703 void AnimationPlayer::uncancel()
704 {
705     if (!m_idle)
706         return;
707
708     m_idle = false;
709     m_held = true;
710     m_holdTime = 0;
711     setFinished(false);
712 }
713
714
715 #if !ENABLE(OILPAN)
716 bool AnimationPlayer::canFree() const
717 {
718     ASSERT(m_content);
719     return hasOneRef() && m_content->isAnimation() && m_content->hasOneRef();
720 }
721 #endif
722
723 bool AnimationPlayer::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
724 {
725     if (eventType == EventTypeNames::finish)
726         UseCounter::count(executionContext(), UseCounter::AnimationPlayerFinishEvent);
727     return EventTargetWithInlineData::addEventListener(eventType, listener, useCapture);
728 }
729
730 void AnimationPlayer::pauseForTesting(double pauseTime)
731 {
732     RELEASE_ASSERT(!paused());
733     setCurrentTimeInternal(pauseTime, TimingUpdateOnDemand);
734     if (hasActiveAnimationsOnCompositor())
735         toAnimation(m_content.get())->pauseAnimationForTestingOnCompositor(currentTimeInternal());
736     m_isPausedForTesting = true;
737     pause();
738 }
739
740 void AnimationPlayer::trace(Visitor* visitor)
741 {
742     visitor->trace(m_content);
743     visitor->trace(m_timeline);
744     visitor->trace(m_pendingFinishedEvent);
745     EventTargetWithInlineData::trace(visitor);
746 }
747
748 } // namespace