Home | History | Annotate | Download | only in animation
      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
    749