Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / inspector / InspectorAnimationAgent.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6
7 #include "core/inspector/InspectorAnimationAgent.h"
8
9 #include "core/animation/Animation.h"
10 #include "core/animation/AnimationEffect.h"
11 #include "core/animation/AnimationNode.h"
12 #include "core/animation/AnimationPlayer.h"
13 #include "core/animation/ElementAnimation.h"
14 #include "core/animation/KeyframeEffectModel.h"
15 #include "core/animation/StringKeyframe.h"
16 #include "core/css/CSSKeyframeRule.h"
17 #include "core/css/CSSKeyframesRule.h"
18 #include "core/inspector/InspectorDOMAgent.h"
19 #include "core/inspector/InspectorStyleSheet.h"
20 #include "platform/Decimal.h"
21
22 namespace blink {
23
24 InspectorAnimationAgent::InspectorAnimationAgent(InspectorDOMAgent* domAgent)
25     : InspectorBaseAgent<InspectorAnimationAgent>("Animation")
26     , m_domAgent(domAgent)
27     , m_frontend(0)
28 {
29 }
30
31 void InspectorAnimationAgent::setFrontend(InspectorFrontend* frontend)
32 {
33     m_frontend = frontend->animation();
34 }
35
36 void InspectorAnimationAgent::clearFrontend()
37 {
38     m_frontend = nullptr;
39     reset();
40 }
41
42 void InspectorAnimationAgent::reset()
43 {
44     m_idToAnimationPlayer.clear();
45 }
46
47 static PassRefPtr<TypeBuilder::Animation::AnimationNode> buildObjectForAnimationNode(AnimationNode* animationNode)
48 {
49     RefPtr<TypeBuilder::Animation::AnimationNode> animationObject = TypeBuilder::Animation::AnimationNode::create()
50         .setStartDelay(animationNode->specifiedTiming().startDelay)
51         .setPlaybackRate(animationNode->specifiedTiming().playbackRate)
52         .setIterationStart(animationNode->specifiedTiming().iterationStart)
53         .setIterationCount(animationNode->specifiedTiming().iterationCount)
54         .setDuration(animationNode->duration())
55         .setDirection(animationNode->specifiedTiming().direction)
56         .setFillMode(animationNode->specifiedTiming().fillMode)
57         .setTimeFraction(animationNode->timeFraction())
58         .setName(animationNode->name());
59     return animationObject.release();
60 }
61
62 static String playerId(AnimationPlayer& player)
63 {
64     return String::number(player.sequenceNumber());
65 }
66
67 static PassRefPtr<TypeBuilder::Animation::AnimationPlayer> buildObjectForAnimationPlayer(AnimationPlayer& animationPlayer, PassRefPtr<TypeBuilder::Animation::KeyframesRule> keyframeRule = nullptr)
68 {
69     RefPtr<TypeBuilder::Animation::AnimationNode> animationObject = buildObjectForAnimationNode(animationPlayer.source());
70     if (keyframeRule)
71         animationObject->setKeyframesRule(keyframeRule);
72
73     RefPtr<TypeBuilder::Animation::AnimationPlayer> playerObject = TypeBuilder::Animation::AnimationPlayer::create()
74         .setId(playerId(animationPlayer))
75         .setPausedState(animationPlayer.paused())
76         .setPlayState(animationPlayer.playState())
77         .setPlaybackRate(animationPlayer.playbackRate())
78         .setStartTime(animationPlayer.startTime())
79         .setCurrentTime(animationPlayer.currentTime())
80         .setSource(animationObject.release());
81     return playerObject.release();
82 }
83
84 static PassRefPtr<TypeBuilder::Animation::KeyframeStyle> buildObjectForStyleKeyframe(StyleKeyframe* keyframe)
85 {
86     RefPtrWillBeRawPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), keyframe->mutableProperties().ensureCSSStyleDeclaration(), 0);
87     RefPtr<TypeBuilder::Animation::KeyframeStyle> keyframeObject = TypeBuilder::Animation::KeyframeStyle::create()
88         .setOffset(keyframe->keyText())
89         .setStyle(inspectorStyle->buildObjectForStyle());
90     return keyframeObject.release();
91 }
92
93 static PassRefPtr<TypeBuilder::Animation::KeyframeStyle> buildObjectForStringKeyframe(const StringKeyframe* keyframe)
94 {
95     RefPtrWillBeRawPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), keyframe->propertySetForInspector().get()->ensureCSSStyleDeclaration(), 0);
96     Decimal decimal = Decimal::fromDouble(keyframe->offset() * 100);
97     String offset = decimal.toString();
98     offset.append("%");
99
100     RefPtr<TypeBuilder::Animation::KeyframeStyle> keyframeObject = TypeBuilder::Animation::KeyframeStyle::create()
101         .setOffset(offset)
102         .setStyle(inspectorStyle->buildObjectForStyle());
103     return keyframeObject.release();
104 }
105
106 static PassRefPtr<TypeBuilder::Animation::KeyframesRule> buildObjectForStyleRuleKeyframes(const StyleRuleKeyframes* keyframesRule)
107 {
108     RefPtr<TypeBuilder::Array<TypeBuilder::Animation::KeyframeStyle> > keyframes = TypeBuilder::Array<TypeBuilder::Animation::KeyframeStyle>::create();
109     const WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >& styleKeyframes = keyframesRule->keyframes();
110     for (const auto& styleKeyframe : styleKeyframes)
111         keyframes->addItem(buildObjectForStyleKeyframe(styleKeyframe.get()));
112
113     RefPtr<TypeBuilder::Animation::KeyframesRule> keyframesObject = TypeBuilder::Animation::KeyframesRule::create()
114         .setKeyframes(keyframes);
115     keyframesObject->setName(keyframesRule->name());
116     return keyframesObject.release();
117 }
118
119 static PassRefPtr<TypeBuilder::Animation::KeyframesRule> buildObjectForAnimationKeyframes(const Animation* animation)
120 {
121     if (!animation->effect()->isKeyframeEffectModel())
122         return nullptr;
123     const KeyframeEffectModelBase* effect = toKeyframeEffectModelBase(animation->effect());
124     WillBeHeapVector<RefPtrWillBeMember<Keyframe> > normalizedKeyframes = KeyframeEffectModelBase::normalizedKeyframesForInspector(effect->getFrames());
125     RefPtr<TypeBuilder::Array<TypeBuilder::Animation::KeyframeStyle> > keyframes = TypeBuilder::Array<TypeBuilder::Animation::KeyframeStyle>::create();
126
127     for (const auto& keyframe : normalizedKeyframes) {
128         // Ignore CSS Transitions
129         if (!keyframe.get()->isStringKeyframe())
130             continue;
131         const StringKeyframe* stringKeyframe = toStringKeyframe(keyframe.get());
132         keyframes->addItem(buildObjectForStringKeyframe(stringKeyframe));
133     }
134     RefPtr<TypeBuilder::Animation::KeyframesRule> keyframesObject = TypeBuilder::Animation::KeyframesRule::create()
135         .setKeyframes(keyframes);
136     return keyframesObject.release();
137 }
138
139 static PassRefPtr<TypeBuilder::Animation::KeyframesRule> buildObjectForKeyframesRule(const Element& element, const AnimationPlayer& player)
140 {
141     StyleResolver& styleResolver = element.ownerDocument()->ensureStyleResolver();
142     CSSAnimations& cssAnimations = element.activeAnimations()->cssAnimations();
143     const AtomicString animationName = cssAnimations.getAnimationNameForInspector(player);
144     RefPtr<TypeBuilder::Animation::KeyframesRule> keyframeRule;
145
146     if (!animationName.isNull()) {
147         // CSS Animations
148         const StyleRuleKeyframes* keyframes = cssAnimations.matchScopedKeyframesRule(&styleResolver, &element, animationName.impl());
149         keyframeRule = buildObjectForStyleRuleKeyframes(keyframes);
150     } else {
151         // Web Animations
152         keyframeRule = buildObjectForAnimationKeyframes(toAnimation(player.source()));
153     }
154
155     return keyframeRule;
156 }
157
158 void InspectorAnimationAgent::getAnimationPlayersForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::Animation::AnimationPlayer> >& animationPlayersArray)
159 {
160     animationPlayersArray = TypeBuilder::Array<TypeBuilder::Animation::AnimationPlayer>::create();
161     Element* element = m_domAgent->assertElement(errorString, nodeId);
162     if (!element)
163         return;
164     m_idToAnimationPlayer.clear();
165     WillBeHeapVector<RefPtrWillBeMember<AnimationPlayer> > players = ElementAnimation::getAnimationPlayers(*element);
166     for (WillBeHeapVector<RefPtrWillBeMember<AnimationPlayer> >::iterator it = players.begin(); it != players.end(); ++it) {
167         AnimationPlayer& player = *(it->get());
168         m_idToAnimationPlayer.set(playerId(player), &player);
169         RefPtr<TypeBuilder::Animation::KeyframesRule> keyframeRule = buildObjectForKeyframesRule(*element, player);
170         animationPlayersArray->addItem(buildObjectForAnimationPlayer(player, keyframeRule));
171     }
172 }
173
174 void InspectorAnimationAgent::pauseAnimationPlayer(ErrorString* errorString, const String& id, RefPtr<TypeBuilder::Animation::AnimationPlayer>& animationPlayer)
175 {
176     AnimationPlayer* player = assertAnimationPlayer(errorString, id);
177     if (!player)
178         return;
179     player->pause();
180     animationPlayer = buildObjectForAnimationPlayer(*player);
181 }
182
183 void InspectorAnimationAgent::playAnimationPlayer(ErrorString* errorString, const String& id, RefPtr<TypeBuilder::Animation::AnimationPlayer>& animationPlayer)
184 {
185     AnimationPlayer* player = assertAnimationPlayer(errorString, id);
186     if (!player)
187         return;
188     player->play();
189     animationPlayer = buildObjectForAnimationPlayer(*player);
190 }
191
192 void InspectorAnimationAgent::setAnimationPlayerCurrentTime(ErrorString* errorString, const String& id, double currentTime, RefPtr<TypeBuilder::Animation::AnimationPlayer>& animationPlayer)
193 {
194     AnimationPlayer* player = assertAnimationPlayer(errorString, id);
195     if (!player)
196         return;
197     player->setCurrentTime(currentTime);
198     animationPlayer = buildObjectForAnimationPlayer(*player);
199 }
200
201 void InspectorAnimationAgent::getAnimationPlayerState(ErrorString* errorString, const String& id, double* currentTime, bool* isRunning)
202 {
203     AnimationPlayer* player = assertAnimationPlayer(errorString, id);
204     if (!player)
205         return;
206     *currentTime = player->currentTime();
207     *isRunning = player->playing();
208 }
209
210 AnimationPlayer* InspectorAnimationAgent::assertAnimationPlayer(ErrorString* errorString, const String& id)
211 {
212     AnimationPlayer* player = m_idToAnimationPlayer.get(id);
213     if (!player) {
214         *errorString = "Could not find animation player with given id";
215         return 0;
216     }
217     return player;
218 }
219
220 void InspectorAnimationAgent::trace(Visitor* visitor)
221 {
222 #if ENABLE(OILPAN)
223     visitor->trace(m_idToAnimationPlayer);
224     visitor->trace(m_domAgent);
225 #endif
226     InspectorBaseAgent::trace(visitor);
227 }
228
229 }