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