/*
 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "CSSAnimationController.h"

#include "AnimationBase.h"
#include "AnimationEvent.h"
#include "CSSAnimationControllerPrivate.h"
#include "CSSPropertyAnimation.h"
#include "CSSPropertyParser.h"
#include "CompositeAnimation.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameView.h"
#include "Logging.h"
#include "PseudoElement.h"
#include "RenderView.h"
#include "TransitionEvent.h"
#include "WebKitAnimationEvent.h"
#include "WebKitTransitionEvent.h"

namespace WebCore {

// Allow a little more than 60fps to make sure we can at least hit that frame rate.
static const Seconds animationTimerDelay { 15_ms };
// Allow a little more than 30fps to make sure we can at least hit that frame rate.
static const Seconds animationTimerThrottledDelay { 30_ms };

class AnimationPrivateUpdateBlock {
public:
    AnimationPrivateUpdateBlock(CSSAnimationControllerPrivate& animationController)
        : m_animationController(animationController)
    {
        m_animationController.beginAnimationUpdate();
    }
    
    ~AnimationPrivateUpdateBlock()
    {
        m_animationController.endAnimationUpdate();
    }
    
    CSSAnimationControllerPrivate& m_animationController;
};

CSSAnimationControllerPrivate::CSSAnimationControllerPrivate(Frame& frame)
    : m_animationTimer(*this, &CSSAnimationControllerPrivate::animationTimerFired)
    , m_updateStyleIfNeededDispatcher(*this, &CSSAnimationControllerPrivate::updateStyleIfNeededDispatcherFired)
    , m_frame(frame)
    , m_beginAnimationUpdateCount(0)
    , m_waitingForAsyncStartNotification(false)
    , m_allowsNewAnimationsWhileSuspended(false)
{
}

CSSAnimationControllerPrivate::~CSSAnimationControllerPrivate() = default;

CompositeAnimation& CSSAnimationControllerPrivate::ensureCompositeAnimation(Element& element)
{
    element.setHasCSSAnimation();

    auto result = m_compositeAnimations.ensure(&element, [&] {
        return CompositeAnimation::create(*this);
    });

    if (animationsAreSuspendedForDocument(&element.document()))
        result.iterator->value->suspendAnimations();

    return *result.iterator->value;
}

bool CSSAnimationControllerPrivate::clear(Element& element)
{
    ASSERT(element.hasCSSAnimation() == m_compositeAnimations.contains(&element));

    if (!element.hasCSSAnimation())
        return false;
    element.clearHasCSSAnimation();

    auto it = m_compositeAnimations.find(&element);
    if (it == m_compositeAnimations.end())
        return false;

    LOG(Animations, "CSSAnimationControllerPrivate %p clear: %p", this, &element);

    m_eventsToDispatch.removeAllMatching([&] (const EventToDispatch& info) {
        return info.element.ptr() == &element;
    });

    m_elementChangesToDispatch.removeAllMatching([&](auto& currentElement) {
        return currentElement.ptr() == &element;
    });
    
    // Return false if we didn't do anything OR we are suspended (so we don't try to
    // do a invalidateStyleForSubtree() when suspended).
    // FIXME: The code below does the opposite of what the comment above says regarding suspended state.
    auto& animation = *it->value;
    bool result = animation.isSuspended();
    animation.clearElement();

    m_compositeAnimations.remove(it);

    return result;
}

Optional<Seconds> CSSAnimationControllerPrivate::updateAnimations(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
{
    AnimationPrivateUpdateBlock updateBlock(*this);
    Optional<Seconds> timeToNextService;
    bool calledSetChanged = false;

    for (auto& compositeAnimation : m_compositeAnimations) {
        CompositeAnimation& animation = *compositeAnimation.value;
        if (!animation.isSuspended() && animation.hasAnimations()) {
            Optional<Seconds> t = animation.timeToNextService();
            if (t && (!timeToNextService || t.value() < timeToNextService.value()))
                timeToNextService = t.value();
            if (timeToNextService && timeToNextService.value() == 0_s) {
                if (callSetChanged != CallSetChanged)
                    break;
                
                Element& element = *compositeAnimation.key;
                ASSERT(element.document().pageCacheState() == Document::NotInPageCache);
                element.invalidateStyle();
                calledSetChanged = true;
            }
        }
    }

    if (calledSetChanged)
        m_frame.document()->updateStyleIfNeeded();

    return timeToNextService;
}

void CSSAnimationControllerPrivate::updateAnimationTimerForElement(Element& element)
{
    Optional<Seconds> timeToNextService;

    const CompositeAnimation* compositeAnimation = m_compositeAnimations.get(&element);
    if (!compositeAnimation->isSuspended() && compositeAnimation->hasAnimations())
        timeToNextService = compositeAnimation->timeToNextService();

    if (!timeToNextService)
        return;

    if (m_animationTimer.isActive() && (m_animationTimer.repeatInterval() || m_animationTimer.nextFireInterval() <= timeToNextService.value()))
        return;

    m_animationTimer.startOneShot(timeToNextService.value());
}

void CSSAnimationControllerPrivate::updateAnimationTimer(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
{
    Optional<Seconds> timeToNextService = updateAnimations(callSetChanged);

    LOG(Animations, "updateAnimationTimer: timeToNextService is %.2f", timeToNextService.valueOr(Seconds { -1 }).value());

    // If we don't need service, we want to make sure the timer is no longer running
    if (!timeToNextService) {
        if (m_animationTimer.isActive())
            m_animationTimer.stop();
        return;
    }

    // If we want service immediately, we start a repeating timer to reduce the overhead of starting
    if (!timeToNextService.value()) {
        auto* page = m_frame.page();
        bool shouldThrottle = page && page->isLowPowerModeEnabled();
        Seconds delay = shouldThrottle ? animationTimerThrottledDelay : animationTimerDelay;

        if (!m_animationTimer.isActive() || m_animationTimer.repeatInterval() != delay)
            m_animationTimer.startRepeating(delay);
        return;
    }

    // Otherwise, we want to start a one-shot timer so we get here again
    m_animationTimer.startOneShot(timeToNextService.value());
}

void CSSAnimationControllerPrivate::updateStyleIfNeededDispatcherFired()
{
    fireEventsAndUpdateStyle();
}

void CSSAnimationControllerPrivate::fireEventsAndUpdateStyle()
{
    // Protect the frame from getting destroyed in the event handler
    Ref<Frame> protector(m_frame);

    bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_elementChangesToDispatch.isEmpty();

    // fire all the events
    Vector<EventToDispatch> eventsToDispatch = WTFMove(m_eventsToDispatch);
    for (auto& event : eventsToDispatch) {
        Element& element = event.element;
        if (event.eventType == eventNames().transitionendEvent)
            element.dispatchEvent(TransitionEvent::create(event.eventType, event.name, event.elapsedTime, PseudoElement::pseudoElementNameForEvents(element.pseudoId())));
        else
            element.dispatchEvent(AnimationEvent::create(event.eventType, event.name, event.elapsedTime));
    }

    for (auto& change : m_elementChangesToDispatch)
        change->invalidateStyle();

    m_elementChangesToDispatch.clear();

    if (updateStyle)
        m_frame.document()->updateStyleIfNeeded();
}

void CSSAnimationControllerPrivate::startUpdateStyleIfNeededDispatcher()
{
    if (!m_updateStyleIfNeededDispatcher.isActive())
        m_updateStyleIfNeededDispatcher.startOneShot(0_s);
}

void CSSAnimationControllerPrivate::addEventToDispatch(Element& element, const AtomicString& eventType, const String& name, double elapsedTime)
{
    m_eventsToDispatch.append({ element, eventType, name, elapsedTime });
    startUpdateStyleIfNeededDispatcher();
}

void CSSAnimationControllerPrivate::addElementChangeToDispatch(Element& element)
{
    m_elementChangesToDispatch.append(element);
    ASSERT(m_elementChangesToDispatch.last()->document().pageCacheState() == Document::NotInPageCache);
    startUpdateStyleIfNeededDispatcher();
}

void CSSAnimationControllerPrivate::animationFrameCallbackFired()
{
    Optional<Seconds> timeToNextService = updateAnimations(CallSetChanged);

    if (timeToNextService)
        m_frame.document()->view()->scheduleAnimation();
}

void CSSAnimationControllerPrivate::animationTimerFired()
{
    // We need to keep the frame alive, since it owns us.
    Ref<Frame> protector(m_frame);

    // The animation timer might fire before the layout timer, in
    // which case we might create some animations with incorrect
    // values if we don't layout first.
    if (m_requiresLayout) {
        if (auto* frameView = m_frame.document()->view()) {
            if (frameView->needsLayout())
                frameView->forceLayout();
        }
        m_requiresLayout = false;
    }

    // Make sure animationUpdateTime is updated, so that it is current even if no
    // styleChange has happened (e.g. accelerated animations)
    AnimationPrivateUpdateBlock updateBlock(*this);

    // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
    // updateStyleIfNeeded. It will then call back to us with new information.
    updateAnimationTimer(CallSetChanged);

    // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before
    // the 'end' event fires.
    fireEventsAndUpdateStyle();
}

bool CSSAnimationControllerPrivate::isRunningAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property) const
{
    if (!renderer.element())
        return false;
    auto* animation = m_compositeAnimations.get(renderer.element());
    if (!animation)
        return false;
    return animation->isAnimatingProperty(property, false);
}

bool CSSAnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property) const
{
    if (!renderer.element())
        return false;
    auto* animation = m_compositeAnimations.get(renderer.element());
    if (!animation)
        return false;
    return animation->isAnimatingProperty(property, true);
}

void CSSAnimationControllerPrivate::updateThrottlingState()
{
    updateAnimationTimer();

    for (auto* childFrame = m_frame.tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling())
        childFrame->animation().updateThrottlingState();
}

Seconds CSSAnimationControllerPrivate::animationInterval() const
{
    if (!m_animationTimer.isActive())
        return Seconds { INFINITY };

    return Seconds { m_animationTimer.repeatInterval() };
}

void CSSAnimationControllerPrivate::suspendAnimations()
{
    if (isSuspended())
        return;

    suspendAnimationsForDocument(m_frame.document());

    // Traverse subframes
    for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
        child->animation().suspendAnimations();

    m_isSuspended = true;
}

void CSSAnimationControllerPrivate::resumeAnimations()
{
    if (!isSuspended())
        return;

    resumeAnimationsForDocument(m_frame.document());

    // Traverse subframes
    for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
        child->animation().resumeAnimations();

    m_isSuspended = false;
}

bool CSSAnimationControllerPrivate::animationsAreSuspendedForDocument(Document* document)
{
    return isSuspended() || m_suspendedDocuments.contains(document);
}

void CSSAnimationControllerPrivate::detachFromDocument(Document* document)
{
    m_suspendedDocuments.remove(document);
}

void CSSAnimationControllerPrivate::suspendAnimationsForDocument(Document* document)
{
    if (animationsAreSuspendedForDocument(document))
        return;

    m_suspendedDocuments.add(document);

    AnimationPrivateUpdateBlock updateBlock(*this);

    for (auto& animation : m_compositeAnimations) {
        if (&animation.key->document() == document)
            animation.value->suspendAnimations();
    }

    updateAnimationTimer();
}

void CSSAnimationControllerPrivate::resumeAnimationsForDocument(Document* document)
{
    if (!animationsAreSuspendedForDocument(document))
        return;

    detachFromDocument(document);

    AnimationPrivateUpdateBlock updateBlock(*this);

    for (auto& animation : m_compositeAnimations) {
        if (&animation.key->document() == document)
            animation.value->resumeAnimations();
    }

    updateAnimationTimer();
}

void CSSAnimationControllerPrivate::startAnimationsIfNotSuspended(Document* document)
{
    if (!animationsAreSuspendedForDocument(document) || allowsNewAnimationsWhileSuspended())
        resumeAnimationsForDocument(document);
}

void CSSAnimationControllerPrivate::setAllowsNewAnimationsWhileSuspended(bool allowed)
{
    m_allowsNewAnimationsWhileSuspended = allowed;
}

bool CSSAnimationControllerPrivate::pauseAnimationAtTime(Element& element, const AtomicString& name, double t)
{
    CompositeAnimation& compositeAnimation = ensureCompositeAnimation(element);
    if (compositeAnimation.pauseAnimationAtTime(name, t)) {
        element.invalidateStyle();
        startUpdateStyleIfNeededDispatcher();
        return true;
    }

    return false;
}

bool CSSAnimationControllerPrivate::pauseTransitionAtTime(Element& element, const String& property, double t)
{
    CompositeAnimation& compositeAnimation = ensureCompositeAnimation(element);
    if (compositeAnimation.pauseTransitionAtTime(cssPropertyID(property), t)) {
        element.invalidateStyle();
        startUpdateStyleIfNeededDispatcher();
        return true;
    }

    return false;
}

MonotonicTime CSSAnimationControllerPrivate::beginAnimationUpdateTime()
{
    ASSERT(m_beginAnimationUpdateCount);
    if (!m_beginAnimationUpdateTime)
        m_beginAnimationUpdateTime = MonotonicTime::now();

    return m_beginAnimationUpdateTime.value();
}

void CSSAnimationControllerPrivate::beginAnimationUpdate()
{
    if (!m_beginAnimationUpdateCount)
        m_beginAnimationUpdateTime = WTF::nullopt;
    ++m_beginAnimationUpdateCount;
}

void CSSAnimationControllerPrivate::endAnimationUpdate()
{
    ASSERT(m_beginAnimationUpdateCount > 0);
    if (m_beginAnimationUpdateCount == 1) {
        styleAvailable();
        if (!m_waitingForAsyncStartNotification)
            startTimeResponse(beginAnimationUpdateTime());
    }
    --m_beginAnimationUpdateCount;
}

void CSSAnimationControllerPrivate::receivedStartTimeResponse(MonotonicTime time)
{
    LOG(Animations, "CSSAnimationControllerPrivate %p receivedStartTimeResponse %f", this, time.secondsSinceEpoch().seconds());

    m_waitingForAsyncStartNotification = false;
    startTimeResponse(time);
}

std::unique_ptr<RenderStyle> CSSAnimationControllerPrivate::animatedStyleForElement(Element& element)
{
    auto* animation = m_compositeAnimations.get(&element);
    if (!animation)
        return nullptr;

    AnimationPrivateUpdateBlock animationUpdateBlock(*this);

    auto animatingStyle = animation->getAnimatedStyle();
    if (!animatingStyle)
        return nullptr;
    
    return animatingStyle;
}

bool CSSAnimationControllerPrivate::computeExtentOfAnimation(Element& element, LayoutRect& bounds) const
{
    auto* animation = m_compositeAnimations.get(&element);
    if (!animation)
        return true;

    if (!animation->isAnimatingProperty(CSSPropertyTransform, false))
        return true;

    return animation->computeExtentOfTransformAnimation(bounds);
}

unsigned CSSAnimationControllerPrivate::numberOfActiveAnimations(Document* document) const
{
    unsigned count = 0;
    
    for (auto& animation : m_compositeAnimations) {
        if (&animation.key->document() == document)
            count += animation.value->numberOfActiveAnimations();
    }

    return count;
}

void CSSAnimationControllerPrivate::addToAnimationsWaitingForStyle(AnimationBase& animation)
{
    m_animationsWaitingForStartTimeResponse.remove(&animation);
    m_animationsWaitingForStyle.add(&animation);
}

void CSSAnimationControllerPrivate::removeFromAnimationsWaitingForStyle(AnimationBase& animationToRemove)
{
    m_animationsWaitingForStyle.remove(&animationToRemove);
}

void CSSAnimationControllerPrivate::styleAvailable()
{
    // Go through list of waiters and send them on their way
    for (const auto& waitingAnimation : m_animationsWaitingForStyle)
        waitingAnimation->styleAvailable();

    m_animationsWaitingForStyle.clear();
}

void CSSAnimationControllerPrivate::addToAnimationsWaitingForStartTimeResponse(AnimationBase& animation, bool willGetResponse)
{
    // If willGetResponse is true, it means this animation is actually waiting for a response
    // (which will come in as a call to notifyAnimationStarted()).
    // In that case we don't need to add it to this list. We just set a waitingForAResponse flag 
    // which says we are waiting for the response. If willGetResponse is false, this animation 
    // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for 
    // another animation to which it will sync.
    //
    // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is
    // true. If so, we just return and will do our work when the first notifyXXXStarted() call
    // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will
    // do our work right away. In both cases we call the onAnimationStartResponse() method
    // on each animation. In the first case we send in the time we got from notifyXXXStarted().
    // In the second case, we just pass in the beginAnimationUpdateTime().
    //
    // This will synchronize all software and accelerated animations started in the same 
    // updateStyleIfNeeded cycle.
    //

    if (willGetResponse)
        m_waitingForAsyncStartNotification = true;

    m_animationsWaitingForStartTimeResponse.add(&animation);
}

void CSSAnimationControllerPrivate::removeFromAnimationsWaitingForStartTimeResponse(AnimationBase& animationToRemove)
{
    m_animationsWaitingForStartTimeResponse.remove(&animationToRemove);
    if (m_animationsWaitingForStartTimeResponse.isEmpty())
        m_waitingForAsyncStartNotification = false;
}

void CSSAnimationControllerPrivate::startTimeResponse(MonotonicTime time)
{
    // Go through list of waiters and send them on their way

    for (const auto& animation : m_animationsWaitingForStartTimeResponse)
        animation->onAnimationStartResponse(time);
    
    m_animationsWaitingForStartTimeResponse.clear();
    m_waitingForAsyncStartNotification = false;
}

void CSSAnimationControllerPrivate::animationWillBeRemoved(AnimationBase& animation)
{
    LOG(Animations, "CSSAnimationControllerPrivate %p animationWillBeRemoved: %p", this, &animation);

    removeFromAnimationsWaitingForStyle(animation);
    removeFromAnimationsWaitingForStartTimeResponse(animation);

    bool anyAnimationsWaitingForAsyncStart = false;
    for (auto& animation : m_animationsWaitingForStartTimeResponse) {
        if (animation->waitingForStartTime() && animation->isAccelerated()) {
            anyAnimationsWaitingForAsyncStart = true;
            break;
        }
    }

    if (!anyAnimationsWaitingForAsyncStart)
        m_waitingForAsyncStartNotification = false;
}

CSSAnimationController::CSSAnimationController(Frame& frame)
    : m_data(std::make_unique<CSSAnimationControllerPrivate>(frame))
{
}

CSSAnimationController::~CSSAnimationController() = default;

void CSSAnimationController::cancelAnimations(Element& element)
{
    if (!m_data->clear(element))
        return;

    if (element.document().renderTreeBeingDestroyed())
        return;
    ASSERT(element.document().pageCacheState() == Document::NotInPageCache);
    element.invalidateStyle();
}

AnimationUpdate CSSAnimationController::updateAnimations(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle)
{
    bool hasOrHadAnimations = (oldStyle && oldStyle->hasAnimationsOrTransitions()) || newStyle.hasAnimationsOrTransitions();
    if (!hasOrHadAnimations)
        return { };

    if (element.document().pageCacheState() != Document::NotInPageCache)
        return { };

    // Don't run transitions when printing.
    if (element.document().renderView()->printing())
        return { };

    // Fetch our current set of implicit animations from a hashtable. We then compare them
    // against the animations in the style and make sure we're in sync. If destination values
    // have changed, we reset the animation. We then do a blend to get new values and we return
    // a new style.

    CompositeAnimation& compositeAnimation = m_data->ensureCompositeAnimation(element);
    auto update = compositeAnimation.animate(element, oldStyle, newStyle);

    auto* renderer = element.renderer();
    if ((renderer && renderer->parent()) || newStyle.animations() || (oldStyle && oldStyle->animations())) {
        auto& frameView = *element.document().view();
        if (compositeAnimation.hasAnimationThatDependsOnLayout())
            m_data->setRequiresLayout();
        m_data->updateAnimationTimerForElement(element);
        frameView.scheduleAnimation();
    }

    return update;
}

std::unique_ptr<RenderStyle> CSSAnimationController::animatedStyleForRenderer(RenderElement& renderer)
{
    std::unique_ptr<RenderStyle> result;

    if (renderer.style().hasAnimationsOrTransitions() && renderer.element())
        result = m_data->animatedStyleForElement(*renderer.element());

    if (!result)
        result = RenderStyle::clonePtr(renderer.style());

    return result;
}

bool CSSAnimationController::computeExtentOfAnimation(RenderElement& renderer, LayoutRect& bounds) const
{
    if (!renderer.element())
        return true;
    if (!renderer.style().hasAnimationsOrTransitions())
        return true;

    return m_data->computeExtentOfAnimation(*renderer.element(), bounds);
}

void CSSAnimationController::notifyAnimationStarted(RenderElement& renderer, MonotonicTime startTime)
{
    LOG(Animations, "CSSAnimationController %p notifyAnimationStarted on renderer %p, time=%f", this, &renderer, startTime.secondsSinceEpoch().seconds());
    UNUSED_PARAM(renderer);

    AnimationUpdateBlock animationUpdateBlock(this);
    m_data->receivedStartTimeResponse(startTime);
}

bool CSSAnimationController::pauseAnimationAtTime(Element& element, const AtomicString& name, double t)
{
    AnimationUpdateBlock animationUpdateBlock(this);
    return m_data->pauseAnimationAtTime(element, name, t);
}

unsigned CSSAnimationController::numberOfActiveAnimations(Document* document) const
{
    return m_data->numberOfActiveAnimations(document);
}

bool CSSAnimationController::pauseTransitionAtTime(Element& element, const String& property, double t)
{
    AnimationUpdateBlock animationUpdateBlock(this);
    return m_data->pauseTransitionAtTime(element, property, t);
}

bool CSSAnimationController::isRunningAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property) const
{
    if (!renderer.style().hasAnimationsOrTransitions())
        return false;
    return m_data->isRunningAnimationOnRenderer(renderer, property);
}

bool CSSAnimationController::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property) const
{
    if (!renderer.style().hasAnimationsOrTransitions())
        return false;
    return m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property);
}

bool CSSAnimationController::isSuspended() const
{
    return m_data->isSuspended();
}

void CSSAnimationController::suspendAnimations()
{
    LOG(Animations, "controller is suspending animations");
    m_data->suspendAnimations();
}

void CSSAnimationController::resumeAnimations()
{
    LOG(Animations, "controller is resuming animations");
    m_data->resumeAnimations();
}

bool CSSAnimationController::allowsNewAnimationsWhileSuspended() const
{
    return m_data->allowsNewAnimationsWhileSuspended();
}

void CSSAnimationController::setAllowsNewAnimationsWhileSuspended(bool allowed)
{
    m_data->setAllowsNewAnimationsWhileSuspended(allowed);
}

void CSSAnimationController::serviceAnimations()
{
    m_data->animationFrameCallbackFired();
}

void CSSAnimationController::updateThrottlingState()
{
    m_data->updateThrottlingState();
}

Seconds CSSAnimationController::animationInterval() const
{
    return m_data->animationInterval();
}

bool CSSAnimationController::animationsAreSuspendedForDocument(Document* document)
{
    return m_data->animationsAreSuspendedForDocument(document);
}

void CSSAnimationController::detachFromDocument(Document* document)
{
    return m_data->detachFromDocument(document);
}

void CSSAnimationController::suspendAnimationsForDocument(Document* document)
{
    LOG(Animations, "suspending animations for document %p", document);
    m_data->suspendAnimationsForDocument(document);
}

void CSSAnimationController::resumeAnimationsForDocument(Document* document)
{
    LOG(Animations, "resuming animations for document %p", document);
    AnimationUpdateBlock animationUpdateBlock(this);
    m_data->resumeAnimationsForDocument(document);
}

void CSSAnimationController::startAnimationsIfNotSuspended(Document* document)
{
    LOG(Animations, "animations may start for document %p", document);

    AnimationUpdateBlock animationUpdateBlock(this);
    m_data->startAnimationsIfNotSuspended(document);
}

void CSSAnimationController::beginAnimationUpdate()
{
    m_data->beginAnimationUpdate();
}

void CSSAnimationController::endAnimationUpdate()
{
    m_data->endAnimationUpdate();
}

bool CSSAnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
{
    return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property);
}

bool CSSAnimationController::hasAnimations() const
{
    return m_data->hasAnimations();
}

} // namespace WebCore
