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