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