1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/animation/element_animation.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/effect_input.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/core/animation/timing_input.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/feature_policy/feature_policy.h"
#include "third_party/blink/renderer/core/feature_policy/layout_animations_policy.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
namespace {
// A helper method which is used to trigger a violation report for cases where
// the |element.animate| API is used to animate a CSS property which is blocked
// by the feature policy 'layout-animations'.
void ReportFeaturePolicyViolationsIfNecessary(
const Document& document,
const KeyframeEffectModelBase& effect) {
for (const auto& property_handle : effect.Properties()) {
if (!property_handle.IsCSSProperty())
continue;
const auto& css_property = property_handle.GetCSSProperty();
if (LayoutAnimationsPolicy::AffectedCSSProperties().Contains(
&css_property)) {
LayoutAnimationsPolicy::ReportViolation(css_property, document);
}
}
}
} // namespace
Animation* ElementAnimation::animate(
ScriptState* script_state,
Element& element,
const ScriptValue& keyframes,
UnrestrictedDoubleOrKeyframeAnimationOptions options,
ExceptionState& exception_state) {
EffectModel::CompositeOperation composite = EffectModel::kCompositeReplace;
if (options.IsKeyframeAnimationOptions()) {
composite = EffectModel::StringToCompositeOperation(
options.GetAsKeyframeAnimationOptions()->composite())
.value();
}
KeyframeEffectModelBase* effect = EffectInput::Convert(
&element, keyframes, composite, script_state, exception_state);
if (exception_state.HadException())
return nullptr;
Timing timing =
TimingInput::Convert(options, &element.GetDocument(), exception_state);
if (exception_state.HadException())
return nullptr;
Animation* animation = animateInternal(element, effect, timing);
if (options.IsKeyframeAnimationOptions())
animation->setId(options.GetAsKeyframeAnimationOptions()->id());
return animation;
}
Animation* ElementAnimation::animate(ScriptState* script_state,
Element& element,
const ScriptValue& keyframes,
ExceptionState& exception_state) {
KeyframeEffectModelBase* effect =
EffectInput::Convert(&element, keyframes, EffectModel::kCompositeReplace,
script_state, exception_state);
if (exception_state.HadException())
return nullptr;
return animateInternal(element, effect, Timing());
}
HeapVector<Member<Animation>> ElementAnimation::getAnimations(
Element& element) {
element.GetDocument().UpdateStyleAndLayoutTreeForNode(&element);
HeapVector<Member<Animation>> animations;
if (!element.HasAnimations())
return animations;
for (const auto& animation :
element.GetDocument().Timeline().getAnimations()) {
DCHECK(animation->effect());
if (ToKeyframeEffect(animation->effect())->target() == element &&
(animation->effect()->IsCurrent() || animation->effect()->IsInEffect()))
animations.push_back(animation);
}
return animations;
}
Animation* ElementAnimation::animateInternal(Element& element,
KeyframeEffectModelBase* effect,
const Timing& timing) {
ReportFeaturePolicyViolationsIfNecessary(element.GetDocument(), *effect);
KeyframeEffect* keyframe_effect =
KeyframeEffect::Create(&element, effect, timing);
return element.GetDocument().Timeline().Play(keyframe_effect);
}
} // namespace blink
|