Rename rendering/RenderFileUploadControl to layout/LayoutFileUploadControl.
[chromium-blink-merge.git] / third_party / WebKit / Source / core / animation / AnimationPlayer.cpp
blob64c06896e306042b7529338806bdc05ad31e14c5
1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
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.
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.
31 #include "config.h"
32 #include "core/animation/AnimationPlayer.h"
34 #include "core/animation/Animation.h"
35 #include "core/animation/AnimationTimeline.h"
36 #include "core/dom/Document.h"
37 #include "core/dom/ExceptionCode.h"
38 #include "core/events/AnimationPlayerEvent.h"
39 #include "core/frame/UseCounter.h"
40 #include "core/inspector/InspectorInstrumentation.h"
41 #include "core/inspector/InspectorTraceEvents.h"
42 #include "platform/TraceEvent.h"
43 #include "wtf/MathExtras.h"
45 namespace blink {
47 namespace {
49 static unsigned nextSequenceNumber()
51 static unsigned next = 0;
52 return ++next;
57 PassRefPtrWillBeRawPtr<AnimationPlayer> AnimationPlayer::create(AnimationNode* source, AnimationTimeline* timeline)
59 if (!timeline) {
60 // FIXME: Support creating players without a timeline.
61 return nullptr;
64 RefPtrWillBeRawPtr<AnimationPlayer> player = adoptRefWillBeNoop(new AnimationPlayer(timeline->document()->contextDocument().get(), *timeline, source));
65 player->suspendIfNeeded();
67 if (timeline) {
68 timeline->playerAttached(*player);
71 return player.release();
74 AnimationPlayer::AnimationPlayer(ExecutionContext* executionContext, AnimationTimeline& timeline, AnimationNode* content)
75 : ActiveDOMObject(executionContext)
76 , m_playState(Idle)
77 , m_playbackRate(1)
78 , m_startTime(nullValue())
79 , m_holdTime(0)
80 , m_sequenceNumber(nextSequenceNumber())
81 , m_content(content)
82 , m_timeline(&timeline)
83 , m_paused(false)
84 , m_held(true)
85 , m_isPausedForTesting(false)
86 , m_outdated(false)
87 , m_finished(true)
88 , m_compositorState(nullptr)
89 , m_compositorPending(false)
90 , m_compositorGroup(0)
91 , m_currentTimePending(false)
92 , m_stateIsBeingUpdated(false)
94 if (m_content) {
95 if (m_content->player()) {
96 m_content->player()->cancel();
97 m_content->player()->setSource(0);
99 m_content->attach(this);
103 AnimationPlayer::~AnimationPlayer()
105 #if !ENABLE(OILPAN)
106 if (m_content)
107 m_content->detach();
108 if (m_timeline)
109 m_timeline->playerDestroyed(this);
110 #endif
113 double AnimationPlayer::sourceEnd() const
115 return m_content ? m_content->endTimeInternal() : 0;
118 bool AnimationPlayer::limited(double currentTime) const
120 return (m_playbackRate < 0 && currentTime <= 0) || (m_playbackRate > 0 && currentTime >= sourceEnd());
123 void AnimationPlayer::setCurrentTime(double newCurrentTime)
125 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetCurrentTime);
127 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
129 m_currentTimePending = false;
130 setCurrentTimeInternal(newCurrentTime / 1000, TimingUpdateOnDemand);
132 if (calculatePlayState() == Finished)
133 m_startTime = calculateStartTime(newCurrentTime);
136 void AnimationPlayer::setCurrentTimeInternal(double newCurrentTime, TimingUpdateReason reason)
138 ASSERT(std::isfinite(newCurrentTime));
140 bool oldHeld = m_held;
141 bool outdated = false;
142 bool isLimited = limited(newCurrentTime);
143 m_held = m_paused || !m_playbackRate || isLimited || std::isnan(m_startTime);
144 if (m_held) {
145 if (!oldHeld || m_holdTime != newCurrentTime)
146 outdated = true;
147 m_holdTime = newCurrentTime;
148 if (m_paused || !m_playbackRate) {
149 m_startTime = nullValue();
150 } else if (isLimited && std::isnan(m_startTime) && reason == TimingUpdateForAnimationFrame) {
151 m_startTime = calculateStartTime(newCurrentTime);
153 } else {
154 m_holdTime = nullValue();
155 m_startTime = calculateStartTime(newCurrentTime);
156 m_finished = false;
157 outdated = true;
160 if (outdated) {
161 setOutdated();
165 // Update timing to reflect updated animation clock due to tick
166 void AnimationPlayer::updateCurrentTimingState(TimingUpdateReason reason)
168 if (m_held) {
169 // Add hystersis due to floating point error accumulation
170 if (!isNull(m_startTime) && m_timeline && !limited(calculateCurrentTime() + 0.001 * m_playbackRate) && playStateInternal() == Finished) {
171 m_held = false;
172 setCurrentTimeInternal(calculateCurrentTime(), reason);
173 return;
175 setCurrentTimeInternal(m_holdTime, reason);
176 return;
178 if (!limited(calculateCurrentTime()))
179 return;
180 m_held = true;
181 m_holdTime = m_playbackRate < 0 ? 0 : sourceEnd();
184 double AnimationPlayer::startTime(bool& isNull) const
186 double result = startTime();
187 isNull = std::isnan(result);
188 return result;
191 double AnimationPlayer::startTime() const
193 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetStartTime);
194 return m_startTime * 1000;
197 double AnimationPlayer::currentTime(bool& isNull)
199 double result = currentTime();
200 isNull = std::isnan(result);
201 return result;
204 double AnimationPlayer::currentTime()
206 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
208 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetCurrentTime);
209 if (m_currentTimePending || playStateInternal() == Idle)
210 return std::numeric_limits<double>::quiet_NaN();
212 return currentTimeInternal() * 1000;
215 double AnimationPlayer::currentTimeInternal() const
217 double result = m_held ? m_holdTime : calculateCurrentTime();
218 #if ENABLE(ASSERT)
219 const_cast<AnimationPlayer*>(this)->updateCurrentTimingState(TimingUpdateOnDemand);
220 ASSERT(result == (m_held ? m_holdTime : calculateCurrentTime()));
221 #endif
222 return result;
225 void AnimationPlayer::preCommit(int compositorGroup, bool startOnCompositor)
227 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);
229 bool softChange = m_compositorState && (paused() || m_compositorState->playbackRate != m_playbackRate);
230 bool hardChange = m_compositorState && (m_compositorState->sourceChanged || m_compositorState->startTime != m_startTime);
232 // FIXME: softChange && !hardChange should generate a Pause/ThenStart,
233 // not a Cancel, but we can't communicate these to the compositor yet.
235 bool changed = softChange || hardChange;
236 bool shouldCancel = (!playing() && m_compositorState) || changed;
237 bool shouldStart = playing() && (!m_compositorState || changed);
239 if (shouldCancel) {
240 cancelAnimationOnCompositor();
241 m_compositorState = nullptr;
244 if (m_compositorState && m_compositorState->pendingAction == Start) {
245 // Still waiting for a start time.
246 return;
249 ASSERT(!m_compositorState || !std::isnan(m_compositorState->startTime));
251 if (!shouldStart) {
252 m_currentTimePending = false;
255 if (shouldStart) {
256 m_compositorGroup = compositorGroup;
257 if (startOnCompositor) {
258 if (maybeStartAnimationOnCompositor())
259 m_compositorState = adoptPtr(new CompositorState(*this));
260 else
261 cancelIncompatibleAnimationsOnCompositor();
266 void AnimationPlayer::postCommit(double timelineTime)
268 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);
270 m_compositorPending = false;
272 if (!m_compositorState || m_compositorState->pendingAction == None)
273 return;
275 switch (m_compositorState->pendingAction) {
276 case Start:
277 if (!std::isnan(m_compositorState->startTime)) {
278 ASSERT(m_startTime == m_compositorState->startTime);
279 m_compositorState->pendingAction = None;
281 break;
282 case Pause:
283 case PauseThenStart:
284 ASSERT(std::isnan(m_startTime));
285 m_compositorState->pendingAction = None;
286 setCurrentTimeInternal((timelineTime - m_compositorState->startTime) * m_playbackRate, TimingUpdateForAnimationFrame);
287 m_currentTimePending = false;
288 break;
289 default:
290 ASSERT_NOT_REACHED();
294 void AnimationPlayer::notifyCompositorStartTime(double timelineTime)
296 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, DoNotSetCompositorPending);
298 if (m_compositorState) {
299 ASSERT(m_compositorState->pendingAction == Start);
300 ASSERT(std::isnan(m_compositorState->startTime));
302 double initialCompositorHoldTime = m_compositorState->holdTime;
303 m_compositorState->pendingAction = None;
304 m_compositorState->startTime = timelineTime + currentTimeInternal() / -m_playbackRate;
306 if (m_startTime == timelineTime) {
307 // The start time was set to the incoming compositor start time.
308 // Unlikely, but possible.
309 // FIXME: Depending on what changed above this might still be pending.
310 // Maybe...
311 m_currentTimePending = false;
312 return;
315 if (!std::isnan(m_startTime) || currentTimeInternal() != initialCompositorHoldTime) {
316 // A new start time or current time was set while starting.
317 setCompositorPending(true);
318 return;
322 notifyStartTime(timelineTime);
325 void AnimationPlayer::notifyStartTime(double timelineTime)
327 if (playing()) {
328 ASSERT(std::isnan(m_startTime));
329 ASSERT(m_held);
331 if (m_playbackRate == 0) {
332 setStartTimeInternal(timelineTime);
333 } else {
334 setStartTimeInternal(timelineTime + currentTimeInternal() / -m_playbackRate);
337 // FIXME: This avoids marking this player as outdated needlessly when a start time
338 // is notified, but we should refactor how outdating works to avoid this.
339 m_outdated = false;
341 m_currentTimePending = false;
345 bool AnimationPlayer::affects(const Element& element, CSSPropertyID property) const
347 if (!m_content || !m_content->isAnimation())
348 return false;
350 const Animation* animation = toAnimation(m_content.get());
351 return (animation->target() == &element) && animation->affects(property);
354 double AnimationPlayer::calculateStartTime(double currentTime) const
356 return m_timeline->effectiveTime() - currentTime / m_playbackRate;
359 double AnimationPlayer::calculateCurrentTime() const
361 if (isNull(m_startTime) || !m_timeline)
362 return 0;
363 return (m_timeline->effectiveTime() - m_startTime) * m_playbackRate;
366 void AnimationPlayer::setStartTime(double startTime)
368 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
370 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetStartTime);
371 if (m_paused || playStateInternal() == Idle)
372 return;
373 if (startTime == m_startTime)
374 return;
376 m_currentTimePending = false;
377 setStartTimeInternal(startTime / 1000);
380 void AnimationPlayer::setStartTimeInternal(double newStartTime)
382 ASSERT(!m_paused);
383 ASSERT(std::isfinite(newStartTime));
384 ASSERT(newStartTime != m_startTime);
386 bool hadStartTime = hasStartTime();
387 double previousCurrentTime = currentTimeInternal();
388 m_startTime = newStartTime;
389 if (m_held && m_playbackRate) {
390 // If held, the start time would still be derrived from the hold time.
391 // Force a new, limited, current time.
392 m_held = false;
393 double currentTime = calculateCurrentTime();
394 if (m_playbackRate > 0 && currentTime > sourceEnd()) {
395 currentTime = sourceEnd();
396 } else if (m_playbackRate < 0 && currentTime < 0) {
397 currentTime = 0;
399 setCurrentTimeInternal(currentTime, TimingUpdateOnDemand);
401 updateCurrentTimingState(TimingUpdateOnDemand);
402 double newCurrentTime = currentTimeInternal();
404 if (previousCurrentTime != newCurrentTime) {
405 setOutdated();
406 } else if (!hadStartTime && m_timeline) {
407 // Even though this player is not outdated, time to effect change is
408 // infinity until start time is set.
409 m_timeline->wake();
413 void AnimationPlayer::setSource(AnimationNode* newSource)
415 if (m_content == newSource)
416 return;
418 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand, SetCompositorPendingWithSourceChanged);
420 double storedCurrentTime = currentTimeInternal();
421 if (m_content)
422 m_content->detach();
423 m_content = newSource;
424 if (newSource) {
425 // FIXME: This logic needs to be updated once groups are implemented
426 if (newSource->player()) {
427 newSource->player()->cancel();
428 newSource->player()->setSource(0);
430 newSource->attach(this);
431 setOutdated();
433 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand);
436 const char* AnimationPlayer::playStateString(AnimationPlayState playState)
438 switch (playState) {
439 case Idle:
440 return "idle";
441 case Pending:
442 return "pending";
443 case Running:
444 return "running";
445 case Paused:
446 return "paused";
447 case Finished:
448 return "finished";
449 default:
450 ASSERT_NOT_REACHED();
451 return "";
455 AnimationPlayer::AnimationPlayState AnimationPlayer::playStateInternal() const
457 return m_playState;
460 AnimationPlayer::AnimationPlayState AnimationPlayer::calculatePlayState()
462 if (m_playState == Idle)
463 return Idle;
464 if (m_currentTimePending || (isNull(m_startTime) && !m_paused && m_playbackRate != 0))
465 return Pending;
466 if (m_paused)
467 return Paused;
468 if (limited())
469 return Finished;
470 return Running;
473 void AnimationPlayer::pause()
475 if (m_paused)
476 return;
478 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
480 if (playing()) {
481 m_currentTimePending = true;
483 m_paused = true;
484 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand);
487 void AnimationPlayer::unpause()
489 if (!m_paused)
490 return;
492 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
494 m_currentTimePending = true;
495 unpauseInternal();
498 void AnimationPlayer::unpauseInternal()
500 if (!m_paused)
501 return;
502 m_paused = false;
503 setCurrentTimeInternal(currentTimeInternal(), TimingUpdateOnDemand);
506 void AnimationPlayer::play()
508 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
510 if (!playing())
511 m_startTime = nullValue();
513 if (playStateInternal() == Idle) {
514 // We may not go into the pending state, but setting it to something other
515 // than Idle here will force an update.
516 ASSERT(isNull(m_startTime));
517 m_playState = Pending;
518 m_held = true;
519 m_holdTime = 0;
522 m_finished = false;
523 unpauseInternal();
524 if (!m_content)
525 return;
526 double currentTime = this->currentTimeInternal();
527 if (m_playbackRate > 0 && (currentTime < 0 || currentTime >= sourceEnd()))
528 setCurrentTimeInternal(0, TimingUpdateOnDemand);
529 else if (m_playbackRate < 0 && (currentTime <= 0 || currentTime > sourceEnd()))
530 setCurrentTimeInternal(sourceEnd(), TimingUpdateOnDemand);
533 void AnimationPlayer::reverse()
535 if (!m_playbackRate) {
536 return;
539 setPlaybackRateInternal(-m_playbackRate);
540 play();
543 void AnimationPlayer::finish(ExceptionState& exceptionState)
545 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
547 if (!m_playbackRate || playStateInternal() == Idle) {
548 return;
550 if (m_playbackRate > 0 && sourceEnd() == std::numeric_limits<double>::infinity()) {
551 exceptionState.throwDOMException(InvalidStateError, "AnimationPlayer has source content whose end time is infinity.");
552 return;
555 double newCurrentTime = m_playbackRate < 0 ? 0 : sourceEnd();
556 setCurrentTimeInternal(newCurrentTime, TimingUpdateOnDemand);
557 if (!paused()) {
558 m_startTime = calculateStartTime(newCurrentTime);
561 m_currentTimePending = false;
562 ASSERT(playStateInternal() != Idle);
563 ASSERT(limited());
566 ScriptPromise AnimationPlayer::finished(ScriptState* scriptState)
568 if (!m_finishedPromise) {
569 m_finishedPromise = new AnimationPlayerPromise(scriptState->executionContext(), this, AnimationPlayerPromise::Finished);
570 if (playStateInternal() == Finished)
571 m_finishedPromise->resolve(this);
573 return m_finishedPromise->promise(scriptState->world());
576 ScriptPromise AnimationPlayer::ready(ScriptState* scriptState)
578 if (!m_readyPromise) {
579 m_readyPromise = new AnimationPlayerPromise(scriptState->executionContext(), this, AnimationPlayerPromise::Ready);
580 if (playStateInternal() != Pending)
581 m_readyPromise->resolve(this);
583 return m_readyPromise->promise(scriptState->world());
586 const AtomicString& AnimationPlayer::interfaceName() const
588 return EventTargetNames::AnimationPlayer;
591 ExecutionContext* AnimationPlayer::executionContext() const
593 return ActiveDOMObject::executionContext();
596 bool AnimationPlayer::hasPendingActivity() const
598 return m_pendingFinishedEvent || (!m_finished && hasEventListeners(EventTypeNames::finish));
601 void AnimationPlayer::stop()
603 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
605 m_finished = true;
606 m_pendingFinishedEvent = nullptr;
609 bool AnimationPlayer::dispatchEvent(PassRefPtrWillBeRawPtr<Event> event)
611 if (m_pendingFinishedEvent == event)
612 m_pendingFinishedEvent = nullptr;
613 return EventTargetWithInlineData::dispatchEvent(event);
616 double AnimationPlayer::playbackRate() const
618 UseCounter::count(executionContext(), UseCounter::AnimationPlayerGetPlaybackRate);
619 return m_playbackRate;
622 void AnimationPlayer::setPlaybackRate(double playbackRate)
624 UseCounter::count(executionContext(), UseCounter::AnimationPlayerSetPlaybackRate);
625 if (playbackRate == m_playbackRate)
626 return;
628 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
630 setPlaybackRateInternal(playbackRate);
633 void AnimationPlayer::setPlaybackRateInternal(double playbackRate)
635 ASSERT(std::isfinite(playbackRate));
636 ASSERT(playbackRate != m_playbackRate);
638 if (!limited() && !paused() && hasStartTime())
639 m_currentTimePending = true;
641 double storedCurrentTime = currentTimeInternal();
642 if ((m_playbackRate < 0 && playbackRate >= 0) || (m_playbackRate > 0 && playbackRate <= 0))
643 m_finished = false;
645 m_playbackRate = playbackRate;
646 m_startTime = std::numeric_limits<double>::quiet_NaN();
647 setCurrentTimeInternal(storedCurrentTime, TimingUpdateOnDemand);
650 void AnimationPlayer::setOutdated()
652 m_outdated = true;
653 if (m_timeline)
654 m_timeline->setOutdatedAnimationPlayer(this);
657 bool AnimationPlayer::canStartAnimationOnCompositor()
659 // FIXME: Timeline playback rates should be compositable
660 if (m_playbackRate == 0 || (std::isinf(sourceEnd()) && m_playbackRate < 0) || (timeline() && timeline()->playbackRate() != 1))
661 return false;
663 return m_timeline && m_content && m_content->isAnimation() && playing();
666 bool AnimationPlayer::maybeStartAnimationOnCompositor()
668 if (!canStartAnimationOnCompositor())
669 return false;
671 bool reversed = m_playbackRate < 0;
673 double startTime = timeline()->zeroTime() + startTimeInternal();
674 if (reversed) {
675 startTime -= sourceEnd() / fabs(m_playbackRate);
678 double timeOffset = 0;
679 if (std::isnan(startTime)) {
680 timeOffset = reversed ? sourceEnd() - currentTimeInternal() : currentTimeInternal();
681 timeOffset = timeOffset / fabs(m_playbackRate);
683 ASSERT(m_compositorGroup != 0);
684 return toAnimation(m_content.get())->maybeStartAnimationOnCompositor(m_compositorGroup, startTime, timeOffset, m_playbackRate);
687 void AnimationPlayer::setCompositorPending(bool sourceChanged)
689 // FIXME: Animation could notify this directly?
690 if (!hasActiveAnimationsOnCompositor()) {
691 m_compositorState.release();
693 if (sourceChanged && m_compositorState) {
694 m_compositorState->sourceChanged = true;
696 if (m_compositorPending || m_isPausedForTesting) {
697 return;
700 if (sourceChanged || !m_compositorState
701 || !playing() || m_compositorState->playbackRate != m_playbackRate
702 || m_compositorState->startTime != m_startTime) {
703 m_compositorPending = true;
704 timeline()->document()->compositorPendingAnimations().add(this);
708 void AnimationPlayer::cancelAnimationOnCompositor()
710 if (hasActiveAnimationsOnCompositor())
711 toAnimation(m_content.get())->cancelAnimationOnCompositor();
714 void AnimationPlayer::restartAnimationOnCompositor()
716 if (hasActiveAnimationsOnCompositor())
717 toAnimation(m_content.get())->restartAnimationOnCompositor();
720 void AnimationPlayer::cancelIncompatibleAnimationsOnCompositor()
722 if (m_content && m_content->isAnimation())
723 toAnimation(m_content.get())->cancelIncompatibleAnimationsOnCompositor();
726 bool AnimationPlayer::hasActiveAnimationsOnCompositor()
728 if (!m_content || !m_content->isAnimation())
729 return false;
731 return toAnimation(m_content.get())->hasActiveAnimationsOnCompositor();
734 bool AnimationPlayer::update(TimingUpdateReason reason)
736 if (!m_timeline)
737 return false;
739 PlayStateUpdateScope updateScope(*this, reason, DoNotSetCompositorPending);
741 m_outdated = false;
742 bool idle = playStateInternal() == Idle;
744 if (m_content) {
745 double inheritedTime = idle || isNull(m_timeline->currentTimeInternal()) ? nullValue() : currentTimeInternal();
746 // Special case for end-exclusivity when playing backwards.
747 if (inheritedTime == 0 && m_playbackRate < 0)
748 inheritedTime = -1;
749 m_content->updateInheritedTime(inheritedTime, reason);
752 if ((idle || limited()) && !m_finished) {
753 if (reason == TimingUpdateForAnimationFrame && (idle || hasStartTime())) {
754 const AtomicString& eventType = EventTypeNames::finish;
755 if (executionContext() && hasEventListeners(eventType)) {
756 double eventCurrentTime = currentTimeInternal() * 1000;
757 m_pendingFinishedEvent = AnimationPlayerEvent::create(eventType, eventCurrentTime, timeline()->currentTime());
758 m_pendingFinishedEvent->setTarget(this);
759 m_pendingFinishedEvent->setCurrentTarget(this);
760 m_timeline->document()->enqueueAnimationFrameEvent(m_pendingFinishedEvent);
762 m_finished = true;
765 ASSERT(!m_outdated);
766 return !m_finished;
769 double AnimationPlayer::timeToEffectChange()
771 ASSERT(!m_outdated);
772 if (m_held || !hasStartTime())
773 return std::numeric_limits<double>::infinity();
774 if (!m_content)
775 return -currentTimeInternal() / m_playbackRate;
776 double result = m_playbackRate > 0
777 ? m_content->timeToForwardsEffectChange() / m_playbackRate
778 : m_content->timeToReverseEffectChange() / -m_playbackRate;
779 return !hasActiveAnimationsOnCompositor() && m_content->phase() == AnimationNode::PhaseActive
781 : result;
784 void AnimationPlayer::cancel()
786 PlayStateUpdateScope updateScope(*this, TimingUpdateOnDemand);
788 if (playStateInternal() == Idle)
789 return;
791 m_holdTime = currentTimeInternal();
792 m_held = true;
793 // TODO
794 m_playState = Idle;
795 m_startTime = nullValue();
796 m_currentTimePending = false;
798 // after cancelation, transitions must be downgraded or they'll fail
799 // to be considered when retriggering themselves. This can happen if
800 // the transition is captured through getAnimationPlayers then played.
801 if (m_content && m_content->isAnimation())
802 toAnimation(m_content.get())->downgradeToNormalAnimation();
805 void AnimationPlayer::beginUpdatingState()
807 // Nested calls are not allowed!
808 ASSERT(!m_stateIsBeingUpdated);
809 m_stateIsBeingUpdated = true;
812 void AnimationPlayer::endUpdatingState()
814 ASSERT(m_stateIsBeingUpdated);
815 m_stateIsBeingUpdated = false;
818 AnimationPlayer::PlayStateUpdateScope::PlayStateUpdateScope(AnimationPlayer& player, TimingUpdateReason reason, CompositorPendingChange compositorPendingChange)
819 : m_player(player)
820 , m_initialPlayState(m_player->playStateInternal())
821 , m_compositorPendingChange(compositorPendingChange)
823 m_player->beginUpdatingState();
824 m_player->updateCurrentTimingState(reason);
827 AnimationPlayer::PlayStateUpdateScope::~PlayStateUpdateScope()
829 AnimationPlayState oldPlayState = m_initialPlayState;
830 AnimationPlayState newPlayState = m_player->calculatePlayState();
832 m_player->m_playState = newPlayState;
833 if (oldPlayState != newPlayState) {
834 bool wasActive = oldPlayState == Pending || oldPlayState == Running;
835 bool isActive = newPlayState == Pending || newPlayState == Running;
836 if (!wasActive && isActive)
837 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("blink.animations," TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Animation", m_player, "data", InspectorAnimationEvent::data(*m_player));
838 else if (wasActive && !isActive)
839 TRACE_EVENT_NESTABLE_ASYNC_END1("blink.animations," TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Animation", m_player, "endData", InspectorAnimationStateEvent::data(*m_player));
840 else
841 TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("blink.animations," TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Animation", m_player, "data", InspectorAnimationStateEvent::data(*m_player));
844 // Ordering is important, the ready promise should resolve/reject before
845 // the finished promise.
846 if (m_player->m_readyPromise && newPlayState != oldPlayState) {
847 if (newPlayState == Idle) {
848 if (m_player->m_readyPromise->state() == AnimationPlayerPromise::Pending) {
849 m_player->m_readyPromise->reject(DOMException::create(AbortError));
851 m_player->m_readyPromise->reset();
852 m_player->m_readyPromise->resolve(m_player);
853 } else if (oldPlayState == Pending) {
854 m_player->m_readyPromise->resolve(m_player);
855 } else if (newPlayState == Pending) {
856 ASSERT(m_player->m_readyPromise->state() != AnimationPlayerPromise::Pending);
857 m_player->m_readyPromise->reset();
861 if (m_player->m_finishedPromise && newPlayState != oldPlayState) {
862 if (newPlayState == Idle) {
863 if (m_player->m_finishedPromise->state() == AnimationPlayerPromise::Pending) {
864 m_player->m_finishedPromise->reject(DOMException::create(AbortError));
866 m_player->m_finishedPromise->reset();
867 } else if (newPlayState == Finished) {
868 m_player->m_finishedPromise->resolve(m_player);
869 } else if (oldPlayState == Finished) {
870 m_player->m_finishedPromise->reset();
874 if (oldPlayState != newPlayState && (oldPlayState == Idle || newPlayState == Idle)) {
875 m_player->setOutdated();
878 #if ENABLE(ASSERT)
879 // Verify that current time is up to date.
880 m_player->currentTimeInternal();
881 #endif
883 switch (m_compositorPendingChange) {
884 case SetCompositorPending:
885 m_player->setCompositorPending();
886 break;
887 case SetCompositorPendingWithSourceChanged:
888 m_player->setCompositorPending(true);
889 break;
890 case DoNotSetCompositorPending:
891 break;
892 default:
893 ASSERT_NOT_REACHED();
894 break;
896 m_player->endUpdatingState();
898 if (oldPlayState != newPlayState && newPlayState == Running)
899 InspectorInstrumentation::didCreateAnimationPlayer(m_player->timeline()->document(), *m_player);
903 #if !ENABLE(OILPAN)
904 bool AnimationPlayer::canFree() const
906 ASSERT(m_content);
907 return hasOneRef() && m_content->isAnimation() && m_content->hasOneRef();
909 #endif
911 bool AnimationPlayer::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
913 if (eventType == EventTypeNames::finish)
914 UseCounter::count(executionContext(), UseCounter::AnimationPlayerFinishEvent);
915 return EventTargetWithInlineData::addEventListener(eventType, listener, useCapture);
918 void AnimationPlayer::pauseForTesting(double pauseTime)
920 RELEASE_ASSERT(!paused());
921 setCurrentTimeInternal(pauseTime, TimingUpdateOnDemand);
922 if (hasActiveAnimationsOnCompositor())
923 toAnimation(m_content.get())->pauseAnimationForTestingOnCompositor(currentTimeInternal());
924 m_isPausedForTesting = true;
925 pause();
928 DEFINE_TRACE(AnimationPlayer)
930 visitor->trace(m_content);
931 visitor->trace(m_timeline);
932 visitor->trace(m_pendingFinishedEvent);
933 visitor->trace(m_finishedPromise);
934 visitor->trace(m_readyPromise);
935 EventTargetWithInlineData::trace(visitor);
936 ActiveDOMObject::trace(visitor);
939 } // namespace