Bug 927349 part 5 - Cancel players that are no longer used; r=jwatt

This patch adds a means of terminating an animation so that is has no effect.
The procedure is defined by Web Animations:

  http://w3c.github.io/web-animations/#cancelling-a-player-section

We don't implement all of this, however, since we don't currently support the
finished promise or custom effects.

In a later bug we will expose this as the cancel() method on AnimationPlayer.

We call this method for terminated animations in nsAnimationManager and
nsTransitionManager to ensure they get removed from the pending player tracker
and so that, for example, the ready promise of CSS Animation player objects is
rejected when the corresponding item is removed from animation-name.
This commit is contained in:
Brian Birtles 2014-12-18 08:42:41 +09:00
parent e6457d3ab6
commit c59d2a6a21
5 changed files with 48 additions and 11 deletions

View File

@ -160,6 +160,20 @@ AnimationPlayer::ResolveStartTime()
}
}
void
AnimationPlayer::Cancel()
{
if (mIsPending) {
CancelPendingPlay();
if (mReady) {
mReady->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
}
mHoldTime.SetNull();
mStartTime.SetNull();
}
bool
AnimationPlayer::IsRunning() const
{
@ -240,18 +254,8 @@ AnimationPlayer::DoPlay()
void
AnimationPlayer::DoPause()
{
// Cancel a pending play
if (mIsPending) {
nsIDocument* doc = GetRenderedDocument();
if (doc) {
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
if (tracker) {
tracker->RemovePlayPending(*this);
}
}
mIsPending = false;
CancelPendingPlay();
// Resolve the ready promise since we currently only use it for
// players that are waiting to play. Later (in bug 1109390), we will
// use this for players waiting to pause as well and then we won't
@ -289,6 +293,24 @@ AnimationPlayer::PostUpdate()
}
}
void
AnimationPlayer::CancelPendingPlay()
{
if (!mIsPending) {
return;
}
nsIDocument* doc = GetRenderedDocument();
if (doc) {
PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
if (tracker) {
tracker->RemovePlayPending(*this);
}
}
mIsPending = false;
}
StickyTimeDuration
AnimationPlayer::SourceContentEnd() const
{

View File

@ -92,6 +92,7 @@ public:
// This should only be called on a player that is currently waiting to play
// (and therefore has a null start time but a fixed hold time).
void ResolveStartTime();
void Cancel();
const nsString& Name() const {
return mSource ? mSource->Name() : EmptyString();
@ -132,6 +133,10 @@ protected:
void FlushStyle() const;
void PostUpdate();
// Remove this player from the pending player tracker and resets mIsPending
// as necessary. The caller is responsible for resolving or aborting the
// mReady promise as necessary.
void CancelPendingPlay();
StickyTimeDuration SourceContentEnd() const;
nsIDocument* GetRenderedDocument() const;

View File

@ -234,6 +234,9 @@ struct AnimationPlayerCollection : public PRCList
void Destroy()
{
for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) {
mPlayers[playerIdx]->Cancel();
}
// This will call our destructor.
mElement->DeleteProperty(mElementProperty);
}

View File

@ -331,6 +331,7 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
// Although we're doing this while iterating this is safe because
// we're not changing the length of newPlayers and we've finished
// iterating over the list of old iterations.
newPlayer->Cancel();
newPlayer = nullptr;
newPlayers.ReplaceElementAt(newIdx, oldPlayer);
collection->mPlayers.RemoveElementAt(oldIdx);
@ -344,6 +345,11 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
collection->mNeedsRefreshes = true;
collection->Tick();
// Cancel removed animations
for (size_t newPlayerIdx = newPlayers.Length(); newPlayerIdx-- != 0; ) {
newPlayers[newPlayerIdx]->Cancel();
}
TimeStamp refreshTime = mPresContext->RefreshDriver()->MostRecentRefresh();
UpdateStyleAndEvents(collection, refreshTime,
EnsureStyleRule_IsNotThrottled);

View File

@ -300,6 +300,7 @@ nsTransitionManager::StyleContextChanged(dom::Element *aElement,
currentValue) ||
currentValue != segment.mToValue) {
// stop the transition
player->Cancel();
players.RemoveElementAt(i);
collection->UpdateAnimationGeneration(mPresContext);
}