1c53bd496fa5acfeb9c04fc27466d7c804fdf619
[WebKit-https.git] / Source / WebCore / css / StyleRule.cpp
1 /*
2  * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3  * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
4  * Copyright (C) 2002, 2005, 2006, 2008, 2012 Apple Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include "StyleRule.h"
24
25 #include "CSSDeferredParser.h"
26 #include "CSSFontFaceRule.h"
27 #include "CSSImportRule.h"
28 #include "CSSKeyframeRule.h"
29 #include "CSSKeyframesRule.h"
30 #include "CSSMediaRule.h"
31 #include "CSSNamespaceRule.h"
32 #include "CSSPageRule.h"
33 #include "CSSStyleRule.h"
34 #include "CSSSupportsRule.h"
35 #include "MediaList.h"
36 #include "StyleProperties.h"
37 #include "StyleRuleImport.h"
38 #include "WebKitCSSViewportRule.h"
39
40 namespace WebCore {
41
42 struct SameSizeAsStyleRuleBase : public WTF::RefCountedBase {
43     unsigned bitfields : 5;
44 };
45
46 COMPILE_ASSERT(sizeof(StyleRuleBase) == sizeof(SameSizeAsStyleRuleBase), StyleRuleBase_should_stay_small);
47
48 RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet) const
49 {
50     return createCSSOMWrapper(parentSheet, nullptr);
51 }
52
53 RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSRule* parentRule) const
54
55     return createCSSOMWrapper(nullptr, parentRule);
56 }
57
58 void StyleRuleBase::destroy()
59 {
60     switch (type()) {
61     case Style:
62         delete downcast<StyleRule>(this);
63         return;
64     case Page:
65         delete downcast<StyleRulePage>(this);
66         return;
67     case FontFace:
68         delete downcast<StyleRuleFontFace>(this);
69         return;
70     case Media:
71         delete downcast<StyleRuleMedia>(this);
72         return;
73     case Supports:
74         delete downcast<StyleRuleSupports>(this);
75         return;
76     case Import:
77         delete downcast<StyleRuleImport>(this);
78         return;
79     case Keyframes:
80         delete downcast<StyleRuleKeyframes>(this);
81         return;
82 #if ENABLE(CSS_DEVICE_ADAPTATION)
83     case Viewport:
84         delete downcast<StyleRuleViewport>(this);
85         return;
86 #endif
87     case Namespace:
88         delete downcast<StyleRuleNamespace>(this);
89         return;
90     case Keyframe:
91         delete downcast<StyleRuleKeyframe>(this);
92         return;
93     case Charset:
94         delete downcast<StyleRuleCharset>(this);
95         return;
96     case Unknown:
97         ASSERT_NOT_REACHED();
98         return;
99     }
100     ASSERT_NOT_REACHED();
101 }
102
103 Ref<StyleRuleBase> StyleRuleBase::copy() const
104 {
105     switch (type()) {
106     case Style:
107         return downcast<StyleRule>(*this).copy();
108     case Page:
109         return downcast<StyleRulePage>(*this).copy();
110     case FontFace:
111         return downcast<StyleRuleFontFace>(*this).copy();
112     case Media:
113         return downcast<StyleRuleMedia>(*this).copy();
114     case Supports:
115         return downcast<StyleRuleSupports>(*this).copy();
116     case Keyframes:
117         return downcast<StyleRuleKeyframes>(*this).copy();
118 #if ENABLE(CSS_DEVICE_ADAPTATION)
119     case Viewport:
120         return downcast<StyleRuleViewport>(*this).copy();
121 #endif
122     case Import:
123     case Namespace:
124         // FIXME: Copy import and namespace rules.
125         break;
126     case Unknown:
127     case Charset:
128     case Keyframe:
129         break;
130     }
131     CRASH();
132 }
133
134 RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const
135 {
136     RefPtr<CSSRule> rule;
137     StyleRuleBase& self = const_cast<StyleRuleBase&>(*this);
138     switch (type()) {
139     case Style:
140         rule = CSSStyleRule::create(downcast<StyleRule>(self), parentSheet);
141         break;
142     case Page:
143         rule = CSSPageRule::create(downcast<StyleRulePage>(self), parentSheet);
144         break;
145     case FontFace:
146         rule = CSSFontFaceRule::create(downcast<StyleRuleFontFace>(self), parentSheet);
147         break;
148     case Media:
149         rule = CSSMediaRule::create(downcast<StyleRuleMedia>(self), parentSheet);
150         break;
151     case Supports:
152         rule = CSSSupportsRule::create(downcast<StyleRuleSupports>(self), parentSheet);
153         break;
154     case Import:
155         rule = CSSImportRule::create(downcast<StyleRuleImport>(self), parentSheet);
156         break;
157     case Keyframes:
158         rule = CSSKeyframesRule::create(downcast<StyleRuleKeyframes>(self), parentSheet);
159         break;
160 #if ENABLE(CSS_DEVICE_ADAPTATION)
161     case Viewport:
162         rule = WebKitCSSViewportRule::create(downcast<StyleRuleViewport>(self), parentSheet);
163         break;
164 #endif
165     case Namespace:
166         rule = CSSNamespaceRule::create(downcast<StyleRuleNamespace>(self), parentSheet);
167         break;
168     case Unknown:
169     case Charset:
170     case Keyframe:
171         ASSERT_NOT_REACHED();
172         return nullptr;
173     }
174     if (parentRule)
175         rule->setParentRule(parentRule);
176     return rule;
177 }
178
179 unsigned StyleRule::averageSizeInBytes()
180 {
181     return sizeof(StyleRule) + sizeof(CSSSelector) + StyleProperties::averageSizeInBytes();
182 }
183
184 StyleRule::StyleRule(Ref<StylePropertiesBase>&& properties)
185     : StyleRuleBase(Style)
186     , m_properties(WTFMove(properties))
187 {
188 }
189
190 StyleRule::StyleRule(const StyleRule& o)
191     : StyleRuleBase(o)
192     , m_properties(o.properties().mutableCopy())
193     , m_selectorList(o.m_selectorList)
194 {
195 }
196
197 StyleRule::~StyleRule() = default;
198
199 const StyleProperties& StyleRule::properties() const
200 {
201     if (m_properties->type() == DeferredPropertiesType)
202         m_properties = downcast<DeferredStyleProperties>(m_properties.get()).parseDeferredProperties();
203     return downcast<StyleProperties>(m_properties.get());
204 }
205
206 MutableStyleProperties& StyleRule::mutableProperties()
207 {
208     if (!is<MutableStyleProperties>(m_properties.get()))
209         m_properties = properties().mutableCopy();
210     return downcast<MutableStyleProperties>(m_properties.get());
211 }
212
213 Ref<StyleRule> StyleRule::create(const Vector<const CSSSelector*>& selectors, Ref<StyleProperties>&& properties)
214 {
215     ASSERT_WITH_SECURITY_IMPLICATION(!selectors.isEmpty());
216     CSSSelector* selectorListArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * selectors.size()));
217     for (unsigned i = 0; i < selectors.size(); ++i)
218         new (NotNull, &selectorListArray[i]) CSSSelector(*selectors.at(i));
219     selectorListArray[selectors.size() - 1].setLastInSelectorList();
220     auto rule = StyleRule::create(WTFMove(properties));
221     rule.get().parserAdoptSelectorArray(selectorListArray);
222     return rule;
223 }
224
225 Vector<RefPtr<StyleRule>> StyleRule::splitIntoMultipleRulesWithMaximumSelectorComponentCount(unsigned maxCount) const
226 {
227     ASSERT(selectorList().componentCount() > maxCount);
228
229     Vector<RefPtr<StyleRule>> rules;
230     Vector<const CSSSelector*> componentsSinceLastSplit;
231
232     for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(selector)) {
233         Vector<const CSSSelector*, 8> componentsInThisSelector;
234         for (const CSSSelector* component = selector; component; component = component->tagHistory())
235             componentsInThisSelector.append(component);
236
237         if (componentsInThisSelector.size() + componentsSinceLastSplit.size() > maxCount && !componentsSinceLastSplit.isEmpty()) {
238             rules.append(create(componentsSinceLastSplit, const_cast<StyleProperties&>(properties())));
239             componentsSinceLastSplit.clear();
240         }
241
242         componentsSinceLastSplit.appendVector(componentsInThisSelector);
243     }
244
245     if (!componentsSinceLastSplit.isEmpty())
246         rules.append(create(componentsSinceLastSplit, const_cast<StyleProperties&>(properties())));
247
248     return rules;
249 }
250
251 StyleRulePage::StyleRulePage(Ref<StyleProperties>&& properties)
252     : StyleRuleBase(Page)
253     , m_properties(WTFMove(properties))
254 {
255 }
256
257 StyleRulePage::StyleRulePage(const StyleRulePage& o)
258     : StyleRuleBase(o)
259     , m_properties(o.m_properties->mutableCopy())
260     , m_selectorList(o.m_selectorList)
261 {
262 }
263
264 StyleRulePage::~StyleRulePage() = default;
265
266 MutableStyleProperties& StyleRulePage::mutableProperties()
267 {
268     if (!is<MutableStyleProperties>(m_properties.get()))
269         m_properties = m_properties->mutableCopy();
270     return downcast<MutableStyleProperties>(m_properties.get());
271 }
272
273 StyleRuleFontFace::StyleRuleFontFace(Ref<StyleProperties>&& properties)
274     : StyleRuleBase(FontFace)
275     , m_properties(WTFMove(properties))
276 {
277 }
278
279 StyleRuleFontFace::StyleRuleFontFace(const StyleRuleFontFace& o)
280     : StyleRuleBase(o)
281     , m_properties(o.m_properties->mutableCopy())
282 {
283 }
284
285 StyleRuleFontFace::~StyleRuleFontFace() = default;
286
287 MutableStyleProperties& StyleRuleFontFace::mutableProperties()
288 {
289     if (!is<MutableStyleProperties>(m_properties.get()))
290         m_properties = m_properties->mutableCopy();
291     return downcast<MutableStyleProperties>(m_properties.get());
292 }
293
294 DeferredStyleGroupRuleList::DeferredStyleGroupRuleList(const CSSParserTokenRange& range, CSSDeferredParser& parser)
295     : m_parser(parser)
296 {
297     size_t length = range.end() - range.begin();
298     m_tokens.reserveCapacity(length);
299     m_tokens.append(range.begin(), length);
300 }
301
302 void DeferredStyleGroupRuleList::parseDeferredRules(Vector<RefPtr<StyleRuleBase>>& childRules)
303 {
304     m_parser->parseRuleList(m_tokens, childRules);
305 }
306
307 void DeferredStyleGroupRuleList::parseDeferredKeyframes(StyleRuleKeyframes& keyframesRule)
308 {
309     m_parser->parseKeyframeList(m_tokens, keyframesRule);
310 }
311     
312 StyleRuleGroup::StyleRuleGroup(Type type, Vector<RefPtr<StyleRuleBase>>& adoptRule)
313     : StyleRuleBase(type)
314 {
315     m_childRules.swap(adoptRule);
316 }
317
318 StyleRuleGroup::StyleRuleGroup(Type type, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
319     : StyleRuleBase(type)
320     , m_deferredRules(WTFMove(deferredRules))
321 {
322 }
323
324 StyleRuleGroup::StyleRuleGroup(const StyleRuleGroup& o)
325     : StyleRuleBase(o)
326 {
327     m_childRules.reserveInitialCapacity(o.childRules().size());
328     for (auto& childRule : o.childRules())
329         m_childRules.uncheckedAppend(childRule->copy());
330 }
331
332 const Vector<RefPtr<StyleRuleBase>>& StyleRuleGroup::childRules() const
333 {
334     parseDeferredRulesIfNeeded();
335     return m_childRules;
336 }
337
338 void StyleRuleGroup::wrapperInsertRule(unsigned index, Ref<StyleRuleBase>&& rule)
339 {
340     parseDeferredRulesIfNeeded();
341     m_childRules.insert(index, WTFMove(rule));
342 }
343     
344 void StyleRuleGroup::wrapperRemoveRule(unsigned index)
345 {
346     parseDeferredRulesIfNeeded();
347     m_childRules.remove(index);
348 }
349
350 void StyleRuleGroup::parseDeferredRulesIfNeeded() const
351 {
352     if (!m_deferredRules)
353         return;
354     
355     m_deferredRules->parseDeferredRules(m_childRules);
356     m_deferredRules = nullptr;
357 }
358     
359 StyleRuleMedia::StyleRuleMedia(Ref<MediaQuerySet>&& media, Vector<RefPtr<StyleRuleBase>>& adoptRules)
360     : StyleRuleGroup(Media, adoptRules)
361     , m_mediaQueries(WTFMove(media))
362 {
363 }
364
365 StyleRuleMedia::StyleRuleMedia(Ref<MediaQuerySet>&& media, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
366     : StyleRuleGroup(Media, WTFMove(deferredRules))
367     , m_mediaQueries(WTFMove(media))
368 {
369 }
370
371 StyleRuleMedia::StyleRuleMedia(const StyleRuleMedia& o)
372     : StyleRuleGroup(o)
373 {
374     if (o.m_mediaQueries)
375         m_mediaQueries = o.m_mediaQueries->copy();
376 }
377
378
379 StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>& adoptRules)
380     : StyleRuleGroup(Supports, adoptRules)
381     , m_conditionText(conditionText)
382     , m_conditionIsSupported(conditionIsSupported)
383 {
384 }
385
386 StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported,  std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
387     : StyleRuleGroup(Supports, WTFMove(deferredRules))
388     , m_conditionText(conditionText)
389     , m_conditionIsSupported(conditionIsSupported)
390 {
391 }
392
393 StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& o)
394     : StyleRuleGroup(o)
395     , m_conditionText(o.m_conditionText)
396     , m_conditionIsSupported(o.m_conditionIsSupported)
397 {
398 }
399
400 #if ENABLE(CSS_DEVICE_ADAPTATION)
401 StyleRuleViewport::StyleRuleViewport(Ref<StyleProperties>&& properties)
402     : StyleRuleBase(Viewport)
403     , m_properties(WTFMove(properties))
404 {
405 }
406
407 StyleRuleViewport::StyleRuleViewport(const StyleRuleViewport& o)
408     : StyleRuleBase(o)
409     , m_properties(o.m_properties->mutableCopy())
410 {
411 }
412
413 StyleRuleViewport::~StyleRuleViewport() = default;
414
415 MutableStyleProperties& StyleRuleViewport::mutableProperties()
416 {
417     if (!m_properties->isMutable())
418         m_properties = m_properties->mutableCopy();
419     return static_cast<MutableStyleProperties&>(m_properties.get());
420 }
421 #endif // ENABLE(CSS_DEVICE_ADAPTATION)
422
423 StyleRuleCharset::StyleRuleCharset()
424     : StyleRuleBase(Charset)
425 {
426 }
427
428 StyleRuleCharset::StyleRuleCharset(const StyleRuleCharset& o)
429     : StyleRuleBase(o)
430 {
431 }
432
433 StyleRuleCharset::~StyleRuleCharset() = default;
434
435 StyleRuleNamespace::StyleRuleNamespace(AtomicString prefix, AtomicString uri)
436     : StyleRuleBase(Namespace)
437     , m_prefix(prefix)
438     , m_uri(uri)
439 {
440 }
441
442 StyleRuleNamespace::StyleRuleNamespace(const StyleRuleNamespace& o)
443     : StyleRuleBase(o)
444     , m_prefix(o.m_prefix)
445     , m_uri(o.m_uri)
446 {
447 }
448
449 StyleRuleNamespace::~StyleRuleNamespace() = default;
450
451 } // namespace WebCore