1/*
2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
4 * Copyright (C) 2002, 2006, 2008, 2012, 2013 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#pragma once
23
24#include "CSSSelectorList.h"
25#include "CompiledSelector.h"
26#include "StyleProperties.h"
27#include <wtf/RefPtr.h>
28#include <wtf/TypeCasts.h>
29#include <wtf/UniqueArray.h>
30
31namespace WebCore {
32
33class CSSRule;
34class CSSStyleRule;
35class CSSStyleSheet;
36class MediaQuerySet;
37class MutableStyleProperties;
38class StyleRuleKeyframe;
39class StyleProperties;
40class StyleRuleKeyframes;
41
42class StyleRuleBase : public WTF::RefCountedBase {
43 WTF_MAKE_FAST_ALLOCATED;
44public:
45 enum Type {
46 Unknown, // Not used.
47 Style,
48 Charset, // Not used. These are internally strings owned by the style sheet.
49 Import,
50 Media,
51 FontFace,
52 Page,
53 Keyframes,
54 Keyframe, // Not used. These are internally non-rule StyleRuleKeyframe objects.
55 Namespace,
56 Supports = 12,
57#if ENABLE(CSS_DEVICE_ADAPTATION)
58 Viewport = 15,
59#endif
60 };
61
62 Type type() const { return static_cast<Type>(m_type); }
63
64 bool isCharsetRule() const { return type() == Charset; }
65 bool isFontFaceRule() const { return type() == FontFace; }
66 bool isKeyframesRule() const { return type() == Keyframes; }
67 bool isKeyframeRule() const { return type() == Keyframe; }
68 bool isNamespaceRule() const { return type() == Namespace; }
69 bool isMediaRule() const { return type() == Media; }
70 bool isPageRule() const { return type() == Page; }
71 bool isStyleRule() const { return type() == Style; }
72 bool isSupportsRule() const { return type() == Supports; }
73#if ENABLE(CSS_DEVICE_ADAPTATION)
74 bool isViewportRule() const { return type() == Viewport; }
75#endif
76 bool isImportRule() const { return type() == Import; }
77
78 Ref<StyleRuleBase> copy() const;
79
80 void deref()
81 {
82 if (derefBase())
83 destroy();
84 }
85
86 // FIXME: There shouldn't be any need for the null parent version.
87 Ref<CSSRule> createCSSOMWrapper(CSSStyleSheet* parentSheet = nullptr) const;
88 Ref<CSSRule> createCSSOMWrapper(CSSRule* parentRule) const;
89
90protected:
91 StyleRuleBase(Type type, bool hasDocumentSecurityOrigin = false)
92 : m_type(type)
93 , m_hasDocumentSecurityOrigin(hasDocumentSecurityOrigin)
94 {
95 }
96
97 StyleRuleBase(const StyleRuleBase& o)
98 : WTF::RefCountedBase()
99 , m_type(o.m_type)
100 , m_hasDocumentSecurityOrigin(o.m_hasDocumentSecurityOrigin)
101 {
102 }
103
104 ~StyleRuleBase() = default;
105
106 bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; }
107
108private:
109 WEBCORE_EXPORT void destroy();
110
111 Ref<CSSRule> createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const;
112
113 unsigned m_type : 5;
114 // This is only needed to support getMatchedCSSRules.
115 unsigned m_hasDocumentSecurityOrigin : 1;
116};
117
118class StyleRule final : public StyleRuleBase {
119 WTF_MAKE_FAST_ALLOCATED;
120public:
121 static Ref<StyleRule> create(Ref<StylePropertiesBase>&& properties, bool hasDocumentSecurityOrigin, CSSSelectorList&& selectors)
122 {
123 return adoptRef(*new StyleRule(WTFMove(properties), hasDocumentSecurityOrigin, WTFMove(selectors)));
124 }
125
126 ~StyleRule();
127
128 const CSSSelectorList& selectorList() const { return m_selectorList; }
129
130 const StyleProperties& properties() const;
131 MutableStyleProperties& mutableProperties();
132 const StyleProperties* propertiesWithoutDeferredParsing() const;
133
134 using StyleRuleBase::hasDocumentSecurityOrigin;
135
136 void wrapperAdoptSelectorList(CSSSelectorList&& selectors)
137 {
138 m_selectorList = WTFMove(selectors);
139#if ENABLE(CSS_SELECTOR_JIT)
140 m_compiledSelectors = nullptr;
141#endif
142 }
143
144 Ref<StyleRule> copy() const { return adoptRef(*new StyleRule(*this)); }
145
146 Vector<RefPtr<StyleRule>> splitIntoMultipleRulesWithMaximumSelectorComponentCount(unsigned) const;
147
148#if ENABLE(CSS_SELECTOR_JIT)
149 CompiledSelector& compiledSelectorForListIndex(unsigned index)
150 {
151 if (!m_compiledSelectors)
152 m_compiledSelectors = makeUniqueArray<CompiledSelector>(m_selectorList.listSize());
153 return m_compiledSelectors[index];
154 }
155 void releaseCompiledSelectors() const
156 {
157 m_compiledSelectors = nullptr;
158 }
159#endif
160
161 static unsigned averageSizeInBytes();
162
163private:
164 StyleRule(Ref<StylePropertiesBase>&&, bool hasDocumentSecurityOrigin, CSSSelectorList&&);
165 StyleRule(const StyleRule&);
166
167 static Ref<StyleRule> createForSplitting(const Vector<const CSSSelector*>&, Ref<StyleProperties>&&, bool hasDocumentSecurityOrigin);
168
169 mutable Ref<StylePropertiesBase> m_properties;
170 CSSSelectorList m_selectorList;
171
172#if ENABLE(CSS_SELECTOR_JIT)
173 mutable UniqueArray<CompiledSelector> m_compiledSelectors;
174#endif
175};
176
177inline const StyleProperties* StyleRule::propertiesWithoutDeferredParsing() const
178{
179 return m_properties->type() != DeferredPropertiesType ? &downcast<StyleProperties>(m_properties.get()) : nullptr;
180}
181
182class StyleRuleFontFace final : public StyleRuleBase {
183public:
184 static Ref<StyleRuleFontFace> create(Ref<StyleProperties>&& properties) { return adoptRef(*new StyleRuleFontFace(WTFMove(properties))); }
185
186 ~StyleRuleFontFace();
187
188 const StyleProperties& properties() const { return m_properties; }
189 MutableStyleProperties& mutableProperties();
190
191 Ref<StyleRuleFontFace> copy() const { return adoptRef(*new StyleRuleFontFace(*this)); }
192
193private:
194 explicit StyleRuleFontFace(Ref<StyleProperties>&&);
195 StyleRuleFontFace(const StyleRuleFontFace&);
196
197 Ref<StyleProperties> m_properties;
198};
199
200class StyleRulePage final : public StyleRuleBase {
201public:
202 static Ref<StyleRulePage> create(Ref<StyleProperties>&& properties, CSSSelectorList&& selectors) { return adoptRef(*new StyleRulePage(WTFMove(properties), WTFMove(selectors))); }
203
204 ~StyleRulePage();
205
206 const CSSSelector* selector() const { return m_selectorList.first(); }
207 const StyleProperties& properties() const { return m_properties; }
208 MutableStyleProperties& mutableProperties();
209
210 void wrapperAdoptSelectorList(CSSSelectorList&& selectors) { m_selectorList = WTFMove(selectors); }
211
212 Ref<StyleRulePage> copy() const { return adoptRef(*new StyleRulePage(*this)); }
213
214private:
215 explicit StyleRulePage(Ref<StyleProperties>&&, CSSSelectorList&&);
216 StyleRulePage(const StyleRulePage&);
217
218 Ref<StyleProperties> m_properties;
219 CSSSelectorList m_selectorList;
220};
221
222class DeferredStyleGroupRuleList final {
223 WTF_MAKE_FAST_ALLOCATED;
224public:
225 DeferredStyleGroupRuleList(const CSSParserTokenRange&, CSSDeferredParser&);
226
227 void parseDeferredRules(Vector<RefPtr<StyleRuleBase>>&);
228 void parseDeferredKeyframes(StyleRuleKeyframes&);
229
230private:
231 Vector<CSSParserToken> m_tokens;
232 Ref<CSSDeferredParser> m_parser;
233};
234
235class StyleRuleGroup : public StyleRuleBase {
236public:
237 const Vector<RefPtr<StyleRuleBase>>& childRules() const;
238 const Vector<RefPtr<StyleRuleBase>>* childRulesWithoutDeferredParsing() const;
239
240 void wrapperInsertRule(unsigned, Ref<StyleRuleBase>&&);
241 void wrapperRemoveRule(unsigned);
242
243protected:
244 StyleRuleGroup(Type, Vector<RefPtr<StyleRuleBase>>&);
245 StyleRuleGroup(Type, std::unique_ptr<DeferredStyleGroupRuleList>&&);
246 StyleRuleGroup(const StyleRuleGroup&);
247
248private:
249 void parseDeferredRulesIfNeeded() const;
250
251 mutable Vector<RefPtr<StyleRuleBase>> m_childRules;
252 mutable std::unique_ptr<DeferredStyleGroupRuleList> m_deferredRules;
253};
254
255inline const Vector<RefPtr<StyleRuleBase>>* StyleRuleGroup::childRulesWithoutDeferredParsing() const
256{
257 return !m_deferredRules ? &m_childRules : nullptr;
258}
259
260class StyleRuleMedia final : public StyleRuleGroup {
261public:
262 static Ref<StyleRuleMedia> create(Ref<MediaQuerySet>&& media, Vector<RefPtr<StyleRuleBase>>& adoptRules)
263 {
264 return adoptRef(*new StyleRuleMedia(WTFMove(media), adoptRules));
265 }
266
267 static Ref<StyleRuleMedia> create(Ref<MediaQuerySet>&& media, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredChildRules)
268 {
269 return adoptRef(*new StyleRuleMedia(WTFMove(media), WTFMove(deferredChildRules)));
270 }
271
272 MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); }
273
274 Ref<StyleRuleMedia> copy() const { return adoptRef(*new StyleRuleMedia(*this)); }
275
276private:
277 StyleRuleMedia(Ref<MediaQuerySet>&&, Vector<RefPtr<StyleRuleBase>>& adoptRules);
278 StyleRuleMedia(Ref<MediaQuerySet>&&, std::unique_ptr<DeferredStyleGroupRuleList>&&);
279 StyleRuleMedia(const StyleRuleMedia&);
280
281 RefPtr<MediaQuerySet> m_mediaQueries;
282};
283
284class StyleRuleSupports final : public StyleRuleGroup {
285public:
286 static Ref<StyleRuleSupports> create(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>& adoptRules)
287 {
288 return adoptRef(*new StyleRuleSupports(conditionText, conditionIsSupported, adoptRules));
289 }
290
291 static Ref<StyleRuleSupports> create(const String& conditionText, bool conditionIsSupported, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredChildRules)
292 {
293 return adoptRef(*new StyleRuleSupports(conditionText, conditionIsSupported, WTFMove(deferredChildRules)));
294 }
295
296 String conditionText() const { return m_conditionText; }
297 bool conditionIsSupported() const { return m_conditionIsSupported; }
298 Ref<StyleRuleSupports> copy() const { return adoptRef(*new StyleRuleSupports(*this)); }
299
300private:
301 StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>& adoptRules);
302 StyleRuleSupports(const String& conditionText, bool conditionIsSupported, std::unique_ptr<DeferredStyleGroupRuleList>&&);
303
304 StyleRuleSupports(const StyleRuleSupports&);
305
306 String m_conditionText;
307 bool m_conditionIsSupported;
308};
309
310#if ENABLE(CSS_DEVICE_ADAPTATION)
311class StyleRuleViewport final : public StyleRuleBase {
312public:
313 static Ref<StyleRuleViewport> create(Ref<StyleProperties>&& properties) { return adoptRef(*new StyleRuleViewport(WTFMove(properties))); }
314
315 ~StyleRuleViewport();
316
317 const StyleProperties& properties() const { return m_properties.get(); }
318 MutableStyleProperties& mutableProperties();
319
320 Ref<StyleRuleViewport> copy() const { return adoptRef(*new StyleRuleViewport(*this)); }
321
322private:
323 explicit StyleRuleViewport(Ref<StyleProperties>&&);
324 StyleRuleViewport(const StyleRuleViewport&);
325
326 Ref<StyleProperties> m_properties;
327};
328#endif // ENABLE(CSS_DEVICE_ADAPTATION)
329
330// This is only used by the CSS parser.
331class StyleRuleCharset final : public StyleRuleBase {
332public:
333 static Ref<StyleRuleCharset> create() { return adoptRef(*new StyleRuleCharset()); }
334
335 ~StyleRuleCharset();
336
337 Ref<StyleRuleCharset> copy() const { return adoptRef(*new StyleRuleCharset(*this)); }
338
339private:
340 explicit StyleRuleCharset();
341 StyleRuleCharset(const StyleRuleCharset&);
342};
343
344class StyleRuleNamespace final : public StyleRuleBase {
345public:
346 static Ref<StyleRuleNamespace> create(AtomString prefix, AtomString uri)
347 {
348 return adoptRef(*new StyleRuleNamespace(prefix, uri));
349 }
350
351 ~StyleRuleNamespace();
352
353 Ref<StyleRuleNamespace> copy() const { return adoptRef(*new StyleRuleNamespace(*this)); }
354
355 AtomString prefix() const { return m_prefix; }
356 AtomString uri() const { return m_uri; }
357
358private:
359 StyleRuleNamespace(AtomString prefix, AtomString uri);
360 StyleRuleNamespace(const StyleRuleNamespace&);
361
362 AtomString m_prefix;
363 AtomString m_uri;
364};
365
366} // namespace WebCore
367
368SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRule)
369 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isStyleRule(); }
370SPECIALIZE_TYPE_TRAITS_END()
371
372SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleFontFace)
373 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isFontFaceRule(); }
374SPECIALIZE_TYPE_TRAITS_END()
375
376SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleMedia)
377 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isMediaRule(); }
378SPECIALIZE_TYPE_TRAITS_END()
379
380SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRulePage)
381 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isPageRule(); }
382SPECIALIZE_TYPE_TRAITS_END()
383
384SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleSupports)
385 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isSupportsRule(); }
386SPECIALIZE_TYPE_TRAITS_END()
387
388#if ENABLE(CSS_DEVICE_ADAPTATION)
389SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleViewport)
390 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isViewportRule(); }
391SPECIALIZE_TYPE_TRAITS_END()
392#endif // ENABLE(CSS_DEVICE_ADAPTATION)
393
394SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleNamespace)
395 static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isNamespaceRule(); }
396SPECIALIZE_TYPE_TRAITS_END()
397
398SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleKeyframe)
399static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isKeyframeRule(); }
400SPECIALIZE_TYPE_TRAITS_END()
401
402SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleCharset)
403static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isCharsetRule(); }
404SPECIALIZE_TYPE_TRAITS_END()
405
406