Upstream version 11.39.250.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/CSSAspectRatioValue.h"
34 #include "core/css/CSSBasicShapes.h"
35 #include "core/css/CSSBorderImage.h"
36 #include "core/css/CSSCanvasValue.h"
37 #include "core/css/CSSCrossfadeValue.h"
38 #include "core/css/CSSCursorImageValue.h"
39 #include "core/css/CSSFontFaceSrcValue.h"
40 #include "core/css/CSSFontFeatureValue.h"
41 #include "core/css/CSSFunctionValue.h"
42 #include "core/css/CSSGradientValue.h"
43 #include "core/css/CSSGridLineNamesValue.h"
44 #include "core/css/CSSGridTemplateAreasValue.h"
45 #include "core/css/CSSImageSetValue.h"
46 #include "core/css/CSSImageValue.h"
47 #include "core/css/CSSInheritedValue.h"
48 #include "core/css/CSSInitialValue.h"
49 #include "core/css/CSSKeyframeRule.h"
50 #include "core/css/CSSKeyframesRule.h"
51 #include "core/css/CSSLineBoxContainValue.h"
52 #include "core/css/CSSPrimitiveValue.h"
53 #include "core/css/CSSPropertySourceData.h"
54 #include "core/css/CSSReflectValue.h"
55 #include "core/css/CSSSelector.h"
56 #include "core/css/CSSShadowValue.h"
57 #include "core/css/CSSStyleSheet.h"
58 #include "core/css/CSSTimingFunctionValue.h"
59 #include "core/css/CSSTransformValue.h"
60 #include "core/css/CSSUnicodeRangeValue.h"
61 #include "core/css/CSSValueList.h"
62 #include "core/css/CSSValuePool.h"
63 #include "core/css/Counter.h"
64 #include "core/css/HashTools.h"
65 #include "core/css/MediaList.h"
66 #include "core/css/MediaQueryExp.h"
67 #include "core/css/Pair.h"
68 #include "core/css/Rect.h"
69 #include "core/css/StylePropertySet.h"
70 #include "core/css/StyleRule.h"
71 #include "core/css/StyleRuleImport.h"
72 #include "core/css/StyleSheetContents.h"
73 #include "core/css/parser/CSSParserIdioms.h"
74 #include "core/dom/Document.h"
75 #include "core/frame/FrameConsole.h"
76 #include "core/frame/FrameHost.h"
77 #include "core/frame/Settings.h"
78 #include "core/frame/UseCounter.h"
79 #include "core/html/parser/HTMLParserIdioms.h"
80 #include "core/inspector/ConsoleMessage.h"
81 #include "core/inspector/InspectorInstrumentation.h"
82 #include "core/rendering/RenderTheme.h"
83 #include "platform/FloatConversion.h"
84 #include "platform/RuntimeEnabledFeatures.h"
85 #include "wtf/BitArray.h"
86 #include "wtf/HexNumber.h"
87 #include "wtf/text/StringBuffer.h"
88 #include "wtf/text/StringBuilder.h"
89 #include "wtf/text/StringImpl.h"
90 #include "wtf/text/TextEncoding.h"
91 #include <limits.h>
92
93 #define YYDEBUG 0
94
95 #if YYDEBUG > 0
96 extern int cssyydebug;
97 #endif
98
99 int cssyyparse(blink::BisonCSSParser*);
100
101 using namespace WTF;
102
103 namespace blink {
104
105 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
106
107 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
108     : m_context(context)
109     , m_important(false)
110     , m_id(CSSPropertyInvalid)
111     , m_styleSheet(nullptr)
112     , m_supportsCondition(false)
113     , m_selectorListForParseSelector(0)
114     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
115     , m_hadSyntacticallyValidCSSRule(false)
116     , m_logErrors(false)
117     , m_ignoreErrors(false)
118     , m_defaultNamespace(starAtom)
119     , m_observer(0)
120     , m_source(0)
121     , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
122     , m_allowImportRules(true)
123     , m_allowNamespaceDeclarations(true)
124     , m_inViewport(false)
125     , m_tokenizer(*this)
126 {
127 #if YYDEBUG > 0
128     cssyydebug = 1;
129 #endif
130 }
131
132 BisonCSSParser::~BisonCSSParser()
133 {
134     clearProperties();
135
136     deleteAllValues(m_floatingSelectors);
137     deleteAllValues(m_floatingSelectorVectors);
138     deleteAllValues(m_floatingValueLists);
139     deleteAllValues(m_floatingFunctions);
140 }
141
142 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
143 {
144     m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
145     m_ruleHasHeader = true;
146 }
147
148 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
149 {
150     setStyleSheet(sheet);
151     m_defaultNamespace = starAtom; // Reset the default namespace.
152     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
153     m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
154     m_ignoreErrors = false;
155     m_tokenizer.m_lineNumber = 0;
156     m_startPosition = startPosition;
157     m_source = &string;
158     m_tokenizer.m_internal = false;
159     setupParser("", string, "");
160     cssyyparse(this);
161     sheet->shrinkToFit();
162     m_source = 0;
163     m_rule = nullptr;
164     m_lineEndings.clear();
165     m_ignoreErrors = false;
166     m_logErrors = false;
167     m_tokenizer.m_internal = true;
168 }
169
170 PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
171 {
172     setStyleSheet(sheet);
173     m_allowNamespaceDeclarations = false;
174     setupParser("@-internal-rule ", string, "");
175     cssyyparse(this);
176     return m_rule.release();
177 }
178
179 PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
180 {
181     setStyleSheet(sheet);
182     setupParser("@-internal-keyframe-rule ", string, "");
183     cssyyparse(this);
184     return m_keyframe.release();
185 }
186
187 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
188 {
189     setupParser("@-internal-keyframe-key-list ", string, "");
190     cssyyparse(this);
191     ASSERT(m_valueList);
192     return StyleKeyframe::createKeyList(m_valueList.get());
193 }
194
195 bool BisonCSSParser::parseSupportsCondition(const String& string)
196 {
197     m_supportsCondition = false;
198     setupParser("@-internal-supports-condition ", string, "");
199     cssyyparse(this);
200     return m_supportsCondition;
201 }
202
203 static inline bool isColorPropertyID(CSSPropertyID propertyId)
204 {
205     switch (propertyId) {
206     case CSSPropertyColor:
207     case CSSPropertyBackgroundColor:
208     case CSSPropertyBorderBottomColor:
209     case CSSPropertyBorderLeftColor:
210     case CSSPropertyBorderRightColor:
211     case CSSPropertyBorderTopColor:
212     case CSSPropertyOutlineColor:
213     case CSSPropertyWebkitBorderAfterColor:
214     case CSSPropertyWebkitBorderBeforeColor:
215     case CSSPropertyWebkitBorderEndColor:
216     case CSSPropertyWebkitBorderStartColor:
217     case CSSPropertyWebkitColumnRuleColor:
218     case CSSPropertyWebkitTextEmphasisColor:
219     case CSSPropertyWebkitTextFillColor:
220     case CSSPropertyWebkitTextStrokeColor:
221     case CSSPropertyTextDecorationColor:
222         return true;
223     default:
224         return false;
225     }
226 }
227
228 static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
229 {
230     ASSERT(!string.isEmpty());
231     bool quirksMode = isQuirksModeBehavior(cssParserMode);
232     if (!isColorPropertyID(propertyId))
233         return false;
234     CSSParserString cssString;
235     cssString.init(string);
236     CSSValueID valueID = cssValueKeywordID(cssString);
237     bool validPrimitive = false;
238     if (valueID == CSSValueWebkitText) {
239         validPrimitive = true;
240     } else if (valueID == CSSValueCurrentcolor) {
241         validPrimitive = true;
242     } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
243         || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
244         validPrimitive = true;
245     }
246
247     if (validPrimitive) {
248         RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
249         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
250         return true;
251     }
252     RGBA32 color;
253     if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
254         return false;
255     RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color);
256     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
257     return true;
258 }
259
260 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
261 {
262     switch (propertyId) {
263     case CSSPropertyFontSize:
264     case CSSPropertyHeight:
265     case CSSPropertyWidth:
266     case CSSPropertyMinHeight:
267     case CSSPropertyMinWidth:
268     case CSSPropertyPaddingBottom:
269     case CSSPropertyPaddingLeft:
270     case CSSPropertyPaddingRight:
271     case CSSPropertyPaddingTop:
272     case CSSPropertyWebkitLogicalWidth:
273     case CSSPropertyWebkitLogicalHeight:
274     case CSSPropertyWebkitMinLogicalWidth:
275     case CSSPropertyWebkitMinLogicalHeight:
276     case CSSPropertyWebkitPaddingAfter:
277     case CSSPropertyWebkitPaddingBefore:
278     case CSSPropertyWebkitPaddingEnd:
279     case CSSPropertyWebkitPaddingStart:
280         acceptsNegativeNumbers = false;
281         return true;
282     case CSSPropertyShapeMargin:
283         acceptsNegativeNumbers = false;
284         return true;
285     case CSSPropertyBottom:
286     case CSSPropertyLeft:
287     case CSSPropertyMarginBottom:
288     case CSSPropertyMarginLeft:
289     case CSSPropertyMarginRight:
290     case CSSPropertyMarginTop:
291     case CSSPropertyRight:
292     case CSSPropertyTop:
293     case CSSPropertyWebkitMarginAfter:
294     case CSSPropertyWebkitMarginBefore:
295     case CSSPropertyWebkitMarginEnd:
296     case CSSPropertyWebkitMarginStart:
297         acceptsNegativeNumbers = true;
298         return true;
299     default:
300         return false;
301     }
302 }
303
304 template <typename CharacterType>
305 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number)
306 {
307     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
308         length -= 2;
309         unit = CSSPrimitiveValue::CSS_PX;
310     } else if (length > 1 && characters[length - 1] == '%') {
311         length -= 1;
312         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
313     }
314
315     // We rely on charactersToDouble for validation as well. The function
316     // will set "ok" to "false" if the entire passed-in character range does
317     // not represent a double.
318     bool ok;
319     number = charactersToDouble(characters, length, &ok);
320     return ok;
321 }
322
323 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
324 {
325     ASSERT(!string.isEmpty());
326     bool acceptsNegativeNumbers = false;
327
328     // In @viewport, width and height are shorthands, not simple length values.
329     if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
330         return false;
331
332     unsigned length = string.length();
333     double number;
334     CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
335
336     if (string.is8Bit()) {
337         if (!parseSimpleLength(string.characters8(), length, unit, number))
338             return false;
339     } else {
340         if (!parseSimpleLength(string.characters16(), length, unit, number))
341             return false;
342     }
343
344     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
345         bool quirksMode = isQuirksModeBehavior(cssParserMode);
346         if (number && !quirksMode)
347             return false;
348         unit = CSSPrimitiveValue::CSS_PX;
349     }
350     if (number < 0 && !acceptsNegativeNumbers)
351         return false;
352
353     RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit);
354     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
355     return true;
356 }
357
358 bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, const CSSParserContext& parserContext)
359 {
360     if (valueID == CSSValueInvalid)
361         return false;
362
363     switch (propertyId) {
364     case CSSPropertyAll:
365         return valueID == CSSValueUnset;
366     case CSSPropertyBackgroundRepeatX: // repeat | no-repeat
367     case CSSPropertyBackgroundRepeatY: // repeat | no-repeat
368         return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat;
369     case CSSPropertyBorderCollapse: // collapse | separate
370         return valueID == CSSValueCollapse || valueID == CSSValueSeparate;
371     case CSSPropertyBorderTopStyle: // <border-style>
372     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
373     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
374     case CSSPropertyBorderLeftStyle:
375     case CSSPropertyWebkitBorderAfterStyle:
376     case CSSPropertyWebkitBorderBeforeStyle:
377     case CSSPropertyWebkitBorderEndStyle:
378     case CSSPropertyWebkitBorderStartStyle:
379     case CSSPropertyWebkitColumnRuleStyle:
380         return valueID >= CSSValueNone && valueID <= CSSValueDouble;
381     case CSSPropertyBoxSizing:
382         return valueID == CSSValueBorderBox || valueID == CSSValueContentBox;
383     case CSSPropertyCaptionSide: // top | bottom | left | right
384         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom;
385     case CSSPropertyClear: // none | left | right | both
386         return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth;
387     case CSSPropertyDirection: // ltr | rtl
388         return valueID == CSSValueLtr || valueID == CSSValueRtl;
389     case CSSPropertyDisplay:
390         // inline | block | list-item | inline-block | table |
391         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
392         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
393         // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid
394         return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone
395             || (RuntimeEnabledFeatures::cssGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid));
396     case CSSPropertyEmptyCells: // show | hide
397         return valueID == CSSValueShow || valueID == CSSValueHide;
398     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
399         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter;
400     case CSSPropertyFontStyle: // normal | italic | oblique
401         return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique;
402     case CSSPropertyFontStretch: // normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded
403         return valueID == CSSValueNormal || (valueID >= CSSValueUltraCondensed && valueID <= CSSValueUltraExpanded);
404     case CSSPropertyImageRendering: // auto | optimizeContrast | pixelated
405         return valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast || (RuntimeEnabledFeatures::imageRenderingPixelatedEnabled() && valueID == CSSValuePixelated);
406     case CSSPropertyIsolation: // auto | isolate
407         ASSERT(RuntimeEnabledFeatures::cssCompositingEnabled());
408         return valueID == CSSValueAuto || valueID == CSSValueIsolate;
409     case CSSPropertyListStylePosition: // inside | outside
410         return valueID == CSSValueInside || valueID == CSSValueOutside;
411     case CSSPropertyListStyleType:
412         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
413         // for the list of supported list-style-types.
414         return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone;
415     case CSSPropertyObjectFit:
416         return valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown;
417     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto
418         return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble);
419     case CSSPropertyOverflowWrap: // normal | break-word
420     case CSSPropertyWordWrap:
421         return valueID == CSSValueNormal || valueID == CSSValueBreakWord;
422     case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay
423         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay;
424     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y
425         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY;
426     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right
427     case CSSPropertyPageBreakBefore:
428     case CSSPropertyWebkitColumnBreakAfter:
429     case CSSPropertyWebkitColumnBreakBefore:
430         return valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight;
431     case CSSPropertyPageBreakInside: // avoid | auto
432     case CSSPropertyWebkitColumnBreakInside:
433         return valueID == CSSValueAuto || valueID == CSSValueAvoid;
434     case CSSPropertyPointerEvents:
435         // none | visiblePainted | visibleFill | visibleStroke | visible |
436         // painted | fill | stroke | auto | all | bounding-box
437         return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox);
438     case CSSPropertyPosition: // static | relative | absolute | fixed
439         return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed;
440     case CSSPropertyResize: // none | both | horizontal | vertical | auto
441         return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
442     case CSSPropertyScrollBehavior: // instant | smooth
443         ASSERT(RuntimeEnabledFeatures::cssomSmoothScrollEnabled());
444         return valueID == CSSValueInstant || valueID == CSSValueSmooth;
445     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation
446         return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation;
447     case CSSPropertyTableLayout: // auto | fixed
448         return valueID == CSSValueAuto || valueID == CSSValueFixed;
449     case CSSPropertyTextAlignLast:
450         // auto | start | end | left | right | center | justify
451         ASSERT(RuntimeEnabledFeatures::css3TextEnabled());
452         return (valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto;
453     case CSSPropertyTextDecorationStyle:
454         // solid | double | dotted | dashed | wavy
455         ASSERT(RuntimeEnabledFeatures::css3TextDecorationsEnabled());
456         return valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDotted || valueID == CSSValueDashed || valueID == CSSValueWavy;
457     case CSSPropertyTextJustify:
458         // auto | none | inter-word | distribute
459         ASSERT(RuntimeEnabledFeatures::css3TextEnabled());
460         return valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone;
461     case CSSPropertyTextOverflow: // clip | ellipsis
462         return valueID == CSSValueClip || valueID == CSSValueEllipsis;
463     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
464         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision;
465     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none
466         return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone;
467     case CSSPropertyUnicodeBidi:
468         return valueID == CSSValueNormal || valueID == CSSValueEmbed
469             || valueID == CSSValueBidiOverride || valueID == CSSValueWebkitIsolate
470             || valueID == CSSValueWebkitIsolateOverride || valueID == CSSValueWebkitPlaintext;
471     case CSSPropertyTouchActionDelay: // none | script
472         ASSERT(RuntimeEnabledFeatures::cssTouchActionDelayEnabled());
473         return valueID == CSSValueScript || valueID == CSSValueNone;
474     case CSSPropertyVisibility: // visible | hidden | collapse
475         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse;
476     case CSSPropertyWebkitAppearance:
477         return (valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone;
478     case CSSPropertyBackfaceVisibility:
479     case CSSPropertyWebkitBackfaceVisibility:
480         return valueID == CSSValueVisible || valueID == CSSValueHidden;
481     case CSSPropertyMixBlendMode:
482         ASSERT(RuntimeEnabledFeatures::cssCompositingEnabled());
483         return valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay
484             || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn
485             || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion
486             || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity;
487     case CSSPropertyWebkitBorderFit:
488         return valueID == CSSValueBorder || valueID == CSSValueLines;
489     case CSSPropertyWebkitBoxAlign:
490         return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline;
491     case CSSPropertyWebkitBoxDecorationBreak:
492         return valueID == CSSValueClone || valueID == CSSValueSlice;
493     case CSSPropertyWebkitBoxDirection:
494         return valueID == CSSValueNormal || valueID == CSSValueReverse;
495     case CSSPropertyWebkitBoxLines:
496         return valueID == CSSValueSingle || valueID == CSSValueMultiple;
497     case CSSPropertyWebkitBoxOrient:
498         return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis;
499     case CSSPropertyWebkitBoxPack:
500         return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify;
501     case CSSPropertyColumnFill:
502         ASSERT(RuntimeEnabledFeatures::regionBasedColumnsEnabled());
503         return valueID == CSSValueAuto || valueID == CSSValueBalance;
504     case CSSPropertyAlignContent:
505         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
506         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch;
507     case CSSPropertyAlignItems:
508         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
509         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
510     case CSSPropertyAlignSelf:
511         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
512         return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
513     case CSSPropertyFlexDirection:
514         return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse;
515     case CSSPropertyFlexWrap:
516         return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse;
517     case CSSPropertyJustifyContent:
518         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
519         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround;
520     case CSSPropertyFontKerning:
521         return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone;
522     case CSSPropertyWebkitFontSmoothing:
523         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased;
524     case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
525         return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace;
526     case CSSPropertyWebkitMarginAfterCollapse:
527     case CSSPropertyWebkitMarginBeforeCollapse:
528     case CSSPropertyWebkitMarginBottomCollapse:
529     case CSSPropertyWebkitMarginTopCollapse:
530         return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard;
531     case CSSPropertyInternalMarqueeDirection:
532         return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
533             || valueID == CSSValueUp || valueID == CSSValueAuto;
534     case CSSPropertyInternalMarqueeStyle:
535         return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate;
536     case CSSPropertyWebkitPrintColorAdjust:
537         return valueID == CSSValueExact || valueID == CSSValueEconomy;
538     case CSSPropertyWebkitRtlOrdering:
539         return valueID == CSSValueLogical || valueID == CSSValueVisual;
540     case CSSPropertyWebkitRubyPosition:
541         return valueID == CSSValueBefore || valueID == CSSValueAfter;
542     case CSSPropertyWebkitTextCombine:
543         return valueID == CSSValueNone || valueID == CSSValueHorizontal;
544     case CSSPropertyWebkitTextEmphasisPosition:
545         return valueID == CSSValueOver || valueID == CSSValueUnder;
546     case CSSPropertyWebkitTextSecurity: // disc | circle | square | none
547         return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone;
548     case CSSPropertyTransformStyle:
549     case CSSPropertyWebkitTransformStyle:
550         return valueID == CSSValueFlat || valueID == CSSValuePreserve3d;
551     case CSSPropertyWebkitUserDrag: // auto | none | element
552         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement;
553     case CSSPropertyWebkitUserModify: // read-only | read-write
554         return valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly;
555     case CSSPropertyWebkitUserSelect: // auto | none | text | all
556         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll;
557     case CSSPropertyWebkitWritingMode:
558         return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt;
559     case CSSPropertyWhiteSpace: // normal | pre | nowrap
560         return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
561     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
562         return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord;
563     default:
564         ASSERT_NOT_REACHED();
565         return false;
566     }
567     return false;
568 }
569
570 bool isKeywordPropertyID(CSSPropertyID propertyId)
571 {
572     switch (propertyId) {
573     case CSSPropertyAll:
574     case CSSPropertyMixBlendMode:
575     case CSSPropertyIsolation:
576     case CSSPropertyBackgroundRepeatX:
577     case CSSPropertyBackgroundRepeatY:
578     case CSSPropertyBorderBottomStyle:
579     case CSSPropertyBorderCollapse:
580     case CSSPropertyBorderLeftStyle:
581     case CSSPropertyBorderRightStyle:
582     case CSSPropertyBorderTopStyle:
583     case CSSPropertyBoxSizing:
584     case CSSPropertyCaptionSide:
585     case CSSPropertyClear:
586     case CSSPropertyDirection:
587     case CSSPropertyDisplay:
588     case CSSPropertyEmptyCells:
589     case CSSPropertyFloat:
590     case CSSPropertyFontStyle:
591     case CSSPropertyFontStretch:
592     case CSSPropertyImageRendering:
593     case CSSPropertyListStylePosition:
594     case CSSPropertyListStyleType:
595     case CSSPropertyObjectFit:
596     case CSSPropertyOutlineStyle:
597     case CSSPropertyOverflowWrap:
598     case CSSPropertyOverflowX:
599     case CSSPropertyOverflowY:
600     case CSSPropertyPageBreakAfter:
601     case CSSPropertyPageBreakBefore:
602     case CSSPropertyPageBreakInside:
603     case CSSPropertyPointerEvents:
604     case CSSPropertyPosition:
605     case CSSPropertyResize:
606     case CSSPropertyScrollBehavior:
607     case CSSPropertySpeak:
608     case CSSPropertyTableLayout:
609     case CSSPropertyTextAlignLast:
610     case CSSPropertyTextDecorationStyle:
611     case CSSPropertyTextJustify:
612     case CSSPropertyTextOverflow:
613     case CSSPropertyTextRendering:
614     case CSSPropertyTextTransform:
615     case CSSPropertyTouchActionDelay:
616     case CSSPropertyUnicodeBidi:
617     case CSSPropertyVisibility:
618     case CSSPropertyWebkitAppearance:
619     case CSSPropertyBackfaceVisibility:
620     case CSSPropertyWebkitBackfaceVisibility:
621     case CSSPropertyWebkitBorderAfterStyle:
622     case CSSPropertyWebkitBorderBeforeStyle:
623     case CSSPropertyWebkitBorderEndStyle:
624     case CSSPropertyWebkitBorderFit:
625     case CSSPropertyWebkitBorderStartStyle:
626     case CSSPropertyWebkitBoxAlign:
627     case CSSPropertyWebkitBoxDecorationBreak:
628     case CSSPropertyWebkitBoxDirection:
629     case CSSPropertyWebkitBoxLines:
630     case CSSPropertyWebkitBoxOrient:
631     case CSSPropertyWebkitBoxPack:
632     case CSSPropertyWebkitColumnBreakAfter:
633     case CSSPropertyWebkitColumnBreakBefore:
634     case CSSPropertyWebkitColumnBreakInside:
635     case CSSPropertyColumnFill:
636     case CSSPropertyWebkitColumnRuleStyle:
637     case CSSPropertyAlignContent:
638     case CSSPropertyFlexDirection:
639     case CSSPropertyFlexWrap:
640     case CSSPropertyJustifyContent:
641     case CSSPropertyFontKerning:
642     case CSSPropertyWebkitFontSmoothing:
643     case CSSPropertyWebkitLineBreak:
644     case CSSPropertyWebkitMarginAfterCollapse:
645     case CSSPropertyWebkitMarginBeforeCollapse:
646     case CSSPropertyWebkitMarginBottomCollapse:
647     case CSSPropertyWebkitMarginTopCollapse:
648     case CSSPropertyInternalMarqueeDirection:
649     case CSSPropertyInternalMarqueeStyle:
650     case CSSPropertyWebkitPrintColorAdjust:
651     case CSSPropertyWebkitRtlOrdering:
652     case CSSPropertyWebkitRubyPosition:
653     case CSSPropertyWebkitTextCombine:
654     case CSSPropertyWebkitTextEmphasisPosition:
655     case CSSPropertyWebkitTextSecurity:
656     case CSSPropertyTransformStyle:
657     case CSSPropertyWebkitTransformStyle:
658     case CSSPropertyWebkitUserDrag:
659     case CSSPropertyWebkitUserModify:
660     case CSSPropertyWebkitUserSelect:
661     case CSSPropertyWebkitWritingMode:
662     case CSSPropertyWhiteSpace:
663     case CSSPropertyWordBreak:
664     case CSSPropertyWordWrap:
665         return true;
666     case CSSPropertyAlignItems:
667     case CSSPropertyAlignSelf:
668         return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
669     default:
670         return false;
671     }
672 }
673
674 static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
675 {
676     ASSERT(!string.isEmpty());
677
678     if (!isKeywordPropertyID(propertyId)) {
679         // All properties accept the values of "initial" and "inherit".
680         String lowerCaseString = string.lower();
681         if (lowerCaseString != "initial" && lowerCaseString != "inherit")
682             return false;
683
684         // Parse initial/inherit shorthands using the BisonCSSParser.
685         if (shorthandForProperty(propertyId).length())
686             return false;
687     }
688
689     CSSParserString cssString;
690     cssString.init(string);
691     CSSValueID valueID = cssValueKeywordID(cssString);
692
693     if (!valueID)
694         return false;
695
696     RefPtrWillBeRawPtr<CSSValue> value = nullptr;
697     if (valueID == CSSValueInherit)
698         value = cssValuePool().createInheritedValue();
699     else if (valueID == CSSValueInitial)
700         value = cssValuePool().createExplicitInitialValue();
701     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
702         value = cssValuePool().createIdentifierValue(valueID);
703     else
704         return false;
705
706     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
707     return true;
708 }
709
710 template <typename CharType>
711 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
712 {
713     while (expectedCount) {
714         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
715         if (delimiter == kNotFound)
716             return false;
717         unsigned argumentLength = static_cast<unsigned>(delimiter);
718         CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
719         double number;
720         if (!parseSimpleLength(pos, argumentLength, unit, number))
721             return false;
722         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
723             return false;
724         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
725         pos += argumentLength + 1;
726         --expectedCount;
727     }
728     return true;
729 }
730
731 template <typename CharType>
732 static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
733 {
734     while (expectedCount) {
735         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
736         if (delimiter == kNotFound)
737             return false;
738         unsigned argumentLength = static_cast<unsigned>(delimiter);
739         bool ok;
740         double number = charactersToDouble(pos, argumentLength, &ok);
741         if (!ok)
742             return false;
743         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER));
744         pos += argumentLength + 1;
745         --expectedCount;
746     }
747     return true;
748 }
749
750 template <typename CharType>
751 static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
752 {
753     static const int shortestValidTransformStringLength = 12;
754
755     if (end - pos < shortestValidTransformStringLength)
756         return nullptr;
757
758     const bool isTranslate = toASCIILower(pos[0]) == 't'
759         && toASCIILower(pos[1]) == 'r'
760         && toASCIILower(pos[2]) == 'a'
761         && toASCIILower(pos[3]) == 'n'
762         && toASCIILower(pos[4]) == 's'
763         && toASCIILower(pos[5]) == 'l'
764         && toASCIILower(pos[6]) == 'a'
765         && toASCIILower(pos[7]) == 't'
766         && toASCIILower(pos[8]) == 'e';
767
768     if (isTranslate) {
769         CSSTransformValue::TransformOperationType transformType;
770         unsigned expectedArgumentCount = 1;
771         unsigned argumentStart = 11;
772         CharType c9 = toASCIILower(pos[9]);
773         if (c9 == 'x' && pos[10] == '(') {
774             transformType = CSSTransformValue::TranslateXTransformOperation;
775         } else if (c9 == 'y' && pos[10] == '(') {
776             transformType = CSSTransformValue::TranslateYTransformOperation;
777         } else if (c9 == 'z' && pos[10] == '(') {
778             transformType = CSSTransformValue::TranslateZTransformOperation;
779         } else if (c9 == '(') {
780             transformType = CSSTransformValue::TranslateTransformOperation;
781             expectedArgumentCount = 2;
782             argumentStart = 10;
783         } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
784             transformType = CSSTransformValue::Translate3DTransformOperation;
785             expectedArgumentCount = 3;
786             argumentStart = 12;
787         } else {
788             return nullptr;
789         }
790         pos += argumentStart;
791         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
792         if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
793             return nullptr;
794         return transformValue.release();
795     }
796
797     const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
798         && toASCIILower(pos[1]) == 'a'
799         && toASCIILower(pos[2]) == 't'
800         && toASCIILower(pos[3]) == 'r'
801         && toASCIILower(pos[4]) == 'i'
802         && toASCIILower(pos[5]) == 'x'
803         && pos[6] == '3'
804         && toASCIILower(pos[7]) == 'd'
805         && pos[8] == '(';
806
807     if (isMatrix3d) {
808         pos += 9;
809         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
810         if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
811             return nullptr;
812         return transformValue.release();
813     }
814
815     const bool isScale3d = toASCIILower(pos[0]) == 's'
816         && toASCIILower(pos[1]) == 'c'
817         && toASCIILower(pos[2]) == 'a'
818         && toASCIILower(pos[3]) == 'l'
819         && toASCIILower(pos[4]) == 'e'
820         && pos[5] == '3'
821         && toASCIILower(pos[6]) == 'd'
822         && pos[7] == '(';
823
824     if (isScale3d) {
825         pos += 8;
826         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation);
827         if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
828             return nullptr;
829         return transformValue.release();
830     }
831
832     return nullptr;
833 }
834
835 template <typename CharType>
836 static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end)
837 {
838     RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
839     while (pos < end) {
840         while (pos < end && isCSSSpace(*pos))
841             ++pos;
842         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end);
843         if (!transformValue)
844             return nullptr;
845         if (!transformList)
846             transformList = CSSValueList::createSpaceSeparated();
847         transformList->append(transformValue.release());
848         if (pos < end) {
849             if (isCSSSpace(*pos))
850                 return nullptr;
851         }
852     }
853     return transformList.release();
854 }
855
856 static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
857 {
858     if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
859         return false;
860     if (string.isEmpty())
861         return false;
862     RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
863     if (string.is8Bit()) {
864         const LChar* pos = string.characters8();
865         const LChar* end = pos + string.length();
866         transformList = parseSimpleTransformList(pos, end);
867         if (!transformList)
868             return false;
869     } else {
870         const UChar* pos = string.characters16();
871         const UChar* end = pos + string.length();
872         transformList = parseSimpleTransformList(pos, end);
873         if (!transformList)
874             return false;
875     }
876     properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
877     return true;
878 }
879
880 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const CSSParserContext& context)
881 {
882     ASSERT(!string.isEmpty());
883
884     if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
885         return true;
886     if (parseColorValue(declaration, propertyID, string, important, context.mode()))
887         return true;
888     if (parseKeywordValue(declaration, propertyID, string, important, context))
889         return true;
890
891     BisonCSSParser parser(context);
892     return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
893 }
894
895 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
896 {
897     ASSERT(!string.isEmpty());
898     if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
899         return true;
900     if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
901         return true;
902
903     CSSParserContext context(cssParserMode, 0);
904     if (contextStyleSheet) {
905         context = contextStyleSheet->parserContext();
906         context.setMode(cssParserMode);
907     }
908
909     if (parseKeywordValue(declaration, propertyID, string, important, context))
910         return true;
911     if (parseSimpleTransform(declaration, propertyID, string, important))
912         return true;
913
914     BisonCSSParser parser(context);
915     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
916 }
917
918 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
919 {
920     if (m_context.useCounter())
921         m_context.useCounter()->count(m_context, propertyID);
922
923     setStyleSheet(contextStyleSheet);
924
925     setupParser("@-internal-value ", string, "");
926
927     m_id = propertyID;
928     m_important = important;
929
930     {
931         StyleDeclarationScope scope(this, declaration);
932         cssyyparse(this);
933     }
934
935     m_rule = nullptr;
936     m_id = CSSPropertyInvalid;
937
938     bool ok = false;
939     if (!m_parsedProperties.isEmpty()) {
940         ok = true;
941         declaration->addParsedProperties(m_parsedProperties);
942         clearProperties();
943     }
944
945     return ok;
946 }
947
948 // The color will only be changed when string contains a valid CSS color, so callers
949 // can set it to a default color and ignore the boolean result.
950 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
951 {
952     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
953     if (CSSPropertyParser::fastParseColor(color, string, strict))
954         return true;
955
956     BisonCSSParser parser(strictCSSParserContext());
957
958     // In case the fast-path parser didn't understand the color, try the full parser.
959     if (!parser.parseColor(string))
960         return false;
961
962     CSSValue* value = parser.m_parsedProperties.first().value();
963     if (!value->isPrimitiveValue())
964         return false;
965
966     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
967     if (!primitiveValue->isRGBColor())
968         return false;
969
970     color = primitiveValue->getRGBA32Value();
971     return true;
972 }
973
974 StyleColor BisonCSSParser::colorFromRGBColorString(const String& colorString)
975 {
976     // FIXME: Rework css parser so it is more SVG aware.
977     RGBA32 color;
978     if (parseColor(color, colorString.stripWhiteSpace()))
979         return StyleColor(color);
980     // FIXME: This branch catches the string currentColor, but we should error if we have an illegal color value.
981     return StyleColor::currentColor();
982 }
983
984 bool BisonCSSParser::parseColor(const String& string)
985 {
986     setupParser("@-internal-decls color:", string, "");
987     cssyyparse(this);
988     m_rule = nullptr;
989
990     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
991 }
992
993 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
994 {
995     CSSParserString cssColor;
996     cssColor.init(string);
997     CSSValueID id = cssValueKeywordID(cssColor);
998     if (!CSSPropertyParser::isSystemColor(id))
999         return false;
1000
1001     Color parsedColor = RenderTheme::theme().systemColor(id);
1002     color = parsedColor.rgb();
1003     return true;
1004 }
1005
1006 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1007 {
1008     m_selectorListForParseSelector = &selectorList;
1009
1010     setupParser("@-internal-selector ", string, "");
1011
1012     cssyyparse(this);
1013
1014     m_selectorListForParseSelector = 0;
1015 }
1016
1017 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1018 {
1019     Document& document = element->document();
1020     CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
1021     context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
1022     return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
1023 }
1024
1025 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1026 {
1027     setStyleSheet(contextStyleSheet);
1028
1029     setupParser("@-internal-decls ", string, "");
1030     cssyyparse(this);
1031     m_rule = nullptr;
1032
1033     RefPtrWillBeRawPtr<ImmutableStylePropertySet> style = createStylePropertySet();
1034     clearProperties();
1035     return style.release();
1036 }
1037
1038
1039 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
1040 {
1041     setStyleSheet(contextStyleSheet);
1042
1043     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
1044
1045     setupParser("@-internal-decls ", string, "");
1046     if (m_observer) {
1047         m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
1048         m_observer->endRuleHeader(1);
1049         m_observer->startRuleBody(0);
1050     }
1051
1052     {
1053         StyleDeclarationScope scope(this, declaration);
1054         cssyyparse(this);
1055     }
1056
1057     m_rule = nullptr;
1058
1059     bool ok = false;
1060     if (!m_parsedProperties.isEmpty()) {
1061         ok = true;
1062         declaration->addParsedProperties(m_parsedProperties);
1063         clearProperties();
1064     }
1065
1066     if (m_observer)
1067         m_observer->endRuleBody(string.length(), false);
1068
1069     return ok;
1070 }
1071
1072 bool BisonCSSParser::parseAttributeMatchType(CSSSelector::AttributeMatchType& matchType, const String& string)
1073 {
1074     if (!RuntimeEnabledFeatures::cssAttributeCaseSensitivityEnabled() && !isUASheetBehavior(m_context.mode()))
1075         return false;
1076     if (string == "i") {
1077         matchType = CSSSelector::CaseInsensitive;
1078         return true;
1079     }
1080     return false;
1081 }
1082
1083 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1084 {
1085     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1086     for (int i = input.size() - 1; i >= 0; --i) {
1087         const CSSProperty& property = input[i];
1088         if (property.isImportant() != important)
1089             continue;
1090         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1091         if (seenProperties.get(propertyIDIndex))
1092             continue;
1093         seenProperties.set(propertyIDIndex);
1094         output[--unusedEntries] = property;
1095     }
1096 }
1097
1098 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
1099 {
1100     BitArray<numCSSProperties> seenProperties;
1101     size_t unusedEntries = m_parsedProperties.size();
1102     WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
1103
1104     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1105     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1106     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1107     if (unusedEntries)
1108         results.remove(0, unusedEntries);
1109
1110     CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
1111
1112     return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
1113 }
1114
1115 void BisonCSSParser::rollbackLastProperties(int num)
1116 {
1117     ASSERT(num >= 0);
1118     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1119     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1120 }
1121
1122 void BisonCSSParser::clearProperties()
1123 {
1124     m_parsedProperties.clear();
1125     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1126 }
1127
1128 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
1129 {
1130     m_id = propId;
1131 }
1132
1133 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
1134 {
1135     return CSSPropertyParser::parseValue(propId, important, m_valueList.get(), m_context, m_inViewport, m_parsedProperties, m_ruleHeaderType);
1136 }
1137
1138
1139 class TransformOperationInfo {
1140 public:
1141     TransformOperationInfo(const CSSParserString& name)
1142         : m_type(CSSTransformValue::UnknownTransformOperation)
1143         , m_argCount(1)
1144         , m_allowSingleArgument(false)
1145         , m_unit(CSSPropertyParser::FUnknown)
1146     {
1147         const UChar* characters;
1148         unsigned nameLength = name.length();
1149
1150         const unsigned longestNameLength = 11;
1151         UChar characterBuffer[longestNameLength];
1152         if (name.is8Bit()) {
1153             unsigned length = std::min(longestNameLength, nameLength);
1154             const LChar* characters8 = name.characters8();
1155             for (unsigned i = 0; i < length; ++i)
1156                 characterBuffer[i] = characters8[i];
1157             characters = characterBuffer;
1158         } else
1159             characters = name.characters16();
1160
1161         SWITCH(characters, nameLength) {
1162             CASE("skew") {
1163                 m_unit = CSSPropertyParser::FAngle;
1164                 m_type = CSSTransformValue::SkewTransformOperation;
1165                 m_allowSingleArgument = true;
1166                 m_argCount = 3;
1167             }
1168             CASE("scale") {
1169                 m_unit = CSSPropertyParser::FNumber;
1170                 m_type = CSSTransformValue::ScaleTransformOperation;
1171                 m_allowSingleArgument = true;
1172                 m_argCount = 3;
1173             }
1174             CASE("skewx") {
1175                 m_unit = CSSPropertyParser::FAngle;
1176                 m_type = CSSTransformValue::SkewXTransformOperation;
1177             }
1178             CASE("skewy") {
1179                 m_unit = CSSPropertyParser::FAngle;
1180                 m_type = CSSTransformValue::SkewYTransformOperation;
1181             }
1182             CASE("matrix") {
1183                 m_unit = CSSPropertyParser::FNumber;
1184                 m_type = CSSTransformValue::MatrixTransformOperation;
1185                 m_argCount = 11;
1186             }
1187             CASE("rotate") {
1188                 m_unit = CSSPropertyParser::FAngle;
1189                 m_type = CSSTransformValue::RotateTransformOperation;
1190             }
1191             CASE("scalex") {
1192                 m_unit = CSSPropertyParser::FNumber;
1193                 m_type = CSSTransformValue::ScaleXTransformOperation;
1194             }
1195             CASE("scaley") {
1196                 m_unit = CSSPropertyParser::FNumber;
1197                 m_type = CSSTransformValue::ScaleYTransformOperation;
1198             }
1199             CASE("scalez") {
1200                 m_unit = CSSPropertyParser::FNumber;
1201                 m_type = CSSTransformValue::ScaleZTransformOperation;
1202             }
1203             CASE("scale3d") {
1204                 m_unit = CSSPropertyParser::FNumber;
1205                 m_type = CSSTransformValue::Scale3DTransformOperation;
1206                 m_argCount = 5;
1207             }
1208             CASE("rotatex") {
1209                 m_unit = CSSPropertyParser::FAngle;
1210                 m_type = CSSTransformValue::RotateXTransformOperation;
1211             }
1212             CASE("rotatey") {
1213                 m_unit = CSSPropertyParser::FAngle;
1214                 m_type = CSSTransformValue::RotateYTransformOperation;
1215             }
1216             CASE("rotatez") {
1217                 m_unit = CSSPropertyParser::FAngle;
1218                 m_type = CSSTransformValue::RotateZTransformOperation;
1219             }
1220             CASE("matrix3d") {
1221                 m_unit = CSSPropertyParser::FNumber;
1222                 m_type = CSSTransformValue::Matrix3DTransformOperation;
1223                 m_argCount = 31;
1224             }
1225             CASE("rotate3d") {
1226                 m_unit = CSSPropertyParser::FNumber;
1227                 m_type = CSSTransformValue::Rotate3DTransformOperation;
1228                 m_argCount = 7;
1229             }
1230             CASE("translate") {
1231                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1232                 m_type = CSSTransformValue::TranslateTransformOperation;
1233                 m_allowSingleArgument = true;
1234                 m_argCount = 3;
1235             }
1236             CASE("translatex") {
1237                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1238                 m_type = CSSTransformValue::TranslateXTransformOperation;
1239             }
1240             CASE("translatey") {
1241                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1242                 m_type = CSSTransformValue::TranslateYTransformOperation;
1243             }
1244             CASE("translatez") {
1245                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1246                 m_type = CSSTransformValue::TranslateZTransformOperation;
1247             }
1248             CASE("perspective") {
1249                 m_unit = CSSPropertyParser::FNumber;
1250                 m_type = CSSTransformValue::PerspectiveTransformOperation;
1251             }
1252             CASE("translate3d") {
1253                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1254                 m_type = CSSTransformValue::Translate3DTransformOperation;
1255                 m_argCount = 5;
1256             }
1257         }
1258     }
1259
1260     CSSTransformValue::TransformOperationType type() const { return m_type; }
1261     unsigned argCount() const { return m_argCount; }
1262     CSSPropertyParser::Units unit() const { return m_unit; }
1263
1264     bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
1265     bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
1266
1267 private:
1268     CSSTransformValue::TransformOperationType m_type;
1269     unsigned m_argCount;
1270     bool m_allowSingleArgument;
1271     CSSPropertyParser::Units m_unit;
1272 };
1273
1274 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
1275 {
1276     if (!m_valueList)
1277         return nullptr;
1278
1279     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1280     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
1281         RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
1282         if (!parsedTransformValue)
1283             return nullptr;
1284
1285         list->append(parsedTransformValue.release());
1286     }
1287
1288     return list.release();
1289 }
1290
1291 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
1292 {
1293     if (value->unit != CSSParserValue::Function || !value->function)
1294         return nullptr;
1295
1296     // Every primitive requires at least one argument.
1297     CSSParserValueList* args = value->function->args.get();
1298     if (!args)
1299         return nullptr;
1300
1301     // See if the specified primitive is one we understand.
1302     TransformOperationInfo info(value->function->name);
1303     if (info.unknown())
1304         return nullptr;
1305
1306     if (!info.hasCorrectArgCount(args->size()))
1307         return nullptr;
1308
1309     // The transform is a list of functional primitives that specify transform operations.
1310     // We collect a list of CSSTransformValues, where each value specifies a single operation.
1311
1312     // Create the new CSSTransformValue for this operation and add it to our list.
1313     RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
1314
1315     // Snag our values.
1316     CSSParserValue* a = args->current();
1317     unsigned argNumber = 0;
1318     while (a) {
1319         CSSPropertyParser::Units unit = info.unit();
1320
1321         if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
1322             // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
1323             if (!validUnit(a, FAngle, HTMLStandardMode))
1324                 return nullptr;
1325         } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
1326             // 3rd param of translate3d() cannot be a percentage
1327             if (!validUnit(a, FLength, HTMLStandardMode))
1328                 return nullptr;
1329         } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
1330             // 1st param of translateZ() cannot be a percentage
1331             if (!validUnit(a, FLength, HTMLStandardMode))
1332                 return nullptr;
1333         } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
1334             // 1st param of perspective() must be a non-negative number (deprecated) or length.
1335             if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
1336                 || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
1337                 return nullptr;
1338         } else if (!validUnit(a, unit, HTMLStandardMode)) {
1339             return nullptr;
1340         }
1341
1342         // Add the value to the current transform operation.
1343         transformValue->append(createPrimitiveNumericValue(a));
1344
1345         a = args->next();
1346         if (!a)
1347             break;
1348         if (a->unit != CSSParserValue::Operator || a->iValue != ',')
1349             return nullptr;
1350         a = args->next();
1351
1352         argNumber++;
1353     }
1354
1355     return transformValue.release();
1356 }
1357
1358 void BisonCSSParser::ensureLineEndings()
1359 {
1360     if (!m_lineEndings)
1361         m_lineEndings = lineEndings(*m_source);
1362 }
1363
1364 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
1365 {
1366     CSSParserSelector* selector = new CSSParserSelector(tagQName);
1367     m_floatingSelectors.append(selector);
1368     return selector;
1369 }
1370
1371 CSSParserSelector* BisonCSSParser::createFloatingSelector()
1372 {
1373     CSSParserSelector* selector = new CSSParserSelector;
1374     m_floatingSelectors.append(selector);
1375     return selector;
1376 }
1377
1378 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
1379 {
1380     if (selector) {
1381         size_t index = m_floatingSelectors.reverseFind(selector);
1382         ASSERT(index != kNotFound);
1383         m_floatingSelectors.remove(index);
1384     }
1385     return adoptPtr(selector);
1386 }
1387
1388 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
1389 {
1390     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
1391     m_floatingSelectorVectors.append(selectorVector);
1392     return selectorVector;
1393 }
1394
1395 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
1396 {
1397     if (selectorVector) {
1398         size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
1399         ASSERT(index != kNotFound);
1400         m_floatingSelectorVectors.remove(index);
1401     }
1402     return adoptPtr(selectorVector);
1403 }
1404
1405 CSSParserValueList* BisonCSSParser::createFloatingValueList()
1406 {
1407     CSSParserValueList* list = new CSSParserValueList;
1408     m_floatingValueLists.append(list);
1409     return list;
1410 }
1411
1412 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
1413 {
1414     if (list) {
1415         size_t index = m_floatingValueLists.reverseFind(list);
1416         ASSERT(index != kNotFound);
1417         m_floatingValueLists.remove(index);
1418     }
1419     return adoptPtr(list);
1420 }
1421
1422 CSSParserFunction* BisonCSSParser::createFloatingFunction()
1423 {
1424     CSSParserFunction* function = new CSSParserFunction;
1425     m_floatingFunctions.append(function);
1426     return function;
1427 }
1428
1429 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
1430 {
1431     CSSParserFunction* function = createFloatingFunction();
1432     function->name = name;
1433     function->args = args;
1434     return function;
1435 }
1436
1437 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
1438 {
1439     if (function) {
1440         size_t index = m_floatingFunctions.reverseFind(function);
1441         ASSERT(index != kNotFound);
1442         m_floatingFunctions.remove(index);
1443     }
1444     return adoptPtr(function);
1445 }
1446
1447 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
1448 {
1449     if (value.unit == CSSParserValue::Function) {
1450         size_t index = m_floatingFunctions.reverseFind(value.function);
1451         ASSERT(index != kNotFound);
1452         m_floatingFunctions.remove(index);
1453     }
1454     return value;
1455 }
1456
1457 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
1458 {
1459     m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
1460     return m_floatingMediaQueryExp.get();
1461 }
1462
1463 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
1464 {
1465     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
1466     return m_floatingMediaQueryExp.release();
1467 }
1468
1469 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
1470 {
1471     m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
1472     return m_floatingMediaQueryExpList.get();
1473 }
1474
1475 PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
1476 {
1477     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
1478     return m_floatingMediaQueryExpList.release();
1479 }
1480
1481 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1482 {
1483     m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
1484     return m_floatingMediaQuery.get();
1485 }
1486
1487 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1488 {
1489     return createFloatingMediaQuery(MediaQuery::None, MediaTypeNames::all, expressions);
1490 }
1491
1492 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
1493 {
1494     return createFloatingMediaQuery(MediaQuery::Not, MediaTypeNames::all, sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
1495 }
1496
1497 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
1498 {
1499     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
1500     return m_floatingMediaQuery.release();
1501 }
1502
1503 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
1504 {
1505     m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
1506     return m_floatingKeyframeVector.get();
1507 }
1508
1509 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
1510 {
1511     ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
1512     return m_floatingKeyframeVector.release();
1513 }
1514
1515 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
1516 {
1517     RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
1518     MediaQuerySet* result = queries.get();
1519     m_parsedMediaQuerySets.append(queries.release());
1520     return result;
1521 }
1522
1523 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
1524 {
1525     if (!media || !m_allowImportRules)
1526         return 0;
1527     RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
1528     StyleRuleImport* result = rule.get();
1529     m_parsedRules.append(rule.release());
1530     return result;
1531 }
1532
1533 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
1534 {
1535     m_allowImportRules = m_allowNamespaceDeclarations = false;
1536     RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
1537     if (rules) {
1538         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
1539     } else {
1540         RuleList emptyRules;
1541         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
1542     }
1543     StyleRuleMedia* result = rule.get();
1544     m_parsedRules.append(rule.release());
1545     return result;
1546 }
1547
1548 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
1549 {
1550     m_allowImportRules = m_allowNamespaceDeclarations = false;
1551
1552     RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
1553     RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
1554     String conditionText;
1555     unsigned conditionOffset = data->ruleHeaderRange.start + 9;
1556     unsigned conditionLength = data->ruleHeaderRange.length() - 9;
1557
1558     if (m_tokenizer.is8BitSource())
1559         conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
1560     else
1561         conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
1562
1563     if (rules) {
1564         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
1565     } else {
1566         RuleList emptyRules;
1567         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
1568     }
1569
1570     StyleRuleSupports* result = rule.get();
1571     m_parsedRules.append(rule.release());
1572
1573     return result;
1574 }
1575
1576 void BisonCSSParser::markSupportsRuleHeaderStart()
1577 {
1578     if (!m_supportsRuleDataStack)
1579         m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
1580
1581     RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
1582     data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
1583     m_supportsRuleDataStack->append(data);
1584 }
1585
1586 void BisonCSSParser::markSupportsRuleHeaderEnd()
1587 {
1588     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1589
1590     if (m_tokenizer.is8BitSource())
1591         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
1592     else
1593         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
1594 }
1595
1596 PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
1597 {
1598     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1599     RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
1600     m_supportsRuleDataStack->removeLast();
1601     return data.release();
1602 }
1603
1604 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
1605 {
1606     OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
1607     RuleList* listPtr = list.get();
1608
1609     m_parsedRuleLists.append(list.release());
1610     return listPtr;
1611 }
1612
1613 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
1614 {
1615     if (rule) {
1616         if (!ruleList)
1617             ruleList = createRuleList();
1618         ruleList->append(rule);
1619     }
1620     return ruleList;
1621 }
1622
1623 template <typename CharacterType>
1624 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
1625 {
1626     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
1627     // that can potentially change the length of the string rather than the character
1628     // by character kind. If we don't need Unicode lowercasing, it would be good to
1629     // simplify this function.
1630
1631     if (charactersAreAllASCII(input, length)) {
1632         // Fast case for all-ASCII.
1633         for (unsigned i = 0; i < length; i++)
1634             output[i] = toASCIILower(input[i]);
1635     } else {
1636         for (unsigned i = 0; i < length; i++)
1637             output[i] = Unicode::toLower(input[i]);
1638     }
1639 }
1640
1641 void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
1642 {
1643     // Since it's our internal token, we know that we created it out
1644     // of our writable work buffers. Therefore the const_cast is just
1645     // ugly and not a potential crash.
1646     size_t length = token.length();
1647     if (token.is8Bit()) {
1648         makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
1649     } else {
1650         makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
1651     }
1652 }
1653
1654 void BisonCSSParser::endInvalidRuleHeader()
1655 {
1656     if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
1657         return;
1658
1659     CSSParserLocation location;
1660     location.lineNumber = m_tokenizer.m_lineNumber;
1661     location.offset = m_ruleHeaderStartOffset;
1662     if (m_tokenizer.is8BitSource())
1663         location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
1664     else
1665         location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
1666
1667     reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
1668
1669     endRuleHeader();
1670 }
1671
1672 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
1673 {
1674     // FIXME: error reporting temporatily disabled.
1675 }
1676
1677 bool BisonCSSParser::isLoggingErrors()
1678 {
1679     return m_logErrors && !m_ignoreErrors;
1680 }
1681
1682 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
1683 {
1684     unsigned lineNumberInStyleSheet;
1685     unsigned columnNumber = 0;
1686     if (InspectorInstrumentation::hasFrontends()) {
1687         ensureLineEndings();
1688         TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
1689         lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
1690         columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
1691     } else {
1692         lineNumberInStyleSheet = location.lineNumber;
1693     }
1694     FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
1695     console.addMessage(ConsoleMessage::create(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1));
1696 }
1697
1698 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
1699 {
1700     OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
1701     m_allowImportRules = m_allowNamespaceDeclarations = false;
1702     RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
1703     for (size_t i = 0; i < keyframes->size(); ++i)
1704         rule->parserAppendKeyframe(keyframes->at(i));
1705     rule->setName(name);
1706     rule->setVendorPrefixed(isPrefixed);
1707     StyleRuleKeyframes* rulePtr = rule.get();
1708     m_parsedRules.append(rule.release());
1709     return rulePtr;
1710 }
1711
1712 static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList)
1713 {
1714     if (!context.useCounter())
1715         return;
1716
1717     for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
1718         for (const CSSSelector* current = selector; current ; current = current->tagHistory()) {
1719             UseCounter::Feature feature = UseCounter::NumberOfFeatures;
1720             switch (current->pseudoType()) {
1721             case CSSSelector::PseudoUnresolved:
1722                 feature = UseCounter::CSSSelectorPseudoUnresolved;
1723                 break;
1724             case CSSSelector::PseudoShadow:
1725                 feature = UseCounter::CSSSelectorPseudoShadow;
1726                 break;
1727             case CSSSelector::PseudoContent:
1728                 feature = UseCounter::CSSSelectorPseudoContent;
1729                 break;
1730             case CSSSelector::PseudoHost:
1731                 feature = UseCounter::CSSSelectorPseudoHost;
1732                 break;
1733             case CSSSelector::PseudoHostContext:
1734                 feature = UseCounter::CSSSelectorPseudoHostContext;
1735                 break;
1736             default:
1737                 break;
1738             }
1739             if (feature != UseCounter::NumberOfFeatures)
1740                 context.useCounter()->count(feature);
1741             if (current->relation() == CSSSelector::ShadowDeep)
1742                 context.useCounter()->count(UseCounter::CSSDeepCombinator);
1743             if (current->selectorList())
1744                 recordSelectorStats(context, *current->selectorList());
1745         }
1746     }
1747 }
1748
1749 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
1750 {
1751     StyleRule* result = 0;
1752     if (selectors) {
1753         m_allowImportRules = m_allowNamespaceDeclarations = false;
1754         RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
1755         rule->parserAdoptSelectorVector(*selectors);
1756         rule->setProperties(createStylePropertySet());
1757         result = rule.get();
1758         m_parsedRules.append(rule.release());
1759         recordSelectorStats(m_context, result->selectorList());
1760     }
1761     clearProperties();
1762     return result;
1763 }
1764
1765 StyleRuleBase* BisonCSSParser::createFontFaceRule()
1766 {
1767     m_allowImportRules = m_allowNamespaceDeclarations = false;
1768     for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
1769         CSSProperty& property = m_parsedProperties[i];
1770         if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
1771             property.wrapValueInCommaSeparatedList();
1772         else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
1773             // Unlike font-family property, font-family descriptor in @font-face rule
1774             // has to be a value list with exactly one family name. It cannot have a
1775             // have 'initial' value and cannot 'inherit' from parent.
1776             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
1777             clearProperties();
1778             return 0;
1779         }
1780     }
1781     RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
1782     rule->setProperties(createStylePropertySet());
1783     clearProperties();
1784     StyleRuleFontFace* result = rule.get();
1785     m_parsedRules.append(rule.release());
1786     if (m_styleSheet)
1787         m_styleSheet->setHasFontFaceRule(true);
1788     return result;
1789 }
1790
1791 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
1792 {
1793     if (!m_styleSheet || !m_allowNamespaceDeclarations)
1794         return;
1795     m_allowImportRules = false;
1796     m_styleSheet->parserAddNamespace(prefix, uri);
1797     if (prefix.isEmpty() && !uri.isNull())
1798         m_defaultNamespace = uri;
1799 }
1800
1801 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
1802 {
1803     if (!m_styleSheet)
1804         return QualifiedName(prefix, localName, m_defaultNamespace);
1805     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
1806 }
1807
1808 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
1809 {
1810     if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
1811         return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
1812     return specifiers;
1813 }
1814
1815 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1816 {
1817     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
1818     QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
1819
1820     if (specifiers->crossesTreeScopes())
1821         return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1822
1823     if (specifiers->isContentPseudoElement())
1824         return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1825
1826     // *:host never matches, so we can't discard the * otherwise we can't tell the
1827     // difference between *:host and just :host.
1828     if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
1829         return specifiers;
1830     if (specifiers->pseudoType() != CSSSelector::PseudoCue)
1831         specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
1832     return specifiers;
1833 }
1834
1835 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1836 {
1837     if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
1838         m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
1839
1840     CSSParserSelector* lastShadowPseudo = specifiers;
1841     CSSParserSelector* history = specifiers;
1842     while (history->tagHistory()) {
1843         history = history->tagHistory();
1844         if (history->crossesTreeScopes() || history->hasShadowPseudo())
1845             lastShadowPseudo = history;
1846     }
1847
1848     if (lastShadowPseudo->tagHistory()) {
1849         if (tag != anyQName())
1850             lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1851         return specifiers;
1852     }
1853
1854     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1855     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1856     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1857     lastShadowPseudo->setTagHistory(elementNameSelector.release());
1858     lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
1859     return specifiers;
1860 }
1861
1862 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1863 {
1864     CSSParserSelector* last = specifiers;
1865     CSSParserSelector* history = specifiers;
1866     while (history->tagHistory()) {
1867         history = history->tagHistory();
1868         if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
1869             last = history;
1870     }
1871
1872     if (last->tagHistory()) {
1873         if (tag != anyQName())
1874             last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1875         return specifiers;
1876     }
1877
1878     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1879     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1880     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1881     last->setTagHistory(elementNameSelector.release());
1882     last->setRelation(CSSSelector::SubSelector);
1883     return specifiers;
1884 }
1885
1886 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
1887 {
1888     if (newSpecifier->crossesTreeScopes()) {
1889         // Unknown pseudo element always goes at the top of selector chain.
1890         newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
1891         return newSpecifier;
1892     }
1893     if (newSpecifier->isContentPseudoElement()) {
1894         newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
1895         return newSpecifier;
1896     }
1897     if (specifiers->crossesTreeScopes()) {
1898         // Specifiers for unknown pseudo element go right behind it in the chain.
1899         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
1900         return specifiers;
1901     }
1902     if (specifiers->isContentPseudoElement()) {
1903         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
1904         return specifiers;
1905     }
1906     specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
1907     return specifiers;
1908 }
1909
1910 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
1911 {
1912     // FIXME: Margin at-rules are ignored.
1913     m_allowImportRules = m_allowNamespaceDeclarations = false;
1914     StyleRulePage* pageRule = 0;
1915     if (pageSelector) {
1916         RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
1917         Vector<OwnPtr<CSSParserSelector> > selectorVector;
1918         selectorVector.append(pageSelector);
1919         rule->parserAdoptSelectorVector(selectorVector);
1920         rule->setProperties(createStylePropertySet());
1921         pageRule = rule.get();
1922         m_parsedRules.append(rule.release());
1923     }
1924     clearProperties();
1925     return pageRule;
1926 }
1927
1928 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
1929 {
1930     // FIXME: Implement margin at-rule here, using:
1931     //        - marginBox: margin box
1932     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
1933     // 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.
1934
1935     endDeclarationsForMarginBox();
1936     return 0; // until this method is implemented.
1937 }
1938
1939 void BisonCSSParser::startDeclarationsForMarginBox()
1940 {
1941     m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
1942 }
1943
1944 void BisonCSSParser::endDeclarationsForMarginBox()
1945 {
1946     rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
1947     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1948 }
1949
1950 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
1951 {
1952     OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
1953     if (keyVector->isEmpty())
1954         return 0;
1955
1956     RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
1957     keyframe->setKeys(keyVector.release());
1958     keyframe->setProperties(createStylePropertySet());
1959
1960     clearProperties();
1961
1962     StyleKeyframe* keyframePtr = keyframe.get();
1963     m_parsedKeyframes.append(keyframe.release());
1964     return keyframePtr;
1965 }
1966
1967 void BisonCSSParser::invalidBlockHit()
1968 {
1969     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
1970         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
1971 }
1972
1973 void BisonCSSParser::startRule()
1974 {
1975     if (!m_observer)
1976         return;
1977
1978     ASSERT(m_ruleHasHeader);
1979     m_ruleHasHeader = false;
1980 }
1981
1982 void BisonCSSParser::endRule(bool valid)
1983 {
1984     if (!m_observer)
1985         return;
1986
1987     if (m_ruleHasHeader)
1988         m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
1989     m_ruleHasHeader = true;
1990 }
1991
1992 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
1993 {
1994     resumeErrorLogging();
1995     m_ruleHeaderType = ruleType;
1996     m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
1997     m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
1998     if (m_observer) {
1999         ASSERT(!m_ruleHasHeader);
2000         m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
2001         m_ruleHasHeader = true;
2002     }
2003 }
2004
2005 void BisonCSSParser::endRuleHeader()
2006 {
2007     ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
2008     m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
2009     if (m_observer) {
2010         ASSERT(m_ruleHasHeader);
2011         m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
2012     }
2013 }
2014
2015 void BisonCSSParser::startSelector()
2016 {
2017     if (m_observer)
2018         m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
2019 }
2020
2021 void BisonCSSParser::endSelector()
2022 {
2023     if (m_observer)
2024         m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
2025 }
2026
2027 void BisonCSSParser::startRuleBody()
2028 {
2029     if (m_observer)
2030         m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
2031 }
2032
2033 void BisonCSSParser::startProperty()
2034 {
2035     resumeErrorLogging();
2036     if (m_observer)
2037         m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
2038 }
2039
2040 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
2041 {
2042     m_id = CSSPropertyInvalid;
2043     if (m_observer)
2044         m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
2045 }
2046
2047 StyleRuleBase* BisonCSSParser::createViewportRule()
2048 {
2049     // Allow @viewport rules from UA stylesheets even if the feature is disabled.
2050     if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
2051         return 0;
2052
2053     m_allowImportRules = m_allowNamespaceDeclarations = false;
2054
2055     RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
2056
2057     rule->setProperties(createStylePropertySet());
2058     clearProperties();
2059
2060     StyleRuleViewport* result = rule.get();
2061     m_parsedRules.append(rule.release());
2062
2063     return result;
2064 }
2065
2066 }