[CSS Parser] Rename StyleKeyframe to StyleRuleKeyframe
[WebKit-https.git] / Source / WebCore / css / CSSKeyframesRule.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2012, 2013, 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "CSSKeyframesRule.h"
28
29 #include "CSSDeferredParser.h"
30 #include "CSSKeyframeRule.h"
31 #include "CSSParser.h"
32 #include "CSSRuleList.h"
33 #include "CSSStyleSheet.h"
34 #include "Document.h"
35 #include "StyleProperties.h"
36 #include "StyleSheet.h"
37 #include <wtf/text/StringBuilder.h>
38
39 namespace WebCore {
40
41 StyleRuleKeyframes::StyleRuleKeyframes(const AtomicString& name)
42     : StyleRuleBase(Keyframes)
43     , m_name(name)
44 {
45 }
46
47 StyleRuleKeyframes::StyleRuleKeyframes(const AtomicString& name, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
48     : StyleRuleBase(Keyframes)
49     , m_name(name)
50     , m_deferredRules(WTFMove(deferredRules))
51 {
52     
53 }
54
55 StyleRuleKeyframes::StyleRuleKeyframes(const StyleRuleKeyframes& o)
56     : StyleRuleBase(o)
57     , m_name(o.m_name)
58 {
59     m_keyframes.reserveInitialCapacity(o.keyframes().size());
60     for (auto& keyframe : o.keyframes())
61         m_keyframes.uncheckedAppend(keyframe.copyRef());
62 }
63
64 StyleRuleKeyframes::~StyleRuleKeyframes()
65 {
66 }
67
68 void StyleRuleKeyframes::parseDeferredRulesIfNeeded() const
69 {
70     if (!m_deferredRules)
71         return;
72     
73     m_deferredRules->parseDeferredKeyframes(const_cast<StyleRuleKeyframes&>(*this));
74     m_deferredRules = nullptr;
75 }
76
77 const Vector<Ref<StyleRuleKeyframe>>& StyleRuleKeyframes::keyframes() const
78 {
79     parseDeferredRulesIfNeeded();
80     return m_keyframes;
81 }
82
83 void StyleRuleKeyframes::parserAppendKeyframe(RefPtr<StyleRuleKeyframe>&& keyframe)
84 {
85     if (!keyframe)
86         return;
87     m_keyframes.append(keyframe.releaseNonNull());
88 }
89
90 void StyleRuleKeyframes::wrapperAppendKeyframe(Ref<StyleRuleKeyframe>&& keyframe)
91 {
92     parseDeferredRulesIfNeeded();
93     m_keyframes.append(WTFMove(keyframe));
94 }
95
96 void StyleRuleKeyframes::wrapperRemoveKeyframe(unsigned index)
97 {
98     parseDeferredRulesIfNeeded();
99     m_keyframes.remove(index);
100 }
101
102 size_t StyleRuleKeyframes::findKeyframeIndex(const String& key) const
103 {
104     parseDeferredRulesIfNeeded();
105
106     auto keys = CSSParser::parseKeyframeKeyList(key);
107
108     for (size_t i = m_keyframes.size(); i--; ) {
109         if (m_keyframes[i]->keys() == *keys)
110             return i;
111     }
112
113     return notFound;
114 }
115
116 CSSKeyframesRule::CSSKeyframesRule(StyleRuleKeyframes& keyframesRule, CSSStyleSheet* parent)
117     : CSSRule(parent)
118     , m_keyframesRule(keyframesRule)
119     , m_childRuleCSSOMWrappers(keyframesRule.keyframes().size())
120 {
121 }
122
123 CSSKeyframesRule::~CSSKeyframesRule()
124 {
125     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
126
127     for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {
128         if (m_childRuleCSSOMWrappers[i])
129             m_childRuleCSSOMWrappers[i]->setParentRule(0);
130     }
131 }
132
133 void CSSKeyframesRule::setName(const String& name)
134 {
135     CSSStyleSheet::RuleMutationScope mutationScope(this);
136
137     m_keyframesRule->setName(name);
138 }
139
140 void CSSKeyframesRule::appendRule(const String& ruleText)
141 {
142     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
143
144     CSSParser parser(parserContext());
145     RefPtr<StyleRuleKeyframe> keyframe = parser.parseKeyframeRule(ruleText);
146     if (!keyframe)
147         return;
148
149     CSSStyleSheet::RuleMutationScope mutationScope(this);
150
151     m_keyframesRule->wrapperAppendKeyframe(keyframe.releaseNonNull());
152
153     m_childRuleCSSOMWrappers.grow(length());
154 }
155
156 void CSSKeyframesRule::insertRule(const String& ruleText)
157 {
158     if (CSSStyleSheet* parent = parentStyleSheet()) {
159         if (Document* ownerDocument = parent->ownerDocument())
160             ownerDocument->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("CSSKeyframesRule 'insertRule' function is deprecated.  Use 'appendRule' instead."));
161     }
162     appendRule(ruleText);
163 }
164
165 void CSSKeyframesRule::deleteRule(const String& s)
166 {
167     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
168
169     size_t i = m_keyframesRule->findKeyframeIndex(s);
170     if (i == notFound)
171         return;
172
173     CSSStyleSheet::RuleMutationScope mutationScope(this);
174
175     m_keyframesRule->wrapperRemoveKeyframe(i);
176
177     if (m_childRuleCSSOMWrappers[i])
178         m_childRuleCSSOMWrappers[i]->setParentRule(0);
179     m_childRuleCSSOMWrappers.remove(i);
180 }
181
182 CSSKeyframeRule* CSSKeyframesRule::findRule(const String& s)
183 {
184     size_t i = m_keyframesRule->findKeyframeIndex(s);
185     return i != notFound ? item(i) : nullptr;
186 }
187
188 String CSSKeyframesRule::cssText() const
189 {
190     StringBuilder result;
191     result.appendLiteral("@-webkit-keyframes ");
192     result.append(name());
193     result.appendLiteral(" { \n");
194
195     unsigned size = length();
196     for (unsigned i = 0; i < size; ++i) {
197         result.appendLiteral("  ");
198         result.append(m_keyframesRule->keyframes()[i]->cssText());
199         result.append('\n');
200     }
201     result.append('}');
202     return result.toString();
203 }
204
205 unsigned CSSKeyframesRule::length() const
206
207     return m_keyframesRule->keyframes().size(); 
208 }
209
210 CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const
211
212     if (index >= length())
213         return nullptr;
214
215     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
216     RefPtr<CSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index];
217     if (!rule)
218         rule = adoptRef(new CSSKeyframeRule(const_cast<StyleRuleKeyframe&>(m_keyframesRule->keyframes()[index].get()), const_cast<CSSKeyframesRule*>(this)));
219
220     return rule.get(); 
221 }
222
223 CSSRuleList& CSSKeyframesRule::cssRules()
224 {
225     if (!m_ruleListCSSOMWrapper)
226         m_ruleListCSSOMWrapper = std::make_unique<LiveCSSRuleList<CSSKeyframesRule>>(*this);
227     return *m_ruleListCSSOMWrapper;
228 }
229
230 void CSSKeyframesRule::reattach(StyleRuleBase& rule)
231 {
232     ASSERT_WITH_SECURITY_IMPLICATION(rule.isKeyframesRule());
233     m_keyframesRule = static_cast<StyleRuleKeyframes&>(rule);
234 }
235
236 } // namespace WebCore