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 "CSSCharsetRule.h"
26#include "CSSFontFaceRule.h"
27#include "CSSImportRule.h"
28#include "CSSMediaRule.h"
29#include "CSSPageRule.h"
30#include "CSSStyleRule.h"
31#include "CSSSupportsRule.h"
32#include "CSSUnknownRule.h"
33#include "StyleProperties.h"
34#include "StyleRuleImport.h"
35#include "WebKitCSSKeyframeRule.h"
36#include "WebKitCSSKeyframesRule.h"
37#include "WebKitCSSRegionRule.h"
38#include "WebKitCSSViewportRule.h"
39
40namespace WebCore {
41
42struct SameSizeAsStyleRuleBase : public WTF::RefCountedBase {
43    unsigned bitfields;
44};
45
46COMPILE_ASSERT(sizeof(StyleRuleBase) == sizeof(SameSizeAsStyleRuleBase), StyleRuleBase_should_stay_small);
47
48PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet) const
49{
50    return createCSSOMWrapper(parentSheet, 0);
51}
52
53PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSRule* parentRule) const
54{
55    return createCSSOMWrapper(0, parentRule);
56}
57
58void StyleRuleBase::destroy()
59{
60    switch (type()) {
61    case Style:
62        delete static_cast<StyleRule*>(this);
63        return;
64    case Page:
65        delete static_cast<StyleRulePage*>(this);
66        return;
67    case FontFace:
68        delete static_cast<StyleRuleFontFace*>(this);
69        return;
70    case Media:
71        delete static_cast<StyleRuleMedia*>(this);
72        return;
73#if ENABLE(CSS3_CONDITIONAL_RULES)
74    case Supports:
75        delete static_cast<StyleRuleSupports*>(this);
76        return;
77#endif
78#if ENABLE(CSS_REGIONS)
79    case Region:
80        delete static_cast<StyleRuleRegion*>(this);
81        return;
82#endif
83    case Import:
84        delete static_cast<StyleRuleImport*>(this);
85        return;
86    case Keyframes:
87        delete static_cast<StyleRuleKeyframes*>(this);
88        return;
89#if ENABLE(CSS_DEVICE_ADAPTATION)
90    case Viewport:
91        delete static_cast<StyleRuleViewport*>(this);
92        return;
93#endif
94    case Unknown:
95    case Charset:
96    case Keyframe:
97#if !ENABLE(CSS_REGIONS)
98    case Region:
99#endif
100        ASSERT_NOT_REACHED();
101        return;
102    }
103    ASSERT_NOT_REACHED();
104}
105
106PassRef<StyleRuleBase> StyleRuleBase::copy() const
107{
108    switch (type()) {
109    case Style:
110        return static_cast<const StyleRule*>(this)->copy();
111    case Page:
112        return static_cast<const StyleRulePage*>(this)->copy();
113    case FontFace:
114        return static_cast<const StyleRuleFontFace*>(this)->copy();
115    case Media:
116        return static_cast<const StyleRuleMedia*>(this)->copy();
117#if ENABLE(CSS3_CONDITIONAL_RULES)
118    case Supports:
119        return static_cast<const StyleRuleSupports*>(this)->copy();
120#endif
121#if ENABLE(CSS_REGIONS)
122    case Region:
123        return static_cast<const StyleRuleRegion*>(this)->copy();
124#endif
125    case Keyframes:
126        return static_cast<const StyleRuleKeyframes*>(this)->copy();
127#if ENABLE(CSS_DEVICE_ADAPTATION)
128    case Viewport:
129        return static_cast<const StyleRuleViewport*>(this)->copy();
130#endif
131    case Import:
132        // FIXME: Copy import rules.
133        break;
134    case Unknown:
135    case Charset:
136    case Keyframe:
137#if !ENABLE(CSS_REGIONS)
138    case Region:
139#endif
140        break;
141    }
142    CRASH();
143    // HACK: EFL won't build without this (old GCC with crappy -Werror=return-type)
144    return PassRef<StyleRuleBase>(*static_cast<StyleRuleBase*>(nullptr));
145}
146
147PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const
148{
149    RefPtr<CSSRule> rule;
150    StyleRuleBase* self = const_cast<StyleRuleBase*>(this);
151    switch (type()) {
152    case Style:
153        rule = CSSStyleRule::create(static_cast<StyleRule*>(self), parentSheet);
154        break;
155    case Page:
156        rule = CSSPageRule::create(static_cast<StyleRulePage*>(self), parentSheet);
157        break;
158    case FontFace:
159        rule = CSSFontFaceRule::create(static_cast<StyleRuleFontFace*>(self), parentSheet);
160        break;
161    case Media:
162        rule = CSSMediaRule::create(static_cast<StyleRuleMedia*>(self), parentSheet);
163        break;
164#if ENABLE(CSS3_CONDITIONAL_RULES)
165    case Supports:
166        rule = CSSSupportsRule::create(static_cast<StyleRuleSupports*>(self), parentSheet);
167        break;
168#endif
169#if ENABLE(CSS_REGIONS)
170    case Region:
171        rule = WebKitCSSRegionRule::create(static_cast<StyleRuleRegion*>(self), parentSheet);
172        break;
173#endif
174    case Import:
175        rule = CSSImportRule::create(static_cast<StyleRuleImport*>(self), parentSheet);
176        break;
177    case Keyframes:
178        rule = WebKitCSSKeyframesRule::create(static_cast<StyleRuleKeyframes*>(self), parentSheet);
179        break;
180#if ENABLE(CSS_DEVICE_ADAPTATION)
181    case Viewport:
182        rule = WebKitCSSViewportRule::create(static_cast<StyleRuleViewport*>(self), parentSheet);
183        break;
184#endif
185    case Unknown:
186    case Charset:
187    case Keyframe:
188#if !ENABLE(CSS_REGIONS)
189    case Region:
190#endif
191        ASSERT_NOT_REACHED();
192        return 0;
193    }
194    if (parentRule)
195        rule->setParentRule(parentRule);
196    return rule.release();
197}
198
199unsigned StyleRule::averageSizeInBytes()
200{
201    return sizeof(StyleRule) + sizeof(CSSSelector) + StyleProperties::averageSizeInBytes();
202}
203
204StyleRule::StyleRule(int sourceLine, PassRef<StyleProperties> properties)
205    : StyleRuleBase(Style, sourceLine)
206    , m_properties(WTF::move(properties))
207{
208}
209
210StyleRule::StyleRule(const StyleRule& o)
211    : StyleRuleBase(o)
212    , m_properties(o.m_properties->mutableCopy())
213    , m_selectorList(o.m_selectorList)
214{
215}
216
217StyleRule::~StyleRule()
218{
219}
220
221MutableStyleProperties& StyleRule::mutableProperties()
222{
223    if (!m_properties->isMutable())
224        m_properties = m_properties->mutableCopy();
225    return static_cast<MutableStyleProperties&>(m_properties.get());
226}
227
228PassRef<StyleRule> StyleRule::create(int sourceLine, const Vector<const CSSSelector*>& selectors, PassRef<StyleProperties> properties)
229{
230    ASSERT_WITH_SECURITY_IMPLICATION(!selectors.isEmpty());
231    CSSSelector* selectorListArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * selectors.size()));
232    for (unsigned i = 0; i < selectors.size(); ++i)
233        new (NotNull, &selectorListArray[i]) CSSSelector(*selectors.at(i));
234    selectorListArray[selectors.size() - 1].setLastInSelectorList();
235    auto rule = StyleRule::create(sourceLine, WTF::move(properties));
236    rule.get().parserAdoptSelectorArray(selectorListArray);
237    return rule;
238}
239
240Vector<RefPtr<StyleRule>> StyleRule::splitIntoMultipleRulesWithMaximumSelectorComponentCount(unsigned maxCount) const
241{
242    ASSERT(selectorList().componentCount() > maxCount);
243
244    Vector<RefPtr<StyleRule>> rules;
245    Vector<const CSSSelector*> componentsSinceLastSplit;
246
247    for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(selector)) {
248        Vector<const CSSSelector*, 8> componentsInThisSelector;
249        for (const CSSSelector* component = selector; component; component = component->tagHistory())
250            componentsInThisSelector.append(component);
251
252        if (componentsInThisSelector.size() + componentsSinceLastSplit.size() > maxCount && !componentsSinceLastSplit.isEmpty()) {
253            rules.append(create(sourceLine(), componentsSinceLastSplit, const_cast<StyleProperties&>(m_properties.get())));
254            componentsSinceLastSplit.clear();
255        }
256
257        componentsSinceLastSplit.appendVector(componentsInThisSelector);
258    }
259
260    if (!componentsSinceLastSplit.isEmpty())
261        rules.append(create(sourceLine(), componentsSinceLastSplit, const_cast<StyleProperties&>(m_properties.get())));
262
263    return rules;
264}
265
266StyleRulePage::StyleRulePage(PassRef<StyleProperties> properties)
267    : StyleRuleBase(Page)
268    , m_properties(WTF::move(properties))
269{
270}
271
272StyleRulePage::StyleRulePage(const StyleRulePage& o)
273    : StyleRuleBase(o)
274    , m_properties(o.m_properties->mutableCopy())
275    , m_selectorList(o.m_selectorList)
276{
277}
278
279StyleRulePage::~StyleRulePage()
280{
281}
282
283MutableStyleProperties& StyleRulePage::mutableProperties()
284{
285    if (!m_properties->isMutable())
286        m_properties = m_properties->mutableCopy();
287    return static_cast<MutableStyleProperties&>(m_properties.get());
288}
289
290StyleRuleFontFace::StyleRuleFontFace(PassRef<StyleProperties> properties)
291    : StyleRuleBase(FontFace, 0)
292    , m_properties(WTF::move(properties))
293{
294}
295
296StyleRuleFontFace::StyleRuleFontFace(const StyleRuleFontFace& o)
297    : StyleRuleBase(o)
298    , m_properties(o.m_properties->mutableCopy())
299{
300}
301
302StyleRuleFontFace::~StyleRuleFontFace()
303{
304}
305
306MutableStyleProperties& StyleRuleFontFace::mutableProperties()
307{
308    if (!m_properties->isMutable())
309        m_properties = m_properties->mutableCopy();
310    return static_cast<MutableStyleProperties&>(m_properties.get());
311}
312
313StyleRuleGroup::StyleRuleGroup(Type type, Vector<RefPtr<StyleRuleBase>>& adoptRule)
314    : StyleRuleBase(type, 0)
315{
316    m_childRules.swap(adoptRule);
317}
318
319StyleRuleGroup::StyleRuleGroup(const StyleRuleGroup& o)
320    : StyleRuleBase(o)
321{
322    m_childRules.reserveInitialCapacity(o.m_childRules.size());
323    for (unsigned i = 0, size = o.m_childRules.size(); i < size; ++i)
324        m_childRules.uncheckedAppend(o.m_childRules[i]->copy());
325}
326
327void StyleRuleGroup::wrapperInsertRule(unsigned index, PassRef<StyleRuleBase> rule)
328{
329    m_childRules.insert(index, WTF::move(rule));
330}
331
332void StyleRuleGroup::wrapperRemoveRule(unsigned index)
333{
334    m_childRules.remove(index);
335}
336
337
338StyleRuleMedia::StyleRuleMedia(PassRefPtr<MediaQuerySet> media, Vector<RefPtr<StyleRuleBase>>& adoptRules)
339    : StyleRuleGroup(Media, adoptRules)
340    , m_mediaQueries(media)
341{
342}
343
344StyleRuleMedia::StyleRuleMedia(const StyleRuleMedia& o)
345    : StyleRuleGroup(o)
346{
347    if (o.m_mediaQueries)
348        m_mediaQueries = o.m_mediaQueries->copy();
349}
350
351
352#if ENABLE(CSS3_CONDITIONAL_RULES)
353StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase>>& adoptRules)
354    : StyleRuleGroup(Supports, adoptRules)
355    , m_conditionText(conditionText)
356    , m_conditionIsSupported(conditionIsSupported)
357{
358}
359
360StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& o)
361    : StyleRuleGroup(o)
362    , m_conditionText(o.m_conditionText)
363    , m_conditionIsSupported(o.m_conditionIsSupported)
364{
365}
366#endif
367
368StyleRuleRegion::StyleRuleRegion(Vector<std::unique_ptr<CSSParserSelector>>* selectors, Vector<RefPtr<StyleRuleBase>>& adoptRules)
369    : StyleRuleGroup(Region, adoptRules)
370{
371    m_selectorList.adoptSelectorVector(*selectors);
372}
373
374StyleRuleRegion::StyleRuleRegion(const StyleRuleRegion& o)
375    : StyleRuleGroup(o)
376    , m_selectorList(o.m_selectorList)
377{
378}
379
380
381#if ENABLE(CSS_DEVICE_ADAPTATION)
382StyleRuleViewport::StyleRuleViewport(PassRef<StyleProperties> properties)
383    : StyleRuleBase(Viewport, 0)
384    , m_properties(WTF::move(properties))
385{
386}
387
388StyleRuleViewport::StyleRuleViewport(const StyleRuleViewport& o)
389    : StyleRuleBase(o)
390    , m_properties(o.m_properties->mutableCopy())
391{
392}
393
394StyleRuleViewport::~StyleRuleViewport()
395{
396}
397
398MutableStyleProperties& StyleRuleViewport::mutableProperties()
399{
400    if (!m_properties->isMutable())
401        m_properties = m_properties->mutableCopy();
402    return static_cast<MutableStyleProperties&>(m_properties.get());
403}
404#endif // ENABLE(CSS_DEVICE_ADAPTATION)
405
406} // namespace WebCore
407