summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/animation/animatable.cc
blob: 6d6466339df7a6d7e82edb972c7ec171f52054e0 (plain)
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
113
114
115
116
117
118
119
120
121
122
123
// 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/animatable.h"

#include "third_party/blink/renderer/bindings/core/v8/unrestricted_double_or_keyframe_animation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/unrestricted_double_or_keyframe_effect_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_get_animations_options.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/document_animations.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/layout_animations_policy.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.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 ExecutionContext& context,
    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, context);
    }
  }
}

UnrestrictedDoubleOrKeyframeEffectOptions CoerceEffectOptions(
    UnrestrictedDoubleOrKeyframeAnimationOptions options) {
  if (options.IsKeyframeAnimationOptions()) {
    return UnrestrictedDoubleOrKeyframeEffectOptions::FromKeyframeEffectOptions(
        options.GetAsKeyframeAnimationOptions());
  } else {
    return UnrestrictedDoubleOrKeyframeEffectOptions::FromUnrestrictedDouble(
        options.GetAsUnrestrictedDouble());
  }
}

}  // namespace

Animation* Animatable::animate(
    ScriptState* script_state,
    const ScriptValue& keyframes,
    const UnrestrictedDoubleOrKeyframeAnimationOptions& options,
    ExceptionState& exception_state) {
  Element* element = GetAnimationTarget();
  KeyframeEffect* effect =
      KeyframeEffect::Create(script_state, element, keyframes,
                             CoerceEffectOptions(options), exception_state);
  if (exception_state.HadException())
    return nullptr;

  ReportFeaturePolicyViolationsIfNecessary(*element->GetExecutionContext(),
                                           *effect->Model());
  Animation* animation = element->GetDocument().Timeline().Play(effect);
  if (options.IsKeyframeAnimationOptions())
    animation->setId(options.GetAsKeyframeAnimationOptions()->id());
  return animation;
}

Animation* Animatable::animate(ScriptState* script_state,
                               const ScriptValue& keyframes,
                               ExceptionState& exception_state) {
  Element* element = GetAnimationTarget();
  KeyframeEffect* effect =
      KeyframeEffect::Create(script_state, element, keyframes, exception_state);
  if (exception_state.HadException())
    return nullptr;

  ReportFeaturePolicyViolationsIfNecessary(*element->GetExecutionContext(),
                                           *effect->Model());
  return element->GetDocument().Timeline().Play(effect);
}

HeapVector<Member<Animation>> Animatable::getAnimations(
    GetAnimationsOptions* options) {
  bool use_subtree = options && options->subtree();
  Element* element = GetAnimationTarget();
  if (use_subtree)
    element->GetDocument().UpdateStyleAndLayoutTreeForSubtree(element);
  else
    element->GetDocument().UpdateStyleAndLayoutTreeForNode(element);

  HeapVector<Member<Animation>> animations;
  if (!use_subtree && !element->HasAnimations())
    return animations;

  for (const auto& animation :
       element->GetDocument().GetDocumentAnimations().getAnimations(
           element->GetTreeScope())) {
    DCHECK(animation->effect());
    // TODO(gtsteel) make this use the idl properties
    Element* target = To<KeyframeEffect>(animation->effect())->EffectTarget();
    if (element == target || (use_subtree && element->contains(target))) {
      // DocumentAnimations::getAnimations should only give us animations that
      // are either current or in effect.
      DCHECK(animation->effect()->IsCurrent() ||
             animation->effect()->IsInEffect());
      animations.push_back(animation);
    }
  }
  return animations;
}

}  // namespace blink