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 "third_party/blink/renderer/core/css/style_rule.h"
23
24 #include "third_party/blink/renderer/core/css/css_font_face_rule.h"
25 #include "third_party/blink/renderer/core/css/css_identifier_value.h"
26 #include "third_party/blink/renderer/core/css/css_import_rule.h"
27 #include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
28 #include "third_party/blink/renderer/core/css/css_media_rule.h"
29 #include "third_party/blink/renderer/core/css/css_namespace_rule.h"
30 #include "third_party/blink/renderer/core/css/css_page_rule.h"
31 #include "third_party/blink/renderer/core/css/css_property_rule.h"
32 #include "third_party/blink/renderer/core/css/css_style_rule.h"
33 #include "third_party/blink/renderer/core/css/css_supports_rule.h"
34 #include "third_party/blink/renderer/core/css/css_value_list.h"
35 #include "third_party/blink/renderer/core/css/css_viewport_rule.h"
36 #include "third_party/blink/renderer/core/css/style_rule_import.h"
37 #include "third_party/blink/renderer/core/css/style_rule_keyframe.h"
38 #include "third_party/blink/renderer/core/css/style_rule_namespace.h"
39
40 namespace blink {
41
42 struct SameSizeAsStyleRuleBase final
43 : public GarbageCollected<SameSizeAsStyleRuleBase> {
44 unsigned bitfields;
45 };
46
47 static_assert(sizeof(StyleRuleBase) <= sizeof(SameSizeAsStyleRuleBase),
48 "StyleRuleBase should stay small");
49
CreateCSSOMWrapper(CSSStyleSheet * parent_sheet) const50 CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet) const {
51 return CreateCSSOMWrapper(parent_sheet, nullptr);
52 }
53
CreateCSSOMWrapper(CSSRule * parent_rule) const54 CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSRule* parent_rule) const {
55 return CreateCSSOMWrapper(nullptr, parent_rule);
56 }
57
Trace(Visitor * visitor)58 void StyleRuleBase::Trace(Visitor* visitor) {
59 switch (GetType()) {
60 case kCharset:
61 To<StyleRuleCharset>(this)->TraceAfterDispatch(visitor);
62 return;
63 case kStyle:
64 To<StyleRule>(this)->TraceAfterDispatch(visitor);
65 return;
66 case kPage:
67 To<StyleRulePage>(this)->TraceAfterDispatch(visitor);
68 return;
69 case kProperty:
70 To<StyleRuleProperty>(this)->TraceAfterDispatch(visitor);
71 return;
72 case kFontFace:
73 To<StyleRuleFontFace>(this)->TraceAfterDispatch(visitor);
74 return;
75 case kMedia:
76 To<StyleRuleMedia>(this)->TraceAfterDispatch(visitor);
77 return;
78 case kSupports:
79 To<StyleRuleSupports>(this)->TraceAfterDispatch(visitor);
80 return;
81 case kImport:
82 To<StyleRuleImport>(this)->TraceAfterDispatch(visitor);
83 return;
84 case kKeyframes:
85 To<StyleRuleKeyframes>(this)->TraceAfterDispatch(visitor);
86 return;
87 case kKeyframe:
88 To<StyleRuleKeyframe>(this)->TraceAfterDispatch(visitor);
89 return;
90 case kNamespace:
91 To<StyleRuleNamespace>(this)->TraceAfterDispatch(visitor);
92 return;
93 case kViewport:
94 To<StyleRuleViewport>(this)->TraceAfterDispatch(visitor);
95 return;
96 }
97 NOTREACHED();
98 }
99
FinalizeGarbageCollectedObject()100 void StyleRuleBase::FinalizeGarbageCollectedObject() {
101 switch (GetType()) {
102 case kCharset:
103 To<StyleRuleCharset>(this)->~StyleRuleCharset();
104 return;
105 case kStyle:
106 To<StyleRule>(this)->~StyleRule();
107 return;
108 case kPage:
109 To<StyleRulePage>(this)->~StyleRulePage();
110 return;
111 case kProperty:
112 To<StyleRuleProperty>(this)->~StyleRuleProperty();
113 return;
114 case kFontFace:
115 To<StyleRuleFontFace>(this)->~StyleRuleFontFace();
116 return;
117 case kMedia:
118 To<StyleRuleMedia>(this)->~StyleRuleMedia();
119 return;
120 case kSupports:
121 To<StyleRuleSupports>(this)->~StyleRuleSupports();
122 return;
123 case kImport:
124 To<StyleRuleImport>(this)->~StyleRuleImport();
125 return;
126 case kKeyframes:
127 To<StyleRuleKeyframes>(this)->~StyleRuleKeyframes();
128 return;
129 case kKeyframe:
130 To<StyleRuleKeyframe>(this)->~StyleRuleKeyframe();
131 return;
132 case kNamespace:
133 To<StyleRuleNamespace>(this)->~StyleRuleNamespace();
134 return;
135 case kViewport:
136 To<StyleRuleViewport>(this)->~StyleRuleViewport();
137 return;
138 }
139 NOTREACHED();
140 }
141
Copy() const142 StyleRuleBase* StyleRuleBase::Copy() const {
143 switch (GetType()) {
144 case kStyle:
145 return To<StyleRule>(this)->Copy();
146 case kPage:
147 return To<StyleRulePage>(this)->Copy();
148 case kProperty:
149 return To<StyleRuleProperty>(this)->Copy();
150 case kFontFace:
151 return To<StyleRuleFontFace>(this)->Copy();
152 case kMedia:
153 return To<StyleRuleMedia>(this)->Copy();
154 case kSupports:
155 return To<StyleRuleSupports>(this)->Copy();
156 case kImport:
157 // FIXME: Copy import rules.
158 NOTREACHED();
159 return nullptr;
160 case kKeyframes:
161 return To<StyleRuleKeyframes>(this)->Copy();
162 case kViewport:
163 return To<StyleRuleViewport>(this)->Copy();
164 case kNamespace:
165 return To<StyleRuleNamespace>(this)->Copy();
166 case kCharset:
167 case kKeyframe:
168 NOTREACHED();
169 return nullptr;
170 }
171 NOTREACHED();
172 return nullptr;
173 }
174
CreateCSSOMWrapper(CSSStyleSheet * parent_sheet,CSSRule * parent_rule) const175 CSSRule* StyleRuleBase::CreateCSSOMWrapper(CSSStyleSheet* parent_sheet,
176 CSSRule* parent_rule) const {
177 CSSRule* rule = nullptr;
178 StyleRuleBase* self = const_cast<StyleRuleBase*>(this);
179 switch (GetType()) {
180 case kStyle:
181 rule =
182 MakeGarbageCollected<CSSStyleRule>(To<StyleRule>(self), parent_sheet);
183 break;
184 case kPage:
185 rule = MakeGarbageCollected<CSSPageRule>(To<StyleRulePage>(self),
186 parent_sheet);
187 break;
188 case kProperty:
189 rule = MakeGarbageCollected<CSSPropertyRule>(To<StyleRuleProperty>(self),
190 parent_sheet);
191 break;
192 case kFontFace:
193 rule = MakeGarbageCollected<CSSFontFaceRule>(To<StyleRuleFontFace>(self),
194 parent_sheet);
195 break;
196 case kMedia:
197 rule = MakeGarbageCollected<CSSMediaRule>(To<StyleRuleMedia>(self),
198 parent_sheet);
199 break;
200 case kSupports:
201 rule = MakeGarbageCollected<CSSSupportsRule>(To<StyleRuleSupports>(self),
202 parent_sheet);
203 break;
204 case kImport:
205 rule = MakeGarbageCollected<CSSImportRule>(To<StyleRuleImport>(self),
206 parent_sheet);
207 break;
208 case kKeyframes:
209 rule = MakeGarbageCollected<CSSKeyframesRule>(
210 To<StyleRuleKeyframes>(self), parent_sheet);
211 break;
212 case kNamespace:
213 rule = MakeGarbageCollected<CSSNamespaceRule>(
214 To<StyleRuleNamespace>(self), parent_sheet);
215 break;
216 case kViewport:
217 rule = MakeGarbageCollected<CSSViewportRule>(To<StyleRuleViewport>(self),
218 parent_sheet);
219 break;
220 case kKeyframe:
221 case kCharset:
222 NOTREACHED();
223 return nullptr;
224 }
225 if (parent_rule)
226 rule->SetParentRule(parent_rule);
227 return rule;
228 }
229
AverageSizeInBytes()230 unsigned StyleRule::AverageSizeInBytes() {
231 return sizeof(StyleRule) + sizeof(CSSSelector) +
232 CSSPropertyValueSet::AverageSizeInBytes();
233 }
234
StyleRule(CSSSelectorList selector_list,CSSPropertyValueSet * properties)235 StyleRule::StyleRule(CSSSelectorList selector_list,
236 CSSPropertyValueSet* properties)
237 : StyleRuleBase(kStyle),
238 should_consider_for_matching_rules_(kConsiderIfNonEmpty),
239 selector_list_(std::move(selector_list)),
240 properties_(properties) {}
241
StyleRule(CSSSelectorList selector_list,CSSLazyPropertyParser * lazy_property_parser)242 StyleRule::StyleRule(CSSSelectorList selector_list,
243 CSSLazyPropertyParser* lazy_property_parser)
244 : StyleRuleBase(kStyle),
245 should_consider_for_matching_rules_(kAlwaysConsider),
246 selector_list_(std::move(selector_list)),
247 lazy_property_parser_(lazy_property_parser) {}
248
Properties() const249 const CSSPropertyValueSet& StyleRule::Properties() const {
250 if (!properties_) {
251 properties_ = lazy_property_parser_->ParseProperties();
252 lazy_property_parser_.Clear();
253 }
254 return *properties_;
255 }
256
StyleRule(const StyleRule & o)257 StyleRule::StyleRule(const StyleRule& o)
258 : StyleRuleBase(o),
259 should_consider_for_matching_rules_(kConsiderIfNonEmpty),
260 selector_list_(o.selector_list_.Copy()),
261 properties_(o.Properties().MutableCopy()) {}
262
263 StyleRule::~StyleRule() = default;
264
MutableProperties()265 MutableCSSPropertyValueSet& StyleRule::MutableProperties() {
266 // Ensure properties_ is initialized.
267 if (!Properties().IsMutable())
268 properties_ = properties_->MutableCopy();
269 return *To<MutableCSSPropertyValueSet>(properties_.Get());
270 }
271
PropertiesHaveFailedOrCanceledSubresources() const272 bool StyleRule::PropertiesHaveFailedOrCanceledSubresources() const {
273 return properties_ && properties_->HasFailedOrCanceledSubresources();
274 }
275
ShouldConsiderForMatchingRules(bool include_empty_rules) const276 bool StyleRule::ShouldConsiderForMatchingRules(bool include_empty_rules) const {
277 DCHECK(should_consider_for_matching_rules_ == kAlwaysConsider || properties_);
278 return include_empty_rules ||
279 should_consider_for_matching_rules_ == kAlwaysConsider ||
280 !properties_->IsEmpty();
281 }
282
HasParsedProperties() const283 bool StyleRule::HasParsedProperties() const {
284 // StyleRule should only have one of {lazy_property_parser_, properties_} set.
285 DCHECK(lazy_property_parser_ || properties_);
286 DCHECK(!lazy_property_parser_ || !properties_);
287 return !lazy_property_parser_;
288 }
289
TraceAfterDispatch(blink::Visitor * visitor) const290 void StyleRule::TraceAfterDispatch(blink::Visitor* visitor) const {
291 visitor->Trace(properties_);
292 visitor->Trace(lazy_property_parser_);
293 StyleRuleBase::TraceAfterDispatch(visitor);
294 }
295
StyleRulePage(CSSSelectorList selector_list,CSSPropertyValueSet * properties)296 StyleRulePage::StyleRulePage(CSSSelectorList selector_list,
297 CSSPropertyValueSet* properties)
298 : StyleRuleBase(kPage),
299 properties_(properties),
300 selector_list_(std::move(selector_list)) {}
301
StyleRulePage(const StyleRulePage & page_rule)302 StyleRulePage::StyleRulePage(const StyleRulePage& page_rule)
303 : StyleRuleBase(page_rule),
304 properties_(page_rule.properties_->MutableCopy()),
305 selector_list_(page_rule.selector_list_.Copy()) {}
306
307 StyleRulePage::~StyleRulePage() = default;
308
MutableProperties()309 MutableCSSPropertyValueSet& StyleRulePage::MutableProperties() {
310 if (!properties_->IsMutable())
311 properties_ = properties_->MutableCopy();
312 return *To<MutableCSSPropertyValueSet>(properties_.Get());
313 }
314
TraceAfterDispatch(blink::Visitor * visitor) const315 void StyleRulePage::TraceAfterDispatch(blink::Visitor* visitor) const {
316 visitor->Trace(properties_);
317 StyleRuleBase::TraceAfterDispatch(visitor);
318 }
319
StyleRuleProperty(const String & name,CSSPropertyValueSet * properties)320 StyleRuleProperty::StyleRuleProperty(const String& name,
321 CSSPropertyValueSet* properties)
322 : StyleRuleBase(kProperty), name_(name), properties_(properties) {}
323
StyleRuleProperty(const StyleRuleProperty & property_rule)324 StyleRuleProperty::StyleRuleProperty(const StyleRuleProperty& property_rule)
325 : StyleRuleBase(property_rule),
326 properties_(property_rule.properties_->MutableCopy()) {}
327
328 StyleRuleProperty::~StyleRuleProperty() = default;
329
MutableProperties()330 MutableCSSPropertyValueSet& StyleRuleProperty::MutableProperties() {
331 if (!properties_->IsMutable())
332 properties_ = properties_->MutableCopy();
333 return *To<MutableCSSPropertyValueSet>(properties_.Get());
334 }
335
TraceAfterDispatch(blink::Visitor * visitor) const336 void StyleRuleProperty::TraceAfterDispatch(blink::Visitor* visitor) const {
337 visitor->Trace(properties_);
338 StyleRuleBase::TraceAfterDispatch(visitor);
339 }
340
StyleRuleFontFace(CSSPropertyValueSet * properties)341 StyleRuleFontFace::StyleRuleFontFace(CSSPropertyValueSet* properties)
342 : StyleRuleBase(kFontFace), properties_(properties) {}
343
StyleRuleFontFace(const StyleRuleFontFace & font_face_rule)344 StyleRuleFontFace::StyleRuleFontFace(const StyleRuleFontFace& font_face_rule)
345 : StyleRuleBase(font_face_rule),
346 properties_(font_face_rule.properties_->MutableCopy()) {}
347
MutableProperties()348 MutableCSSPropertyValueSet& StyleRuleFontFace::MutableProperties() {
349 if (!properties_->IsMutable())
350 properties_ = properties_->MutableCopy();
351 return *To<MutableCSSPropertyValueSet>(properties_.Get());
352 }
353
TraceAfterDispatch(blink::Visitor * visitor) const354 void StyleRuleFontFace::TraceAfterDispatch(blink::Visitor* visitor) const {
355 visitor->Trace(properties_);
356 StyleRuleBase::TraceAfterDispatch(visitor);
357 }
358
StyleRuleGroup(RuleType type,HeapVector<Member<StyleRuleBase>> & adopt_rule)359 StyleRuleGroup::StyleRuleGroup(RuleType type,
360 HeapVector<Member<StyleRuleBase>>& adopt_rule)
361 : StyleRuleBase(type) {
362 child_rules_.swap(adopt_rule);
363 }
364
StyleRuleGroup(const StyleRuleGroup & group_rule)365 StyleRuleGroup::StyleRuleGroup(const StyleRuleGroup& group_rule)
366 : StyleRuleBase(group_rule), child_rules_(group_rule.child_rules_.size()) {
367 for (unsigned i = 0; i < child_rules_.size(); ++i)
368 child_rules_[i] = group_rule.child_rules_[i]->Copy();
369 }
370
WrapperInsertRule(unsigned index,StyleRuleBase * rule)371 void StyleRuleGroup::WrapperInsertRule(unsigned index, StyleRuleBase* rule) {
372 child_rules_.insert(index, rule);
373 }
374
WrapperRemoveRule(unsigned index)375 void StyleRuleGroup::WrapperRemoveRule(unsigned index) {
376 child_rules_.EraseAt(index);
377 }
378
TraceAfterDispatch(blink::Visitor * visitor) const379 void StyleRuleGroup::TraceAfterDispatch(blink::Visitor* visitor) const {
380 visitor->Trace(child_rules_);
381 StyleRuleBase::TraceAfterDispatch(visitor);
382 }
383
StyleRuleCondition(RuleType type,HeapVector<Member<StyleRuleBase>> & adopt_rules)384 StyleRuleCondition::StyleRuleCondition(
385 RuleType type,
386 HeapVector<Member<StyleRuleBase>>& adopt_rules)
387 : StyleRuleGroup(type, adopt_rules) {}
388
StyleRuleCondition(RuleType type,const String & condition_text,HeapVector<Member<StyleRuleBase>> & adopt_rules)389 StyleRuleCondition::StyleRuleCondition(
390 RuleType type,
391 const String& condition_text,
392 HeapVector<Member<StyleRuleBase>>& adopt_rules)
393 : StyleRuleGroup(type, adopt_rules), condition_text_(condition_text) {}
394
395 StyleRuleCondition::StyleRuleCondition(
396 const StyleRuleCondition& condition_rule) = default;
397
StyleRuleMedia(scoped_refptr<MediaQuerySet> media,HeapVector<Member<StyleRuleBase>> & adopt_rules)398 StyleRuleMedia::StyleRuleMedia(scoped_refptr<MediaQuerySet> media,
399 HeapVector<Member<StyleRuleBase>>& adopt_rules)
400 : StyleRuleCondition(kMedia, adopt_rules), media_queries_(media) {}
401
StyleRuleMedia(const StyleRuleMedia & media_rule)402 StyleRuleMedia::StyleRuleMedia(const StyleRuleMedia& media_rule)
403 : StyleRuleCondition(media_rule) {
404 if (media_rule.media_queries_)
405 media_queries_ = media_rule.media_queries_->Copy();
406 }
407
StyleRuleSupports(const String & condition_text,bool condition_is_supported,HeapVector<Member<StyleRuleBase>> & adopt_rules)408 StyleRuleSupports::StyleRuleSupports(
409 const String& condition_text,
410 bool condition_is_supported,
411 HeapVector<Member<StyleRuleBase>>& adopt_rules)
412 : StyleRuleCondition(kSupports, condition_text, adopt_rules),
413 condition_is_supported_(condition_is_supported) {}
414
TraceAfterDispatch(blink::Visitor * visitor) const415 void StyleRuleMedia::TraceAfterDispatch(blink::Visitor* visitor) const {
416 StyleRuleCondition::TraceAfterDispatch(visitor);
417 }
418
StyleRuleSupports(const StyleRuleSupports & supports_rule)419 StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& supports_rule)
420 : StyleRuleCondition(supports_rule),
421 condition_is_supported_(supports_rule.condition_is_supported_) {}
422
StyleRuleViewport(CSSPropertyValueSet * properties)423 StyleRuleViewport::StyleRuleViewport(CSSPropertyValueSet* properties)
424 : StyleRuleBase(kViewport), properties_(properties) {}
425
StyleRuleViewport(const StyleRuleViewport & viewport_rule)426 StyleRuleViewport::StyleRuleViewport(const StyleRuleViewport& viewport_rule)
427 : StyleRuleBase(viewport_rule),
428 properties_(viewport_rule.properties_->MutableCopy()) {}
429
MutableProperties()430 MutableCSSPropertyValueSet& StyleRuleViewport::MutableProperties() {
431 if (!properties_->IsMutable())
432 properties_ = properties_->MutableCopy();
433 return *To<MutableCSSPropertyValueSet>(properties_.Get());
434 }
435
TraceAfterDispatch(blink::Visitor * visitor) const436 void StyleRuleViewport::TraceAfterDispatch(blink::Visitor* visitor) const {
437 visitor->Trace(properties_);
438 StyleRuleBase::TraceAfterDispatch(visitor);
439 }
440
441 } // namespace blink
442