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 | Ref<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet) const |
49 | { |
50 | return createCSSOMWrapper(parentSheet, nullptr); |
51 | } |
52 | |
53 | Ref<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 | Ref<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 | break; |
173 | } |
174 | ASSERT(rule); |
175 | |
176 | if (parentRule) |
177 | rule->setParentRule(parentRule); |
178 | return rule.releaseNonNull(); |
179 | } |
180 | |
181 | unsigned StyleRule::averageSizeInBytes() |
182 | { |
183 | return sizeof(StyleRule) + sizeof(CSSSelector) + StyleProperties::averageSizeInBytes(); |
184 | } |
185 | |
186 | StyleRule::StyleRule(Ref<StylePropertiesBase>&& properties, bool hasDocumentSecurityOrigin, CSSSelectorList&& selectors) |
187 | : StyleRuleBase(Style, hasDocumentSecurityOrigin) |
188 | , m_properties(WTFMove(properties)) |
189 | , m_selectorList(WTFMove(selectors)) |
190 | { |
191 | } |
192 | |
193 | StyleRule::StyleRule(const StyleRule& o) |
194 | : StyleRuleBase(o) |
195 | , m_properties(o.properties().mutableCopy()) |
196 | , m_selectorList(o.m_selectorList) |
197 | { |
198 | } |
199 | |
200 | StyleRule::~StyleRule() = default; |
201 | |
202 | const StyleProperties& StyleRule::properties() const |
203 | { |
204 | if (m_properties->type() == DeferredPropertiesType) |
205 | m_properties = downcast<DeferredStyleProperties>(m_properties.get()).parseDeferredProperties(); |
206 | return downcast<StyleProperties>(m_properties.get()); |
207 | } |
208 | |
209 | MutableStyleProperties& StyleRule::mutableProperties() |
210 | { |
211 | if (!is<MutableStyleProperties>(m_properties.get())) |
212 | m_properties = properties().mutableCopy(); |
213 | return downcast<MutableStyleProperties>(m_properties.get()); |
214 | } |
215 | |
216 | Ref<StyleRule> StyleRule::createForSplitting(const Vector<const CSSSelector*>& selectors, Ref<StyleProperties>&& properties, bool hasDocumentSecurityOrigin) |
217 | { |
218 | ASSERT_WITH_SECURITY_IMPLICATION(!selectors.isEmpty()); |
219 | auto selectorListArray = makeUniqueArray<CSSSelector>(selectors.size()); |
220 | for (unsigned i = 0; i < selectors.size(); ++i) |
221 | new (NotNull, &selectorListArray[i]) CSSSelector(*selectors.at(i)); |
222 | selectorListArray[selectors.size() - 1].setLastInSelectorList(); |
223 | return StyleRule::create(WTFMove(properties), hasDocumentSecurityOrigin, CSSSelectorList(WTFMove(selectorListArray))); |
224 | } |
225 | |
226 | Vector<RefPtr<StyleRule>> StyleRule::splitIntoMultipleRulesWithMaximumSelectorComponentCount(unsigned maxCount) const |
227 | { |
228 | ASSERT(selectorList().componentCount() > maxCount); |
229 | |
230 | Vector<RefPtr<StyleRule>> rules; |
231 | Vector<const CSSSelector*> componentsSinceLastSplit; |
232 | |
233 | for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(selector)) { |
234 | Vector<const CSSSelector*, 8> componentsInThisSelector; |
235 | for (const CSSSelector* component = selector; component; component = component->tagHistory()) |
236 | componentsInThisSelector.append(component); |
237 | |
238 | if (componentsInThisSelector.size() + componentsSinceLastSplit.size() > maxCount && !componentsSinceLastSplit.isEmpty()) { |
239 | rules.append(createForSplitting(componentsSinceLastSplit, const_cast<StyleProperties&>(properties()), hasDocumentSecurityOrigin())); |
240 | componentsSinceLastSplit.clear(); |
241 | } |
242 | |
243 | componentsSinceLastSplit.appendVector(componentsInThisSelector); |
244 | } |
245 | |
246 | if (!componentsSinceLastSplit.isEmpty()) |
247 | rules.append(createForSplitting(componentsSinceLastSplit, const_cast<StyleProperties&>(properties()), hasDocumentSecurityOrigin())); |
248 | |
249 | return rules; |
250 | } |
251 | |
252 | StyleRulePage::StyleRulePage(Ref<StyleProperties>&& properties, CSSSelectorList&& selectors) |
253 | : StyleRuleBase(Page) |
254 | , m_properties(WTFMove(properties)) |
255 | , m_selectorList(WTFMove(selectors)) |
256 | { |
257 | } |
258 | |
259 | StyleRulePage::StyleRulePage(const StyleRulePage& o) |
260 | : StyleRuleBase(o) |
261 | , m_properties(o.m_properties->mutableCopy()) |
262 | , m_selectorList(o.m_selectorList) |
263 | { |
264 | } |
265 | |
266 | StyleRulePage::~StyleRulePage() = default; |
267 | |
268 | MutableStyleProperties& StyleRulePage::mutableProperties() |
269 | { |
270 | if (!is<MutableStyleProperties>(m_properties.get())) |
271 | m_properties = m_properties->mutableCopy(); |
272 | return downcast<MutableStyleProperties>(m_properties.get()); |
273 | } |
274 | |
275 | StyleRuleFontFace::StyleRuleFontFace(Ref<StyleProperties>&& properties) |
276 | : StyleRuleBase(FontFace) |
277 | , m_properties(WTFMove(properties)) |
278 | { |
279 | } |
280 | |
281 | StyleRuleFontFace::StyleRuleFontFace(const StyleRuleFontFace& o) |
282 | : StyleRuleBase(o) |
283 | , m_properties(o.m_properties->mutableCopy()) |
284 | { |
285 | } |
286 | |
287 | StyleRuleFontFace::~StyleRuleFontFace() = default; |
288 | |
289 | MutableStyleProperties& StyleRuleFontFace::mutableProperties() |
290 | { |
291 | if (!is<MutableStyleProperties>(m_properties.get())) |
292 | m_properties = m_properties->mutableCopy(); |
293 | return downcast<MutableStyleProperties>(m_properties.get()); |
294 | } |
295 | |
296 | DeferredStyleGroupRuleList::DeferredStyleGroupRuleList(const CSSParserTokenRange& range, CSSDeferredParser& parser) |
297 | : m_parser(parser) |
298 | { |
299 | size_t length = range.end() - range.begin(); |
300 | m_tokens.reserveCapacity(length); |
301 | m_tokens.append(range.begin(), length); |
302 | } |
303 | |
304 | void DeferredStyleGroupRuleList::parseDeferredRules(Vector<RefPtr<StyleRuleBase>>& childRules) |
305 | { |
306 | m_parser->parseRuleList(m_tokens, childRules); |
307 | } |
308 | |
309 | void DeferredStyleGroupRuleList::parseDeferredKeyframes(StyleRuleKeyframes& keyframesRule) |
310 | { |
311 | m_parser->parseKeyframeList(m_tokens, keyframesRule); |
312 | } |
313 | |
314 | StyleRuleGroup::StyleRuleGroup(Type type, Vector<RefPtr<StyleRuleBase>>& adoptRule) |
315 | : StyleRuleBase(type) |
316 | { |
317 | m_childRules.swap(adoptRule); |
318 | } |
319 | |
320 | StyleRuleGroup::StyleRuleGroup(Type type, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules) |
321 | : StyleRuleBase(type) |
322 | , m_deferredRules(WTFMove(deferredRules)) |
323 | { |
324 | } |
325 | |
326 | StyleRuleGroup::StyleRuleGroup(const StyleRuleGroup& o) |
327 | : StyleRuleBase(o) |
328 | { |
329 | m_childRules.reserveInitialCapacity(o.childRules().size()); |
330 | for (auto& childRule : o.childRules()) |
331 | m_childRules.uncheckedAppend(childRule->copy()); |
332 | } |
333 | |
334 | const Vector<RefPtr<StyleRuleBase>>& StyleRuleGroup::childRules() const |
335 | { |
336 | parseDeferredRulesIfNeeded(); |
337 | return m_childRules; |
338 | } |
339 | |
340 | void StyleRuleGroup::wrapperInsertRule(unsigned index, Ref<StyleRuleBase>&& rule) |
341 | { |
342 | parseDeferredRulesIfNeeded(); |
343 | m_childRules.insert(index, WTFMove(rule)); |
344 | } |
345 | |
346 | void StyleRuleGroup::wrapperRemoveRule(unsigned index) |
347 | { |
348 | parseDeferredRulesIfNeeded(); |
349 | m_childRules.remove(index); |
350 | } |
351 | |
352 | void StyleRuleGroup::parseDeferredRulesIfNeeded() const |
353 | { |
354 | if (!m_deferredRules) |
355 | return; |
356 | |
357 | m_deferredRules->parseDeferredRules(m_childRules); |
358 | m_deferredRules = nullptr; |
359 | } |
360 | |
361 | StyleRuleMedia::StyleRuleMedia(Ref<MediaQuerySet>&& media, Vector<RefPtr<StyleRuleBase>>& adoptRules) |
362 | : StyleRuleGroup(Media, adoptRules) |
363 | , m_mediaQueries(WTFMove(media)) |
364 | { |
365 | } |
366 | |
367 | StyleRuleMedia::StyleRuleMedia(Ref<MediaQuerySet>&& media, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules) |
368 | : StyleRuleGroup(Media, WTFMove(deferredRules)) |
369 | , m_mediaQueries(WTFMove(media)) |
370 | { |
371 | } |
372 | |
373 | StyleRuleMedia::StyleRuleMedia(const StyleRuleMedia& o) |
374 | : StyleRuleGroup(o) |
375 | { |
376 | if (o.m_mediaQueries) |
377 | m_mediaQueries = o.m_mediaQueries->copy(); |
378 | } |
379 | |
380 | |
381 | StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>& adoptRules) |
382 | : StyleRuleGroup(Supports, adoptRules) |
383 | , m_conditionText(conditionText) |
384 | , m_conditionIsSupported(conditionIsSupported) |
385 | { |
386 | } |
387 | |
388 | StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, std::unique_ptr<DeferredStyleGroupRuleList>&& deferredRules) |
389 | : StyleRuleGroup(Supports, WTFMove(deferredRules)) |
390 | , m_conditionText(conditionText) |
391 | , m_conditionIsSupported(conditionIsSupported) |
392 | { |
393 | } |
394 | |
395 | StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& o) |
396 | : StyleRuleGroup(o) |
397 | , m_conditionText(o.m_conditionText) |
398 | , m_conditionIsSupported(o.m_conditionIsSupported) |
399 | { |
400 | } |
401 | |
402 | #if ENABLE(CSS_DEVICE_ADAPTATION) |
403 | StyleRuleViewport::StyleRuleViewport(Ref<StyleProperties>&& properties) |
404 | : StyleRuleBase(Viewport) |
405 | , m_properties(WTFMove(properties)) |
406 | { |
407 | } |
408 | |
409 | StyleRuleViewport::StyleRuleViewport(const StyleRuleViewport& o) |
410 | : StyleRuleBase(o) |
411 | , m_properties(o.m_properties->mutableCopy()) |
412 | { |
413 | } |
414 | |
415 | StyleRuleViewport::~StyleRuleViewport() = default; |
416 | |
417 | MutableStyleProperties& StyleRuleViewport::mutableProperties() |
418 | { |
419 | if (!m_properties->isMutable()) |
420 | m_properties = m_properties->mutableCopy(); |
421 | return static_cast<MutableStyleProperties&>(m_properties.get()); |
422 | } |
423 | #endif // ENABLE(CSS_DEVICE_ADAPTATION) |
424 | |
425 | StyleRuleCharset::StyleRuleCharset() |
426 | : StyleRuleBase(Charset) |
427 | { |
428 | } |
429 | |
430 | StyleRuleCharset::StyleRuleCharset(const StyleRuleCharset& o) |
431 | : StyleRuleBase(o) |
432 | { |
433 | } |
434 | |
435 | StyleRuleCharset::~StyleRuleCharset() = default; |
436 | |
437 | StyleRuleNamespace::StyleRuleNamespace(AtomicString prefix, AtomicString uri) |
438 | : StyleRuleBase(Namespace) |
439 | , m_prefix(prefix) |
440 | , m_uri(uri) |
441 | { |
442 | } |
443 | |
444 | StyleRuleNamespace::StyleRuleNamespace(const StyleRuleNamespace& o) |
445 | : StyleRuleBase(o) |
446 | , m_prefix(o.m_prefix) |
447 | , m_uri(o.m_uri) |
448 | { |
449 | } |
450 | |
451 | StyleRuleNamespace::~StyleRuleNamespace() = default; |
452 | |
453 | } // namespace WebCore |
454 | |