Add modern API for overriding the page's specified viewport configuration
[WebKit-https.git] / Source / WebCore / css / StyleRule.cpp
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