/* * Copyright (C) 2017-2018 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. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR * 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. */ #pragma once #include "ActiveDOMObject.h" #include "EventTarget.h" #include "ExceptionOr.h" #include "IDLTypes.h" #include "Styleable.h" #include "WebAnimationTypes.h" #include #include #include #include #include #include namespace WebCore { class AnimationEffect; class AnimationEventBase; class AnimationTimeline; class Document; class RenderStyle; template class DOMPromiseProxyWithResolveCallback; class WebAnimation : public RefCounted, public EventTargetWithInlineData, public ActiveDOMObject { WTF_MAKE_ISO_ALLOCATED(WebAnimation); public: static Ref create(Document&, AnimationEffect*); static Ref create(Document&, AnimationEffect*, AnimationTimeline*); ~WebAnimation(); WEBCORE_EXPORT static HashSet& instances(); virtual bool isDeclarativeAnimation() const { return false; } virtual bool isCSSAnimation() const { return false; } virtual bool isCSSTransition() const { return false; } const String& id() const { return m_id; } void setId(const String&); AnimationEffect* bindingsEffect() const { return effect(); } virtual void setBindingsEffect(RefPtr&&); AnimationEffect* effect() const { return m_effect.get(); } void setEffect(RefPtr&&); AnimationTimeline* timeline() const { return m_timeline.get(); } virtual void setTimeline(RefPtr&&); std::optional currentTime(std::optional = std::nullopt) const; ExceptionOr setCurrentTime(std::optional); double playbackRate() const { return m_playbackRate + 0; } void setPlaybackRate(double); enum class PlayState : uint8_t { Idle, Running, Paused, Finished }; PlayState playState() const; enum class ReplaceState : uint8_t { Active, Removed, Persisted }; ReplaceState replaceState() const { return m_replaceState; } void setReplaceState(ReplaceState replaceState) { m_replaceState = replaceState; } bool pending() const { return hasPendingPauseTask() || hasPendingPlayTask(); } using ReadyPromise = DOMPromiseProxyWithResolveCallback>; ReadyPromise& ready() { return m_readyPromise.get(); } using FinishedPromise = DOMPromiseProxyWithResolveCallback>; FinishedPromise& finished() { return m_finishedPromise.get(); } virtual void cancel(); ExceptionOr finish(); ExceptionOr play(); void updatePlaybackRate(double); ExceptionOr pause(); virtual ExceptionOr bindingsReverse(); ExceptionOr reverse(); void persist(); ExceptionOr commitStyles(); virtual std::optional bindingsStartTime() const; virtual void setBindingsStartTime(std::optional); std::optional startTime() const { return m_startTime; } void setStartTime(std::optional); virtual std::optional bindingsCurrentTime() const; virtual ExceptionOr setBindingsCurrentTime(std::optional); virtual PlayState bindingsPlayState() const { return playState(); } virtual ReplaceState bindingsReplaceState() const { return replaceState(); } virtual bool bindingsPending() const { return pending(); } virtual ReadyPromise& bindingsReady() { return ready(); } virtual FinishedPromise& bindingsFinished() { return finished(); } virtual ExceptionOr bindingsPlay() { return play(); } virtual ExceptionOr bindingsPause() { return pause(); } bool needsTick() const; virtual void tick(); WEBCORE_EXPORT Seconds timeToNextTick() const; virtual void resolve(RenderStyle& targetStyle, const RenderStyle* parentElementStyle, std::optional = std::nullopt); void effectTargetDidChange(const std::optional& previousTarget, const std::optional& newTarget); void acceleratedStateDidChange(); void willChangeRenderer(); bool isRunningAccelerated() const; bool isRelevant() const { return m_isRelevant; } void updateRelevance(); void effectTimingDidChange(); void suspendEffectInvalidation(); void unsuspendEffectInvalidation(); void setSuspended(bool); bool isSuspended() const { return m_isSuspended; } bool isReplaceable() const; void remove(); void enqueueAnimationPlaybackEvent(const AtomString&, std::optional, std::optional); uint64_t globalPosition() const { return m_globalPosition; } void setGlobalPosition(uint64_t globalPosition) { m_globalPosition = globalPosition; } virtual bool canHaveGlobalPosition() { return true; } // ContextDestructionObserver. ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); } void contextDestroyed() final; using RefCounted::ref; using RefCounted::deref; protected: explicit WebAnimation(Document&); void enqueueAnimationEvent(Ref&&); private: enum class DidSeek : uint8_t { Yes, No }; enum class SynchronouslyNotify : uint8_t { Yes, No }; enum class Silently : uint8_t { Yes, No }; enum class RespectHoldTime : uint8_t { Yes, No }; enum class AutoRewind : uint8_t { Yes, No }; enum class TimeToRunPendingTask : uint8_t { NotScheduled, ASAP, WhenReady }; void timingDidChange(DidSeek, SynchronouslyNotify, Silently = Silently::No); void updateFinishedState(DidSeek, SynchronouslyNotify); Seconds effectEndTime() const; WebAnimation& readyPromiseResolve(); WebAnimation& finishedPromiseResolve(); std::optional currentTime(RespectHoldTime, std::optional = std::nullopt) const; ExceptionOr silentlySetCurrentTime(std::optional); void finishNotificationSteps(); bool hasPendingPauseTask() const { return m_timeToRunPendingPauseTask != TimeToRunPendingTask::NotScheduled; } bool hasPendingPlayTask() const { return m_timeToRunPendingPlayTask != TimeToRunPendingTask::NotScheduled; } ExceptionOr play(AutoRewind); void runPendingPauseTask(); void runPendingPlayTask(); void resetPendingTasks(); void setEffectInternal(RefPtr&&, bool = false); void setTimelineInternal(RefPtr&&); bool isEffectInvalidationSuspended() { return m_suspendCount; } bool computeRelevance(); void invalidateEffect(); double effectivePlaybackRate() const; void applyPendingPlaybackRate(); RefPtr m_effect; RefPtr m_timeline; UniqueRef m_readyPromise; UniqueRef m_finishedPromise; Markable m_previousCurrentTime; Markable m_startTime; Markable m_holdTime; MarkableDouble m_pendingPlaybackRate; double m_playbackRate { 1 }; String m_id; int m_suspendCount { 0 }; bool m_isSuspended { false }; bool m_finishNotificationStepsMicrotaskPending; bool m_isRelevant; bool m_shouldSkipUpdatingFinishedStateWhenResolving; bool m_hasScheduledEventsDuringTick { false }; TimeToRunPendingTask m_timeToRunPendingPlayTask { TimeToRunPendingTask::NotScheduled }; TimeToRunPendingTask m_timeToRunPendingPauseTask { TimeToRunPendingTask::NotScheduled }; ReplaceState m_replaceState { ReplaceState::Active }; uint64_t m_globalPosition { 0 }; // ActiveDOMObject. const char* activeDOMObjectName() const final; void suspend(ReasonForSuspension) final; void resume() final; void stop() final; bool virtualHasPendingActivity() const final; // EventTarget EventTargetInterface eventTargetInterface() const final { return WebAnimationEventTargetInterfaceType; } void refEventTarget() final { ref(); } void derefEventTarget() final { deref(); } }; } // namespace WebCore #define SPECIALIZE_TYPE_TRAITS_WEB_ANIMATION(ToValueTypeName, predicate) \ SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \ static bool isType(const WebCore::WebAnimation& value) { return value.predicate; } \ SPECIALIZE_TYPE_TRAITS_END()