Use "= default" to denote default constructor or destructor
[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 <wtf/text/StringBuilder.h>
36
37 namespace WebCore {
38
39 StyleRuleKeyframes::StyleRuleKeyframes(const AtomicString& name)
40     : StyleRuleBase(Keyframes)
41     , m_name(name)
42 {
43 }
44
45 StyleRuleKeyframes::StyleRuleKeyframes(const AtomicString& name, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
46     : StyleRuleBase(Keyframes)
47     , m_name(name)
48     , m_deferredRules(WTFMove(deferredRules))
49 {
50     
51 }
52
53 StyleRuleKeyframes::StyleRuleKeyframes(const StyleRuleKeyframes& o)
54     : StyleRuleBase(o)
55     , m_name(o.m_name)
56 {
57     m_keyframes.reserveInitialCapacity(o.keyframes().size());
58     for (auto& keyframe : o.keyframes())
59         m_keyframes.uncheckedAppend(keyframe.copyRef());
60 }
61
62 StyleRuleKeyframes::~StyleRuleKeyframes() = default;
63
64 void StyleRuleKeyframes::parseDeferredRulesIfNeeded() const
65 {
66     if (!m_deferredRules)
67         return;
68     
69     m_deferredRules->parseDeferredKeyframes(const_cast<StyleRuleKeyframes&>(*this));
70     m_deferredRules = nullptr;
71 }
72
73 const Vector<Ref<StyleRuleKeyframe>>& StyleRuleKeyframes::keyframes() const
74 {
75     parseDeferredRulesIfNeeded();
76     return m_keyframes;
77 }
78
79 void StyleRuleKeyframes::parserAppendKeyframe(RefPtr<StyleRuleKeyframe>&& keyframe)
80 {
81     if (!keyframe)
82         return;
83     m_keyframes.append(keyframe.releaseNonNull());
84 }
85
86 void StyleRuleKeyframes::wrapperAppendKeyframe(Ref<StyleRuleKeyframe>&& keyframe)
87 {
88     parseDeferredRulesIfNeeded();
89     m_keyframes.append(WTFMove(keyframe));
90 }
91
92 void StyleRuleKeyframes::wrapperRemoveKeyframe(unsigned index)
93 {
94     parseDeferredRulesIfNeeded();
95     m_keyframes.remove(index);
96 }
97
98 size_t StyleRuleKeyframes::findKeyframeIndex(const String& key) const
99 {
100     parseDeferredRulesIfNeeded();
101
102     auto keys = CSSParser::parseKeyframeKeyList(key);
103
104     if (!keys)
105         return notFound;
106
107     for (size_t i = m_keyframes.size(); i--; ) {
108         if (m_keyframes[i]->keys() == *keys)
109             return i;
110     }
111
112     return notFound;
113 }
114
115 CSSKeyframesRule::CSSKeyframesRule(StyleRuleKeyframes& keyframesRule, CSSStyleSheet* parent)
116     : CSSRule(parent)
117     , m_keyframesRule(keyframesRule)
118     , m_childRuleCSSOMWrappers(keyframesRule.keyframes().size())
119 {
120 }
121
122 CSSKeyframesRule::~CSSKeyframesRule()
123 {
124     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
125
126     for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {
127         if (m_childRuleCSSOMWrappers[i])
128             m_childRuleCSSOMWrappers[i]->setParentRule(0);
129     }
130 }
131
132 void CSSKeyframesRule::setName(const String& name)
133 {
134     CSSStyleSheet::RuleMutationScope mutationScope(this);
135
136     m_keyframesRule->setName(name);
137 }
138
139 void CSSKeyframesRule::appendRule(const String& ruleText)
140 {
141     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
142
143     CSSParser parser(parserContext());
144     RefPtr<StyleRuleKeyframe> keyframe = parser.parseKeyframeRule(ruleText);
145     if (!keyframe)
146         return;
147
148     CSSStyleSheet::RuleMutationScope mutationScope(this);
149
150     m_keyframesRule->wrapperAppendKeyframe(keyframe.releaseNonNull());
151
152     m_childRuleCSSOMWrappers.grow(length());
153 }
154
155 void CSSKeyframesRule::insertRule(const String& ruleText)
156 {
157     if (CSSStyleSheet* parent = parentStyleSheet()) {
158         if (Document* ownerDocument = parent->ownerDocument())
159             ownerDocument->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("CSSKeyframesRule 'insertRule' function is deprecated.  Use 'appendRule' instead."));
160     }
161     appendRule(ruleText);
162 }
163
164 void CSSKeyframesRule::deleteRule(const String& s)
165 {
166     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
167
168     size_t i = m_keyframesRule->findKeyframeIndex(s);
169     if (i == notFound)
170         return;
171
172     CSSStyleSheet::RuleMutationScope mutationScope(this);
173
174     m_keyframesRule->wrapperRemoveKeyframe(i);
175
176     if (m_childRuleCSSOMWrappers[i])
177         m_childRuleCSSOMWrappers[i]->setParentRule(0);
178     m_childRuleCSSOMWrappers.remove(i);
179 }
180
181 CSSKeyframeRule* CSSKeyframesRule::findRule(const String& s)
182 {
183     size_t i = m_keyframesRule->findKeyframeIndex(s);
184     return i != notFound ? item(i) : nullptr;
185 }
186
187 String CSSKeyframesRule::cssText() const
188 {
189     StringBuilder result;
190     result.appendLiteral("@-webkit-keyframes ");
191     result.append(name());
192     result.appendLiteral(" { \n");
193
194     unsigned size = length();
195     for (unsigned i = 0; i < size; ++i) {
196         result.appendLiteral("  ");
197         result.append(m_keyframesRule->keyframes()[i]->cssText());
198         result.append('\n');
199     }
200     result.append('}');
201     return result.toString();
202 }
203
204 unsigned CSSKeyframesRule::length() const
205
206     return m_keyframesRule->keyframes().size(); 
207 }
208
209 CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const
210
211     if (index >= length())
212         return nullptr;
213     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
214     auto& rule = m_childRuleCSSOMWrappers[index];
215     if (!rule)
216         rule = adoptRef(*new CSSKeyframeRule(m_keyframesRule->keyframes()[index], const_cast<CSSKeyframesRule*>(this)));
217     return rule.get(); 
218 }
219
220 CSSRuleList& CSSKeyframesRule::cssRules()
221 {
222     if (!m_ruleListCSSOMWrapper)
223         m_ruleListCSSOMWrapper = std::make_unique<LiveCSSRuleList<CSSKeyframesRule>>(*this);
224     return *m_ruleListCSSOMWrapper;
225 }
226
227 void CSSKeyframesRule::reattach(StyleRuleBase& rule)
228 {
229     ASSERT_WITH_SECURITY_IMPLICATION(rule.isKeyframesRule());
230     m_keyframesRule = static_cast<StyleRuleKeyframes&>(rule);
231 }
232
233 } // namespace WebCore