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