6376586c1e11b19d6cbf1c9c0d74d64d47b98c9c
[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/FrameHost.h"
78 #include "core/frame/PageConsole.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 static const double MAX_SCALE = 1000000;
108
109 template <unsigned N>
110 static bool equal(const CSSParserString& a, const char (&b)[N])
111 {
112     unsigned length = N - 1; // Ignore the trailing null character
113     if (a.length() != length)
114         return false;
115
116     return a.is8Bit() ? WTF::equal(a.characters8(), reinterpret_cast<const LChar*>(b), length) : WTF::equal(a.characters16(), reinterpret_cast<const LChar*>(b), length);
117 }
118
119 template <unsigned N>
120 static bool equalIgnoringCase(const CSSParserString& a, const char (&b)[N])
121 {
122     unsigned length = N - 1; // Ignore the trailing null character
123     if (a.length() != length)
124         return false;
125
126     return a.is8Bit() ? WTF::equalIgnoringCase(b, a.characters8(), length) : WTF::equalIgnoringCase(b, a.characters16(), length);
127 }
128
129 template <unsigned N>
130 static bool equalIgnoringCase(CSSParserValue* value, const char (&b)[N])
131 {
132     ASSERT(value->unit == CSSPrimitiveValue::CSS_IDENT || value->unit == CSSPrimitiveValue::CSS_STRING);
133     return equalIgnoringCase(value->string, b);
134 }
135
136 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> first, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> second, Pair::IdenticalValuesPolicy identicalValuesPolicy = Pair::DropIdenticalValues)
137 {
138     return cssValuePool().createValue(Pair::create(first, second, identicalValuesPolicy));
139 }
140
141 class AnimationParseContext {
142 public:
143     AnimationParseContext()
144         : m_animationPropertyKeywordAllowed(true)
145         , m_firstAnimationCommitted(false)
146         , m_hasSeenAnimationPropertyKeyword(false)
147     {
148     }
149
150     void commitFirstAnimation()
151     {
152         m_firstAnimationCommitted = true;
153     }
154
155     bool hasCommittedFirstAnimation() const
156     {
157         return m_firstAnimationCommitted;
158     }
159
160     void commitAnimationPropertyKeyword()
161     {
162         m_animationPropertyKeywordAllowed = false;
163     }
164
165     bool animationPropertyKeywordAllowed() const
166     {
167         return m_animationPropertyKeywordAllowed;
168     }
169
170     bool hasSeenAnimationPropertyKeyword() const
171     {
172         return m_hasSeenAnimationPropertyKeyword;
173     }
174
175     void sawAnimationPropertyKeyword()
176     {
177         m_hasSeenAnimationPropertyKeyword = true;
178     }
179
180 private:
181     bool m_animationPropertyKeywordAllowed;
182     bool m_firstAnimationCommitted;
183     bool m_hasSeenAnimationPropertyKeyword;
184 };
185
186 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
187     : m_context(context)
188     , m_important(false)
189     , m_id(CSSPropertyInvalid)
190     , m_styleSheet(0)
191     , m_supportsCondition(false)
192     , m_selectorListForParseSelector(0)
193     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
194     , m_inParseShorthand(0)
195     , m_currentShorthand(CSSPropertyInvalid)
196     , m_implicitShorthand(false)
197     , m_hasFontFaceOnlyValues(false)
198     , m_hadSyntacticallyValidCSSRule(false)
199     , m_logErrors(false)
200     , m_ignoreErrors(false)
201     , m_defaultNamespace(starAtom)
202     , m_observer(0)
203     , m_source(0)
204     , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
205     , m_allowImportRules(true)
206     , m_allowNamespaceDeclarations(true)
207     , m_inViewport(false)
208     , m_tokenizer(*this)
209 {
210 #if YYDEBUG > 0
211     cssyydebug = 1;
212 #endif
213     CSSPropertySourceData::init();
214 }
215
216 BisonCSSParser::~BisonCSSParser()
217 {
218     clearProperties();
219
220     deleteAllValues(m_floatingSelectors);
221     deleteAllValues(m_floatingSelectorVectors);
222     deleteAllValues(m_floatingValueLists);
223     deleteAllValues(m_floatingFunctions);
224 }
225
226 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
227 {
228     m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
229     m_ruleHasHeader = true;
230 }
231
232 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
233 {
234     setStyleSheet(sheet);
235     m_defaultNamespace = starAtom; // Reset the default namespace.
236     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
237     m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
238     m_ignoreErrors = false;
239     m_tokenizer.m_lineNumber = 0;
240     m_startPosition = startPosition;
241     m_source = &string;
242     m_tokenizer.m_internal = false;
243     setupParser("", string, "");
244     cssyyparse(this);
245     sheet->shrinkToFit();
246     m_source = 0;
247     m_rule = 0;
248     m_lineEndings.clear();
249     m_ignoreErrors = false;
250     m_logErrors = false;
251     m_tokenizer.m_internal = true;
252 }
253
254 PassRefPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
255 {
256     setStyleSheet(sheet);
257     m_allowNamespaceDeclarations = false;
258     setupParser("@-internal-rule ", string, "");
259     cssyyparse(this);
260     return m_rule.release();
261 }
262
263 PassRefPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
264 {
265     setStyleSheet(sheet);
266     setupParser("@-internal-keyframe-rule ", string, "");
267     cssyyparse(this);
268     return m_keyframe.release();
269 }
270
271 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
272 {
273     setupParser("@-internal-keyframe-key-list ", string, "");
274     cssyyparse(this);
275     ASSERT(m_valueList);
276     return StyleKeyframe::createKeyList(m_valueList.get());
277 }
278
279 bool BisonCSSParser::parseSupportsCondition(const String& string)
280 {
281     m_supportsCondition = false;
282     setupParser("@-internal-supports-condition ", string, "");
283     cssyyparse(this);
284     return m_supportsCondition;
285 }
286
287 static inline bool isColorPropertyID(CSSPropertyID propertyId)
288 {
289     switch (propertyId) {
290     case CSSPropertyColor:
291     case CSSPropertyBackgroundColor:
292     case CSSPropertyBorderBottomColor:
293     case CSSPropertyBorderLeftColor:
294     case CSSPropertyBorderRightColor:
295     case CSSPropertyBorderTopColor:
296     case CSSPropertyOutlineColor:
297     case CSSPropertyTextLineThroughColor:
298     case CSSPropertyTextOverlineColor:
299     case CSSPropertyTextUnderlineColor:
300     case CSSPropertyWebkitBorderAfterColor:
301     case CSSPropertyWebkitBorderBeforeColor:
302     case CSSPropertyWebkitBorderEndColor:
303     case CSSPropertyWebkitBorderStartColor:
304     case CSSPropertyWebkitColumnRuleColor:
305     case CSSPropertyWebkitTextEmphasisColor:
306     case CSSPropertyWebkitTextFillColor:
307     case CSSPropertyWebkitTextStrokeColor:
308         return true;
309     case CSSPropertyTextDecorationColor:
310         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
311     default:
312         return false;
313     }
314 }
315
316 static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
317 {
318     ASSERT(!string.isEmpty());
319     bool quirksMode = isQuirksModeBehavior(cssParserMode);
320     if (!isColorPropertyID(propertyId))
321         return false;
322     CSSParserString cssString;
323     cssString.init(string);
324     CSSValueID valueID = cssValueKeywordID(cssString);
325     bool validPrimitive = false;
326     if (valueID == CSSValueWebkitText) {
327         validPrimitive = true;
328     } else if (valueID == CSSValueCurrentcolor) {
329         validPrimitive = true;
330     } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
331         || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
332         validPrimitive = true;
333     }
334
335     if (validPrimitive) {
336         RefPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
337         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
338         return true;
339     }
340     RGBA32 color;
341     if (!BisonCSSParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
342         return false;
343     RefPtr<CSSValue> value = cssValuePool().createColorValue(color);
344     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
345     return true;
346 }
347
348 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
349 {
350     switch (propertyId) {
351     case CSSPropertyFontSize:
352     case CSSPropertyHeight:
353     case CSSPropertyWidth:
354     case CSSPropertyMinHeight:
355     case CSSPropertyMinWidth:
356     case CSSPropertyPaddingBottom:
357     case CSSPropertyPaddingLeft:
358     case CSSPropertyPaddingRight:
359     case CSSPropertyPaddingTop:
360     case CSSPropertyWebkitLogicalWidth:
361     case CSSPropertyWebkitLogicalHeight:
362     case CSSPropertyWebkitMinLogicalWidth:
363     case CSSPropertyWebkitMinLogicalHeight:
364     case CSSPropertyWebkitPaddingAfter:
365     case CSSPropertyWebkitPaddingBefore:
366     case CSSPropertyWebkitPaddingEnd:
367     case CSSPropertyWebkitPaddingStart:
368         acceptsNegativeNumbers = false;
369         return true;
370     case CSSPropertyShapeMargin:
371     case CSSPropertyShapePadding:
372         acceptsNegativeNumbers = false;
373         return RuntimeEnabledFeatures::cssShapesEnabled();
374     case CSSPropertyBottom:
375     case CSSPropertyLeft:
376     case CSSPropertyMarginBottom:
377     case CSSPropertyMarginLeft:
378     case CSSPropertyMarginRight:
379     case CSSPropertyMarginTop:
380     case CSSPropertyRight:
381     case CSSPropertyTop:
382     case CSSPropertyWebkitMarginAfter:
383     case CSSPropertyWebkitMarginBefore:
384     case CSSPropertyWebkitMarginEnd:
385     case CSSPropertyWebkitMarginStart:
386         acceptsNegativeNumbers = true;
387         return true;
388     default:
389         return false;
390     }
391 }
392
393 template <typename CharacterType>
394 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitTypes& unit, double& number)
395 {
396     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
397         length -= 2;
398         unit = CSSPrimitiveValue::CSS_PX;
399     } else if (length > 1 && characters[length - 1] == '%') {
400         length -= 1;
401         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
402     }
403
404     // We rely on charactersToDouble for validation as well. The function
405     // will set "ok" to "false" if the entire passed-in character range does
406     // not represent a double.
407     bool ok;
408     number = charactersToDouble(characters, length, &ok);
409     return ok;
410 }
411
412 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
413 {
414     ASSERT(!string.isEmpty());
415     bool acceptsNegativeNumbers;
416
417     // In @viewport, width and height are shorthands, not simple length values.
418     if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
419         return false;
420
421     unsigned length = string.length();
422     double number;
423     CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
424
425     if (string.is8Bit()) {
426         if (!parseSimpleLength(string.characters8(), length, unit, number))
427             return false;
428     } else {
429         if (!parseSimpleLength(string.characters16(), length, unit, number))
430             return false;
431     }
432
433     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
434         bool quirksMode = isQuirksModeBehavior(cssParserMode);
435         if (number && !quirksMode)
436             return false;
437         unit = CSSPrimitiveValue::CSS_PX;
438     }
439     if (number < 0 && !acceptsNegativeNumbers)
440         return false;
441
442     RefPtr<CSSValue> value = cssValuePool().createValue(number, unit);
443     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
444     return true;
445 }
446
447 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext)
448 {
449     if (!valueID)
450         return false;
451
452     switch (propertyId) {
453     case CSSPropertyBorderCollapse: // collapse | separate | inherit
454         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
455             return true;
456         break;
457     case CSSPropertyBorderTopStyle: // <border-style> | inherit
458     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
459     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
460     case CSSPropertyBorderLeftStyle:
461     case CSSPropertyWebkitBorderAfterStyle:
462     case CSSPropertyWebkitBorderBeforeStyle:
463     case CSSPropertyWebkitBorderEndStyle:
464     case CSSPropertyWebkitBorderStartStyle:
465     case CSSPropertyWebkitColumnRuleStyle:
466         if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
467             return true;
468         break;
469     case CSSPropertyBoxSizing:
470          if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
471              return true;
472          break;
473     case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
474         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
475             return true;
476         break;
477     case CSSPropertyClear: // none | left | right | both | inherit
478         if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
479             return true;
480         break;
481     case CSSPropertyDirection: // ltr | rtl | inherit
482         if (valueID == CSSValueLtr || valueID == CSSValueRtl)
483             return true;
484         break;
485     case CSSPropertyDisplay:
486         // inline | block | list-item | inline-block | table |
487         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
488         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
489         // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid | lazy-block
490         if ((valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone)
491             return true;
492         if (valueID == CSSValueGrid || valueID == CSSValueInlineGrid)
493             return RuntimeEnabledFeatures::cssGridLayoutEnabled();
494         break;
495
496     case CSSPropertyEmptyCells: // show | hide | inherit
497         if (valueID == CSSValueShow || valueID == CSSValueHide)
498             return true;
499         break;
500     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
501         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter)
502             return true;
503         break;
504     case CSSPropertyFontStyle: // normal | italic | oblique | inherit
505         if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
506             return true;
507         break;
508     case CSSPropertyImageRendering: // auto | optimizeContrast
509         if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
510             return true;
511         break;
512     case CSSPropertyIsolation: // auto | isolate
513         if (valueID == CSSValueAuto || valueID == CSSValueIsolate)
514             return RuntimeEnabledFeatures::cssCompositingEnabled();
515         break;
516     case CSSPropertyListStylePosition: // inside | outside | inherit
517         if (valueID == CSSValueInside || valueID == CSSValueOutside)
518             return true;
519         break;
520     case CSSPropertyListStyleType:
521         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
522         // for the list of supported list-style-types.
523         if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
524             return true;
525         break;
526     case CSSPropertyObjectFit:
527         if (RuntimeEnabledFeatures::objectFitPositionEnabled()) {
528             if (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown)
529                 return true;
530         }
531         break;
532     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
533         if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
534             return true;
535         break;
536     case CSSPropertyOverflowWrap: // normal | break-word
537     case CSSPropertyWordWrap:
538         if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
539             return true;
540         break;
541     case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay | inherit
542         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay)
543             return true;
544         break;
545     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | inherit | -webkit-paged-x | -webkit-paged-y
546         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY)
547             return true;
548         break;
549     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
550     case CSSPropertyPageBreakBefore:
551     case CSSPropertyWebkitColumnBreakAfter:
552     case CSSPropertyWebkitColumnBreakBefore:
553         if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)
554             return true;
555         break;
556     case CSSPropertyPageBreakInside: // avoid | auto | inherit
557     case CSSPropertyWebkitColumnBreakInside:
558         if (valueID == CSSValueAuto || valueID == CSSValueAvoid)
559             return true;
560         break;
561     case CSSPropertyPointerEvents:
562         // none | visiblePainted | visibleFill | visibleStroke | visible |
563         // painted | fill | stroke | auto | all | bounding-box | inherit
564         if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox))
565             return true;
566         break;
567     case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit
568         if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed
569             || (RuntimeEnabledFeatures::cssStickyPositionEnabled() && valueID == CSSValueSticky))
570             return true;
571         break;
572     case CSSPropertyResize: // none | both | horizontal | vertical | auto
573         if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
574             return true;
575         break;
576     case CSSPropertyScrollBehavior: // instant | smooth
577         if (valueID == CSSValueInstant || valueID == CSSValueSmooth)
578             return RuntimeEnabledFeatures::cssomSmoothScrollEnabled();
579     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
580         if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
581             return true;
582         break;
583     case CSSPropertyTableLayout: // auto | fixed | inherit
584         if (valueID == CSSValueAuto || valueID == CSSValueFixed)
585             return true;
586         break;
587     case CSSPropertyTextAlignLast:
588         // auto | start | end | left | right | center | justify
589         if (RuntimeEnabledFeatures::css3TextEnabled()
590             && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto))
591             return true;
592         break;
593     case CSSPropertyTextJustify:
594         // auto | none | inter-word | distribute
595         if (RuntimeEnabledFeatures::css3TextEnabled()
596             && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone))
597             return true;
598         break;
599     case CSSPropertyTextLineThroughMode:
600     case CSSPropertyTextOverlineMode:
601     case CSSPropertyTextUnderlineMode:
602         if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
603             return true;
604         break;
605     case CSSPropertyTextLineThroughStyle:
606     case CSSPropertyTextOverlineStyle:
607     case CSSPropertyTextUnderlineStyle:
608         if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
609             return true;
610         break;
611     case CSSPropertyTextOverflow: // clip | ellipsis
612         if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
613             return true;
614         break;
615     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
616         if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
617             return true;
618         break;
619     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
620         if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
621             return true;
622         break;
623     case CSSPropertyTouchActionDelay: // none | script
624         if (RuntimeEnabledFeatures::cssTouchActionDelayEnabled() && (valueID == CSSValueScript || valueID == CSSValueNone))
625             return true;
626         break;
627     case CSSPropertyVisibility: // visible | hidden | collapse | inherit
628         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
629             return true;
630         break;
631     case CSSPropertyWebkitAppearance:
632         if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
633             return true;
634         break;
635     case CSSPropertyWebkitBackfaceVisibility:
636         if (valueID == CSSValueVisible || valueID == CSSValueHidden)
637             return true;
638         break;
639     case CSSPropertyMixBlendMode:
640         if (RuntimeEnabledFeatures::cssCompositingEnabled() && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen
641             || valueID == CSSValueOverlay || valueID == CSSValueDarken || valueID == CSSValueLighten ||  valueID == CSSValueColorDodge
642             || valueID == CSSValueColorBurn || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference
643             || valueID == CSSValueExclusion || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor
644             || valueID == CSSValueLuminosity))
645             return true;
646         break;
647     case CSSPropertyWebkitBorderFit:
648         if (valueID == CSSValueBorder || valueID == CSSValueLines)
649             return true;
650         break;
651     case CSSPropertyWebkitBoxAlign:
652         if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
653             return true;
654         break;
655     case CSSPropertyWebkitBoxDecorationBreak:
656          if (valueID == CSSValueClone || valueID == CSSValueSlice)
657              return true;
658          break;
659     case CSSPropertyWebkitBoxDirection:
660         if (valueID == CSSValueNormal || valueID == CSSValueReverse)
661             return true;
662         break;
663     case CSSPropertyWebkitBoxLines:
664         if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
665                 return true;
666         break;
667     case CSSPropertyWebkitBoxOrient:
668         if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
669             return true;
670         break;
671     case CSSPropertyWebkitBoxPack:
672         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
673             return true;
674         break;
675     case CSSPropertyInternalCallback:
676         // This property is only injected programmatically, not parsed from stylesheets.
677         return false;
678     case CSSPropertyColumnFill:
679         if (RuntimeEnabledFeatures::regionBasedColumnsEnabled()) {
680             if (valueID == CSSValueAuto || valueID == CSSValueBalance)
681                 return true;
682         }
683         break;
684     case CSSPropertyAlignContent:
685         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
686          if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch)
687              return true;
688          break;
689     case CSSPropertyAlignItems:
690         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
691         if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
692             return true;
693         break;
694     case CSSPropertyAlignSelf:
695         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
696         if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
697             return true;
698         break;
699     case CSSPropertyFlexDirection:
700         if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
701             return true;
702         break;
703     case CSSPropertyFlexWrap:
704         if (valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
705              return true;
706         break;
707     case CSSPropertyJustifyContent:
708         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
709         if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround)
710             return true;
711         break;
712     case CSSPropertyFontKerning:
713         if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
714             return true;
715         break;
716     case CSSPropertyWebkitFontSmoothing:
717         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
718             return true;
719         break;
720     case CSSPropertyGridAutoFlow:
721         if (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn)
722             return RuntimeEnabledFeatures::cssGridLayoutEnabled();
723         break;
724     case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
725         if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace)
726             return true;
727         break;
728     case CSSPropertyWebkitMarginAfterCollapse:
729     case CSSPropertyWebkitMarginBeforeCollapse:
730     case CSSPropertyWebkitMarginBottomCollapse:
731     case CSSPropertyWebkitMarginTopCollapse:
732         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
733             return true;
734         break;
735     case CSSPropertyInternalMarqueeDirection:
736         if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
737             || valueID == CSSValueUp || valueID == CSSValueAuto)
738             return true;
739         break;
740     case CSSPropertyInternalMarqueeStyle:
741         if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
742             return true;
743         break;
744     case CSSPropertyWebkitPrintColorAdjust:
745         if (valueID == CSSValueExact || valueID == CSSValueEconomy)
746             return true;
747         break;
748     case CSSPropertyWebkitRtlOrdering:
749         if (valueID == CSSValueLogical || valueID == CSSValueVisual)
750             return true;
751         break;
752
753     case CSSPropertyWebkitRubyPosition:
754         if (valueID == CSSValueBefore || valueID == CSSValueAfter)
755             return true;
756         break;
757
758     case CSSPropertyWebkitTextCombine:
759         if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
760             return true;
761         break;
762     case CSSPropertyWebkitTextEmphasisPosition:
763         if (valueID == CSSValueOver || valueID == CSSValueUnder)
764             return true;
765         break;
766     case CSSPropertyWebkitTextSecurity:
767         // disc | circle | square | none | inherit
768         if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
769             return true;
770         break;
771     case CSSPropertyWebkitTransformStyle:
772         if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
773             return true;
774         break;
775     case CSSPropertyWebkitUserDrag: // auto | none | element
776         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
777             return true;
778         break;
779     case CSSPropertyWebkitUserModify: // read-only | read-write
780         if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
781             return true;
782         break;
783     case CSSPropertyWebkitUserSelect: // auto | none | text | all
784         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll)
785             return true;
786         break;
787     case CSSPropertyWebkitWrapFlow:
788         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
789             return false;
790         if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear)
791             return true;
792         break;
793     case CSSPropertyWebkitWrapThrough:
794         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
795             return false;
796         if (valueID == CSSValueWrap || valueID == CSSValueNone)
797             return true;
798         break;
799     case CSSPropertyWebkitWritingMode:
800         if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
801             return true;
802         break;
803     case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
804         if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
805             return true;
806         break;
807     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
808         if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
809             return true;
810         break;
811     default:
812         ASSERT_NOT_REACHED();
813         return false;
814     }
815     return false;
816 }
817
818 static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
819 {
820     switch (propertyId) {
821     case CSSPropertyMixBlendMode:
822     case CSSPropertyIsolation:
823     case CSSPropertyBorderBottomStyle:
824     case CSSPropertyBorderCollapse:
825     case CSSPropertyBorderLeftStyle:
826     case CSSPropertyBorderRightStyle:
827     case CSSPropertyBorderTopStyle:
828     case CSSPropertyBoxSizing:
829     case CSSPropertyCaptionSide:
830     case CSSPropertyClear:
831     case CSSPropertyDirection:
832     case CSSPropertyDisplay:
833     case CSSPropertyEmptyCells:
834     case CSSPropertyFloat:
835     case CSSPropertyFontStyle:
836     case CSSPropertyImageRendering:
837     case CSSPropertyListStylePosition:
838     case CSSPropertyListStyleType:
839     case CSSPropertyObjectFit:
840     case CSSPropertyOutlineStyle:
841     case CSSPropertyOverflowWrap:
842     case CSSPropertyOverflowX:
843     case CSSPropertyOverflowY:
844     case CSSPropertyPageBreakAfter:
845     case CSSPropertyPageBreakBefore:
846     case CSSPropertyPageBreakInside:
847     case CSSPropertyPointerEvents:
848     case CSSPropertyPosition:
849     case CSSPropertyResize:
850     case CSSPropertyScrollBehavior:
851     case CSSPropertySpeak:
852     case CSSPropertyTableLayout:
853     case CSSPropertyTextAlignLast:
854     case CSSPropertyTextJustify:
855     case CSSPropertyTextLineThroughMode:
856     case CSSPropertyTextLineThroughStyle:
857     case CSSPropertyTextOverflow:
858     case CSSPropertyTextOverlineMode:
859     case CSSPropertyTextOverlineStyle:
860     case CSSPropertyTextRendering:
861     case CSSPropertyTextTransform:
862     case CSSPropertyTextUnderlineMode:
863     case CSSPropertyTextUnderlineStyle:
864     case CSSPropertyTouchActionDelay:
865     case CSSPropertyVisibility:
866     case CSSPropertyWebkitAppearance:
867     case CSSPropertyWebkitBackfaceVisibility:
868     case CSSPropertyWebkitBorderAfterStyle:
869     case CSSPropertyWebkitBorderBeforeStyle:
870     case CSSPropertyWebkitBorderEndStyle:
871     case CSSPropertyWebkitBorderFit:
872     case CSSPropertyWebkitBorderStartStyle:
873     case CSSPropertyWebkitBoxAlign:
874     case CSSPropertyWebkitBoxDecorationBreak:
875     case CSSPropertyWebkitBoxDirection:
876     case CSSPropertyWebkitBoxLines:
877     case CSSPropertyWebkitBoxOrient:
878     case CSSPropertyWebkitBoxPack:
879     case CSSPropertyInternalCallback:
880     case CSSPropertyWebkitColumnBreakAfter:
881     case CSSPropertyWebkitColumnBreakBefore:
882     case CSSPropertyWebkitColumnBreakInside:
883     case CSSPropertyColumnFill:
884     case CSSPropertyWebkitColumnRuleStyle:
885     case CSSPropertyAlignContent:
886     case CSSPropertyFlexDirection:
887     case CSSPropertyFlexWrap:
888     case CSSPropertyJustifyContent:
889     case CSSPropertyFontKerning:
890     case CSSPropertyWebkitFontSmoothing:
891     case CSSPropertyGridAutoFlow:
892     case CSSPropertyWebkitLineBreak:
893     case CSSPropertyWebkitMarginAfterCollapse:
894     case CSSPropertyWebkitMarginBeforeCollapse:
895     case CSSPropertyWebkitMarginBottomCollapse:
896     case CSSPropertyWebkitMarginTopCollapse:
897     case CSSPropertyInternalMarqueeDirection:
898     case CSSPropertyInternalMarqueeStyle:
899     case CSSPropertyWebkitPrintColorAdjust:
900     case CSSPropertyWebkitRtlOrdering:
901     case CSSPropertyWebkitRubyPosition:
902     case CSSPropertyWebkitTextCombine:
903     case CSSPropertyWebkitTextEmphasisPosition:
904     case CSSPropertyWebkitTextSecurity:
905     case CSSPropertyWebkitTransformStyle:
906     case CSSPropertyWebkitUserDrag:
907     case CSSPropertyWebkitUserModify:
908     case CSSPropertyWebkitUserSelect:
909     case CSSPropertyWebkitWrapFlow:
910     case CSSPropertyWebkitWrapThrough:
911     case CSSPropertyWebkitWritingMode:
912     case CSSPropertyWhiteSpace:
913     case CSSPropertyWordBreak:
914     case CSSPropertyWordWrap:
915         return true;
916     case CSSPropertyAlignItems:
917     case CSSPropertyAlignSelf:
918         return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
919     default:
920         return false;
921     }
922 }
923
924 static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
925 {
926     ASSERT(!string.isEmpty());
927
928     if (!isKeywordPropertyID(propertyId)) {
929         // All properties accept the values of "initial" and "inherit".
930         String lowerCaseString = string.lower();
931         if (lowerCaseString != "initial" && lowerCaseString != "inherit")
932             return false;
933
934         // Parse initial/inherit shorthands using the BisonCSSParser.
935         if (shorthandForProperty(propertyId).length())
936             return false;
937     }
938
939     CSSParserString cssString;
940     cssString.init(string);
941     CSSValueID valueID = cssValueKeywordID(cssString);
942
943     if (!valueID)
944         return false;
945
946     RefPtr<CSSValue> value;
947     if (valueID == CSSValueInherit)
948         value = cssValuePool().createInheritedValue();
949     else if (valueID == CSSValueInitial)
950         value = cssValuePool().createExplicitInitialValue();
951     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
952         value = cssValuePool().createIdentifierValue(valueID);
953     else
954         return false;
955
956     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
957     return true;
958 }
959
960 template <typename CharType>
961 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
962 {
963     while (expectedCount) {
964         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
965         if (delimiter == kNotFound)
966             return false;
967         unsigned argumentLength = static_cast<unsigned>(delimiter);
968         CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
969         double number;
970         if (!parseSimpleLength(pos, argumentLength, unit, number))
971             return false;
972         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
973             return false;
974         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
975         pos += argumentLength + 1;
976         --expectedCount;
977     }
978     return true;
979 }
980
981 template <typename CharType>
982 static PassRefPtrWillBeRawPtr<CSSTransformValue> parseTranslateTransformValue(CharType*& pos, CharType* end)
983 {
984     static const int shortestValidTransformStringLength = 12;
985
986     if (end - pos < shortestValidTransformStringLength)
987         return 0;
988
989     if ((pos[0] != 't' && pos[0] != 'T')
990         || (pos[1] != 'r' && pos[1] != 'R')
991         || (pos[2] != 'a' && pos[2] != 'A')
992         || (pos[3] != 'n' && pos[3] != 'N')
993         || (pos[4] != 's' && pos[4] != 'S')
994         || (pos[5] != 'l' && pos[5] != 'L')
995         || (pos[6] != 'a' && pos[6] != 'A')
996         || (pos[7] != 't' && pos[7] != 'T')
997         || (pos[8] != 'e' && pos[8] != 'E'))
998         return 0;
999
1000     CSSTransformValue::TransformOperationType transformType;
1001     unsigned expectedArgumentCount = 1;
1002     unsigned argumentStart = 11;
1003     if ((pos[9] == 'x' || pos[9] == 'X') && pos[10] == '(') {
1004         transformType = CSSTransformValue::TranslateXTransformOperation;
1005     } else if ((pos[9] == 'y' || pos[9] == 'Y') && pos[10] == '(') {
1006         transformType = CSSTransformValue::TranslateYTransformOperation;
1007     } else if ((pos[9] == 'z' || pos[9] == 'Z') && pos[10] == '(') {
1008         transformType = CSSTransformValue::TranslateZTransformOperation;
1009     } else if (pos[9] == '(') {
1010         transformType = CSSTransformValue::TranslateTransformOperation;
1011         expectedArgumentCount = 2;
1012         argumentStart = 10;
1013     } else if (pos[9] == '3' && (pos[10] == 'd' || pos[10] == 'D') && pos[11] == '(') {
1014         transformType = CSSTransformValue::Translate3DTransformOperation;
1015         expectedArgumentCount = 3;
1016         argumentStart = 12;
1017     } else {
1018         return 0;
1019     }
1020     pos += argumentStart;
1021
1022     RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
1023     if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
1024         return 0;
1025     return transformValue.release();
1026 }
1027
1028 template <typename CharType>
1029 static PassRefPtrWillBeRawPtr<CSSValueList> parseTranslateTransformList(CharType*& pos, CharType* end)
1030 {
1031     RefPtrWillBeRawPtr<CSSValueList> transformList;
1032     while (pos < end) {
1033         while (pos < end && isCSSSpace(*pos))
1034             ++pos;
1035         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseTranslateTransformValue(pos, end);
1036         if (!transformValue)
1037             return 0;
1038         if (!transformList)
1039             transformList = CSSValueList::createSpaceSeparated();
1040         transformList->append(transformValue.release());
1041         if (pos < end) {
1042             if (isCSSSpace(*pos))
1043                 return 0;
1044         }
1045     }
1046     return transformList.release();
1047 }
1048
1049 static bool parseTranslateTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
1050 {
1051     if (propertyID != CSSPropertyWebkitTransform)
1052         return false;
1053     if (string.isEmpty())
1054         return false;
1055     RefPtrWillBeRawPtr<CSSValueList> transformList;
1056     if (string.is8Bit()) {
1057         const LChar* pos = string.characters8();
1058         const LChar* end = pos + string.length();
1059         transformList = parseTranslateTransformList(pos, end);
1060         if (!transformList)
1061             return false;
1062     } else {
1063         const UChar* pos = string.characters16();
1064         const UChar* end = pos + string.length();
1065         transformList = parseTranslateTransformList(pos, end);
1066         if (!transformList)
1067             return false;
1068     }
1069     properties->addParsedProperty(CSSProperty(CSSPropertyWebkitTransform, transformList.release(), important));
1070     return true;
1071 }
1072
1073 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string)
1074 {
1075     if (string.isEmpty())
1076         return 0;
1077     RefPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create();
1078     if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0))
1079         return 0;
1080
1081     RefPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily);
1082     if (!fontFamily->isValueList())
1083         return 0;
1084
1085     return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
1086 }
1087
1088 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string)
1089 {
1090     if (string.isEmpty())
1091         return 0;
1092     RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
1093     if (!parseValue(style.get(), CSSPropertyAnimationTimingFunction, string, false, HTMLStandardMode, 0))
1094         return 0;
1095
1096     return style->getPropertyCSSValue(CSSPropertyAnimationTimingFunction);
1097 }
1098
1099 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document)
1100 {
1101     ASSERT(!string.isEmpty());
1102
1103     CSSParserContext context(document, UseCounter::getFrom(&document));
1104
1105     if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
1106         return true;
1107     if (parseColorValue(declaration, propertyID, string, important, context.mode()))
1108         return true;
1109     if (parseKeywordValue(declaration, propertyID, string, important, context))
1110         return true;
1111
1112     BisonCSSParser parser(context);
1113     return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
1114 }
1115
1116 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
1117 {
1118     ASSERT(!string.isEmpty());
1119     if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
1120         return true;
1121     if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
1122         return true;
1123
1124     CSSParserContext context(cssParserMode, 0);
1125     if (contextStyleSheet) {
1126         context = contextStyleSheet->parserContext();
1127         context.setMode(cssParserMode);
1128     }
1129
1130     if (parseKeywordValue(declaration, propertyID, string, important, context))
1131         return true;
1132     if (parseTranslateTransform(declaration, propertyID, string, important))
1133         return true;
1134
1135     BisonCSSParser parser(context);
1136     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
1137 }
1138
1139 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
1140 {
1141     // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty.
1142
1143     if (m_context.useCounter())
1144         m_context.useCounter()->count(m_context, propertyID);
1145
1146     setStyleSheet(contextStyleSheet);
1147
1148     setupParser("@-internal-value ", string, "");
1149
1150     m_id = propertyID;
1151     m_important = important;
1152
1153     {
1154         StyleDeclarationScope scope(this, declaration);
1155         cssyyparse(this);
1156     }
1157
1158     m_rule = 0;
1159     m_id = CSSPropertyInvalid;
1160
1161     bool ok = false;
1162     if (m_hasFontFaceOnlyValues)
1163         deleteFontFaceOnlyValues();
1164     if (!m_parsedProperties.isEmpty()) {
1165         ok = true;
1166         declaration->addParsedProperties(m_parsedProperties);
1167         clearProperties();
1168     }
1169
1170     return ok;
1171 }
1172
1173 // The color will only be changed when string contains a valid CSS color, so callers
1174 // can set it to a default color and ignore the boolean result.
1175 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
1176 {
1177     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
1178     if (fastParseColor(color, string, strict))
1179         return true;
1180
1181     BisonCSSParser parser(strictCSSParserContext());
1182
1183     // In case the fast-path parser didn't understand the color, try the full parser.
1184     if (!parser.parseColor(string))
1185         return false;
1186
1187     CSSValue* value = parser.m_parsedProperties.first().value();
1188     if (!value->isPrimitiveValue())
1189         return false;
1190
1191     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1192     if (!primitiveValue->isRGBColor())
1193         return false;
1194
1195     color = primitiveValue->getRGBA32Value();
1196     return true;
1197 }
1198
1199 bool BisonCSSParser::parseColor(const String& string)
1200 {
1201     setupParser("@-internal-decls color:", string, "");
1202     cssyyparse(this);
1203     m_rule = 0;
1204
1205     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1206 }
1207
1208 // FIXME: This is copied from SVGCSSParser.cpp
1209 static bool isSystemColor(int id)
1210 {
1211     return (id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu;
1212 }
1213
1214 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1215 {
1216     if (!document)
1217         return false;
1218
1219     CSSParserString cssColor;
1220     cssColor.init(string);
1221     CSSValueID id = cssValueKeywordID(cssColor);
1222     if (!isSystemColor(id))
1223         return false;
1224
1225     Color parsedColor = RenderTheme::theme().systemColor(id);
1226     color = parsedColor.rgb();
1227     return true;
1228 }
1229
1230 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1231 {
1232     m_selectorListForParseSelector = &selectorList;
1233
1234     setupParser("@-internal-selector ", string, "");
1235
1236     cssyyparse(this);
1237
1238     m_selectorListForParseSelector = 0;
1239 }
1240
1241 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1242 {
1243     Document& document = element->document();
1244     CSSParserContext context = CSSParserContext(document.elementSheet()->contents()->parserContext(), UseCounter::getFrom(&document));
1245     context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
1246     return BisonCSSParser(context).parseDeclaration(string, document.elementSheet()->contents());
1247 }
1248
1249 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1250 {
1251     setStyleSheet(contextStyleSheet);
1252
1253     setupParser("@-internal-decls ", string, "");
1254     cssyyparse(this);
1255     m_rule = 0;
1256
1257     if (m_hasFontFaceOnlyValues)
1258         deleteFontFaceOnlyValues();
1259
1260     RefPtr<ImmutableStylePropertySet> style = createStylePropertySet();
1261     clearProperties();
1262     return style.release();
1263 }
1264
1265
1266 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
1267 {
1268     setStyleSheet(contextStyleSheet);
1269
1270     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
1271
1272     setupParser("@-internal-decls ", string, "");
1273     if (m_observer) {
1274         m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
1275         m_observer->endRuleHeader(1);
1276         m_observer->startRuleBody(0);
1277     }
1278
1279     {
1280         StyleDeclarationScope scope(this, declaration);
1281         cssyyparse(this);
1282     }
1283
1284     m_rule = 0;
1285
1286     bool ok = false;
1287     if (m_hasFontFaceOnlyValues)
1288         deleteFontFaceOnlyValues();
1289     if (!m_parsedProperties.isEmpty()) {
1290         ok = true;
1291         declaration->addParsedProperties(m_parsedProperties);
1292         clearProperties();
1293     }
1294
1295     if (m_observer)
1296         m_observer->endRuleBody(string.length(), false);
1297
1298     return ok;
1299 }
1300
1301 PassRefPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
1302 {
1303     ASSERT(!m_mediaList);
1304
1305     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1306     // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
1307     setupParser("@-internal-medialist ", string, "");
1308     cssyyparse(this);
1309
1310     ASSERT(m_mediaList);
1311     return m_mediaList.release();
1312 }
1313
1314 static inline void filterProperties(bool important, const BisonCSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1315 {
1316     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1317     for (int i = input.size() - 1; i >= 0; --i) {
1318         const CSSProperty& property = input[i];
1319         if (property.isImportant() != important)
1320             continue;
1321         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1322         if (seenProperties.get(propertyIDIndex))
1323             continue;
1324         seenProperties.set(propertyIDIndex);
1325         output[--unusedEntries] = property;
1326     }
1327 }
1328
1329 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
1330 {
1331     BitArray<numCSSProperties> seenProperties;
1332     size_t unusedEntries = m_parsedProperties.size();
1333     Vector<CSSProperty, 256> results(unusedEntries);
1334
1335     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1336     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1337     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1338     if (unusedEntries)
1339         results.remove(0, unusedEntries);
1340
1341     CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
1342
1343     return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
1344 }
1345
1346 void BisonCSSParser::addPropertyWithPrefixingVariant(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1347 {
1348     RefPtr<CSSValue> val = value.get();
1349     addProperty(propId, value, important, implicit);
1350
1351     CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(propId);
1352     if (prefixingVariant == propId)
1353         return;
1354
1355     if (m_currentShorthand) {
1356         // We can't use ShorthandScope here as we can already be inside one (e.g we are parsing CSSTransition).
1357         m_currentShorthand = prefixingVariantForPropertyId(m_currentShorthand);
1358         addProperty(prefixingVariant, val.release(), important, implicit);
1359         m_currentShorthand = prefixingVariantForPropertyId(m_currentShorthand);
1360     } else {
1361         addProperty(prefixingVariant, val.release(), important, implicit);
1362     }
1363 }
1364
1365 void BisonCSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1366 {
1367     // This property doesn't belong to a shorthand.
1368     if (!m_currentShorthand) {
1369         m_parsedProperties.append(CSSProperty(propId, value, important, false, CSSPropertyInvalid, m_implicitShorthand || implicit));
1370         return;
1371     }
1372
1373     Vector<StylePropertyShorthand, 4> shorthands;
1374     getMatchingShorthandsForLonghand(propId, &shorthands);
1375     // The longhand does not belong to multiple shorthands.
1376     if (shorthands.size() == 1)
1377         m_parsedProperties.append(CSSProperty(propId, value, important, true, CSSPropertyInvalid, m_implicitShorthand || implicit));
1378     else
1379         m_parsedProperties.append(CSSProperty(propId, value, important, true, indexOfShorthandForLonghand(m_currentShorthand, shorthands), m_implicitShorthand || implicit));
1380 }
1381
1382 void BisonCSSParser::rollbackLastProperties(int num)
1383 {
1384     ASSERT(num >= 0);
1385     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1386     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1387 }
1388
1389 void BisonCSSParser::clearProperties()
1390 {
1391     m_parsedProperties.clear();
1392     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1393     m_hasFontFaceOnlyValues = false;
1394 }
1395
1396 KURL BisonCSSParser::completeURL(const String& url) const
1397 {
1398     return m_context.completeURL(url);
1399 }
1400
1401 bool BisonCSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags, ReleaseParsedCalcValueCondition releaseCalc)
1402 {
1403     bool mustBeNonNegative = unitflags & FNonNeg;
1404
1405     if (!parseCalculation(value, mustBeNonNegative ? ValueRangeNonNegative : ValueRangeAll))
1406         return false;
1407
1408     bool b = false;
1409     switch (m_parsedCalculation->category()) {
1410     case CalcLength:
1411         b = (unitflags & FLength);
1412         break;
1413     case CalcPercent:
1414         b = (unitflags & FPercent);
1415         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1416             b = false;
1417         break;
1418     case CalcNumber:
1419         b = (unitflags & FNumber);
1420         if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt())
1421             b = true;
1422         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1423             b = false;
1424         break;
1425     case CalcPercentLength:
1426         b = (unitflags & FPercent) && (unitflags & FLength);
1427         break;
1428     case CalcPercentNumber:
1429         b = (unitflags & FPercent) && (unitflags & FNumber);
1430         break;
1431     case CalcOther:
1432         break;
1433     }
1434     if (!b || releaseCalc == ReleaseParsedCalcValue)
1435         m_parsedCalculation.release();
1436     return b;
1437 }
1438
1439 inline bool BisonCSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1440 {
1441     // Quirks mode and presentation attributes accept unit less values.
1442     return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || isUnitLessLengthParsingEnabledForMode(cssParserMode));
1443 }
1444
1445 bool BisonCSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode, ReleaseParsedCalcValueCondition releaseCalc)
1446 {
1447     if (isCalculation(value))
1448         return validCalculationUnit(value, unitflags, releaseCalc);
1449
1450     bool b = false;
1451     switch (value->unit) {
1452     case CSSPrimitiveValue::CSS_NUMBER:
1453         b = (unitflags & FNumber);
1454         if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) {
1455             value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
1456                           ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1457             b = true;
1458         }
1459         if (!b && (unitflags & FInteger) && value->isInt)
1460             b = true;
1461         if (!b && (unitflags & FPositiveInteger) && value->isInt && value->fValue > 0)
1462             b = true;
1463         break;
1464     case CSSPrimitiveValue::CSS_PERCENTAGE:
1465         b = (unitflags & FPercent);
1466         break;
1467     case CSSParserValue::Q_EMS:
1468     case CSSPrimitiveValue::CSS_EMS:
1469     case CSSPrimitiveValue::CSS_REMS:
1470     case CSSPrimitiveValue::CSS_CHS:
1471     case CSSPrimitiveValue::CSS_EXS:
1472     case CSSPrimitiveValue::CSS_PX:
1473     case CSSPrimitiveValue::CSS_CM:
1474     case CSSPrimitiveValue::CSS_MM:
1475     case CSSPrimitiveValue::CSS_IN:
1476     case CSSPrimitiveValue::CSS_PT:
1477     case CSSPrimitiveValue::CSS_PC:
1478     case CSSPrimitiveValue::CSS_VW:
1479     case CSSPrimitiveValue::CSS_VH:
1480     case CSSPrimitiveValue::CSS_VMIN:
1481     case CSSPrimitiveValue::CSS_VMAX:
1482         b = (unitflags & FLength);
1483         break;
1484     case CSSPrimitiveValue::CSS_MS:
1485     case CSSPrimitiveValue::CSS_S:
1486         b = (unitflags & FTime);
1487         break;
1488     case CSSPrimitiveValue::CSS_DEG:
1489     case CSSPrimitiveValue::CSS_RAD:
1490     case CSSPrimitiveValue::CSS_GRAD:
1491     case CSSPrimitiveValue::CSS_TURN:
1492         b = (unitflags & FAngle);
1493         break;
1494     case CSSPrimitiveValue::CSS_DPPX:
1495     case CSSPrimitiveValue::CSS_DPI:
1496     case CSSPrimitiveValue::CSS_DPCM:
1497         b = (unitflags & FResolution);
1498         break;
1499     case CSSPrimitiveValue::CSS_HZ:
1500     case CSSPrimitiveValue::CSS_KHZ:
1501     case CSSPrimitiveValue::CSS_DIMENSION:
1502     default:
1503         break;
1504     }
1505     if (b && unitflags & FNonNeg && value->fValue < 0)
1506         b = false;
1507     return b;
1508 }
1509
1510 inline PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::createPrimitiveNumericValue(CSSParserValue* value)
1511 {
1512     if (m_parsedCalculation) {
1513         ASSERT(isCalculation(value));
1514         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1515     }
1516
1517     ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1518         || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_CHS)
1519         || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMAX)
1520         || (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM));
1521     return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
1522 }
1523
1524 inline PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::createPrimitiveStringValue(CSSParserValue* value)
1525 {
1526     ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
1527     return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING);
1528 }
1529
1530 static inline bool isComma(CSSParserValue* value)
1531 {
1532     return value && value->unit == CSSParserValue::Operator && value->iValue == ',';
1533 }
1534
1535 static inline bool isForwardSlashOperator(CSSParserValue* value)
1536 {
1537     ASSERT(value);
1538     return value->unit == CSSParserValue::Operator && value->iValue == '/';
1539 }
1540
1541 static bool isGeneratedImageValue(CSSParserValue* val)
1542 {
1543     if (val->unit != CSSParserValue::Function)
1544         return false;
1545
1546     return equalIgnoringCase(val->function->name, "-webkit-gradient(")
1547         || equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")
1548         || equalIgnoringCase(val->function->name, "linear-gradient(")
1549         || equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")
1550         || equalIgnoringCase(val->function->name, "repeating-linear-gradient(")
1551         || equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")
1552         || equalIgnoringCase(val->function->name, "radial-gradient(")
1553         || equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")
1554         || equalIgnoringCase(val->function->name, "repeating-radial-gradient(")
1555         || equalIgnoringCase(val->function->name, "-webkit-canvas(")
1556         || equalIgnoringCase(val->function->name, "-webkit-cross-fade(");
1557 }
1558
1559 bool BisonCSSParser::validWidthOrHeight(CSSParserValue* value)
1560 {
1561     int id = value->id;
1562     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic || id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent || id == CSSValueWebkitFillAvailable || id == CSSValueWebkitFitContent)
1563         return true;
1564     return !id && validUnit(value, FLength | FPercent | FNonNeg);
1565 }
1566
1567 inline PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::parseValidPrimitive(CSSValueID identifier, CSSParserValue* value)
1568 {
1569     if (identifier)
1570         return cssValuePool().createIdentifierValue(identifier);
1571     if (value->unit == CSSPrimitiveValue::CSS_STRING)
1572         return createPrimitiveStringValue(value);
1573     if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1574         return createPrimitiveNumericValue(value);
1575     if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_CHS)
1576         return createPrimitiveNumericValue(value);
1577     if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMAX)
1578         return createPrimitiveNumericValue(value);
1579     if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM)
1580         return createPrimitiveNumericValue(value);
1581     if (value->unit >= CSSParserValue::Q_EMS)
1582         return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
1583     if (isCalculation(value))
1584         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1585
1586     return 0;
1587 }
1588
1589 void BisonCSSParser::addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtr<CSSValue> prpValue, bool important)
1590 {
1591     const StylePropertyShorthand& shorthand = shorthandForProperty(propId);
1592     unsigned shorthandLength = shorthand.length();
1593     if (!shorthandLength) {
1594         addProperty(propId, prpValue, important);
1595         return;
1596     }
1597
1598     RefPtr<CSSValue> value = prpValue;
1599     ShorthandScope scope(this, propId);
1600     const CSSPropertyID* longhands = shorthand.properties();
1601     for (unsigned i = 0; i < shorthandLength; ++i)
1602         addProperty(longhands[i], value, important);
1603 }
1604
1605 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
1606 {
1607     m_id = propId;
1608 }
1609
1610 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
1611 {
1612     if (!isInternalPropertyAndValueParsingEnabledForMode(m_context.mode()) && isInternalProperty(propId))
1613         return false;
1614
1615     // We don't count the UA style sheet in our statistics.
1616     if (m_context.useCounter())
1617         m_context.useCounter()->count(m_context, propId);
1618
1619     if (!m_valueList)
1620         return false;
1621
1622     CSSParserValue* value = m_valueList->current();
1623
1624     if (!value)
1625         return false;
1626
1627     if (inViewport()) {
1628         // Allow @viewport rules from UA stylesheets even if the feature is disabled.
1629         if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
1630             return false;
1631
1632         return parseViewportProperty(propId, important);
1633     }
1634
1635     // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function.
1636     // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers.
1637     ASSERT(!m_parsedCalculation);
1638
1639     CSSValueID id = value->id;
1640
1641     int num = inShorthand() ? 1 : m_valueList->size();
1642
1643     if (id == CSSValueInherit) {
1644         if (num != 1)
1645             return false;
1646         addExpandedPropertyForValue(propId, cssValuePool().createInheritedValue(), important);
1647         return true;
1648     }
1649     else if (id == CSSValueInitial) {
1650         if (num != 1)
1651             return false;
1652         addExpandedPropertyForValue(propId, cssValuePool().createExplicitInitialValue(), important);
1653         return true;
1654     }
1655
1656     if (isKeywordPropertyID(propId)) {
1657         if (!isValidKeywordPropertyAndValue(propId, id, m_context))
1658             return false;
1659         if (m_valueList->next() && !inShorthand())
1660             return false;
1661         addProperty(propId, cssValuePool().createIdentifierValue(id), important);
1662         return true;
1663     }
1664
1665     bool validPrimitive = false;
1666     RefPtr<CSSValue> parsedValue;
1667
1668     switch (propId) {
1669     case CSSPropertySize:                 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1670         return parseSize(propId, important);
1671
1672     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
1673         if (id)
1674             validPrimitive = true;
1675         else
1676             return parseQuotes(propId, important);
1677         break;
1678     case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | isolate-override | plaintext | inherit
1679         if (id == CSSValueNormal
1680             || id == CSSValueEmbed
1681             || id == CSSValueBidiOverride
1682             || id == CSSValueWebkitIsolate
1683             || id == CSSValueWebkitIsolateOverride
1684             || id == CSSValueWebkitPlaintext)
1685             validPrimitive = true;
1686         break;
1687
1688     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1689         // close-quote | no-open-quote | no-close-quote ]+ | inherit
1690         return parseContent(propId, important);
1691
1692     case CSSPropertyClip:                 // <shape> | auto | inherit
1693         if (id == CSSValueAuto)
1694             validPrimitive = true;
1695         else if (value->unit == CSSParserValue::Function)
1696             return parseClipShape(propId, important);
1697         break;
1698
1699     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1700      * correctly and allows optimization in WebCore::applyRule(..)
1701      */
1702     case CSSPropertyOverflow: {
1703         ShorthandScope scope(this, propId);
1704         if (num != 1 || !parseValue(CSSPropertyOverflowY, important))
1705             return false;
1706
1707         RefPtr<CSSValue> overflowXValue;
1708
1709         // FIXME: -webkit-paged-x or -webkit-paged-y only apply to overflow-y. If this value has been
1710         // set using the shorthand, then for now overflow-x will default to auto, but once we implement
1711         // pagination controls, it should default to hidden. If the overflow-y value is anything but
1712         // paged-x or paged-y, then overflow-x and overflow-y should have the same value.
1713         if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY)
1714             overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto);
1715         else
1716             overflowXValue = m_parsedProperties.last().value();
1717         addProperty(CSSPropertyOverflowX, overflowXValue.release(), important);
1718         return true;
1719     }
1720
1721     case CSSPropertyTextAlign:
1722         // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent
1723         // | start | end | <string> | inherit | -webkit-auto (converted to start)
1724         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
1725             || value->unit == CSSPrimitiveValue::CSS_STRING)
1726             validPrimitive = true;
1727         break;
1728
1729     case CSSPropertyFontWeight:  { // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1730         if (m_valueList->size() != 1)
1731             return false;
1732         return parseFontWeight(important);
1733     }
1734     case CSSPropertyBorderSpacing: {
1735         if (num == 1) {
1736             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1737             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important))
1738                 return false;
1739             CSSValue* value = m_parsedProperties.last().value();
1740             addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important);
1741             return true;
1742         }
1743         else if (num == 2) {
1744             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1745             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important))
1746                 return false;
1747             return true;
1748         }
1749         return false;
1750     }
1751     case CSSPropertyWebkitBorderHorizontalSpacing:
1752     case CSSPropertyWebkitBorderVerticalSpacing:
1753         validPrimitive = validUnit(value, FLength | FNonNeg);
1754         break;
1755     case CSSPropertyOutlineColor:        // <color> | invert | inherit
1756         // Outline color has "invert" as additional keyword.
1757         // Also, we want to allow the special focus color even in HTML Standard parsing mode.
1758         if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
1759             validPrimitive = true;
1760             break;
1761         }
1762         /* nobreak */
1763     case CSSPropertyBackgroundColor: // <color> | inherit
1764     case CSSPropertyBorderTopColor: // <color> | inherit
1765     case CSSPropertyBorderRightColor:
1766     case CSSPropertyBorderBottomColor:
1767     case CSSPropertyBorderLeftColor:
1768     case CSSPropertyWebkitBorderStartColor:
1769     case CSSPropertyWebkitBorderEndColor:
1770     case CSSPropertyWebkitBorderBeforeColor:
1771     case CSSPropertyWebkitBorderAfterColor:
1772     case CSSPropertyColor: // <color> | inherit
1773     case CSSPropertyTextDecorationColor: // CSS3 text decoration colors
1774     case CSSPropertyTextLineThroughColor:
1775     case CSSPropertyTextUnderlineColor:
1776     case CSSPropertyTextOverlineColor:
1777     case CSSPropertyWebkitColumnRuleColor:
1778     case CSSPropertyWebkitTextEmphasisColor:
1779     case CSSPropertyWebkitTextFillColor:
1780     case CSSPropertyWebkitTextStrokeColor:
1781         if (propId == CSSPropertyTextDecorationColor
1782             && !RuntimeEnabledFeatures::css3TextDecorationsEnabled())
1783             return false;
1784
1785         if ((id >= CSSValueAqua && id <= CSSValueWebkitText) || id == CSSValueMenu) {
1786             validPrimitive = isValueAllowedInMode(id, m_context.mode());
1787         } else {
1788             parsedValue = parseColor();
1789             if (parsedValue)
1790                 m_valueList->next();
1791         }
1792         break;
1793
1794     case CSSPropertyCursor: {
1795         // Grammar defined by CSS3 UI and modified by CSS4 images:
1796         // [ [<image> [<x> <y>]?,]*
1797         // [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
1798         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
1799         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
1800         // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
1801         // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
1802         RefPtrWillBeRawPtr<CSSValueList> list;
1803         while (value) {
1804             RefPtr<CSSValue> image = 0;
1805             if (value->unit == CSSPrimitiveValue::CSS_URI) {
1806                 String uri = value->string;
1807                 if (!uri.isNull())
1808                     image = CSSImageValue::create(completeURL(uri));
1809             } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1810                 image = parseImageSet(m_valueList.get());
1811                 if (!image)
1812                     break;
1813             } else
1814                 break;
1815
1816             Vector<int> coords;
1817             value = m_valueList->next();
1818             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
1819                 coords.append(int(value->fValue));
1820                 value = m_valueList->next();
1821             }
1822             bool hasHotSpot = false;
1823             IntPoint hotSpot(-1, -1);
1824             int nrcoords = coords.size();
1825             if (nrcoords > 0 && nrcoords != 2)
1826                 return false;
1827             if (nrcoords == 2) {
1828                 hasHotSpot = true;
1829                 hotSpot = IntPoint(coords[0], coords[1]);
1830             }
1831
1832             if (!list)
1833                 list = CSSValueList::createCommaSeparated();
1834
1835             if (image)
1836                 list->append(CSSCursorImageValue::create(image, hasHotSpot, hotSpot));
1837
1838             if (!value || !(value->unit == CSSParserValue::Operator && value->iValue == ','))
1839                 return false;
1840             value = m_valueList->next(); // comma
1841         }
1842         if (list) {
1843             if (!value)
1844                 return false;
1845             if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/
1846                 list->append(cssValuePool().createIdentifierValue(CSSValuePointer));
1847             else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1848                 list->append(cssValuePool().createIdentifierValue(value->id));
1849             m_valueList->next();
1850             parsedValue = list.release();
1851             break;
1852         } else if (value) {
1853             id = value->id;
1854             if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/
1855                 id = CSSValuePointer;
1856                 validPrimitive = true;
1857             } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1858                 validPrimitive = true;
1859         } else {
1860             ASSERT_NOT_REACHED();
1861             return false;
1862         }
1863         break;
1864     }
1865
1866     case CSSPropertyBackgroundBlendMode:
1867     case CSSPropertyBackgroundAttachment:
1868     case CSSPropertyBackgroundClip:
1869     case CSSPropertyWebkitBackgroundClip:
1870     case CSSPropertyWebkitBackgroundComposite:
1871     case CSSPropertyBackgroundImage:
1872     case CSSPropertyBackgroundOrigin:
1873     case CSSPropertyMaskSourceType:
1874     case CSSPropertyWebkitBackgroundOrigin:
1875     case CSSPropertyBackgroundPosition:
1876     case CSSPropertyBackgroundPositionX:
1877     case CSSPropertyBackgroundPositionY:
1878     case CSSPropertyBackgroundSize:
1879     case CSSPropertyWebkitBackgroundSize:
1880     case CSSPropertyBackgroundRepeat:
1881     case CSSPropertyBackgroundRepeatX:
1882     case CSSPropertyBackgroundRepeatY:
1883     case CSSPropertyWebkitMaskClip:
1884     case CSSPropertyWebkitMaskComposite:
1885     case CSSPropertyWebkitMaskImage:
1886     case CSSPropertyWebkitMaskOrigin:
1887     case CSSPropertyWebkitMaskPosition:
1888     case CSSPropertyWebkitMaskPositionX:
1889     case CSSPropertyWebkitMaskPositionY:
1890     case CSSPropertyWebkitMaskSize:
1891     case CSSPropertyWebkitMaskRepeat:
1892     case CSSPropertyWebkitMaskRepeatX:
1893     case CSSPropertyWebkitMaskRepeatY:
1894     {
1895         RefPtr<CSSValue> val1;
1896         RefPtr<CSSValue> val2;
1897         CSSPropertyID propId1, propId2;
1898         bool result = false;
1899         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
1900             OwnPtr<ShorthandScope> shorthandScope;
1901             if (propId == CSSPropertyBackgroundPosition ||
1902                 propId == CSSPropertyBackgroundRepeat ||
1903                 propId == CSSPropertyWebkitMaskPosition ||
1904                 propId == CSSPropertyWebkitMaskRepeat) {
1905                 shorthandScope = adoptPtr(new ShorthandScope(this, propId));
1906             }
1907             addProperty(propId1, val1.release(), important);
1908             if (val2)
1909                 addProperty(propId2, val2.release(), important);
1910             result = true;
1911         }
1912         m_implicitShorthand = false;
1913         return result;
1914     }
1915     case CSSPropertyObjectPosition:
1916         return RuntimeEnabledFeatures::objectFitPositionEnabled() && parseObjectPosition(important);
1917     case CSSPropertyListStyleImage:     // <uri> | none | inherit
1918     case CSSPropertyBorderImageSource:
1919     case CSSPropertyWebkitMaskBoxImageSource:
1920         if (id == CSSValueNone) {
1921             parsedValue = cssValuePool().createIdentifierValue(CSSValueNone);
1922             m_valueList->next();
1923         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
1924             parsedValue = CSSImageValue::create(completeURL(value->string));
1925             m_valueList->next();
1926         } else if (isGeneratedImageValue(value)) {
1927             if (parseGeneratedImage(m_valueList.get(), parsedValue))
1928                 m_valueList->next();
1929             else
1930                 return false;
1931         }
1932         else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1933             parsedValue = parseImageSet(m_valueList.get());
1934             if (!parsedValue)
1935                 return false;
1936             m_valueList->next();
1937         }
1938         break;
1939
1940     case CSSPropertyWebkitTextStrokeWidth:
1941     case CSSPropertyOutlineWidth:        // <border-width> | inherit
1942     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
1943     case CSSPropertyBorderRightWidth:   //   Which is defined as
1944     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
1945     case CSSPropertyBorderLeftWidth:
1946     case CSSPropertyWebkitBorderStartWidth:
1947     case CSSPropertyWebkitBorderEndWidth:
1948     case CSSPropertyWebkitBorderBeforeWidth:
1949     case CSSPropertyWebkitBorderAfterWidth:
1950     case CSSPropertyWebkitColumnRuleWidth:
1951         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1952             validPrimitive = true;
1953         else
1954             validPrimitive = validUnit(value, FLength | FNonNeg);
1955         break;
1956
1957     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
1958     case CSSPropertyWordSpacing:         // normal | <length> | inherit
1959         if (id == CSSValueNormal)
1960             validPrimitive = true;
1961         else
1962             validPrimitive = validUnit(value, FLength);
1963         break;
1964
1965     case CSSPropertyTextIndent:
1966         parsedValue = parseTextIndent();
1967         break;
1968
1969     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
1970     case CSSPropertyPaddingRight:        //   Which is defined as
1971     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
1972     case CSSPropertyPaddingLeft:         ////
1973     case CSSPropertyWebkitPaddingStart:
1974     case CSSPropertyWebkitPaddingEnd:
1975     case CSSPropertyWebkitPaddingBefore:
1976     case CSSPropertyWebkitPaddingAfter:
1977         validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
1978         break;
1979
1980     case CSSPropertyMaxWidth:
1981     case CSSPropertyWebkitMaxLogicalWidth:
1982     case CSSPropertyMaxHeight:
1983     case CSSPropertyWebkitMaxLogicalHeight:
1984         validPrimitive = (id == CSSValueNone || validWidthOrHeight(value));
1985         break;
1986
1987     case CSSPropertyMinWidth:
1988     case CSSPropertyWebkitMinLogicalWidth:
1989     case CSSPropertyMinHeight:
1990     case CSSPropertyWebkitMinLogicalHeight:
1991         validPrimitive = validWidthOrHeight(value);
1992         break;
1993
1994     case CSSPropertyWidth:
1995     case CSSPropertyWebkitLogicalWidth:
1996     case CSSPropertyHeight:
1997     case CSSPropertyWebkitLogicalHeight:
1998         validPrimitive = (id == CSSValueAuto || validWidthOrHeight(value));
1999         break;
2000
2001     case CSSPropertyFontSize:
2002         return parseFontSize(important);
2003
2004     case CSSPropertyFontVariant:         // normal | small-caps | inherit
2005         return parseFontVariant(important);
2006
2007     case CSSPropertyVerticalAlign:
2008         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
2009         // <percentage> | <length> | inherit
2010
2011         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
2012             validPrimitive = true;
2013         else
2014             validPrimitive = (!id && validUnit(value, FLength | FPercent));
2015         break;
2016
2017     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
2018     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
2019     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
2020     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
2021     case CSSPropertyMarginTop:           //// <margin-width> | inherit
2022     case CSSPropertyMarginRight:         //   Which is defined as
2023     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
2024     case CSSPropertyMarginLeft:          ////
2025     case CSSPropertyWebkitMarginStart:
2026     case CSSPropertyWebkitMarginEnd:
2027     case CSSPropertyWebkitMarginBefore:
2028     case CSSPropertyWebkitMarginAfter:
2029         if (id == CSSValueAuto)
2030             validPrimitive = true;
2031         else
2032             validPrimitive = (!id && validUnit(value, FLength | FPercent));
2033         break;
2034
2035     case CSSPropertyOrphans: // <integer> | inherit | auto (We've added support for auto for backwards compatibility)
2036     case CSSPropertyWidows: // <integer> | inherit | auto (Ditto)
2037         if (id == CSSValueAuto)
2038             validPrimitive = true;
2039         else
2040             validPrimitive = (!id && validUnit(value, FPositiveInteger, HTMLQuirksMode));
2041         break;
2042
2043     case CSSPropertyZIndex: // auto | <integer> | inherit
2044         if (id == CSSValueAuto)
2045             validPrimitive = true;
2046         else
2047             validPrimitive = (!id && validUnit(value, FInteger, HTMLQuirksMode));
2048         break;
2049
2050     case CSSPropertyLineHeight:
2051         return parseLineHeight(important);
2052     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
2053         if (id != CSSValueNone)
2054             return parseCounter(propId, 1, important);
2055         validPrimitive = true;
2056         break;
2057     case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
2058         if (id != CSSValueNone)
2059             return parseCounter(propId, 0, important);
2060         validPrimitive = true;
2061         break;
2062     case CSSPropertyFontFamily:
2063         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
2064     {
2065         parsedValue = parseFontFamily();
2066         break;
2067     }
2068
2069     case CSSPropertyTextDecoration:
2070         // Fall through 'text-decoration-line' parsing if CSS 3 Text Decoration
2071         // is disabled to match CSS 2.1 rules for parsing 'text-decoration'.
2072         if (RuntimeEnabledFeatures::css3TextDecorationsEnabled()) {
2073             // [ <text-decoration-line> || <text-decoration-style> || <text-decoration-color> ] | inherit
2074             return parseShorthand(CSSPropertyTextDecoration, textDecorationShorthand(), important);
2075         }
2076     case CSSPropertyWebkitTextDecorationsInEffect:
2077     case CSSPropertyTextDecorationLine:
2078         // none | [ underline || overline || line-through || blink ] | inherit
2079         return parseTextDecoration(propId, important);
2080
2081     case CSSPropertyTextDecorationStyle:
2082         // solid | double | dotted | dashed | wavy
2083         if (RuntimeEnabledFeatures::css3TextDecorationsEnabled()
2084             && (id == CSSValueSolid || id == CSSValueDouble || id == CSSValueDotted || id == CSSValueDashed || id == CSSValueWavy))
2085             validPrimitive = true;
2086         break;
2087
2088     case CSSPropertyTextUnderlinePosition:
2089         // auto | under | inherit
2090         if (RuntimeEnabledFeatures::css3TextDecorationsEnabled())
2091             return parseTextUnderlinePosition(important);
2092         return false;
2093
2094     case CSSPropertyZoom:          // normal | reset | document | <number> | <percentage> | inherit
2095         if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
2096             validPrimitive = true;
2097         else
2098             validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, HTMLStandardMode));
2099         break;
2100
2101     case CSSPropertySrc: // Only used within @font-face and @-webkit-filter, so cannot use inherit | initial or be !important. This is a list of urls or local references.
2102         return parseFontFaceSrc();
2103
2104     case CSSPropertyUnicodeRange:
2105         return parseFontFaceUnicodeRange();
2106
2107     /* CSS3 properties */
2108
2109     case CSSPropertyBorderImage:
2110     case CSSPropertyWebkitMaskBoxImage:
2111         return parseBorderImageShorthand(propId, important);
2112     case CSSPropertyWebkitBorderImage: {
2113         if (RefPtr<CSSValue> result = parseBorderImage(propId)) {
2114             addProperty(propId, result, important);
2115             return true;
2116         }
2117         return false;
2118     }
2119
2120     case CSSPropertyBorderImageOutset:
2121     case CSSPropertyWebkitMaskBoxImageOutset: {
2122         RefPtrWillBeRawPtr<CSSPrimitiveValue> result;
2123         if (parseBorderImageOutset(result)) {
2124             addProperty(propId, result, important);
2125             return true;
2126         }
2127         break;
2128     }
2129     case CSSPropertyBorderImageRepeat:
2130     case CSSPropertyWebkitMaskBoxImageRepeat: {
2131         RefPtr<CSSValue> result;
2132         if (parseBorderImageRepeat(result)) {
2133             addProperty(propId, result, important);
2134             return true;
2135         }
2136         break;
2137     }
2138     case CSSPropertyBorderImageSlice:
2139     case CSSPropertyWebkitMaskBoxImageSlice: {
2140         RefPtrWillBeRawPtr<CSSBorderImageSliceValue> result;
2141         if (parseBorderImageSlice(propId, result)) {
2142             addProperty(propId, result, important);
2143             return true;
2144         }
2145         break;
2146     }
2147     case CSSPropertyBorderImageWidth:
2148     case CSSPropertyWebkitMaskBoxImageWidth: {
2149         RefPtrWillBeRawPtr<CSSPrimitiveValue> result;
2150         if (parseBorderImageWidth(result)) {
2151             addProperty(propId, result, important);
2152             return true;
2153         }
2154         break;
2155     }
2156     case CSSPropertyBorderTopRightRadius:
2157     case CSSPropertyBorderTopLeftRadius:
2158     case CSSPropertyBorderBottomLeftRadius:
2159     case CSSPropertyBorderBottomRightRadius: {
2160         if (num != 1 && num != 2)
2161             return false;
2162         validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
2163         if (!validPrimitive)
2164             return false;
2165         RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
2166         RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2;
2167         if (num == 2) {
2168             value = m_valueList->next();
2169             validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
2170             if (!validPrimitive)
2171                 return false;
2172             parsedValue2 = createPrimitiveNumericValue(value);
2173         } else
2174             parsedValue2 = parsedValue1;
2175
2176         addProperty(propId, createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release()), important);
2177         return true;
2178     }
2179     case CSSPropertyTabSize:
2180         validPrimitive = validUnit(value, FInteger | FNonNeg);
2181         break;
2182     case CSSPropertyWebkitAspectRatio:
2183         return parseAspectRatio(important);
2184     case CSSPropertyBorderRadius:
2185     case CSSPropertyWebkitBorderRadius:
2186         return parseBorderRadius(propId, important);
2187     case CSSPropertyOutlineOffset:
2188         validPrimitive = validUnit(value, FLength);
2189         break;
2190     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
2191     case CSSPropertyBoxShadow:
2192     case CSSPropertyWebkitBoxShadow:
2193         if (id == CSSValueNone)
2194             validPrimitive = true;
2195         else {
2196             RefPtrWillBeRawPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
2197             if (shadowValueList) {
2198                 addProperty(propId, shadowValueList.release(), important);
2199                 m_valueList->next();
2200                 return true;
2201             }
2202             return false;
2203         }
2204         break;
2205     case CSSPropertyWebkitBoxReflect:
2206         if (id == CSSValueNone)
2207             validPrimitive = true;
2208         else
2209             return parseReflect(propId, important);
2210         break;
2211     case CSSPropertyOpacity:
2212         validPrimitive = validUnit(value, FNumber);
2213         break;
2214     case CSSPropertyWebkitBoxFlex:
2215         validPrimitive = validUnit(value, FNumber);
2216         break;
2217     case CSSPropertyWebkitBoxFlexGroup:
2218         validPrimitive = validUnit(value, FInteger | FNonNeg, HTMLStandardMode);
2219         break;
2220     case CSSPropertyWebkitBoxOrdinalGroup:
2221         validPrimitive = validUnit(value, FInteger | FNonNeg, HTMLStandardMode) && value->fValue;
2222         break;
2223     case CSSPropertyWebkitFilter:
2224         if (id == CSSValueNone)
2225             validPrimitive = true;
2226         else {
2227             RefPtr<CSSValue> val = parseFilter();
2228             if (val) {
2229                 addProperty(propId, val, important);
2230                 return true;
2231             }
2232             return false;
2233         }
2234         break;
2235     case CSSPropertyFlex: {
2236         ShorthandScope scope(this, propId);
2237         if (id == CSSValueNone) {
2238             addProperty(CSSPropertyFlexGrow, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2239             addProperty(CSSPropertyFlexShrink, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2240             addProperty(CSSPropertyFlexBasis, cssValuePool().createIdentifierValue(CSSValueAuto), important);
2241             return true;
2242         }
2243         return parseFlex(m_valueList.get(), important);
2244     }
2245     case CSSPropertyFlexBasis:
2246         // FIXME: Support intrinsic dimensions too.
2247         if (id == CSSValueAuto)
2248             validPrimitive = true;
2249         else
2250             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
2251         break;
2252     case CSSPropertyFlexGrow:
2253     case CSSPropertyFlexShrink:
2254         validPrimitive = validUnit(value, FNumber | FNonNeg);
2255         break;
2256     case CSSPropertyOrder:
2257         validPrimitive = validUnit(value, FInteger, HTMLStandardMode);
2258         break;
2259     case CSSPropertyInternalMarqueeIncrement:
2260         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2261             validPrimitive = true;
2262         else
2263             validPrimitive = validUnit(value, FLength | FPercent);
2264         break;
2265     case CSSPropertyInternalMarqueeRepetition:
2266         if (id == CSSValueInfinite)
2267             validPrimitive = true;
2268         else
2269             validPrimitive = validUnit(value, FInteger | FNonNeg);
2270         break;
2271     case CSSPropertyInternalMarqueeSpeed:
2272         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2273             validPrimitive = true;
2274         else
2275             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg);
2276         break;
2277     case CSSPropertyWebkitTransform:
2278         if (id == CSSValueNone)
2279             validPrimitive = true;
2280         else {
2281             RefPtr<CSSValue> transformValue = parseTransform();
2282             if (transformValue) {
2283                 addProperty(propId, transformValue.release(), important);
2284                 return true;
2285             }
2286             return false;
2287         }
2288         break;
2289     case CSSPropertyWebkitTransformOrigin:
2290     case CSSPropertyWebkitTransformOriginX:
2291     case CSSPropertyWebkitTransformOriginY:
2292     case CSSPropertyWebkitTransformOriginZ: {
2293         RefPtr<CSSValue> val1;
2294         RefPtr<CSSValue> val2;
2295         RefPtr<CSSValue> val3;
2296         CSSPropertyID propId1, propId2, propId3;
2297         if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2298             addProperty(propId1, val1.release(), important);
2299             if (val2)
2300                 addProperty(propId2, val2.release(), important);
2301             if (val3)
2302                 addProperty(propId3, val3.release(), important);
2303             return true;
2304         }
2305         return false;
2306     }
2307     case CSSPropertyWebkitPerspective:
2308         if (id == CSSValueNone)
2309             validPrimitive = true;
2310         else {
2311             // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2312             if (validUnit(value, FNumber | FLength | FNonNeg)) {
2313                 RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
2314                 if (val) {
2315                     addProperty(propId, val.release(), important);
2316                     return true;
2317                 }
2318                 return false;
2319             }
2320         }
2321         break;
2322     case CSSPropertyWebkitPerspectiveOrigin:
2323     case CSSPropertyWebkitPerspectiveOriginX:
2324     case CSSPropertyWebkitPerspectiveOriginY: {
2325         RefPtr<CSSValue> val1;
2326         RefPtr<CSSValue> val2;
2327         CSSPropertyID propId1, propId2;
2328         if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2329             addProperty(propId1, val1.release(), important);
2330             if (val2)
2331                 addProperty(propId2, val2.release(), important);
2332             return true;
2333         }
2334         return false;
2335     }
2336     case CSSPropertyAnimationDelay:
2337     case CSSPropertyAnimationDirection:
2338     case CSSPropertyAnimationDuration:
2339     case CSSPropertyAnimationFillMode:
2340     case CSSPropertyAnimationName:
2341     case CSSPropertyAnimationPlayState:
2342     case CSSPropertyAnimationIterationCount:
2343     case CSSPropertyAnimationTimingFunction:
2344         if (!RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled())
2345             break;
2346     case CSSPropertyWebkitAnimationDelay:
2347     case CSSPropertyWebkitAnimationDirection:
2348     case CSSPropertyWebkitAnimationDuration:
2349     case CSSPropertyWebkitAnimationFillMode:
2350     case CSSPropertyWebkitAnimationName:
2351     case CSSPropertyWebkitAnimationPlayState:
2352     case CSSPropertyWebkitAnimationIterationCount:
2353     case CSSPropertyWebkitAnimationTimingFunction:
2354     case CSSPropertyTransitionDelay:
2355     case CSSPropertyTransitionDuration:
2356     case CSSPropertyTransitionTimingFunction:
2357     case CSSPropertyTransitionProperty:
2358     case CSSPropertyWebkitTransitionDelay:
2359     case CSSPropertyWebkitTransitionDuration:
2360     case CSSPropertyWebkitTransitionTimingFunction:
2361     case CSSPropertyWebkitTransitionProperty: {
2362         RefPtr<CSSValue> val;
2363         AnimationParseContext context;
2364         if (parseAnimationProperty(propId, val, context)) {
2365             addPropertyWithPrefixingVariant(propId, val.release(), important);
2366             return true;
2367         }
2368         return false;
2369     }
2370
2371     case CSSPropertyJustifySelf:
2372         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2373             return false;
2374
2375         return parseItemPositionOverflowPosition(propId, important);
2376     case CSSPropertyGridAutoColumns:
2377     case CSSPropertyGridAutoRows:
2378         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2379             return false;
2380         parsedValue = parseGridTrackSize(*m_valueList);
2381         break;
2382
2383     case CSSPropertyGridTemplateColumns:
2384     case CSSPropertyGridTemplateRows:
2385         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2386             return false;
2387         return parseGridTrackList(propId, important);
2388
2389     case CSSPropertyGridColumnEnd:
2390     case CSSPropertyGridColumnStart:
2391     case CSSPropertyGridRowEnd:
2392     case CSSPropertyGridRowStart:
2393         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2394             return false;
2395         parsedValue = parseGridPosition();
2396         break;
2397
2398     case CSSPropertyGridColumn:
2399     case CSSPropertyGridRow:
2400         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2401             return false;
2402         return parseGridItemPositionShorthand(propId, important);
2403
2404     case CSSPropertyGridArea:
2405         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2406             return false;
2407         return parseGridAreaShorthand(important);
2408
2409     case CSSPropertyGridTemplateAreas:
2410         if (!RuntimeEnabledFeatures::cssGridLayoutEnabled())
2411             return false;
2412         parsedValue = parseGridTemplateAreas();
2413         break;
2414
2415     case CSSPropertyWebkitMarginCollapse: {
2416         if (num == 1) {
2417             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2418             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important))
2419                 return false;
2420             CSSValue* value = m_parsedProperties.last().value();
2421             addProperty(webkitMarginCollapseShorthand().properties()[1], value, important);
2422             return true;
2423         }
2424         else if (num == 2) {
2425             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2426             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important))
2427                 return false;
2428             return true;
2429         }
2430         return false;
2431     }
2432     case CSSPropertyTextLineThroughWidth:
2433     case CSSPropertyTextOverlineWidth:
2434     case CSSPropertyTextUnderlineWidth:
2435         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2436             id == CSSValueMedium || id == CSSValueThick)
2437             validPrimitive = true;
2438         else
2439             validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent);
2440         break;
2441     case CSSPropertyWebkitColumnCount:
2442         parsedValue = parseColumnCount();
2443         break;
2444     case CSSPropertyWebkitColumnGap:         // normal | <length>
2445         if (id == CSSValueNormal)
2446             validPrimitive = true;
2447         else
2448             validPrimitive = validUnit(value, FLength | FNonNeg);
2449         break;
2450     case CSSPropertyWebkitColumnAxis:
2451         if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2452             validPrimitive = true;
2453         break;
2454     case CSSPropertyWebkitColumnProgression:
2455         if (id == CSSValueNormal || id == CSSValueReverse)
2456             validPrimitive = true;
2457         break;
2458     case CSSPropertyWebkitColumnSpan: // none | all | 1 (will be dropped in the unprefixed property)
2459         if (id == CSSValueAll || id == CSSValueNone)
2460             validPrimitive = true;
2461         else
2462             validPrimitive = validUnit(value, FNumber | FNonNeg) && value->fValue == 1;
2463         break;
2464     case CSSPropertyWebkitColumnWidth:         // auto | <length>
2465         parsedValue = parseColumnWidth();
2466         break;
2467     // End of CSS3 properties
2468
2469     // Apple specific properties.  These will never be standardized and are purely to
2470     // support custom WebKit-based Apple applications.
2471     case CSSPropertyWebkitLineClamp:
2472         // When specifying number of lines, don't allow 0 as a valid value
2473         // When specifying either type of unit, require non-negative integers
2474         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, HTMLQuirksMode));
2475         break;
2476
2477     case CSSPropertyWebkitFontSizeDelta:           // <length>
2478         validPrimitive = validUnit(value, FLength);
2479         break;
2480
2481     case CSSPropertyWebkitHighlight:
2482         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
2483             validPrimitive = true;
2484         break;
2485
2486     case CSSPropertyWebkitHyphenateCharacter:
2487         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2488             validPrimitive = true;
2489         break;
2490
2491     case CSSPropertyWebkitLocale:
2492         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2493             validPrimitive = true;
2494         break;
2495
2496     // End Apple-specific properties
2497
2498     case CSSPropertyWebkitAppRegion:
2499         if (id >= CSSValueDrag && id <= CSSValueNoDrag)
2500             validPrimitive = true;
2501         break;
2502
2503     case CSSPropertyWebkitTapHighlightColor:
2504         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
2505             || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2506             validPrimitive = true;
2507         } else {
2508             parsedValue = parseColor();
2509             if (parsedValue)
2510                 m_valueList->next();
2511         }
2512         break;
2513
2514         /* shorthand properties */
2515     case CSSPropertyBackground: {
2516         // Position must come before color in this array because a plain old "0" is a legal color
2517         // in quirks mode but it's usually the X coordinate of a position.
2518         const CSSPropertyID properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2519                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2520                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor, CSSPropertyBackgroundSize };
2521         return parseFillShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2522     }
2523     case CSSPropertyWebkitMask: {
2524         const CSSPropertyID properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
2525             CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip, CSSPropertyWebkitMaskSize };
2526         return parseFillShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2527     }
2528     case CSSPropertyBorder:
2529         // [ 'border-width' || 'border-style' || <color> ] | inherit
2530     {
2531         if (parseShorthand(propId, parsingShorthandForProperty(CSSPropertyBorder), important)) {
2532             // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2533             // though a value of none was specified for the image.
2534             addExpandedPropertyForValue(CSSPropertyBorderImage, cssValuePool().createImplicitInitialValue(), important);
2535             return true;
2536         }
2537         return false;
2538     }
2539     case CSSPropertyBorderTop:
2540         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2541         return parseShorthand(propId, borderTopShorthand(), important);
2542     case CSSPropertyBorderRight:
2543         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2544         return parseShorthand(propId, borderRightShorthand(), important);
2545     case CSSPropertyBorderBottom:
2546         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2547         return parseShorthand(propId, borderBottomShorthand(), important);
2548     case CSSPropertyBorderLeft:
2549         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2550         return parseShorthand(propId, borderLeftShorthand(), important);
2551     case CSSPropertyWebkitBorderStart:
2552         return parseShorthand(propId, webkitBorderStartShorthand(), important);
2553     case CSSPropertyWebkitBorderEnd:
2554         return parseShorthand(propId, webkitBorderEndShorthand(), important);
2555     case CSSPropertyWebkitBorderBefore:
2556         return parseShorthand(propId, webkitBorderBeforeShorthand(), important);
2557     case CSSPropertyWebkitBorderAfter:
2558         return parseShorthand(propId, webkitBorderAfterShorthand(), important);
2559     case CSSPropertyOutline:
2560         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2561         return parseShorthand(propId, outlineShorthand(), important);
2562     case CSSPropertyBorderColor:
2563         // <color>{1,4} | inherit
2564         return parse4Values(propId, borderColorShorthand().properties(), important);
2565     case CSSPropertyBorderWidth:
2566         // <border-width>{1,4} | inherit
2567         return parse4Values(propId, borderWidthShorthand().properties(), important);
2568     case CSSPropertyBorderStyle:
2569         // <border-style>{1,4} | inherit
2570         return parse4Values(propId, borderStyleShorthand().properties(), important);
2571     case CSSPropertyMargin:
2572         // <margin-width>{1,4} | inherit
2573         return parse4Values(propId, marginShorthand().properties(), important);
2574     case CSSPropertyPadding:
2575         // <padding-width>{1,4} | inherit
2576         return parse4Values(propId, paddingShorthand().properties(), important);
2577     case CSSPropertyFlexFlow:
2578         return parseShorthand(propId, flexFlowShorthand(), important);
2579     case CSSPropertyFont:
2580         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2581         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2582         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
2583             validPrimitive = true;
2584         else
2585             return parseFont(important);
2586         break;
2587     case CSSPropertyListStyle:
2588         return parseShorthand(propId, listStyleShorthand(), important);
2589     case CSSPropertyWebkitColumns:
2590         return parseColumnsShorthand(important);
2591     case CSSPropertyWebkitColumnRule:
2592         return parseShorthand(propId, webkitColumnRuleShorthand(), important);
2593     case CSSPropertyWebkitTextStroke:
2594         return parseShorthand(propId, webkitTextStrokeShorthand(), important);
2595     case CSSPropertyAnimation:
2596         if (!RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled())
2597             break;
2598     case CSSPropertyWebkitAnimation:
2599         return parseAnimationShorthand(propId, important);
2600     case CSSPropertyTransition:
2601     case CSSPropertyWebkitTransition:
2602         return parseTransitionShorthand(propId, important);
2603     case CSSPropertyInvalid:
2604         return false;
2605     case CSSPropertyPage:
2606         return parsePage(propId, important);
2607     case CSSPropertyFontStretch:
2608         return false;
2609     // CSS Text Layout Module Level 3: Vertical writing support
2610     case CSSPropertyWebkitTextEmphasis:
2611         return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
2612
2613     case CSSPropertyWebkitTextEmphasisStyle:
2614         return parseTextEmphasisStyle(important);
2615
2616     case CSSPropertyWebkitTextOrientation:
2617         // FIXME: For now just support sideways, sideways-right, upright and vertical-right.
2618         if (id == CSSValueSideways || id == CSSValueSidewaysRight || id == CSSValueVerticalRight || id == CSSValueUpright)
2619             validPrimitive = true;
2620         break;
2621
2622     case CSSPropertyWebkitLineBoxContain:
2623         if (id == CSSValueNone)
2624             validPrimitive = true;
2625         else
2626             return parseLineBoxContain(important);
2627         break;
2628     case CSSPropertyWebkitFontFeatureSettings:
2629         if (id == CSSValueNormal)
2630             validPrimitive = true;
2631         else
2632             return parseFontFeatureSettings(important);
2633         break;
2634
2635     case CSSPropertyFontVariantLigatures:
2636         if (id == CSSValueNormal)
2637             validPrimitive = true;
2638         else
2639             return parseFontVariantLigatures(important);
2640         break;
2641     case CSSPropertyWebkitClipPath:
2642         if (id == CSSValueNone) {
2643             validPrimitive = true;
2644         } else if (value->unit == CSSParserValue::Function) {
2645             parsedValue = parseBasicShape();
2646         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
2647             parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI);
2648             addProperty(propId, parsedValue.release(), important);
2649             return true;
2650         }
2651         break;
2652     case CSSPropertyShapeInside:
2653     case CSSPropertyShapeOutside:
2654         parsedValue = parseShapeProperty(propId);
2655         break;
2656     case CSSPropertyShapeMargin:
2657     case CSSPropertyShapePadding:
2658         validPrimitive = (RuntimeEnabledFeatures::cssShapesEnabled() && !id && validUnit(value, FLength | FNonNeg));
2659         break;
2660     case CSSPropertyShapeImageThreshold:
2661         validPrimitive = (RuntimeEnabledFeatures::cssShapesEnabled() && !id && validUnit(value, FNumber));
2662         break;
2663
2664     case CSSPropertyTouchAction:
2665         // auto | none | [pan-x || pan-y]
2666         return parseTouchAction(important);
2667
2668     case CSSPropertyAlignSelf:
2669         ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
2670         return parseItemPositionOverflowPosition(propId, important);
2671
2672     case CSSPropertyAlignItems:
2673         ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
2674         return parseItemPositionOverflowPosition(propId, important);
2675
2676     case CSSPropertyBorderBottomStyle:
2677     case CSSPropertyBorderCollapse:
2678     case CSSPropertyBorderLeftStyle:
2679     case CSSPropertyBorderRightStyle:
2680     case CSSPropertyBorderTopStyle:
2681     case CSSPropertyBoxSizing:
2682     case CSSPropertyCaptionSide:
2683     case CSSPropertyClear:
2684     case CSSPropertyDirection:
2685     case CSSPropertyDisplay:
2686     case CSSPropertyEmptyCells:
2687     case CSSPropertyFloat:
2688     case CSSPropertyFontStyle:
2689     case CSSPropertyImageRendering:
2690     case CSSPropertyListStylePosition:
2691     case CSSPropertyListStyleType:
2692     case CSSPropertyObjectFit:
2693     case CSSPropertyOutlineStyle:
2694     case CSSPropertyOverflowWrap:
2695     case CSSPropertyOverflowX:
2696     case CSSPropertyOverflowY:
2697     case CSSPropertyPageBreakAfter:
2698     case CSSPropertyPageBreakBefore:
2699     case CSSPropertyPageBreakInside:
2700     case CSSPropertyPointerEvents:
2701     case CSSPropertyPosition:
2702     case CSSPropertyResize:
2703     case CSSPropertySpeak:
2704     case CSSPropertyTableLayout:
2705     case CSSPropertyTextAlignLast:
2706     case CSSPropertyTextJustify:
2707     case CSSPropertyTextLineThroughMode:
2708     case CSSPropertyTextLineThroughStyle:
2709     case CSSPropertyTextOverflow:
2710     case CSSPropertyTextOverlineMode:
2711     case CSSPropertyTextOverlineStyle:
2712     case CSSPropertyTextRendering:
2713     case CSSPropertyTextTransform:
2714     case CSSPropertyTextUnderlineMode:
2715     case CSSPropertyTextUnderlineStyle:
2716     case CSSPropertyTouchActionDelay:
2717     case CSSPropertyVisibility:
2718     case CSSPropertyWebkitAppearance:
2719     case CSSPropertyWebkitBackfaceVisibility:
2720     case CSSPropertyWebkitBorderAfterStyle:
2721     case CSSPropertyWebkitBorderBeforeStyle:
2722     case CSSPropertyWebkitBorderEndStyle:
2723     case CSSPropertyWebkitBorderFit:
2724     case CSSPropertyWebkitBorderStartStyle:
2725     case CSSPropertyWebkitBoxAlign:
2726     case CSSPropertyWebkitBoxDecorationBreak:
2727     case CSSPropertyWebkitBoxDirection:
2728     case CSSPropertyWebkitBoxLines:
2729     case CSSPropertyWebkitBoxOrient:
2730     case CSSPropertyWebkitBoxPack:
2731     case CSSPropertyInternalCallback:
2732     case CSSPropertyWebkitColumnBreakAfter:
2733     case CSSPropertyWebkitColumnBreakBefore:
2734     case CSSPropertyWebkitColumnBreakInside:
2735     case CSSPropertyColumnFill:
2736     case CSSPropertyWebkitColumnRuleStyle:
2737     case CSSPropertyAlignContent:
2738     case CSSPropertyFlexDirection:
2739     case CSSPropertyFlexWrap:
2740     case CSSPropertyJustifyContent:
2741     case CSSPropertyFontKerning:
2742     case CSSPropertyWebkitFontSmoothing:
2743     case CSSPropertyGridAutoFlow:
2744     case CSSPropertyWebkitLineBreak:
2745     case CSSPropertyWebkitMarginAfterCollapse:
2746     case CSSPropertyWebkitMarginBeforeCollapse:
2747     case CSSPropertyWebkitMarginBottomCollapse:
2748     case CSSPropertyWebkitMarginTopCollapse:
2749     case CSSPropertyInternalMarqueeDirection:
2750     case CSSPropertyInternalMarqueeStyle:
2751     case CSSPropertyWebkitPrintColorAdjust:
2752     case CSSPropertyWebkitRtlOrdering:
2753     case CSSPropertyWebkitRubyPosition:
2754     case CSSPropertyWebkitTextCombine:
2755     case CSSPropertyWebkitTextEmphasisPosition:
2756     case CSSPropertyWebkitTextSecurity:
2757     case CSSPropertyWebkitTransformStyle:
2758     case CSSPropertyWebkitUserDrag:
2759     case CSSPropertyWebkitUserModify:
2760     case CSSPropertyWebkitUserSelect:
2761     case CSSPropertyWebkitWrapFlow:
2762     case CSSPropertyWebkitWrapThrough:
2763     case CSSPropertyWebkitWritingMode:
2764     case CSSPropertyWhiteSpace:
2765     case CSSPropertyWordBreak:
2766     case CSSPropertyWordWrap:
2767     case CSSPropertyMixBlendMode:
2768     case CSSPropertyIsolation:
2769         // These properties should be handled before in isValidKeywordPropertyAndValue().
2770         ASSERT_NOT_REACHED();
2771         return false;
2772     // Properties below are validated inside parseViewportProperty, because we
2773     // check for parser state. We need to invalidate if someone adds them outside
2774     // a @viewport rule.
2775     case CSSPropertyMaxZoom:
2776     case CSSPropertyMinZoom:
2777     case CSSPropertyOrientation:
2778     case CSSPropertyUserZoom:
2779         validPrimitive = false;
2780         break;
2781     default:
2782         return parseSVGValue(propId, important);
2783     }
2784
2785     if (validPrimitive) {
2786         parsedValue = parseValidPrimitive(id, value);
2787         m_valueList->next();
2788     }
2789     ASSERT(!m_parsedCalculation);
2790     if (parsedValue) {
2791         if (!m_valueList->current() || inShorthand()) {
2792             addProperty(propId, parsedValue.release(), important);
2793             return true;
2794         }
2795     }
2796     return false;
2797 }
2798
2799 void BisonCSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2800 {
2801     if (lval) {
2802         if (lval->isBaseValueList())
2803             toCSSValueList(lval.get())->append(rval);
2804         else {
2805             PassRefPtr<CSSValue> oldlVal(lval.release());
2806             PassRefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2807             list->append(oldlVal);
2808             list->append(rval);
2809             lval = list;
2810         }
2811     }
2812     else
2813         lval = rval;
2814 }
2815
2816 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue)
2817 {
2818     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2819         || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2820         cssValue = cssValuePool().createIdentifierValue(parserValue->id);
2821         return true;
2822     }
2823     return false;
2824 }
2825
2826 bool BisonCSSParser::useLegacyBackgroundSizeShorthandBehavior() const
2827 {
2828     return m_context.useLegacyBackgroundSizeShorthandBehavior();
2829 }
2830
2831 const int cMaxFillProperties = 9;
2832
2833 bool BisonCSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important)
2834 {
2835     ASSERT(numProperties <= cMaxFillProperties);
2836     if (numProperties > cMaxFillProperties)
2837         return false;
2838
2839     ShorthandScope scope(this, propId);
2840
2841     bool parsedProperty[cMaxFillProperties] = { false };
2842     RefPtr<CSSValue> values[cMaxFillProperties];
2843     RefPtr<CSSValue> clipValue;
2844     RefPtr<CSSValue> positionYValue;
2845     RefPtr<CSSValue> repeatYValue;
2846     bool foundClip = false;
2847     int i;
2848     bool foundPositionCSSProperty = false;
2849
2850     while (m_valueList->current()) {
2851         CSSParserValue* val = m_valueList->current();
2852         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2853             // We hit the end.  Fill in all remaining values with the initial value.
2854             m_valueList->next();
2855             for (i = 0; i < numProperties; ++i) {
2856                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2857                     // Color is not allowed except as the last item in a list for backgrounds.
2858                     // Reject the entire property.
2859                     return false;
2860
2861                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2862                     addFillValue(values[i], cssValuePool().createImplicitInitialValue());
2863                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2864                         addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
2865                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2866                         addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
2867                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2868                         // If background-origin wasn't present, then reset background-clip also.
2869                         addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
2870                     }
2871                 }
2872                 parsedProperty[i] = false;
2873             }
2874             if (!m_valueList->current())
2875                 break;
2876         }
2877
2878         bool sizeCSSPropertyExpected = false;
2879         if (isForwardSlashOperator(val) && foundPositionCSSProperty) {
2880             sizeCSSPropertyExpected = true;
2881             m_valueList->next();
2882         }
2883
2884         foundPositionCSSProperty = false;
2885         bool found = false;
2886         for (i = 0; !found && i < numProperties; ++i) {
2887
2888             if (sizeCSSPropertyExpected && (properties[i] != CSSPropertyBackgroundSize && properties[i] != CSSPropertyWebkitMaskSize))
2889                 continue;
2890             if (!sizeCSSPropertyExpected && (properties[i] == CSSPropertyBackgroundSize || properties[i] == CSSPropertyWebkitMaskSize))
2891                 continue;
2892
2893             if (!parsedProperty[i]) {
2894                 RefPtr<CSSValue> val1;
2895                 RefPtr<CSSValue> val2;
2896                 CSSPropertyID propId1, propId2;
2897                 CSSParserValue* parserValue = m_valueList->current();
2898                 // parseFillProperty() may modify m_implicitShorthand, so we MUST reset it
2899                 // before EACH return below.
2900                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2901                     parsedProperty[i] = found = true;
2902                     addFillValue(values[i], val1.release());
2903                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2904                         addFillValue(positionYValue, val2.release());
2905                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2906                         addFillValue(repeatYValue, val2.release());
2907                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2908                         // Reparse the value as a clip, and see if we succeed.
2909                         if (parseBackgroundClip(parserValue, val1))
2910                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
2911                         else
2912                             addFillValue(clipValue, cssValuePool().createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2913                     }
2914                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2915                         // Update clipValue
2916                         addFillValue(clipValue, val1.release());
2917                         foundClip = true;
2918                     }
2919                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2920                         foundPositionCSSProperty = true;
2921                 }
2922             }
2923         }
2924
2925         // if we didn't find at least one match, this is an
2926         // invalid shorthand and we have to ignore it
2927         if (!found) {
2928             m_implicitShorthand = false;
2929             return false;
2930         }
2931     }
2932
2933     // Now add all of the properties we found.
2934     for (i = 0; i < numProperties; i++) {
2935         // Fill in any remaining properties with the initial value.
2936         if (!parsedProperty[i]) {
2937             addFillValue(values[i], cssValuePool().createImplicitInitialValue());
2938             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2939                 addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
2940             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2941                 addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
2942             if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2943                 // If background-origin wasn't present, then reset background-clip also.
2944                 addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
2945             }
2946         }
2947         if (properties[i] == CSSPropertyBackgroundPosition) {
2948             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2949             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2950             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2951         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2952             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2953             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2954             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2955         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2956             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2957             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2958             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2959         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2960             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2961             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2962             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2963         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2964             // Value is already set while updating origin
2965             continue;
2966         else if (properties[i] == CSSPropertyBackgroundSize && !parsedProperty[i] && useLegacyBackgroundSizeShorthandBehavior())
2967             continue;
2968         else
2969             addProperty(properties[i], values[i].release(), important);
2970
2971         // Add in clip values when we hit the corresponding origin property.
2972         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2973             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2974         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2975             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2976     }
2977
2978     m_implicitShorthand = false;
2979     return true;
2980 }
2981
2982 void BisonCSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2983 {
2984     if (lval) {
2985         if (lval->isValueList())
2986             toCSSValueList(lval.get())->append(rval);
2987         else {
2988             PassRefPtr<CSSValue> oldVal(lval.release());
2989             PassRefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2990             list->append(oldVal);
2991             list->append(rval);
2992             lval = list;
2993         }
2994     }
2995     else
2996         lval = rval;
2997 }
2998
2999 bool BisonCSSParser::parseAnimationShorthand(CSSPropertyID propId, bool important)
3000 {
3001     const StylePropertyShorthand& animationProperties = parsingShorthandForProperty(propId);
3002     const unsigned numProperties = 8;
3003
3004     // The list of properties in the shorthand should be the same
3005     // length as the list with animation name in last position, even though they are
3006     // in a different order.
3007     ASSERT(numProperties == animationProperties.length());
3008     ASSERT(numProperties == shorthandForProperty(propId).length());
3009
3010     ShorthandScope scope(this, propId);
3011
3012     bool parsedProperty[numProperties] = { false };
3013     AnimationParseContext context;
3014     RefPtr<CSSValue> values[numProperties];
3015
3016     unsigned i;
3017     while (m_valueList->current()) {
3018         CSSParserValue* val = m_valueList->current();
3019         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3020             // We hit the end.  Fill in all remaining values with the initial value.
3021             m_valueList->next();
3022             for (i = 0; i < numProperties; ++i) {
3023                 if (!parsedProperty[i])
3024                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3025                 parsedProperty[i] = false;
3026             }
3027             if (!m_valueList->current())
3028                 break;
3029             context.commitFirstAnimation();
3030         }
3031
3032         bool found = false;
3033         for (i = 0; i < numProperties; ++i) {
3034             if (!parsedProperty[i]) {
3035                 RefPtr<CSSValue> val;
3036                 if (parseAnimationProperty(animationProperties.properties()[i], val, context)) {
3037                     parsedProperty[i] = found = true;
3038                     addAnimationValue(values[i], val.release());
3039                     break;
3040                 }
3041             }
3042         }
3043
3044         // if we didn't find at least one match, this is an
3045         // invalid shorthand and we have to ignore it
3046         if (!found)
3047             return false;
3048     }
3049
3050     for (i = 0; i < numProperties; ++i) {
3051         // If we didn't find the property, set an intial value.
3052         if (!parsedProperty[i])
3053             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3054
3055         addProperty(animationProperties.properties()[i], values[i].release(), important);
3056     }
3057
3058     return true;
3059 }
3060
3061 bool BisonCSSParser::parseTransitionShorthand(CSSPropertyID propId, bool important)
3062 {
3063     const unsigned numProperties = 4;
3064     const StylePropertyShorthand& shorthand = shorthandForProperty(propId);
3065     ASSERT(numProperties == shorthand.length());
3066
3067     ShorthandScope scope(this, propId);
3068
3069     bool parsedProperty[numProperties] = { false };
3070     AnimationParseContext context;
3071     RefPtr<CSSValue> values[numProperties];
3072
3073     unsigned i;
3074     while (m_valueList->current()) {
3075         CSSParserValue* val = m_valueList->current();
3076         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3077             // We hit the end. Fill in all remaining values with the initial value.
3078             m_valueList->next();
3079             for (i = 0; i < numProperties; ++i) {
3080                 if (!parsedProperty[i])
3081                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3082                 parsedProperty[i] = false;
3083             }
3084             if (!m_valueList->current())
3085                 break;
3086             context.commitFirstAnimation();
3087         }
3088
3089         bool found = false;
3090         for (i = 0; !found && i < numProperties; ++i) {
3091             if (!parsedProperty[i]) {
3092                 RefPtr<CSSValue> val;
3093                 if (parseAnimationProperty(shorthand.properties()[i], val, context)) {
3094                     parsedProperty[i] = found = true;
3095                     addAnimationValue(values[i], val.release());
3096                 }
3097
3098                 // There are more values to process but 'none' or 'all' were already defined as the animation property, the declaration becomes invalid.
3099                 if (!context.animationPropertyKeywordAllowed() && context.hasCommittedFirstAnimation())
3100                     return false;
3101             }
3102         }
3103
3104         // if we didn't find at least one match, this is an
3105         // invalid shorthand and we have to ignore it
3106         if (!found)
3107             return false;
3108     }
3109
3110     // Fill in any remaining properties with the initial value.
3111     for (i = 0; i < numProperties; ++i) {
3112         if (!parsedProperty[i])
3113             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3114     }
3115
3116     // Now add all of the properties we found.
3117     for (i = 0; i < numProperties; i++)
3118         addPropertyWithPrefixingVariant(shorthand.properties()[i], values[i].release(), important);
3119
3120     return true;
3121 }
3122
3123 PassRefPtr<CSSValue> BisonCSSParser::parseColumnWidth()
3124 {
3125     CSSParserValue* value = m_valueList->current();
3126     // Always parse lengths in strict mode here, since it would be ambiguous otherwise when used in
3127     // the 'columns' shorthand property.
3128     if (value->id == CSSValueAuto
3129         || (validUnit(value, FLength | FNonNeg, HTMLStandardMode) && value->fValue)) {
3130         RefPtr<CSSValue> parsedValue = parseValidPrimitive(value->id, value);
3131         m_valueList->next();
3132         return parsedValue;
3133     }
3134     return 0;
3135 }
3136
3137 PassRefPtr<CSSValue> BisonCSSParser::parseColumnCount()
3138 {
3139     CSSParserValue* value = m_valueList->current();
3140     if (value->id == CSSValueAuto
3141         || (!value->id && validUnit(value, FPositiveInteger, HTMLQuirksMode))) {
3142         RefPtr<CSSValue> parsedValue = parseValidPrimitive(value->id, value);
3143         m_valueList->next();
3144         return parsedValue;
3145     }
3146     return 0;
3147 }
3148
3149 bool BisonCSSParser::parseColumnsShorthand(bool important)
3150 {
3151     RefPtr <CSSValue> columnWidth;
3152     RefPtr <CSSValue> columnCount;
3153     bool hasPendingExplicitAuto = false;
3154
3155     for (unsigned propertiesParsed = 0; CSSParserValue* value = m_valueList->current(); propertiesParsed++) {
3156         if (propertiesParsed >= 2)
3157             return false; // Too many values for this shorthand. Invalid declaration.
3158         if (!propertiesParsed && value->id == CSSValueAuto) {
3159             // 'auto' is a valid value for any of the two longhands, and at this point we
3160             // don't know which one(s) it is meant for. We need to see if there are other
3161             // values first.
3162             m_valueList->next();
3163             hasPendingExplicitAuto = true;
3164         } else {
3165             if (!columnWidth) {
3166                 if ((columnWidth = parseColumnWidth()))
3167                     continue;
3168             }
3169             if (!columnCount) {
3170                 if ((columnCount = parseColumnCount()))
3171                     continue;
3172             }
3173             // If we didn't find at least one match, this is an
3174             // invalid shorthand and we have to ignore it.
3175             return false;
3176         }
3177     }
3178     if (hasPendingExplicitAuto) {
3179         // Time to assign the previously skipped 'auto' value to a property. If both properties are
3180         // unassigned at this point (i.e. 'columns:auto'), it doesn't matter that much which one we
3181         // set (although it does make a slight difference to web-inspector). The one we don't set
3182         // here will get an implicit 'auto' value further down.
3183         if (!columnWidth) {
3184             columnWidth = cssValuePool().createIdentifierValue(CSSValueAuto);
3185         } else {
3186             ASSERT(!columnCount);
3187             columnCount = cssValuePool().createIdentifierValue(CSSValueAuto);
3188         }
3189     }
3190     ASSERT(columnCount || columnWidth);
3191
3192     // Any unassigned property at this point will become implicit 'auto'.
3193     if (columnWidth)
3194         addProperty(CSSPropertyWebkitColumnWidth, columnWidth, important);
3195     else
3196         addProperty(CSSPropertyWebkitColumnWidth, cssValuePool().createIdentifierValue(CSSValueAuto), important, true /* implicit */);
3197     if (columnCount)
3198         addProperty(CSSPropertyWebkitColumnCount, columnCount, important);
3199     else
3200         addProperty(CSSPropertyWebkitColumnCount, cssValuePool().createIdentifierValue(CSSValueAuto), important, true /* implicit */);
3201     return true;
3202 }
3203
3204 bool BisonCSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important)
3205 {
3206     // We try to match as many properties as possible
3207     // We set up an array of booleans to mark which property has been found,
3208     // and we try to search for properties until it makes no longer any sense.
3209     ShorthandScope scope(this, propId);
3210
3211     bool found = false;
3212     unsigned propertiesParsed = 0;
3213     bool propertyFound[6] = { false, false, false, false, false, false }; // 6 is enough size.
3214
3215     while (m_valueList->current()) {
3216         found = false;
3217         for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) {
3218             if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) {
3219                 propertyFound[propIndex] = found = true;
3220                 propertiesParsed++;
3221             }
3222         }
3223
3224         // if we didn't find at least one match, this is an
3225         // invalid shorthand and we have to ignore it
3226         if (!found)
3227             return false;
3228     }
3229
3230     if (propertiesParsed == shorthand.length())
3231         return true;
3232
3233     // Fill in any remaining properties with the initial value.
3234     ImplicitScope implicitScope(this, PropertyImplicit);
3235     const StylePropertyShorthand* const* const propertiesForInitialization = shorthand.propertiesForInitialization();
3236     for (unsigned i = 0; i < shorthand.length(); ++i) {
3237         if (propertyFound[i])
3238             continue;
3239
3240         if (propertiesForInitialization) {
3241             const StylePropertyShorthand& initProperties = *(propertiesForInitialization[i]);
3242             for (unsigned propIndex = 0; propIndex < initProperties.length(); ++propIndex)
3243                 addProperty(initProperties.properties()[propIndex], cssValuePool().createImplicitInitialValue(), important);
3244         } else
3245             addProperty(shorthand.properties()[i], cssValuePool().createImplicitInitialValue(), important);
3246     }
3247
3248     return true;
3249 }
3250
3251 bool BisonCSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties,  bool important)
3252 {
3253     /* From the CSS 2 specs, 8.3
3254      * If there is only one value, it applies to all sides. If there are two values, the top and
3255      * bottom margins are set to the first value and the right and left margins are set to the second.
3256      * If there are three values, the top is set to the first value, the left and right are set to the
3257      * second, and the bottom is set to the third. If there are four values, they apply to the top,
3258      * right, bottom, and left, respectively.
3259      */
3260
3261     int num = inShorthand() ? 1 : m_valueList->size();
3262
3263     ShorthandScope scope(this, propId);
3264
3265     // the order is top, right, bottom, left
3266     switch (num) {
3267         case 1: {
3268             if (!parseValue(properties[0], important))
3269                 return false;
3270             CSSValue* value = m_parsedProperties.last().value();
3271             ImplicitScope implicitScope(this, PropertyImplicit);
3272             addProperty(properties[1], value, important);
3273             addProperty(properties[2], value, important);
3274             addProperty(properties[3], value, important);
3275             break;
3276         }
3277         case 2: {
3278             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
3279                 return false;
3280             CSSValue* value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3281             ImplicitScope implicitScope(this, PropertyImplicit);
3282             addProperty(properties[2], value, important);
3283             value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3284             addProperty(properties[3], value, important);
3285             break;
3286         }
3287         case 3: {
3288             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
3289                 return false;
3290             CSSValue* value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3291             ImplicitScope implicitScope(this, PropertyImplicit);
3292             addProperty(properties[3], value, important);
3293             break;
3294         }
3295         case 4: {
3296             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
3297                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
3298                 return false;
3299             break;
3300         }
3301         default: {
3302             return false;
3303         }
3304     }
3305
3306     return true;
3307 }
3308
3309 // auto | <identifier>
3310 bool BisonCSSParser::parsePage(CSSPropertyID propId, bool important)
3311 {
3312     ASSERT(propId == CSSPropertyPage);
3313
3314     if (m_valueList->size() != 1)
3315         return false;
3316
3317     CSSParserValue* value = m_valueList->current();
3318     if (!value)
3319         return false;
3320
3321     if (value->id == CSSValueAuto) {
3322         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
3323         return true;
3324     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
3325         addProperty(propId, createPrimitiveStringValue(value), important);
3326         return true;
3327     }
3328     return false;
3329 }
3330
3331 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
3332 bool BisonCSSParser::parseSize(CSSPropertyID propId, bool important)
3333 {
3334     ASSERT(propId == CSSPropertySize);
3335
3336     if (m_valueList->size() > 2)
3337         return false;
3338
3339     CSSParserValue* value = m_valueList->current();
3340     if (!value)
3341         return false;
3342
3343     RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
3344
3345     // First parameter.
3346     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
3347     if (paramType == None)
3348         return false;
3349
3350     // Second parameter, if any.
3351     value = m_valueList->next();
3352     if (value) {
3353         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
3354         if (paramType == None)
3355             return false;
3356     }
3357
3358     addProperty(propId, parsedValues.release(), important);
3359     return true;
3360 }
3361
3362 BisonCSSParser::SizeParameterType BisonCSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
3363 {
3364     switch (value->id) {
3365     case CSSValueAuto:
3366         if (prevParamType == None) {
3367             parsedValues->append(cssValuePool().createIdentifierValue(value->id));
3368             return Auto;
3369         }
3370         return None;
3371     case CSSValueLandscape:
3372     case CSSValuePortrait:
3373         if (prevParamType == None || prevParamType == PageSize) {
3374             parsedValues->append(cssValuePool().createIdentifierValue(value->id));
3375             return Orientation;
3376         }
3377         return None;
3378     case CSSValueA3:
3379     case CSSValueA4:
3380     case CSSValueA5:
3381     case CSSValueB4:
3382     case CSSValueB5:
3383     case CSSValueLedger:
3384     case CSSValueLegal:
3385     case CSSValueLetter:
3386         if (prevParamType == None || prevParamType == Orientation) {
3387             // Normalize to Page Size then Orientation order by prepending.
3388             // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (StyleResolver::applyPageSizeProperty).
3389             parsedValues->prepend(cssValuePool().createIdentifierValue(value->id));
3390             return PageSize;
3391         }
3392         return None;
3393     case 0:
3394         if (validUnit(value, FLength | FNonNeg) && (prevParamType == None || prevParamType == Length)) {
3395             parsedValues->append(createPrimitiveNumericValue(value));
3396             return Length;
3397         }
3398         return None;
3399     default:
3400         return None;
3401     }
3402 }
3403
3404 // [ <string> <string> ]+ | inherit | none
3405 // inherit and none are handled in parseValue.
3406 bool BisonCSSParser::parseQuotes(CSSPropertyID propId, bool important)
3407 {
3408     RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3409     while (CSSParserValue* val = m_valueList->current()) {
3410         RefPtr<CSSValue> parsedValue;
3411         if (val->unit == CSSPrimitiveValue::CSS_STRING)
3412             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3413         else
3414             break;
3415         values->append(parsedValue.release());
3416         m_valueList->next();
3417     }
3418     if (values->length()) {
3419         addProperty(propId, values.release(), important);
3420         m_valueList->next();
3421         return true;
3422     }
3423     return false;
3424 }
3425
3426 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3427 // in CSS 2.1 this got somewhat reduced:
3428 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3429 bool BisonCSSParser::parseContent(CSSPropertyID propId, bool important)
3430 {
3431     RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3432
3433     while (CSSParserValue* val = m_valueList->current()) {
3434         RefPtr<CSSValue> parsedValue;
3435         if (val->unit == CSSPrimitiveValue::CSS_URI) {
3436             // url
3437             parsedValue = CSSImageValue::create(completeURL(val->string));
3438         } else if (val->unit == CSSParserValue::Function) {
3439             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
3440             CSSParserValueList* args = val->function->args.get();
3441             if (!args)
3442                 return false;
3443             if (equalIgnoringCase(val->function->name, "attr(")) {
3444                 parsedValue = parseAttr(args);
3445                 if (!parsedValue)
3446                     return false;
3447             } else if (equalIgnoringCase(val->function->name, "counter(")) {
3448                 parsedValue = parseCounterContent(args, false);
3449                 if (!parsedValue)
3450                     return false;
3451             } else if (equalIgnoringCase(val->function->name, "counters(")) {
3452                 parsedValue = parseCounterContent(args, true);
3453                 if (!parsedValue)
3454                     return false;
3455             } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
3456                 parsedValue = parseImageSet(m_valueList.get());
3457                 if (!parsedValue)
3458                     return false;
3459             } else if (isGeneratedImageValue(val)) {
3460                 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
3461                     return false;
3462             } else
3463                 return false;
3464         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3465             // open-quote
3466             // close-quote
3467             // no-open-quote
3468             // no-close-quote
3469             // inherit
3470             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
3471             // none
3472             // normal
3473             switch (val->id) {
3474             case CSSValueOpenQuote:
3475             case CSSValueCloseQuote:
3476             case CSSValueNoOpenQuote:
3477             case CSSValueNoCloseQuote:
3478             case CSSValueNone:
3479             case CSSValueNormal:
3480                 parsedValue = cssValuePool().createIdentifierValue(val->id);
3481             default:
3482                 break;
3483             }
3484         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
3485             parsedValue = createPrimitiveStringValue(val);
3486         }
3487         if (!parsedValue)
3488             break;
3489         values->append(parsedValue.release());
3490         m_valueList->next();
3491     }
3492
3493     if (values->length()) {
3494         addProperty(propId, values.release(), important);
3495         m_valueList->next();
3496         return true;
3497     }
3498
3499     return false;
3500 }
3501
3502 PassRefPtr<CSSValue> BisonCSSParser::parseAttr(CSSParserValueList* args)
3503 {
3504     if (args->size() != 1)
3505         return 0;
3506
3507     CSSParserValue* a = args->current();
3508
3509     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
3510         return 0;
3511
3512     String attrName = a->string;
3513     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
3514     // But HTML attribute names can't have those characters, and we should not
3515     // even parse them inside attr().
3516     if (attrName[0] == '-')
3517         return 0;
3518
3519     if (m_context.isHTMLDocument())
3520         attrName = attrName.lower();
3521
3522     return cssValuePool().createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
3523 }
3524
3525 PassRefPtr<CSSValue> BisonCSSParser::parseBackgroundColor()
3526 {
3527     CSSValueID id = m_valueList->current()->id;
3528     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
3529         (id >= CSSValueGrey && id < CSSValueWebkitText && inQuirksMode()))
3530         return cssValuePool().createIdentifierValue(id);
3531     return parseColor();
3532 }
3533
3534 bool BisonCSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
3535 {
3536     if (valueList->current()->id == CSSValueNone) {
3537         value = cssValuePool().createIdentifierValue(CSSValueNone);
3538         return true;
3539     }
3540     if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
3541         value = CSSImageValue::create(completeURL(valueList->current()->string));
3542         return true;
3543     }
3544
3545     if (isGeneratedImageValue(valueList->current()))
3546         return parseGeneratedImage(valueList, value);
3547
3548     if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
3549         value = parseImageSet(m_valueList.get());
3550         if (value)
3551             return true;
3552     }
3553
3554     return false;
3555 }
3556
3557 PassRefPtr<CSSValue> BisonCSSParser::parseFillPositionX(CSSParserValueList* valueList)
3558 {
3559     int id = valueList->current()->id;
3560     if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
3561         int percent = 0;
3562         if (id == CSSValueRight)
3563             percent = 100;
3564         else if (id == CSSValueCenter)
3565             percent = 50;
3566         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3567     }
3568     if (validUnit(valueList->current(), FPercent | FLength))
3569         return createPrimitiveNumericValue(valueList->current());
3570     return 0;
3571 }
3572
3573 PassRefPtr<CSSValue> BisonCSSParser::parseFillPositionY(CSSParserValueList* valueList)
3574 {
3575     int id = valueList->current()->id;
3576     if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
3577         int percent = 0;
3578         if (id == CSSValueBottom)
3579             percent = 100;
3580         else if (id == CSSValueCenter)
3581             percent = 50;
3582         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3583     }
3584     if (validUnit(valueList->current(), FPercent | FLength))
3585         return createPrimitiveNumericValue(valueList->current());
3586     return 0;
3587 }
3588
3589 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag, FillPositionParsingMode parsingMode)
3590 {
3591     CSSValueID id = valueList->current()->id;
3592     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
3593         int percent = 0;
3594         if (id == CSSValueLeft || id == CSSValueRight) {
3595             if (cumulativeFlags & XFillPosition)
3596                 return 0;
3597             cumulativeFlags |= XFillPosition;
3598             individualFlag = XFillPosition;
3599             if (id == CSSValueRight)
3600                 percent = 100;
3601         }
3602         else if (id == CSSValueTop || id == CSSValueBottom) {
3603             if (cumulativeFlags & YFillPosition)
3604                 return 0;
3605             cumulativeFlags |= YFillPosition;
3606             individualFlag = YFillPosition;
3607             if (id == CSSValueBottom)
3608                 percent = 100;
3609         } else if (id == CSSValueCenter) {
3610             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
3611             percent = 50;
3612             cumulativeFlags |= AmbiguousFillPosition;
3613             individualFlag = AmbiguousFillPosition;
3614         }
3615
3616         if (parsingMode == ResolveValuesAsKeyword)
3617             return cssValuePool().createIdentifierValue(id);
3618
3619         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3620     }
3621     if (validUnit(valueList->current(), FPercent | FLength)) {
3622         if (!cumulativeFlags) {
3623             cumulativeFlags |= XFillPosition;
3624             individualFlag = XFillPosition;
3625         } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
3626             cumulativeFlags |= YFillPosition;
3627             individualFlag = YFillPosition;
3628         } else {
3629             if (m_parsedCalculation)
3630                 m_parsedCalculation.release();
3631             return 0;
3632         }
3633         return createPrimitiveNumericValue(valueList->current());
3634     }
3635     return 0;
3636 }
3637
3638 static bool isValueConflictingWithCurrentEdge(int value1, int value2)
3639 {
3640     if ((value1 == CSSValueLeft || value1 == CSSValueRight) && (value2 == CSSValueLeft || value2 == CSSValueRight))
3641         return true;
3642
3643     if ((value1 == CSSValueTop || value1 == CSSValueBottom) && (value2 == CSSValueTop || value2 == CSSValueBottom))
3644         return true;
3645
3646     return false;
3647 }
3648
3649 static bool isFillPositionKeyword(CSSValueID value)
3650 {
3651     return value == CSSValueLeft || value == CSSValueTop || value == CSSValueBottom || value == CSSValueRight || value == CSSValueCenter;
3652 }
3653
3654 void BisonCSSParser::parse4ValuesFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2)
3655 {
3656     // [ left | right ] [ <percentage] | <length> ] && [ top | bottom ] [ <percentage> | <length> ]
3657     // In the case of 4 values <position> requires the second value to be a length or a percentage.
3658     if (isFillPositionKeyword(parsedValue2->getValueID()))
3659         return;
3660
3661     unsigned cumulativeFlags = 0;
3662     FillPositionFlag value3Flag = InvalidFillPosition;
3663     RefPtrWillBeRawPtr<CSSPrimitiveValue> value3 = parseFillPositionComponent(valueList, cumulativeFlags, value3Flag, ResolveValuesAsKeyword);
3664     if (!value3)
3665         return;
3666
3667     CSSValueID ident1 = parsedValue1->getValueID();
3668     CSSValueID ident3 = value3->getValueID();
3669
3670     if (ident1 == CSSValueCenter)
3671         return;
3672
3673     if (!isFillPositionKeyword(ident3) || ident3 == CSSValueCenter)
3674         return;
3675
3676     // We need to check if the values are not conflicting, e.g. they are not on the same edge. It is
3677     // needed as the second call to parseFillPositionComponent was on purpose not checking it. In the
3678     // case of two values top 20px is invalid but in the case of 4 values it becomes valid.
3679     if (isValueConflictingWithCurrentEdge(ident1, ident3))
3680         return;
3681
3682     valueList->next();
3683
3684     cumulativeFlags = 0;
3685     FillPositionFlag value4Flag = InvalidFillPosition;
3686     RefPtrWillBeRawPtr<CSSPrimitiveValue> value4 = parseFillPositionComponent(valueList, cumulativeFlags, value4Flag, ResolveValuesAsKeyword);
3687     if (!value4)
3688         return;
3689
3690     // 4th value must be a length or a percentage.
3691     if (isFillPositionKeyword(value4->getValueID()))
3692         return;
3693
3694     value1 = createPrimitiveValuePair(parsedValue1, parsedValue2);
3695     value2 = createPrimitiveValuePair(value3, value4);
3696
3697     if (ident1 == CSSValueTop || ident1 == CSSValueBottom)
3698         value1.swap(value2);
3699
3700     valueList->next();
3701 }
3702 void BisonCSSParser::parse3ValuesFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2)
3703 {
3704     unsigned cumulativeFlags = 0;
3705     FillPositionFlag value3Flag = InvalidFillPosition;
3706     RefPtrWillBeRawPtr<CSSPrimitiveValue> value3 = parseFillPositionComponent(valueList, cumulativeFlags, value3Flag, ResolveValuesAsKeyword);
3707
3708     // value3 is not an expected value, we return.
3709     if (!value3)
3710         return;
3711
3712     valueList->next();
3713
3714     bool swapNeeded = false;
3715     CSSValueID ident1 = parsedValue1->getValueID();
3716     CSSValueID ident2 = parsedValue2->getValueID();
3717     CSSValueID ident3 = value3->getValueID();
3718
3719     CSSValueID firstPositionKeyword;
3720     CSSValueID secondPositionKeyword;
3721
3722     if (ident1 == CSSValueCenter) {
3723         // <position> requires the first 'center' to be followed by a keyword.
3724         if (!isFillPositionKeyword(ident2))
3725             return;
3726
3727         // If 'center' is the first keyword then the last one needs to be a length.
3728         if (isFillPositionKeyword(ident3))
3729             return;
3730
3731         firstPositionKeyword = CSSValueLeft;
3732         if (ident2 == CSSValueLeft || ident2 == CSSValueRight) {
3733             firstPositionKeyword = CSSValueTop;
3734             swapNeeded = true;
3735         }
3736         value1 = createPrimitiveValuePair(cssValuePool().createIdentifierValue(firstPositionKeyword), cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE));
3737         value2 = createPrimitiveValuePair(parsedValue2, value3);
3738     } else if (ident3 == CSSValueCenter) {
3739         if (isFillPositionKeyword(ident2))
3740             return;
3741
3742         secondPositionKeyword = CSSValueTop;
3743         if (ident1 == CSSValueTop || ident1 == CSSValueBottom) {
3744             secondPositionKeyword = CSSValueLeft;
3745             swapNeeded = true;
3746         }
3747         value1 = createPrimitiveValuePair(parsedValue1, parsedValue2);
3748         value2 = createPrimitiveValuePair(cssValuePool().createIdentifierValue(secondPositionKeyword), cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE));
3749     } else {
3750         RefPtrWillBeRawPtr<CSSPrimitiveValue> firstPositionValue;
3751         RefPtrWillBeRawPtr<CSSPrimitiveValue> secondPositionValue;
3752
3753         if (isFillPositionKeyword(ident2)) {
3754             // To match CSS grammar, we should only accept: [ center | left | right | bottom | top ] [ left | right | top | bottom ] [ <percentage> | <length> ].
3755             ASSERT(ident2 != CSSValueCenter);
3756
3757             if (isFillPositionKeyword(ident3))
3758                 return;
3759
3760             secondPositionValue = value3;
3761             secondPositionKeyword = ident2;
3762             firstPositionValue = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PERCENTAGE);
3763         } else {
3764             // Per CSS, we should only accept: [ right | left | top | bottom ] [ <percentage> | <length> ] [ center | left | right | bottom | top ].
3765             if (!isFillPositionKeyword(ident3))
3766                 return;
3767
3768             firstPositionValue = parsedValue2;
3769             secondPositionKeyword = ident3;
3770             secondPositionValue = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PERCENTAGE);
3771         }
3772
3773         if (isValueConflictingWithCurrentEdge(ident1, secondPositionKeyword))
3774             return;
3775
3776         value1 = createPrimitiveValuePair(parsedValue1, firstPositionValue);
3777         value2 = createPrimitiveValuePair(cssValuePool().createIdentifierValue(secondPositionKeyword), secondPositionValue);
3778     }
3779
3780     if (ident1 == CSSValueTop || ident1 == CSSValueBottom || swapNeeded)
3781         value1.swap(value2);
3782
3783 #ifndef NDEBUG
3784     CSSPrimitiveValue* first = toCSSPrimitiveValue(value1.get());
3785     CSSPrimitiveValue* second = toCSSPrimitiveValue(value2.get());
3786     ident1 = first->getPairValue()->first()->getValueID();
3787     ident2 = second->getPairValue()->first()->getValueID();
3788     ASSERT(ident1 == CSSValueLeft || ident1 == CSSValueRight);
3789     ASSERT(ident2 == CSSValueBottom || ident2 == CSSValueTop);
3790 #endif
3791 }
3792
3793 inline bool BisonCSSParser::isPotentialPositionValue(CSSParserValue* value)
3794 {
3795     return isFillPositionKeyword(value->id) || validUnit(value, FPercent | FLength, ReleaseParsedCalcValue);
3796 }
3797
3798 void BisonCSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3799 {
3800     unsigned numberOfValues = 0;
3801     for (unsigned i = valueList->currentIndex(); i < valueList->size(); ++i, ++numberOfValues) {
3802         CSSParserValue* current = valueList->valueAt(i);
3803         if (isComma(current) || !current || isForwardSlashOperator(current) || !isPotentialPositionValue(current))
3804             break;
3805     }
3806
3807     if (numberOfValues > 4)
3808         return;
3809
3810     // If we are parsing two values, we can safely call the CSS 2.1 parsing function and return.
3811     if (numberOfValues <= 2) {
3812         parse2ValuesFillPosition(valueList, value1, value2);
3813         return;
3814     }
3815
3816     ASSERT(numberOfValues > 2 && numberOfValues <= 4);
3817
3818     CSSParserValue* value = valueList->current();
3819
3820     // <position> requires the first value to be a background keyword.
3821     if (!isFillPositionKeyword(value->id))
3822         return;
3823
3824     // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
3825     unsigned cumulativeFlags = 0;
3826     FillPositionFlag value1Flag = InvalidFillPosition;
3827     FillPositionFlag value2Flag = InvalidFillPosition;
3828     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag, ResolveValuesAsKeyword);
3829     if (!value1)
3830         return;
3831
3832     valueList->next();
3833
3834     // In case we are parsing more than two values, relax the check inside of parseFillPositionComponent. top 20px is
3835     // a valid start for <position>.
3836     cumulativeFlags = AmbiguousFillPosition;
3837     value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag, ResolveValuesAsKeyword);
3838     if (value2)
3839         valueList->next();
3840     else {
3841         value1.clear();
3842         return;
3843     }
3844
3845     RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1 = toCSSPrimitiveValue(value1.get());
3846     RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2 = toCSSPrimitiveValue(value2.get());
3847
3848     value1.clear();
3849     value2.clear();
3850
3851     // Per CSS3 syntax, <position> can't have 'center' as its second keyword as we have more arguments to follow.
3852     if (parsedValue2->getValueID() == CSSValueCenter)
3853         return;
3854
3855     if (numberOfValues == 3)
3856         parse3ValuesFillPosition(valueList, value1, value2, parsedValue1.release(), parsedValue2.release());
3857     else
3858         parse4ValuesFillPosition(valueList, value1, value2, parsedValue1.release(), parsedValue2.release());
3859 }
3860
3861 void BisonCSSParser::parse2ValuesFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3862 {
3863     CSSParserValue* value = valueList->current();
3864
3865     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
3866     unsigned cumulativeFlags = 0;
3867     FillPositionFlag value1Flag = InvalidFillPosition;
3868     FillPositionFlag value2Flag = InvalidFillPosition;
3869     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
3870     if (!value1)
3871         return;
3872
3873     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
3874     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
3875     // value was explicitly specified for our property.
3876     value = valueList->next();
3877
3878     // First check for the comma.  If so, we are finished parsing this value or value pair.
3879     if (isComma(value))
3880         value = 0;
3881
3882     if (value) {
3883         value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
3884         if (value2)
3885             valueList->next();
3886         else {
3887             if (!inShorthand()) {
3888                 value1.clear();
3889                 return;
3890             }
3891         }
3892     }
3893
3894     if (!value2)
3895         // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
3896         // is simply 50%. This is our default.
3897         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
3898         // For left/right/center, the default of 50% in the y is still correct.
3899         value2 = cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
3900
3901     if (value1Flag == YFillPosition || value2Flag == XFillPosition)
3902         value1.swap(value2);
3903 }
3904
3905 void BisonCSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3906 {
3907     CSSValueID id = m_valueList->current()->id;
3908     if (id == CSSValueRepeatX) {
3909         m_implicitShorthand = true;
3910         value1 = cssValuePool().createIdentifierValue(CSSValueRepeat);
3911         value2 = cssValuePool().createIdentifierValue(CSSValueNoRepeat);
3912         m_valueList->next();
3913         return;
3914     }
3915     if (id == CSSValueRepeatY) {
3916         m_implicitShorthand = true;
3917         value1 = cssValuePool().createIdentifierValue(CSSValueNoRepeat);
3918         value2 = cssValuePool().createIdentifierValue(CSSValueRepeat);
3919         m_valueList->next();
3920         return;
3921     }
3922     if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
3923         value1 = cssValuePool().createIdentifierValue(id);
3924     else {
3925         value1 = 0;
3926         return;
3927     }
3928
3929     CSSParserValue* value = m_valueList->next();
3930
3931     // Parse the second value if one is available
3932     if (value && !isComma(value)) {
3933         id = value->id;
3934         if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace) {
3935             value2 = cssValuePool().createIdentifierValue(id);
3936             m_valueList->next();
3937             return;
3938         }
3939     }
3940
3941     // If only one value was specified, value2 is the same as value1.
3942     m_implicitShorthand = true;
3943     value2 = cssValuePool().createIdentifierValue(toCSSPrimitiveValue(value1.get())->getValueID());
3944 }
3945
3946 PassRefPtr<CSSValue> BisonCSSParser::parseFillSize(CSSPropertyID propId, bool& allowComma)
3947 {
3948     allowComma = true;
3949     CSSParserValue* value = m_valueList->current();
3950
3951     if (value->id == CSSValueContain || value->id == CSSValueCover)
3952         return cssValuePool().createIdentifierValue(value->id);
3953
3954     RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1;
3955
3956     if (value->id == CSSValueAuto)
3957         parsedValue1 = cssValuePool().createIdentifierValue(CSSValueAuto);
3958     else {
3959         if (!validUnit(value, FLength | FPercent))
3960             return 0;
3961         parsedValue1 = createPrimitiveNumericValue(value);
3962     }
3963
3964     RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2;
3965     if ((value = m_valueList->next())) {
3966         if (value->unit == CSSParserValue::Operator && value->iValue == ',')
3967             allowComma = false;
3968         else if (value->id != CSSValueAuto) {
3969             if (!validUnit(value, FLength | FPercent)) {
3970                 if (!inShorthand())
3971                     return 0;
3972                 // We need to rewind the value list, so that when it is advanced we'll end up back at this value.
3973                 m_valueList->previous();
3974             } else
3975                 parsedValue2 = createPrimitiveNumericValue(value);
3976         }
3977     } else if (!parsedValue2 && propId == CSSPropertyWebkitBackgroundSize) {
3978         // For backwards compatibility we set the second value to the first if it is omitted.
3979         // We only need to do this for -webkit-background-size. It should be safe to let masks match
3980         // the real property.
3981         parsedValue2 = parsedValue1;
3982     }
3983
3984     if (!parsedValue2)
3985         return parsedValue1;
3986     return createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release());
3987 }
3988
3989 bool BisonCSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2,
3990                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
3991 {
3992     RefPtrWillBeRawPtr<CSSValueList> values;
3993     RefPtrWillBeRawPtr<CSSValueList> values2;
3994     CSSParserValue* val;
3995     RefPtr<CSSValue> value;
3996     RefPtr<CSSValue> value2;
3997
3998     bool allowComma = false;
3999
4000     retValue1 = retValue2 = 0;
4001     propId1 = propId;
4002     propId2 = propId;
4003     if (propId == CSSPropertyBackgroundPosition) {
4004         propId1 = CSSPropertyBackgroundPositionX;
4005         propId2 = CSSPropertyBackgroundPositionY;
4006     } else if (propId == CSSPropertyWebkitMaskPosition) {
4007         propId1 = CSSPropertyWebkitMaskPositionX;
4008         propId2 = CSSPropertyWebkitMaskPositionY;
4009     } else if (propId == CSSPropertyBackgroundRepeat) {
4010         propId1 = CSSPropertyBackgroundRepeatX;
4011         propId2 = CSSPropertyBackgroundRepeatY;
4012     } else if (propId == CSSPropertyWebkitMaskRepeat) {
4013         propId1 = CSSPropertyWebkitMaskRepeatX;
4014         propId2 = CSSPropertyWebkitMaskRepeatY;
4015     }
4016
4017     while ((val = m_valueList->current())) {
4018         RefPtr<CSSValue> currValue;
4019         RefPtr<CSSValue> currValue2;
4020
4021         if (allowComma) {
4022             if (!isComma(val))
4023                 return false;
4024             m_valueList->next();
4025             allowComma = false;
4026         } else {
4027             allowComma = true;
4028             switch (propId) {
4029                 case CSSPropertyBackgroundColor:
4030                     currValue = parseBackgroundColor();
4031                     if (currValue)
4032                         m_valueList->next();
4033                     break;
4034                 case CSSPropertyBackgroundAttachment:
4035                     if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
4036                         currValue = cssValuePool().createIdentifierValue(val->id);
4037                         m_valueList->next();
4038                     }
4039                     break;
4040                 case CSSPropertyBackgroundImage:
4041                 case CSSPropertyWebkitMaskImage:
4042                     if (parseFillImage(m_valueList.get(), currValue))
4043                         m_valueList->next();
4044                     break;
4045                 case CSSPropertyWebkitBackgroundClip:
4046                 case CSSPropertyWebkitBackgroundOrigin:
4047                 case CSSPropertyWebkitMaskClip:
4048                 case CSSPropertyWebkitMaskOrigin:
4049                     // The first three values here are deprecated and do not apply to the version of the property that has
4050                     // the -webkit- prefix removed.
4051                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
4052                         val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
4053                         ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
4054                          (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
4055                         currValue = cssValuePool().createIdentifierValue(val->id);
4056                         m_valueList->next();
4057                     }
4058                     break;
4059                 case CSSPropertyBackgroundClip:
4060                     if (parseBackgroundClip(val, currValue))
4061                         m_valueList->next();
4062                     break;
4063                 case CSSPropertyBackgroundOrigin:
4064                     if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
4065                         currValue = cssValuePool().createIdentifierValue(val->id);
4066                         m_valueList->next();
4067                     }
4068                     break;
4069                 case CSSPropertyBackgroundPosition:
4070                 case CSSPropertyWebkitMaskPosition:
4071                     parseFillPosition(m_valueList.get(), currValue, currValue2);
4072                     // parseFillPosition advances the m_valueList pointer.
4073                     break;
4074                 case CSSPropertyBackgroundPositionX:
4075                 case CSSPropertyWebkitMaskPositionX: {
4076                     currValue = parseFillPositionX(m_valueList.get());
4077                     if (currValue)
4078                         m_valueList->next();
4079                     break;
4080                 }
4081                 case CSSPropertyBackgroundPositionY:
4082                 case CSSPropertyWebkitMaskPositionY: {
4083                     currValue = parseFillPositionY(m_valueList.get());
4084                     if (currValue)
4085                         m_valueList->next();
4086                     break;
4087                 }
4088                 case CSSPropertyWebkitBackgroundComposite:
4089                 case CSSPropertyWebkitMaskComposite:
4090                     if (val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) {
4091                         currValue = cssValuePool().createIdentifierValue(val->id);
4092                         m_valueList->next();
4093                     }
4094                     break;
4095                 case CSSPropertyBackgroundBlendMode:
4096                     if (RuntimeEnabledFeatures::cssCompositingEnabled() && (val->id == CSSValueNormal || val->id == CSSValueMultiply
4097                         || val->id == CSSValueScreen || val->id == CSSValueOverlay || val->id == CSSValueDarken
4098                         || val->id == CSSValueLighten ||  val->id == CSSValueColorDodge || val->id == CSSValueColorBurn
4099                         || val->id == CSSValueHardLight || val->id == CSSValueSoftLight || val->id == CSSValueDifference
4100                         || val->id == CSSValueExclusion || val->id == CSSValueHue || val->id == CSSValueSaturation
4101                         || val->id == CSSValueColor || val->id == CSSValueLuminosity)) {
4102                         currValue = cssValuePool().createIdentifierValue(val->id);
4103                         m_valueList->next();
4104                     }
4105                     break;
4106                 case CSSPropertyBackgroundRepeat:
4107                 case CSSPropertyWebkitMaskRepeat:
4108                     parseFillRepeat(currValue, currValue2);
4109                     // parseFillRepeat advances the m_valueList pointer
4110                     break;
4111                 case CSSPropertyBackgroundSize:
4112                 case CSSPropertyWebkitBackgroundSize:
4113                 case CSSPropertyWebkitMaskSize: {
4114                     currValue = parseFillSize(propId, allowComma);
4115                     if (currValue)
4116                         m_valueList->next();
4117                     break;
4118                 }
4119                 case CSSPropertyMaskSourceType: {
4120                     if (RuntimeEnabledFeatures::cssMaskSourceTypeEnabled()) {
4121                         if (val->id == CSSValueAuto || val->id == CSSValueAlpha || val->id == CSSValueLuminance) {
4122                             currValue = cssValuePool().createIdentifierValue(val->id);
4123                             m_valueList->next();
4124                         } else {
4125                             currValue = 0;
4126                         }
4127                     }
4128                     break;
4129                 }
4130                 default:
4131                     break;
4132             }
4133             if (!currValue)
4134                 return false;
4135
4136             if (value && !values) {
4137                 values = CSSValueList::createCommaSeparated();
4138                 values->append(value.release());
4139             }
4140
4141             if (value2 && !values2) {
4142                 values2 = CSSValueList::createCommaSeparated();
4143                 values2->append(value2.release());
4144             }
4145
4146             if (values)
4147                 values->append(currValue.release());
4148             else
4149                 value = currValue.release();
4150             if (currValue2) {
4151                 if (values2)
4152                     values2->append(currValue2.release());
4153                 else
4154                     value2 = currValue2.release();
4155             }
4156         }
4157
4158         // When parsing any fill shorthand property, we let it handle building up the lists for all
4159         // properties.
4160         if (inShorthand())
4161             break;
4162     }
4163
4164     if (values && values->length()) {
4165         retValue1 = values.release();
4166         if (values2 && values2->length())
4167             retValue2 = values2.release();
4168         return true;
4169     }
4170     if (value) {
4171         retValue1 = value.release();
4172         retValue2 = value2.release();
4173         return true;
4174     }
4175     return false;
4176 }
4177
4178 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationDelay()
4179 {
4180     CSSParserValue* value = m_valueList->current();
4181     if (validUnit(value, FTime))
4182         return createPrimitiveNumericValue(value);
4183     return 0;
4184 }
4185
4186 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationDirection()
4187 {
4188     CSSParserValue* value = m_valueList->current();
4189     if (value->id == CSSValueNormal || value->id == CSSValueAlternate || value->id == CSSValueReverse || value->id == CSSValueAlternateReverse)
4190         return cssValuePool().createIdentifierValue(value->id);
4191     return 0;
4192 }
4193
4194 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationDuration()
4195 {
4196     CSSParserValue* value = m_valueList->current();
4197     if (validUnit(value, FTime | FNonNeg))
4198         return createPrimitiveNumericValue(value);
4199     return 0;
4200 }
4201
4202 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationFillMode()
4203 {
4204     CSSParserValue* value = m_valueList->current();
4205     if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
4206         return cssValuePool().createIdentifierValue(value->id);
4207     return 0;
4208 }
4209
4210 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationIterationCount()
4211 {
4212     CSSParserValue* value = m_valueList->current();
4213     if (value->id == CSSValueInfinite)
4214         return cssValuePool().createIdentifierValue(value->id);
4215     if (validUnit(value, FNumber | FNonNeg))
4216         return createPrimitiveNumericValue(value);
4217     return 0;
4218 }
4219
4220 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationName()
4221 {
4222     CSSParserValue* value = m_valueList->current();
4223     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
4224         if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value, "none"))) {
4225             return cssValuePool().createIdentifierValue(CSSValueNone);
4226         } else {
4227             return createPrimitiveStringValue(value);
4228         }
4229     }
4230     return 0;
4231 }
4232
4233 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationPlayState()
4234 {
4235     CSSParserValue* value = m_valueList->current();
4236     if (value->id == CSSValueRunning || value->id == CSSValuePaused)
4237         return cssValuePool().createIdentifierValue(value->id);
4238     return 0;
4239 }
4240
4241 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationProperty(AnimationParseContext& context)
4242 {
4243     CSSParserValue* value = m_valueList->current();
4244     if (value->unit != CSSPrimitiveValue::CSS_IDENT)
4245         return 0;
4246     CSSPropertyID result = cssPropertyID(value->string);
4247     if (result)
4248         return cssValuePool().createIdentifierValue(result);
4249     if (equalIgnoringCase(value, "all")) {
4250         context.sawAnimationPropertyKeyword();
4251         return cssValuePool().createIdentifierValue(CSSValueAll);
4252     }
4253     if (equalIgnoringCase(value, "none")) {
4254         context.commitAnimationPropertyKeyword();
4255         context.sawAnimationPropertyKeyword();
4256         return cssValuePool().createIdentifierValue(CSSValueNone);
4257     }
4258     return 0;
4259 }
4260
4261 bool BisonCSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
4262 {
4263     parse2ValuesFillPosition(m_valueList.get(), value1, value2);
4264
4265     // now get z
4266     if (m_valueList->current()) {
4267         if (validUnit(m_valueList->current(), FLength)) {
4268             value3 = createPrimitiveNumericValue(m_valueList->current());
4269             m_valueList->next();
4270             return true;
4271         }
4272         return false;
4273     }
4274     value3 = cssValuePool().createImplicitInitialValue();
4275     return true;
4276 }
4277
4278 bool BisonCSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result)
4279 {
4280     CSSParserValue* v = args->current();
4281     if (!validUnit(v, FNumber))
4282         return false;
4283     result = v->fValue;
4284     v = args->next();
4285     if (!v)
4286         // The last number in the function has no comma after it, so we're done.
4287         return true;
4288     if (!isComma(v))
4289         return false;
4290     args->next();
4291     return true;
4292 }
4293
4294 PassRefPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunction()
4295 {
4296     CSSParserValue* value = m_valueList->current();
4297     if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut
4298         || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd)
4299         return cssValuePool().createIdentifierValue(value->id);
4300
4301     // We must be a function.
4302     if (value->unit != CSSParserValue::Function)
4303         return 0;
4304
4305     CSSParserValueList* args = value->function->args.get();
4306
4307     if (equalIgnoringCase(value->function->name, "steps(")) {
4308         // For steps, 1 or 2 params must be specified (comma-separated)
4309         if (!args || (args->size() != 1 && args->size() != 3))
4310             return 0;
4311
4312         // There are two values.
4313         int numSteps;
4314         bool stepAtStart = false;
4315
4316         CSSParserValue* v = args->current();
4317         if (!validUnit(v, FInteger))
4318             return 0;
4319         numSteps = clampToInteger(v->fValue);
4320         if (numSteps < 1)
4321             return 0;
4322         v = args->next();
4323
4324         if (v) {
4325             // There is a comma so we need to parse the second value
4326             if (!isComma(v))
4327                 return 0;
4328             v = args->next();
4329             if (v->id != CSSValueStart && v->id != CSSValueEnd)
4330                 return 0;
4331             stepAtStart = v->id == CSSValueStart;
4332         }
4333
4334         return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart);
4335     }
4336
4337     if (equalIgnoringCase(value->function->name, "cubic-bezier(")) {
4338         // For cubic bezier, 4 values must be specified.
4339         if (!args || args->size() != 7)
4340             return 0;
4341
4342         // There are two points specified. The x values must be between 0 and 1 but the y values can exceed this range.
4343         double x1, y1, x2, y2;
4344
4345         if (!parseCubicBezierTimingFunctionValue(args, x1))
4346             return 0;
4347         if (x1 < 0 || x1 > 1)
4348             return 0;
4349         if (!parseCubicBezierTimingFunctionValue(args, y1))
4350             return 0;
4351         if (!parseCubicBezierTimingFunctionValue(args, x2))
4352             return 0;
4353         if (x2 < 0 || x2 > 1)
4354             return 0;
4355         if (!parseCubicBezierTimingFunctionValue(args, y2))
4356             return 0;
4357
4358         return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2);
4359     }
4360
4361     return 0;
4362 }
4363
4364 bool BisonCSSParser::parseAnimationProperty(CSSPropertyID propId, RefPtr<CSSValue>& result, AnimationParseContext& context)
4365 {
4366     RefPtrWillBeRawPtr<CSSValueList> values;
4367     CSSParserValue* val;
4368     RefPtr<CSSValue> value;
4369     bool allowComma = false;
4370
4371     result = 0;
4372
4373     while ((val = m_valueList->current())) {
4374         RefPtr<CSSValue> currValue;
4375         if (allowComma) {
4376             if (!isComma(val))
4377                 return false;
4378             m_valueList->next();
4379             allowComma = false;
4380         }
4381         else {
4382             switch (propId) {
4383                 case CSSPropertyAnimationDelay:
4384                 case CSSPropertyWebkitAnimationDelay:
4385                 case CSSPropertyTransitionDelay:
4386                 case CSSPropertyWebkitTransitionDelay:
4387                     currValue = parseAnimationDelay();
4388                     if (currValue)
4389                         m_valueList->next();
4390                     break;
4391                 case CSSPropertyAnimationDirection:
4392                 case CSSPropertyWebkitAnimationDirection:
4393                     currValue = parseAnimationDirection();
4394                     if (currValue)
4395                         m_valueList->next();
4396                     break;
4397                 case CSSPropertyAnimationDuration:
4398                 case CSSPropertyWebkitAnimationDuration:
4399                 case CSSPropertyTransitionDuration:
4400                 case CSSPropertyWebkitTransitionDuration:
4401                     currValue = parseAnimationDuration();
4402                     if (currValue)
4403                         m_valueList->next();
4404                     break;
4405                 case CSSPropertyAnimationFillMode:
4406                 case CSSPropertyWebkitAnimationFillMode:
4407                     currValue = parseAnimationFillMode();
4408                     if (currValue)
4409                         m_valueList->next();
4410                     break;
4411                 case CSSPropertyAnimationIterationCount:
4412                 case CSSPropertyWebkitAnimationIterationCount:
4413                     currValue = parseAnimationIterationCount();
4414                     if (currValue)
4415                         m_valueList->next();
4416                     break;
4417                 case CSSPropertyAnimationName:
4418                 case CSSPropertyWebkitAnimationName:
4419                     currValue = parseAnimationName();
4420                     if (currValue)
4421                         m_valueList->next();
4422                     break;
4423                 case CSSPropertyAnimationPlayState:
4424                 case CSSPropertyWebkitAnimationPlayState:
4425                     currValue = parseAnimationPlayState();
4426                     if (currValue)
4427                         m_valueList->next();
4428                     break;
4429                 case CSSPropertyTransitionProperty:
4430                 case CSSPropertyWebkitTransitionProperty:
4431                     currValue = parseAnimationProperty(context);
4432                     if (value && !context.animationPropertyKeywordAllowed())
4433                         return false;
4434                     if (currValue)
4435                         m_valueList->next();
4436                     break;
4437                 case CSSPropertyAnimationTimingFunction:
4438                 case CSSPropertyWebkitAnimationTimingFunction:
4439                 case CSSPropertyTransitionTimingFunction:
4440                 case CSSPropertyWebkitTransitionTimingFunction:
4441                     currValue = parseAnimationTimingFunction();
4442                     if (currValue)
4443                         m_valueList->next();
4444                     break;
4445                 default:
4446                     ASSERT_NOT_REACHED();
4447                     return false;
4448             }
4449
4450             if (!currValue)
4451                 return false;
4452
4453             if (value && !values) {
4454                 values = CSSValueList::createCommaSeparated();
4455                 values->append(value.release());
4456             }
4457
4458             if (values)
4459                 values->append(currValue.release());
4460             else
4461                 value = currValue.release();
4462
4463             allowComma = true;
4464         }
4465
4466         // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
4467         // properties.
4468         if (inShorthand())
4469             break;
4470     }
4471
4472     if (values && values->length()) {
4473         result = values.release();
4474         return true;
4475     }
4476     if (value) {
4477         result = value.release();
4478         return true;
4479     }
4480     return false;
4481 }
4482
4483 // The function parses [ <integer> || <string> ] in <grid-line> (which can be stand alone or with 'span').
4484 bool BisonCSSParser::parseIntegerOrStringFromGridPosition(RefPtrWillBeRawPtr<CSSPrimitiveValue>& numericValue, RefPtrWillBeRawPtr<CSSPrimitiveValue>& gridLineName)
4485 {
4486     CSSParserValue* value = m_valueList->current();
4487     if (validUnit(value, FInteger) && value->fValue) {
4488         numericValue = createPrimitiveNumericValue(value);
4489         value = m_valueList->next();
4490         if (value && value->unit == CSSPrimitiveValue::CSS_STRING) {
4491             gridLineName = createPrimitiveStringValue(m_valueList->current());
4492             m_valueList->next();
4493         }
4494         return true;
4495     }
4496
4497     if (value->unit == CSSPrimitiveValue::CSS_STRING) {
4498         gridLineName = createPrimitiveStringValue(m_valueList->current());
4499         value = m_valueList->next();
4500         if (value && validUnit(value, FInteger) && value->fValue) {
4501             numericValue = createPrimitiveNumericValue(value);
4502             m_valueList->next();
4503         }
4504         return true;
4505     }
4506
4507     return false;
4508 }
4509
4510 PassRefPtr<CSSValue> BisonCSSParser::parseGridPosition()
4511 {
4512     ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
4513
4514     CSSParserValue* value = m_valueList->current();
4515     if (value->id == CSSValueAuto) {
4516         m_valueList->next();
4517         return cssValuePool().createIdentifierValue(CSSValueAuto);
4518     }
4519
4520     if (value->id != CSSValueSpan && value->unit == CSSPrimitiveValue::CSS_IDENT) {
4521         m_valueList->next();
4522         return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING);
4523     }
4524
4525     RefPtrWillBeRawPtr<CSSPrimitiveValue> numericValue;
4526     RefPtrWillBeRawPtr<CSSPrimitiveValue> gridLineName;
4527     bool hasSeenSpanKeyword = false;
4528
4529     if (parseIntegerOrStringFromGridPosition(numericValue, gridLineName)) {
4530         value = m_valueList->current();
4531         if (value && value->id == CSSValueSpan) {
4532             hasSeenSpanKeyword = true;
4533             m_valueList->next();
4534         }
4535     } else if (value->id == CSSValueSpan) {
4536         hasSeenSpanKeyword = true;
4537         if (m_valueList->next())
4538             parseIntegerOrStringFromGridPosition(numericValue, gridLineName);
4539     }
4540
4541     // Check that we have consumed all the value list. For shorthands, the parser will pass
4542     // the whole value list (including the opposite position).
4543     if (m_valueList->current() && !isForwardSlashOperator(m_valueList->current()))
4544         return 0;
4545
4546     // If we didn't parse anything, this is not a valid grid position.
4547     if (!hasSeenSpanKeyword && !gridLineName && !numericValue)
4548         return 0;
4549
4550     // Negative numbers are not allowed for span (but are for <integer>).
4551     if (hasSeenSpanKeyword && numericValue && numericValue->getIntValue() < 0)
4552         return 0;
4553
4554     RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
4555     if (hasSeenSpanKeyword)
4556         values->append(cssValuePool().createIdentifierValue(CSSValueSpan));
4557     if (numericValue)
4558         values->append(numericValue.release());
4559     if (gridLineName)
4560         values->append(gridLineName.release());
4561     ASSERT(values->length());
4562     return values.release();
4563 }
4564
4565 static PassRefPtr<CSSValue> gridMissingGridPositionValue(CSSValue* value)
4566 {
4567     if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->isString())
4568         return value;
4569
4570     return cssValuePool().createIdentifierValue(CSSValueAuto);
4571 }
4572
4573 bool BisonCSSParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool important)
4574 {
4575     ShorthandScope scope(this, shorthandId);
4576     const StylePropertyShorthand& shorthand = shorthandForProperty(shorthandId);
4577     ASSERT(shorthand.length() == 2);
4578
4579     RefPtr<CSSValue> startValue = parseGridPosition();
4580     if (!startValue)
4581         return false;
4582
4583     RefPtr<CSSValue> endValue;
4584     if (m_valueList->current()) {
4585         if (!isForwardSlashOperator(m_valueList->current()))
4586             return false;
4587
4588         if (!m_valueList->next())
4589             return false;
4590
4591         endValue = parseGridPosition();
4592         if (!endValue || m_valueList->current())
4593             return false;
4594     } else {
4595         endValue = gridMissingGridPositionValue(startValue.get());
4596     }
4597
4598     addProperty(shorthand.properties()[0], startValue, important);
4599     addProperty(shorthand.properties()[1], endValue, important);
4600     return true;
4601 }
4602
4603 bool BisonCSSParser::parseGridAreaShorthand(bool important)
4604 {
4605     ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
4606
4607     ShorthandScope scope(this, CSSPropertyGridArea);
4608     const StylePropertyShorthand& shorthand = gridAreaShorthand();
4609     ASSERT_UNUSED(shorthand, shorthand.length() == 4);
4610
4611     RefPtr<CSSValue> rowStartValue = parseGridPosition();
4612     if (!rowStartValue)
4613         return false;
4614
4615     RefPtr<CSSValue> columnStartValue;
4616     if (!parseSingleGridAreaLonghand(columnStartValue))
4617         return false;
4618
4619     RefPtr<CSSValue> rowEndValue;
4620     if (!parseSingleGridAreaLonghand(rowEndValue))
4621         return false;
4622
4623     RefPtr<CSSValue> columnEndValue;
4624     if (!parseSingleGridAreaLonghand(columnEndValue))
4625         return false;
4626
4627     if (!columnStartValue)
4628         columnStartValue = gridMissingGridPositionValue(rowStartValue.get());
4629
4630     if (!rowEndValue)
4631         rowEndValue = gridMissingGridPositionValue(rowStartValue.get());
4632
4633     if (!columnEndValue)
4634         columnEndValue = gridMissingGridPositionValue(columnStartValue.get());
4635
4636     addProperty(CSSPropertyGridRowStart, rowStartValue, important);
4637     addProperty(CSSPropertyGridColumnStart, columnStartValue, important);
4638     addProperty(CSSPropertyGridRowEnd, rowEndValue, important);
4639     addProperty(CSSPropertyGridColumnEnd, columnEndValue, important);
4640     return true;
4641 }
4642
4643 bool BisonCSSParser::parseSingleGridAreaLonghand(RefPtr<CSSValue>& property)
4644 {
4645     if (!m_valueList->current())
4646         return true;
4647
4648     if (!isForwardSlashOperator(m_valueList->current()))
4649         return false;
4650
4651     if (!m_valueList->next())
4652         return false;
4653
4654     property = parseGridPosition();
4655     return true;
4656 }
4657
4658 void BisonCSSParser::parseGridLineNames(CSSParserValueList* parserValueList, CSSValueList& valueList)
4659 {
4660     ASSERT(parserValueList->current() && parserValueList->current()->unit == CSSParserValue::ValueList);
4661
4662     CSSParserValueList* identList = parserValueList->current()->valueList;
4663     if (!identList->size()) {
4664         parserValueList->next();
4665         return;
4666     }
4667
4668     RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create();
4669     while (CSSParserValue* identValue = identList->current()) {
4670         ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT);
4671         RefPtrWillBeRawPtr<CSSPrimitiveValue> lineName = createPrimitiveStringValue(identValue);
4672         lineNames->append(lineName.release());
4673         identList->next();
4674     }
4675     valueList.append(lineNames.release());
4676
4677     parserValueList->next();
4678 }
4679
4680 bool BisonCSSParser::parseGridTrackList(CSSPropertyID propId, bool important)
4681 {
4682     ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
4683
4684     CSSParserValue* value = m_valueList->current();
4685     if (value->id == CSSValueNone) {
4686         if (m_valueList->next())
4687             return false;
4688
4689         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
4690         return true;
4691     }
4692
4693     RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
4694     // Handle leading  <ident>*.
4695     value = m_valueList->current();
4696     if (value && value->unit == CSSParserValue::ValueList)
4697         parseGridLineNames(m_valueList.get(), *values);
4698
4699     bool seenTrackSizeOrRepeatFunction = false;
4700     while (CSSParserValue* currentValue = m_valueList->current()) {
4701         if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "repeat(")) {
4702             if (!parseGridTrackRepeatFunction(*values))
4703                 return false;
4704             seenTrackSizeOrRepeatFunction = true;
4705         } else {
4706             RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList);
4707             if (!value)
4708                 return false;
4709             values->append(value);
4710             seenTrackSizeOrRepeatFunction = true;
4711         }
4712         // This will handle the trailing <ident>* in the grammar.
4713         value = m_valueList->current();
4714         if (value && value->unit == CSSParserValue::ValueList)
4715             parseGridLineNames(m_valueList.get(), *values);
4716     }
4717
4718     // We should have found a <track-size> or else it is not a valid <track-list>
4719     if (!seenTrackSizeOrRepeatFunction)
4720         return false;
4721
4722     addProperty(propId, values.release(), important);
4723     return true;
4724 }
4725
4726 bool BisonCSSParser::parseGridTrackRepeatFunction(CSSValueList& list)
4727 {
4728     CSSParserValueList* arguments = m_valueList->current()->function->args.get();
4729     if (!arguments || arguments->size() < 3 || !validUnit(arguments->valueAt(0), FPositiveInteger) || !isComma(arguments->valueAt(1)))
4730         return false;
4731
4732     ASSERT_WITH_SECURITY_IMPLICATION(arguments->valueAt(0)->fValue > 0);
4733     size_t repetitions = arguments->valueAt(0)->fValue;
4734     RefPtrWillBeRawPtr<CSSValueList> repeatedValues = CSSValueList::createSpaceSeparated();
4735     arguments->next(); // Skip the repetition count.
4736     arguments->next(); // Skip the comma.
4737
4738     // Handle leading <ident>*.
4739     CSSParserValue* currentValue = arguments->current();
4740     if (currentValue && currentValue->unit == CSSParserValue::ValueList)
4741         parseGridLineNames(arguments, *repeatedValues);
4742
4743     while (arguments->current()) {
4744         RefPtr<CSSValue> trackSize = parseGridTrackSize(*arguments);
4745         if (!trackSize)
4746             return false;
4747
4748         repeatedValues->append(trackSize);
4749
4750         // This takes care of any trailing <ident>* in the grammar.
4751         currentValue = arguments->current();
4752         if (currentValue && currentValue->unit == CSSParserValue::ValueList)
4753             parseGridLineNames(arguments, *repeatedValues);
4754     }
4755
4756     for (size_t i = 0; i < repetitions; ++i) {
4757         for (size_t j = 0; j < repeatedValues->length(); ++j)
4758             list.append(repeatedValues->itemWithoutBoundsCheck(j));
4759     }
4760
4761     // parseGridTrackSize iterated over the repeat arguments, move to the next value.
4762     m_valueList->next();
4763     return true;
4764 }
4765
4766 PassRefPtr<CSSValue> BisonCSSParser::parseGridTrackSize(CSSParserValueList& inputList)
4767 {
4768     ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
4769
4770     CSSParserValue* currentValue = inputList.current();
4771     inputList.next();
4772
4773     if (currentValue->id == CSSValueAuto)
4774         return cssValuePool().createIdentifierValue(CSSValueAuto);
4775
4776     if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "minmax(")) {
4777         // The spec defines the following grammar: minmax( <track-breadth> , <track-breadth> )
4778         CSSParserValueList* arguments = currentValue->function->args.get();
4779         if (!arguments || arguments->size() != 3 || !isComma(arguments->valueAt(1)))
4780             return 0;
4781
4782         RefPtrWillBeRawPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(arguments->valueAt(0));
4783         if (!minTrackBreadth)
4784             return 0;
4785
4786         RefPtrWillBeRawPtr<CSSPrimitiveValue> maxTrackBreadth = parseGridBreadth(arguments->valueAt(2));
4787         if (!maxTrackBreadth)
4788             return 0;
4789
4790         RefPtrWillBeRawPtr<CSSValueList> parsedArguments = CSSValueList::createCommaSeparated();
4791         parsedArguments->append(minTrackBreadth);
4792         parsedArguments->append(maxTrackBreadth);
4793         return CSSFunctionValue::create("minmax(", parsedArguments);
4794     }
4795
4796     return parseGridBreadth(currentValue);
4797 }
4798
4799 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::parseGridBreadth(CSSParserValue* currentValue)
4800 {
4801     if (currentValue->id == CSSValueMinContent || currentValue->id == CSSValueMaxContent)
4802         return cssValuePool().createIdentifierValue(currentValue->id);
4803
4804     if (currentValue->unit == CSSPrimitiveValue::CSS_FR) {
4805         double flexValue = currentValue->fValue;
4806
4807         // Fractional unit is a non-negative dimension.
4808         if (flexValue <= 0)
4809             return 0;
4810
4811         return cssValuePool().createValue(flexValue, CSSPrimitiveValue::CSS_FR);
4812     }
4813
4814     if (!validUnit(currentValue, FNonNeg | FLength | FPercent))
4815         return 0;
4816
4817     return createPrimitiveNumericValue(currentValue);
4818 }
4819
4820 PassRefPtr<CSSValue> BisonCSSParser::parseGridTemplateAreas()
4821 {
4822     NamedGridAreaMap gridAreaMap;
4823     size_t rowCount = 0;
4824     size_t columnCount = 0;
4825
4826     while (CSSParserValue* currentValue = m_valueList->current()) {
4827         if (currentValue->unit != CSSPrimitiveValue::CSS_STRING)
4828             return 0;
4829
4830         String gridRowNames = currentValue->string;
4831         if (!gridRowNames.length())
4832             return 0;
4833
4834         Vector<String> columnNames;
4835         gridRowNames.split(' ', columnNames);
4836
4837         if (!columnCount) {
4838             columnCount = columnNames.size();
4839             ASSERT(columnCount);
4840         } else if (columnCount != columnNames.size()) {
4841             // The declaration is invalid is all the rows don't have the number of columns.
4842             return 0;
4843         }
4844
4845         for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) {
4846             const String& gridAreaName = columnNames[currentCol];
4847
4848             // Unamed areas are always valid (we consider them to be 1x1).
4849             if (gridAreaName == ".")
4850                 continue;
4851
4852             // We handle several grid areas with the same name at once to simplify the validation code.
4853             size_t lookAheadCol;
4854             for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) {
4855                 if (columnNames[lookAheadCol + 1] != gridAreaName)
4856                     break;
4857             }
4858
4859             NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
4860             if (gridAreaIt == gridAreaMap.end()) {
4861                 gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol)));
4862             } else {
4863                 GridCoordinate& gridCoordinate = gridAreaIt->value;
4864
4865                 // The following checks test that the grid area is a single filled-in rectangle.
4866                 // 1. The new row is adjacent to the previously parsed row.
4867                 if (rowCount != gridCoordinate.rows.initialPositionIndex + 1)
4868                     return 0;
4869
4870                 // 2. The new area starts at the same position as the previously parsed area.
4871                 if (currentCol != gridCoordinate.columns.initialPositionIndex)
4872                     return 0;
4873
4874                 // 3. The new area ends at the same position as the previously parsed area.
4875                 if (lookAheadCol != gridCoordinate.columns.finalPositionIndex)
4876                     return 0;
4877
4878                 ++gridCoordinate.rows.finalPositionIndex;
4879             }
4880             currentCol = lookAheadCol;
4881         }
4882
4883         ++rowCount;
4884         m_valueList->next();
4885     }
4886
4887     if (!rowCount || !columnCount)
4888         return 0;
4889
4890     return CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount);
4891 }
4892
4893 PassRefPtr<CSSValue> BisonCSSParser::parseCounterContent(CSSParserValueList* args, bool counters)
4894 {
4895     unsigned numArgs = args->size();
4896     if (counters && numArgs != 3 && numArgs != 5)
4897         return 0;
4898     if (!counters && numArgs != 1 && numArgs != 3)
4899         return 0;
4900
4901     CSSParserValue* i = args->current();
4902     if (i->unit != CSSPrimitiveValue::CSS_IDENT)
4903         return 0;
4904     RefPtrWillBeRawPtr<CSSPrimitiveValue> identifier = createPrimitiveStringValue(i);
4905
4906     RefPtrWillBeRawPtr<CSSPrimitiveValue> separator;
4907     if (!counters)
4908         separator = cssValuePool().createValue(String(), CSSPrimitiveValue::CSS_STRING);
4909     else {
4910         i = args->next();
4911         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
4912             return 0;
4913
4914         i = args->next();
4915         if (i->unit != CSSPrimitiveValue::CSS_STRING)
4916             return 0;
4917
4918         separator = createPrimitiveStringValue(i);
4919     }
4920
4921     RefPtrWillBeRawPtr<CSSPrimitiveValue> listStyle;
4922     i = args->next();
4923     if (!i) // Make the list style default decimal
4924         listStyle = cssValuePool().createIdentifierValue(CSSValueDecimal);
4925     else {
4926         if (i->unit != CSSParserValue::Operator || i->iValue != ',')
4927             return 0;
4928
4929         i = args->next();
4930         if (i->unit != CSSPrimitiveValue::CSS_IDENT)
4931             return 0;
4932
4933         CSSValueID listStyleID = CSSValueInvalid;
4934         if (i->id == CSSValueNone || (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha))
4935             listStyleID = i->id;
4936         else
4937             return 0;
4938
4939         listStyle = cssValuePool().createIdentifierValue(listStyleID);
4940     }
4941
4942     return cssValuePool().createValue(Counter::create(identifier.release(), listStyle.release(), separator.release()));
4943 }
4944
4945 bool BisonCSSParser::parseClipShape(CSSPropertyID propId, bool important)
4946 {
4947     CSSParserValue* value = m_valueList->current();
4948     CSSParserValueList* args = value->function->args.get();
4949
4950     if (!equalIgnoringCase(value->function->name, "rect(") || !args)
4951         return false;
4952
4953     // rect(t, r, b, l) || rect(t r b l)
4954     if (args->size() != 4 && args->size() != 7)
4955         return false;
4956     RefPtr<Rect> rect = Rect::create();
4957     bool valid = true;
4958     int i = 0;
4959     CSSParserValue* a = args->current();
4960     while (a) {
4961         valid = a->id == CSSValueAuto || validUnit(a, FLength);
4962         if (!valid)
4963             break;
4964         RefPtrWillBeRawPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
4965             cssValuePool().createIdentifierValue(CSSValueAuto) :
4966             createPrimitiveNumericValue(a);
4967         if (i == 0)
4968             rect->setTop(length);
4969         else if (i == 1)
4970             rect->setRight(length);
4971         else if (i == 2)
4972             rect->setBottom(length);
4973         else
4974             rect->setLeft(length);
4975         a = args->next();
4976         if (a && args->size() == 7) {
4977             if (a->unit == CSSParserValue::Operator && a->iValue == ',') {
4978                 a = args->next();
4979             } else {
4980                 valid = false;
4981                 break;
4982             }
4983         }
4984         i++;
4985     }
4986     if (valid) {
4987         addProperty(propId, cssValuePool().createValue(rect.release()), important);
4988         m_valueList->next();
4989         return true;
4990     }
4991     return false;
4992 }
4993
4994 static void completeBorderRadii(RefPtrWillBeRawPtr<CSSPrimitiveValue> radii[4])
4995 {
4996     if (radii[3])
4997         return;
4998     if (!radii[2]) {
4999         if (!radii[1])
5000             radii[1] = radii[0];
5001         radii[2] = radii[0];
5002     }
5003     radii[3] = radii[1];
5004 }
5005
5006 // FIXME: This should be refactored with CSSParser::parseBorderRadius.
5007 // CSSParser::parseBorderRadius contains support for some legacy radius construction.
5008 PassRefPtr<CSSBasicShape> BisonCSSParser::parseInsetRoundedCorners(PassRefPtr<CSSBasicShapeInset> shape, CSSParserValueList* args)
5009 {
5010     CSSParserValue* argument = args->next();
5011
5012     if (!argument)
5013         return 0;
5014
5015     CSSParserValueList radiusArguments;
5016     while (argument) {
5017         radiusArguments.addValue(*argument);
5018         argument = args->next();
5019     }
5020
5021     unsigned num = radiusArguments.size();
5022     if (!num || num > 9)
5023         return 0;
5024
5025     // FIXME: Refactor completeBorderRadii and the array
5026     RefPtrWillBeRawPtr<CSSPrimitiveValue> radii[2][4];
5027
5028     unsigned indexAfterSlash = 0;
5029     for (unsigned i = 0; i < num; ++i) {
5030         CSSParserValue* value = radiusArguments.valueAt(i);
5031         if (value->unit == CSSParserValue::Operator) {
5032             if (value->iValue != '/')
5033                 return 0;
5034
5035             if (!i || indexAfterSlash || i + 1 == num)
5036                 return 0;
5037
5038             indexAfterSlash = i + 1;
5039             completeBorderRadii(radii[0]);
5040             continue;
5041         }
5042
5043         if (i - indexAfterSlash >= 4)
5044             return 0;
5045
5046         if (!validUnit(value, FLength | FPercent | FNonNeg))
5047             return 0;
5048
5049         RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value);
5050
5051         if (!indexAfterSlash)
5052             radii[0][i] = radius;
5053         else
5054             radii[1][i - indexAfterSlash] = radius.release();
5055     }
5056
5057     if (!indexAfterSlash) {
5058         completeBorderRadii(radii[0]);
5059         for (unsigned i = 0; i < 4; ++i)
5060             radii[1][i] = radii[0][i];
5061     } else {
5062         completeBorderRadii(radii[1]);
5063     }
5064     shape->setTopLeftRadius(createPrimitiveValuePair(radii[0][0].release(), radii[1][0].release()));
5065     shape->setTopRightRadius(createPrimitiveValuePair(radii[0][1].release(), radii[1][1].release()));
5066     shape->setBottomRightRadius(createPrimitiveValuePair(radii[0][2].release(), radii[1][2].release()));
5067     shape->setBottomLeftRadius(createPrimitiveValuePair(radii[0][3].release(), radii[1][3].release()));
5068
5069     return shape;
5070 }
5071
5072 PassRefPtr<CSSBasicShape> BisonCSSParser::parseBasicShapeInset(CSSParserValueList* args)
5073 {
5074     ASSERT(args);
5075
5076     RefPtr<CSSBasicShapeInset> shape = CSSBasicShapeInset::create();
5077
5078     CSSParserValue* argument = args->current();
5079     WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> > widthArguments;
5080     bool hasRoundedInset = false;
5081
5082     while (argument) {
5083         if (argument->unit == CSSPrimitiveValue::CSS_IDENT && equalIgnoringCase(argument->string, "round")) {
5084             hasRoundedInset = true;
5085             break;
5086         }
5087
5088         Units unitFlags = FLength | FPercent;
5089         if (!validUnit(argument, unitFlags) || widthArguments.size() > 4)
5090             return 0;
5091
5092         widthArguments.append(createPrimitiveNumericValue(argument));
5093         argument = args->next();
5094     }
5095
5096     switch (widthArguments.size()) {
5097     case 1: {
5098         shape->updateShapeSize1Value(widthArguments[0].get());
5099         break;
5100     }
5101     case 2: {
5102         shape->updateShapeSize2Values(widthArguments[0].get(), widthArguments[1].get());
5103         break;
5104         }
5105     case 3: {
5106         shape->updateShapeSize3Values(widthArguments[0].get(), widthArguments[1].get(), widthArguments[2].get());
5107         break;
5108     }
5109     case 4: {
5110         shape->updateShapeSize4Values(widthArguments[0].get(), widthArguments[1].get(), widthArguments[2].get(), widthArguments[3].get());
5111         break;
5112     }
5113     default:
5114         return 0;
5115     }
5116
5117     if (hasRoundedInset)
5118         return parseInsetRoundedCorners(shape, args);
5119     return shape;
5120 }
5121
5122 static bool isItemPositionKeyword(CSSValueID id)
5123 {
5124     return id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter
5125         || id == CSSValueSelfStart || id == CSSValueSelfEnd || id == CSSValueFlexStart
5126         || id == CSSValueFlexEnd || id == CSSValueLeft || id == CSSValueRight;
5127 }
5128
5129 bool BisonCSSParser::parseItemPositionOverflowPosition(CSSPropertyID propId, bool important)
5130 {
5131     // auto | baseline | stretch | [<item-position> && <overflow-position>? ]
5132     // <item-position> = center | start | end | self-start | self-end | flex-start | flex-end | left | right;
5133     // <overflow-position> = true | safe
5134
5135     CSSParserValue* value = m_valueList->current();
5136
5137     if (value->id == CSSValueAuto || value->id == CSSValueBaseline || value->id == CSSValueStretch) {
5138         if (m_valueList->next())
5139             return false;
5140
5141         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
5142         return true;
5143     }
5144
5145     RefPtrWillBeRawPtr<CSSPrimitiveValue> position = 0;
5146     RefPtrWillBeRawPtr<CSSPrimitiveValue> overflowAlignmentKeyword = 0;
5147     if (isItemPositionKeyword(value->id)) {
5148         position = cssValuePool().createIdentifierValue(value->id);
5149         value = m_valueList->next();
5150         if (value) {
5151             if (value->id == CSSValueTrue || value->id == CSSValueSafe)
5152                 overflowAlignmentKeyword = cssValuePool().createIdentifierValue(value->id);
5153             else
5154                 return false;
5155         }
5156     } else if (value->id == CSSValueTrue || value->id == CSSValueSafe) {
5157         overflowAlignmentKeyword = cssValuePool().createIdentifierValue(value->id);
5158         value = m_valueList->next();
5159         if (value) {
5160             if (isItemPositionKeyword(value->id))
5161                 position = cssValuePool().createIdentifierValue(value->id);
5162             else
5163                 return false;
5164         }
5165     } else {
5166         return false;
5167     }
5168
5169     if (m_valueList->next())
5170         return false;
5171
5172     ASSERT(position);
5173     if (overflowAlignmentKeyword)
5174         addProperty(propId, createPrimitiveValuePair(position, overflowAlignmentKeyword), important);
5175     else
5176         addProperty(propId, position.release(), important);
5177
5178     return true;
5179 }
5180
5181 PassRefPtr<CSSBasicShape> BisonCSSParser::parseBasicShapeRectangle(CSSParserValueList* args)
5182 {
5183     ASSERT(args);
5184
5185     // rect(x, y, width, height, [[rx], ry])
5186     if (args->size() != 7 && args->size() != 9 && args->size() != 11)
5187         return 0;
5188
5189     RefPtr<CSSBasicShapeRectangle> shape = CSSBasicShapeRectangle::create();
5190
5191     unsigned argumentNumber = 0;
5192     CSSParserValue* argument = args->current();
5193     while (argument) {
5194         Units unitFlags = FLength | FPercent;
5195         if (argumentNumber > 1) {
5196             // Arguments width, height, rx, and ry cannot be negative.
5197             unitFlags = unitFlags | FNonNeg;
5198         }
5199         if (!validUnit(argument, unitFlags))
5200             return 0;
5201
5202         RefPtrWillBeRawPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
5203         ASSERT(argumentNumber < 6);
5204         switch (argumentNumber) {
5205         case 0:
5206             shape->setX(length);
5207             break;
5208         case 1:
5209             shape->setY(length);
5210             break;
5211         case 2:
5212             shape->setWidth(length);
5213             break;
5214         case 3:
5215             shape->setHeight(length);
5216             break;
5217         case 4:
5218             shape->setRadiusX(length);
5219             break;
5220         case 5:
5221             shape->setRadiusY(length);
5222             break;
5223         }
5224         argument = args->next();
5225         if (argument) {
5226             if (!isComma(argument))
5227                 return 0;
5228
5229             argument = args->next();
5230         }
5231         argumentNumber++;
5232     }
5233
5234     if (argumentNumber < 4)
5235         return 0;
5236     return shape;
5237 }
5238
5239 PassRefPtr<CSSBasicShape> BisonCSSParser::parseBasicShapeInsetRectangle(CSSParserValueList* args)
5240 {
5241     ASSERT(args);
5242
5243     // inset-rectangle(top, right, bottom, left, [[rx], ry])
5244     if (args->size() != 7 && args->size() != 9 && args->size() != 11)
5245         return 0;
5246
5247     RefPtr<CSSBasicShapeInsetRectangle> shape = CSSBasicShapeInsetRectangle::create();
5248
5249     unsigned argumentNumber = 0;
5250     CSSParserValue* argument = args->current();
5251     while (argument) {
5252         Units unitFlags = FLength | FPercent | FNonNeg;
5253         if (!validUnit(argument, unitFlags))
5254             return 0;
5255
5256         RefPtrWillBeRawPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
5257         ASSERT(argumentNumber < 6);
5258         switch (argumentNumber) {
5259         case 0:
5260             shape->setTop(length);
5261             break;
5262         case 1:
5263             shape->setRight(length);
5264             break;
5265         case 2:
5266             shape->setBottom(length);
5267             break;
5268         case 3:
5269             shape->setLeft(length);
5270             break;
5271         case 4:
5272             shape->setRadiusX(length);
5273             break;
5274         case 5:
5275             shape->setRadiusY(length);
5276             break;
5277         }
5278         argument = args->next();
5279         if (argument) {
5280             if (!isComma(argument))
5281                 return 0;
5282
5283             argument = args->next();
5284         }
5285         argumentNumber++;
5286     }
5287
5288     if (argumentNumber < 4)
5289         return 0;
5290     return shape;
5291 }
5292
5293 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::parseShapeRadius(CSSParserValue* value)
5294 {
5295     if (value->id == CSSValueClosestSide || value->id == CSSValueFarthestSide)
5296         return cssValuePool().createIdentifierValue(value->id);
5297
5298     if (!validUnit(value, FLength | FPercent | FNonNeg))
5299         return 0;
5300
5301     return createPrimitiveNumericValue(value);
5302 }
5303
5304 PassRefPtr<CSSBasicShape> BisonCSSParser::parseBasicShapeCircle(CSSParserValueList* args)
5305 {
5306     ASSERT(args);
5307
5308     // circle(radius)
5309     // circle(radius at <position>
5310     // circle(at <position>)
5311     // where position defines centerX and centerY using a CSS <position> data type.
5312     RefPtr<CSSBasicShapeCircle> shape = CSSBasicShapeCircle::create();
5313
5314     for (CSSParserValue* argument = args->current(); argument; argument = args->next()) {
5315         // The call to parseFillPosition below should consume all of the
5316         // arguments except the first two. Thus, and index greater than one
5317         // indicates an invalid production.
5318         if (args->currentIndex() > 1)
5319             return 0;
5320
5321         if (!args->currentIndex() && argument->id != CSSValueAt) {
5322             if (RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = parseShapeRadius(argument)) {
5323                 shape->setRadius(radius);
5324                 continue;
5325             }
5326
5327             return 0;
5328         }
5329
5330         if (argument->id == CSSValueAt) {
5331             RefPtr<CSSValue> centerX;
5332             RefPtr<CSSValue> centerY;
5333             args->next(); // set list to start of position center
5334             parseFillPosition(args, centerX, centerY);
5335             if (centerX && centerY) {
5336                 ASSERT(centerX->isPrimitiveValue());
5337                 ASSERT(centerY->isPrimitiveValue());
5338                 shape->setCenterX(toCSSPrimitiveValue(centerX.get()));
5339                 shape->setCenterY(toCSSPrimitiveValue(centerY.get()));
5340             } else {
5341                 return 0;
5342             }
5343         } else {
5344             return 0;
5345         }
5346     }
5347
5348     return shape;
5349 }
5350
5351 PassRefPtr<CSSBasicShape> BisonCSSParser::parseDeprecatedBasicShapeCircle(CSSParserValueList* args)
5352 {
5353     ASSERT(args);
5354
5355     // circle(centerX, centerY, radius)
5356     if (args->size() != 5)
5357         return 0;
5358
5359     RefPtr<CSSDeprecatedBasicShapeCircle> shape = CSSDeprecatedBasicShapeCircle::create();
5360
5361     unsigned argumentNumber = 0;
5362     CSSParserValue* argument = args->current();
5363     while (argument) {
5364         Units unitFlags = FLength | FPercent;
5365         if (argumentNumber == 2) {
5366             // Argument radius cannot be negative.
5367             unitFlags = unitFlags | FNonNeg;
5368         }
5369
5370         if (!validUnit(argument, unitFlags))
5371             return 0;
5372
5373         RefPtrWillBeRawPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
5374         ASSERT(argumentNumber < 3);
5375         switch (argumentNumber) {
5376         case 0:
5377             shape->setCenterX(length);
5378             break;
5379         case 1:
5380             shape->setCenterY(length);
5381             break;
5382         case 2:
5383             shape->setRadius(length);
5384             break;
5385         }
5386
5387         argument = args->next();
5388         if (argument) {
5389             if (!isComma(argument))
5390                 return 0;
5391             argument = args->next();
5392         }
5393         argumentNumber++;
5394     }
5395
5396     if (argumentNumber < 3)
5397         return 0;
5398     return shape;
5399 }
5400
5401 PassRefPtr<CSSBasicShape> BisonCSSParser::parseBasicShapeEllipse(CSSParserValueList* args)
5402 {
5403     ASSERT(args);
5404
5405     // ellipse(radiusX)
5406     // ellipse(radiusX at <position>
5407     // ellipse(radiusX radiusY)
5408     // ellipse(radiusX radiusY at <position>
5409     // ellipse(at <position>)
5410     // where position defines centerX and centerY using a CSS <position> data type.
5411     RefPtr<CSSBasicShapeEllipse> shape = CSSBasicShapeEllipse::create();
5412
5413     for (CSSParserValue* argument = args->current(); argument; argument = args->next()) {
5414         // The call to parseFillPosition below should consume all of the
5415         // arguments except the first three. Thus, an index greater than two
5416         // indicates an invalid production.
5417         if (args->currentIndex() > 2)
5418             return 0;
5419
5420         if (args->currentIndex() < 2 && argument->id != CSSValueAt) {
5421             if (RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = parseShapeRadius(argument)) {
5422                 if (!shape->radiusX())
5423                     shape->setRadiusX(radius);
5424                 else
5425                     shape->setRadiusY(radius);
5426                 continue;
5427             }
5428
5429             return 0;
5430         }
5431
5432         if (argument->id != CSSValueAt)
5433             return 0;
5434         RefPtr<CSSValue> centerX;
5435         RefPtr<CSSValue> centerY;
5436         args->next(); // set list to start of position center
5437         parseFillPosition(args, centerX, centerY);
5438         if (!centerX || !centerY)
5439             return 0;
5440
5441         ASSERT(centerX->isPrimitiveValue());
5442         ASSERT(centerY->isPrimitiveValue());
5443         shape->setCenterX(toCSSPrimitiveValue(centerX.get()));
5444         shape->setCenterY(toCSSPrimitiveValue(centerY.get()));
5445     }
5446
5447     return shape;
5448 }
5449
5450 PassRefPtr<CSSBasicShape> BisonCSSParser::parseDeprecatedBasicShapeEllipse(CSSParserValueList* args)
5451 {
5452     ASSERT(args);
5453
5454     // ellipse(centerX, centerY, radiusX, radiusY)
5455     if (args->size() != 7)
5456         return 0;
5457
5458     RefPtr<CSSDeprecatedBasicShapeEllipse> shape = CSSDeprecatedBasicShapeEllipse::create();
5459     unsigned argumentNumber = 0;
5460     CSSParserValue* argument = args->current();
5461     while (argument) {
5462         Units unitFlags = FLength | FPercent;
5463         if (argumentNumber > 1) {
5464             // Arguments radiusX and radiusY cannot be negative.
5465             unitFlags = unitFlags | FNonNeg;
5466         }
5467         if (!validUnit(argument, unitFlags))
5468             return 0;
5469
5470         RefPtrWillBeRawPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
5471         ASSERT(argumentNumber < 4);
5472         switch (argumentNumber) {
5473         case 0:
5474             shape->setCenterX(length);
5475             break;
5476         case 1:
5477             shape->setCenterY(length);
5478             break;
5479         case 2:
5480             shape->setRadiusX(length);
5481             break;
5482         case 3:
5483             shape->setRadiusY(length);
5484             break;
5485         }
5486
5487         argument = args->next();
5488         if (argument) {
5489             if (!isComma(argument))
5490                 return 0;
5491             argument = args->next();
5492         }
5493         argumentNumber++;
5494     }
5495
5496     if (argumentNumber < 4)
5497         return 0;
5498     return shape;
5499 }
5500
5501 PassRefPtr<CSSBasicShape> BisonCSSParser::parseBasicShapePolygon(CSSParserValueList* args)
5502 {
5503     ASSERT(args);
5504
5505     unsigned size = args->size();
5506     if (!size)
5507         return 0;
5508
5509     RefPtr<CSSBasicShapePolygon> shape = CSSBasicShapePolygon::create();
5510
5511     CSSParserValue* argument = args->current();
5512     if (argument->id == CSSValueEvenodd || argument->id == CSSValueNonzero) {
5513         shape->setWindRule(argument->id == CSSValueEvenodd ? RULE_EVENODD : RULE_NONZERO);
5514
5515         if (!isComma(args->next()))
5516             return 0;
5517
5518         argument = args->next();
5519         size -= 2;
5520     }
5521
5522     // <length> <length>, ... <length> <length> -> each pair has 3 elements except the last one
5523     if (!size || (size % 3) - 2)
5524         return 0;
5525
5526     CSSParserValue* argumentX = argument;
5527     while (argumentX) {
5528         if (!validUnit(argumentX, FLength | FPercent))
5529             return 0;
5530
5531         CSSParserValue* argumentY = args->next();
5532         if (!argumentY || !validUnit(argumentY, FLength | FPercent))
5533             return 0;
5534
5535         RefPtrWillBeRawPtr<CSSPrimitiveValue> xLength = createPrimitiveNumericValue(argumentX);
5536         RefPtrWillBeRawPtr<CSSPrimitiveValue> yLength = createPrimitiveNumericValue(argumentY);
5537
5538         shape->appendPoint(xLength.release(), yLength.release());
5539
5540         CSSParserValue* commaOrNull = args->next();
5541         if (!commaOrNull)
5542             argumentX = 0;
5543         else if (!isComma(commaOrNull))
5544             return 0;
5545         else
5546             argumentX = args->next();
5547     }
5548
5549     return shape;
5550 }
5551
5552 static bool isBoxValue(CSSValueID valueId)
5553 {
5554     switch (valueId) {
5555     case CSSValueContentBox:
5556     case CSSValuePaddingBox:
5557     case CSSValueBorderBox:
5558     case CSSValueMarginBox:
5559         return true;
5560     default:
5561         break;
5562     }
5563
5564     return false;
5565 }
5566
5567 // FIXME This function is temporary to allow for an orderly transition between
5568 // the new CSS Shapes circle and ellipse syntax. It will be removed when the
5569 // old syntax is removed.
5570 static bool isDeprecatedBasicShape(CSSParserValueList* args)
5571 {
5572     for (unsigned i = args->currentIndex(); i < args->size(); ++i) {
5573         CSSParserValue* value = args->valueAt(i);
5574         if (isComma(value))
5575             return true;
5576     }
5577
5578     return false;
5579 }
5580
5581 PassRefPtr<CSSValue> BisonCSSParser::parseShapeProperty(CSSPropertyID propId)
5582 {
5583     if (!RuntimeEnabledFeatures::cssShapesEnabled())
5584         return 0;
5585
5586     CSSParserValue* value = m_valueList->current();
5587     CSSValueID valueId = value->id;
5588     RefPtrWillBeRawPtr<CSSPrimitiveValue> boxValue;
5589     RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue;
5590
5591     if (valueId == CSSValueNone
5592         || (valueId == CSSValueOutsideShape && propId == CSSPropertyShapeInside)) {
5593         RefPtrWillBeRawPtr<CSSPrimitiveValue> keywordValue = parseValidPrimitive(valueId, value);
5594         m_valueList->next();
5595         return keywordValue.release();
5596     }
5597
5598     RefPtr<CSSValue> imageValue;
5599     if (valueId != CSSValueNone && parseFillImage(m_valueList.get(), imageValue)) {
5600         m_valueList->next();
5601         return imageValue.release();
5602     }
5603
5604     if (value->unit == CSSParserValue::Function) {
5605         shapeValue = parseBasicShape();
5606         if (!shapeValue)
5607             return 0;
5608     } else if (isBoxValue(valueId)) {
5609         boxValue = parseValidPrimitive(valueId, value);
5610         m_valueList->next();
5611     } else {
5612         return 0;
5613     }
5614
5615     ASSERT(shapeValue || boxValue);
5616     value = m_valueList->current();
5617
5618     if (value) {
5619         valueId = value->id;
5620         if (boxValue && value->unit == CSSParserValue::Function) {
5621             shapeValue = parseBasicShape();
5622             if (!shapeValue)
5623                 return 0;
5624         } else if (shapeValue && isBoxValue(valueId)) {
5625             boxValue = parseValidPrimitive(valueId, value);
5626             m_valueList->next();
5627         } else {
5628             return 0;
5629         }
5630
5631         ASSERT(shapeValue && boxValue);
5632         shapeValue->getShapeValue()->setLayoutBox(boxValue.release());
5633     }
5634
5635     if (shapeValue)
5636         return shapeValue.release();
5637     return boxValue.release();
5638 }
5639
5640 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::parseBasicShape()
5641 {
5642     CSSParserValue* value = m_valueList->current();
5643     ASSERT(value->unit == CSSParserValue::Function);
5644     CSSParserValueList* args = value->function->args.get();
5645
5646     if (!args)
5647         return 0;
5648
5649     RefPtr<CSSBasicShape> shape;
5650     if (equalIgnoringCase(value->function->name, "rectangle("))
5651         shape = parseBasicShapeRectangle(args);
5652     else if (equalIgnoringCase(value->function->name, "circle("))
5653         if (isDeprecatedBasicShape(args))
5654             shape = parseDeprecatedBasicShapeCircle(args);
5655         else
5656             shape = parseBasicShapeCircle(args);
5657     else if (equalIgnoringCase(value->function->name, "ellipse("))
5658         if (isDeprecatedBasicShape(args))
5659             shape = parseDeprecatedBasicShapeEllipse(args);
5660         else
5661             shape = parseBasicShapeEllipse(args);
5662     else if (equalIgnoringCase(value->function->name, "polygon("))
5663         shape = parseBasicShapePolygon(args);
5664     else if (equalIgnoringCase(value->function->name, "inset-rectangle("))
5665         shape = parseBasicShapeInsetRectangle(args);
5666     else if (equalIgnoringCase(value->function->name, "inset("))
5667         shape = parseBasicShapeInset(args);
5668
5669     if (!shape)
5670         return 0;
5671
5672     m_valueList->next();
5673     return cssValuePool().createValue(shape.release());
5674 }
5675
5676 // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
5677 bool BisonCSSParser::parseFont(bool important)
5678 {
5679     // Let's check if there is an inherit or initial somewhere in the shorthand.
5680     for (unsigned i = 0; i < m_valueList->size(); ++i) {
5681         if (m_valueList->valueAt(i)->id == CSSValueInherit || m_valueList->valueAt(i)->id == CSSValueInitial)
5682             return false;
5683     }
5684
5685     ShorthandScope scope(this, CSSPropertyFont);
5686     // Optional font-style, font-variant and font-weight.
5687     bool fontStyleParsed = false;
5688     bool fontVariantParsed = false;
5689     bool fontWeightParsed = false;
5690     CSSParserValue* value;
5691     while ((value = m_valueList->current())) {
5692         if (!fontStyleParsed && isValidKeywordPropertyAndValue(CSSPropertyFontStyle, value->id, m_context)) {
5693             addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(value->id), important);
5694             fontStyleParsed = true;
5695         } else if (!fontVariantParsed && (value->id == CSSValueNormal || value->id == CSSValueSmallCaps)) {
5696             // Font variant in the shorthand is particular, it only accepts normal or small-caps.
5697             addProperty(CSSPropertyFontVariant, cssValuePool().createIdentifierValue(value->id), important);
5698             fontVariantParsed = true;
5699         } else if (!fontWeightParsed && parseFontWeight(important))
5700             fontWeightParsed = true;
5701         else
5702             break;
5703         m_valueList->next();
5704     }
5705
5706     if (!value)
5707         return false;
5708
5709     if (!fontStyleParsed)
5710         addProperty(CSSPropertyFontStyle, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
5711     if (!fontVariantParsed)
5712         addProperty(CSSPropertyFontVariant, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
5713     if (!fontWeightParsed)
5714         addProperty(CSSPropertyFontWeight, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
5715
5716     // Now a font size _must_ come.
5717     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
5718     if (!parseFontSize(important))
5719         return false;
5720
5721     value = m_valueList->current();
5722     if (!value)
5723         return false;
5724
5725     if (isForwardSlashOperator(value)) {
5726         // The line-height property.
5727         value = m_valueList->next();
5728         if (!value)
5729             return false;
5730         if (!parseLineHeight(important))
5731             return false;
5732     } else
5733         addProperty(CSSPropertyLineHeight, cssValuePool().createIdentifierValue(CSSValueNormal), important, true);
5734
5735     // Font family must come now.
5736     RefPtr<CSSValue> parsedFamilyValue = parseFontFamily();
5737     if (!parsedFamilyValue)
5738         return false;
5739
5740     addProperty(CSSPropertyFontFamily, parsedFamilyValue.release(), important);
5741
5742     // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires that
5743     // "font-stretch", "font-size-adjust", and "font-kerning" be reset to their initial values
5744     // but we don't seem to support them at the moment. They should also be added here once implemented.
5745     if (m_valueList->current())
5746         return false;
5747
5748     return true;
5749 }
5750
5751 class FontFamilyValueBuilder {
5752 public:
5753     FontFamilyValueBuilder(CSSValueList* list)
5754         : m_list(list)
5755     {
5756     }
5757
5758     void add(const CSSParserString& string)
5759     {
5760         if (!m_builder.isEmpty())
5761             m_builder.append(' ');
5762
5763         if (string.is8Bit()) {
5764             m_builder.append(string.characters8(), string.length());
5765             return;
5766         }
5767
5768         m_builder.append(string.characters16(), string.length());
5769     }
5770
5771     void commit()
5772     {
5773         if (m_builder.isEmpty())
5774             return;
5775         m_list->append(cssValuePool().createFontFamilyValue(m_builder.toString()));
5776         m_builder.clear();
5777     }
5778
5779 private:
5780     StringBuilder m_builder;
5781     CSSValueList* m_list;
5782 };
5783
5784 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFamily()
5785 {
5786     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
5787     CSSParserValue* value = m_valueList->current();
5788
5789     FontFamilyValueBuilder familyBuilder(list.get());
5790     bool inFamily = false;
5791
5792     while (value) {
5793         CSSParserValue* nextValue = m_valueList->next();
5794         bool nextValBreaksFont = !nextValue ||
5795                                  (nextValue->unit == CSSParserValue::Operator && nextValue->iValue == ',');
5796         bool nextValIsFontName = nextValue &&
5797             ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
5798             (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
5799
5800         bool valueIsKeyword = value->id == CSSValueInitial || value->id == CSSValueInherit || value->id == CSSValueDefault;
5801         if (valueIsKeyword && !inFamily) {
5802             if (nextValBreaksFont)
5803                 value = m_valueList->next();
5804             else if (nextValIsFontName)
5805                 value = nextValue;
5806             continue;
5807         }
5808
5809         if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
5810             if (inFamily)
5811                 familyBuilder.add(value->string);
5812             else if (nextValBreaksFont || !nextValIsFontName)
5813                 list->append(cssValuePool().createIdentifierValue(value->id));
5814             else {
5815                 familyBuilder.commit();
5816                 familyBuilder.add(value->string);
5817                 inFamily = true;
5818             }
5819         } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
5820             // Strings never share in a family name.
5821             inFamily = false;
5822             familyBuilder.commit();
5823             list->append(cssValuePool().createFontFamilyValue(value->string));
5824         } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
5825             if (inFamily)
5826                 familyBuilder.add(value->string);
5827             else if (nextValBreaksFont || !nextValIsFontName)
5828                 list->append(cssValuePool().createFontFamilyValue(value->string));
5829             else {
5830                 familyBuilder.commit();
5831                 familyBuilder.add(value->string);
5832                 inFamily = true;
5833             }
5834         } else {
5835             break;
5836         }
5837
5838         if (!nextValue)
5839             break;
5840
5841         if (nextValBreaksFont) {
5842             value = m_valueList->next();
5843             familyBuilder.commit();
5844             inFamily = false;
5845         }
5846         else if (nextValIsFontName)
5847             value = nextValue;
5848         else
5849             break;
5850     }
5851     familyBuilder.commit();
5852
5853     if (!list->length())
5854         list = 0;
5855     return list.release();
5856 }
5857
5858 bool BisonCSSParser::parseLineHeight(bool important)
5859 {
5860     CSSParserValue* value = m_valueList->current();
5861     CSSValueID id = value->id;
5862     bool validPrimitive = false;
5863     // normal | <number> | <length> | <percentage> | inherit
5864     if (id == CSSValueNormal)
5865         validPrimitive = true;
5866     else
5867         validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg));
5868     if (validPrimitive && (!m_valueList->next() || inShorthand()))
5869         addProperty(CSSPropertyLineHeight, parseValidPrimitive(id, value), important);
5870     return validPrimitive;
5871 }
5872
5873 bool BisonCSSParser::parseFontSize(bool important)
5874 {
5875     CSSParserValue* value = m_valueList->current();
5876     CSSValueID id = value->id;
5877     bool validPrimitive = false;
5878     // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
5879     if (id >= CSSValueXxSmall && id <= CSSValueLarger)
5880         validPrimitive = true;
5881     else
5882         validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
5883     if (validPrimitive && (!m_valueList->next() || inShorthand()))
5884         addProperty(CSSPropertyFontSize, parseValidPrimitive(id, value), important);
5885     return validPrimitive;
5886 }
5887
5888 bool BisonCSSParser::parseFontVariant(bool important)
5889 {
5890     RefPtrWillBeRawPtr<CSSValueList> values;
5891     if (m_valueList->size() > 1)
5892         values = CSSValueList::createCommaSeparated();
5893     CSSParserValue* val;
5894     bool expectComma = false;
5895     while ((val = m_valueList->current())) {
5896         RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue;
5897         if (!expectComma) {
5898             expectComma = true;
5899             if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps)
5900                 parsedValue = cssValuePool().createIdentifierValue(val->id);
5901             else if (val->id == CSSValueAll && !values) {
5902                 // 'all' is only allowed in @font-face and with no other values. Make a value list to
5903                 // indicate that we are in the @font-face case.
5904                 values = CSSValueList::createCommaSeparated();
5905                 parsedValue = cssValuePool().createIdentifierValue(val->id);
5906             }
5907         } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
5908             expectComma = false;
5909             m_valueList->next();
5910             continue;
5911         }
5912
5913         if (!parsedValue)
5914             return false;
5915
5916         m_valueList->next();
5917
5918         if (values)
5919             values->append(parsedValue.release());
5920         else {
5921             addProperty(CSSPropertyFontVariant, parsedValue.release(), important);
5922             return true;
5923         }
5924     }
5925
5926     if (values && values->length()) {
5927         m_hasFontFaceOnlyValues = true;
5928         addProperty(CSSPropertyFontVariant, values.release(), important);
5929         return true;
5930     }
5931
5932     return false;
5933 }
5934
5935 bool BisonCSSParser::parseFontWeight(bool important)
5936 {
5937     CSSParserValue* value = m_valueList->current();
5938     if ((value->id >= CSSValueNormal) && (value->id <= CSSValue900)) {
5939         addProperty(CSSPropertyFontWeight, cssValuePool().createIdentifierValue(value->id), important);
5940         return true;
5941     }
5942     if (validUnit(value, FInteger | FNonNeg, HTMLQuirksMode)) {
5943         int weight = static_cast<int>(value->fValue);
5944         if (!(weight % 100) && weight >= 100 && weight <= 900) {
5945             addProperty(CSSPropertyFontWeight, cssValuePool().createIdentifierValue(static_cast<CSSValueID>(CSSValue100 + weight / 100 - 1)), important);
5946             return true;
5947         }
5948     }
5949     return false;
5950 }
5951
5952 bool BisonCSSParser::parseFontFaceSrcURI(CSSValueList* valueList)
5953 {
5954     RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(completeURL(m_valueList->current()->string)));
5955
5956     CSSParserValue* value = m_valueList->next();
5957     if (!value) {
5958         valueList->append(uriValue.release());
5959         return true;
5960     }
5961     if (value->unit == CSSParserValue::Operator && value->iValue == ',') {
5962         m_valueList->next();
5963         valueList->append(uriValue.release());
5964         return true;
5965     }
5966
5967     if (value->unit != CSSParserValue::Function || !equalIgnoringCase(value->function->name, "format("))
5968         return false;
5969
5970     // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20111004/ says that format() contains a comma-separated list of strings,
5971     // but CSSFontFaceSrcValue stores only one format. Allowing one format for now.
5972     CSSParserValueList* args = value->function->args.get();
5973     if (!args || args->size() != 1 || (args->current()->unit != CSSPrimitiveValue::CSS_STRING && args->current()->unit != CSSPrimitiveValue::CSS_IDENT))
5974         return false;
5975     uriValue->setFormat(args->current()->string);
5976     valueList->append(uriValue.release());
5977     value = m_valueList->next();
5978     if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
5979         m_valueList->next();
5980     return true;
5981 }
5982
5983 bool BisonCSSParser::parseFontFaceSrcLocal(CSSValueList* valueList)
5984 {
5985     CSSParserValueList* args = m_valueList->current()->function->args.get();
5986     if (!args || !args->size())
5987         return false;
5988
5989     if (args->size() == 1 && args->current()->unit == CSSPrimitiveValue::CSS_STRING)
5990         valueList->append(CSSFontFaceSrcValue::createLocal(args->current()->string));
5991     else if (args->current()->unit == CSSPrimitiveValue::CSS_IDENT) {
5992         StringBuilder builder;
5993         for (CSSParserValue* localValue = args->current(); localValue; localValue = args->next()) {
5994             if (localValue->unit != CSSPrimitiveValue::CSS_IDENT)
5995                 return false;
5996             if (!builder.isEmpty())
5997                 builder.append(' ');
5998             builder.append(localValue->string);
5999         }
6000         valueList->append(CSSFontFaceSrcValue::createLocal(builder.toString()));
6001     } else
6002         return false;
6003
6004     if (CSSParserValue* value = m_valueList->next()) {
6005         if (value->unit == CSSParserValue::Operator && value->iValue == ',')
6006             m_valueList->next();
6007     }
6008     return true;
6009 }
6010
6011 bool BisonCSSParser::parseFontFaceSrc()
6012 {
6013     RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
6014
6015     while (CSSParserValue* value = m_valueList->current()) {
6016         if (value->unit == CSSPrimitiveValue::CSS_URI) {
6017             if (!parseFontFaceSrcURI(values.get()))
6018                 return false;
6019         } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "local(")) {
6020             if (!parseFontFaceSrcLocal(values.get()))
6021                 return false;
6022         } else
6023             return false;
6024     }
6025     if (!values->length())
6026         return false;
6027
6028     addProperty(CSSPropertySrc, values.release(), m_important);
6029     m_valueList->next();
6030     return true;
6031 }
6032
6033 bool BisonCSSParser::parseFontFaceUnicodeRange()
6034 {
6035     RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
6036     bool failed = false;
6037     bool operatorExpected = false;
6038     for (; m_valueList->current(); m_valueList->next(), operatorExpected = !operatorExpected) {
6039         if (operatorExpected) {
6040             if (m_valueList->current()->unit == CSSParserValue::Operator && m_valueList->current()->iValue == ',')
6041                 continue;
6042             failed = true;
6043             break;
6044         }
6045         if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
6046             failed = true;
6047             break;
6048         }
6049
6050         String rangeString = m_valueList->current()->string;
6051         UChar32 from = 0;
6052         UChar32 to = 0;
6053         unsigned length = rangeString.length();
6054
6055         if (length < 3) {
6056             failed = true;
6057             break;
6058         }
6059
6060         unsigned i = 2;
6061         while (i < length) {
6062             UChar c = rangeString[i];
6063             if (c == '-' || c == '?')
6064                 break;
6065             from *= 16;
6066             if (c >= '0' && c <= '9')
6067                 from += c - '0';
6068             else if (c >= 'A' && c <= 'F')
6069                 from += 10 + c - 'A';
6070             else if (c >= 'a' && c <= 'f')
6071                 from += 10 + c - 'a';
6072             else {
6073                 failed = true;
6074                 break;
6075             }
6076             i++;
6077         }
6078         if (failed)
6079             break;
6080
6081         if (i == length)
6082             to = from;
6083         else if (rangeString[i] == '?') {
6084             unsigned span = 1;
6085             while (i < length && rangeString[i] == '?') {
6086                 span *= 16;
6087                 from *= 16;
6088                 i++;
6089             }
6090             if (i < length)
6091                 failed = true;
6092             to = from + span - 1;
6093         } else {
6094             if (length < i + 2) {
6095                 failed = true;
6096                 break;
6097             }
6098             i++;
6099             while (i < length) {
6100                 UChar c = rangeString[i];
6101                 to *= 16;
6102                 if (c >= '0' && c <= '9')
6103                     to += c - '0';
6104                 else if (c >= 'A' && c <= 'F')
6105                     to += 10 + c - 'A';
6106                 else if (c >= 'a' && c <= 'f')
6107                     to += 10 + c - 'a';
6108                 else {
6109                     failed = true;
6110                     break;
6111                 }
6112                 i++;
6113             }
6114             if (failed)
6115                 break;
6116         }
6117         if (from <= to)
6118             values->append(CSSUnicodeRangeValue::create(from, to));
6119     }
6120     if (failed || !values->length())
6121         return false;
6122     addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
6123     return true;
6124 }
6125
6126 // Returns the number of characters which form a valid double
6127 // and are terminated by the given terminator character
6128 template <typename CharacterType>
6129 static int checkForValidDouble(const CharacterType* string, const CharacterType* end, const char terminator)
6130 {
6131     int length = end - string;
6132     if (length < 1)
6133         return 0;
6134
6135     bool decimalMarkSeen = false;
6136     int processedLength = 0;
6137
6138     for (int i = 0; i < length; ++i) {
6139         if (string[i] == terminator) {
6140             processedLength = i;
6141             break;
6142         }
6143         if (!isASCIIDigit(string[i])) {
6144             if (!decimalMarkSeen && string[i] == '.')
6145                 decimalMarkSeen = true;
6146             else
6147                 return 0;
6148         }
6149     }
6150
6151     if (decimalMarkSeen && processedLength == 1)
6152         return 0;
6153
6154     return processedLength;
6155 }
6156
6157 // Returns the number of characters consumed for parsing a valid double
6158 // terminated by the given terminator character
6159 template <typename CharacterType>
6160 static int parseDouble(const CharacterType* string, const CharacterType* end, const char terminator, double& value)
6161 {
6162     int length = checkForValidDouble(string, end, terminator);
6163     if (!length)
6164         return 0;
6165
6166     int position = 0;
6167     double localValue = 0;
6168
6169     // The consumed characters here are guaranteed to be
6170     // ASCII digits with or without a decimal mark
6171     for (; position < length; ++position) {
6172         if (string[position] == '.')
6173             break;
6174         localValue = localValue * 10 + string[position] - '0';
6175     }
6176
6177     if (++position == length) {
6178         value = localValue;
6179         return length;
6180     }
6181
6182     double fraction = 0;
6183     double scale = 1;
6184
6185     while (position < length && scale < MAX_SCALE) {
6186         fraction = fraction * 10 + string[position++] - '0';
6187         scale *= 10;
6188     }
6189
6190     value = localValue + fraction / scale;
6191     return length;
6192 }
6193
6194 template <typename CharacterType>
6195 static bool parseColorIntOrPercentage(const CharacterType*& string, const CharacterType* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
6196 {
6197     const CharacterType* current = string;
6198     double localValue = 0;
6199     bool negative = false;
6200     while (current != end && isHTMLSpace<CharacterType>(*current))
6201         current++;
6202     if (current != end && *current == '-') {
6203         negative = true;
6204         current++;
6205     }
6206     if (current == end || !isASCIIDigit(*current))
6207         return false;
6208     while (current != end && isASCIIDigit(*current)) {
6209         double newValue = localValue * 10 + *current++ - '0';
6210         if (newValue >= 255) {
6211             // Clamp values at 255.
6212             localValue = 255;
6213             while (current != end && isASCIIDigit(*current))
6214                 ++current;
6215             break;
6216         }
6217         localValue = newValue;
6218     }
6219
6220     if (current == end)
6221         return false;
6222
6223     if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%'))
6224         return false;
6225
6226     if (*current == '.') {
6227         // We already parsed the integral part, try to parse
6228         // the fraction part of the percentage value.
6229         double percentage = 0;
6230         int numCharactersParsed = parseDouble(current, end, '%', percentage);
6231         if (!numCharactersParsed)
6232             return false;
6233         current += numCharactersParsed;
6234         if (*current != '%')
6235             return false;
6236         localValue += percentage;
6237     }
6238
6239     if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%')
6240         return false;
6241
6242     if (*current == '%') {
6243         expect = CSSPrimitiveValue::CSS_PERCENTAGE;
6244         localValue = localValue / 100.0 * 256.0;
6245         // Clamp values at 255 for percentages over 100%
6246         if (localValue > 255)
6247             localValue = 255;
6248         current++;
6249     } else
6250         expect = CSSPrimitiveValue::CSS_NUMBER;
6251
6252     while (current != end && isHTMLSpace<CharacterType>(*current))
6253         current++;
6254     if (current == end || *current++ != terminator)
6255         return false;
6256     // Clamp negative values at zero.
6257     value = negative ? 0 : static_cast<int>(localValue);
6258     string = current;
6259     return true;
6260 }
6261
6262 template <typename CharacterType>
6263 static inline bool isTenthAlpha(const CharacterType* string, const int length)
6264 {
6265     // "0.X"
6266     if (length == 3 && string[0] == '0' && string[1] == '.' && isASCIIDigit(string[2]))
6267         return true;
6268
6269     // ".X"
6270     if (length == 2 && string[0] == '.' && isASCIIDigit(string[1]))
6271         return true;
6272
6273     return false;
6274 }
6275
6276 template <typename CharacterType>
6277 static inline bool parseAlphaValue(const CharacterType*& string, const CharacterType* end, const char terminator, int& value)
6278 {
6279     while (string != end && isHTMLSpace<CharacterType>(*string))
6280         string++;
6281
6282     bool negative = false;
6283
6284     if (string != end && *string == '-') {
6285         negative = true;
6286         string++;
6287     }
6288
6289     value = 0;
6290
6291     int length = end - string;
6292     if (length < 2)
6293         return false;
6294
6295     if (string[length - 1] != terminator || !isASCIIDigit(string[length - 2]))
6296         return false;
6297
6298     if (string[0] != '0' && string[0] != '1' && string[0] != '.') {
6299         if (checkForValidDouble(string, end, terminator)) {
6300             value = negative ? 0 : 255;
6301             string = end;
6302             return true;
6303         }
6304         return false;
6305     }
6306
6307     if (length == 2 && string[0] != '.') {
6308         value = !negative && string[0] == '1' ? 255 : 0;
6309         string = end;
6310         return true;
6311     }
6312
6313     if (isTenthAlpha(string, length - 1)) {
6314         static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 };
6315         value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0'];
6316         string = end;
6317         return true;
6318     }
6319
6320     double alpha = 0;
6321     if (!parseDouble(string, end, terminator, alpha))
6322         return false;
6323     value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0));
6324     string = end;
6325     return true;
6326 }
6327
6328 template <typename CharacterType>
6329 static inline bool mightBeRGBA(const CharacterType* characters, unsigned length)
6330 {
6331     if (length < 5)
6332         return false;
6333     return characters[4] == '('
6334         && isASCIIAlphaCaselessEqual(characters[0], 'r')
6335         && isASCIIAlphaCaselessEqual(characters[1], 'g')
6336         && isASCIIAlphaCaselessEqual(characters[2], 'b')
6337         && isASCIIAlphaCaselessEqual(characters[3], 'a');
6338 }
6339
6340 template <typename CharacterType>
6341 static inline bool mightBeRGB(const CharacterType* characters, unsigned length)
6342 {
6343     if (length < 4)
6344         return false;
6345     return characters[3] == '('
6346         && isASCIIAlphaCaselessEqual(characters[0], 'r')
6347         && isASCIIAlphaCaselessEqual(characters[1], 'g')
6348         && isASCIIAlphaCaselessEqual(characters[2], 'b');
6349 }
6350
6351 template <typename CharacterType>
6352 static inline bool fastParseColorInternal(RGBA32& rgb, const CharacterType* characters, unsigned length , bool strict)
6353 {
6354     CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN;
6355
6356     if (!strict && length >= 3) {
6357         if (characters[0] == '#') {
6358             if (Color::parseHexColor(characters + 1, length - 1, rgb))
6359                 return true;
6360         } else {
6361             if (Color::parseHexColor(characters, length, rgb))
6362                 return true;
6363         }
6364     }
6365
6366     // Try rgba() syntax.
6367     if (mightBeRGBA(characters, length)) {
6368         const CharacterType* current = characters + 5;
6369         const CharacterType* end = characters + length;
6370         int red;
6371         int green;
6372         int blue;
6373         int alpha;
6374
6375         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
6376             return false;
6377         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
6378             return false;
6379         if (!parseColorIntOrPercentage(current, end, ',', expect, blue))
6380             return false;
6381         if (!parseAlphaValue(current, end, ')', alpha))
6382             return false;
6383         if (current != end)
6384             return false;
6385         rgb = makeRGBA(red, green, blue, alpha);
6386         return true;
6387     }
6388
6389     // Try rgb() syntax.
6390     if (mightBeRGB(characters, length)) {
6391         const CharacterType* current = characters + 4;
6392         const CharacterType* end = characters + length;
6393         int red;
6394         int green;
6395         int blue;
6396         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
6397             return false;
6398         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
6399             return false;
6400         if (!parseColorIntOrPercentage(current, end, ')', expect, blue))
6401             return false;
6402         if (current != end)
6403             return false;
6404         rgb = makeRGB(red, green, blue);
6405         return true;
6406     }
6407
6408     return false;
6409 }
6410
6411 template<typename StringType>
6412 bool BisonCSSParser::fastParseColor(RGBA32& rgb, const StringType& name, bool strict)
6413 {
6414     unsigned length = name.length();
6415     bool parseResult;
6416
6417     if (!length)
6418         return false;
6419
6420     if (name.is8Bit())
6421         parseResult = fastParseColorInternal(rgb, name.characters8(), length, strict);
6422     else
6423         parseResult = fastParseColorInternal(rgb, name.characters16(), length, strict);
6424
6425     if (parseResult)
6426         return true;
6427
6428     // Try named colors.
6429     Color tc;
6430     if (!tc.setNamedColor(name))
6431         return false;
6432     rgb = tc.rgb();
6433     return true;
6434 }
6435
6436 inline double BisonCSSParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueCondition releaseCalc)
6437 {
6438     const double result = m_parsedCalculation ? m_parsedCalculation->doubleValue() : v->fValue;
6439     if (releaseCalc == ReleaseParsedCalcValue)
6440         m_parsedCalculation.release();
6441     return result;
6442 }
6443
6444 bool BisonCSSParser::isCalculation(CSSParserValue* value)
6445 {
6446     return (value->unit == CSSParserValue::Function)
6447         && (equalIgnoringCase(value->function->name, "calc(")
6448             || equalIgnoringCase(value->function->name, "-webkit-calc(")
6449             || equalIgnoringCase(value->function->name, "-webkit-min(")
6450             || equalIgnoringCase(value->function->name, "-webkit-max("));
6451 }
6452
6453 inline int BisonCSSParser::colorIntFromValue(CSSParserValue* v)
6454 {
6455     bool isPercent;
6456
6457     if (m_parsedCalculation)
6458         isPercent = m_parsedCalculation->category() == CalcPercent;
6459     else
6460         isPercent = v->unit == CSSPrimitiveValue::CSS_PERCENTAGE;
6461
6462     const double value = parsedDouble(v, ReleaseParsedCalcValue);
6463
6464     if (value <= 0.0)
6465         return 0;
6466
6467     if (isPercent) {
6468         if (value >= 100.0)
6469             return 255;
6470         return static_cast<int>(value * 256.0 / 100.0);
6471     }
6472
6473     if (value >= 255.0)
6474         return 255;
6475
6476     return static_cast<int>(value);
6477 }
6478
6479 bool BisonCSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha)
6480 {
6481     CSSParserValueList* args = value->function->args.get();
6482     CSSParserValue* v = args->current();
6483     Units unitType = FUnknown;
6484     // Get the first value and its type
6485     if (validUnit(v, FInteger, HTMLStandardMode))
6486         unitType = FInteger;
6487     else if (validUnit(v, FPercent, HTMLStandardMode))
6488         unitType = FPercent;
6489     else
6490         return false;
6491
6492     colorArray[0] = colorIntFromValue(v);
6493     for (int i = 1; i < 3; i++) {
6494         v = args->next();
6495         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
6496             return false;
6497         v = args->next();
6498         if (!validUnit(v, unitType, HTMLStandardMode))
6499             return false;
6500         colorArray[i] = colorIntFromValue(v);
6501     }
6502     if (parseAlpha) {
6503         v = args->next();
6504         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
6505             return false;
6506         v = args->next();
6507         if (!validUnit(v, FNumber, HTMLStandardMode))
6508             return false;
6509         const double value = parsedDouble(v, ReleaseParsedCalcValue);
6510         // Convert the floating pointer number of alpha to an integer in the range [0, 256),
6511         // with an equal distribution across all 256 values.
6512         colorArray[3] = static_cast<int>(max(0.0, min(1.0, value)) * nextafter(256.0, 0.0));
6513     }
6514     return true;
6515 }
6516
6517 // The CSS3 specification defines the format of a HSL color as
6518 // hsl(<number>, <percent>, <percent>)
6519 // and with alpha, the format is
6520 // hsla(<number>, <percent>, <percent>, <number>)
6521 // The first value, HUE, is in an angle with a value between 0 and 360
6522 bool BisonCSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha)
6523 {
6524     CSSParserValueList* args = value->function->args.get();
6525     CSSParserValue* v = args->current();
6526     // Get the first value
6527     if (!validUnit(v, FNumber, HTMLStandardMode))
6528         return false;
6529     // normalize the Hue value and change it to be between 0 and 1.0
6530     colorArray[0] = (((static_cast<int>(parsedDouble(v, ReleaseParsedCalcValue)) % 360) + 360) % 360) / 360.0;
6531     for (int i = 1; i < 3; i++) {
6532         v = args->next();
6533         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
6534             return false;
6535         v = args->next();
6536         if (!validUnit(v, FPercent, HTMLStandardMode))
6537             return false;
6538         colorArray[i] = max(0.0, min(100.0, parsedDouble(v, ReleaseParsedCalcValue))) / 100.0; // needs to be value between 0 and 1.0
6539     }
6540     if (parseAlpha) {
6541         v = args->next();
6542         if (v->unit != CSSParserValue::Operator && v->iValue != ',')
6543             return false;
6544         v = args->next();
6545         if (!validUnit(v, FNumber, HTMLStandardMode))
6546             return false;
6547         colorArray[3] = max(0.0, min(1.0, parsedDouble(v, ReleaseParsedCalcValue)));
6548     }
6549     return true;
6550 }
6551
6552 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> BisonCSSParser::parseColor(CSSParserValue* value)
6553 {
6554     RGBA32 c = Color::transparent;
6555     if (!parseColorFromValue(value ? value : m_valueList->current(), c))
6556         return 0;
6557     return cssValuePool().createColorValue(c);
6558 }
6559
6560 bool BisonCSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c)
6561 {
6562     if (inQuirksMode() && value->unit == CSSPrimitiveValue::CSS_NUMBER
6563         && value->fValue >= 0. && value->fValue < 1000000.) {
6564         String str = String::format("%06d", static_cast<int>((value->fValue+.5)));
6565         // FIXME: This should be strict parsing for SVG as well.
6566         if (!fastParseColor(c, str, !inQuirksMode()))
6567             return false;
6568     } else if (value->unit == CSSPrimitiveValue::CSS_PARSER_HEXCOLOR ||
6569                 value->unit == CSSPrimitiveValue::CSS_IDENT ||
6570                 (inQuirksMode() && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
6571         if (!fastParseColor(c, value->string, !inQuirksMode() && value->unit == CSSPrimitiveValue::CSS_IDENT))
6572             return false;
6573     } else if (value->unit == CSSParserValue::Function &&
6574                 value->function->args != 0 &&
6575                 value->function->args->size() == 5 /* rgb + two commas */ &&
6576                 equalIgnoringCase(value->function->name, "rgb(")) {
6577         int colorValues[3];
6578         if (!parseColorParameters(value, colorValues, false))
6579             return false;
6580         c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
6581     } else {
6582         if (value->unit == CSSParserValue::Function &&
6583                 value->function->args != 0 &&
6584                 value->function->args->size() == 7 /* rgba + three commas */ &&
6585                 equalIgnoringCase(value->function->name, "rgba(")) {
6586             int colorValues[4];
6587             if (!parseColorParameters(value, colorValues, true))
6588                 return false;
6589             c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
6590         } else if (value->unit == CSSParserValue::Function &&
6591                     value->function->args != 0 &&
6592                     value->function->args->size() == 5 /* hsl + two commas */ &&
6593                     equalIgnoringCase(value->function->name, "hsl(")) {
6594             double colorValues[3];
6595             if (!parseHSLParameters(value, colorValues, false))
6596                 return false;
6597             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
6598         } else if (value->unit == CSSParserValue::Function &&
6599                     value->function->args != 0 &&
6600                     value->function->args->size() == 7 /* hsla + three commas */ &&
6601                     equalIgnoringCase(value->function->name, "hsla(")) {
6602             double colorValues[4];
6603             if (!parseHSLParameters(value, colorValues, true))
6604                 return false;
6605             c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
6606         } else
6607             return false;
6608     }
6609
6610     return true;
6611 }
6612
6613 // This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
6614 // without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
6615 struct ShadowParseContext {
6616     DISALLOW_ALLOCATION();
6617 public:
6618     ShadowParseContext(CSSPropertyID prop, BisonCSSParser* parser)
6619         : property(prop)
6620         , m_parser(parser)
6621         , allowX(true)
6622         , allowY(false)
6623         , allowBlur(false)
6624         , allowSpread(false)
6625         , allowColor(true)
6626         , allowStyle(prop == CSSPropertyWebkitBoxShadow || prop == CSSPropertyBoxShadow)
6627         , allowBreak(true)
6628     {
6629     }
6630
6631     bool allowLength() { return allowX || allowY || allowBlur || allowSpread; }
6632
6633     void commitValue()
6634     {
6635         // Handle the ,, case gracefully by doing nothing.
6636         if (x || y || blur || spread || color || style) {
6637             if (!values)
6638                 values = CSSValueList::createCommaSeparated();
6639
6640             // Construct the current shadow value and add it to the list.
6641             values->append(CSSShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
6642         }
6643
6644         // Now reset for the next shadow value.
6645         x = 0;
6646         y = 0;
6647         blur = 0;
6648         spread = 0;
6649         style = 0;
6650         color = 0;
6651
6652         allowX = true;
6653         allowColor = true;
6654         allowBreak = true;
6655         allowY = false;
6656         allowBlur = false;
6657         allowSpread = false;
6658         allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
6659     }
6660
6661     void commitLength(CSSParserValue* v)
6662     {
6663         RefPtrWillBeRawPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v);
6664
6665         if (allowX) {
6666             x = val.release();
6667             allowX = false;
6668             allowY = true;
6669             allowColor = false;
6670             allowStyle = false;
6671             allowBreak = false;
6672         } else if (allowY) {
6673             y = val.release();
6674             allowY = false;
6675             allowBlur = true;
6676             allowColor = true;
6677             allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
6678             allowBreak = true;
6679         } else if (allowBlur) {
6680             blur = val.release();
6681             allowBlur = false;
6682             allowSpread = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
6683         } else if (allowSpread) {
6684             spread = val.release();
6685             allowSpread = false;
6686         }
6687     }
6688
6689     void commitColor(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val)
6690     {
6691         color = val;
6692         allowColor = false;
6693         if (allowX) {
6694             allowStyle = false;
6695             allowBreak = false;
6696         } else {
6697             allowBlur = false;
6698             allowSpread = false;
6699             allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
6700         }
6701     }
6702
6703     void commitStyle(CSSParserValue* v)
6704     {
6705         style = cssValuePool().createIdentifierValue(v->id);
6706         allowStyle = false;
6707         if (allowX)
6708             allowBreak = false;
6709         else {
6710             allowBlur = false;
6711             allowSpread = false;
6712             allowColor = false;
6713         }
6714     }
6715
6716     CSSPropertyID property;
6717     BisonCSSParser* m_parser;
6718
6719     RefPtrWillBeRawPtr<CSSValueList> values;
6720     RefPtrWillBeRawPtr<CSSPrimitiveValue> x;
6721     RefPtrWillBeRawPtr<CSSPrimitiveValue> y;
6722     RefPtrWillBeRawPtr<CSSPrimitiveValue> blur;
6723     RefPtrWillBeRawPtr<CSSPrimitiveValue> spread;
6724     RefPtrWillBeRawPtr<CSSPrimitiveValue> style;
6725     RefPtrWillBeRawPtr<CSSPrimitiveValue> color;
6726
6727     bool allowX;
6728     bool allowY;
6729     bool allowBlur;
6730     bool allowSpread;
6731     bool allowColor;
6732     bool allowStyle; // inset or not.
6733     bool allowBreak;
6734 };
6735
6736 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseShadow(CSSParserValueList* valueList, CSSPropertyID propId)
6737 {
6738     ShadowParseContext context(propId, this);
6739     CSSParserValue* val;
6740     while ((val = valueList->current())) {
6741         // Check for a comma break first.
6742         if (val->unit == CSSParserValue::Operator) {
6743             if (val->iValue != ',' || !context.allowBreak)
6744                 // Other operators aren't legal or we aren't done with the current shadow
6745                 // value.  Treat as invalid.
6746                 return 0;
6747             // The value is good.  Commit it.
6748             context.commitValue();
6749         } else if (validUnit(val, FLength, HTMLStandardMode)) {
6750             // We required a length and didn't get one. Invalid.
6751             if (!context.allowLength())
6752                 return 0;
6753
6754             // Blur radius must be non-negative.
6755             if (context.allowBlur && !validUnit(val, FLength | FNonNeg, HTMLStandardMode))
6756                 return 0;
6757
6758             // A length is allowed here.  Construct the value and add it.
6759             context.commitLength(val);
6760         } else if (val->id == CSSValueInset) {
6761             if (!context.allowStyle)
6762                 return 0;
6763
6764             context.commitStyle(val);
6765         } else {
6766             // The only other type of value that's ok is a color value.
6767             RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedColor;
6768             bool isColor = ((val->id >= CSSValueAqua && val->id <= CSSValueWindowtext) || val->id == CSSValueMenu
6769                             || (val->id >= CSSValueWebkitFocusRingColor && val->id <= CSSValueWebkitText && inQuirksMode())
6770                             || val->id == CSSValueCurrentcolor);
6771             if (isColor) {
6772                 if (!context.allowColor)
6773                     return 0;
6774                 parsedColor = cssValuePool().createIdentifierValue(val->id);
6775             }
6776
6777             if (!parsedColor)
6778                 // It's not built-in. Try to parse it as a color.
6779                 parsedColor = parseColor(val);
6780
6781             if (!parsedColor || !context.allowColor)
6782                 return 0; // This value is not a color or length and is invalid or
6783                           // it is a color, but a color isn't allowed at this point.
6784
6785             context.commitColor(parsedColor.release());
6786         }
6787
6788         valueList->next();
6789     }
6790
6791     if (context.allowBreak) {
6792         context.commitValue();
6793         if (context.values && context.values->length())
6794             return context.values.release();
6795     }
6796
6797     return 0;
6798 }
6799
6800 bool BisonCSSParser::parseReflect(CSSPropertyID propId, bool important)
6801 {
6802     // box-reflect: <direction> <offset> <mask>
6803
6804     // Direction comes first.
6805     CSSParserValue* val = m_valueList->current();
6806     RefPtrWillBeRawPtr<CSSPrimitiveValue> direction;
6807     switch (val->id) {
6808     case CSSValueAbove:
6809     case CSSValueBelow:
6810     case CSSValueLeft:
6811     case CSSValueRight:
6812         direction = cssValuePool().createIdentifierValue(val->id);
6813         break;
6814     default:
6815         return false;
6816     }
6817
6818     // The offset comes next.
6819     val = m_valueList->next();
6820     RefPtrWillBeRawPtr<CSSPrimitiveValue> offset;
6821     if (!val)
6822         offset = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX);
6823     else {
6824         if (!validUnit(val, FLength | FPercent))
6825             return false;
6826         offset = createPrimitiveNumericValue(val);
6827     }
6828
6829     // Now for the mask.
6830     RefPtr<CSSValue> mask;
6831     val = m_valueList->next();
6832     if (val) {
6833         mask = parseBorderImage(propId);
6834         if (!mask)
6835             return false;
6836     }
6837
6838     RefPtrWillBeRawPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction.release(), offset.release(), mask.release());
6839     addProperty(propId, reflectValue.release(), important);
6840     m_valueList->next();
6841     return true;
6842 }
6843
6844 bool BisonCSSParser::parseFlex(CSSParserValueList* args, bool important)
6845 {
6846     if (!args || !args->size() || args->size() > 3)
6847         return false;
6848     static const double unsetValue = -1;
6849     double flexGrow = unsetValue;
6850     double flexShrink = unsetValue;
6851     RefPtrWillBeRawPtr<CSSPrimitiveValue> flexBasis;
6852
6853     while (CSSParserValue* arg = args->current()) {
6854         if (validUnit(arg, FNumber | FNonNeg)) {
6855             if (flexGrow == unsetValue)
6856                 flexGrow = arg->fValue;
6857             else if (flexShrink == unsetValue)
6858                 flexShrink = arg->fValue;
6859             else if (!arg->fValue) {
6860                 // flex only allows a basis of 0 (sans units) if flex-grow and flex-shrink values have already been set.
6861                 flexBasis = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX);
6862             } else {
6863                 // We only allow 3 numbers without units if the last value is 0. E.g., flex:1 1 1 is invalid.
6864                 return false;
6865             }
6866         } else if (!flexBasis && (arg->id == CSSValueAuto || validUnit(arg, FLength | FPercent | FNonNeg)))
6867             flexBasis = parseValidPrimitive(arg->id, arg);
6868         else {
6869             // Not a valid arg for flex.
6870             return false;
6871         }
6872         args->next();
6873     }
6874
6875     if (flexGrow == unsetValue)
6876         flexGrow = 1;
6877     if (flexShrink == unsetValue)
6878         flexShrink = 1;
6879     if (!flexBasis)
6880         flexBasis = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX);
6881
6882     addProperty(CSSPropertyFlexGrow, cssValuePool().createValue(clampToFloat(flexGrow), CSSPrimitiveValue::CSS_NUMBER), important);
6883     addProperty(CSSPropertyFlexShrink, cssValuePool().createValue(clampToFloat(flexShrink), CSSPrimitiveValue::CSS_NUMBER), important);
6884     addProperty(CSSPropertyFlexBasis, flexBasis, important);
6885     return true;
6886 }
6887
6888 bool BisonCSSParser::parseObjectPosition(bool important)
6889 {
6890     RefPtr<CSSValue> xValue;
6891     RefPtr<CSSValue> yValue;
6892     parseFillPosition(m_valueList.get(), xValue, yValue);
6893     if (!xValue || !yValue)
6894         return false;
6895     addProperty(
6896         CSSPropertyObjectPosition,
6897         createPrimitiveValuePair(toCSSPrimitiveValue(xValue.get()), toCSSPrimitiveValue(yValue.get()), Pair::KeepIdenticalValues),
6898         important);
6899     return true;
6900 }
6901
6902 struct BorderImageParseContext {
6903     DISALLOW_ALLOCATION();
6904 public:
6905     BorderImageParseContext()
6906     : m_canAdvance(false)
6907     , m_allowCommit(true)
6908     , m_allowImage(true)
6909     , m_allowImageSlice(true)
6910     , m_allowRepeat(true)
6911     , m_allowForwardSlashOperator(false)
6912     , m_requireWidth(false)
6913     , m_requireOutset(false)
6914     {}
6915
6916     bool canAdvance() const { return m_canAdvance; }
6917     void setCanAdvance(bool canAdvance) { m_canAdvance = canAdvance; }
6918
6919     bool allowCommit() const { return m_allowCommit; }
6920     bool allowImage() const { return m_allowImage; }
6921     bool allowImageSlice() const { return m_allowImageSlice; }
6922     bool allowRepeat() const { return m_allowRepeat; }
6923     bool allowForwardSlashOperator() const { return m_allowForwardSlashOperator; }
6924
6925     bool requireWidth() const { return m_requireWidth; }
6926     bool requireOutset() const { return m_requireOutset; }
6927
6928     void commitImage(PassRefPtr<CSSValue> image)
6929     {
6930         m_image = image;
6931         m_canAdvance = true;
6932         m_allowCommit = true;
6933         m_allowImage = m_allowForwardSlashOperator = m_requireWidth = m_requireOutset = false;
6934         m_allowImageSlice = !m_imageSlice;
6935         m_allowRepeat = !m_repeat;
6936     }
6937     void commitImageSlice(PassRefPtrWillBeRawPtr<CSSBorderImageSliceValue> slice)
6938     {
6939         m_imageSlice = slice;
6940         m_canAdvance = true;
6941         m_allowCommit = m_allowForwardSlashOperator = true;
6942         m_allowImageSlice = m_requireWidth = m_requireOutset = false;
6943         m_allowImage = !m_image;
6944         m_allowRepeat = !m_repeat;
6945     }
6946     void commitForwardSlashOperator()
6947     {
6948         m_canAdvance = true;
6949         m_allowCommit = m_allowImage = m_allowImageSlice = m_allowRepeat = m_allowForwardSlashOperator = false;
6950         if (!m_borderSlice) {
6951             m_requireWidth = true;
6952             m_requireOutset = false;
6953         } else {
6954             m_requireOutset = true;
6955             m_requireWidth = false;
6956         }
6957     }
6958     void commitBorderWidth(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> slice)
6959     {
6960         m_borderSlice = slice;
6961         m_canAdvance = true;
6962         m_allowCommit = m_allowForwardSlashOperator = true;
6963         m_allowImageSlice = m_requireWidth = m_requireOutset = false;
6964         m_allowImage = !m_image;
6965         m_allowRepeat = !m_repeat;
6966     }
6967     void commitBorderOutset(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> outset)
6968     {
6969         m_outset = outset;
6970         m_canAdvance = true;
6971         m_allowCommit = true;
6972         m_allowImageSlice = m_allowForwardSlashOperator = m_requireWidth = m_requireOutset = false;
6973         m_allowImage = !m_image;
6974         m_allowRepeat = !m_repeat;
6975     }
6976     void commitRepeat(PassRefPtr<CSSValue> repeat)
6977     {
6978         m_repeat = repeat;
6979         m_canAdvance = true;
6980         m_allowCommit = true;
6981         m_allowRepeat = m_allowForwardSlashOperator = m_requireWidth = m_requireOutset = false;
6982         m_allowImageSlice = !m_imageSlice;
6983         m_allowImage = !m_image;
6984     }
6985
6986     PassRefPtr<CSSValue> commitCSSValue()
6987     {
6988         return createBorderImageValue(m_image, m_imageSlice, m_borderSlice, m_outset, m_repeat);
6989     }
6990
6991     void commitMaskBoxImage(BisonCSSParser* parser, bool important)
6992     {
6993         commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageSource, parser, m_image, important);
6994         commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageSlice, parser, m_imageSlice, important);
6995         commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageWidth, parser, m_borderSlice, important);
6996         commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageOutset, parser, m_outset, important);
6997         commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageRepeat, parser, m_repeat, important);
6998     }
6999
7000     void commitBorderImage(BisonCSSParser* parser, bool important)
7001     {
7002         commitBorderImageProperty(CSSPropertyBorderImageSource, parser, m_image, important);
7003         commitBorderImageProperty(CSSPropertyBorderImageSlice, parser, m_imageSlice, important);
7004         commitBorderImageProperty(CSSPropertyBorderImageWidth, parser, m_borderSlice, important);
7005         commitBorderImageProperty(CSSPropertyBorderImageOutset, parser, m_outset, important);
7006         commitBorderImageProperty(CSSPropertyBorderImageRepeat, parser, m_repeat, important);
7007     }
7008
7009     void commitBorderImageProperty(CSSPropertyID propId, BisonCSSParser* parser, PassRefPtr<CSSValue> value, bool important)
7010     {
7011         if (value)
7012             parser->addProperty(propId, value, important);
7013         else
7014             parser->addProperty(propId, cssValuePool().createImplicitInitialValue(), important, true);
7015     }
7016
7017     bool m_canAdvance;
7018
7019     bool m_allowCommit;
7020     bool m_allowImage;
7021     bool m_allowImageSlice;
7022     bool m_allowRepeat;
7023     bool m_allowForwardSlashOperator;
7024
7025     bool m_requireWidth;
7026     bool m_requireOutset;
7027
7028     RefPtr<CSSValue> m_image;
7029     RefPtrWillBeRawPtr<CSSBorderImageSliceValue> m_imageSlice;
7030     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_borderSlice;
7031     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_outset;
7032
7033     RefPtr<CSSValue> m_repeat;
7034 };
7035
7036 static bool buildBorderImageParseContext(BisonCSSParser& parser, CSSPropertyID propId, BorderImageParseContext& context)
7037 {
7038     ShorthandScope scope(&parser, propId);
7039     while (CSSParserValue* val = parser.m_valueList->current()) {
7040         context.setCanAdvance(false);
7041
7042         if (!context.canAdvance() && context.allowForwardSlashOperator() && isForwardSlashOperator(val))
7043             context.commitForwardSlashOperator();
7044
7045         if (!context.canAdvance() && context.allowImage()) {
7046             if (val->unit == CSSPrimitiveValue::CSS_URI) {
7047                 context.commitImage(CSSImageValue::create(parser.m_context.completeURL(val->string)));
7048             } else if (isGeneratedImageValue(val)) {
7049                 RefPtr<CSSValue> value;
7050                 if (parser.parseGeneratedImage(parser.m_valueList.get(), value))
7051                     context.commitImage(value.release());
7052                 else
7053                     return false;
7054             } else if (val->unit == CSSParserValue::Function && equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
7055                 RefPtr<CSSValue> value = parser.parseImageSet(parser.m_valueList.get());
7056                 if (value)
7057                     context.commitImage(value.release());
7058                 else
7059                     return false;
7060             } else if (val->id == CSSValueNone)
7061                 context.commitImage(cssValuePool().createIdentifierValue(CSSValueNone));
7062         }
7063
7064         if (!context.canAdvance() && context.allowImageSlice()) {
7065             RefPtrWillBeRawPtr<CSSBorderImageSliceValue> imageSlice;
7066             if (parser.parseBorderImageSlice(propId, imageSlice))
7067                 context.commitImageSlice(imageSlice.release());
7068         }
7069
7070         if (!context.canAdvance() && context.allowRepeat()) {
7071             RefPtr<CSSValue> repeat;
7072             if (parser.parseBorderImageRepeat(repeat))
7073                 context.commitRepeat(repeat.release());
7074         }
7075
7076         if (!context.canAdvance() && context.requireWidth()) {
7077             RefPtrWillBeRawPtr<CSSPrimitiveValue> borderSlice;
7078             if (parser.parseBorderImageWidth(borderSlice))
7079                 context.commitBorderWidth(borderSlice.release());
7080         }
7081
7082         if (!context.canAdvance() && context.requireOutset()) {
7083             RefPtrWillBeRawPtr<CSSPrimitiveValue> borderOutset;
7084             if (parser.parseBorderImageOutset(borderOutset))
7085                 context.commitBorderOutset(borderOutset.release());
7086         }
7087
7088         if (!context.canAdvance())
7089             return false;
7090
7091         parser.m_valueList->next();
7092     }
7093
7094     return context.allowCommit();
7095 }
7096
7097 bool BisonCSSParser::parseBorderImageShorthand(CSSPropertyID propId, bool important)
7098 {
7099     BorderImageParseContext context;
7100     if (buildBorderImageParseContext(*this, propId, context)) {
7101         switch (propId) {
7102         case CSSPropertyWebkitMaskBoxImage:
7103             context.commitMaskBoxImage(this, important);
7104             return true;
7105         case CSSPropertyBorderImage:
7106             context.commitBorderImage(this, important);
7107             return true;
7108         default:
7109             ASSERT_NOT_REACHED();
7110             return false;
7111         }
7112     }
7113     return false;
7114 }
7115
7116 PassRefPtr<CSSValue> BisonCSSParser::parseBorderImage(CSSPropertyID propId)
7117 {
7118     BorderImageParseContext context;
7119     if (buildBorderImageParseContext(*this, propId, context)) {
7120         return context.commitCSSValue();
7121     }
7122     return 0;
7123 }
7124
7125 static bool isBorderImageRepeatKeyword(int id)
7126 {
7127     return id == CSSValueStretch || id == CSSValueRepeat || id == CSSValueSpace || id == CSSValueRound;
7128 }
7129
7130 bool BisonCSSParser::parseBorderImageRepeat(RefPtr<CSSValue>& result)
7131 {
7132     RefPtrWillBeRawPtr<CSSPrimitiveValue> firstValue;
7133     RefPtrWillBeRawPtr<CSSPrimitiveValue> secondValue;
7134     CSSParserValue* val = m_valueList->current();
7135     if (!val)
7136         return false;
7137     if (isBorderImageRepeatKeyword(val->id))
7138         firstValue = cssValuePool().createIdentifierValue(val->id);
7139     else
7140         return false;
7141
7142     val = m_valueList->next();
7143     if (val) {
7144         if (isBorderImageRepeatKeyword(val->id))
7145             secondValue = cssValuePool().createIdentifierValue(val->id);
7146         else if (!inShorthand()) {
7147             // If we're not parsing a shorthand then we are invalid.
7148             return false;
7149         } else {
7150             // We need to rewind the value list, so that when its advanced we'll
7151             // end up back at this value.
7152             m_valueList->previous();
7153             secondValue = firstValue;
7154         }
7155     } else
7156         secondValue = firstValue;
7157
7158     result = createPrimitiveValuePair(firstValue, secondValue);
7159     return true;
7160 }
7161
7162 class BorderImageSliceParseContext {
7163     DISALLOW_ALLOCATION();
7164 public:
7165     BorderImageSliceParseContext(BisonCSSParser* parser)
7166     : m_parser(parser)
7167     , m_allowNumber(true)
7168     , m_allowFill(true)
7169     , m_allowFinalCommit(false)
7170     , m_fill(false)
7171     { }
7172
7173     bool allowNumber() const { return m_allowNumber; }
7174     bool allowFill() const { return m_allowFill; }
7175     bool allowFinalCommit() const { return m_allowFinalCommit; }
7176     CSSPrimitiveValue* top() const { return m_top.get(); }
7177
7178     void commitNumber(CSSParserValue* v)
7179     {
7180         RefPtrWillBeRawPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v);
7181         if (!m_top)
7182             m_top = val;
7183         else if (!m_right)
7184             m_right = val;
7185         else if (!m_bottom)
7186             m_bottom = val;
7187         else {
7188             ASSERT(!m_left);
7189             m_left = val;
7190         }
7191
7192         m_allowNumber = !m_left;
7193         m_allowFinalCommit = true;
7194     }
7195
7196     void commitFill() { m_fill = true; m_allowFill = false; m_allowNumber = !m_top; }
7197
7198     PassRefPtrWillBeRawPtr<CSSBorderImageSliceValue> commitBorderImageSlice()
7199     {
7200         // We need to clone and repeat values for any omissions.
7201         ASSERT(m_top);
7202         if (!m_right) {
7203             m_right = m_top;
7204             m_bottom = m_top;
7205             m_left = m_top;
7206         }
7207         if (!m_bottom) {
7208             m_bottom = m_top;
7209             m_left = m_right;
7210         }
7211         if (!m_left)
7212             m_left = m_right;
7213
7214         // Now build a rect value to hold all four of our primitive values.
7215         RefPtr<Quad> quad = Quad::create();
7216         quad->setTop(m_top);
7217         quad->setRight(m_right);
7218         quad->setBottom(m_bottom);
7219         quad->setLeft(m_left);
7220
7221         // Make our new border image value now.
7222         return CSSBorderImageSliceValue::create(cssValuePool().createValue(quad.release()), m_fill);
7223     }
7224
7225 private:
7226     BisonCSSParser* m_parser;
7227
7228     bool m_allowNumber;
7229     bool m_allowFill;
7230     bool m_allowFinalCommit;
7231
7232     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_top;
7233     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_right;
7234     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_bottom;
7235     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_left;
7236
7237     bool m_fill;
7238 };
7239
7240 bool BisonCSSParser::parseBorderImageSlice(CSSPropertyID propId, RefPtrWillBeRawPtr<CSSBorderImageSliceValue>& result)
7241 {
7242     BorderImageSliceParseContext context(this);
7243     CSSParserValue* val;
7244     while ((val = m_valueList->current())) {
7245         // FIXME calc() http://webkit.org/b/16662 : calc is parsed but values are not created yet.
7246         if (context.allowNumber() && !isCalculation(val) && validUnit(val, FInteger | FNonNeg | FPercent, HTMLStandardMode)) {
7247             context.commitNumber(val);
7248         } else if (context.allowFill() && val->id == CSSValueFill)
7249             context.commitFill();
7250         else if (!inShorthand()) {
7251             // If we're not parsing a shorthand then we are invalid.
7252             return false;
7253         } else {
7254             if (context.allowFinalCommit()) {
7255                 // We're going to successfully parse, but we don't want to consume this token.
7256                 m_valueList->previous();
7257             }
7258             break;
7259         }
7260         m_valueList->next();
7261     }
7262
7263     if (context.allowFinalCommit()) {
7264         // FIXME: For backwards compatibility, -webkit-border-image, -webkit-mask-box-image and -webkit-box-reflect have to do a fill by default.
7265         // FIXME: What do we do with -webkit-box-reflect and -webkit-mask-box-image? Probably just have to leave them filling...
7266         if (propId == CSSPropertyWebkitBorderImage || propId == CSSPropertyWebkitMaskBoxImage || propId == CSSPropertyWebkitBoxReflect)
7267             context.commitFill();
7268
7269         // Need to fully commit as a single value.
7270         result = context.commitBorderImageSlice();
7271         return true;
7272     }
7273
7274     return false;
7275 }
7276
7277 class BorderImageQuadParseContext {
7278 public:
7279     BorderImageQuadParseContext(BisonCSSParser* parser)
7280     : m_parser(parser)
7281     , m_allowNumber(true)
7282     , m_allowFinalCommit(false)
7283     { }
7284
7285     bool allowNumber() const { return m_allowNumber; }
7286     bool allowFinalCommit() const { return m_allowFinalCommit; }
7287     CSSPrimitiveValue* top() const { return m_top.get(); }
7288
7289     void commitNumber(CSSParserValue* v)
7290     {
7291         RefPtrWillBeRawPtr<CSSPrimitiveValue> val;
7292         if (v->id == CSSValueAuto)
7293             val = cssValuePool().createIdentifierValue(v->id);
7294         else
7295             val = m_parser->createPrimitiveNumericValue(v);
7296
7297         if (!m_top)
7298             m_top = val;
7299         else if (!m_right)
7300             m_right = val;
7301         else if (!m_bottom)
7302             m_bottom = val;
7303         else {
7304             ASSERT(!m_left);
7305             m_left = val;
7306         }
7307
7308         m_allowNumber = !m_left;
7309         m_allowFinalCommit = true;
7310     }
7311
7312     void setAllowFinalCommit() { m_allowFinalCommit = true; }
7313     void setTop(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_top = val; }
7314
7315     PassRefPtrWillBeRawPtr<CSSPrimitiveValue> commitBorderImageQuad()
7316     {
7317         // We need to clone and repeat values for any omissions.
7318         ASSERT(m_top);
7319         if (!m_right) {
7320             m_right = m_top;
7321             m_bottom = m_top;
7322             m_left = m_top;
7323         }
7324         if (!m_bottom) {
7325             m_bottom = m_top;
7326             m_left = m_right;
7327         }
7328         if (!m_left)
7329             m_left = m_right;
7330
7331         // Now build a quad value to hold all four of our primitive values.
7332         RefPtr<Quad> quad = Quad::create();
7333         quad->setTop(m_top);
7334         quad->setRight(m_right);
7335         quad->setBottom(m_bottom);
7336         quad->setLeft(m_left);
7337
7338         // Make our new value now.
7339         return cssValuePool().createValue(quad.release());
7340     }
7341
7342 private:
7343     BisonCSSParser* m_parser;
7344
7345     bool m_allowNumber;
7346     bool m_allowFinalCommit;
7347
7348     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_top;
7349     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_right;
7350     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_bottom;
7351     RefPtrWillBeRawPtr<CSSPrimitiveValue> m_left;
7352 };
7353
7354 bool BisonCSSParser::parseBorderImageQuad(Units validUnits, RefPtrWillBeRawPtr<CSSPrimitiveValue>& result)
7355 {
7356     BorderImageQuadParseContext context(this);
7357     CSSParserValue* val;
7358     while ((val = m_valueList->current())) {
7359         if (context.allowNumber() && (validUnit(val, validUnits, HTMLStandardMode) || val->id == CSSValueAuto)) {
7360             context.commitNumber(val);
7361         } else if (!inShorthand()) {
7362             // If we're not parsing a shorthand then we are invalid.
7363             return false;
7364         } else {
7365             if (context.allowFinalCommit())
7366                 m_valueList->previous(); // The shorthand loop will advance back to this point.
7367             break;
7368         }
7369         m_valueList->next();
7370     }
7371
7372     if (context.allowFinalCommit()) {
7373         // Need to fully commit as a single value.
7374         result = context.commitBorderImageQuad();
7375         return true;
7376     }
7377     return false;
7378 }
7379
7380 bool BisonCSSParser::parseBorderImageWidth(RefPtrWillBeRawPtr<CSSPrimitiveValue>& result)
7381 {
7382     return parseBorderImageQuad(FLength | FNumber | FNonNeg | FPercent, result);
7383 }
7384
7385 bool BisonCSSParser::parseBorderImageOutset(RefPtrWillBeRawPtr<CSSPrimitiveValue>& result)
7386 {
7387     return parseBorderImageQuad(FLength | FNumber | FNonNeg, result);
7388 }
7389
7390 bool BisonCSSParser::parseBorderRadius(CSSPropertyID propId, bool important)
7391 {
7392     unsigned num = m_valueList->size();
7393     if (num > 9)
7394         return false;
7395
7396     ShorthandScope scope(this, propId);
7397     RefPtrWillBeRawPtr<CSSPrimitiveValue> radii[2][4];
7398
7399     unsigned indexAfterSlash = 0;
7400     for (unsigned i = 0; i < num; ++i) {
7401         CSSParserValue* value = m_valueList->valueAt(i);
7402         if (value->unit == CSSParserValue::Operator) {
7403             if (value->iValue != '/')
7404                 return false;
7405
7406             if (!i || indexAfterSlash || i + 1 == num || num > i + 5)
7407                 return false;
7408
7409             indexAfterSlash = i + 1;
7410             completeBorderRadii(radii[0]);
7411             continue;
7412         }
7413
7414         if (i - indexAfterSlash >= 4)
7415             return false;
7416
7417         if (!validUnit(value, FLength | FPercent | FNonNeg))
7418             return false;
7419
7420         RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value);
7421
7422         if (!indexAfterSlash) {
7423             radii[0][i] = radius;
7424
7425             // Legacy syntax: -webkit-border-radius: l1 l2; is equivalent to border-radius: l1 / l2;
7426             if (num == 2 && propId == CSSPropertyWebkitBorderRadius) {
7427                 indexAfterSlash = 1;
7428                 completeBorderRadii(radii[0]);
7429             }
7430         } else
7431             radii[1][i - indexAfterSlash] = radius.release();
7432     }
7433
7434     if (!indexAfterSlash) {
7435         completeBorderRadii(radii[0]);
7436         for (unsigned i = 0; i < 4; ++i)
7437             radii[1][i] = radii[0][i];
7438     } else
7439         completeBorderRadii(radii[1]);
7440
7441     ImplicitScope implicitScope(this, PropertyImplicit);
7442     addProperty(CSSPropertyBorderTopLeftRadius, createPrimitiveValuePair(radii[0][0].release(), radii[1][0].release()), important);
7443     addProperty(CSSPropertyBorderTopRightRadius, createPrimitiveValuePair(radii[0][1].release(), radii[1][1].release()), important);
7444     addProperty(CSSPropertyBorderBottomRightRadius, createPrimitiveValuePair(radii[0][2].release(), radii[1][2].release()), important);
7445     addProperty(CSSPropertyBorderBottomLeftRadius, createPrimitiveValuePair(radii[0][3].release(), radii[1][3].release()), important);
7446     return true;
7447 }
7448
7449 bool BisonCSSParser::parseAspectRatio(bool important)
7450 {
7451     unsigned num = m_valueList->size();
7452     if (num == 1 && m_valueList->valueAt(0)->id == CSSValueNone) {
7453         addProperty(CSSPropertyWebkitAspectRatio, cssValuePool().createIdentifierValue(CSSValueNone), important);
7454         return true;
7455     }
7456
7457     if (num != 3)
7458         return false;
7459
7460     CSSParserValue* lvalue = m_valueList->valueAt(0);
7461     CSSParserValue* op = m_valueList->valueAt(1);
7462     CSSParserValue* rvalue = m_valueList->valueAt(2);
7463
7464     if (!isForwardSlashOperator(op))
7465         return false;
7466
7467     if (!validUnit(lvalue, FNumber | FNonNeg) || !validUnit(rvalue, FNumber | FNonNeg))
7468         return false;
7469
7470     if (!lvalue->fValue || !rvalue->fValue)
7471         return false;
7472
7473     addProperty(CSSPropertyWebkitAspectRatio, CSSAspectRatioValue::create(narrowPrecisionToFloat(lvalue->fValue), narrowPrecisionToFloat(rvalue->fValue)), important);
7474
7475     return true;
7476 }
7477
7478 bool BisonCSSParser::parseCounter(CSSPropertyID propId, int defaultValue, bool important)
7479 {
7480     enum { ID, VAL } state = ID;
7481
7482     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
7483     RefPtrWillBeRawPtr<CSSPrimitiveValue> counterName;
7484
7485     while (true) {
7486         CSSParserValue* val = m_valueList->current();
7487         switch (state) {
7488             case ID:
7489                 if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
7490                     counterName = createPrimitiveStringValue(val);
7491                     state = VAL;
7492                     m_valueList->next();
7493                     continue;
7494                 }
7495                 break;
7496             case VAL: {
7497                 int i = defaultValue;
7498                 if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
7499                     i = clampToInteger(val->fValue);
7500                     m_valueList->next();
7501                 }
7502
7503                 list->append(createPrimitiveValuePair(counterName.release(),
7504                     cssValuePool().createValue(i, CSSPrimitiveValue::CSS_NUMBER)));
7505                 state = ID;
7506                 continue;
7507             }
7508         }
7509         break;
7510     }
7511
7512     if (list->length() > 0) {
7513         addProperty(propId, list.release(), important);
7514         return true;
7515     }
7516
7517     return false;
7518 }
7519
7520 // This should go away once we drop support for -webkit-gradient
7521 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal)
7522 {
7523     RefPtrWillBeRawPtr<CSSPrimitiveValue> result;
7524     if (a->unit == CSSPrimitiveValue::CSS_IDENT) {
7525         if ((equalIgnoringCase(a, "left") && horizontal)
7526             || (equalIgnoringCase(a, "top") && !horizontal))
7527             result = cssValuePool().createValue(0., CSSPrimitiveValue::CSS_PERCENTAGE);
7528         else if ((equalIgnoringCase(a, "right") && horizontal)
7529                  || (equalIgnoringCase(a, "bottom") && !horizontal))
7530             result = cssValuePool().createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE);
7531         else if (equalIgnoringCase(a, "center"))
7532             result = cssValuePool().createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE);
7533     } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
7534         result = cssValuePool().createValue(a->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(a->unit));
7535     return result;
7536 }
7537
7538 static bool parseDeprecatedGradientColorStop(BisonCSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop)
7539 {
7540     if (a->unit != CSSParserValue::Function)
7541         return false;
7542
7543     if (!equalIgnoringCase(a->function->name, "from(") &&
7544         !equalIgnoringCase(a->function->name, "to(") &&
7545         !equalIgnoringCase(a->function->name, "color-stop("))
7546         return false;
7547
7548     CSSParserValueList* args = a->function->args.get();
7549     if (!args)
7550         return false;
7551
7552     if (equalIgnoringCase(a->function->name, "from(")
7553         || equalIgnoringCase(a->function->name, "to(")) {
7554         // The "from" and "to" stops expect 1 argument.
7555         if (args->size() != 1)
7556             return false;
7557
7558         if (equalIgnoringCase(a->function->name, "from("))
7559             stop.m_position = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER);
7560         else
7561             stop.m_position = cssValuePool().createValue(1, CSSPrimitiveValue::CSS_NUMBER);
7562
7563         CSSValueID id = args->current()->id;
7564         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
7565             stop.m_color = cssValuePool().createIdentifierValue(id);
7566         else
7567             stop.m_color = p->parseColor(args->current());
7568         if (!stop.m_color)
7569             return false;
7570     }
7571
7572     // The "color-stop" function expects 3 arguments.
7573     if (equalIgnoringCase(a->function->name, "color-stop(")) {
7574         if (args->size() != 3)
7575             return false;
7576
7577         CSSParserValue* stopArg = args->current();
7578         if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
7579             stop.m_position = cssValuePool().createValue(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER);
7580         else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER)
7581             stop.m_position = cssValuePool().createValue(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER);
7582         else
7583             return false;
7584
7585         stopArg = args->next();
7586         if (stopArg->unit != CSSParserValue::Operator || stopArg->iValue != ',')
7587             return false;
7588
7589         stopArg = args->next();
7590         CSSValueID id = stopArg->id;
7591         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
7592             stop.m_color = cssValuePool().createIdentifierValue(id);
7593         else
7594             stop.m_color = p->parseColor(stopArg);
7595         if (!stop.m_color)
7596             return false;
7597     }
7598
7599     return true;
7600 }
7601
7602 bool BisonCSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient)
7603 {
7604     // Walk the arguments.
7605     CSSParserValueList* args = valueList->current()->function->args.get();
7606     if (!args || args->size() == 0)
7607         return false;
7608
7609     // The first argument is the gradient type.  It is an identifier.
7610     CSSGradientType gradientType;
7611     CSSParserValue* a = args->current();
7612     if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT)
7613         return false;
7614     if (equalIgnoringCase(a, "linear"))
7615         gradientType = CSSDeprecatedLinearGradient;
7616     else if (equalIgnoringCase(a, "radial"))
7617         gradientType = CSSDeprecatedRadialGradient;
7618     else
7619         return false;
7620
7621     RefPtr<CSSGradientValue> result;
7622     switch (gradientType) {
7623     case CSSDeprecatedLinearGradient:
7624         result = CSSLinearGradientValue::create(NonRepeating, gradientType);
7625         break;
7626     case CSSDeprecatedRadialGradient:
7627         result = CSSRadialGradientValue::create(NonRepeating, gradientType);
7628         break;
7629     default:
7630         // The rest of the gradient types shouldn't appear here.
7631         ASSERT_NOT_REACHED();
7632     }
7633
7634     // Comma.
7635     a = args->next();
7636     if (!isComma(a))
7637         return false;
7638
7639     // Next comes the starting point for the gradient as an x y pair.  There is no
7640     // comma between the x and the y values.
7641     // First X.  It can be left, right, number or percent.
7642     a = args->next();
7643     if (!a)
7644         return false;
7645     RefPtrWillBeRawPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true);
7646     if (!point)
7647         return false;
7648     result->setFirstX(point.release());
7649
7650     // First Y.  It can be top, bottom, number or percent.
7651     a = args->next();
7652     if (!a)
7653         return false;
7654     point = parseDeprecatedGradientPoint(a, false);
7655     if (!point)
7656         return false;
7657     result->setFirstY(point.release());
7658
7659     // Comma after the first point.
7660     a = args->next();
7661     if (!isComma(a))
7662         return false;
7663
7664     // For radial gradients only, we now expect a numeric radius.
7665     if (gradientType == CSSDeprecatedRadialGradient) {
7666         a = args->next();
7667         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
7668             return false;
7669         toCSSRadialGradientValue(result.get())->setFirstRadius(createPrimitiveNumericValue(a));
7670
7671         // Comma after the first radius.
7672         a = args->next();
7673         if (!isComma(a))
7674             return false;
7675     }
7676
7677     // Next is the ending point for the gradient as an x, y pair.
7678     // Second X.  It can be left, right, number or percent.
7679     a = args->next();
7680     if (!a)
7681         return false;
7682     point = parseDeprecatedGradientPoint(a, true);
7683     if (!point)
7684         return false;
7685     result->setSecondX(point.release());
7686
7687     // Second Y.  It can be top, bottom, number or percent.
7688     a = args->next();
7689     if (!a)
7690         return false;
7691     point = parseDeprecatedGradientPoint(a, false);
7692     if (!point)
7693         return false;
7694     result->setSecondY(point.release());
7695
7696     // For radial gradients only, we now expect the second radius.
7697     if (gradientType == CSSDeprecatedRadialGradient) {
7698         // Comma after the second point.
7699         a = args->next();
7700         if (!isComma(a))
7701             return false;
7702
7703         a = args->next();
7704         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
7705             return false;
7706         toCSSRadialGradientValue(result.get())->setSecondRadius(createPrimitiveNumericValue(a));
7707     }
7708
7709     // We now will accept any number of stops (0 or more).
7710     a = args->next();
7711     while (a) {
7712         // Look for the comma before the next stop.
7713         if (!isComma(a))
7714             return false;
7715
7716         // Now examine the stop itself.
7717         a = args->next();
7718         if (!a)
7719             return false;
7720
7721         // The function name needs to be one of "from", "to", or "color-stop."
7722         CSSGradientColorStop stop;
7723         if (!parseDeprecatedGradientColorStop(this, a, stop))
7724             return false;
7725         result->addStop(stop);
7726
7727         // Advance
7728         a = args->next();
7729     }
7730
7731     gradient = result.release();
7732     return true;
7733 }
7734
7735 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal)
7736 {
7737     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
7738         return 0;
7739
7740     switch (a->id) {
7741         case CSSValueLeft:
7742         case CSSValueRight:
7743             isHorizontal = true;
7744             break;
7745         case CSSValueTop:
7746         case CSSValueBottom:
7747             isHorizontal = false;
7748             break;
7749         default:
7750             return 0;
7751     }
7752     return cssValuePool().createIdentifierValue(a->id);
7753 }
7754
7755 static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(BisonCSSParser* p, CSSParserValue* value)
7756 {
7757     CSSValueID id = value->id;
7758     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor)
7759         return cssValuePool().createIdentifierValue(id);
7760
7761     return p->parseColor(value);
7762 }
7763
7764 bool BisonCSSParser::parseDeprecatedLinearGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
7765 {
7766     RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, CSSPrefixedLinearGradient);
7767
7768     // Walk the arguments.
7769     CSSParserValueList* args = valueList->current()->function->args.get();
7770     if (!args || !args->size())
7771         return false;
7772
7773     CSSParserValue* a = args->current();
7774     if (!a)
7775         return false;
7776
7777     bool expectComma = false;
7778     // Look for angle.
7779     if (validUnit(a, FAngle, HTMLStandardMode)) {
7780         result->setAngle(createPrimitiveNumericValue(a));
7781
7782         args->next();
7783         expectComma = true;
7784     } else {
7785         // Look one or two optional keywords that indicate a side or corner.
7786         RefPtrWillBeRawPtr<CSSPrimitiveValue> startX, startY;
7787
7788         RefPtrWillBeRawPtr<CSSPrimitiveValue> location;
7789         bool isHorizontal = false;
7790         if ((location = valueFromSideKeyword(a, isHorizontal))) {
7791             if (isHorizontal)
7792                 startX = location;
7793             else
7794                 startY = location;
7795
7796             if ((a = args->next())) {
7797                 if ((location = valueFromSideKeyword(a, isHorizontal))) {
7798                     if (isHorizontal) {
7799                         if (startX)
7800                             return false;
7801                         startX = location;
7802                     } else {
7803                         if (startY)
7804                             return false;
7805                         startY = location;
7806                     }
7807
7808                     args->next();
7809                 }
7810             }
7811
7812             expectComma = true;
7813         }
7814
7815         if (!startX && !startY)
7816             startY = cssValuePool().createIdentifierValue(CSSValueTop);
7817
7818         result->setFirstX(startX.release());
7819         result->setFirstY(startY.release());
7820     }
7821
7822     if (!parseGradientColorStops(args, result.get(), expectComma))
7823         return false;
7824
7825     if (!result->stopCount())
7826         return false;
7827
7828     gradient = result.release();
7829     return true;
7830 }
7831
7832 bool BisonCSSParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
7833 {
7834     RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSPrefixedRadialGradient);
7835
7836     // Walk the arguments.
7837     CSSParserValueList* args = valueList->current()->function->args.get();
7838     if (!args || !args->size())
7839         return false;
7840
7841     CSSParserValue* a = args->current();
7842     if (!a)
7843         return false;
7844
7845     bool expectComma = false;
7846
7847     // Optional background-position
7848     RefPtr<CSSValue> centerX;
7849     RefPtr<CSSValue> centerY;
7850     // parse2ValuesFillPosition advances the args next pointer.
7851     parse2ValuesFillPosition(args, centerX, centerY);
7852     a = args->current();
7853     if (!a)
7854         return false;
7855
7856     if (centerX || centerY) {
7857         // Comma
7858         if (!isComma(a))
7859             return false;
7860
7861         a = args->next();
7862         if (!a)
7863             return false;
7864     }
7865
7866     result->setFirstX(toCSSPrimitiveValue(centerX.get()));
7867     result->setSecondX(toCSSPrimitiveValue(centerX.get()));
7868     // CSS3 radial gradients always share the same start and end point.
7869     result->setFirstY(toCSSPrimitiveValue(centerY.get()));
7870     result->setSecondY(toCSSPrimitiveValue(centerY.get()));
7871
7872     RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue;
7873     RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeValue;
7874
7875     // Optional shape and/or size in any order.
7876     for (int i = 0; i < 2; ++i) {
7877         if (a->unit != CSSPrimitiveValue::CSS_IDENT)
7878             break;
7879
7880         bool foundValue = false;
7881         switch (a->id) {
7882         case CSSValueCircle:
7883         case CSSValueEllipse:
7884             shapeValue = cssValuePool().createIdentifierValue(a->id);
7885             foundValue = true;
7886             break;
7887         case CSSValueClosestSide:
7888         case CSSValueClosestCorner:
7889         case CSSValueFarthestSide:
7890         case CSSValueFarthestCorner:
7891         case CSSValueContain:
7892         case CSSValueCover:
7893             sizeValue = cssValuePool().createIdentifierValue(a->id);
7894             foundValue = true;
7895             break;
7896         default:
7897             break;
7898         }
7899
7900         if (foundValue) {
7901             a = args->next();
7902             if (!a)
7903                 return false;
7904
7905             expectComma = true;
7906         }
7907     }
7908
7909     result->setShape(shapeValue);
7910     result->setSizingBehavior(sizeValue);
7911
7912     // Or, two lengths or percentages
7913     RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize;
7914     RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize;
7915
7916     if (!shapeValue && !sizeValue) {
7917         if (validUnit(a, FLength | FPercent)) {
7918             horizontalSize = createPrimitiveNumericValue(a);
7919             a = args->next();
7920             if (!a)
7921                 return false;
7922
7923             expectComma = true;
7924         }
7925
7926         if (validUnit(a, FLength | FPercent)) {
7927             verticalSize = createPrimitiveNumericValue(a);
7928
7929             a = args->next();
7930             if (!a)
7931                 return false;
7932             expectComma = true;
7933         }
7934     }
7935
7936     // Must have neither or both.
7937     if (!horizontalSize != !verticalSize)
7938         return false;
7939
7940     result->setEndHorizontalSize(horizontalSize);
7941     result->setEndVerticalSize(verticalSize);
7942
7943     if (!parseGradientColorStops(args, result.get(), expectComma))
7944         return false;
7945
7946     gradient = result.release();
7947     return true;
7948 }
7949
7950 bool BisonCSSParser::parseLinearGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
7951 {
7952     RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, CSSLinearGradient);
7953
7954     CSSParserValueList* args = valueList->current()->function->args.get();
7955     if (!args || !args->size())
7956         return false;
7957
7958     CSSParserValue* a = args->current();
7959     if (!a)
7960         return false;
7961
7962     bool expectComma = false;
7963     // Look for angle.
7964     if (validUnit(a, FAngle, HTMLStandardMode)) {
7965         result->setAngle(createPrimitiveNumericValue(a));
7966
7967         args->next();
7968         expectComma = true;
7969     } else if (a->unit == CSSPrimitiveValue::CSS_IDENT && equalIgnoringCase(a, "to")) {
7970         // to [ [left | right] || [top | bottom] ]
7971         a = args->next();
7972         if (!a)
7973             return false;
7974
7975         RefPtrWillBeRawPtr<CSSPrimitiveValue> endX, endY;
7976         RefPtrWillBeRawPtr<CSSPrimitiveValue> location;
7977         bool isHorizontal = false;
7978
7979         location = valueFromSideKeyword(a, isHorizontal);
7980         if (!location)
7981             return false;
7982
7983         if (isHorizontal)
7984             endX = location;
7985         else
7986             endY = location;
7987
7988         a = args->next();
7989         if (!a)
7990             return false;
7991
7992         location = valueFromSideKeyword(a, isHorizontal);
7993         if (location) {
7994             if (isHorizontal) {
7995                 if (endX)
7996                     return false;
7997                 endX = location;
7998             } else {
7999                 if (endY)
8000                     return false;
8001                 endY = location;
8002             }
8003
8004             args->next();
8005         }
8006
8007         expectComma = true;
8008         result->setFirstX(endX.release());
8009         result->setFirstY(endY.release());
8010     }
8011
8012     if (!parseGradientColorStops(args, result.get(), expectComma))
8013         return false;
8014
8015     if (!result->stopCount())
8016         return false;
8017
8018     gradient = result.release();
8019     return true;
8020 }
8021
8022 bool BisonCSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
8023 {
8024     RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSRadialGradient);
8025
8026     CSSParserValueList* args = valueList->current()->function->args.get();
8027     if (!args || !args->size())
8028         return false;
8029
8030     CSSParserValue* a = args->current();
8031     if (!a)
8032         return false;
8033
8034     bool expectComma = false;
8035
8036     RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue;
8037     RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeValue;
8038     RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize;
8039     RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize;
8040
8041     // First part of grammar, the size/shape clause:
8042     // [ circle || <length> ] |
8043     // [ ellipse || [ <length> | <percentage> ]{2} ] |
8044     // [ [ circle | ellipse] || <size-keyword> ]
8045     for (int i = 0; i < 3; ++i) {
8046         if (a->unit == CSSPrimitiveValue::CSS_IDENT) {
8047             bool badIdent = false;
8048             switch (a->id) {
8049             case CSSValueCircle:
8050             case CSSValueEllipse:
8051                 if (shapeValue)
8052                     return false;
8053                 shapeValue = cssValuePool().createIdentifierValue(a->id);
8054                 break;
8055             case CSSValueClosestSide:
8056             case CSSValueClosestCorner:
8057             case CSSValueFarthestSide:
8058             case CSSValueFarthestCorner:
8059                 if (sizeValue || horizontalSize)
8060                     return false;
8061                 sizeValue = cssValuePool().createIdentifierValue(a->id);
8062                 break;
8063             default:
8064                 badIdent = true;
8065             }
8066
8067             if (badIdent)
8068                 break;
8069
8070             a = args->next();
8071             if (!a)
8072                 return false;
8073         } else if (validUnit(a, FLength | FPercent)) {
8074
8075             if (sizeValue || horizontalSize)
8076                 return false;
8077             horizontalSize = createPrimitiveNumericValue(a);
8078
8079             a = args->next();
8080             if (!a)
8081                 return false;
8082
8083             if (validUnit(a, FLength | FPercent)) {
8084                 verticalSize = createPrimitiveNumericValue(a);
8085                 ++i;
8086                 a = args->next();
8087                 if (!a)
8088                     return false;
8089             }
8090         } else
8091             break;
8092     }
8093
8094     // You can specify size as a keyword or a length/percentage, not both.
8095     if (sizeValue && horizontalSize)
8096         return false;
8097     // Circles must have 0 or 1 lengths.
8098     if (shapeValue && shapeValue->getValueID() == CSSValueCircle && verticalSize)
8099         return false;
8100     // Ellipses must have 0 or 2 length/percentages.
8101     if (shapeValue && shapeValue->getValueID() == CSSValueEllipse && horizontalSize && !verticalSize)
8102         return false;
8103     // If there's only one size, it must be a length.
8104     if (!verticalSize && horizontalSize && horizontalSize->isPercentage())
8105         return false;
8106
8107     result->setShape(shapeValue);
8108     result->setSizingBehavior(sizeValue);
8109     result->setEndHorizontalSize(horizontalSize);
8110     result->setEndVerticalSize(verticalSize);
8111
8112     // Second part of grammar, the center-position clause:
8113     // at <position>
8114     RefPtr<CSSValue> centerX;
8115     RefPtr<CSSValue> centerY;
8116     if (a->unit == CSSPrimitiveValue::CSS_IDENT && equalIgnoringCase(a, "at")) {
8117         a = args->next();
8118         if (!a)
8119             return false;
8120
8121         parseFillPosition(args, centerX, centerY);
8122         if (!(centerX && centerY))
8123             return false;
8124
8125         a = args->current();
8126         if (!a)
8127             return false;
8128         result->setFirstX(toCSSPrimitiveValue(centerX.get()));
8129         result->setFirstY(toCSSPrimitiveValue(centerY.get()));
8130         // Right now, CSS radial gradients have the same start and end centers.
8131         result->setSecondX(toCSSPrimitiveValue(centerX.get()));
8132         result->setSecondY(toCSSPrimitiveValue(centerY.get()));
8133     }
8134
8135     if (shapeValue || sizeValue || horizontalSize || centerX || centerY)
8136         expectComma = true;
8137
8138     if (!parseGradientColorStops(args, result.get(), expectComma))
8139         return false;
8140
8141     gradient = result.release();
8142     return true;
8143 }
8144
8145 bool BisonCSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradientValue* gradient, bool expectComma)
8146 {
8147     CSSParserValue* a = valueList->current();
8148
8149     // Now look for color stops.
8150     while (a) {
8151         // Look for the comma before the next stop.
8152         if (expectComma) {
8153             if (!isComma(a))
8154                 return false;
8155
8156             a = valueList->next();
8157             if (!a)
8158                 return false;
8159         }
8160
8161         // <color-stop> = <color> [ <percentage> | <length> ]?
8162         CSSGradientColorStop stop;
8163         stop.m_color = parseGradientColorOrKeyword(this, a);
8164         if (!stop.m_color)
8165             return false;
8166
8167         a = valueList->next();
8168         if (a) {
8169             if (validUnit(a, FLength | FPercent)) {
8170                 stop.m_position = createPrimitiveNumericValue(a);
8171                 a = valueList->next();
8172             }
8173         }
8174
8175         gradient->addStop(stop);
8176         expectComma = true;
8177     }
8178
8179     // Must have 2 or more stops to be valid.
8180     return gradient->stopCount() >= 2;
8181 }
8182
8183 bool BisonCSSParser::parseGeneratedImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
8184 {
8185     CSSParserValue* val = valueList->current();
8186
8187     if (val->unit != CSSParserValue::Function)
8188         return false;
8189
8190     if (equalIgnoringCase(val->function->name, "-webkit-gradient(")) {
8191         // FIXME: This should send a deprecation message.
8192         if (m_context.useCounter())
8193             m_context.useCounter()->count(UseCounter::DeprecatedWebKitGradient);
8194         return parseDeprecatedGradient(valueList, value);
8195     }
8196
8197     if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")) {
8198         // FIXME: This should send a deprecation message.
8199         if (m_context.useCounter())
8200             m_context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradient);
8201         return parseDeprecatedLinearGradient(valueList, value, NonRepeating);
8202     }
8203
8204     if (equalIgnoringCase(val->function->name, "linear-gradient("))
8205         return parseLinearGradient(valueList, value, NonRepeating);
8206
8207     if (equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")) {
8208         // FIXME: This should send a deprecation message.
8209         if (m_context.useCounter())
8210             m_context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLinearGradient);
8211         return parseDeprecatedLinearGradient(valueList, value, Repeating);
8212     }
8213
8214     if (equalIgnoringCase(val->function->name, "repeating-linear-gradient("))
8215         return parseLinearGradient(valueList, value, Repeating);
8216
8217     if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")) {
8218         // FIXME: This should send a deprecation message.
8219         if (m_context.useCounter())
8220             m_context.useCounter()->count(UseCounter::DeprecatedWebKitRadialGradient);
8221         return parseDeprecatedRadialGradient(valueList, value, NonRepeating);
8222     }
8223
8224     if (equalIgnoringCase(val->function->name, "radial-gradient("))
8225         return parseRadialGradient(valueList, value, NonRepeating);
8226
8227     if (equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")) {
8228         if (m_context.useCounter())
8229             m_context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingRadialGradient);
8230         return parseDeprecatedRadialGradient(valueList, value, Repeating);
8231     }
8232
8233     if (equalIgnoringCase(val->function->name, "repeating-radial-gradient("))
8234         return parseRadialGradient(valueList, value, Repeating);
8235
8236     if (equalIgnoringCase(val->function->name, "-webkit-canvas("))
8237         return parseCanvas(valueList, value);
8238
8239     if (equalIgnoringCase(val->function->name, "-webkit-cross-fade("))
8240         return parseCrossfade(valueList, value);
8241
8242     return false;
8243 }
8244
8245 bool BisonCSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& crossfade)
8246 {
8247     // Walk the arguments.
8248     CSSParserValueList* args = valueList->current()->function->args.get();
8249     if (!args || args->size() != 5)
8250         return false;
8251     CSSParserValue* a = args->current();
8252     RefPtr<CSSValue> fromImageValue;
8253     RefPtr<CSSValue> toImageValue;
8254
8255     // The first argument is the "from" image. It is a fill image.
8256     if (!a || !parseFillImage(args, fromImageValue))
8257         return false;
8258     a = args->next();
8259
8260     // Skip a comma
8261     if (!isComma(a))
8262         return false;
8263     a = args->next();
8264
8265     // The second argument is the "to" image. It is a fill image.
8266     if (!a || !parseFillImage(args, toImageValue))
8267         return false;
8268     a = args->next();
8269
8270     // Skip a comma
8271     if (!isComma(a))
8272         return false;
8273     a = args->next();
8274
8275     // The third argument is the crossfade value. It is a percentage or a fractional number.
8276     RefPtrWillBeRawPtr<CSSPrimitiveValue> percentage;
8277     if (!a)
8278         return false;
8279
8280     if (a->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
8281         percentage = cssValuePool().createValue(clampTo<double>(a->fValue / 100, 0, 1), CSSPrimitiveValue::CSS_NUMBER);
8282     else if (a->unit == CSSPrimitiveValue::CSS_NUMBER)
8283         percentage = cssValuePool().createValue(clampTo<double>(a->fValue, 0, 1), CSSPrimitiveValue::CSS_NUMBER);
8284     else
8285         return false;
8286
8287     RefPtrWillBeRawPtr<CSSCrossfadeValue> result = CSSCrossfadeValue::create(fromImageValue, toImageValue);
8288     result->setPercentage(percentage);
8289
8290     crossfade = result;
8291
8292     return true;
8293 }
8294
8295 bool BisonCSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& canvas)
8296 {
8297     // Walk the arguments.
8298     CSSParserValueList* args = valueList->current()->function->args.get();
8299     if (!args || args->size() != 1)
8300         return false;
8301
8302     // The first argument is the canvas name.  It is an identifier.
8303     CSSParserValue* value = args->current();
8304     if (!value || value->unit != CSSPrimitiveValue::CSS_IDENT)
8305         return false;
8306
8307     canvas = CSSCanvasValue::create(value->string);
8308     return true;
8309 }
8310
8311 PassRefPtr<CSSValue> BisonCSSParser::parseImageSet(CSSParserValueList* valueList)
8312 {
8313     CSSParserValue* function = valueList->current();
8314
8315     if (function->unit != CSSParserValue::Function)
8316         return 0;
8317
8318     CSSParserValueList* functionArgs = valueList->current()->function->args.get();
8319     if (!functionArgs || !functionArgs->size() || !functionArgs->current())
8320         return 0;
8321
8322     RefPtrWillBeRawPtr<CSSImageSetValue> imageSet = CSSImageSetValue::create();
8323
8324     CSSParserValue* arg = functionArgs->current();
8325     while (arg) {
8326         if (arg->unit != CSSPrimitiveValue::CSS_URI)
8327             return 0;
8328
8329         RefPtr<CSSImageValue> image = CSSImageValue::create(completeURL(arg->string));
8330         imageSet->append(image);
8331
8332         arg = functionArgs->next();
8333         if (!arg || arg->unit != CSSPrimitiveValue::CSS_DIMENSION)
8334             return 0;
8335
8336         double imageScaleFactor = 0;
8337         const String& string = arg->string;
8338         unsigned length = string.length();
8339         if (!length)
8340             return 0;
8341         if (string.is8Bit()) {
8342             const LChar* start = string.characters8();
8343             parseDouble(start, start + length, 'x', imageScaleFactor);
8344         } else {
8345             const UChar* start = string.characters16();
8346             parseDouble(start, start + length, 'x', imageScaleFactor);
8347         }
8348         if (imageScaleFactor <= 0)
8349             return 0;
8350         imageSet->append(cssValuePool().createValue(imageScaleFactor, CSSPrimitiveValue::CSS_NUMBER));
8351
8352         // If there are no more arguments, we're done.
8353         arg = functionArgs->next();
8354         if (!arg)
8355             break;
8356
8357         // If there are more arguments, they should be after a comma.
8358         if (!isComma(arg))
8359             return 0;
8360
8361         // Skip the comma and move on to the next argument.
8362         arg = functionArgs->next();
8363     }
8364
8365     return imageSet.release();
8366 }
8367
8368 class TransformOperationInfo {
8369 public:
8370     TransformOperationInfo(const CSSParserString& name)
8371         : m_type(CSSTransformValue::UnknownTransformOperation)
8372         , m_argCount(1)
8373         , m_allowSingleArgument(false)
8374         , m_unit(BisonCSSParser::FUnknown)
8375     {
8376         const UChar* characters;
8377         unsigned nameLength = name.length();
8378
8379         const unsigned longestNameLength = 12;
8380         UChar characterBuffer[longestNameLength];
8381         if (name.is8Bit()) {
8382             unsigned length = std::min(longestNameLength, nameLength);
8383             const LChar* characters8 = name.characters8();
8384             for (unsigned i = 0; i < length; ++i)
8385                 characterBuffer[i] = characters8[i];
8386             characters = characterBuffer;
8387         } else
8388             characters = name.characters16();
8389
8390         SWITCH(characters, nameLength) {
8391             CASE("skew(") {
8392                 m_unit = BisonCSSParser::FAngle;
8393                 m_type = CSSTransformValue::SkewTransformOperation;
8394                 m_allowSingleArgument = true;
8395                 m_argCount = 3;
8396             }
8397             CASE("scale(") {
8398                 m_unit = BisonCSSParser::FNumber;
8399                 m_type = CSSTransformValue::ScaleTransformOperation;
8400                 m_allowSingleArgument = true;
8401                 m_argCount = 3;
8402             }
8403             CASE("skewx(") {
8404                 m_unit = BisonCSSParser::FAngle;
8405                 m_type = CSSTransformValue::SkewXTransformOperation;
8406             }
8407             CASE("skewy(") {
8408                 m_unit = BisonCSSParser::FAngle;
8409                 m_type = CSSTransformValue::SkewYTransformOperation;
8410             }
8411             CASE("matrix(") {
8412                 m_unit = BisonCSSParser::FNumber;
8413                 m_type = CSSTransformValue::MatrixTransformOperation;
8414                 m_argCount = 11;
8415             }
8416             CASE("rotate(") {
8417                 m_unit = BisonCSSParser::FAngle;
8418                 m_type = CSSTransformValue::RotateTransformOperation;
8419             }
8420             CASE("scalex(") {
8421                 m_unit = BisonCSSParser::FNumber;
8422                 m_type = CSSTransformValue::ScaleXTransformOperation;
8423             }
8424             CASE("scaley(") {
8425                 m_unit = BisonCSSParser::FNumber;
8426                 m_type = CSSTransformValue::ScaleYTransformOperation;
8427             }
8428             CASE("scalez(") {
8429                 m_unit = BisonCSSParser::FNumber;
8430                 m_type = CSSTransformValue::ScaleZTransformOperation;
8431             }
8432             CASE("scale3d(") {
8433                 m_unit = BisonCSSParser::FNumber;
8434                 m_type = CSSTransformValue::Scale3DTransformOperation;
8435                 m_argCount = 5;
8436             }
8437             CASE("rotatex(") {
8438                 m_unit = BisonCSSParser::FAngle;
8439                 m_type = CSSTransformValue::RotateXTransformOperation;
8440             }
8441             CASE("rotatey(") {
8442                 m_unit = BisonCSSParser::FAngle;
8443                 m_type = CSSTransformValue::RotateYTransformOperation;
8444             }
8445             CASE("rotatez(") {
8446                 m_unit = BisonCSSParser::FAngle;
8447                 m_type = CSSTransformValue::RotateZTransformOperation;
8448             }
8449             CASE("matrix3d(") {
8450                 m_unit = BisonCSSParser::FNumber;
8451                 m_type = CSSTransformValue::Matrix3DTransformOperation;
8452                 m_argCount = 31;
8453             }
8454             CASE("rotate3d(") {
8455                 m_unit = BisonCSSParser::FNumber;
8456                 m_type = CSSTransformValue::Rotate3DTransformOperation;
8457                 m_argCount = 7;
8458             }
8459             CASE("translate(") {
8460                 m_unit = BisonCSSParser::FLength | BisonCSSParser::FPercent;
8461                 m_type = CSSTransformValue::TranslateTransformOperation;
8462                 m_allowSingleArgument = true;
8463                 m_argCount = 3;
8464             }
8465             CASE("translatex(") {
8466                 m_unit = BisonCSSParser::FLength | BisonCSSParser::FPercent;
8467                 m_type = CSSTransformValue::TranslateXTransformOperation;
8468             }
8469             CASE("translatey(") {
8470                 m_unit = BisonCSSParser::FLength | BisonCSSParser::FPercent;
8471                 m_type = CSSTransformValue::TranslateYTransformOperation;
8472             }
8473             CASE("translatez(") {
8474                 m_unit = BisonCSSParser::FLength | BisonCSSParser::FPercent;
8475                 m_type = CSSTransformValue::TranslateZTransformOperation;
8476             }
8477             CASE("perspective(") {
8478                 m_unit = BisonCSSParser::FNumber;
8479                 m_type = CSSTransformValue::PerspectiveTransformOperation;
8480             }
8481             CASE("translate3d(") {
8482                 m_unit = BisonCSSParser::FLength | BisonCSSParser::FPercent;
8483                 m_type = CSSTransformValue::Translate3DTransformOperation;
8484                 m_argCount = 5;
8485             }
8486         }
8487     }
8488
8489     CSSTransformValue::TransformOperationType type() const { return m_type; }
8490     unsigned argCount() const { return m_argCount; }
8491     BisonCSSParser::Units unit() const { return m_unit; }
8492
8493     bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
8494     bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
8495
8496 private:
8497     CSSTransformValue::TransformOperationType m_type;
8498     unsigned m_argCount;
8499     bool m_allowSingleArgument;
8500     BisonCSSParser::Units m_unit;
8501 };
8502
8503 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseTransform()
8504 {
8505     if (!m_valueList)
8506         return 0;
8507
8508     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
8509     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
8510         RefPtr<CSSValue> parsedTransformValue = parseTransformValue(value);
8511         if (!parsedTransformValue)
8512             return 0;
8513
8514         list->append(parsedTransformValue.release());
8515     }
8516
8517     return list.release();
8518 }
8519
8520 PassRefPtr<CSSValue> BisonCSSParser::parseTransformValue(CSSParserValue *value)
8521 {
8522     if (value->unit != CSSParserValue::Function || !value->function)
8523         return 0;
8524
8525     // Every primitive requires at least one argument.
8526     CSSParserValueList* args = value->function->args.get();
8527     if (!args)
8528         return 0;
8529
8530     // See if the specified primitive is one we understand.
8531     TransformOperationInfo info(value->function->name);
8532     if (info.unknown())
8533         return 0;
8534
8535     if (!info.hasCorrectArgCount(args->size()))
8536         return 0;
8537
8538     // The transform is a list of functional primitives that specify transform operations.
8539     // We collect a list of CSSTransformValues, where each value specifies a single operation.
8540
8541     // Create the new CSSTransformValue for this operation and add it to our list.
8542     RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
8543
8544     // Snag our values.
8545     CSSParserValue* a = args->current();
8546     unsigned argNumber = 0;
8547     while (a) {
8548         BisonCSSParser::Units unit = info.unit();
8549
8550         if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
8551             // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
8552             if (!validUnit(a, FAngle, HTMLStandardMode))
8553                 return 0;
8554         } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
8555             // 3rd param of translate3d() cannot be a percentage
8556             if (!validUnit(a, FLength, HTMLStandardMode))
8557                 return 0;
8558         } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
8559             // 1st param of translateZ() cannot be a percentage
8560             if (!validUnit(a, FLength, HTMLStandardMode))
8561                 return 0;
8562         } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
8563             // 1st param of perspective() must be a non-negative number (deprecated) or length.
8564             if (!validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
8565                 return 0;
8566         } else if (!validUnit(a, unit, HTMLStandardMode))
8567             return 0;
8568
8569         // Add the value to the current transform operation.
8570         transformValue->append(createPrimitiveNumericValue(a));
8571
8572         a = args->next();
8573         if (!a)
8574             break;
8575         if (a->unit != CSSParserValue::Operator || a->iValue != ',')
8576             return 0;
8577         a = args->next();
8578
8579         argNumber++;
8580     }
8581
8582     return transformValue.release();
8583 }
8584
8585 bool BisonCSSParser::isBlendMode(CSSValueID valueID)
8586 {
8587     return (valueID >= CSSValueMultiply && valueID <= CSSValueLuminosity)
8588         || valueID == CSSValueNormal
8589         || valueID == CSSValueOverlay;
8590 }
8591
8592 bool BisonCSSParser::isCompositeOperator(CSSValueID valueID)
8593 {
8594     // FIXME: Add CSSValueDestination and CSSValueLighter when the Compositing spec updates.
8595     return valueID >= CSSValueClear && valueID <= CSSValueXor;
8596 }
8597
8598 static void filterInfoForName(const CSSParserString& name, CSSFilterValue::FilterOperationType& filterType, unsigned& maximumArgumentCount)
8599 {
8600     if (equalIgnoringCase(name, "grayscale("))
8601         filterType = CSSFilterValue::GrayscaleFilterOperation;
8602     else if (equalIgnoringCase(name, "sepia("))
8603         filterType = CSSFilterValue::SepiaFilterOperation;
8604     else if (equalIgnoringCase(name, "saturate("))
8605         filterType = CSSFilterValue::SaturateFilterOperation;
8606     else if (equalIgnoringCase(name, "hue-rotate("))
8607         filterType = CSSFilterValue::HueRotateFilterOperation;
8608     else if (equalIgnoringCase(name, "invert("))
8609         filterType = CSSFilterValue::InvertFilterOperation;
8610     else if (equalIgnoringCase(name, "opacity("))
8611         filterType = CSSFilterValue::OpacityFilterOperation;
8612     else if (equalIgnoringCase(name, "brightness("))
8613         filterType = CSSFilterValue::BrightnessFilterOperation;
8614     else if (equalIgnoringCase(name, "contrast("))
8615         filterType = CSSFilterValue::ContrastFilterOperation;
8616     else if (equalIgnoringCase(name, "blur("))
8617         filterType = CSSFilterValue::BlurFilterOperation;
8618     else if (equalIgnoringCase(name, "drop-shadow(")) {
8619         filterType = CSSFilterValue::DropShadowFilterOperation;
8620         maximumArgumentCount = 4;  // x-offset, y-offset, blur-radius, color -- spread and inset style not allowed.
8621     }
8622 }
8623
8624 PassRefPtrWillBeRawPtr<CSSFilterValue> BisonCSSParser::parseBuiltinFilterArguments(CSSParserValueList* args, CSSFilterValue::FilterOperationType filterType)
8625 {
8626     RefPtrWillBeRawPtr<CSSFilterValue> filterValue = CSSFilterValue::create(filterType);
8627     ASSERT(args);
8628
8629     switch (filterType) {
8630     case CSSFilterValue::GrayscaleFilterOperation:
8631     case CSSFilterValue::SepiaFilterOperation:
8632     case CSSFilterValue::SaturateFilterOperation:
8633     case CSSFilterValue::InvertFilterOperation:
8634     case CSSFilterValue::OpacityFilterOperation:
8635     case CSSFilterValue::ContrastFilterOperation: {
8636         // One optional argument, 0-1 or 0%-100%, if missing use 100%.
8637         if (args->size() > 1)
8638             return 0;
8639
8640         if (args->size()) {
8641             CSSParserValue* value = args->current();
8642             if (!validUnit(value, FNumber | FPercent | FNonNeg, HTMLStandardMode))
8643                 return 0;
8644
8645             double amount = value->fValue;
8646
8647             // Saturate and Contrast allow values over 100%.
8648             if (filterType != CSSFilterValue::SaturateFilterOperation
8649                 && filterType != CSSFilterValue::ContrastFilterOperation) {
8650                 double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0;
8651                 if (amount > maxAllowed)
8652                     return 0;
8653             }
8654
8655             filterValue->append(cssValuePool().createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
8656         }
8657         break;
8658     }
8659     case CSSFilterValue::BrightnessFilterOperation: {
8660         // One optional argument, if missing use 100%.
8661         if (args->size() > 1)
8662             return 0;
8663
8664         if (args->size()) {
8665             CSSParserValue* value = args->current();
8666             if (!validUnit(value, FNumber | FPercent, HTMLStandardMode))
8667                 return 0;
8668
8669             filterValue->append(cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
8670         }
8671         break;
8672     }
8673     case CSSFilterValue::HueRotateFilterOperation: {
8674         // hue-rotate() takes one optional angle.
8675         if (args->size() > 1)
8676             return 0;
8677
8678         if (args->size()) {
8679             CSSParserValue* argument = args->current();
8680             if (!validUnit(argument, FAngle, HTMLStandardMode))
8681                 return 0;
8682
8683             filterValue->append(createPrimitiveNumericValue(argument));
8684         }
8685         break;
8686     }
8687     case CSSFilterValue::BlurFilterOperation: {
8688         // Blur takes a single length. Zero parameters are allowed.
8689         if (args->size() > 1)
8690             return 0;
8691
8692         if (args->size()) {
8693             CSSParserValue* argument = args->current();
8694             if (!validUnit(argument, FLength | FNonNeg, HTMLStandardMode))
8695                 return 0;
8696
8697             filterValue->append(createPrimitiveNumericValue(argument));
8698         }
8699         break;
8700     }
8701     case CSSFilterValue::DropShadowFilterOperation: {
8702         // drop-shadow() takes a single shadow.
8703         RefPtrWillBeRawPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter);
8704         if (!shadowValueList || shadowValueList->length() != 1)
8705             return 0;
8706
8707         filterValue->append((shadowValueList.release())->itemWithoutBoundsCheck(0));
8708         break;
8709     }
8710     default:
8711         ASSERT_NOT_REACHED();
8712     }
8713     return filterValue.release();
8714 }
8715
8716 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFilter()
8717 {
8718     if (!m_valueList)
8719         return 0;
8720
8721     // The filter is a list of functional primitives that specify individual operations.
8722     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
8723     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
8724         if (value->unit != CSSPrimitiveValue::CSS_URI && (value->unit != CSSParserValue::Function || !value->function))
8725             return 0;
8726
8727         CSSFilterValue::FilterOperationType filterType = CSSFilterValue::UnknownFilterOperation;
8728
8729         // See if the specified primitive is one we understand.
8730         if (value->unit == CSSPrimitiveValue::CSS_URI) {
8731             RefPtrWillBeRawPtr<CSSFilterValue> referenceFilterValue = CSSFilterValue::create(CSSFilterValue::ReferenceFilterOperation);
8732             list->append(referenceFilterValue);
8733             referenceFilterValue->append(CSSSVGDocumentValue::create(value->string));
8734         } else {
8735             const CSSParserString name = value->function->name;
8736             unsigned maximumArgumentCount = 1;
8737
8738             filterInfoForName(name, filterType, maximumArgumentCount);
8739
8740             if (filterType == CSSFilterValue::UnknownFilterOperation)
8741                 return 0;
8742
8743             CSSParserValueList* args = value->function->args.get();
8744             if (!args)
8745                 return 0;
8746
8747             RefPtrWillBeRawPtr<CSSFilterValue> filterValue = parseBuiltinFilterArguments(args, filterType);
8748             if (!filterValue)
8749                 return 0;
8750
8751             list->append(filterValue);
8752         }
8753     }
8754
8755     return list.release();
8756 }
8757
8758 bool BisonCSSParser::parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
8759 {
8760     propId1 = propId;
8761     propId2 = propId;
8762     propId3 = propId;
8763     if (propId == CSSPropertyWebkitTransformOrigin) {
8764         propId1 = CSSPropertyWebkitTransformOriginX;
8765         propId2 = CSSPropertyWebkitTransformOriginY;
8766         propId3 = CSSPropertyWebkitTransformOriginZ;
8767     }
8768
8769     switch (propId) {
8770         case CSSPropertyWebkitTransformOrigin:
8771             if (!parseTransformOriginShorthand(value, value2, value3))
8772                 return false;
8773             // parseTransformOriginShorthand advances the m_valueList pointer
8774             break;
8775         case CSSPropertyWebkitTransformOriginX: {
8776             value = parseFillPositionX(m_valueList.get());
8777             if (value)
8778                 m_valueList->next();
8779             break;
8780         }
8781         case CSSPropertyWebkitTransformOriginY: {
8782             value = parseFillPositionY(m_valueList.get());
8783             if (value)
8784                 m_valueList->next();
8785             break;
8786         }
8787         case CSSPropertyWebkitTransformOriginZ: {
8788             if (validUnit(m_valueList->current(), FLength))
8789                 value = createPrimitiveNumericValue(m_valueList->current());
8790             if (value)
8791                 m_valueList->next();
8792             break;
8793         }
8794         default:
8795             ASSERT_NOT_REACHED();
8796             return false;
8797     }
8798
8799     return value;
8800 }
8801
8802 bool BisonCSSParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2)
8803 {
8804     propId1 = propId;
8805     propId2 = propId;
8806     if (propId == CSSPropertyWebkitPerspectiveOrigin) {
8807         propId1 = CSSPropertyWebkitPerspectiveOriginX;
8808         propId2 = CSSPropertyWebkitPerspectiveOriginY;
8809     }
8810
8811     switch (propId) {
8812         case CSSPropertyWebkitPerspectiveOrigin:
8813             if (m_valueList->size() > 2)
8814                 return false;
8815             parse2ValuesFillPosition(m_valueList.get(), value, value2);
8816             break;
8817         case CSSPropertyWebkitPerspectiveOriginX: {
8818             value = parseFillPositionX(m_valueList.get());
8819             if (value)
8820                 m_valueList->next();
8821             break;
8822         }
8823         case CSSPropertyWebkitPerspectiveOriginY: {
8824             value = parseFillPositionY(m_valueList.get());
8825             if (value)
8826                 m_valueList->next();
8827             break;
8828         }
8829         default:
8830             ASSERT_NOT_REACHED();
8831             return false;
8832     }
8833
8834     return value;
8835 }
8836
8837 bool BisonCSSParser::parseTouchAction(bool important)
8838 {
8839     if (!RuntimeEnabledFeatures::cssTouchActionEnabled())
8840         return false;
8841
8842     CSSParserValue* value = m_valueList->current();
8843     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
8844     if (m_valueList->size() == 1 && value && (value->id == CSSValueAuto || value->id == CSSValueNone)) {
8845         list->append(cssValuePool().createIdentifierValue(value->id));
8846         addProperty(CSSPropertyTouchAction, list.release(), important);
8847         m_valueList->next();
8848         return true;
8849     }
8850
8851     bool isValid = true;
8852     while (isValid && value) {
8853         switch (value->id) {
8854         case CSSValuePanX:
8855         case CSSValuePanY: {
8856             RefPtr<CSSValue> panValue = cssValuePool().createIdentifierValue(value->id);
8857             if (list->hasValue(panValue.get())) {
8858                 isValid = false;
8859                 break;
8860             }
8861             list->append(panValue.release());
8862             break;
8863         }
8864         default:
8865             isValid = false;
8866             break;
8867         }
8868         if (isValid)
8869             value = m_valueList->next();
8870     }
8871
8872     if (list->length() && isValid) {
8873         addProperty(CSSPropertyTouchAction, list.release(), important);
8874         return true;
8875     }
8876
8877     return false;
8878 }
8879
8880 void BisonCSSParser::addTextDecorationProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important)
8881 {
8882     // The text-decoration-line property takes priority over text-decoration, unless the latter has important priority set.
8883     if (propId == CSSPropertyTextDecoration && !important && !inShorthand()) {
8884         for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
8885             if (m_parsedProperties[i].id() == CSSPropertyTextDecorationLine)
8886                 return;
8887         }
8888     }
8889     addProperty(propId, value, important);
8890 }
8891
8892 bool BisonCSSParser::parseTextDecoration(CSSPropertyID propId, bool important)
8893 {
8894     if (propId == CSSPropertyTextDecorationLine
8895         && !RuntimeEnabledFeatures::css3TextDecorationsEnabled())
8896         return false;
8897
8898     CSSParserValue* value = m_valueList->current();
8899     if (value && value->id == CSSValueNone) {
8900         addTextDecorationProperty(propId, cssValuePool().createIdentifierValue(CSSValueNone), important);
8901         m_valueList->next();
8902         return true;
8903     }
8904
8905     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
8906     bool isValid = true;
8907     while (isValid && value) {
8908         switch (value->id) {
8909         case CSSValueUnderline:
8910         case CSSValueOverline:
8911         case CSSValueLineThrough:
8912         case CSSValueBlink:
8913             list->append(cssValuePool().createIdentifierValue(value->id));
8914             break;
8915         default:
8916             isValid = false;
8917             break;
8918         }
8919         if (isValid)
8920             value = m_valueList->next();
8921     }
8922
8923     // Values are either valid or in shorthand scope.
8924     if (list->length() && (isValid || inShorthand())) {
8925         addTextDecorationProperty(propId, list.release(), important);
8926         return true;
8927     }
8928
8929     return false;
8930 }
8931
8932 bool BisonCSSParser::parseTextUnderlinePosition(bool important)
8933 {
8934     // The text-underline-position property has syntax "auto | [ under || [ left | right ] ]".
8935     // However, values 'left' and 'right' are not implemented yet, so we will parse syntax
8936     // "auto | under" for now.
8937     CSSParserValue* value = m_valueList->current();
8938     switch (value->id) {
8939     case CSSValueAuto:
8940     case CSSValueUnder:
8941         if (m_valueList->next())
8942             return false;
8943         addProperty(CSSPropertyTextUnderlinePosition, cssValuePool().createIdentifierValue(value->id), important);
8944         return true;
8945     default:
8946         return false;
8947     }
8948 }
8949
8950 bool BisonCSSParser::parseTextEmphasisStyle(bool important)
8951 {
8952     unsigned valueListSize = m_valueList->size();
8953
8954     RefPtrWillBeRawPtr<CSSPrimitiveValue> fill;
8955     RefPtrWillBeRawPtr<CSSPrimitiveValue> shape;
8956
8957     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
8958         if (value->unit == CSSPrimitiveValue::CSS_STRING) {
8959             if (fill || shape || (valueListSize != 1 && !inShorthand()))
8960                 return false;
8961             addProperty(CSSPropertyWebkitTextEmphasisStyle, createPrimitiveStringValue(value), important);
8962             m_valueList->next();
8963             return true;
8964         }
8965
8966         if (value->id == CSSValueNone) {
8967             if (fill || shape || (valueListSize != 1 && !inShorthand()))
8968                 return false;
8969             addProperty(CSSPropertyWebkitTextEmphasisStyle, cssValuePool().createIdentifierValue(CSSValueNone), important);
8970             m_valueList->next();
8971             return true;
8972         }
8973
8974         if (value->id == CSSValueOpen || value->id == CSSValueFilled) {
8975             if (fill)
8976                 return false;
8977             fill = cssValuePool().createIdentifierValue(value->id);
8978         } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) {
8979             if (shape)
8980                 return false;
8981             shape = cssValuePool().createIdentifierValue(value->id);
8982         } else if (!inShorthand())
8983             return false;
8984         else
8985             break;
8986     }
8987
8988     if (fill && shape) {
8989         RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
8990         parsedValues->append(fill.release());
8991         parsedValues->append(shape.release());
8992         addProperty(CSSPropertyWebkitTextEmphasisStyle, parsedValues.release(), important);
8993         return true;
8994     }
8995     if (fill) {
8996         addProperty(CSSPropertyWebkitTextEmphasisStyle, fill.release(), important);
8997         return true;
8998     }
8999     if (shape) {
9000         addProperty(CSSPropertyWebkitTextEmphasisStyle, shape.release(), important);
9001         return true;
9002     }
9003
9004     return false;
9005 }
9006
9007 PassRefPtr<CSSValue> BisonCSSParser::parseTextIndent()
9008 {
9009     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
9010
9011     // <length> | <percentage> | inherit
9012     if (m_valueList->size() == 1) {
9013         CSSParserValue* value = m_valueList->current();
9014         if (!value->id && validUnit(value, FLength | FPercent)) {
9015             list->append(createPrimitiveNumericValue(value));
9016             m_valueList->next();
9017             return list.release();
9018         }
9019     }
9020
9021     if (!RuntimeEnabledFeatures::css3TextEnabled())
9022         return 0;
9023
9024     // The case where text-indent has only <length>(or <percentage>) value
9025     // is handled above if statement even though css3TextEnabled() returns true.
9026
9027     // [ [ <length> | <percentage> ] && each-line ] | inherit
9028     if (m_valueList->size() != 2)
9029         return 0;
9030
9031     CSSParserValue* firstValue = m_valueList->current();
9032     CSSParserValue* secondValue = m_valueList->next();
9033     CSSParserValue* lengthOrPercentageValue = 0;
9034
9035     // [ <length> | <percentage> ] each-line
9036     if (validUnit(firstValue, FLength | FPercent) && secondValue->id == CSSValueEachLine)
9037         lengthOrPercentageValue = firstValue;
9038     // each-line [ <length> | <percentage> ]
9039     else if (firstValue->id == CSSValueEachLine && validUnit(secondValue, FLength | FPercent))
9040         lengthOrPercentageValue = secondValue;
9041
9042     if (lengthOrPercentageValue) {
9043         list->append(createPrimitiveNumericValue(lengthOrPercentageValue));
9044         list->append(cssValuePool().createIdentifierValue(CSSValueEachLine));
9045         m_valueList->next();
9046         return list.release();
9047     }
9048
9049     return 0;
9050 }
9051
9052 bool BisonCSSParser::parseLineBoxContain(bool important)
9053 {
9054     LineBoxContain lineBoxContain = LineBoxContainNone;
9055
9056     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
9057         if (value->id == CSSValueBlock) {
9058             if (lineBoxContain & LineBoxContainBlock)
9059                 return false;
9060             lineBoxContain |= LineBoxContainBlock;
9061         } else if (value->id == CSSValueInline) {
9062             if (lineBoxContain & LineBoxContainInline)
9063                 return false;
9064             lineBoxContain |= LineBoxContainInline;
9065         } else if (value->id == CSSValueFont) {
9066             if (lineBoxContain & LineBoxContainFont)
9067                 return false;
9068             lineBoxContain |= LineBoxContainFont;
9069         } else if (value->id == CSSValueGlyphs) {
9070             if (lineBoxContain & LineBoxContainGlyphs)
9071                 return false;
9072             lineBoxContain |= LineBoxContainGlyphs;
9073         } else if (value->id == CSSValueReplaced) {
9074             if (lineBoxContain & LineBoxContainReplaced)
9075                 return false;
9076             lineBoxContain |= LineBoxContainReplaced;
9077         } else if (value->id == CSSValueInlineBox) {
9078             if (lineBoxContain & LineBoxContainInlineBox)
9079                 return false;
9080             lineBoxContain |= LineBoxContainInlineBox;
9081         } else
9082             return false;
9083     }
9084
9085     if (!lineBoxContain)
9086         return false;
9087
9088     addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important);
9089     return true;
9090 }
9091
9092 bool BisonCSSParser::parseFontFeatureTag(CSSValueList* settings)
9093 {
9094     // Feature tag name consists of 4-letter characters.
9095     static const unsigned tagNameLength = 4;
9096
9097     CSSParserValue* value = m_valueList->current();
9098     // Feature tag name comes first
9099     if (value->unit != CSSPrimitiveValue::CSS_STRING)
9100         return false;
9101     if (value->string.length() != tagNameLength)
9102         return false;
9103     for (unsigned i = 0; i < tagNameLength; ++i) {
9104         // Limits the range of characters to 0x20-0x7E, following the tag name rules defiend in the OpenType specification.
9105         UChar character = value->string[i];
9106         if (character < 0x20 || character > 0x7E)
9107             return false;
9108     }
9109
9110     AtomicString tag = value->string;
9111     int tagValue = 1;
9112     // Feature tag values could follow: <integer> | on | off
9113     value = m_valueList->next();
9114     if (value) {
9115         if (value->unit == CSSPrimitiveValue::CSS_NUMBER && value->isInt && value->fValue >= 0) {
9116             tagValue = clampToInteger(value->fValue);
9117             if (tagValue < 0)
9118                 return false;
9119             m_valueList->next();
9120         } else if (value->id == CSSValueOn || value->id == CSSValueOff) {
9121             tagValue = value->id == CSSValueOn;
9122             m_valueList->next();
9123         }
9124     }
9125     settings->append(CSSFontFeatureValue::create(tag, tagValue));
9126     return true;
9127 }
9128
9129 bool BisonCSSParser::parseFontFeatureSettings(bool important)
9130 {
9131     if (m_valueList->size() == 1 && m_valueList->current()->id == CSSValueNormal) {
9132         RefPtrWillBeRawPtr<CSSPrimitiveValue> normalValue = cssValuePool().createIdentifierValue(CSSValueNormal);
9133         m_valueList->next();
9134         addProperty(CSSPropertyWebkitFontFeatureSettings, normalValue.release(), important);
9135         return true;
9136     }
9137
9138     RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparated();
9139     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
9140         if (!parseFontFeatureTag(settings.get()))
9141             return false;
9142
9143         // If the list isn't parsed fully, the current value should be comma.
9144         value = m_valueList->current();
9145         if (value && !isComma(value))
9146             return false;
9147     }
9148     if (settings->length()) {
9149         addProperty(CSSPropertyWebkitFontFeatureSettings, settings.release(), important);
9150         return true;
9151     }
9152     return false;
9153 }
9154
9155 bool BisonCSSParser::parseFontVariantLigatures(bool important)
9156 {
9157     RefPtrWillBeRawPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated();
9158     bool sawCommonLigaturesValue = false;
9159     bool sawDiscretionaryLigaturesValue = false;
9160     bool sawHistoricalLigaturesValue = false;
9161
9162     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
9163         if (value->unit != CSSPrimitiveValue::CSS_IDENT)
9164             return false;
9165
9166         switch (value->id) {
9167         case CSSValueNoCommonLigatures:
9168         case CSSValueCommonLigatures:
9169             if (sawCommonLigaturesValue)
9170                 return false;
9171             sawCommonLigaturesValue = true;
9172             ligatureValues->append(cssValuePool().createIdentifierValue(value->id));
9173             break;
9174         case CSSValueNoDiscretionaryLigatures:
9175         case CSSValueDiscretionaryLigatures:
9176             if (sawDiscretionaryLigaturesValue)
9177                 return false;
9178             sawDiscretionaryLigaturesValue = true;
9179             ligatureValues->append(cssValuePool().createIdentifierValue(value->id));
9180             break;
9181         case CSSValueNoHistoricalLigatures:
9182         case CSSValueHistoricalLigatures:
9183             if (sawHistoricalLigaturesValue)
9184                 return false;
9185             sawHistoricalLigaturesValue = true;
9186             ligatureValues->append(cssValuePool().createIdentifierValue(value->id));
9187             break;
9188         default:
9189             return false;
9190         }
9191     }
9192
9193     if (!ligatureValues->length())
9194         return false;
9195
9196     addProperty(CSSPropertyFontVariantLigatures, ligatureValues.release(), important);
9197     return true;
9198 }
9199
9200 bool BisonCSSParser::parseCalculation(CSSParserValue* value, ValueRange range)
9201 {
9202     ASSERT(isCalculation(value));
9203
9204     CSSParserValueList* args = value->function->args.get();
9205     if (!args || !args->size())
9206         return false;
9207
9208     ASSERT(!m_parsedCalculation);
9209     m_parsedCalculation = CSSCalcValue::create(value->function->name, args, range);
9210
9211     if (!m_parsedCalculation)
9212         return false;
9213
9214     return true;
9215 }
9216
9217 #define END_TOKEN 0
9218
9219 void BisonCSSParser::ensureLineEndings()
9220 {
9221     if (!m_lineEndings)
9222         m_lineEndings = lineEndings(*m_source);
9223 }
9224
9225 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
9226 {
9227     CSSParserSelector* selector = new CSSParserSelector(tagQName);
9228     m_floatingSelectors.append(selector);
9229     return selector;
9230 }
9231
9232 CSSParserSelector* BisonCSSParser::createFloatingSelector()
9233 {
9234     CSSParserSelector* selector = new CSSParserSelector;
9235     m_floatingSelectors.append(selector);
9236     return selector;
9237 }
9238
9239 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
9240 {
9241     if (selector) {
9242         size_t index = m_floatingSelectors.reverseFind(selector);
9243         ASSERT(index != kNotFound);
9244         m_floatingSelectors.remove(index);
9245     }
9246     return adoptPtr(selector);
9247 }
9248
9249 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
9250 {
9251     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
9252     m_floatingSelectorVectors.append(selectorVector);
9253     return selectorVector;
9254 }
9255
9256 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
9257 {
9258     if (selectorVector) {
9259         size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
9260         ASSERT(index != kNotFound);
9261         m_floatingSelectorVectors.remove(index);
9262     }
9263     return adoptPtr(selectorVector);
9264 }
9265
9266 CSSParserValueList* BisonCSSParser::createFloatingValueList()
9267 {
9268     CSSParserValueList* list = new CSSParserValueList;
9269     m_floatingValueLists.append(list);
9270     return list;
9271 }
9272
9273 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
9274 {
9275     if (list) {
9276         size_t index = m_floatingValueLists.reverseFind(list);
9277         ASSERT(index != kNotFound);
9278         m_floatingValueLists.remove(index);
9279     }
9280     return adoptPtr(list);
9281 }
9282
9283 CSSParserFunction* BisonCSSParser::createFloatingFunction()
9284 {
9285     CSSParserFunction* function = new CSSParserFunction;
9286     m_floatingFunctions.append(function);
9287     return function;
9288 }
9289
9290 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
9291 {
9292     CSSParserFunction* function = createFloatingFunction();
9293     function->name = name;
9294     function->args = args;
9295     return function;
9296 }
9297
9298 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
9299 {
9300     if (function) {
9301         size_t index = m_floatingFunctions.reverseFind(function);
9302         ASSERT(index != kNotFound);
9303         m_floatingFunctions.remove(index);
9304     }
9305     return adoptPtr(function);
9306 }
9307
9308 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
9309 {
9310     if (value.unit == CSSParserValue::Function) {
9311         size_t index = m_floatingFunctions.reverseFind(value.function);
9312         ASSERT(index != kNotFound);
9313         m_floatingFunctions.remove(index);
9314     }
9315     return value;
9316 }
9317
9318 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
9319 {
9320     m_floatingMediaQueryExp = MediaQueryExp::create(mediaFeature, values);
9321     return m_floatingMediaQueryExp.get();
9322 }
9323
9324 PassOwnPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
9325 {
9326     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
9327     return m_floatingMediaQueryExp.release();
9328 }
9329
9330 Vector<OwnPtr<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
9331 {
9332     m_floatingMediaQueryExpList = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >);
9333     return m_floatingMediaQueryExpList.get();
9334 }
9335
9336 PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >* list)
9337 {
9338     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
9339     return m_floatingMediaQueryExpList.release();
9340 }
9341
9342 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
9343 {
9344     m_floatingMediaQuery = adoptPtr(new MediaQuery(restrictor, mediaType, expressions));
9345     return m_floatingMediaQuery.get();
9346 }
9347
9348 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
9349 {
9350     return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions);
9351 }
9352
9353 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
9354 {
9355     return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
9356 }
9357
9358 PassOwnPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
9359 {
9360     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
9361     return m_floatingMediaQuery.release();
9362 }
9363
9364 Vector<RefPtr<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
9365 {
9366     m_floatingKeyframeVector = adoptPtr(new Vector<RefPtr<StyleKeyframe> >());
9367     return m_floatingKeyframeVector.get();
9368 }
9369
9370 PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(Vector<RefPtr<StyleKeyframe> >* keyframeVector)
9371 {
9372     ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
9373     return m_floatingKeyframeVector.release();
9374 }
9375
9376 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
9377 {
9378     RefPtr<MediaQuerySet> queries = MediaQuerySet::create();
9379     MediaQuerySet* result = queries.get();
9380     m_parsedMediaQuerySets.append(queries.release());
9381     return result;
9382 }
9383
9384 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
9385 {
9386     if (!media || !m_allowImportRules)
9387         return 0;
9388     RefPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
9389     StyleRuleImport* result = rule.get();
9390     m_parsedRules.append(rule.release());
9391     return result;
9392 }
9393
9394 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
9395 {
9396     m_allowImportRules = m_allowNamespaceDeclarations = false;
9397     RefPtr<StyleRuleMedia> rule;
9398     if (rules) {
9399         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create(), *rules);
9400     } else {
9401         RuleList emptyRules;
9402         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create(), emptyRules);
9403     }
9404     StyleRuleMedia* result = rule.get();
9405     m_parsedRules.append(rule.release());
9406     return result;
9407 }
9408
9409 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
9410 {
9411     m_allowImportRules = m_allowNamespaceDeclarations = false;
9412
9413     RefPtr<CSSRuleSourceData> data = popSupportsRuleData();
9414     RefPtr<StyleRuleSupports> rule;
9415     String conditionText;
9416     unsigned conditionOffset = data->ruleHeaderRange.start + 9;
9417     unsigned conditionLength = data->ruleHeaderRange.length() - 9;
9418
9419     if (m_tokenizer.is8BitSource())
9420         conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
9421     else
9422         conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
9423
9424     if (rules) {
9425         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
9426     } else {
9427         RuleList emptyRules;
9428         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
9429     }
9430
9431     StyleRuleSupports* result = rule.get();
9432     m_parsedRules.append(rule.release());
9433
9434     return result;
9435 }
9436
9437 void BisonCSSParser::markSupportsRuleHeaderStart()
9438 {
9439     if (!m_supportsRuleDataStack)
9440         m_supportsRuleDataStack = adoptPtr(new RuleSourceDataList());
9441
9442     RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
9443     data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
9444     m_supportsRuleDataStack->append(data);
9445 }
9446
9447 void BisonCSSParser::markSupportsRuleHeaderEnd()
9448 {
9449     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
9450
9451     if (m_tokenizer.is8BitSource())
9452         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
9453     else
9454         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
9455 }
9456
9457 PassRefPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
9458 {
9459     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
9460     RefPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
9461     m_supportsRuleDataStack->removeLast();
9462     return data.release();
9463 }
9464
9465 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
9466 {
9467     OwnPtr<RuleList> list = adoptPtr(new RuleList);
9468     RuleList* listPtr = list.get();
9469
9470     m_parsedRuleLists.append(list.release());
9471     return listPtr;
9472 }
9473
9474 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
9475 {
9476     if (rule) {
9477         if (!ruleList)
9478             ruleList = createRuleList();
9479         ruleList->append(rule);
9480     }
9481     return ruleList;
9482 }
9483
9484 template <typename CharacterType>
9485 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
9486 {
9487     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
9488     // that can potentially change the length of the string rather than the character
9489     // by character kind. If we don't need Unicode lowercasing, it would be good to
9490     // simplify this function.
9491
9492     if (charactersAreAllASCII(input, length)) {
9493         // Fast case for all-ASCII.
9494         for (unsigned i = 0; i < length; i++)
9495             output[i] = toASCIILower(input[i]);
9496     } else {
9497         for (unsigned i = 0; i < length; i++)
9498             output[i] = Unicode::toLower(input[i]);
9499     }
9500 }
9501
9502 void BisonCSSParser::tokenToLowerCase(const CSSParserString& token)
9503 {
9504     size_t length = token.length();
9505     if (m_tokenizer.is8BitSource()) {
9506         size_t offset = token.characters8() - m_tokenizer.m_dataStart8.get();
9507         makeLower(token.characters8(), m_tokenizer.m_dataStart8.get() + offset, length);
9508     } else {
9509         size_t offset = token.characters16() - m_tokenizer.m_dataStart16.get();
9510         makeLower(token.characters16(), m_tokenizer.m_dataStart16.get() + offset, length);
9511     }
9512 }
9513
9514 void BisonCSSParser::endInvalidRuleHeader()
9515 {
9516     if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
9517         return;
9518
9519     CSSParserLocation location;
9520     location.lineNumber = m_tokenizer.m_lineNumber;
9521     location.offset = m_ruleHeaderStartOffset;
9522     if (m_tokenizer.is8BitSource())
9523         location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
9524     else
9525         location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
9526
9527     reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
9528
9529     endRuleHeader();
9530 }
9531
9532 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
9533 {
9534     // FIXME: error reporting temporatily disabled.
9535 }
9536
9537 bool BisonCSSParser::isLoggingErrors()
9538 {
9539     return m_logErrors && !m_ignoreErrors;
9540 }
9541
9542 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
9543 {
9544     unsigned lineNumberInStyleSheet;
9545     unsigned columnNumber = 0;
9546     if (InspectorInstrumentation::hasFrontends()) {
9547         ensureLineEndings();
9548         TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
9549         lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
9550         columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
9551     } else {
9552         lineNumberInStyleSheet = location.lineNumber;
9553     }
9554     PageConsole& console = m_styleSheet->singleOwnerDocument()->frameHost()->console();
9555     console.addMessage(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1);
9556 }
9557
9558 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > popKeyframes, bool isPrefixed)
9559 {
9560     OwnPtr<Vector<RefPtr<StyleKeyframe> > > keyframes = popKeyframes;
9561     m_allowImportRules = m_allowNamespaceDeclarations = false;
9562     RefPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
9563     for (size_t i = 0; i < keyframes->size(); ++i)
9564         rule->parserAppendKeyframe(keyframes->at(i));
9565     rule->setName(name);
9566     rule->setVendorPrefixed(isPrefixed);
9567     StyleRuleKeyframes* rulePtr = rule.get();
9568     m_parsedRules.append(rule.release());
9569     return rulePtr;
9570 }
9571
9572 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
9573 {
9574     StyleRule* result = 0;
9575     if (selectors) {
9576         m_allowImportRules = m_allowNamespaceDeclarations = false;
9577         RefPtr<StyleRule> rule = StyleRule::create();
9578         rule->parserAdoptSelectorVector(*selectors);
9579         if (m_hasFontFaceOnlyValues)
9580             deleteFontFaceOnlyValues();
9581         rule->setProperties(createStylePropertySet());
9582         result = rule.get();
9583         m_parsedRules.append(rule.release());
9584     }
9585     clearProperties();
9586     return result;
9587 }
9588
9589 StyleRuleBase* BisonCSSParser::createFontFaceRule()
9590 {
9591     m_allowImportRules = m_allowNamespaceDeclarations = false;
9592     for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
9593         CSSProperty& property = m_parsedProperties[i];
9594         if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
9595             property.wrapValueInCommaSeparatedList();
9596         else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
9597             // Unlike font-family property, font-family descriptor in @font-face rule
9598             // has to be a value list with exactly one family name. It cannot have a
9599             // have 'initial' value and cannot 'inherit' from parent.
9600             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
9601             clearProperties();
9602             return 0;
9603         }
9604     }
9605     RefPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
9606     rule->setProperties(createStylePropertySet());
9607     clearProperties();
9608     StyleRuleFontFace* result = rule.get();
9609     m_parsedRules.append(rule.release());
9610     if (m_styleSheet)
9611         m_styleSheet->setHasFontFaceRule(true);
9612     return result;
9613 }
9614
9615 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
9616 {
9617     if (!m_styleSheet || !m_allowNamespaceDeclarations)
9618         return;
9619     m_allowImportRules = false;
9620     m_styleSheet->parserAddNamespace(prefix, uri);
9621     if (prefix.isEmpty() && !uri.isNull())
9622         m_defaultNamespace = uri;
9623 }
9624
9625 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
9626 {
9627     if (!m_styleSheet)
9628         return QualifiedName(prefix, localName, m_defaultNamespace);
9629     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
9630 }
9631
9632 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
9633 {
9634     if (m_defaultNamespace != starAtom || specifiers->needsCrossingTreeScopeBoundary())
9635         return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
9636     if (CSSParserSelector* distributedPseudoElementSelector = specifiers->findDistributedPseudoElementSelector()) {
9637         specifiers->prependTagSelector(QualifiedName(nullAtom, starAtom, m_defaultNamespace), /*tagIsForNamespaceRule*/true);
9638         return rewriteSpecifiersForShadowDistributed(specifiers, distributedPseudoElementSelector);
9639     }
9640     return specifiers;
9641 }
9642
9643 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
9644 {
9645     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
9646     QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
9647
9648     if (CSSParserSelector* distributedPseudoElementSelector = specifiers->findDistributedPseudoElementSelector()) {
9649         specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
9650         return rewriteSpecifiersForShadowDistributed(specifiers, distributedPseudoElementSelector);
9651     }
9652
9653     if (specifiers->needsCrossingTreeScopeBoundary())
9654         return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
9655
9656     if (specifiers->isContentPseudoElement())
9657         return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
9658
9659     if (tag == anyQName())
9660         return specifiers;
9661     if (!(specifiers->pseudoType() == CSSSelector::PseudoCue))
9662         specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
9663     return specifiers;
9664 }
9665
9666 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
9667 {
9668     if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
9669         m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
9670
9671     CSSParserSelector* lastShadowPseudo = specifiers;
9672     CSSParserSelector* history = specifiers;
9673     while (history->tagHistory()) {
9674         history = history->tagHistory();
9675         if (history->needsCrossingTreeScopeBoundary() || history->hasShadowPseudo())
9676             lastShadowPseudo = history;
9677     }
9678
9679     if (lastShadowPseudo->tagHistory()) {
9680         if (tag != anyQName())
9681             lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
9682         return specifiers;
9683     }
9684
9685     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
9686     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
9687     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
9688     lastShadowPseudo->setTagHistory(elementNameSelector.release());
9689     lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
9690     return specifiers;
9691 }
9692
9693 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
9694 {
9695     CSSParserSelector* last = specifiers;
9696     CSSParserSelector* history = specifiers;
9697     while (history->tagHistory()) {
9698         history = history->tagHistory();
9699         if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
9700             last = history;
9701     }
9702
9703     if (last->tagHistory()) {
9704         if (tag != anyQName())
9705             last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
9706         return specifiers;
9707     }
9708
9709     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
9710     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
9711     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
9712     last->setTagHistory(elementNameSelector.release());
9713     last->setRelation(CSSSelector::SubSelector);
9714     return specifiers;
9715 }
9716
9717 CSSParserSelector* BisonCSSParser::rewriteSpecifiersForShadowDistributed(CSSParserSelector* specifiers, CSSParserSelector* distributedPseudoElementSelector)
9718 {
9719     if (m_context.useCounter())
9720         m_context.useCounter()->count(UseCounter::CSSPseudoElementPrefixedDistributed);
9721     CSSParserSelector* argumentSelector = distributedPseudoElementSelector->functionArgumentSelector();
9722     ASSERT(argumentSelector);
9723     ASSERT(!specifiers->isDistributedPseudoElement());
9724     for (CSSParserSelector* end = specifiers; end->tagHistory(); end = end->tagHistory()) {
9725         if (end->tagHistory()->isDistributedPseudoElement()) {
9726             end->clearTagHistory();
9727             break;
9728         }
9729     }
9730     CSSParserSelector* end = argumentSelector;
9731     while (end->tagHistory())
9732         end = end->tagHistory();
9733
9734     switch (end->relation()) {
9735     case CSSSelector::Child:
9736     case CSSSelector::Descendant:
9737         end->setTagHistory(sinkFloatingSelector(specifiers));
9738         end->setRelationIsAffectedByPseudoContent();
9739         return argumentSelector;
9740     default:
9741         return 0;
9742     }
9743 }
9744
9745 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
9746 {
9747     if (newSpecifier->needsCrossingTreeScopeBoundary()) {
9748         // Unknown pseudo element always goes at the top of selector chain.
9749         newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
9750         return newSpecifier;
9751     }
9752     if (newSpecifier->isContentPseudoElement()) {
9753         newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
9754         return newSpecifier;
9755     }
9756     if (specifiers->needsCrossingTreeScopeBoundary()) {
9757         // Specifiers for unknown pseudo element go right behind it in the chain.
9758         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
9759         return specifiers;
9760     }
9761     if (specifiers->isContentPseudoElement()) {
9762         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
9763         return specifiers;
9764     }
9765     specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
9766     return specifiers;
9767 }
9768
9769 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
9770 {
9771     // FIXME: Margin at-rules are ignored.
9772     m_allowImportRules = m_allowNamespaceDeclarations = false;
9773     StyleRulePage* pageRule = 0;
9774     if (pageSelector) {
9775         RefPtr<StyleRulePage> rule = StyleRulePage::create();
9776         Vector<OwnPtr<CSSParserSelector> > selectorVector;
9777         selectorVector.append(pageSelector);
9778         rule->parserAdoptSelectorVector(selectorVector);
9779         rule->setProperties(createStylePropertySet());
9780         pageRule = rule.get();
9781         m_parsedRules.append(rule.release());
9782     }
9783     clearProperties();
9784     return pageRule;
9785 }
9786
9787 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
9788 {
9789     // FIXME: Implement margin at-rule here, using:
9790     //        - marginBox: margin box
9791     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
9792     // 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.
9793
9794     endDeclarationsForMarginBox();
9795     return 0; // until this method is implemented.
9796 }
9797
9798 void BisonCSSParser::startDeclarationsForMarginBox()
9799 {
9800     m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
9801 }
9802
9803 void BisonCSSParser::endDeclarationsForMarginBox()
9804 {
9805     rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
9806     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
9807 }
9808
9809 void BisonCSSParser::deleteFontFaceOnlyValues()
9810 {
9811     ASSERT(m_hasFontFaceOnlyValues);
9812     for (unsigned i = 0; i < m_parsedProperties.size();) {
9813         CSSProperty& property = m_parsedProperties[i];
9814         if (property.id() == CSSPropertyFontVariant && property.value()->isValueList()) {
9815             m_parsedProperties.remove(i);
9816             continue;
9817         }
9818         ++i;
9819     }
9820 }
9821
9822 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
9823 {
9824     OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
9825     if (keyVector->isEmpty())
9826         return 0;
9827
9828     RefPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
9829     keyframe->setKeys(keyVector.release());
9830     keyframe->setProperties(createStylePropertySet());
9831
9832     clearProperties();
9833
9834     StyleKeyframe* keyframePtr = keyframe.get();
9835     m_parsedKeyframes.append(keyframe.release());
9836     return keyframePtr;
9837 }
9838
9839 void BisonCSSParser::invalidBlockHit()
9840 {
9841     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
9842         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
9843 }
9844
9845 void BisonCSSParser::startRule()
9846 {
9847     if (!m_observer)
9848         return;
9849
9850     ASSERT(m_ruleHasHeader);
9851     m_ruleHasHeader = false;
9852 }
9853
9854 void BisonCSSParser::endRule(bool valid)
9855 {
9856     if (!m_observer)
9857         return;
9858
9859     if (m_ruleHasHeader)
9860         m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
9861     m_ruleHasHeader = true;
9862 }
9863
9864 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
9865 {
9866     resumeErrorLogging();
9867     m_ruleHeaderType = ruleType;
9868     m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
9869     m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
9870     if (m_observer) {
9871         ASSERT(!m_ruleHasHeader);
9872         m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
9873         m_ruleHasHeader = true;
9874     }
9875 }
9876
9877 void BisonCSSParser::endRuleHeader()
9878 {
9879     ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
9880     m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
9881     if (m_observer) {
9882         ASSERT(m_ruleHasHeader);
9883         m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
9884     }
9885 }
9886
9887 void BisonCSSParser::startSelector()
9888 {
9889     if (m_observer)
9890         m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
9891 }
9892
9893 void BisonCSSParser::endSelector()
9894 {
9895     if (m_observer)
9896         m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
9897 }
9898
9899 void BisonCSSParser::startRuleBody()
9900 {
9901     if (m_observer)
9902         m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
9903 }
9904
9905 void BisonCSSParser::startProperty()
9906 {
9907     resumeErrorLogging();
9908     if (m_observer)
9909         m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
9910 }
9911
9912 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
9913 {
9914     m_id = CSSPropertyInvalid;
9915     if (m_observer)
9916         m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
9917 }
9918
9919 void BisonCSSParser::startEndUnknownRule()
9920 {
9921     if (m_observer)
9922         m_observer->startEndUnknownRule();
9923 }
9924
9925 StyleRuleBase* BisonCSSParser::createViewportRule()
9926 {
9927     // Allow @viewport rules from UA stylesheets even if the feature is disabled.
9928     if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
9929         return 0;
9930
9931     m_allowImportRules = m_allowNamespaceDeclarations = false;
9932
9933     RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
9934
9935     rule->setProperties(createStylePropertySet());
9936     clearProperties();
9937
9938     StyleRuleViewport* result = rule.get();
9939     m_parsedRules.append(rule.release());
9940
9941     return result;
9942 }
9943
9944 bool BisonCSSParser::parseViewportProperty(CSSPropertyID propId, bool important)
9945 {
9946     ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode()));
9947
9948     CSSParserValue* value = m_valueList->current();
9949     if (!value)
9950         return false;
9951
9952     CSSValueID id = value->id;
9953     bool validPrimitive = false;
9954
9955     switch (propId) {
9956     case CSSPropertyMinWidth: // auto | extend-to-zoom | <length> | <percentage>
9957     case CSSPropertyMaxWidth:
9958     case CSSPropertyMinHeight:
9959     case CSSPropertyMaxHeight:
9960         if (id == CSSValueAuto || id == CSSValueInternalExtendToZoom)
9961             validPrimitive = true;
9962         else
9963             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
9964         break;
9965     case CSSPropertyWidth: // shorthand
9966         return parseViewportShorthand(propId, CSSPropertyMinWidth, CSSPropertyMaxWidth, important);
9967     case CSSPropertyHeight:
9968         return parseViewportShorthand(propId, CSSPropertyMinHeight, CSSPropertyMaxHeight, important);
9969     case CSSPropertyMinZoom: // auto | <number> | <percentage>
9970     case CSSPropertyMaxZoom:
9971     case CSSPropertyZoom:
9972         if (id == CSSValueAuto)
9973             validPrimitive = true;
9974         else
9975             validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg));
9976         break;
9977     case CSSPropertyUserZoom: // zoom | fixed
9978         if (id == CSSValueZoom || id == CSSValueFixed)
9979             validPrimitive = true;
9980         break;
9981     case CSSPropertyOrientation: // auto | portrait | landscape
9982         if (id == CSSValueAuto || id == CSSValuePortrait || id == CSSValueLandscape)
9983             validPrimitive = true;
9984     default:
9985         break;
9986     }
9987
9988     RefPtr<CSSValue> parsedValue;
9989     if (validPrimitive) {
9990         parsedValue = parseValidPrimitive(id, value);
9991         m_valueList->next();
9992     }
9993
9994     if (parsedValue) {
9995         if (!m_valueList->current() || inShorthand()) {
9996             addProperty(propId, parsedValue.release(), important);
9997             return true;
9998         }
9999     }
10000
10001     return false;
10002 }
10003
10004 bool BisonCSSParser::parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important)
10005 {
10006     ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode()));
10007     unsigned numValues = m_valueList->size();
10008
10009     if (numValues > 2)
10010         return false;
10011
10012     ShorthandScope scope(this, propId);
10013
10014     if (!parseViewportProperty(first, important))
10015         return false;
10016
10017     // If just one value is supplied, the second value
10018     // is implicitly initialized with the first value.
10019     if (numValues == 1)
10020         m_valueList->previous();
10021
10022     return parseViewportProperty(second, important);
10023 }
10024
10025 template <typename CharacterType>
10026 static CSSPropertyID cssPropertyID(const CharacterType* propertyName, unsigned length)
10027 {
10028     char buffer[maxCSSPropertyNameLength + 1]; // 1 for null character
10029
10030     for (unsigned i = 0; i != length; ++i) {
10031         CharacterType c = propertyName[i];
10032         if (c == 0 || c >= 0x7F)
10033             return CSSPropertyInvalid; // illegal character
10034         buffer[i] = toASCIILower(c);
10035     }
10036     buffer[length] = '\0';
10037
10038     const char* name = buffer;
10039     const Property* hashTableEntry = findProperty(name, length);
10040     return hashTableEntry ? static_cast<CSSPropertyID>(hashTableEntry->id) : CSSPropertyInvalid;
10041 }
10042
10043 CSSPropertyID cssPropertyID(const String& string)
10044 {
10045     unsigned length = string.length();
10046
10047     if (!length)
10048         return CSSPropertyInvalid;
10049     if (length > maxCSSPropertyNameLength)
10050         return CSSPropertyInvalid;
10051
10052     return string.is8Bit() ? cssPropertyID(string.characters8(), length) : cssPropertyID(string.characters16(), length);
10053 }
10054
10055 CSSPropertyID cssPropertyID(const CSSParserString& string)
10056 {
10057     unsigned length = string.length();
10058
10059     if (!length)
10060         return CSSPropertyInvalid;
10061     if (length > maxCSSPropertyNameLength)
10062         return CSSPropertyInvalid;
10063
10064     return string.is8Bit() ? cssPropertyID(string.characters8(), length) : cssPropertyID(string.characters16(), length);
10065 }
10066
10067 template <typename CharacterType>
10068 static CSSValueID cssValueKeywordID(const CharacterType* valueKeyword, unsigned length)
10069 {
10070     char buffer[maxCSSValueKeywordLength + 1]; // 1 for null character
10071
10072     for (unsigned i = 0; i != length; ++i) {
10073         CharacterType c = valueKeyword[i];
10074         if (c == 0 || c >= 0x7F)
10075             return CSSValueInvalid; // illegal character
10076         buffer[i] = WTF::toASCIILower(c);
10077     }
10078     buffer[length] = '\0';
10079
10080     const Value* hashTableEntry = findValue(buffer, length);
10081     return hashTableEntry ? static_cast<CSSValueID>(hashTableEntry->id) : CSSValueInvalid;
10082 }
10083
10084 CSSValueID cssValueKeywordID(const CSSParserString& string)
10085 {
10086     unsigned length = string.length();
10087     if (!length)
10088         return CSSValueInvalid;
10089     if (length > maxCSSValueKeywordLength)
10090         return CSSValueInvalid;
10091
10092     return string.is8Bit() ? cssValueKeywordID(string.characters8(), length) : cssValueKeywordID(string.characters16(), length);
10093 }
10094
10095 bool isValidNthToken(const CSSParserString& token)
10096 {
10097     // The tokenizer checks for the construct of an+b.
10098     // However, since the {ident} rule precedes the {nth} rule, some of those
10099     // tokens are identified as string literal. Furthermore we need to accept
10100     // "odd" and "even" which does not match to an+b.
10101     return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even")
10102         || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n");
10103 }
10104
10105 }