CSSOM rule wrappers always have a corresponding internal style object.
[WebKit-https.git] / Source / WebCore / css / WebKitCSSKeyframesRule.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2012, 2013 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 "WebKitCSSKeyframesRule.h"
28
29 #include "CSSParser.h"
30 #include "CSSRuleList.h"
31 #include "CSSStyleSheet.h"
32 #include "StyleProperties.h"
33 #include "StyleSheet.h"
34 #include "WebKitCSSKeyframeRule.h"
35 #include <wtf/text/StringBuilder.h>
36
37 namespace WebCore {
38
39 StyleRuleKeyframes::StyleRuleKeyframes()
40     : StyleRuleBase(Keyframes, 0)
41 {
42 }
43
44 StyleRuleKeyframes::StyleRuleKeyframes(const StyleRuleKeyframes& o)
45     : StyleRuleBase(o)
46     , m_keyframes(o.m_keyframes)
47     , m_name(o.m_name)
48 {
49 }
50
51 StyleRuleKeyframes::~StyleRuleKeyframes()
52 {
53 }
54
55 void StyleRuleKeyframes::parserAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe)
56 {
57     if (!keyframe)
58         return;
59     m_keyframes.append(keyframe);
60 }
61
62 void StyleRuleKeyframes::wrapperAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe)
63 {
64     m_keyframes.append(keyframe);
65 }
66
67 void StyleRuleKeyframes::wrapperRemoveKeyframe(unsigned index)
68 {
69     m_keyframes.remove(index);
70 }
71
72 int StyleRuleKeyframes::findKeyframeIndex(const String& key) const
73 {
74     String percentageString;
75     if (equalIgnoringCase(key, "from"))
76         percentageString = ASCIILiteral("0%");
77     else if (equalIgnoringCase(key, "to"))
78         percentageString = ASCIILiteral("100%");
79     else
80         percentageString = key;
81     
82     for (unsigned i = 0; i < m_keyframes.size(); ++i) {
83         if (m_keyframes[i]->keyText() == percentageString)
84             return i;
85     }
86     return -1;
87 }
88
89 WebKitCSSKeyframesRule::WebKitCSSKeyframesRule(StyleRuleKeyframes& keyframesRule, CSSStyleSheet* parent)
90     : CSSRule(parent)
91     , m_keyframesRule(keyframesRule)
92     , m_childRuleCSSOMWrappers(keyframesRule.keyframes().size())
93 {
94 }
95
96 WebKitCSSKeyframesRule::~WebKitCSSKeyframesRule()
97 {
98     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
99
100     for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {
101         if (m_childRuleCSSOMWrappers[i])
102             m_childRuleCSSOMWrappers[i]->setParentRule(0);
103     }
104 }
105
106 void WebKitCSSKeyframesRule::setName(const String& name)
107 {
108     CSSStyleSheet::RuleMutationScope mutationScope(this);
109
110     m_keyframesRule->setName(name);
111 }
112
113 void WebKitCSSKeyframesRule::insertRule(const String& ruleText)
114 {
115     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
116
117     CSSParser parser(parserContext());
118     CSSStyleSheet* styleSheet = parentStyleSheet();
119     RefPtr<StyleKeyframe> keyframe = parser.parseKeyframeRule(styleSheet ? &styleSheet->contents() : nullptr, ruleText);
120     if (!keyframe)
121         return;
122
123     CSSStyleSheet::RuleMutationScope mutationScope(this);
124
125     m_keyframesRule->wrapperAppendKeyframe(keyframe);
126
127     m_childRuleCSSOMWrappers.grow(length());
128 }
129
130 void WebKitCSSKeyframesRule::deleteRule(const String& s)
131 {
132     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
133
134     int i = m_keyframesRule->findKeyframeIndex(s);
135     if (i < 0)
136         return;
137
138     CSSStyleSheet::RuleMutationScope mutationScope(this);
139
140     m_keyframesRule->wrapperRemoveKeyframe(i);
141
142     if (m_childRuleCSSOMWrappers[i])
143         m_childRuleCSSOMWrappers[i]->setParentRule(0);
144     m_childRuleCSSOMWrappers.remove(i);
145 }
146
147 WebKitCSSKeyframeRule* WebKitCSSKeyframesRule::findRule(const String& s)
148 {
149     int i = m_keyframesRule->findKeyframeIndex(s);
150     return (i >= 0) ? item(i) : 0;
151 }
152
153 String WebKitCSSKeyframesRule::cssText() const
154 {
155     StringBuilder result;
156     result.appendLiteral("@-webkit-keyframes ");
157     result.append(name());
158     result.appendLiteral(" { \n");
159
160     unsigned size = length();
161     for (unsigned i = 0; i < size; ++i) {
162         result.appendLiteral("  ");
163         result.append(m_keyframesRule->keyframes()[i]->cssText());
164         result.append('\n');
165     }
166     result.append('}');
167     return result.toString();
168 }
169
170 unsigned WebKitCSSKeyframesRule::length() const
171
172     return m_keyframesRule->keyframes().size(); 
173 }
174
175 WebKitCSSKeyframeRule* WebKitCSSKeyframesRule::item(unsigned index) const
176
177     if (index >= length())
178         return 0;
179
180     ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size());
181     RefPtr<WebKitCSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index];
182     if (!rule)
183         rule = adoptRef(new WebKitCSSKeyframeRule(*m_keyframesRule->keyframes()[index], const_cast<WebKitCSSKeyframesRule*>(this)));
184
185     return rule.get(); 
186 }
187
188 CSSRuleList& WebKitCSSKeyframesRule::cssRules()
189 {
190     if (!m_ruleListCSSOMWrapper)
191         m_ruleListCSSOMWrapper = std::make_unique<LiveCSSRuleList<WebKitCSSKeyframesRule>>(this);
192     return *m_ruleListCSSOMWrapper;
193 }
194
195 void WebKitCSSKeyframesRule::reattach(StyleRuleBase& rule)
196 {
197     ASSERT_WITH_SECURITY_IMPLICATION(rule.isKeyframesRule());
198     m_keyframesRule = static_cast<StyleRuleKeyframes&>(rule);
199 }
200
201 } // namespace WebCore