1ee65244ff4faf1ca6b1aafc692d4657d4106438
[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 "CSSUnknownRule.h"
36 #include "MediaList.h"
37 #include "StyleProperties.h"
38 #include "StyleRuleImport.h"
39 #include "WebKitCSSRegionRule.h"
40 #include "WebKitCSSViewportRule.h"
41
42 namespace WebCore {
43
44 struct SameSizeAsStyleRuleBase : public WTF::RefCountedBase {
45     unsigned bitfields : 5;
46 };
47
48 COMPILE_ASSERT(sizeof(StyleRuleBase) == sizeof(SameSizeAsStyleRuleBase), StyleRuleBase_should_stay_small);
49
50 RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet) const
51 {
52     return createCSSOMWrapper(parentSheet, nullptr);
53 }
54
55 RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSRule* parentRule) const
56
57     return createCSSOMWrapper(nullptr, parentRule);
58 }
59
60 void StyleRuleBase::destroy()
61 {
62     switch (type()) {
63     case Style:
64         delete downcast<StyleRule>(this);
65         return;
66     case Page:
67         delete downcast<StyleRulePage>(this);
68         return;
69     case FontFace:
70         delete downcast<StyleRuleFontFace>(this);
71         return;
72     case Media:
73         delete downcast<StyleRuleMedia>(this);
74         return;
75     case Supports:
76         delete downcast<StyleRuleSupports>(this);
77         return;
78 #if ENABLE(CSS_REGIONS)
79     case Region:
80         delete downcast<StyleRuleRegion>(this);
81         return;
82 #endif
83     case Import:
84         delete downcast<StyleRuleImport>(this);
85         return;
86     case Keyframes:
87         delete downcast<StyleRuleKeyframes>(this);
88         return;
89 #if ENABLE(CSS_DEVICE_ADAPTATION)
90     case Viewport:
91         delete downcast<StyleRuleViewport>(this);
92         return;
93 #endif
94     case Namespace:
95         delete downcast<StyleRuleNamespace>(this);
96         return;
97     case Keyframe:
98         delete downcast<StyleKeyframe>(this);
99         return;
100     case Charset:
101         delete downcast<StyleRuleCharset>(this);
102         return;
103     case Unknown:
104 #if !ENABLE(CSS_REGIONS)
105     case Region:
106 #endif
107         ASSERT_NOT_REACHED();
108         return;
109     }
110     ASSERT_NOT_REACHED();
111 }
112
113 Ref<StyleRuleBase> StyleRuleBase::copy() const
114 {
115     switch (type()) {
116     case Style:
117         return downcast<StyleRule>(*this).copy();
118     case Page:
119         return downcast<StyleRulePage>(*this).copy();
120     case FontFace:
121         return downcast<StyleRuleFontFace>(*this).copy();
122     case Media:
123         return downcast<StyleRuleMedia>(*this).copy();
124     case Supports:
125         return downcast<StyleRuleSupports>(*this).copy();
126 #if ENABLE(CSS_REGIONS)
127     case Region:
128         return downcast<StyleRuleRegion>(*this).copy();
129 #endif
130     case Keyframes:
131         return downcast<StyleRuleKeyframes>(*this).copy();
132 #if ENABLE(CSS_DEVICE_ADAPTATION)
133     case Viewport:
134         return downcast<StyleRuleViewport>(*this).copy();
135 #endif
136     case Import:
137     case Namespace:
138         // FIXME: Copy import and namespace rules.
139         break;
140     case Unknown:
141     case Charset:
142     case Keyframe:
143 #if !ENABLE(CSS_REGIONS)
144     case Region:
145 #endif
146         break;
147     }
148     CRASH();
149     // HACK: EFL won't build without this (old GCC with crappy -Werror=return-type)
150     return Ref<StyleRuleBase>(*static_cast<StyleRuleBase*>(nullptr));
151 }
152
153 RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const
154 {
155     RefPtr<CSSRule> rule;
156     StyleRuleBase& self = const_cast<StyleRuleBase&>(*this);
157     switch (type()) {
158     case Style:
159         rule = CSSStyleRule::create(downcast<StyleRule>(self), parentSheet);
160         break;
161     case Page:
162         rule = CSSPageRule::create(downcast<StyleRulePage>(self), parentSheet);
163         break;
164     case FontFace:
165         rule = CSSFontFaceRule::create(downcast<StyleRuleFontFace>(self), parentSheet);
166         break;
167     case Media:
168         rule = CSSMediaRule::create(downcast<StyleRuleMedia>(self), parentSheet);
169         break;
170     case Supports:
171         rule = CSSSupportsRule::create(downcast<StyleRuleSupports>(self), parentSheet);
172         break;
173 #if ENABLE(CSS_REGIONS)
174     case Region:
175         rule = WebKitCSSRegionRule::create(downcast<StyleRuleRegion>(self), parentSheet);
176         break;
177 #endif
178     case Import:
179         rule = CSSImportRule::create(downcast<StyleRuleImport>(self), parentSheet);
180         break;
181     case Keyframes:
182         rule = CSSKeyframesRule::create(downcast<StyleRuleKeyframes>(self), parentSheet);
183         break;
184 #if ENABLE(CSS_DEVICE_ADAPTATION)
185     case Viewport:
186         rule = WebKitCSSViewportRule::create(downcast<StyleRuleViewport>(self), parentSheet);
187         break;
188 #endif
189     case Namespace:
190         rule = CSSNamespaceRule::create(downcast<StyleRuleNamespace>(self), parentSheet);
191         break;
192     case Unknown:
193     case Charset:
194     case Keyframe:
195 #if !ENABLE(CSS_REGIONS)
196     case Region:
197 #endif
198         ASSERT_NOT_REACHED();
199         return nullptr;
200     }
201     if (parentRule)
202         rule->setParentRule(parentRule);
203     return rule;
204 }
205
206 unsigned StyleRule::averageSizeInBytes()
207 {
208     return sizeof(StyleRule) + sizeof(CSSSelector) + StyleProperties::averageSizeInBytes();
209 }
210
211 StyleRule::StyleRule(Ref<StylePropertiesBase>&& properties)
212     : StyleRuleBase(Style)
213     , m_properties(WTFMove(properties))
214 {
215 }
216
217 StyleRule::StyleRule(const StyleRule& o)
218     : StyleRuleBase(o)
219     , m_properties(o.properties().mutableCopy())
220     , m_selectorList(o.m_selectorList)
221 {
222 }
223
224 StyleRule::~StyleRule()
225 {
226 }
227
228 const StyleProperties& StyleRule::properties() const
229 {
230     if (m_properties->type() == DeferredPropertiesType)
231         m_properties = downcast<DeferredStyleProperties>(m_properties.get()).parseDeferredProperties();
232     return downcast<StyleProperties>(m_properties.get());
233 }
234
235 MutableStyleProperties& StyleRule::mutableProperties()
236 {
237     if (!is<MutableStyleProperties>(m_properties.get()))
238         m_properties = properties().mutableCopy();
239     return downcast<MutableStyleProperties>(m_properties.get());
240 }
241
242 Ref<StyleRule> StyleRule::create(const Vector<const CSSSelector*>& selectors, Ref<StyleProperties>&& properties)
243 {
244     ASSERT_WITH_SECURITY_IMPLICATION(!selectors.isEmpty());
245     CSSSelector* selectorListArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * selectors.size()));
246     for (unsigned i = 0; i < selectors.size(); ++i)
247         new (NotNull, &selectorListArray[i]) CSSSelector(*selectors.at(i));
248     selectorListArray[selectors.size() - 1].setLastInSelectorList();
249     auto rule = StyleRule::create(WTFMove(properties));
250     rule.get().parserAdoptSelectorArray(selectorListArray);
251     return rule;
252 }
253
254 Vector<RefPtr<StyleRule>> StyleRule::splitIntoMultipleRulesWithMaximumSelectorComponentCount(unsigned maxCount) const
255 {
256     ASSERT(selectorList().componentCount() > maxCount);
257
258     Vector<RefPtr<StyleRule>> rules;
259     Vector<const CSSSelector*> componentsSinceLastSplit;
260
261     for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(selector)) {
262         Vector<const CSSSelector*, 8> componentsInThisSelector;
263         for (const CSSSelector* component = selector; component; component = component->tagHistory())
264             componentsInThisSelector.append(component);
265
266         if (componentsInThisSelector.size() + componentsSinceLastSplit.size() > maxCount && !componentsSinceLastSplit.isEmpty()) {
267             rules.append(create(componentsSinceLastSplit, const_cast<StyleProperties&>(properties())));
268             componentsSinceLastSplit.clear();
269         }
270
271         componentsSinceLastSplit.appendVector(componentsInThisSelector);
272     }
273
274     if (!componentsSinceLastSplit.isEmpty())
275         rules.append(create(componentsSinceLastSplit, const_cast<StyleProperties&>(properties())));
276
277     return rules;
278 }
279
280 StyleRulePage::StyleRulePage(Ref<StyleProperties>&& properties)
281     : StyleRuleBase(Page)
282     , m_properties(WTFMove(properties))
283 {
284 }
285
286 StyleRulePage::StyleRulePage(const StyleRulePage& o)
287     : StyleRuleBase(o)
288     , m_properties(o.m_properties->mutableCopy())
289     , m_selectorList(o.m_selectorList)
290 {
291 }
292
293 StyleRulePage::~StyleRulePage()
294 {
295 }
296
297 MutableStyleProperties& StyleRulePage::mutableProperties()
298 {
299     if (!is<MutableStyleProperties>(m_properties.get()))
300         m_properties = m_properties->mutableCopy();
301     return downcast<MutableStyleProperties>(m_properties.get());
302 }
303
304 StyleRuleFontFace::StyleRuleFontFace(Ref<StyleProperties>&& properties)
305     : StyleRuleBase(FontFace)
306     , m_properties(WTFMove(properties))
307 {
308 }
309
310 StyleRuleFontFace::StyleRuleFontFace(const StyleRuleFontFace& o)
311     : StyleRuleBase(o)
312     , m_properties(o.m_properties->mutableCopy())
313 {
314 }
315
316 StyleRuleFontFace::~StyleRuleFontFace()
317 {
318 }
319
320 MutableStyleProperties& StyleRuleFontFace::mutableProperties()
321 {
322     if (!is<MutableStyleProperties>(m_properties.get()))
323         m_properties = m_properties->mutableCopy();
324     return downcast<MutableStyleProperties>(m_properties.get());
325 }
326
327 DeferredStyleGroupRuleList::DeferredStyleGroupRuleList(const CSSParserTokenRange& range, CSSDeferredParser& parser)
328     : m_parser(parser)
329 {
330     size_t length = range.end() - range.begin();
331     m_tokens.reserveCapacity(length);
332     m_tokens.append(range.begin(), length);
333 }
334
335 void DeferredStyleGroupRuleList::parseDeferredRules(Vector<RefPtr<StyleRuleBase>>& childRules)
336 {
337     m_parser->parseRuleList(m_tokens, childRules);
338 }
339
340 void DeferredStyleGroupRuleList::parseDeferredKeyframes(StyleRuleKeyframes& keyframesRule)
341 {
342     m_parser->parseKeyframeList(m_tokens, keyframesRule);
343 }
344     
345 StyleRuleGroup::StyleRuleGroup(Type type, Vector<RefPtr<StyleRuleBase>>& adoptRule)
346     : StyleRuleBase(type)
347 {
348     m_childRules.swap(adoptRule);
349 }
350
351 StyleRuleGroup::StyleRuleGroup(Type type, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
352     : StyleRuleBase(type)
353     , m_deferredRules(WTFMove(deferredRules))
354 {
355 }
356
357 StyleRuleGroup::StyleRuleGroup(const StyleRuleGroup& o)
358     : StyleRuleBase(o)
359 {
360     m_childRules.reserveInitialCapacity(o.childRules().size());
361     for (auto& childRule : o.childRules())
362         m_childRules.uncheckedAppend(childRule->copy());
363 }
364
365 const Vector<RefPtr<StyleRuleBase>>& StyleRuleGroup::childRules() const
366 {
367     parseDeferredRulesIfNeeded();
368     return m_childRules;
369 }
370
371 void StyleRuleGroup::wrapperInsertRule(unsigned index, Ref<StyleRuleBase>&& rule)
372 {
373     parseDeferredRulesIfNeeded();
374     m_childRules.insert(index, WTFMove(rule));
375 }
376     
377 void StyleRuleGroup::wrapperRemoveRule(unsigned index)
378 {
379     parseDeferredRulesIfNeeded();
380     m_childRules.remove(index);
381 }
382
383 void StyleRuleGroup::parseDeferredRulesIfNeeded() const
384 {
385     if (!m_deferredRules)
386         return;
387     
388     m_deferredRules->parseDeferredRules(m_childRules);
389     m_deferredRules = nullptr;
390 }
391     
392 StyleRuleMedia::StyleRuleMedia(Ref<MediaQuerySet>&& media, Vector<RefPtr<StyleRuleBase>>& adoptRules)
393     : StyleRuleGroup(Media, adoptRules)
394     , m_mediaQueries(WTFMove(media))
395 {
396 }
397
398 StyleRuleMedia::StyleRuleMedia(Ref<MediaQuerySet>&& media, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
399     : StyleRuleGroup(Media, WTFMove(deferredRules))
400     , m_mediaQueries(WTFMove(media))
401 {
402 }
403
404 StyleRuleMedia::StyleRuleMedia(const StyleRuleMedia& o)
405     : StyleRuleGroup(o)
406 {
407     if (o.m_mediaQueries)
408         m_mediaQueries = o.m_mediaQueries->copy();
409 }
410
411
412 StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>& adoptRules)
413     : StyleRuleGroup(Supports, adoptRules)
414     , m_conditionText(conditionText)
415     , m_conditionIsSupported(conditionIsSupported)
416 {
417 }
418
419 StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported,  std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules)
420     : StyleRuleGroup(Supports, WTFMove(deferredRules))
421     , m_conditionText(conditionText)
422     , m_conditionIsSupported(conditionIsSupported)
423 {
424 }
425
426 StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& o)
427     : StyleRuleGroup(o)
428     , m_conditionText(o.m_conditionText)
429     , m_conditionIsSupported(o.m_conditionIsSupported)
430 {
431 }
432
433 StyleRuleRegion::StyleRuleRegion(Vector<std::unique_ptr<CSSParserSelector>>* selectors, Vector<RefPtr<StyleRuleBase>>& adoptRules)
434     : StyleRuleGroup(Region, adoptRules)
435 {
436     m_selectorList.adoptSelectorVector(*selectors);
437 }
438
439 StyleRuleRegion::StyleRuleRegion(CSSSelectorList& selectors, Vector<RefPtr<StyleRuleBase>>& adoptRules)
440     : StyleRuleGroup(Region, adoptRules)
441     , m_selectorList(WTFMove(selectors))
442 {
443 }
444
445 StyleRuleRegion::StyleRuleRegion(const StyleRuleRegion& o)
446     : StyleRuleGroup(o)
447     , m_selectorList(o.m_selectorList)
448 {
449 }
450
451
452 #if ENABLE(CSS_DEVICE_ADAPTATION)
453 StyleRuleViewport::StyleRuleViewport(Ref<StyleProperties>&& properties)
454     : StyleRuleBase(Viewport, 0)
455     , m_properties(WTFMove(properties))
456 {
457 }
458
459 StyleRuleViewport::StyleRuleViewport(const StyleRuleViewport& o)
460     : StyleRuleBase(o)
461     , m_properties(o.m_properties->mutableCopy())
462 {
463 }
464
465 StyleRuleViewport::~StyleRuleViewport()
466 {
467 }
468
469 MutableStyleProperties& StyleRuleViewport::mutableProperties()
470 {
471     if (!m_properties->isMutable())
472         m_properties = m_properties->mutableCopy();
473     return static_cast<MutableStyleProperties&>(m_properties.get());
474 }
475 #endif // ENABLE(CSS_DEVICE_ADAPTATION)
476
477 StyleRuleCharset::StyleRuleCharset()
478     : StyleRuleBase(Charset)
479 {
480 }
481
482 StyleRuleCharset::StyleRuleCharset(const StyleRuleCharset& o)
483     : StyleRuleBase(o)
484 {
485 }
486
487 StyleRuleCharset::~StyleRuleCharset()
488 {
489 }
490
491 StyleRuleNamespace::StyleRuleNamespace(AtomicString prefix, AtomicString uri)
492     : StyleRuleBase(Namespace)
493     , m_prefix(prefix)
494     , m_uri(uri)
495 {
496 }
497
498 StyleRuleNamespace::StyleRuleNamespace(const StyleRuleNamespace& o)
499     : StyleRuleBase(o)
500     , m_prefix(o.m_prefix)
501     , m_uri(o.m_uri)
502 {
503 }
504
505 StyleRuleNamespace::~StyleRuleNamespace()
506 {
507 }
508
509 } // namespace WebCore