Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / parser / BisonCSSParser-in.cpp
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
9  * Copyright (C) 2012 Intel Corporation. All rights reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26
27 #include "config.h"
28 #include "core/css/parser/BisonCSSParser.h"
29
30 #include "core/CSSValueKeywords.h"
31 #include "core/MediaTypeNames.h"
32 #include "core/StylePropertyShorthand.h"
33 #include "core/css/CSSBasicShapes.h"
34 #include "core/css/CSSBorderImage.h"
35 #include "core/css/CSSCanvasValue.h"
36 #include "core/css/CSSCrossfadeValue.h"
37 #include "core/css/CSSCursorImageValue.h"
38 #include "core/css/CSSFontFaceSrcValue.h"
39 #include "core/css/CSSFontFeatureValue.h"
40 #include "core/css/CSSFunctionValue.h"
41 #include "core/css/CSSGradientValue.h"
42 #include "core/css/CSSGridLineNamesValue.h"
43 #include "core/css/CSSGridTemplateAreasValue.h"
44 #include "core/css/CSSImageSetValue.h"
45 #include "core/css/CSSImageValue.h"
46 #include "core/css/CSSInheritedValue.h"
47 #include "core/css/CSSInitialValue.h"
48 #include "core/css/CSSKeyframeRule.h"
49 #include "core/css/CSSKeyframesRule.h"
50 #include "core/css/CSSLineBoxContainValue.h"
51 #include "core/css/CSSPrimitiveValue.h"
52 #include "core/css/CSSPropertySourceData.h"
53 #include "core/css/CSSReflectValue.h"
54 #include "core/css/CSSSelector.h"
55 #include "core/css/CSSShadowValue.h"
56 #include "core/css/CSSStyleSheet.h"
57 #include "core/css/CSSTimingFunctionValue.h"
58 #include "core/css/CSSTransformValue.h"
59 #include "core/css/CSSUnicodeRangeValue.h"
60 #include "core/css/CSSValueList.h"
61 #include "core/css/CSSValuePool.h"
62 #include "core/css/Counter.h"
63 #include "core/css/HashTools.h"
64 #include "core/css/MediaList.h"
65 #include "core/css/MediaQueryExp.h"
66 #include "core/css/Pair.h"
67 #include "core/css/Rect.h"
68 #include "core/css/StylePropertySet.h"
69 #include "core/css/StyleRule.h"
70 #include "core/css/StyleRuleImport.h"
71 #include "core/css/StyleSheetContents.h"
72 #include "core/dom/Document.h"
73 #include "core/frame/FrameConsole.h"
74 #include "core/frame/FrameHost.h"
75 #include "core/frame/Settings.h"
76 #include "core/frame/UseCounter.h"
77 #include "core/html/parser/HTMLParserIdioms.h"
78 #include "core/inspector/ConsoleMessage.h"
79 #include "core/inspector/InspectorInstrumentation.h"
80 #include "core/rendering/RenderTheme.h"
81 #include "platform/FloatConversion.h"
82 #include "platform/RuntimeEnabledFeatures.h"
83 #include "wtf/BitArray.h"
84 #include "wtf/HexNumber.h"
85 #include "wtf/text/StringBuffer.h"
86 #include "wtf/text/StringBuilder.h"
87 #include "wtf/text/StringImpl.h"
88 #include "wtf/text/TextEncoding.h"
89 #include <limits.h>
90
91 #define YYDEBUG 0
92
93 #if YYDEBUG > 0
94 extern int cssyydebug;
95 #endif
96
97 int cssyyparse(blink::BisonCSSParser*);
98
99 using namespace WTF;
100
101 namespace blink {
102
103 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
104
105 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
106     : m_context(context)
107     , m_important(false)
108     , m_id(CSSPropertyInvalid)
109     , m_styleSheet(nullptr)
110     , m_supportsCondition(false)
111     , m_selectorListForParseSelector(0)
112     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
113     , m_hadSyntacticallyValidCSSRule(false)
114     , m_logErrors(false)
115     , m_ignoreErrors(false)
116     , m_defaultNamespace(starAtom)
117     , m_observer(0)
118     , m_source(0)
119     , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
120     , m_allowImportRules(true)
121     , m_allowNamespaceDeclarations(true)
122     , m_inViewport(false)
123     , m_tokenizer(*this)
124 {
125 #if YYDEBUG > 0
126     cssyydebug = 1;
127 #endif
128 }
129
130 BisonCSSParser::~BisonCSSParser()
131 {
132     clearProperties();
133
134     deleteAllValues(m_floatingSelectors);
135     deleteAllValues(m_floatingSelectorVectors);
136     deleteAllValues(m_floatingValueLists);
137     deleteAllValues(m_floatingFunctions);
138 }
139
140 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
141 {
142     m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
143     m_ruleHasHeader = true;
144 }
145
146 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
147 {
148     setStyleSheet(sheet);
149     m_defaultNamespace = starAtom; // Reset the default namespace.
150     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
151     m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
152     m_ignoreErrors = false;
153     m_tokenizer.m_lineNumber = 0;
154     m_startPosition = startPosition;
155     m_source = &string;
156     m_tokenizer.m_internal = false;
157     setupParser("", string, "");
158     cssyyparse(this);
159     sheet->shrinkToFit();
160     m_source = 0;
161     m_rule = nullptr;
162     m_lineEndings.clear();
163     m_ignoreErrors = false;
164     m_logErrors = false;
165     m_tokenizer.m_internal = true;
166 }
167
168 PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
169 {
170     setStyleSheet(sheet);
171     m_allowNamespaceDeclarations = false;
172     setupParser("@-internal-rule ", string, "");
173     cssyyparse(this);
174     return m_rule.release();
175 }
176
177 PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
178 {
179     setStyleSheet(sheet);
180     setupParser("@-internal-keyframe-rule ", string, "");
181     cssyyparse(this);
182     return m_keyframe.release();
183 }
184
185 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
186 {
187     setupParser("@-internal-keyframe-key-list ", string, "");
188     cssyyparse(this);
189     ASSERT(m_valueList);
190     return StyleKeyframe::createKeyList(m_valueList.get());
191 }
192
193 bool BisonCSSParser::parseSupportsCondition(const String& string)
194 {
195     m_supportsCondition = false;
196     setupParser("@-internal-supports-condition ", string, "");
197     cssyyparse(this);
198     return m_supportsCondition;
199 }
200
201 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const CSSParserContext& context)
202 {
203     ASSERT(!string.isEmpty());
204     BisonCSSParser parser(context);
205     return parser.parseValue(declaration, propertyID, string, important);
206 }
207
208 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important)
209 {
210     if (m_context.useCounter())
211         m_context.useCounter()->count(m_context, propertyID);
212
213     setupParser("@-internal-value ", string, "");
214
215     m_id = propertyID;
216     m_important = important;
217
218     {
219         StyleDeclarationScope scope(this, declaration);
220         cssyyparse(this);
221     }
222
223     m_rule = nullptr;
224     m_id = CSSPropertyInvalid;
225
226     bool ok = false;
227     if (!m_parsedProperties.isEmpty()) {
228         ok = true;
229         declaration->addParsedProperties(m_parsedProperties);
230         clearProperties();
231     }
232
233     return ok;
234 }
235
236 // The color will only be changed when string contains a valid CSS color, so callers
237 // can set it to a default color and ignore the boolean result.
238 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
239 {
240     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
241     if (CSSPropertyParser::fastParseColor(color, string, strict))
242         return true;
243
244     BisonCSSParser parser(strictCSSParserContext());
245
246     // In case the fast-path parser didn't understand the color, try the full parser.
247     if (!parser.parseColor(string))
248         return false;
249
250     CSSValue* value = parser.m_parsedProperties.first().value();
251     if (!value->isPrimitiveValue())
252         return false;
253
254     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
255     if (!primitiveValue->isRGBColor())
256         return false;
257
258     color = primitiveValue->getRGBA32Value();
259     return true;
260 }
261
262 StyleColor BisonCSSParser::colorFromRGBColorString(const String& colorString)
263 {
264     // FIXME: Rework css parser so it is more SVG aware.
265     RGBA32 color;
266     if (parseColor(color, colorString.stripWhiteSpace()))
267         return StyleColor(color);
268     // FIXME: This branch catches the string currentColor, but we should error if we have an illegal color value.
269     return StyleColor::currentColor();
270 }
271
272 bool BisonCSSParser::parseColor(const String& string)
273 {
274     setupParser("@-internal-decls color:", string, "");
275     cssyyparse(this);
276     m_rule = nullptr;
277
278     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
279 }
280
281 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
282 {
283     CSSParserString cssColor;
284     cssColor.init(string);
285     CSSValueID id = cssValueKeywordID(cssColor);
286     if (!CSSPropertyParser::isSystemColor(id))
287         return false;
288
289     Color parsedColor = RenderTheme::theme().systemColor(id);
290     color = parsedColor.rgb();
291     return true;
292 }
293
294 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
295 {
296     m_selectorListForParseSelector = &selectorList;
297
298     setupParser("@-internal-selector ", string, "");
299
300     cssyyparse(this);
301
302     m_selectorListForParseSelector = 0;
303 }
304
305 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
306 {
307     Document& document = element->document();
308     CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
309     context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
310     return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
311 }
312
313 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
314 {
315     setStyleSheet(contextStyleSheet);
316
317     setupParser("@-internal-decls ", string, "");
318     cssyyparse(this);
319     m_rule = nullptr;
320
321     RefPtrWillBeRawPtr<ImmutableStylePropertySet> style = createStylePropertySet();
322     clearProperties();
323     return style.release();
324 }
325
326
327 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
328 {
329     setStyleSheet(contextStyleSheet);
330
331     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
332
333     setupParser("@-internal-decls ", string, "");
334     if (m_observer) {
335         m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
336         m_observer->endRuleHeader(1);
337         m_observer->startRuleBody(0);
338     }
339
340     {
341         StyleDeclarationScope scope(this, declaration);
342         cssyyparse(this);
343     }
344
345     m_rule = nullptr;
346
347     bool ok = false;
348     if (!m_parsedProperties.isEmpty()) {
349         ok = true;
350         declaration->addParsedProperties(m_parsedProperties);
351         clearProperties();
352     }
353
354     if (m_observer)
355         m_observer->endRuleBody(string.length(), false);
356
357     return ok;
358 }
359
360 bool BisonCSSParser::parseAttributeMatchType(CSSSelector::AttributeMatchType& matchType, const String& string)
361 {
362     if (!RuntimeEnabledFeatures::cssAttributeCaseSensitivityEnabled() && !isUASheetBehavior(m_context.mode()))
363         return false;
364     if (string == "i") {
365         matchType = CSSSelector::CaseInsensitive;
366         return true;
367     }
368     return false;
369 }
370
371 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
372 {
373     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
374     for (int i = input.size() - 1; i >= 0; --i) {
375         const CSSProperty& property = input[i];
376         if (property.isImportant() != important)
377             continue;
378         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
379         if (seenProperties.get(propertyIDIndex))
380             continue;
381         seenProperties.set(propertyIDIndex);
382         output[--unusedEntries] = property;
383     }
384 }
385
386 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
387 {
388     BitArray<numCSSProperties> seenProperties;
389     size_t unusedEntries = m_parsedProperties.size();
390     WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
391
392     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
393     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
394     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
395     if (unusedEntries)
396         results.remove(0, unusedEntries);
397
398     CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
399
400     return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
401 }
402
403 void BisonCSSParser::rollbackLastProperties(int num)
404 {
405     ASSERT(num >= 0);
406     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
407     m_parsedProperties.shrink(m_parsedProperties.size() - num);
408 }
409
410 void BisonCSSParser::clearProperties()
411 {
412     m_parsedProperties.clear();
413     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
414 }
415
416 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
417 {
418     m_id = propId;
419 }
420
421 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
422 {
423     return CSSPropertyParser::parseValue(propId, important, m_valueList.get(), m_context, m_inViewport, m_parsedProperties, m_ruleHeaderType);
424 }
425
426 void BisonCSSParser::ensureLineEndings()
427 {
428     if (!m_lineEndings)
429         m_lineEndings = lineEndings(*m_source);
430 }
431
432 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
433 {
434     CSSParserSelector* selector = new CSSParserSelector(tagQName);
435     m_floatingSelectors.append(selector);
436     return selector;
437 }
438
439 CSSParserSelector* BisonCSSParser::createFloatingSelector()
440 {
441     CSSParserSelector* selector = new CSSParserSelector;
442     m_floatingSelectors.append(selector);
443     return selector;
444 }
445
446 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
447 {
448     if (selector) {
449         size_t index = m_floatingSelectors.reverseFind(selector);
450         ASSERT(index != kNotFound);
451         m_floatingSelectors.remove(index);
452     }
453     return adoptPtr(selector);
454 }
455
456 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
457 {
458     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
459     m_floatingSelectorVectors.append(selectorVector);
460     return selectorVector;
461 }
462
463 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
464 {
465     if (selectorVector) {
466         size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
467         ASSERT(index != kNotFound);
468         m_floatingSelectorVectors.remove(index);
469     }
470     return adoptPtr(selectorVector);
471 }
472
473 CSSParserValueList* BisonCSSParser::createFloatingValueList()
474 {
475     CSSParserValueList* list = new CSSParserValueList;
476     m_floatingValueLists.append(list);
477     return list;
478 }
479
480 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
481 {
482     if (list) {
483         size_t index = m_floatingValueLists.reverseFind(list);
484         ASSERT(index != kNotFound);
485         m_floatingValueLists.remove(index);
486     }
487     return adoptPtr(list);
488 }
489
490 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
491 {
492     CSSParserFunction* function = new CSSParserFunction;
493     m_floatingFunctions.append(function);
494     function->id = cssValueKeywordID(name);
495     function->args = args;
496     return function;
497 }
498
499 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
500 {
501     if (function) {
502         size_t index = m_floatingFunctions.reverseFind(function);
503         ASSERT(index != kNotFound);
504         m_floatingFunctions.remove(index);
505     }
506     return adoptPtr(function);
507 }
508
509 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
510 {
511     if (value.unit == CSSParserValue::Function) {
512         size_t index = m_floatingFunctions.reverseFind(value.function);
513         ASSERT(index != kNotFound);
514         m_floatingFunctions.remove(index);
515     }
516     return value;
517 }
518
519 void BisonCSSParser::startMediaValue()
520 {
521     if (!m_observer)
522         return;
523     m_mediaQueryValueStartOffset = m_tokenizer.safeUserStringTokenOffset();
524 }
525
526 void BisonCSSParser::endMediaValue()
527 {
528     if (!m_observer)
529         return;
530     m_mediaQueryValueEndOffset = m_tokenizer.safeUserStringTokenOffset();
531 }
532
533 void BisonCSSParser::startMediaQuery()
534 {
535     if (!m_observer)
536         return;
537     m_observer->startMediaQuery();
538 }
539
540 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
541 {
542     m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
543     if (m_observer && m_floatingMediaQueryExp.get() && values) {
544         m_observer->startMediaQueryExp(m_mediaQueryValueStartOffset);
545         m_observer->endMediaQueryExp(m_mediaQueryValueEndOffset);
546     }
547     return m_floatingMediaQueryExp.get();
548 }
549
550 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
551 {
552     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
553     return m_floatingMediaQueryExp.release();
554 }
555
556 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
557 {
558     m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
559     return m_floatingMediaQueryExpList.get();
560 }
561
562 PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
563 {
564     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
565     return m_floatingMediaQueryExpList.release();
566 }
567
568 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
569 {
570     m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
571     if (m_observer)
572         m_observer->endMediaQuery();
573     return m_floatingMediaQuery.get();
574 }
575
576 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
577 {
578     return createFloatingMediaQuery(MediaQuery::None, MediaTypeNames::all, expressions);
579 }
580
581 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
582 {
583     return createFloatingMediaQuery(MediaQuery::Not, MediaTypeNames::all, sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
584 }
585
586 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
587 {
588     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
589     return m_floatingMediaQuery.release();
590 }
591
592 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
593 {
594     m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
595     return m_floatingKeyframeVector.get();
596 }
597
598 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
599 {
600     ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
601     return m_floatingKeyframeVector.release();
602 }
603
604 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
605 {
606     RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
607     MediaQuerySet* result = queries.get();
608     m_parsedMediaQuerySets.append(queries.release());
609     return result;
610 }
611
612 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
613 {
614     if (!media || !m_allowImportRules)
615         return 0;
616     RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
617     StyleRuleImport* result = rule.get();
618     m_parsedRules.append(rule.release());
619     return result;
620 }
621
622 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
623 {
624     m_allowImportRules = m_allowNamespaceDeclarations = false;
625     RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
626     if (rules) {
627         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
628     } else {
629         RuleList emptyRules;
630         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
631     }
632     StyleRuleMedia* result = rule.get();
633     m_parsedRules.append(rule.release());
634     return result;
635 }
636
637 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
638 {
639     m_allowImportRules = m_allowNamespaceDeclarations = false;
640
641     RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
642     RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
643     String conditionText;
644     unsigned conditionOffset = data->ruleHeaderRange.start + 9;
645     unsigned conditionLength = data->ruleHeaderRange.length() - 9;
646
647     if (m_tokenizer.is8BitSource())
648         conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
649     else
650         conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
651
652     if (rules) {
653         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
654     } else {
655         RuleList emptyRules;
656         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
657     }
658
659     StyleRuleSupports* result = rule.get();
660     m_parsedRules.append(rule.release());
661
662     return result;
663 }
664
665 void BisonCSSParser::markSupportsRuleHeaderStart()
666 {
667     if (!m_supportsRuleDataStack)
668         m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
669
670     RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
671     data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
672     m_supportsRuleDataStack->append(data);
673 }
674
675 void BisonCSSParser::markSupportsRuleHeaderEnd()
676 {
677     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
678
679     if (m_tokenizer.is8BitSource())
680         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
681     else
682         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
683 }
684
685 PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
686 {
687     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
688     RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
689     m_supportsRuleDataStack->removeLast();
690     return data.release();
691 }
692
693 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
694 {
695     OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
696     RuleList* listPtr = list.get();
697
698     m_parsedRuleLists.append(list.release());
699     return listPtr;
700 }
701
702 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
703 {
704     if (rule) {
705         if (!ruleList)
706             ruleList = createRuleList();
707         ruleList->append(rule);
708     }
709     return ruleList;
710 }
711
712 template <typename CharacterType>
713 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
714 {
715     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
716     // that can potentially change the length of the string rather than the character
717     // by character kind. If we don't need Unicode lowercasing, it would be good to
718     // simplify this function.
719
720     if (charactersAreAllASCII(input, length)) {
721         // Fast case for all-ASCII.
722         for (unsigned i = 0; i < length; i++)
723             output[i] = toASCIILower(input[i]);
724     } else {
725         for (unsigned i = 0; i < length; i++)
726             output[i] = Unicode::toLower(input[i]);
727     }
728 }
729
730 void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
731 {
732     // Since it's our internal token, we know that we created it out
733     // of our writable work buffers. Therefore the const_cast is just
734     // ugly and not a potential crash.
735     size_t length = token.length();
736     if (token.is8Bit()) {
737         makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
738     } else {
739         makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
740     }
741 }
742
743 void BisonCSSParser::endInvalidRuleHeader()
744 {
745     if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
746         return;
747
748     CSSParserLocation location;
749     location.lineNumber = m_tokenizer.m_lineNumber;
750     location.offset = m_ruleHeaderStartOffset;
751     if (m_tokenizer.is8BitSource())
752         location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
753     else
754         location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
755
756     reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
757
758     endRuleHeader();
759 }
760
761 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
762 {
763     // FIXME: error reporting temporatily disabled.
764 }
765
766 bool BisonCSSParser::isLoggingErrors()
767 {
768     return m_logErrors && !m_ignoreErrors;
769 }
770
771 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
772 {
773     unsigned lineNumberInStyleSheet;
774     unsigned columnNumber = 0;
775     if (InspectorInstrumentation::hasFrontends()) {
776         ensureLineEndings();
777         TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
778         lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
779         columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
780     } else {
781         lineNumberInStyleSheet = location.lineNumber;
782     }
783     FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
784     console.addMessage(ConsoleMessage::create(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1));
785 }
786
787 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
788 {
789     OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
790     m_allowImportRules = m_allowNamespaceDeclarations = false;
791     RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
792     for (size_t i = 0; i < keyframes->size(); ++i)
793         rule->parserAppendKeyframe(keyframes->at(i));
794     rule->setName(name);
795     rule->setVendorPrefixed(isPrefixed);
796     StyleRuleKeyframes* rulePtr = rule.get();
797     m_parsedRules.append(rule.release());
798     return rulePtr;
799 }
800
801 static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList)
802 {
803     if (!context.useCounter())
804         return;
805
806     for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
807         for (const CSSSelector* current = selector; current ; current = current->tagHistory()) {
808             UseCounter::Feature feature = UseCounter::NumberOfFeatures;
809             switch (current->pseudoType()) {
810             case CSSSelector::PseudoUnresolved:
811                 feature = UseCounter::CSSSelectorPseudoUnresolved;
812                 break;
813             case CSSSelector::PseudoShadow:
814                 feature = UseCounter::CSSSelectorPseudoShadow;
815                 break;
816             case CSSSelector::PseudoContent:
817                 feature = UseCounter::CSSSelectorPseudoContent;
818                 break;
819             case CSSSelector::PseudoHost:
820                 feature = UseCounter::CSSSelectorPseudoHost;
821                 break;
822             case CSSSelector::PseudoHostContext:
823                 feature = UseCounter::CSSSelectorPseudoHostContext;
824                 break;
825             default:
826                 break;
827             }
828             if (feature != UseCounter::NumberOfFeatures)
829                 context.useCounter()->count(feature);
830             if (current->relation() == CSSSelector::ShadowDeep)
831                 context.useCounter()->count(UseCounter::CSSDeepCombinator);
832             if (current->selectorList())
833                 recordSelectorStats(context, *current->selectorList());
834         }
835     }
836 }
837
838 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
839 {
840     StyleRule* result = 0;
841     if (selectors) {
842         m_allowImportRules = m_allowNamespaceDeclarations = false;
843         RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
844         rule->parserAdoptSelectorVector(*selectors);
845         rule->setProperties(createStylePropertySet());
846         result = rule.get();
847         m_parsedRules.append(rule.release());
848         recordSelectorStats(m_context, result->selectorList());
849     }
850     clearProperties();
851     return result;
852 }
853
854 StyleRuleBase* BisonCSSParser::createFontFaceRule()
855 {
856     m_allowImportRules = m_allowNamespaceDeclarations = false;
857     for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
858         CSSProperty& property = m_parsedProperties[i];
859         if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
860             property.wrapValueInCommaSeparatedList();
861         else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
862             // Unlike font-family property, font-family descriptor in @font-face rule
863             // has to be a value list with exactly one family name. It cannot have a
864             // have 'initial' value and cannot 'inherit' from parent.
865             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
866             clearProperties();
867             return 0;
868         }
869     }
870     RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
871     rule->setProperties(createStylePropertySet());
872     clearProperties();
873     StyleRuleFontFace* result = rule.get();
874     m_parsedRules.append(rule.release());
875     if (m_styleSheet)
876         m_styleSheet->setHasFontFaceRule(true);
877     return result;
878 }
879
880 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
881 {
882     if (!m_styleSheet || !m_allowNamespaceDeclarations)
883         return;
884     m_allowImportRules = false;
885     m_styleSheet->parserAddNamespace(prefix, uri);
886     if (prefix.isEmpty() && !uri.isNull())
887         m_defaultNamespace = uri;
888 }
889
890 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
891 {
892     if (!m_styleSheet)
893         return QualifiedName(prefix, localName, m_defaultNamespace);
894     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
895 }
896
897 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
898 {
899     if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
900         return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
901     return specifiers;
902 }
903
904 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
905 {
906     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
907     QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
908
909     if (specifiers->crossesTreeScopes())
910         return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
911
912     if (specifiers->isContentPseudoElement())
913         return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
914
915     // *:host never matches, so we can't discard the * otherwise we can't tell the
916     // difference between *:host and just :host.
917     if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
918         return specifiers;
919     if (specifiers->pseudoType() != CSSSelector::PseudoCue)
920         specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
921     return specifiers;
922 }
923
924 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
925 {
926     CSSParserSelector* lastShadowPseudo = specifiers;
927     CSSParserSelector* history = specifiers;
928     while (history->tagHistory()) {
929         history = history->tagHistory();
930         if (history->crossesTreeScopes() || history->hasShadowPseudo())
931             lastShadowPseudo = history;
932     }
933
934     if (lastShadowPseudo->tagHistory()) {
935         if (tag != anyQName())
936             lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
937         return specifiers;
938     }
939
940     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
941     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
942     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
943     lastShadowPseudo->setTagHistory(elementNameSelector.release());
944     lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
945     return specifiers;
946 }
947
948 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
949 {
950     CSSParserSelector* last = specifiers;
951     CSSParserSelector* history = specifiers;
952     while (history->tagHistory()) {
953         history = history->tagHistory();
954         if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
955             last = history;
956     }
957
958     if (last->tagHistory()) {
959         if (tag != anyQName())
960             last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
961         return specifiers;
962     }
963
964     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
965     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
966     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
967     last->setTagHistory(elementNameSelector.release());
968     return specifiers;
969 }
970
971 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
972 {
973     if (newSpecifier->crossesTreeScopes()) {
974         // Unknown pseudo element always goes at the top of selector chain.
975         newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
976         return newSpecifier;
977     }
978     if (newSpecifier->isContentPseudoElement()) {
979         newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
980         return newSpecifier;
981     }
982     if (specifiers->crossesTreeScopes()) {
983         // Specifiers for unknown pseudo element go right behind it in the chain.
984         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
985         return specifiers;
986     }
987     if (specifiers->isContentPseudoElement()) {
988         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
989         return specifiers;
990     }
991     specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
992     return specifiers;
993 }
994
995 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
996 {
997     // FIXME: Margin at-rules are ignored.
998     m_allowImportRules = m_allowNamespaceDeclarations = false;
999     StyleRulePage* pageRule = 0;
1000     if (pageSelector) {
1001         RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
1002         Vector<OwnPtr<CSSParserSelector> > selectorVector;
1003         selectorVector.append(pageSelector);
1004         rule->parserAdoptSelectorVector(selectorVector);
1005         rule->setProperties(createStylePropertySet());
1006         pageRule = rule.get();
1007         m_parsedRules.append(rule.release());
1008     }
1009     clearProperties();
1010     return pageRule;
1011 }
1012
1013 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
1014 {
1015     // FIXME: Implement margin at-rule here, using:
1016     //        - marginBox: margin box
1017     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
1018     // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
1019
1020     endDeclarationsForMarginBox();
1021     return 0; // until this method is implemented.
1022 }
1023
1024 void BisonCSSParser::startDeclarationsForMarginBox()
1025 {
1026     m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
1027 }
1028
1029 void BisonCSSParser::endDeclarationsForMarginBox()
1030 {
1031     rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
1032     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1033 }
1034
1035 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
1036 {
1037     OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
1038     if (keyVector->isEmpty())
1039         return 0;
1040
1041     RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
1042     keyframe->setKeys(keyVector.release());
1043     keyframe->setProperties(createStylePropertySet());
1044
1045     clearProperties();
1046
1047     StyleKeyframe* keyframePtr = keyframe.get();
1048     m_parsedKeyframes.append(keyframe.release());
1049     return keyframePtr;
1050 }
1051
1052 void BisonCSSParser::invalidBlockHit()
1053 {
1054     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
1055         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
1056 }
1057
1058 void BisonCSSParser::startRule()
1059 {
1060     if (!m_observer)
1061         return;
1062
1063     ASSERT(m_ruleHasHeader);
1064     m_ruleHasHeader = false;
1065 }
1066
1067 void BisonCSSParser::endRule(bool valid)
1068 {
1069     if (!m_observer)
1070         return;
1071
1072     if (m_ruleHasHeader)
1073         m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
1074     m_ruleHasHeader = true;
1075 }
1076
1077 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
1078 {
1079     resumeErrorLogging();
1080     m_ruleHeaderType = ruleType;
1081     m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
1082     m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
1083     if (m_observer) {
1084         ASSERT(!m_ruleHasHeader);
1085         m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
1086         m_ruleHasHeader = true;
1087     }
1088 }
1089
1090 void BisonCSSParser::endRuleHeader()
1091 {
1092     ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
1093     m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
1094     if (m_observer) {
1095         ASSERT(m_ruleHasHeader);
1096         m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
1097     }
1098 }
1099
1100 void BisonCSSParser::startSelector()
1101 {
1102     if (m_observer)
1103         m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
1104 }
1105
1106 void BisonCSSParser::endSelector()
1107 {
1108     if (m_observer)
1109         m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
1110 }
1111
1112 void BisonCSSParser::startRuleBody()
1113 {
1114     if (m_observer)
1115         m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
1116 }
1117
1118 void BisonCSSParser::startProperty()
1119 {
1120     resumeErrorLogging();
1121     if (m_observer)
1122         m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
1123 }
1124
1125 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
1126 {
1127     m_id = CSSPropertyInvalid;
1128     if (m_observer)
1129         m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
1130 }
1131
1132 StyleRuleBase* BisonCSSParser::createViewportRule()
1133 {
1134     // Allow @viewport rules from UA stylesheets even if the feature is disabled.
1135     if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
1136         return 0;
1137
1138     m_allowImportRules = m_allowNamespaceDeclarations = false;
1139
1140     RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
1141
1142     rule->setProperties(createStylePropertySet());
1143     clearProperties();
1144
1145     StyleRuleViewport* result = rule.get();
1146     m_parsedRules.append(rule.release());
1147
1148     return result;
1149 }
1150
1151 }