aeb681edac83bb0620620275fd78f7e891c29b3a
[WebKit-https.git] / Source / WebCore / css / CSSParser.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  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "CSSParser.h"
28
29 #include "CSSAspectRatioValue.h"
30 #include "CSSBorderImage.h"
31 #include "CSSCanvasValue.h"
32 #include "CSSCrossfadeValue.h"
33 #include "CSSCursorImageValue.h"
34 #include "CSSFontFaceRule.h"
35 #include "CSSFontFaceSrcValue.h"
36 #include "CSSFunctionValue.h"
37 #include "CSSGradientValue.h"
38 #include "CSSImageValue.h"
39 #include "CSSInheritedValue.h"
40 #include "CSSInitialValue.h"
41 #include "CSSLineBoxContainValue.h"
42 #include "CSSMediaRule.h"
43 #include "CSSPageRule.h"
44 #include "CSSPrimitiveValue.h"
45 #include "CSSProperty.h"
46 #include "CSSPropertySourceData.h"
47 #include "CSSReflectValue.h"
48 #include "CSSSelector.h"
49 #include "CSSTimingFunctionValue.h"
50 #include "CSSUnicodeRangeValue.h"
51 #include "CSSValueKeywords.h"
52 #include "CSSValueList.h"
53 #include "CSSValuePool.h"
54 #if ENABLE(CSS_VARIABLES)
55 #include "CSSVariableValue.h"
56 #endif
57 #include "CSSWrapShapes.h"
58 #include "Counter.h"
59 #include "Document.h"
60 #include "FloatConversion.h"
61 #include "FontFeatureValue.h"
62 #include "FontValue.h"
63 #include "HTMLParserIdioms.h"
64 #include "HashTools.h"
65 #include "MediaList.h"
66 #include "MediaQueryExp.h"
67 #include "Page.h"
68 #include "Pair.h"
69 #include "Rect.h"
70 #include "RenderTheme.h"
71 #include "RuntimeEnabledFeatures.h"
72 #include "SVGParserUtilities.h"
73 #include "Settings.h"
74 #include "ShadowValue.h"
75 #include "StylePropertySet.h"
76 #include "StylePropertyShorthand.h"
77 #include "StyleRule.h"
78 #include "StyleRuleImport.h"
79 #include "StyleSheetContents.h"
80 #include "TextEncoding.h"
81 #include "WebKitCSSKeyframeRule.h"
82 #include "WebKitCSSKeyframesRule.h"
83 #include "WebKitCSSRegionRule.h"
84 #include "WebKitCSSTransformValue.h"
85 #include <limits.h>
86 #include <wtf/BitArray.h>
87 #include <wtf/HexNumber.h>
88 #include <wtf/dtoa.h>
89 #include <wtf/text/StringBuffer.h>
90 #include <wtf/text/StringBuilder.h>
91
92 #if ENABLE(CSS_IMAGE_SET)
93 #include "CSSImageSetValue.h"
94 #endif
95
96 #if ENABLE(CSS_FILTERS)
97 #include "WebKitCSSFilterValue.h"
98 #if ENABLE(SVG)
99 #include "WebKitCSSSVGDocumentValue.h"
100 #endif
101 #endif
102
103 #if ENABLE(CSS_SHADERS)
104 #include "WebKitCSSMixFunctionValue.h"
105 #include "WebKitCSSShaderValue.h"
106 #endif
107
108 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION)
109 #include "DashboardRegion.h"
110 #endif
111
112 #define YYDEBUG 0
113
114 #if YYDEBUG > 0
115 extern int cssyydebug;
116 #endif
117
118 extern int cssyyparse(WebCore::CSSParser*);
119
120 using namespace std;
121 using namespace WTF;
122
123 namespace {
124
125 enum PropertyType {
126     PropertyExplicit,
127     PropertyImplicit
128 };
129
130 class ImplicitScope {
131     WTF_MAKE_NONCOPYABLE(ImplicitScope);
132 public:
133     ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType)
134         : m_parser(parser)
135     {
136         m_parser->m_implicitShorthand = propertyType == PropertyImplicit;
137     }
138
139     ~ImplicitScope()
140     {
141         m_parser->m_implicitShorthand = false;
142     }
143
144 private:
145     WebCore::CSSParser* m_parser;
146 };
147
148 } // namespace
149
150 namespace WebCore {
151
152 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
153 static const double MAX_SCALE = 1000000;
154
155 static bool equal(const CSSParserString& a, const char* b)
156 {
157     for (int i = 0; i < a.length; ++i) {
158         if (!b[i])
159             return false;
160         if (a.characters[i] != b[i])
161             return false;
162     }
163     return !b[a.length];
164 }
165
166 static bool equalIgnoringCase(const CSSParserString& a, const char* b)
167 {
168     for (int i = 0; i < a.length; ++i) {
169         if (!b[i])
170             return false;
171         ASSERT(!isASCIIUpper(b[i]));
172         if (toASCIILower(a.characters[i]) != b[i])
173             return false;
174     }
175     return !b[a.length];
176 }
177
178 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
179 {
180     for (unsigned i = 0; i < length; ++i) {
181         if (!prefix[i])
182             return true;
183         if (string[i] != prefix[i])
184             return false;
185     }
186     return false;
187 }
188     
189 const CSSParserContext& strictCSSParserContext()
190 {
191     DEFINE_STATIC_LOCAL(CSSParserContext, strictContext, (CSSStrictMode));
192     return strictContext;
193 }
194
195 CSSParserContext::CSSParserContext(CSSParserMode mode, const KURL& baseURL)
196     : baseURL(baseURL)
197     , mode(mode)
198     , isHTMLDocument(false)
199     , isCSSCustomFilterEnabled(false)
200     , isCSSRegionsEnabled(false)
201     , isCSSGridLayoutEnabled(false)
202 #if ENABLE(CSS_VARIABLES)
203     , isCSSVariablesEnabled(false)
204 #endif
205     , needsSiteSpecificQuirks(false)
206     , enforcesCSSMIMETypeInNoQuirksMode(true)
207 {
208 }
209
210 CSSParserContext::CSSParserContext(Document* document, const KURL& baseURL, const String& charset)
211     : baseURL(baseURL.isNull() ? document->baseURL() : baseURL)
212     , charset(charset)
213     , mode(document->inQuirksMode() ? CSSQuirksMode : CSSStrictMode)
214     , isHTMLDocument(document->isHTMLDocument())
215     , isCSSCustomFilterEnabled(document->settings() ? document->settings()->isCSSCustomFilterEnabled() : false)
216     , isCSSRegionsEnabled(document->cssRegionsEnabled())
217     , isCSSGridLayoutEnabled(document->cssGridLayoutEnabled())
218 #if ENABLE(CSS_VARIABLES)
219     , isCSSVariablesEnabled(document->settings() ? document->settings()->cssVariablesEnabled() : false)
220 #endif
221     , needsSiteSpecificQuirks(document->settings() ? document->settings()->needsSiteSpecificQuirks() : false)
222     , enforcesCSSMIMETypeInNoQuirksMode(!document->settings() || document->settings()->enforceCSSMIMETypeInNoQuirksMode())
223 {
224 }
225
226 bool operator==(const CSSParserContext& a, const CSSParserContext& b)
227 {
228     return a.baseURL == b.baseURL
229         && a.charset == b.charset
230         && a.mode == b.mode
231         && a.isHTMLDocument == b.isHTMLDocument
232         && a.isCSSCustomFilterEnabled == b.isCSSCustomFilterEnabled
233         && a.isCSSRegionsEnabled == b.isCSSRegionsEnabled
234         && a.isCSSGridLayoutEnabled == b.isCSSGridLayoutEnabled
235 #if ENABLE(CSS_VARIABLES)
236         && a.isCSSVariablesEnabled == b.isCSSVariablesEnabled
237 #endif
238         && a.needsSiteSpecificQuirks == b.needsSiteSpecificQuirks
239         && a.enforcesCSSMIMETypeInNoQuirksMode == b.enforcesCSSMIMETypeInNoQuirksMode;
240 }
241
242 CSSParser::CSSParser(const CSSParserContext& context)
243     : m_context(context)
244     , m_important(false)
245     , m_id(CSSPropertyInvalid)
246     , m_styleSheet(0)
247     , m_parsedProperties(adoptPtr(new ParsedPropertyVector))
248     , m_selectorListForParseSelector(0)
249     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
250     , m_inParseShorthand(0)
251     , m_currentShorthand(CSSPropertyInvalid)
252     , m_implicitShorthand(false)
253     , m_hasFontFaceOnlyValues(false)
254     , m_hadSyntacticallyValidCSSRule(false)
255     , m_defaultNamespace(starAtom)
256     , m_parsedTextPrefixLength(0)
257     , m_propertyRange(UINT_MAX, UINT_MAX)
258     , m_ruleSourceDataResult(0)
259     , m_parsingMode(NormalMode)
260     , m_currentCharacter(0)
261     , m_tokenStart(0)
262     , m_token(0)
263     , m_lineNumber(0)
264     , m_lastSelectorLineNumber(0)
265     , m_allowImportRules(true)
266     , m_allowNamespaceDeclarations(true)
267     , m_selectorVector(adoptPtr(new CSSSelectorVector))
268 {
269 #if YYDEBUG > 0
270     cssyydebug = 1;
271 #endif
272     CSSPropertySourceData::init();
273 }
274
275 CSSParser::~CSSParser()
276 {
277     clearProperties();
278
279     fastDeleteAllValues(m_floatingSelectors);
280     deleteAllValues(m_floatingSelectorVectors);
281     deleteAllValues(m_floatingValueLists);
282     deleteAllValues(m_floatingFunctions);
283 }
284
285 void CSSParserString::lower()
286 {
287     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
288     // that can potentially change the length of the string rather than the character
289     // by character kind. If we don't need Unicode lowercasing, it would be good to
290     // simplify this function.
291
292     if (charactersAreAllASCII(characters, length)) {
293         // Fast case for all-ASCII.
294         for (int i = 0; i < length; i++)
295             characters[i] = toASCIILower(characters[i]);
296     } else {
297         for (int i = 0; i < length; i++)
298             characters[i] = Unicode::toLower(characters[i]);
299     }
300 }
301
302 void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
303 {
304     m_parsedTextPrefixLength = strlen(prefix);
305     int length = string.length() + m_parsedTextPrefixLength + strlen(suffix) + 1;
306
307     m_dataStart = adoptArrayPtr(new UChar[length]);
308     for (unsigned i = 0; i < m_parsedTextPrefixLength; i++)
309         m_dataStart[i] = prefix[i];
310
311     memcpy(m_dataStart.get() + m_parsedTextPrefixLength, string.characters(), string.length() * sizeof(UChar));
312
313     unsigned start = m_parsedTextPrefixLength + string.length();
314     unsigned end = start + strlen(suffix);
315     for (unsigned i = start; i < end; i++)
316         m_dataStart[i] = suffix[i - start];
317
318     m_dataStart[length - 1] = 0;
319
320     m_currentCharacter = m_tokenStart = m_dataStart.get();
321 }
322
323 void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, int startLineNumber, RuleSourceDataList* ruleSourceDataResult)
324 {
325     setStyleSheet(sheet);
326     m_defaultNamespace = starAtom; // Reset the default namespace.
327     if (ruleSourceDataResult)
328         m_currentRuleDataStack = adoptPtr(new RuleSourceDataList());
329     m_ruleSourceDataResult = ruleSourceDataResult;
330
331     m_lineNumber = startLineNumber;
332     setupParser("", string, "");
333     cssyyparse(this);
334     m_currentRuleDataStack.clear();
335     m_ruleSourceDataResult = 0;
336     m_rule = 0;
337 }
338
339 PassRefPtr<StyleRuleBase> CSSParser::parseRule(StyleSheetContents* sheet, const String& string)
340 {
341     setStyleSheet(sheet);
342     m_allowNamespaceDeclarations = false;
343     setupParser("@-webkit-rule{", string, "} ");
344     cssyyparse(this);
345     return m_rule.release();
346 }
347
348 PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
349 {
350     setStyleSheet(sheet);
351     setupParser("@-webkit-keyframe-rule{ ", string, "} ");
352     cssyyparse(this);
353     return m_keyframe.release();
354 }
355
356 static inline bool isColorPropertyID(CSSPropertyID propertyId)
357 {
358     switch (propertyId) {
359     case CSSPropertyColor:
360     case CSSPropertyBackgroundColor:
361     case CSSPropertyBorderBottomColor:
362     case CSSPropertyBorderLeftColor:
363     case CSSPropertyBorderRightColor:
364     case CSSPropertyBorderTopColor:
365     case CSSPropertyOutlineColor:
366     case CSSPropertyTextLineThroughColor:
367     case CSSPropertyTextOverlineColor:
368     case CSSPropertyTextUnderlineColor:
369     case CSSPropertyWebkitBorderAfterColor:
370     case CSSPropertyWebkitBorderBeforeColor:
371     case CSSPropertyWebkitBorderEndColor:
372     case CSSPropertyWebkitBorderStartColor:
373     case CSSPropertyWebkitColumnRuleColor:
374     case CSSPropertyWebkitTextEmphasisColor:
375     case CSSPropertyWebkitTextFillColor:
376     case CSSPropertyWebkitTextStrokeColor:
377         return true;
378     default:
379         return false;
380     }
381 }
382
383 static bool parseColorValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
384 {
385     ASSERT(!string.isEmpty());
386     bool strict = isStrictParserMode(cssParserMode);
387     if (!isColorPropertyID(propertyId))
388         return false;
389     CSSParserString cssString;
390     cssString.characters = const_cast<UChar*>(string.characters());
391     cssString.length = string.length();
392     int valueID = cssValueKeywordID(cssString);
393     bool validPrimitive = false;
394     if (valueID == CSSValueWebkitText)
395         validPrimitive = true;
396     else if (valueID == CSSValueCurrentcolor)
397         validPrimitive = true;
398     else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
399              || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
400         validPrimitive = true;
401     }
402
403     if (validPrimitive) {
404         RefPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
405         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
406         return true;
407     }
408     RGBA32 color;
409     if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
410         return false;
411     RefPtr<CSSValue> value = cssValuePool().createColorValue(color);
412     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
413     return true;
414 }
415
416 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
417 {
418     switch (propertyId) {
419     case CSSPropertyFontSize:
420     case CSSPropertyHeight:
421     case CSSPropertyWidth:
422     case CSSPropertyMinHeight:
423     case CSSPropertyMinWidth:
424     case CSSPropertyPaddingBottom:
425     case CSSPropertyPaddingLeft:
426     case CSSPropertyPaddingRight:
427     case CSSPropertyPaddingTop:
428     case CSSPropertyWebkitLogicalWidth:
429     case CSSPropertyWebkitLogicalHeight:
430     case CSSPropertyWebkitMinLogicalWidth:
431     case CSSPropertyWebkitMinLogicalHeight:
432     case CSSPropertyWebkitPaddingAfter:
433     case CSSPropertyWebkitPaddingBefore:
434     case CSSPropertyWebkitPaddingEnd:
435     case CSSPropertyWebkitPaddingStart:
436         acceptsNegativeNumbers = false;
437         return true;
438 #if ENABLE(CSS_EXCLUSIONS)
439     case CSSPropertyWebkitWrapMargin:
440     case CSSPropertyWebkitWrapPadding:
441         acceptsNegativeNumbers = false;
442         return RuntimeEnabledFeatures::cssExclusionsEnabled();
443 #endif
444     case CSSPropertyBottom:
445     case CSSPropertyLeft:
446     case CSSPropertyMarginBottom:
447     case CSSPropertyMarginLeft:
448     case CSSPropertyMarginRight:
449     case CSSPropertyMarginTop:
450     case CSSPropertyRight:
451     case CSSPropertyTextIndent:
452     case CSSPropertyTop:
453     case CSSPropertyWebkitMarginAfter:
454     case CSSPropertyWebkitMarginBefore:
455     case CSSPropertyWebkitMarginEnd:
456     case CSSPropertyWebkitMarginStart:
457         acceptsNegativeNumbers = true;
458         return true;
459     default:
460         return false;
461     }
462 }
463
464 template <typename CharType>
465 static inline bool parseSimpleLength(const CharType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number)
466 {
467     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
468         length -= 2;
469         unit = CSSPrimitiveValue::CSS_PX;
470     } else if (length > 1 && characters[length - 1] == '%') {
471         length -= 1;
472         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
473     }
474
475     // We rely on charactersToDouble for validation as well. The function
476     // will set "ok" to "false" if the entire passed-in character range does
477     // not represent a double.
478     bool ok;
479     number = charactersToDouble(characters, length, &ok);
480     return ok;
481 }
482
483 static bool parseSimpleLengthValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
484 {
485     ASSERT(!string.isEmpty());
486     bool acceptsNegativeNumbers;
487     if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
488         return false;
489
490     unsigned length = string.length();
491     double number;
492     CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
493
494     if (string.is8Bit()) {
495         if (!parseSimpleLength(string.characters8(), length, unit, number))
496             return false;
497     } else {
498         if (!parseSimpleLength(string.characters16(), length, unit, number))
499             return false;
500     }
501
502     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
503         if (number && isStrictParserMode(cssParserMode))
504             return false;
505         unit = CSSPrimitiveValue::CSS_PX;
506     }
507     if (number < 0 && !acceptsNegativeNumbers)
508         return false;
509
510     RefPtr<CSSValue> value = cssValuePool().createValue(number, unit);
511     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
512     return true;
513 }
514
515 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext)
516 {
517     if (!valueID)
518         return false;
519
520     switch (propertyId) {
521     case CSSPropertyBorderCollapse: // collapse | separate | inherit
522         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
523             return true;
524         break;
525     case CSSPropertyBorderTopStyle: // <border-style> | inherit
526     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
527     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
528     case CSSPropertyBorderLeftStyle:
529     case CSSPropertyWebkitBorderAfterStyle:
530     case CSSPropertyWebkitBorderBeforeStyle:
531     case CSSPropertyWebkitBorderEndStyle:
532     case CSSPropertyWebkitBorderStartStyle:
533     case CSSPropertyWebkitColumnRuleStyle:
534         if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
535             return true;
536         break;
537     case CSSPropertyBoxSizing:
538          if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
539              return true;
540          break;
541     case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
542         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
543             return true;
544         break;
545     case CSSPropertyClear: // none | left | right | both | inherit
546         if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
547             return true;
548         break;
549     case CSSPropertyDirection: // ltr | rtl | inherit
550         if (valueID == CSSValueLtr || valueID == CSSValueRtl)
551             return true;
552         break;
553     case CSSPropertyDisplay:
554         // inline | block | list-item | run-in | inline-block | table |
555         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
556         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
557         // -webkit-flex | -webkit-inline-flex | -webkit-grid | -webkit-inline-grid
558         if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineBox) || valueID == CSSValueNone)
559             return true;
560 #if ENABLE(CSS3_FLEXBOX)
561         if (valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex)
562             return true;
563 #endif
564         if (parserContext.isCSSGridLayoutEnabled && (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid))
565             return true;
566         break;
567
568     case CSSPropertyEmptyCells: // show | hide | inherit
569         if (valueID == CSSValueShow || valueID == CSSValueHide)
570             return true;
571         break;
572     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
573         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter)
574             return true;
575         break;
576     case CSSPropertyFontStyle: // normal | italic | oblique | inherit
577         if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
578             return true;
579         break;
580     case CSSPropertyImageRendering: // auto | optimizeContrast
581         if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
582             return true;
583         break;
584     case CSSPropertyListStylePosition: // inside | outside | inherit
585         if (valueID == CSSValueInside || valueID == CSSValueOutside)
586             return true;
587         break;
588     case CSSPropertyListStyleType:
589         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
590         // for the list of supported list-style-types.
591         if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
592             return true;
593         break;
594     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
595         if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
596             return true;
597         break;
598     case CSSPropertyOverflowX:
599     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
600         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
601             return true;
602         break;
603     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
604     case CSSPropertyPageBreakBefore:
605     case CSSPropertyWebkitColumnBreakAfter:
606     case CSSPropertyWebkitColumnBreakBefore:
607         if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)
608             return true;
609         break;
610     case CSSPropertyPageBreakInside: // avoid | auto | inherit
611     case CSSPropertyWebkitColumnBreakInside:
612         if (valueID == CSSValueAuto || valueID == CSSValueAvoid)
613             return true;
614         break;
615     case CSSPropertyPointerEvents:
616         // none | visiblePainted | visibleFill | visibleStroke | visible |
617         // painted | fill | stroke | auto | all | inherit
618         if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke))
619             return true;
620         break;
621     case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit
622         if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed
623 #if ENABLE(CSS_STICKY_POSITION)
624             || valueID == CSSValueWebkitSticky
625 #endif
626             )
627             return true;
628         break;
629     case CSSPropertyResize: // none | both | horizontal | vertical | auto
630         if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
631             return true;
632         break;
633     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
634         if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
635             return true;
636         break;
637     case CSSPropertyTableLayout: // auto | fixed | inherit
638         if (valueID == CSSValueAuto || valueID == CSSValueFixed)
639             return true;
640         break;
641     case CSSPropertyTextLineThroughMode:
642     case CSSPropertyTextOverlineMode:
643     case CSSPropertyTextUnderlineMode:
644         if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
645             return true;
646         break;
647     case CSSPropertyTextLineThroughStyle:
648     case CSSPropertyTextOverlineStyle:
649     case CSSPropertyTextUnderlineStyle:
650         if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
651             return true;
652         break;
653     case CSSPropertyTextOverflow: // clip | ellipsis
654         if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
655             return true;
656         break;
657     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
658         if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
659             return true;
660         break;
661     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
662         if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
663             return true;
664         break;
665     case CSSPropertyVisibility: // visible | hidden | collapse | inherit
666         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
667             return true;
668         break;
669     case CSSPropertyWebkitAppearance:
670         if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
671             return true;
672         break;
673     case CSSPropertyWebkitBackfaceVisibility:
674         if (valueID == CSSValueVisible || valueID == CSSValueHidden)
675             return true;
676         break;
677     case CSSPropertyWebkitBorderFit:
678         if (valueID == CSSValueBorder || valueID == CSSValueLines)
679             return true;
680         break;
681     case CSSPropertyWebkitBoxAlign:
682         if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
683             return true;
684         break;
685 #if ENABLE(CSS_BOX_DECORATION_BREAK)
686     case CSSPropertyWebkitBoxDecorationBreak:
687          if (valueID == CSSValueClone || valueID == CSSValueSlice)
688              return true;
689          break;
690 #endif
691     case CSSPropertyWebkitBoxDirection:
692         if (valueID == CSSValueNormal || valueID == CSSValueReverse)
693             return true;
694         break;
695     case CSSPropertyWebkitBoxLines:
696         if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
697                 return true;
698         break;
699     case CSSPropertyWebkitBoxOrient:
700         if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
701             return true;
702         break;
703     case CSSPropertyWebkitBoxPack:
704         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
705             return true;
706         break;
707     case CSSPropertyWebkitColorCorrection:
708         if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
709             return true;
710         break;
711 #if ENABLE(CSS3_FLEXBOX)
712     case CSSPropertyWebkitAlignContent:
713          if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch)
714              return true;
715          break;
716     case CSSPropertyWebkitAlignItems:
717         if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
718             return true;
719         break;
720     case CSSPropertyWebkitAlignSelf:
721         if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
722             return true;
723         break;
724     case CSSPropertyWebkitFlexDirection:
725         if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
726             return true;
727         break;
728     case CSSPropertyWebkitFlexWrap:
729         if (valueID == CSSValueNone || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
730              return true;
731         break;
732     case CSSPropertyWebkitJustifyContent:
733         if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround)
734             return true;
735         break;
736 #endif
737     case CSSPropertyWebkitFontKerning:
738         if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
739             return true;
740         break;
741     case CSSPropertyWebkitFontSmoothing:
742         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
743             return true;
744         break;
745     case CSSPropertyWebkitHyphens:
746         if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto)
747             return true;
748         break;
749     case CSSPropertyWebkitLineAlign:
750         if (valueID == CSSValueNone || valueID == CSSValueEdges)
751             return true;
752         break;
753     case CSSPropertyWebkitLineBreak: // normal | after-white-space
754         if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace)
755             return true;
756         break;
757     case CSSPropertyWebkitLineSnap:
758         if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain)
759             return true;
760         break;
761     case CSSPropertyWebkitMarginAfterCollapse:
762     case CSSPropertyWebkitMarginBeforeCollapse:
763     case CSSPropertyWebkitMarginBottomCollapse:
764     case CSSPropertyWebkitMarginTopCollapse:
765         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
766             return true;
767         break;
768     case CSSPropertyWebkitMarqueeDirection:
769         if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
770             || valueID == CSSValueUp || valueID == CSSValueAuto)
771             return true;
772         break;
773     case CSSPropertyWebkitMarqueeStyle:
774         if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
775             return true;
776         break;
777     case CSSPropertyWebkitNbspMode: // normal | space
778         if (valueID == CSSValueNormal || valueID == CSSValueSpace)
779             return true;
780         break;
781 #if ENABLE(OVERFLOW_SCROLLING)
782     case CSSPropertyWebkitOverflowScrolling:
783         if (valueID == CSSValueAuto || valueID == CSSValueTouch)
784             return true;
785         break;
786 #endif
787     case CSSPropertyWebkitPrintColorAdjust:
788         if (valueID == CSSValueExact || valueID == CSSValueEconomy)
789             return true;
790         break;
791 #if ENABLE(CSS_REGIONS)
792     case CSSPropertyWebkitRegionBreakAfter:
793     case CSSPropertyWebkitRegionBreakBefore:
794         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight))
795             return true;
796         break;
797     case CSSPropertyWebkitRegionBreakInside:
798         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAvoid))
799             return true;
800         break;
801     case CSSPropertyWebkitRegionOverflow:
802         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueBreak))
803             return true;
804         break;
805 #endif
806     case CSSPropertyWebkitRtlOrdering:
807         if (valueID == CSSValueLogical || valueID == CSSValueVisual)
808             return true;
809         break;
810     case CSSPropertyWebkitTextCombine:
811         if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
812             return true;
813         break;
814     case CSSPropertyWebkitTextEmphasisPosition:
815         if (valueID == CSSValueOver || valueID == CSSValueUnder)
816             return true;
817         break;
818     case CSSPropertyWebkitTextSecurity:
819         // disc | circle | square | none | inherit
820         if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
821             return true;
822         break;
823     case CSSPropertyWebkitTextSizeAdjust:
824         if (valueID == CSSValueAuto || valueID == CSSValueNone)
825             return true;
826         break;
827     case CSSPropertyWebkitTransformStyle:
828         if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
829             return true;
830         break;
831     case CSSPropertyWebkitUserDrag: // auto | none | element
832         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
833             return true;
834         break;
835     case CSSPropertyWebkitUserModify: // read-only | read-write
836         if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
837             return true;
838         break;
839     case CSSPropertyWebkitUserSelect: // auto | none | text | all
840         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll)
841             return true;
842         break;
843 #if ENABLE(CSS_EXCLUSIONS)
844     case CSSPropertyWebkitWrapFlow:
845         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
846             return false;
847         if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear)
848             return true;
849         break;
850     case CSSPropertyWebkitWrapThrough:
851         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
852             return false;
853         if (valueID == CSSValueWrap || valueID == CSSValueNone)
854             return true;
855         break;
856 #endif
857     case CSSPropertyWebkitWritingMode:
858         if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
859             return true;
860         break;
861     case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
862         if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
863             return true;
864         break;
865     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
866         if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
867             return true;
868         break;
869     case CSSPropertyWordWrap: // normal | break-word
870         if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
871             return true;
872         break;
873     default:
874         ASSERT_NOT_REACHED();
875         return false;
876     }
877     return false;
878 }
879
880 static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
881 {
882     switch (propertyId) {
883     case CSSPropertyBorderBottomStyle:
884     case CSSPropertyBorderCollapse:
885     case CSSPropertyBorderLeftStyle:
886     case CSSPropertyBorderRightStyle:
887     case CSSPropertyBorderTopStyle:
888     case CSSPropertyBoxSizing:
889     case CSSPropertyCaptionSide:
890     case CSSPropertyClear:
891     case CSSPropertyDirection:
892     case CSSPropertyDisplay:
893     case CSSPropertyEmptyCells:
894     case CSSPropertyFloat:
895     case CSSPropertyFontStyle:
896     case CSSPropertyImageRendering:
897     case CSSPropertyListStylePosition:
898     case CSSPropertyListStyleType:
899     case CSSPropertyOutlineStyle:
900     case CSSPropertyOverflowX:
901     case CSSPropertyOverflowY:
902     case CSSPropertyPageBreakAfter:
903     case CSSPropertyPageBreakBefore:
904     case CSSPropertyPageBreakInside:
905     case CSSPropertyPointerEvents:
906     case CSSPropertyPosition:
907     case CSSPropertyResize:
908     case CSSPropertySpeak:
909     case CSSPropertyTableLayout:
910     case CSSPropertyTextLineThroughMode:
911     case CSSPropertyTextLineThroughStyle:
912     case CSSPropertyTextOverflow:
913     case CSSPropertyTextOverlineMode:
914     case CSSPropertyTextOverlineStyle:
915     case CSSPropertyTextRendering:
916     case CSSPropertyTextTransform:
917     case CSSPropertyTextUnderlineMode:
918     case CSSPropertyTextUnderlineStyle:
919     case CSSPropertyVisibility:
920     case CSSPropertyWebkitAppearance:
921     case CSSPropertyWebkitBackfaceVisibility:
922     case CSSPropertyWebkitBorderAfterStyle:
923     case CSSPropertyWebkitBorderBeforeStyle:
924     case CSSPropertyWebkitBorderEndStyle:
925     case CSSPropertyWebkitBorderFit:
926     case CSSPropertyWebkitBorderStartStyle:
927     case CSSPropertyWebkitBoxAlign:
928 #if ENABLE(CSS_BOX_DECORATION_BREAK)
929     case CSSPropertyWebkitBoxDecorationBreak:
930 #endif
931     case CSSPropertyWebkitBoxDirection:
932     case CSSPropertyWebkitBoxLines:
933     case CSSPropertyWebkitBoxOrient:
934     case CSSPropertyWebkitBoxPack:
935     case CSSPropertyWebkitColorCorrection:
936     case CSSPropertyWebkitColumnBreakAfter:
937     case CSSPropertyWebkitColumnBreakBefore:
938     case CSSPropertyWebkitColumnBreakInside:
939     case CSSPropertyWebkitColumnRuleStyle:
940 #if ENABLE(CSS3_FLEXBOX)
941     case CSSPropertyWebkitAlignContent:
942     case CSSPropertyWebkitAlignItems:
943     case CSSPropertyWebkitAlignSelf:
944     case CSSPropertyWebkitFlexDirection:
945     case CSSPropertyWebkitFlexWrap:
946     case CSSPropertyWebkitJustifyContent:
947 #endif
948     case CSSPropertyWebkitFontKerning:
949     case CSSPropertyWebkitFontSmoothing:
950     case CSSPropertyWebkitHyphens:
951     case CSSPropertyWebkitLineAlign:
952     case CSSPropertyWebkitLineBreak:
953     case CSSPropertyWebkitLineSnap:
954     case CSSPropertyWebkitMarginAfterCollapse:
955     case CSSPropertyWebkitMarginBeforeCollapse:
956     case CSSPropertyWebkitMarginBottomCollapse:
957     case CSSPropertyWebkitMarginTopCollapse:
958     case CSSPropertyWebkitMarqueeDirection:
959     case CSSPropertyWebkitMarqueeStyle:
960     case CSSPropertyWebkitNbspMode:
961 #if ENABLE(OVERFLOW_SCROLLING)
962     case CSSPropertyWebkitOverflowScrolling:
963 #endif
964     case CSSPropertyWebkitPrintColorAdjust:
965 #if ENABLE(CSS_REGIONS)
966     case CSSPropertyWebkitRegionBreakAfter:
967     case CSSPropertyWebkitRegionBreakBefore:
968     case CSSPropertyWebkitRegionBreakInside:
969     case CSSPropertyWebkitRegionOverflow:
970 #endif
971     case CSSPropertyWebkitRtlOrdering:
972     case CSSPropertyWebkitTextCombine:
973     case CSSPropertyWebkitTextEmphasisPosition:
974     case CSSPropertyWebkitTextSecurity:
975     case CSSPropertyWebkitTextSizeAdjust:
976     case CSSPropertyWebkitTransformStyle:
977     case CSSPropertyWebkitUserDrag:
978     case CSSPropertyWebkitUserModify:
979     case CSSPropertyWebkitUserSelect:
980 #if ENABLE(CSS_EXCLUSIONS)
981     case CSSPropertyWebkitWrapFlow:
982     case CSSPropertyWebkitWrapThrough:
983 #endif
984     case CSSPropertyWebkitWritingMode:
985     case CSSPropertyWhiteSpace:
986     case CSSPropertyWordBreak:
987     case CSSPropertyWordWrap:
988         return true;
989     default:
990         return false;
991     }
992 }
993
994 static bool parseKeywordValue(StylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
995 {
996     ASSERT(!string.isEmpty());
997
998     if (!isKeywordPropertyID(propertyId))
999         return false;
1000
1001     CSSParserString cssString;
1002     cssString.characters = const_cast<UChar*>(string.characters());
1003     cssString.length = string.length();
1004     int valueID = cssValueKeywordID(cssString);
1005
1006     if (!valueID)
1007         return false;
1008
1009     RefPtr<CSSValue> value;
1010     if (valueID == CSSValueInherit)
1011         value = cssValuePool().createInheritedValue();
1012     else if (valueID == CSSValueInitial)
1013         value = cssValuePool().createExplicitInitialValue();
1014     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
1015         value = cssValuePool().createIdentifierValue(valueID);
1016     else
1017         return false;
1018
1019     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
1020     return true;
1021 }
1022
1023 template <typename CharType>
1024 static bool parseTransformArguments(WebKitCSSTransformValue* transformValue, CharType* characters, unsigned length, unsigned start, unsigned expectedCount)
1025 {
1026     while (expectedCount) {
1027         size_t end = WTF::find(characters, length, expectedCount == 1 ? ')' : ',', start);
1028         if (end == notFound || (expectedCount == 1 && end != length - 1))
1029             return false;
1030         unsigned argumentLength = end - start;
1031         CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
1032         double number;
1033         if (!parseSimpleLength(characters + start, argumentLength, unit, number))
1034             return false;
1035         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
1036             return false;
1037         transformValue->append(cssValuePool().createValue(number, unit));
1038         start = end + 1;
1039         --expectedCount;
1040     }
1041     return true;
1042 }
1043
1044 static bool parseTranslateTransformValue(StylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
1045 {
1046     if (propertyID != CSSPropertyWebkitTransform)
1047         return false;
1048     static const unsigned shortestValidTransformStringLength = 12;
1049     static const unsigned likelyMultipartTransformStringLengthCutoff = 32;
1050     if (string.length() < shortestValidTransformStringLength || string.length() > likelyMultipartTransformStringLengthCutoff)
1051         return false;
1052     if (!string.startsWith("translate", false))
1053         return false;
1054     UChar c9 = toASCIILower(string[9]);
1055     UChar c10 = toASCIILower(string[10]);
1056
1057     WebKitCSSTransformValue::TransformOperationType transformType;
1058     unsigned expectedArgumentCount = 1;
1059     unsigned argumentStart = 11;
1060     if (c9 == 'x' && c10 == '(')
1061         transformType = WebKitCSSTransformValue::TranslateXTransformOperation;
1062     else if (c9 == 'y' && c10 == '(')
1063         transformType = WebKitCSSTransformValue::TranslateYTransformOperation;
1064     else if (c9 == 'z' && c10 == '(')
1065         transformType = WebKitCSSTransformValue::TranslateZTransformOperation;
1066     else if (c9 == '(') {
1067         transformType = WebKitCSSTransformValue::TranslateTransformOperation;
1068         expectedArgumentCount = 2;
1069         argumentStart = 10;
1070     } else if (c9 == '3' && c10 == 'd' && string[11] == '(') {
1071         transformType = WebKitCSSTransformValue::Translate3DTransformOperation;
1072         expectedArgumentCount = 3;
1073         argumentStart = 12;
1074     } else
1075         return false;
1076
1077     RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(transformType);
1078     bool success;
1079     if (string.is8Bit())
1080         success = parseTransformArguments(transformValue.get(), string.characters8(), string.length(), argumentStart, expectedArgumentCount);
1081     else
1082         success = parseTransformArguments(transformValue.get(), string.characters16(), string.length(), argumentStart, expectedArgumentCount);
1083     if (!success)
1084         return false;
1085     RefPtr<CSSValueList> result = CSSValueList::createSpaceSeparated();
1086     result->append(transformValue.release());
1087     properties->addParsedProperty(CSSProperty(CSSPropertyWebkitTransform, result.release(), important));
1088     return true;
1089 }
1090
1091 PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string)
1092 {
1093     if (string.isEmpty())
1094         return 0;
1095     RefPtr<StylePropertySet> dummyStyle = StylePropertySet::create();
1096     if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, CSSQuirksMode, 0))
1097         return 0;
1098     return static_pointer_cast<CSSValueList>(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily));
1099 }
1100
1101 #if ENABLE(CSS_VARIABLES)
1102 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, Document* document)
1103 {
1104     ASSERT(!string.isEmpty());
1105
1106     CSSParserContext context(document);
1107
1108     if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode))
1109         return true;
1110     if (parseColorValue(declaration, propertyID, string, important, context.mode))
1111         return true;
1112     if (parseKeywordValue(declaration, propertyID, string, important, context))
1113         return true;
1114
1115     CSSParser parser(context);
1116     return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
1117 }
1118 #endif
1119
1120 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
1121 {
1122     ASSERT(!string.isEmpty());
1123     if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
1124         return true;
1125     if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
1126         return true;
1127     if (parseKeywordValue(declaration, propertyID, string, important, contextStyleSheet->parserContext()))
1128         return true;
1129     if (parseTranslateTransformValue(declaration, propertyID, string, important))
1130         return true;
1131
1132     CSSParserContext context(cssParserMode);
1133     if (contextStyleSheet) {
1134         context = contextStyleSheet->parserContext();
1135         context.mode = cssParserMode;
1136     }
1137     CSSParser parser(context);
1138     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
1139 }
1140
1141 bool CSSParser::parseValue(StylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
1142 {
1143     setStyleSheet(contextStyleSheet);
1144
1145     setupParser("@-webkit-value{", string, "} ");
1146
1147     m_id = propertyID;
1148     m_important = important;
1149
1150     cssyyparse(this);
1151
1152     m_rule = 0;
1153
1154     bool ok = false;
1155     if (m_hasFontFaceOnlyValues)
1156         deleteFontFaceOnlyValues();
1157     if (!m_parsedProperties->isEmpty()) {
1158         ok = true;
1159         declaration->addParsedProperties(*m_parsedProperties);
1160         clearProperties();
1161     }
1162
1163     return ok;
1164 }
1165
1166 // The color will only be changed when string contains a valid CSS color, so callers
1167 // can set it to a default color and ignore the boolean result.
1168 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
1169 {
1170     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
1171     if (fastParseColor(color, string, strict))
1172         return true;
1173
1174     CSSParser parser(CSSStrictMode);
1175
1176     // In case the fast-path parser didn't understand the color, try the full parser.
1177     if (!parser.parseColor(string))
1178         return false;
1179
1180     CSSValue* value = parser.m_parsedProperties->first().value();
1181     if (!value->isPrimitiveValue())
1182         return false;
1183
1184     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
1185     if (!primitiveValue->isRGBColor())
1186         return false;
1187
1188     color = primitiveValue->getRGBA32Value();
1189     return true;
1190 }
1191
1192 bool CSSParser::parseColor(const String& string)
1193 {
1194     setupParser("@-webkit-decls{color:", string, "} ");
1195     cssyyparse(this);
1196     m_rule = 0;
1197
1198     return !m_parsedProperties->isEmpty() && m_parsedProperties->first().id() == CSSPropertyColor;
1199 }
1200
1201 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1202 {
1203     if (!document || !document->page())
1204         return false;
1205
1206     CSSParserString cssColor;
1207     cssColor.characters = const_cast<UChar*>(string.characters());
1208     cssColor.length = string.length();
1209     int id = cssValueKeywordID(cssColor);
1210     if (id <= 0)
1211         return false;
1212
1213     color = document->page()->theme()->systemColor(id).rgb();
1214     return true;
1215 }
1216
1217 void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1218 {
1219     m_selectorListForParseSelector = &selectorList;
1220
1221     setupParser("@-webkit-selector{", string, "}");
1222
1223     cssyyparse(this);
1224
1225     m_selectorListForParseSelector = 0;
1226 }
1227
1228 bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, PassRefPtr<CSSRuleSourceData> prpRuleSourceData, StyleSheetContents* contextStyleSheet)
1229 {
1230     // Length of the "@-webkit-decls{" prefix.
1231     static const unsigned prefixLength = 15;
1232
1233     setStyleSheet(contextStyleSheet);
1234
1235     RefPtr<CSSRuleSourceData> ruleSourceData = prpRuleSourceData;
1236     if (ruleSourceData) {
1237         m_currentRuleDataStack = adoptPtr(new RuleSourceDataList());
1238         m_currentRuleDataStack->append(ruleSourceData);
1239     }
1240
1241     setupParser("@-webkit-decls{", string, "} ");
1242     cssyyparse(this);
1243     m_rule = 0;
1244
1245     bool ok = false;
1246     if (m_hasFontFaceOnlyValues)
1247         deleteFontFaceOnlyValues();
1248     if (!m_parsedProperties->isEmpty()) {
1249         ok = true;
1250         declaration->addParsedProperties(*m_parsedProperties);
1251         clearProperties();
1252     }
1253
1254     if (ruleSourceData) {
1255         ASSERT(m_currentRuleDataStack->size() == 1);
1256         ruleSourceData->ruleBodyRange.start = 0;
1257         ruleSourceData->ruleBodyRange.end = string.length();
1258         for (size_t i = 0, size = ruleSourceData->styleSourceData->propertyData.size(); i < size; ++i) {
1259             CSSPropertySourceData& propertyData = ruleSourceData->styleSourceData->propertyData.at(i);
1260             propertyData.range.start -= prefixLength;
1261             propertyData.range.end -= prefixLength;
1262         }
1263
1264         fixUnparsedPropertyRanges(ruleSourceData.get());
1265         m_currentRuleDataStack.clear();
1266     }
1267
1268     return ok;
1269 }
1270
1271 PassOwnPtr<MediaQuery> CSSParser::parseMediaQuery(const String& string)
1272 {
1273     if (string.isEmpty())
1274         return nullptr;
1275
1276     ASSERT(!m_mediaQuery);
1277
1278     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1279     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
1280     setupParser("@-webkit-mediaquery ", string, "} ");
1281     cssyyparse(this);
1282
1283     return m_mediaQuery.release();
1284 }
1285
1286 #if ENABLE(CSS_VARIABLES)
1287 static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector* input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties, HashSet<AtomicString>& seenVariables)
1288 #else
1289 static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector* input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1290 #endif
1291 {
1292     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1293     for (int i = input->size() - 1; i >= 0; --i) {
1294         const CSSProperty& property = input->at(i);
1295         if (property.isImportant() != important)
1296             continue;
1297 #if ENABLE(CSS_VARIABLES)
1298         if (property.id() == CSSPropertyVariable) {
1299             const AtomicString& name = static_cast<CSSVariableValue*>(property.value())->name();
1300             if (seenVariables.contains(name))
1301                 continue;
1302             seenVariables.add(name);
1303             output[--unusedEntries] = property;
1304             continue;
1305         }
1306 #endif
1307         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1308         if (seenProperties.get(propertyIDIndex))
1309             continue;
1310         seenProperties.set(propertyIDIndex);
1311         output[--unusedEntries] = property;
1312     }
1313 }
1314
1315 PassRefPtr<StylePropertySet> CSSParser::createStylePropertySet()
1316 {
1317     BitArray<numCSSProperties> seenProperties;
1318     size_t unusedEntries = m_parsedProperties->size();
1319     Vector<CSSProperty, 256> results(unusedEntries);
1320
1321     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1322 #if ENABLE(CSS_VARIABLES)
1323     HashSet<AtomicString> seenVariables;
1324     filterProperties(true, m_parsedProperties.get(), results, unusedEntries, seenProperties, seenVariables);
1325     filterProperties(false, m_parsedProperties.get(), results, unusedEntries, seenProperties, seenVariables);
1326 #else
1327     filterProperties(true, m_parsedProperties.get(), results, unusedEntries, seenProperties);
1328     filterProperties(false, m_parsedProperties.get(), results, unusedEntries, seenProperties);
1329 #endif
1330     if (unusedEntries)
1331         results.remove(0, unusedEntries);
1332
1333     return StylePropertySet::createImmutable(results.data(), results.size(), m_context.mode);
1334 }
1335
1336 void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1337 {
1338     m_parsedProperties->append(CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit));
1339 }
1340
1341 void CSSParser::rollbackLastProperties(int num)
1342 {
1343     ASSERT(num >= 0);
1344     ASSERT(m_parsedProperties->size() >= static_cast<unsigned>(num));
1345     m_parsedProperties->shrink(m_parsedProperties->size() - num);
1346 }
1347
1348 void CSSParser::clearProperties()
1349 {
1350     m_parsedProperties->clear();
1351     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1352     m_hasFontFaceOnlyValues = false;
1353 }
1354
1355 void CSSParser::setStyleSheet(StyleSheetContents* styleSheet)
1356 {
1357     m_styleSheet = styleSheet;
1358 }
1359
1360 KURL CSSParser::completeURL(const CSSParserContext& context, const String& url)
1361 {
1362     if (url.isNull())
1363         return KURL();
1364     if (context.charset.isEmpty())
1365         return KURL(context.baseURL, url);
1366     return KURL(context.baseURL, url, context.charset);
1367 }
1368
1369 KURL CSSParser::completeURL(const String& url) const
1370 {
1371     return completeURL(m_context, url);
1372 }
1373
1374 bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags)
1375 {
1376     bool mustBeNonNegative = unitflags & FNonNeg;
1377
1378     if (!parseCalculation(value, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll))
1379         return false;
1380
1381     bool b = false;
1382     switch (m_parsedCalculation->category()) {
1383     case CalcLength:
1384         b = (unitflags & FLength);
1385         break;
1386     case CalcPercent:
1387         b = (unitflags & FPercent);
1388         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1389             b = false;
1390         break;
1391     case CalcNumber:
1392         b = (unitflags & FNumber);
1393         if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt())
1394             b = true;
1395         if (b && mustBeNonNegative && m_parsedCalculation->isNegative())
1396             b = false;
1397         break;
1398     case CalcPercentLength:
1399         b = (unitflags & FPercent) && (unitflags & FLength);
1400         break;
1401     case CalcPercentNumber:
1402         b = (unitflags & FPercent) && (unitflags & FNumber);
1403         break;
1404     case CalcOther:
1405         break;
1406     }
1407     if (!b)
1408         m_parsedCalculation.release();
1409     return b;    
1410 }
1411
1412 inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1413 {
1414     // Qirks mode and svg presentation attributes accept unit less values.
1415     return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || cssParserMode == CSSQuirksMode || cssParserMode == SVGAttributeMode);
1416 }
1417
1418 bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode)
1419 {
1420     if (isCalculation(value))
1421         return validCalculationUnit(value, unitflags);
1422         
1423     bool b = false;
1424     switch (value->unit) {
1425 #if ENABLE(CSS_VARIABLES)
1426     case CSSPrimitiveValue::CSS_VARIABLE_NAME:
1427         // Variables are checked at the point they are dereferenced because unit type is not available here.
1428         b = true;
1429         break;
1430 #endif
1431     case CSSPrimitiveValue::CSS_NUMBER:
1432         b = (unitflags & FNumber);
1433         if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) {
1434             value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
1435                           ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1436             b = true;
1437         }
1438         if (!b && (unitflags & FInteger) && value->isInt)
1439             b = true;
1440         break;
1441     case CSSPrimitiveValue::CSS_PERCENTAGE:
1442         b = (unitflags & FPercent);
1443         break;
1444     case CSSParserValue::Q_EMS:
1445     case CSSPrimitiveValue::CSS_EMS:
1446     case CSSPrimitiveValue::CSS_REMS:
1447     case CSSPrimitiveValue::CSS_EXS:
1448     case CSSPrimitiveValue::CSS_PX:
1449     case CSSPrimitiveValue::CSS_CM:
1450     case CSSPrimitiveValue::CSS_MM:
1451     case CSSPrimitiveValue::CSS_IN:
1452     case CSSPrimitiveValue::CSS_PT:
1453     case CSSPrimitiveValue::CSS_PC:
1454     case CSSPrimitiveValue::CSS_VW:
1455     case CSSPrimitiveValue::CSS_VH:
1456     case CSSPrimitiveValue::CSS_VMIN:
1457         b = (unitflags & FLength);
1458         break;
1459     case CSSPrimitiveValue::CSS_MS:
1460     case CSSPrimitiveValue::CSS_S:
1461         b = (unitflags & FTime);
1462         break;
1463     case CSSPrimitiveValue::CSS_DEG:
1464     case CSSPrimitiveValue::CSS_RAD:
1465     case CSSPrimitiveValue::CSS_GRAD:
1466     case CSSPrimitiveValue::CSS_TURN:
1467         b = (unitflags & FAngle);
1468         break;
1469 #if ENABLE(CSS_IMAGE_RESOLUTION)
1470     case CSSPrimitiveValue::CSS_DPPX:
1471     case CSSPrimitiveValue::CSS_DPI:
1472     case CSSPrimitiveValue::CSS_DPCM:
1473         b = (unitflags & FResolution);
1474         break;
1475 #endif
1476     case CSSPrimitiveValue::CSS_HZ:
1477     case CSSPrimitiveValue::CSS_KHZ:
1478     case CSSPrimitiveValue::CSS_DIMENSION:
1479     default:
1480         break;
1481     }
1482     if (b && unitflags & FNonNeg && value->fValue < 0)
1483         b = false;
1484     return b;
1485 }
1486
1487 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value)
1488 {
1489 #if ENABLE(CSS_VARIABLES)
1490     if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME)
1491         return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME);
1492 #endif
1493
1494     if (m_parsedCalculation) {
1495         ASSERT(isCalculation(value));
1496         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1497     }
1498                
1499 #if ENABLE(CSS_IMAGE_RESOLUTION)
1500     ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1501            || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1502            || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)
1503            || (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM));
1504 #else
1505     ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1506            || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1507            || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN));
1508 #endif
1509     return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
1510 }
1511
1512 inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value)
1513 {
1514     ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
1515     return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING);
1516 }
1517
1518 static int unitFromString(CSSParserValue* value)
1519 {
1520     if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
1521         return 0;
1522
1523     if (equal(value->string, "em"))
1524         return CSSPrimitiveValue::CSS_EMS;
1525     if (equal(value->string, "rem"))
1526         return CSSPrimitiveValue::CSS_REMS;
1527     if (equal(value->string, "ex"))
1528         return CSSPrimitiveValue::CSS_EXS;
1529     if (equal(value->string, "px"))
1530         return CSSPrimitiveValue::CSS_PX;
1531     if (equal(value->string, "cm"))
1532         return CSSPrimitiveValue::CSS_CM;
1533     if (equal(value->string, "mm"))
1534         return CSSPrimitiveValue::CSS_MM;
1535     if (equal(value->string, "in"))
1536         return CSSPrimitiveValue::CSS_IN;
1537     if (equal(value->string, "pt"))
1538         return CSSPrimitiveValue::CSS_PT;
1539     if (equal(value->string, "pc"))
1540         return CSSPrimitiveValue::CSS_PC;
1541     if (equal(value->string, "deg"))
1542         return CSSPrimitiveValue::CSS_DEG;
1543     if (equal(value->string, "rad"))
1544         return CSSPrimitiveValue::CSS_RAD;
1545     if (equal(value->string, "grad"))
1546         return CSSPrimitiveValue::CSS_GRAD;
1547     if (equal(value->string, "turn"))
1548         return CSSPrimitiveValue::CSS_TURN;
1549     if (equal(value->string, "ms"))
1550         return CSSPrimitiveValue::CSS_MS;
1551     if (equal(value->string, "s"))
1552         return CSSPrimitiveValue::CSS_S;
1553     if (equal(value->string, "Hz"))
1554         return CSSPrimitiveValue::CSS_HZ;
1555     if (equal(value->string, "kHz"))
1556         return CSSPrimitiveValue::CSS_KHZ;
1557     if (equal(value->string, "vw"))
1558         return CSSPrimitiveValue::CSS_VW;
1559     if (equal(value->string, "vh"))
1560         return CSSPrimitiveValue::CSS_VH;
1561     if (equal(value->string, "vmin"))
1562         return CSSPrimitiveValue::CSS_VMIN;
1563 #if ENABLE(CSS_IMAGE_RESOLUTION)
1564     if (equal(value->string, "dppx"))
1565         return CSSPrimitiveValue::CSS_DPPX;
1566     if (equal(value->string, "dpi"))
1567         return CSSPrimitiveValue::CSS_DPI;
1568     if (equal(value->string, "dpcm"))
1569         return CSSPrimitiveValue::CSS_DPCM;
1570 #endif
1571
1572     return 0;
1573 }
1574
1575 static inline bool isComma(CSSParserValue* value)
1576
1577     return value && value->unit == CSSParserValue::Operator && value->iValue == ','; 
1578 }
1579
1580 bool CSSParser::validWidth(CSSParserValue* value)
1581 {
1582     int id = value->id;
1583     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic || id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent || id == CSSValueWebkitFillAvailable || id == CSSValueWebkitFitContent)
1584         return true;
1585     return !id && validUnit(value, FLength | FPercent | FNonNeg);
1586 }
1587
1588 // FIXME: Combine this with validWidth when we support fit-content, et al, for heights.
1589 bool CSSParser::validHeight(CSSParserValue* value)
1590 {
1591     int id = value->id;
1592     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1593         return true;
1594     return !id && validUnit(value, FLength | FPercent | FNonNeg);
1595 }
1596
1597 void CSSParser::checkForOrphanedUnits()
1598 {
1599     if (inStrictMode() || inShorthand())
1600         return;
1601
1602     // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
1603     // by whitespace, so e.g., width: 20 px instead of width:20px.  This is invalid CSS, so we don't do this in strict mode.
1604     CSSParserValue* numericVal = 0;
1605     unsigned size = m_valueList->size();
1606     for (unsigned i = 0; i < size; i++) {
1607         CSSParserValue* value = m_valueList->valueAt(i);
1608
1609         if (numericVal) {
1610             // Change the unit type of the numeric val to match.
1611             int unit = unitFromString(value);
1612             if (unit) {
1613                 numericVal->unit = unit;
1614                 numericVal = 0;
1615
1616                 // Now delete the bogus unit value.
1617                 m_valueList->deleteValueAt(i);
1618                 i--; // We're safe even though |i| is unsigned, since we only hit this code if we had a previous numeric value (so |i| is always > 0 here).
1619                 size--;
1620                 continue;
1621             }
1622         }
1623
1624         numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
1625     }
1626 }
1627
1628 inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifier, CSSParserValue* value)
1629 {
1630     if (identifier)
1631         return cssValuePool().createIdentifierValue(identifier);
1632     if (value->unit == CSSPrimitiveValue::CSS_STRING)
1633         return createPrimitiveStringValue(value);
1634     if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
1635         return createPrimitiveNumericValue(value);
1636     if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
1637         return createPrimitiveNumericValue(value);
1638     if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)
1639         return createPrimitiveNumericValue(value);
1640 #if ENABLE(CSS_IMAGE_RESOLUTION)
1641     if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM)
1642         return createPrimitiveNumericValue(value);
1643 #endif
1644 #if ENABLE(CSS_VARIABLES)
1645     if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME)
1646         return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME);
1647 #endif
1648     if (value->unit >= CSSParserValue::Q_EMS)
1649         return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
1650     if (isCalculation(value))
1651         return CSSPrimitiveValue::create(m_parsedCalculation.release());
1652
1653     return 0;
1654 }
1655
1656 bool CSSParser::parseValue(CSSPropertyID propId, bool important)
1657 {
1658     if (!m_valueList)
1659         return false;
1660
1661     CSSParserValue* value = m_valueList->current();
1662
1663     if (!value)
1664         return false;
1665
1666     // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function.
1667     // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers.
1668     ASSERT(!m_parsedCalculation);
1669     
1670     int id = value->id;
1671
1672     // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
1673     // by a space.  We go ahead and associate the unit with the number even though it is invalid CSS.
1674     checkForOrphanedUnits();
1675
1676     int num = inShorthand() ? 1 : m_valueList->size();
1677
1678     if (id == CSSValueInherit) {
1679         if (num != 1)
1680             return false;
1681         addProperty(propId, cssValuePool().createInheritedValue(), important);
1682         return true;
1683     }
1684     else if (id == CSSValueInitial) {
1685         if (num != 1)
1686             return false;
1687         addProperty(propId, cssValuePool().createExplicitInitialValue(), important);
1688         return true;
1689     }
1690
1691 #if ENABLE(CSS_VARIABLES)
1692     if (!id && value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME && num == 1) {
1693         addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME), important);
1694         m_valueList->next();
1695         return true;
1696     }
1697     ASSERT(propId != CSSPropertyVariable);
1698 #endif
1699
1700     if (isKeywordPropertyID(propId)) {
1701         if (!isValidKeywordPropertyAndValue(propId, id, m_context))
1702             return false;
1703         if (m_valueList->next() && !inShorthand())
1704             return false;
1705         addProperty(propId, cssValuePool().createIdentifierValue(id), important);
1706         return true;
1707     }
1708
1709     bool validPrimitive = false;
1710     RefPtr<CSSValue> parsedValue;
1711
1712     switch (propId) {
1713     case CSSPropertySize:                 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1714         return parseSize(propId, important);
1715
1716     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
1717         if (id)
1718             validPrimitive = true;
1719         else
1720             return parseQuotes(propId, important);
1721         break;
1722     case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | isolate-override | plaintext | inherit
1723         if (id == CSSValueNormal
1724             || id == CSSValueEmbed
1725             || id == CSSValueBidiOverride
1726             || id == CSSValueWebkitIsolate
1727             || id == CSSValueWebkitIsolateOverride
1728             || id == CSSValueWebkitPlaintext)
1729             validPrimitive = true;
1730         break;
1731
1732     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1733         // close-quote | no-open-quote | no-close-quote ]+ | inherit
1734         return parseContent(propId, important);
1735
1736     case CSSPropertyClip:                 // <shape> | auto | inherit
1737         if (id == CSSValueAuto)
1738             validPrimitive = true;
1739         else if (value->unit == CSSParserValue::Function)
1740             return parseClipShape(propId, important);
1741         break;
1742
1743     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1744      * correctly and allows optimization in WebCore::applyRule(..)
1745      */
1746     case CSSPropertyOverflow: {
1747         ShorthandScope scope(this, propId);
1748         if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
1749             return false;
1750         CSSValue* value = m_parsedProperties->last().value();
1751         addProperty(CSSPropertyOverflowY, value, important);
1752         return true;
1753     }
1754
1755     case CSSPropertyTextAlign:
1756         // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent
1757         // | start | end | <string> | inherit | -webkit-auto (converted to start)
1758         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
1759             || value->unit == CSSPrimitiveValue::CSS_STRING)
1760             validPrimitive = true;
1761         break;
1762
1763     case CSSPropertyFontWeight:  { // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1764         if (m_valueList->size() != 1)
1765             return false;
1766         return parseFontWeight(important);
1767     }
1768     case CSSPropertyBorderSpacing: {
1769         if (num == 1) {
1770             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1771             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important))
1772                 return false;
1773             CSSValue* value = m_parsedProperties->last().value();
1774             addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important);
1775             return true;
1776         }
1777         else if (num == 2) {
1778             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1779             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important))
1780                 return false;
1781             return true;
1782         }
1783         return false;
1784     }
1785     case CSSPropertyWebkitBorderHorizontalSpacing:
1786     case CSSPropertyWebkitBorderVerticalSpacing:
1787         validPrimitive = validUnit(value, FLength | FNonNeg);
1788         break;
1789     case CSSPropertyOutlineColor:        // <color> | invert | inherit
1790         // Outline color has "invert" as additional keyword.
1791         // Also, we want to allow the special focus color even in strict parsing mode.
1792         if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
1793             validPrimitive = true;
1794             break;
1795         }
1796         /* nobreak */
1797     case CSSPropertyBackgroundColor: // <color> | inherit
1798     case CSSPropertyBorderTopColor: // <color> | inherit
1799     case CSSPropertyBorderRightColor:
1800     case CSSPropertyBorderBottomColor:
1801     case CSSPropertyBorderLeftColor:
1802     case CSSPropertyWebkitBorderStartColor:
1803     case CSSPropertyWebkitBorderEndColor:
1804     case CSSPropertyWebkitBorderBeforeColor:
1805     case CSSPropertyWebkitBorderAfterColor:
1806     case CSSPropertyColor: // <color> | inherit
1807     case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
1808     case CSSPropertyTextUnderlineColor:
1809     case CSSPropertyTextOverlineColor:
1810     case CSSPropertyWebkitColumnRuleColor:
1811     case CSSPropertyWebkitTextEmphasisColor:
1812     case CSSPropertyWebkitTextFillColor:
1813     case CSSPropertyWebkitTextStrokeColor:
1814         if (id == CSSValueWebkitText)
1815             validPrimitive = true; // Always allow this, even when strict parsing is on,
1816                                     // since we use this in our UA sheets.
1817         else if (id == CSSValueCurrentcolor)
1818             validPrimitive = true;
1819         else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
1820              (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
1821             validPrimitive = true;
1822         } else {
1823             parsedValue = parseColor();
1824             if (parsedValue)
1825                 m_valueList->next();
1826         }
1827         break;
1828
1829     case CSSPropertyCursor: {
1830         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
1831         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
1832         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
1833         // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
1834         // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
1835         RefPtr<CSSValueList> list;
1836         while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
1837             if (!list)
1838                 list = CSSValueList::createCommaSeparated();
1839             String uri = value->string;
1840             Vector<int> coords;
1841             value = m_valueList->next();
1842             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
1843                 coords.append(int(value->fValue));
1844                 value = m_valueList->next();
1845             }
1846             IntPoint hotSpot(-1, -1);
1847             int nrcoords = coords.size();
1848             if (nrcoords > 0 && nrcoords != 2)
1849                 return false;
1850             if (nrcoords == 2)
1851                 hotSpot = IntPoint(coords[0], coords[1]);
1852
1853             if (!uri.isNull())
1854                 list->append(CSSCursorImageValue::create(completeURL(uri), hotSpot));
1855
1856             if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
1857                 return false;
1858             value = m_valueList->next(); // comma
1859         }
1860         if (list) {
1861             if (!value) { // no value after url list (MSIE 5 compatibility)
1862                 if (list->length() != 1)
1863                     return false;
1864             } else if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/
1865                 list->append(cssValuePool().createIdentifierValue(CSSValuePointer));
1866             else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1867                 list->append(cssValuePool().createIdentifierValue(value->id));
1868             m_valueList->next();
1869             parsedValue = list.release();
1870             break;
1871         } else if (value) {
1872             id = value->id;
1873             if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/
1874                 id = CSSValuePointer;
1875                 validPrimitive = true;
1876             } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
1877                 validPrimitive = true;
1878         } else {
1879             ASSERT_NOT_REACHED();
1880             return false;
1881         }
1882         break;
1883     }
1884
1885     case CSSPropertyBackgroundAttachment:
1886     case CSSPropertyBackgroundClip:
1887     case CSSPropertyWebkitBackgroundClip:
1888     case CSSPropertyWebkitBackgroundComposite:
1889     case CSSPropertyBackgroundImage:
1890     case CSSPropertyBackgroundOrigin:
1891     case CSSPropertyWebkitBackgroundOrigin:
1892     case CSSPropertyBackgroundPosition:
1893     case CSSPropertyBackgroundPositionX:
1894     case CSSPropertyBackgroundPositionY:
1895     case CSSPropertyBackgroundSize:
1896     case CSSPropertyWebkitBackgroundSize:
1897     case CSSPropertyBackgroundRepeat:
1898     case CSSPropertyBackgroundRepeatX:
1899     case CSSPropertyBackgroundRepeatY:
1900     case CSSPropertyWebkitMaskAttachment:
1901     case CSSPropertyWebkitMaskClip:
1902     case CSSPropertyWebkitMaskComposite:
1903     case CSSPropertyWebkitMaskImage:
1904     case CSSPropertyWebkitMaskOrigin:
1905     case CSSPropertyWebkitMaskPosition:
1906     case CSSPropertyWebkitMaskPositionX:
1907     case CSSPropertyWebkitMaskPositionY:
1908     case CSSPropertyWebkitMaskSize:
1909     case CSSPropertyWebkitMaskRepeat:
1910     case CSSPropertyWebkitMaskRepeatX:
1911     case CSSPropertyWebkitMaskRepeatY: {
1912         RefPtr<CSSValue> val1;
1913         RefPtr<CSSValue> val2;
1914         CSSPropertyID propId1, propId2;
1915         bool result = false;
1916         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
1917             OwnPtr<ShorthandScope> shorthandScope;
1918             if (propId == CSSPropertyBackgroundPosition ||
1919                 propId == CSSPropertyBackgroundRepeat ||
1920                 propId == CSSPropertyWebkitMaskPosition ||
1921                 propId == CSSPropertyWebkitMaskRepeat) {
1922                 shorthandScope = adoptPtr(new ShorthandScope(this, propId));
1923             }
1924             addProperty(propId1, val1.release(), important);
1925             if (val2)
1926                 addProperty(propId2, val2.release(), important);
1927             result = true;
1928         }
1929         m_implicitShorthand = false;
1930         return result;
1931     }
1932     case CSSPropertyListStyleImage:     // <uri> | none | inherit
1933     case CSSPropertyBorderImageSource:
1934     case CSSPropertyWebkitMaskBoxImageSource:
1935         if (id == CSSValueNone) {
1936             parsedValue = cssValuePool().createIdentifierValue(CSSValueNone);
1937             m_valueList->next();
1938         } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
1939             parsedValue = CSSImageValue::create(completeURL(value->string));
1940             m_valueList->next();
1941         } else if (isGeneratedImageValue(value)) {
1942             if (parseGeneratedImage(m_valueList.get(), parsedValue))
1943                 m_valueList->next();
1944             else
1945                 return false;
1946         }
1947 #if ENABLE(CSS_IMAGE_SET)
1948         else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
1949             parsedValue = parseImageSet(m_valueList.get());
1950             if (!parsedValue)
1951                 return false;
1952             m_valueList->next();
1953         }
1954 #endif
1955         break;
1956
1957     case CSSPropertyWebkitTextStrokeWidth:
1958     case CSSPropertyOutlineWidth:        // <border-width> | inherit
1959     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
1960     case CSSPropertyBorderRightWidth:   //   Which is defined as
1961     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
1962     case CSSPropertyBorderLeftWidth:
1963     case CSSPropertyWebkitBorderStartWidth:
1964     case CSSPropertyWebkitBorderEndWidth:
1965     case CSSPropertyWebkitBorderBeforeWidth:
1966     case CSSPropertyWebkitBorderAfterWidth:
1967     case CSSPropertyWebkitColumnRuleWidth:
1968         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
1969             validPrimitive = true;
1970         else
1971             validPrimitive = validUnit(value, FLength | FNonNeg);
1972         break;
1973
1974     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
1975     case CSSPropertyWordSpacing:         // normal | <length> | inherit
1976         if (id == CSSValueNormal)
1977             validPrimitive = true;
1978         else
1979             validPrimitive = validUnit(value, FLength);
1980         break;
1981
1982     case CSSPropertyTextIndent:          // <length> | <percentage> | inherit
1983         validPrimitive = (!id && validUnit(value, FLength | FPercent));
1984         break;
1985
1986     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
1987     case CSSPropertyPaddingRight:        //   Which is defined as
1988     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
1989     case CSSPropertyPaddingLeft:         ////
1990     case CSSPropertyWebkitPaddingStart:
1991     case CSSPropertyWebkitPaddingEnd:
1992     case CSSPropertyWebkitPaddingBefore:
1993     case CSSPropertyWebkitPaddingAfter:
1994         validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
1995         break;
1996
1997     case CSSPropertyMaxWidth:
1998     case CSSPropertyWebkitMaxLogicalWidth:
1999         validPrimitive = (id == CSSValueNone || validWidth(value));
2000         break;
2001
2002     case CSSPropertyMinWidth:
2003     case CSSPropertyWebkitMinLogicalWidth:
2004     case CSSPropertyWidth:
2005     case CSSPropertyWebkitLogicalWidth:
2006         validPrimitive = (id == CSSValueAuto || validWidth(value));
2007         break;
2008
2009     case CSSPropertyMaxHeight:
2010     case CSSPropertyWebkitMaxLogicalHeight:
2011         validPrimitive = (id == CSSValueNone || validHeight(value));
2012         break;
2013
2014     case CSSPropertyMinHeight:
2015     case CSSPropertyWebkitMinLogicalHeight:
2016     case CSSPropertyHeight:
2017     case CSSPropertyWebkitLogicalHeight:
2018         validPrimitive = (id == CSSValueAuto || validHeight(value));
2019         break;
2020
2021     case CSSPropertyFontSize:
2022         return parseFontSize(important);
2023
2024     case CSSPropertyFontVariant:         // normal | small-caps | inherit
2025         return parseFontVariant(important);
2026
2027     case CSSPropertyVerticalAlign:
2028         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
2029         // <percentage> | <length> | inherit
2030
2031         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
2032             validPrimitive = true;
2033         else
2034             validPrimitive = (!id && validUnit(value, FLength | FPercent));
2035         break;
2036
2037     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
2038     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
2039     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
2040     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
2041     case CSSPropertyMarginTop:           //// <margin-width> | inherit
2042     case CSSPropertyMarginRight:         //   Which is defined as
2043     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
2044     case CSSPropertyMarginLeft:          ////
2045     case CSSPropertyWebkitMarginStart:
2046     case CSSPropertyWebkitMarginEnd:
2047     case CSSPropertyWebkitMarginBefore:
2048     case CSSPropertyWebkitMarginAfter:
2049         if (id == CSSValueAuto)
2050             validPrimitive = true;
2051         else
2052             validPrimitive = (!id && validUnit(value, FLength | FPercent));
2053         break;
2054
2055     case CSSPropertyZIndex:              // auto | <integer> | inherit
2056         if (id == CSSValueAuto) {
2057             validPrimitive = true;
2058             break;
2059         }
2060         /* nobreak */
2061     case CSSPropertyOrphans:              // <integer> | inherit
2062     case CSSPropertyWidows:               // <integer> | inherit
2063         // ### not supported later on
2064         validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode));
2065         break;
2066
2067     case CSSPropertyLineHeight:
2068         return parseLineHeight(important);
2069     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
2070         if (id != CSSValueNone)
2071             return parseCounter(propId, 1, important);
2072         validPrimitive = true;
2073         break;
2074     case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
2075         if (id != CSSValueNone)
2076             return parseCounter(propId, 0, important);
2077         validPrimitive = true;
2078         break;
2079     case CSSPropertyFontFamily:
2080         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
2081     {
2082         parsedValue = parseFontFamily();
2083         break;
2084     }
2085
2086     case CSSPropertyTextDecoration:
2087     case CSSPropertyWebkitTextDecorationsInEffect:
2088         // none | [ underline || overline || line-through || blink ] | inherit
2089         return parseTextDecoration(propId, important);
2090
2091 #if ENABLE(CSS3_TEXT_DECORATION)
2092     case CSSPropertyWebkitTextDecorationLine:
2093         // none | [ underline || overline || line-through ] | inherit
2094         return parseTextDecoration(propId, important);
2095
2096     case CSSPropertyWebkitTextDecorationStyle:
2097         // solid | double | dotted | dashed | wavy
2098         if (id == CSSValueSolid || id == CSSValueDouble || id == CSSValueDotted || id == CSSValueDashed || id == CSSValueWavy)
2099             validPrimitive = true;
2100         break;
2101 #endif // CSS3_TEXT_DECORATION
2102
2103     case CSSPropertyZoom:          // normal | reset | document | <number> | <percentage> | inherit
2104         if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
2105             validPrimitive = true;
2106         else
2107             validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, CSSStrictMode));
2108         break;
2109
2110     case CSSPropertySrc:  // Only used within @font-face, so cannot use inherit | initial or be !important.  This is a list of urls or local references.
2111         return parseFontFaceSrc();
2112
2113     case CSSPropertyUnicodeRange:
2114         return parseFontFaceUnicodeRange();
2115
2116     /* CSS3 properties */
2117
2118     case CSSPropertyBorderImage: {
2119         RefPtr<CSSValue> result;
2120         return parseBorderImage(propId, result, important);
2121     }
2122     case CSSPropertyWebkitBorderImage:
2123     case CSSPropertyWebkitMaskBoxImage: {
2124         RefPtr<CSSValue> result;
2125         if (parseBorderImage(propId, result)) {
2126             addProperty(propId, result, important);
2127             return true;
2128         }
2129         break;
2130     }
2131     case CSSPropertyBorderImageOutset:
2132     case CSSPropertyWebkitMaskBoxImageOutset: {
2133         RefPtr<CSSPrimitiveValue> result;
2134         if (parseBorderImageOutset(result)) {
2135             addProperty(propId, result, important);
2136             return true;
2137         }
2138         break;
2139     }
2140     case CSSPropertyBorderImageRepeat:
2141     case CSSPropertyWebkitMaskBoxImageRepeat: {
2142         RefPtr<CSSValue> result;
2143         if (parseBorderImageRepeat(result)) {
2144             addProperty(propId, result, important);
2145             return true;
2146         }
2147         break;
2148     }
2149     case CSSPropertyBorderImageSlice:
2150     case CSSPropertyWebkitMaskBoxImageSlice: {
2151         RefPtr<CSSBorderImageSliceValue> result;
2152         if (parseBorderImageSlice(propId, result)) {
2153             addProperty(propId, result, important);
2154             return true;
2155         }
2156         break;
2157     }
2158     case CSSPropertyBorderImageWidth:
2159     case CSSPropertyWebkitMaskBoxImageWidth: {
2160         RefPtr<CSSPrimitiveValue> result;
2161         if (parseBorderImageWidth(result)) {
2162             addProperty(propId, result, important);
2163             return true;
2164         }
2165         break;
2166     }
2167     case CSSPropertyBorderTopRightRadius:
2168     case CSSPropertyBorderTopLeftRadius:
2169     case CSSPropertyBorderBottomLeftRadius:
2170     case CSSPropertyBorderBottomRightRadius: {
2171         if (num != 1 && num != 2)
2172             return false;
2173         validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
2174         if (!validPrimitive)
2175             return false;
2176         RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
2177         RefPtr<CSSPrimitiveValue> parsedValue2;
2178         if (num == 2) {
2179             value = m_valueList->next();
2180             validPrimitive = validUnit(value, FLength | FPercent | FNonNeg);
2181             if (!validPrimitive)
2182                 return false;
2183             parsedValue2 = createPrimitiveNumericValue(value);
2184         } else
2185             parsedValue2 = parsedValue1;
2186
2187         RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
2188         RefPtr<CSSPrimitiveValue> val = cssValuePool().createValue(pair.release());
2189         addProperty(propId, val.release(), important);
2190         return true;
2191     }
2192     case CSSPropertyTabSize:
2193         validPrimitive = validUnit(value, FInteger | FNonNeg);
2194         break;
2195     case CSSPropertyWebkitAspectRatio:
2196         return parseAspectRatio(important);
2197     case CSSPropertyBorderRadius:
2198     case CSSPropertyWebkitBorderRadius:
2199         return parseBorderRadius(propId, important);
2200     case CSSPropertyOutlineOffset:
2201         validPrimitive = validUnit(value, FLength | FPercent);
2202         break;
2203     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
2204     case CSSPropertyBoxShadow:
2205     case CSSPropertyWebkitBoxShadow:
2206         if (id == CSSValueNone)
2207             validPrimitive = true;
2208         else {
2209             RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
2210             if (shadowValueList) {
2211                 addProperty(propId, shadowValueList.release(), important);
2212                 m_valueList->next();
2213                 return true;
2214             }
2215             return false;
2216         }
2217         break;
2218     case CSSPropertyWebkitBoxReflect:
2219         if (id == CSSValueNone)
2220             validPrimitive = true;
2221         else
2222             return parseReflect(propId, important);
2223         break;
2224     case CSSPropertyOpacity:
2225         validPrimitive = validUnit(value, FNumber);
2226         break;
2227     case CSSPropertyWebkitBoxFlex:
2228         validPrimitive = validUnit(value, FNumber);
2229         break;
2230     case CSSPropertyWebkitBoxFlexGroup:
2231         validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode);
2232         break;
2233     case CSSPropertyWebkitBoxOrdinalGroup:
2234         validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode) && value->fValue;
2235         break;
2236 #if ENABLE(CSS_FILTERS)
2237     case CSSPropertyWebkitFilter:
2238         if (id == CSSValueNone)
2239             validPrimitive = true;
2240         else {
2241             RefPtr<CSSValue> val = parseFilter();
2242             if (val) {
2243                 addProperty(propId, val, important);
2244                 return true;
2245             }
2246             return false;
2247         }
2248         break;
2249 #endif
2250 #if ENABLE(CSS3_FLEXBOX)
2251     case CSSPropertyWebkitFlex: {
2252         ShorthandScope scope(this, propId);
2253         if (id == CSSValueNone) {
2254             addProperty(CSSPropertyWebkitFlexGrow, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2255             addProperty(CSSPropertyWebkitFlexShrink, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2256             addProperty(CSSPropertyWebkitFlexBasis, cssValuePool().createIdentifierValue(CSSValueAuto), important);
2257             return true;
2258         }
2259         return parseFlex(m_valueList.get(), important);
2260     }
2261     case CSSPropertyWebkitFlexBasis:
2262         // FIXME: Support intrinsic dimensions too.
2263         if (id == CSSValueAuto)
2264             validPrimitive = true;
2265         else
2266             validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg));
2267         break;
2268     case CSSPropertyWebkitFlexGrow:
2269     case CSSPropertyWebkitFlexShrink:
2270         validPrimitive = validUnit(value, FNumber | FNonNeg);
2271         break;
2272     case CSSPropertyWebkitOrder:
2273         if (validUnit(value, FInteger, CSSStrictMode)) {
2274             // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set.
2275             parsedValue = cssValuePool().createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue),
2276                                                              static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
2277             m_valueList->next();
2278         }
2279         break;
2280 #endif
2281     case CSSPropertyWebkitMarquee:
2282         return parseShorthand(propId, webkitMarqueeShorthand(), important);
2283     case CSSPropertyWebkitMarqueeIncrement:
2284         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2285             validPrimitive = true;
2286         else
2287             validPrimitive = validUnit(value, FLength | FPercent);
2288         break;
2289     case CSSPropertyWebkitMarqueeRepetition:
2290         if (id == CSSValueInfinite)
2291             validPrimitive = true;
2292         else
2293             validPrimitive = validUnit(value, FInteger | FNonNeg);
2294         break;
2295     case CSSPropertyWebkitMarqueeSpeed:
2296         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2297             validPrimitive = true;
2298         else
2299             validPrimitive = validUnit(value, FTime | FInteger | FNonNeg);
2300         break;
2301 #if ENABLE(CSS_REGIONS)
2302     case CSSPropertyWebkitFlowInto:
2303         if (!cssRegionsEnabled())
2304             return false;
2305         return parseFlowThread(propId, important);
2306     case CSSPropertyWebkitFlowFrom:
2307         if (!cssRegionsEnabled())
2308             return false;
2309         return parseRegionThread(propId, important);
2310 #endif
2311     case CSSPropertyWebkitTransform:
2312         if (id == CSSValueNone)
2313             validPrimitive = true;
2314         else {
2315             RefPtr<CSSValue> transformValue = parseTransform();
2316             if (transformValue) {
2317                 addProperty(propId, transformValue.release(), important);
2318                 return true;
2319             }
2320             return false;
2321         }
2322         break;
2323     case CSSPropertyWebkitTransformOrigin:
2324     case CSSPropertyWebkitTransformOriginX:
2325     case CSSPropertyWebkitTransformOriginY:
2326     case CSSPropertyWebkitTransformOriginZ: {
2327         RefPtr<CSSValue> val1;
2328         RefPtr<CSSValue> val2;
2329         RefPtr<CSSValue> val3;
2330         CSSPropertyID propId1, propId2, propId3;
2331         if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2332             addProperty(propId1, val1.release(), important);
2333             if (val2)
2334                 addProperty(propId2, val2.release(), important);
2335             if (val3)
2336                 addProperty(propId3, val3.release(), important);
2337             return true;
2338         }
2339         return false;
2340     }
2341     case CSSPropertyWebkitPerspective:
2342         if (id == CSSValueNone)
2343             validPrimitive = true;
2344         else {
2345             // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2346             if (validUnit(value, FNumber | FLength | FNonNeg)) {
2347                 RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
2348                 if (val) {
2349                     addProperty(propId, val.release(), important);
2350                     return true;
2351                 }
2352                 return false;
2353             }
2354         }
2355         break;
2356     case CSSPropertyWebkitPerspectiveOrigin:
2357     case CSSPropertyWebkitPerspectiveOriginX:
2358     case CSSPropertyWebkitPerspectiveOriginY: {
2359         RefPtr<CSSValue> val1;
2360         RefPtr<CSSValue> val2;
2361         CSSPropertyID propId1, propId2;
2362         if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2363             addProperty(propId1, val1.release(), important);
2364             if (val2)
2365                 addProperty(propId2, val2.release(), important);
2366             return true;
2367         }
2368         return false;
2369     }
2370     case CSSPropertyWebkitAnimationDelay:
2371     case CSSPropertyWebkitAnimationDirection:
2372     case CSSPropertyWebkitAnimationDuration:
2373     case CSSPropertyWebkitAnimationFillMode:
2374     case CSSPropertyWebkitAnimationName:
2375     case CSSPropertyWebkitAnimationPlayState:
2376     case CSSPropertyWebkitAnimationIterationCount:
2377     case CSSPropertyWebkitAnimationTimingFunction:
2378     case CSSPropertyWebkitTransitionDelay:
2379     case CSSPropertyWebkitTransitionDuration:
2380     case CSSPropertyWebkitTransitionTimingFunction:
2381     case CSSPropertyWebkitTransitionProperty: {
2382         RefPtr<CSSValue> val;
2383         if (parseAnimationProperty(propId, val)) {
2384             addProperty(propId, val.release(), important);
2385             return true;
2386         }
2387         return false;
2388     }
2389
2390     case CSSPropertyWebkitGridColumns:
2391     case CSSPropertyWebkitGridRows:
2392         if (!cssGridLayoutEnabled())
2393             return false;
2394         return parseGridTrackList(propId, important);
2395
2396     case CSSPropertyWebkitGridColumn:
2397     case CSSPropertyWebkitGridRow:
2398         if (!cssGridLayoutEnabled())
2399             return false;
2400         validPrimitive = id == CSSValueAuto || validUnit(value, FInteger);
2401         break;
2402
2403     case CSSPropertyWebkitMarginCollapse: {
2404         if (num == 1) {
2405             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2406             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important))
2407                 return false;
2408             CSSValue* value = m_parsedProperties->last().value();
2409             addProperty(webkitMarginCollapseShorthand().properties()[1], value, important);
2410             return true;
2411         }
2412         else if (num == 2) {
2413             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2414             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important))
2415                 return false;
2416             return true;
2417         }
2418         return false;
2419     }
2420     case CSSPropertyTextLineThroughWidth:
2421     case CSSPropertyTextOverlineWidth:
2422     case CSSPropertyTextUnderlineWidth:
2423         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2424             id == CSSValueMedium || id == CSSValueThick)
2425             validPrimitive = true;
2426         else
2427             validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent);
2428         break;
2429     case CSSPropertyWebkitColumnCount:
2430         if (id == CSSValueAuto)
2431             validPrimitive = true;
2432         else
2433             validPrimitive = !id && validUnit(value, FInteger | FNonNeg, CSSQuirksMode);
2434         break;
2435     case CSSPropertyWebkitColumnGap:         // normal | <length>
2436         if (id == CSSValueNormal)
2437             validPrimitive = true;
2438         else
2439             validPrimitive = validUnit(value, FLength | FNonNeg);
2440         break;
2441     case CSSPropertyWebkitColumnAxis:
2442         if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2443             validPrimitive = true;
2444         break;
2445     case CSSPropertyWebkitColumnProgression:
2446         if (id == CSSValueNormal || id == CSSValueReverse)
2447             validPrimitive = true;
2448         break;
2449     case CSSPropertyWebkitColumnSpan:        // all | 1
2450         if (id == CSSValueAll)
2451             validPrimitive = true;
2452         else
2453             validPrimitive = validUnit(value, FNumber | FNonNeg) && value->fValue == 1;
2454         break;
2455     case CSSPropertyWebkitColumnWidth:         // auto | <length>
2456         if (id == CSSValueAuto)
2457             validPrimitive = true;
2458         else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
2459             validPrimitive = validUnit(value, FLength, CSSStrictMode);
2460         break;
2461     // End of CSS3 properties
2462
2463     // Apple specific properties.  These will never be standardized and are purely to
2464     // support custom WebKit-based Apple applications.
2465     case CSSPropertyWebkitLineClamp:
2466         // When specifying number of lines, don't allow 0 as a valid value
2467         // When specifying either type of unit, require non-negative integers
2468         validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, CSSQuirksMode));
2469         break;
2470
2471     case CSSPropertyWebkitFontSizeDelta:           // <length>
2472         validPrimitive = validUnit(value, FLength);
2473         break;
2474
2475     case CSSPropertyWebkitHighlight:
2476         if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
2477             validPrimitive = true;
2478         break;
2479
2480     case CSSPropertyWebkitHyphenateCharacter:
2481         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2482             validPrimitive = true;
2483         break;
2484
2485     case CSSPropertyWebkitHyphenateLimitBefore:
2486     case CSSPropertyWebkitHyphenateLimitAfter:
2487         if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2488             validPrimitive = true;
2489         break;
2490
2491     case CSSPropertyWebkitHyphenateLimitLines:
2492         if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, CSSStrictMode))
2493             validPrimitive = true;
2494         break;
2495
2496     case CSSPropertyWebkitLineGrid:
2497         if (id == CSSValueNone)
2498             validPrimitive = true;
2499         else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
2500             String lineGridValue = String(value->string);
2501             if (!lineGridValue.isEmpty()) {
2502                 addProperty(propId, cssValuePool().createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
2503                 return true;
2504             }
2505         }
2506         break;
2507     case CSSPropertyWebkitLocale:
2508         if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
2509             validPrimitive = true;
2510         break;
2511
2512 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION)
2513 #if ENABLE(DASHBOARD_SUPPORT)
2514     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
2515 #endif
2516 #if ENABLE(WIDGET_REGION)
2517     case CSSPropertyWebkitWidgetRegion:
2518 #endif
2519         if (value->unit == CSSParserValue::Function || id == CSSValueNone)
2520             return parseDashboardRegions(propId, important);
2521         break;
2522 #endif
2523     // End Apple-specific properties
2524
2525 #if ENABLE(TOUCH_EVENTS)
2526     case CSSPropertyWebkitTapHighlightColor:
2527         if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
2528             || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2529             validPrimitive = true;
2530         } else {
2531             parsedValue = parseColor();
2532             if (parsedValue)
2533                 m_valueList->next();
2534         }
2535         break;
2536 #endif
2537
2538         /* shorthand properties */
2539     case CSSPropertyBackground: {
2540         // Position must come before color in this array because a plain old "0" is a legal color
2541         // in quirks mode but it's usually the X coordinate of a position.
2542         const CSSPropertyID properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2543                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2544                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor, CSSPropertyBackgroundSize };
2545         return parseFillShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2546     }
2547     case CSSPropertyWebkitMask: {
2548         const CSSPropertyID properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
2549                                    CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
2550                                    CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
2551         return parseFillShorthand(propId, properties, 6, important);
2552     }
2553     case CSSPropertyBorder:
2554         // [ 'border-width' || 'border-style' || <color> ] | inherit
2555     {
2556         if (parseShorthand(propId, borderAbridgedShorthand(), important)) {
2557             // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2558             // though a value of none was specified for the image.
2559             addProperty(CSSPropertyBorderImage, cssValuePool().createImplicitInitialValue(), important);
2560             return true;
2561         }
2562         return false;
2563     }
2564     case CSSPropertyBorderTop:
2565         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2566         return parseShorthand(propId, borderTopShorthand(), important);
2567     case CSSPropertyBorderRight:
2568         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2569         return parseShorthand(propId, borderRightShorthand(), important);
2570     case CSSPropertyBorderBottom:
2571         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2572         return parseShorthand(propId, borderBottomShorthand(), important);
2573     case CSSPropertyBorderLeft:
2574         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2575         return parseShorthand(propId, borderLeftShorthand(), important);
2576     case CSSPropertyWebkitBorderStart:
2577         return parseShorthand(propId, webkitBorderStartShorthand(), important);
2578     case CSSPropertyWebkitBorderEnd:
2579         return parseShorthand(propId, webkitBorderEndShorthand(), important);
2580     case CSSPropertyWebkitBorderBefore:
2581         return parseShorthand(propId, webkitBorderBeforeShorthand(), important);
2582     case CSSPropertyWebkitBorderAfter:
2583         return parseShorthand(propId, webkitBorderAfterShorthand(), important);
2584     case CSSPropertyOutline:
2585         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2586         return parseShorthand(propId, outlineShorthand(), important);
2587     case CSSPropertyBorderColor:
2588         // <color>{1,4} | inherit
2589         return parse4Values(propId, borderColorShorthand().properties(), important);
2590     case CSSPropertyBorderWidth:
2591         // <border-width>{1,4} | inherit
2592         return parse4Values(propId, borderWidthShorthand().properties(), important);
2593     case CSSPropertyBorderStyle:
2594         // <border-style>{1,4} | inherit
2595         return parse4Values(propId, borderStyleShorthand().properties(), important);
2596     case CSSPropertyMargin:
2597         // <margin-width>{1,4} | inherit
2598         return parse4Values(propId, marginShorthand().properties(), important);
2599     case CSSPropertyPadding:
2600         // <padding-width>{1,4} | inherit
2601         return parse4Values(propId, paddingShorthand().properties(), important);
2602 #if ENABLE(CSS3_FLEXBOX)
2603     case CSSPropertyWebkitFlexFlow:
2604         return parseShorthand(propId, webkitFlexFlowShorthand(), important);
2605 #endif
2606     case CSSPropertyFont:
2607         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2608         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2609         if (id >= CSSValueCaption && id <= CSSValueStatusBar)
2610             validPrimitive = true;
2611         else
2612             return parseFont(important);
2613         break;
2614     case CSSPropertyListStyle:
2615         return parseShorthand(propId, listStyleShorthand(), important);
2616     case CSSPropertyWebkitColumns:
2617         return parseShorthand(propId, webkitColumnsShorthand(), important);
2618     case CSSPropertyWebkitColumnRule:
2619         return parseShorthand(propId, webkitColumnRuleShorthand(), important);
2620     case CSSPropertyWebkitTextStroke:
2621         return parseShorthand(propId, webkitTextStrokeShorthand(), important);
2622     case CSSPropertyWebkitAnimation:
2623         return parseAnimationShorthand(important);
2624     case CSSPropertyWebkitTransition:
2625         return parseTransitionShorthand(important);
2626     case CSSPropertyInvalid:
2627         return false;
2628     case CSSPropertyPage:
2629         return parsePage(propId, important);
2630     case CSSPropertyFontStretch:
2631     case CSSPropertyTextLineThrough:
2632     case CSSPropertyTextOverline:
2633     case CSSPropertyTextUnderline:
2634         return false;
2635     // CSS Text Layout Module Level 3: Vertical writing support
2636     case CSSPropertyWebkitTextEmphasis:
2637         return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
2638
2639     case CSSPropertyWebkitTextEmphasisStyle:
2640         return parseTextEmphasisStyle(important);
2641
2642     case CSSPropertyWebkitTextOrientation:
2643         // FIXME: For now just support upright and vertical-right.
2644         if (id == CSSValueVerticalRight || id == CSSValueUpright)
2645             validPrimitive = true;
2646         break;
2647
2648     case CSSPropertyWebkitLineBoxContain:
2649         if (id == CSSValueNone)
2650             validPrimitive = true;
2651         else
2652             return parseLineBoxContain(important);
2653         break;
2654     case CSSPropertyWebkitFontFeatureSettings:
2655         if (id == CSSValueNormal)
2656             validPrimitive = true;
2657         else
2658             return parseFontFeatureSettings(important);
2659         break;
2660
2661     case CSSPropertyWebkitFontVariantLigatures:
2662         if (id == CSSValueNormal)
2663             validPrimitive = true;
2664         else
2665             return parseFontVariantLigatures(important);
2666         break;
2667 #if ENABLE(CSS_EXCLUSIONS)
2668     case CSSPropertyWebkitShapeInside:
2669     case CSSPropertyWebkitShapeOutside:
2670         if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
2671             return false;
2672         if (id == CSSValueAuto)
2673             validPrimitive = true;
2674         else if (value->unit == CSSParserValue::Function)
2675             return parseExclusionShape((propId == CSSPropertyWebkitShapeInside), important);
2676         break;
2677     case CSSPropertyWebkitWrapMargin:
2678     case CSSPropertyWebkitWrapPadding:
2679         validPrimitive = (RuntimeEnabledFeatures::cssExclusionsEnabled() && !id && validUnit(value, FLength | FNonNeg));
2680         break;
2681     case CSSPropertyWebkitWrap:
2682         return RuntimeEnabledFeatures::cssExclusionsEnabled() && parseShorthand(propId, webkitWrapShorthand(), important);
2683 #endif
2684 #if ENABLE(CSS_IMAGE_ORIENTATION)
2685     case CSSPropertyImageOrientation:
2686         validPrimitive = !id && validUnit(value, FAngle);
2687         break;
2688 #endif
2689 #if ENABLE(CSS_IMAGE_RESOLUTION)
2690     case CSSPropertyImageResolution:
2691         parsedValue = parseImageResolution(m_valueList.get());
2692         if (!parsedValue)
2693             return false;
2694         m_valueList->next();
2695         break;
2696 #endif
2697     case CSSPropertyBorderBottomStyle:
2698     case CSSPropertyBorderCollapse:
2699     case CSSPropertyBorderLeftStyle:
2700     case CSSPropertyBorderRightStyle:
2701     case CSSPropertyBorderTopStyle:
2702     case CSSPropertyBoxSizing:
2703     case CSSPropertyCaptionSide:
2704     case CSSPropertyClear:
2705     case CSSPropertyDirection:
2706     case CSSPropertyDisplay:
2707     case CSSPropertyEmptyCells:
2708     case CSSPropertyFloat:
2709     case CSSPropertyFontStyle:
2710     case CSSPropertyImageRendering:
2711     case CSSPropertyListStylePosition:
2712     case CSSPropertyListStyleType:
2713     case CSSPropertyOutlineStyle:
2714     case CSSPropertyOverflowX:
2715     case CSSPropertyOverflowY:
2716     case CSSPropertyPageBreakAfter:
2717     case CSSPropertyPageBreakBefore:
2718     case CSSPropertyPageBreakInside:
2719     case CSSPropertyPointerEvents:
2720     case CSSPropertyPosition:
2721     case CSSPropertyResize:
2722     case CSSPropertySpeak:
2723     case CSSPropertyTableLayout:
2724     case CSSPropertyTextLineThroughMode:
2725     case CSSPropertyTextLineThroughStyle:
2726     case CSSPropertyTextOverflow:
2727     case CSSPropertyTextOverlineMode:
2728     case CSSPropertyTextOverlineStyle:
2729     case CSSPropertyTextRendering:
2730     case CSSPropertyTextTransform:
2731     case CSSPropertyTextUnderlineMode:
2732     case CSSPropertyTextUnderlineStyle:
2733 #if ENABLE(CSS_VARIABLES)
2734     case CSSPropertyVariable:
2735 #endif
2736     case CSSPropertyVisibility:
2737     case CSSPropertyWebkitAppearance:
2738     case CSSPropertyWebkitBackfaceVisibility:
2739     case CSSPropertyWebkitBorderAfterStyle:
2740     case CSSPropertyWebkitBorderBeforeStyle:
2741     case CSSPropertyWebkitBorderEndStyle:
2742     case CSSPropertyWebkitBorderFit:
2743     case CSSPropertyWebkitBorderStartStyle:
2744     case CSSPropertyWebkitBoxAlign:
2745 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2746     case CSSPropertyWebkitBoxDecorationBreak:
2747 #endif
2748     case CSSPropertyWebkitBoxDirection:
2749     case CSSPropertyWebkitBoxLines:
2750     case CSSPropertyWebkitBoxOrient:
2751     case CSSPropertyWebkitBoxPack:
2752     case CSSPropertyWebkitColorCorrection:
2753     case CSSPropertyWebkitColumnBreakAfter:
2754     case CSSPropertyWebkitColumnBreakBefore:
2755     case CSSPropertyWebkitColumnBreakInside:
2756     case CSSPropertyWebkitColumnRuleStyle:
2757 #if ENABLE(CSS3_FLEXBOX)
2758     case CSSPropertyWebkitAlignContent:
2759     case CSSPropertyWebkitAlignItems:
2760     case CSSPropertyWebkitAlignSelf:
2761     case CSSPropertyWebkitFlexDirection:
2762     case CSSPropertyWebkitFlexWrap:
2763     case CSSPropertyWebkitJustifyContent:
2764 #endif
2765     case CSSPropertyWebkitFontKerning:
2766     case CSSPropertyWebkitFontSmoothing:
2767     case CSSPropertyWebkitHyphens:
2768     case CSSPropertyWebkitLineAlign:
2769     case CSSPropertyWebkitLineBreak:
2770     case CSSPropertyWebkitLineSnap:
2771     case CSSPropertyWebkitMarginAfterCollapse:
2772     case CSSPropertyWebkitMarginBeforeCollapse:
2773     case CSSPropertyWebkitMarginBottomCollapse:
2774     case CSSPropertyWebkitMarginTopCollapse:
2775     case CSSPropertyWebkitMarqueeDirection:
2776     case CSSPropertyWebkitMarqueeStyle:
2777     case CSSPropertyWebkitNbspMode:
2778 #if ENABLE(OVERFLOW_SCROLLING)
2779     case CSSPropertyWebkitOverflowScrolling:
2780 #endif
2781     case CSSPropertyWebkitPrintColorAdjust:
2782 #if ENABLE(CSS_REGIONS)
2783     case CSSPropertyWebkitRegionBreakAfter:
2784     case CSSPropertyWebkitRegionBreakBefore:
2785     case CSSPropertyWebkitRegionBreakInside:
2786     case CSSPropertyWebkitRegionOverflow:
2787 #endif
2788     case CSSPropertyWebkitRtlOrdering:
2789     case CSSPropertyWebkitTextCombine:
2790     case CSSPropertyWebkitTextEmphasisPosition:
2791     case CSSPropertyWebkitTextSecurity:
2792     case CSSPropertyWebkitTextSizeAdjust:
2793     case CSSPropertyWebkitTransformStyle:
2794     case CSSPropertyWebkitUserDrag:
2795     case CSSPropertyWebkitUserModify:
2796     case CSSPropertyWebkitUserSelect:
2797 #if ENABLE(CSS_EXCLUSIONS)
2798     case CSSPropertyWebkitWrapFlow:
2799     case CSSPropertyWebkitWrapThrough:
2800 #endif
2801     case CSSPropertyWebkitWritingMode:
2802     case CSSPropertyWhiteSpace:
2803     case CSSPropertyWordBreak:
2804     case CSSPropertyWordWrap:
2805         // These properties should be handled before in isValidKeywordPropertyAndValue().
2806         ASSERT_NOT_REACHED();
2807         return false;
2808 #if ENABLE(SVG)
2809     default:
2810         return parseSVGValue(propId, important);
2811 #endif
2812     }
2813
2814     if (validPrimitive) {
2815         parsedValue = parseValidPrimitive(id, value);
2816         m_valueList->next();
2817     }
2818     ASSERT(!m_parsedCalculation);
2819     if (parsedValue) {
2820         if (!m_valueList->current() || inShorthand()) {
2821             addProperty(propId, parsedValue.release(), important);
2822             return true;
2823         }
2824     }
2825     return false;
2826 }
2827
2828 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
2829 {
2830     if (lval) {
2831         if (lval->isValueList())
2832             static_cast<CSSValueList*>(lval.get())->append(rval);
2833         else {
2834             PassRefPtr<CSSValue> oldlVal(lval.release());
2835             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
2836             list->append(oldlVal);
2837             list->append(rval);
2838             lval = list;
2839         }
2840     }
2841     else
2842         lval = rval;
2843 }
2844
2845 static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue)
2846 {
2847     if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
2848         || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
2849         cssValue = cssValuePool().createIdentifierValue(parserValue->id);
2850         return true;
2851     }
2852     return false;
2853 }
2854
2855 const int cMaxFillProperties = 9;
2856
2857 bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important)
2858 {
2859     ASSERT(numProperties <= cMaxFillProperties);
2860     if (numProperties > cMaxFillProperties)
2861         return false;
2862
2863     ShorthandScope scope(this, propId);
2864
2865     bool parsedProperty[cMaxFillProperties] = { false };
2866     RefPtr<CSSValue> values[cMaxFillProperties];
2867     RefPtr<CSSValue> clipValue;
2868     RefPtr<CSSValue> positionYValue;
2869     RefPtr<CSSValue> repeatYValue;
2870     bool foundClip = false;
2871     int i;
2872     bool foundBackgroundPositionCSSProperty = false;
2873
2874     while (m_valueList->current()) {
2875         CSSParserValue* val = m_valueList->current();
2876         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
2877             // We hit the end.  Fill in all remaining values with the initial value.
2878             m_valueList->next();
2879             for (i = 0; i < numProperties; ++i) {
2880                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
2881                     // Color is not allowed except as the last item in a list for backgrounds.
2882                     // Reject the entire property.
2883                     return false;
2884
2885                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
2886                     addFillValue(values[i], cssValuePool().createImplicitInitialValue());
2887                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2888                         addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
2889                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2890                         addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
2891                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
2892                         // If background-origin wasn't present, then reset background-clip also.
2893                         addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
2894                     }
2895                 }
2896                 parsedProperty[i] = false;
2897             }
2898             if (!m_valueList->current())
2899                 break;
2900         }
2901
2902         bool backgroundSizeCSSPropertyExpected = false;
2903         if ((val->unit == CSSParserValue::Operator && val->iValue == '/') && foundBackgroundPositionCSSProperty) {
2904             backgroundSizeCSSPropertyExpected = true;
2905             m_valueList->next();
2906         }
2907
2908         foundBackgroundPositionCSSProperty = false;
2909         bool found = false;
2910         for (i = 0; !found && i < numProperties; ++i) {
2911
2912             if (backgroundSizeCSSPropertyExpected && properties[i] != CSSPropertyBackgroundSize)
2913                 continue;
2914             if (!backgroundSizeCSSPropertyExpected && properties[i] == CSSPropertyBackgroundSize)
2915                 continue;
2916
2917             if (!parsedProperty[i]) {
2918                 RefPtr<CSSValue> val1;
2919                 RefPtr<CSSValue> val2;
2920                 CSSPropertyID propId1, propId2;
2921                 CSSParserValue* parserValue = m_valueList->current();
2922                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
2923                     parsedProperty[i] = found = true;
2924                     addFillValue(values[i], val1.release());
2925                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2926                         addFillValue(positionYValue, val2.release());
2927                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2928                         addFillValue(repeatYValue, val2.release());
2929                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
2930                         // Reparse the value as a clip, and see if we succeed.
2931                         if (parseBackgroundClip(parserValue, val1))
2932                             addFillValue(clipValue, val1.release()); // The property parsed successfully.
2933                         else
2934                             addFillValue(clipValue, cssValuePool().createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
2935                     }
2936                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
2937                         // Update clipValue
2938                         addFillValue(clipValue, val1.release());
2939                         foundClip = true;
2940                     }
2941                     if (properties[i] == CSSPropertyBackgroundPosition)
2942                         foundBackgroundPositionCSSProperty =  true;
2943                 }
2944             }
2945         }
2946
2947         // if we didn't find at least one match, this is an
2948         // invalid shorthand and we have to ignore it
2949         if (!found)
2950             return false;
2951     }
2952
2953     // Now add all of the properties we found.
2954     for (i = 0; i < numProperties; i++) {
2955         // Fill in any remaining properties with the initial value.
2956         if (!parsedProperty[i]) {
2957             addFillValue(values[i], cssValuePool().createImplicitInitialValue());
2958             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
2959                 addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
2960             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
2961                 addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
2962             if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin)) {
2963                 // If background-origin wasn't present, then reset background-clip also.
2964                 addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
2965             }
2966         }
2967         if (properties[i] == CSSPropertyBackgroundPosition) {
2968             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
2969             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
2970             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
2971         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
2972             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
2973             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
2974             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
2975         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
2976             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
2977             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2978             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
2979         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
2980             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
2981             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
2982             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
2983         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
2984             // Value is already set while updating origin
2985             continue;
2986         else
2987             addProperty(properties[i], values[i].release(), important);
2988
2989         // Add in clip values when we hit the corresponding origin property.
2990         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
2991             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
2992         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
2993             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
2994     }
2995
2996     return true;
2997 }
2998
2999 #if ENABLE(CSS_VARIABLES)
3000 bool CSSParser::cssVariablesEnabled() const
3001 {
3002     return m_context.isCSSVariablesEnabled;
3003 }
3004
3005 void CSSParser::storeVariableDeclaration(const CSSParserString& name, PassOwnPtr<CSSParserValueList> value, bool important)
3006 {
3007     // When CSSGrammar.y encounters an invalid declaration it passes null for the CSSParserValueList, just bail.
3008     if (!value)
3009         return;
3010     
3011     ASSERT(name.length > 12);
3012     AtomicString variableName = String(name.characters + 12, name.length - 12);
3013
3014     StringBuilder builder;
3015     for (unsigned i = 0, size = value->size(); i < size; i++) {
3016         if (i)
3017             builder.append(' ');
3018         RefPtr<CSSValue> cssValue = value->valueAt(i)->createCSSValue();
3019         if (!cssValue)
3020             return;
3021         builder.append(cssValue->cssText());
3022     }
3023     addProperty(CSSPropertyVariable, CSSVariableValue::create(variableName, builder.toString()), important, false);
3024 }
3025 #endif
3026
3027 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
3028 {
3029     if (lval) {
3030         if (lval->isValueList())
3031             static_cast<CSSValueList*>(lval.get())->append(rval);
3032         else {
3033             PassRefPtr<CSSValue> oldVal(lval.release());
3034             PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
3035             list->append(oldVal);
3036             list->append(rval);
3037             lval = list;
3038         }
3039     }
3040     else
3041         lval = rval;
3042 }
3043
3044 bool CSSParser::parseAnimationShorthand(bool important)
3045 {
3046     // When we parse the animation shorthand we need to look for animation-name
3047     // last because otherwise it might match against the keywords for fill mode,
3048     // timing functions and infinite iteration. This means that animation names
3049     // that are the same as keywords (e.g. 'forwards') won't always match in the
3050     // shorthand. In that case they should be using longhands (or reconsidering
3051     // their approach). This is covered by the animations spec bug:
3052     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=14790
3053     // And in the spec (editor's draft) at:
3054     // http://dev.w3.org/csswg/css3-animations/#animation-shorthand-property
3055
3056     static const CSSPropertyID animationProperties[] = {
3057         CSSPropertyWebkitAnimationDuration,
3058         CSSPropertyWebkitAnimationTimingFunction,
3059         CSSPropertyWebkitAnimationDelay,
3060         CSSPropertyWebkitAnimationIterationCount,
3061         CSSPropertyWebkitAnimationDirection,
3062         CSSPropertyWebkitAnimationFillMode,
3063         CSSPropertyWebkitAnimationName
3064     };
3065     const unsigned numProperties = 7;
3066
3067     // The list of properties in the shorthand should be the same
3068     // length as the list we have here, even though they are
3069     // a different order.
3070     ASSERT(numProperties == webkitAnimationShorthand().length());
3071
3072     ShorthandScope scope(this, CSSPropertyWebkitAnimation);
3073
3074     bool parsedProperty[numProperties] = { false };
3075     RefPtr<CSSValue> values[numProperties];
3076
3077     unsigned i;
3078     while (m_valueList->current()) {
3079         CSSParserValue* val = m_valueList->current();
3080         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3081             // We hit the end.  Fill in all remaining values with the initial value.
3082             m_valueList->next();
3083             for (i = 0; i < numProperties; ++i) {
3084                 if (!parsedProperty[i])
3085                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3086                 parsedProperty[i] = false;
3087             }
3088             if (!m_valueList->current())
3089                 break;
3090         }
3091
3092         bool found = false;
3093         for (i = 0; i < numProperties; ++i) {
3094             if (!parsedProperty[i]) {
3095                 RefPtr<CSSValue> val;
3096                 if (parseAnimationProperty(animationProperties[i], val)) {
3097                     parsedProperty[i] = found = true;
3098                     addAnimationValue(values[i], val.release());
3099                     break;
3100                 }
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     for (i = 0; i < numProperties; ++i) {
3111         // If we didn't find the property, set an intial value.
3112         if (!parsedProperty[i])
3113             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3114
3115         addProperty(animationProperties[i], values[i].release(), important);
3116     }
3117
3118     return true;
3119 }
3120
3121 bool CSSParser::parseTransitionShorthand(bool important)
3122 {
3123     const unsigned numProperties = webkitTransitionShorthand().length();
3124
3125     ShorthandScope scope(this, CSSPropertyWebkitTransition);
3126
3127     bool parsedProperty[] = { false, false, false, false };
3128     RefPtr<CSSValue> values[4];
3129
3130     unsigned i;
3131     while (m_valueList->current()) {
3132         CSSParserValue* val = m_valueList->current();
3133         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3134             // We hit the end.  Fill in all remaining values with the initial value.
3135             m_valueList->next();
3136             for (i = 0; i < numProperties; ++i) {
3137                 if (!parsedProperty[i])
3138                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3139                 parsedProperty[i] = false;
3140             }
3141             if (!m_valueList->current())
3142                 break;
3143         }
3144
3145         bool found = false;
3146         for (i = 0; !found && i < numProperties; ++i) {
3147             if (!parsedProperty[i]) {
3148                 RefPtr<CSSValue> val;
3149                 if (parseAnimationProperty(webkitTransitionShorthand().properties()[i], val)) {
3150                     parsedProperty[i] = found = true;
3151                     addAnimationValue(values[i], val.release());
3152                 }
3153             }
3154         }
3155
3156         // if we didn't find at least one match, this is an
3157         // invalid shorthand and we have to ignore it
3158         if (!found)
3159             return false;
3160     }
3161
3162     // Fill in any remaining properties with the initial value.
3163     for (i = 0; i < numProperties; ++i) {
3164         if (!parsedProperty[i])
3165             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3166     }
3167
3168     // Now add all of the properties we found.
3169     for (i = 0; i < numProperties; i++)
3170         addProperty(webkitTransitionShorthand().properties()[i], values[i].release(), important);
3171
3172     return true;
3173 }
3174
3175 bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important)
3176 {
3177     // We try to match as many properties as possible
3178     // We set up an array of booleans to mark which property has been found,
3179     // and we try to search for properties until it makes no longer any sense.
3180     ShorthandScope scope(this, propId);
3181
3182     bool found = false;
3183     unsigned propertiesParsed = 0;
3184     bool propertyFound[6]= { false, false, false, false, false, false }; // 6 is enough size.
3185
3186     while (m_valueList->current()) {
3187         found = false;
3188         for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) {
3189             if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) {
3190                     propertyFound[propIndex] = found = true;
3191                     propertiesParsed++;
3192             }
3193         }
3194
3195         // if we didn't find at least one match, this is an
3196         // invalid shorthand and we have to ignore it
3197         if (!found)
3198             return false;
3199     }
3200
3201     if (propertiesParsed == shorthand.length())
3202         return true;
3203
3204     // Fill in any remaining properties with the initial value.
3205     ImplicitScope implicitScope(this, PropertyImplicit);
3206     const StylePropertyShorthand* const* const propertiesForInitialization = shorthand.propertiesForInitialization();
3207     for (unsigned i = 0; i < shorthand.length(); ++i) {
3208         if (propertyFound[i])
3209             continue;
3210
3211         if (propertiesForInitialization) {
3212             const StylePropertyShorthand& initProperties = *(propertiesForInitialization[i]);
3213             for (unsigned propIndex = 0; propIndex < initProperties.length(); ++propIndex)
3214                 addProperty(initProperties.properties()[propIndex], cssValuePool().createImplicitInitialValue(), important);
3215         } else
3216             addProperty(shorthand.properties()[i], cssValuePool().createImplicitInitialValue(), important);
3217     }
3218
3219     return true;
3220 }
3221
3222 bool CSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties,  bool important)
3223 {
3224     /* From the CSS 2 specs, 8.3
3225      * If there is only one value, it applies to all sides. If there are two values, the top and
3226      * bottom margins are set to the first value and the right and left margins are set to the second.
3227      * If there are three values, the top is set to the first value, the left and right are set to the
3228      * second, and the bottom is set to the third. If there are four values, they apply to the top,
3229      * right, bottom, and left, respectively.
3230      */
3231
3232     int num = inShorthand() ? 1 : m_valueList->size();
3233
3234     ShorthandScope scope(this, propId);
3235
3236     // the order is top, right, bottom, left
3237     switch (num) {
3238         case 1: {
3239             if (!parseValue(properties[0], important))
3240                 return false;
3241             CSSValue* value = m_parsedProperties->last().value();
3242             ImplicitScope implicitScope(this, PropertyImplicit);
3243             addProperty(properties[1], value, important);
3244             addProperty(properties[2], value, important);
3245             addProperty(properties[3], value, important);
3246             break;
3247         }
3248         case 2: {
3249             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
3250                 return false;
3251             CSSValue* value = m_parsedProperties->at(m_parsedProperties->size() - 2).value();
3252             ImplicitScope implicitScope(this, PropertyImplicit);
3253             addProperty(properties[2], value, important);
3254             value = m_parsedProperties->at(m_parsedProperties->size() - 2).value();
3255             addProperty(properties[3], value, important);
3256             break;
3257         }
3258         case 3: {
3259             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
3260                 return false;
3261             CSSValue* value = m_parsedProperties->at(m_parsedProperties->size() - 2).value();
3262             ImplicitScope implicitScope(this, PropertyImplicit);
3263             addProperty(properties[3], value, important);
3264             break;
3265         }
3266         case 4: {
3267             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
3268                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
3269                 return false;
3270             break;
3271         }
3272         default: {
3273             return false;
3274         }
3275     }
3276
3277     return true;
3278 }
3279
3280 // auto | <identifier>
3281 bool CSSParser::parsePage(CSSPropertyID propId, bool important)
3282 {
3283     ASSERT(propId == CSSPropertyPage);
3284
3285     if (m_valueList->size() != 1)
3286         return false;
3287
3288     CSSParserValue* value = m_valueList->current();
3289     if (!value)
3290         return false;
3291
3292     if (value->id == CSSValueAuto) {
3293         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
3294         return true;
3295     } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
3296         addProperty(propId, createPrimitiveStringValue(value), important);
3297         return true;
3298     }
3299     return false;
3300 }
3301
3302 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
3303 bool CSSParser::parseSize(CSSPropertyID propId, bool important)
3304 {
3305     ASSERT(propId == CSSPropertySize);
3306
3307     if (m_valueList->size() > 2)
3308         return false;
3309
3310     CSSParserValue* value = m_valueList->current();
3311     if (!value)
3312         return false;
3313
3314     RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
3315
3316     // First parameter.
3317     SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
3318     if (paramType == None)
3319         return false;
3320
3321     // Second parameter, if any.
3322     value = m_valueList->next();
3323     if (value) {
3324         paramType = parseSizeParameter(parsedValues.get(), value, paramType);
3325         if (paramType == None)
3326             return false;
3327     }
3328
3329     addProperty(propId, parsedValues.release(), important);
3330     return true;
3331 }
3332
3333 CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
3334 {
3335     switch (value->id) {
3336     case CSSValueAuto:
3337         if (prevParamType == None) {
3338             parsedValues->append(cssValuePool().createIdentifierValue(value->id));
3339             return Auto;
3340         }
3341         return None;
3342     case CSSValueLandscape:
3343     case CSSValuePortrait:
3344         if (prevParamType == None || prevParamType == PageSize) {
3345             parsedValues->append(cssValuePool().createIdentifierValue(value->id));
3346             return Orientation;
3347         }
3348         return None;
3349     case CSSValueA3:
3350     case CSSValueA4:
3351     case CSSValueA5:
3352     case CSSValueB4:
3353     case CSSValueB5:
3354     case CSSValueLedger:
3355     case CSSValueLegal:
3356     case CSSValueLetter:
3357         if (prevParamType == None || prevParamType == Orientation) {
3358             // Normalize to Page Size then Orientation order by prepending.
3359             // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (StyleResolver::applyPageSizeProperty).
3360             parsedValues->prepend(cssValuePool().createIdentifierValue(value->id));
3361             return PageSize;
3362         }
3363         return None;
3364     case 0:
3365         if (validUnit(value, FLength | FNonNeg) && (prevParamType == None || prevParamType == Length)) {
3366             parsedValues->append(createPrimitiveNumericValue(value));
3367             return Length;
3368         }
3369         return None;
3370     default:
3371         return None;
3372     }
3373 }
3374
3375 // [ <string> <string> ]+ | inherit | none
3376 // inherit and none are handled in parseValue.
3377 bool CSSParser::parseQuotes(CSSPropertyID propId, bool important)
3378 {
3379     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3380     while (CSSParserValue* val = m_valueList->current()) {
3381         RefPtr<CSSValue> parsedValue;
3382         if (val->unit == CSSPrimitiveValue::CSS_STRING)
3383             parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
3384         else
3385             break;
3386         values->append(parsedValue.release());
3387         m_valueList->next();
3388     }
3389     if (values->length()) {
3390         addProperty(propId, values.release(), important);
3391         m_valueList->next();
3392         return true;
3393     }
3394     return false;
3395 }
3396
3397 // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3398 // in CSS 2.1 this got somewhat reduced:
3399 // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
3400 bool CSSParser::parseContent(CSSPropertyID propId, bool important)
3401 {
3402     RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
3403
3404     while (CSSParserValue* val = m_valueList->current()) {
3405         RefPtr<CSSValue> parsedValue;
3406         if (val->unit == CSSPrimitiveValue::CSS_URI) {
3407             // url
3408             parsedValue = CSSImageValue::create(completeURL(val->string));
3409         } else if (val->unit == CSSParserValue::Function) {
3410             // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
3411             CSSParserValueList* args = val->function->args.get();
3412             if (!args)
3413                 return false;
3414             if (equalIgnoringCase(val->function->name, "attr(")) {
3415                 parsedValue = parseAttr(args);
3416                 if (!parsedValue)
3417                     return false;
3418             } else if (equalIgnoringCase(val->function->name, "counter(")) {
3419                 parsedValue = parseCounterContent(args, false);
3420                 if (!parsedValue)
3421                     return false;
3422             } else if (equalIgnoringCase(val->function->name, "counters(")) {
3423                 parsedValue = parseCounterContent(args, true);
3424                 if (!parsedValue)
3425                     return false;
3426 #if ENABLE(CSS_IMAGE_SET)
3427             } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
3428                 parsedValue = parseImageSet(m_valueList.get());
3429                 if (!parsedValue)
3430                     return false;
3431 #endif
3432             } else if (isGeneratedImageValue(val)) {
3433                 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
3434                     return false;
3435             } else
3436                 return false;
3437         } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
3438             // open-quote
3439             // close-quote
3440             // no-open-quote
3441             // no-close-quote
3442             // inherit
3443             // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
3444             // none
3445             // normal
3446             switch (val->id) {
3447             case CSSValueOpenQuote:
3448             case CSSValueCloseQuote:
3449             case CSSValueNoOpenQuote:
3450             case CSSValueNoCloseQuote:
3451             case CSSValueNone:
3452             case CSSValueNormal:
3453                 parsedValue = cssValuePool().createIdentifierValue(val->id);
3454             }
3455         } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
3456             parsedValue = createPrimitiveStringValue(val);
3457         }
3458         if (!parsedValue)
3459             break;
3460         values->append(parsedValue.release());
3461         m_valueList->next();
3462     }
3463
3464     if (values->length()) {
3465         addProperty(propId, values.release(), important);
3466         m_valueList->next();
3467         return true;
3468     }
3469
3470     return false;
3471 }
3472
3473 PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
3474 {
3475     if (args->size() != 1)
3476         return 0;
3477
3478     CSSParserValue* a = args->current();
3479
3480     if (a->unit != CSSPrimitiveValue::CSS_IDENT)
3481         return 0;
3482
3483     String attrName = a->string;
3484     // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
3485     // But HTML attribute names can't have those characters, and we should not
3486     // even parse them inside attr().
3487     if (attrName[0] == '-')
3488         return 0;
3489
3490     if (m_context.isHTMLDocument)
3491         attrName = attrName.lower();
3492
3493     return cssValuePool().createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
3494 }
3495
3496 PassRefPtr<CSSValue> CSSParser::parseBackgroundColor()
3497 {
3498     int id = m_valueList->current()->id;
3499     if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor ||
3500         (id >= CSSValueGrey && id < CSSValueWebkitText && inQuirksMode()))
3501         return cssValuePool().createIdentifierValue(id);
3502     return parseColor();
3503 }
3504
3505 bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
3506 {
3507     if (valueList->current()->id == CSSValueNone) {
3508         value = cssValuePool().createIdentifierValue(CSSValueNone);
3509         return true;
3510     }
3511     if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
3512         value = CSSImageValue::create(completeURL(valueList->current()->string));
3513         return true;
3514     }
3515
3516     if (isGeneratedImageValue(valueList->current()))
3517         return parseGeneratedImage(valueList, value);
3518     
3519 #if ENABLE(CSS_IMAGE_SET)
3520     if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
3521         value = parseImageSet(m_valueList.get());
3522         if (value)
3523             return true;
3524     }
3525 #endif
3526
3527     return false;
3528 }
3529
3530 PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
3531 {
3532     int id = valueList->current()->id;
3533     if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
3534         int percent = 0;
3535         if (id == CSSValueRight)
3536             percent = 100;
3537         else if (id == CSSValueCenter)
3538             percent = 50;
3539         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3540     }
3541     if (validUnit(valueList->current(), FPercent | FLength))
3542         return createPrimitiveNumericValue(valueList->current());
3543     return 0;
3544 }
3545
3546 PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
3547 {
3548     int id = valueList->current()->id;
3549     if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
3550         int percent = 0;
3551         if (id == CSSValueBottom)
3552             percent = 100;
3553         else if (id == CSSValueCenter)
3554             percent = 50;
3555         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3556     }
3557     if (validUnit(valueList->current(), FPercent | FLength))
3558         return createPrimitiveNumericValue(valueList->current());
3559     return 0;
3560 }
3561
3562 PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
3563 {
3564     int id = valueList->current()->id;
3565     if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
3566         int percent = 0;
3567         if (id == CSSValueLeft || id == CSSValueRight) {
3568             if (cumulativeFlags & XFillPosition)
3569                 return 0;
3570             cumulativeFlags |= XFillPosition;
3571             individualFlag = XFillPosition;
3572             if (id == CSSValueRight)
3573                 percent = 100;
3574         }
3575         else if (id == CSSValueTop || id == CSSValueBottom) {
3576             if (cumulativeFlags & YFillPosition)
3577                 return 0;
3578             cumulativeFlags |= YFillPosition;
3579             individualFlag = YFillPosition;
3580             if (id == CSSValueBottom)
3581                 percent = 100;
3582         } else if (id == CSSValueCenter) {
3583             // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
3584             percent = 50;
3585             cumulativeFlags |= AmbiguousFillPosition;
3586             individualFlag = AmbiguousFillPosition;
3587         }
3588         return cssValuePool().createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
3589     }
3590     if (validUnit(valueList->current(), FPercent | FLength)) {
3591         if (!cumulativeFlags) {
3592             cumulativeFlags |= XFillPosition;
3593             individualFlag = XFillPosition;
3594         } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
3595             cumulativeFlags |= YFillPosition;
3596             individualFlag = YFillPosition;
3597         } else {
3598             if (m_parsedCalculation)
3599                 m_parsedCalculation.release();
3600             return 0;
3601         }
3602         return createPrimitiveNumericValue(valueList->current());
3603     }
3604     return 0;
3605 }
3606
3607 void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3608 {
3609     CSSParserValue* value = valueList->current();
3610
3611     // Parse the first value.  We're just making sure that it is one of the valid keywords or a percentage/length.
3612     unsigned cumulativeFlags = 0;
3613     FillPositionFlag value1Flag = InvalidFillPosition;
3614     FillPositionFlag value2Flag = InvalidFillPosition;
3615     value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
3616     if (!value1)
3617         return;
3618
3619     // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
3620     // can assume that any other values belong to the rest of the shorthand).  If we're not parsing a shorthand, though, the
3621     // value was explicitly specified for our property.
3622     value = valueList->next();
3623
3624     // First check for the comma.  If so, we are finished parsing this value or value pair.
3625     if (isComma(value))
3626         value = 0;
3627
3628     if (value) {
3629         value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
3630         if (value2)
3631             valueList->next();
3632         else {
3633             if (!inShorthand()) {
3634                 value1.clear();
3635                 return;
3636             }
3637         }
3638     }
3639
3640     if (!value2)
3641         // Only one value was specified.  If that value was not a keyword, then it sets the x position, and the y position
3642         // is simply 50%.  This is our default.
3643         // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
3644         // For left/right/center, the default of 50% in the y is still correct.
3645         value2 = cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
3646
3647     if (value1Flag == YFillPosition || value2Flag == XFillPosition)
3648         value1.swap(value2);
3649 }
3650
3651 void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
3652 {
3653     int id = m_valueList->current()->id;
3654     if (id == CSSValueRepeatX) {
3655         m_implicitShorthand = true;
3656         value1 = cssValuePool().createIdentifierValue(CSSValueRepeat);
3657         value2 = cssValuePool().createIdentifierValue(CSSValueNoRepeat);
3658         m_valueList->next();
3659         return;
3660     }
3661     if (id == CSSValueRepeatY) {
3662         m_implicitShorthand = true;
3663         value1 = cssValuePool().createIdentifierValue(CSSValueNoRepeat);
3664         value2 = cssValuePool().createIdentifierValue(CSSValueRepeat);
3665         m_valueList->next();
3666         return;
3667     }
3668     if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
3669         value1 = cssValuePool().createIdentifierValue(id);
3670     else {
3671         value1 = 0;
3672         return;
3673     }
3674
3675     CSSParserValue* value = m_valueList->next();
3676
3677     // Parse the second value if one is available
3678     if (value && !isComma(value)) {
3679         id = value->id;
3680         if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace) {
3681             value2 = cssValuePool().createIdentifierValue(id);
3682             m_valueList->next();
3683             return;
3684         }
3685     }
3686
3687     // If only one value was specified, value2 is the same as value1.
3688     m_implicitShorthand = true;
3689     value2 = cssValuePool().createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
3690 }
3691
3692 PassRefPtr<CSSValue> CSSParser::parseFillSize(CSSPropertyID propId, bool& allowComma)
3693 {
3694     allowComma = true;
3695     CSSParserValue* value = m_valueList->current();
3696
3697     if (value->id == CSSValueContain || value->id == CSSValueCover)
3698         return cssValuePool().createIdentifierValue(value->id);
3699
3700     RefPtr<CSSPrimitiveValue> parsedValue1;
3701
3702     if (value->id == CSSValueAuto)
3703         parsedValue1 = cssValuePool().createIdentifierValue(CSSValueAuto);
3704     else {
3705         if (!validUnit(value, FLength | FPercent))
3706             return 0;
3707         parsedValue1 = createPrimitiveNumericValue(value);
3708     }
3709
3710     RefPtr<CSSPrimitiveValue> parsedValue2;
3711     if ((value = m_valueList->next())) {
3712         if (value->unit == CSSParserValue::Operator && value->iValue == ',')
3713             allowComma = false;
3714         else if (value->id != CSSValueAuto) {
3715             if (!validUnit(value, FLength | FPercent)) {
3716                 if (!inShorthand())
3717                     return 0;
3718                 // We need to rewind the value list, so that when it is advanced we'll end up back at this value.
3719                 m_valueList->previous();
3720             } else
3721                 parsedValue2 = createPrimitiveNumericValue(value);
3722         }
3723     } else if (!parsedValue2 && propId == CSSPropertyWebkitBackgroundSize) {
3724         // For backwards compatibility we set the second value to the first if it is omitted.
3725         // We only need to do this for -webkit-background-size. It should be safe to let masks match
3726         // the real property.
3727         parsedValue2 = parsedValue1;
3728     }
3729
3730     if (!parsedValue2)
3731         return parsedValue1;
3732     return cssValuePool().createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));
3733 }
3734
3735 bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2,
3736                                   RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
3737 {
3738     RefPtr<CSSValueList> values;
3739     RefPtr<CSSValueList> values2;
3740     CSSParserValue* val;
3741     RefPtr<CSSValue> value;
3742     RefPtr<CSSValue> value2;
3743
3744     bool allowComma = false;
3745
3746     retValue1 = retValue2 = 0;
3747     propId1 = propId;
3748     propId2 = propId;
3749     if (propId == CSSPropertyBackgroundPosition) {
3750         propId1 = CSSPropertyBackgroundPositionX;
3751         propId2 = CSSPropertyBackgroundPositionY;
3752     } else if (propId == CSSPropertyWebkitMaskPosition) {
3753         propId1 = CSSPropertyWebkitMaskPositionX;
3754         propId2 = CSSPropertyWebkitMaskPositionY;
3755     } else if (propId == CSSPropertyBackgroundRepeat) {
3756         propId1 = CSSPropertyBackgroundRepeatX;
3757         propId2 = CSSPropertyBackgroundRepeatY;
3758     } else if (propId == CSSPropertyWebkitMaskRepeat) {
3759         propId1 = CSSPropertyWebkitMaskRepeatX;
3760         propId2 = CSSPropertyWebkitMaskRepeatY;
3761     }
3762
3763     while ((val = m_valueList->current())) {
3764         RefPtr<CSSValue> currValue;
3765         RefPtr<CSSValue> currValue2;
3766
3767         if (allowComma) {
3768             if (!isComma(val))
3769                 return false;
3770             m_valueList->next();
3771             allowComma = false;
3772         } else {
3773             allowComma = true;
3774             switch (propId) {
3775                 case CSSPropertyBackgroundColor:
3776                     currValue = parseBackgroundColor();
3777                     if (currValue)
3778                         m_valueList->next();
3779                     break;
3780                 case CSSPropertyBackgroundAttachment:
3781                 case CSSPropertyWebkitMaskAttachment:
3782                     if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
3783                         currValue = cssValuePool().createIdentifierValue(val->id);
3784                         m_valueList->next();
3785                     }
3786                     break;
3787                 case CSSPropertyBackgroundImage:
3788                 case CSSPropertyWebkitMaskImage:
3789                     if (parseFillImage(m_valueList.get(), currValue))
3790                         m_valueList->next();
3791                     break;
3792                 case CSSPropertyWebkitBackgroundClip:
3793                 case CSSPropertyWebkitBackgroundOrigin:
3794                 case CSSPropertyWebkitMaskClip:
3795                 case CSSPropertyWebkitMaskOrigin:
3796                     // The first three values here are deprecated and do not apply to the version of the property that has
3797                     // the -webkit- prefix removed.
3798                     if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
3799                         val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
3800                         ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
3801                          (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
3802                         currValue = cssValuePool().createIdentifierValue(val->id);
3803                         m_valueList->next();
3804                     }
3805                     break;
3806                 case CSSPropertyBackgroundClip:
3807                     if (parseBackgroundClip(val, currValue))
3808                         m_valueList->next();
3809                     break;
3810                 case CSSPropertyBackgroundOrigin:
3811                     if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
3812                         currValue = cssValuePool().createIdentifierValue(val->id);
3813                         m_valueList->next();
3814                     }
3815                     break;
3816                 case CSSPropertyBackgroundPosition:
3817                 case CSSPropertyWebkitMaskPosition:
3818                     parseFillPosition(m_valueList.get(), currValue, currValue2);
3819                     // parseFillPosition advances the m_valueList pointer
3820                     break;
3821                 case CSSPropertyBackgroundPositionX:
3822                 case CSSPropertyWebkitMaskPositionX: {
3823                     currValue = parseFillPositionX(m_valueList.get());
3824                     if (currValue)
3825                         m_valueList->next();
3826                     break;
3827                 }
3828                 case CSSPropertyBackgroundPositionY:
3829                 case CSSPropertyWebkitMaskPositionY: {
3830                     currValue = parseFillPositionY(m_valueList.get());
3831                     if (currValue)
3832                         m_valueList->next();
3833                     break;
3834                 }
3835                 case CSSPropertyWebkitBackgroundComposite:
3836                 case CSSPropertyWebkitMaskComposite:
3837                     if (val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) {
3838                         currValue = cssValuePool().createIdentifierValue(val->id);
3839                         m_valueList->next();
3840                     }
3841                     break;
3842                 case CSSPropertyBackgroundRepeat:
3843                 case CSSPropertyWebkitMaskRepeat:
3844                     parseFillRepeat(currValue, currValue2);
3845                     // parseFillRepeat advances the m_valueList pointer
3846                     break;
3847                 case CSSPropertyBackgroundSize:
3848                 case CSSPropertyWebkitBackgroundSize:
3849                 case CSSPropertyWebkitMaskSize: {
3850                     currValue = parseFillSize(propId, allowComma);
3851                     if (currValue)
3852                         m_valueList->next();
3853                     break;
3854                 }
3855                 default:
3856                     break;
3857             }
3858             if (!currValue)
3859                 return false;
3860
3861             if (value && !values) {
3862                 values = CSSValueList::createCommaSeparated();
3863                 values->append(value.release());
3864             }
3865
3866             if (value2 && !values2) {
3867                 values2 = CSSValueList::createCommaSeparated();
3868                 values2->append(value2.release());
3869             }
3870
3871             if (values)
3872                 values->append(currValue.release());
3873             else
3874                 value = currValue.release();
3875             if (currValue2) {
3876                 if (values2)
3877                     values2->append(currValue2.release());
3878                 else
3879                     value2 = currValue2.release();
3880             }
3881         }
3882
3883         // When parsing any fill shorthand property, we let it handle building up the lists for all
3884         // properties.
3885         if (inShorthand())
3886             break;
3887     }
3888
3889     if (values && values->length()) {
3890         retValue1 = values.release();
3891         if (values2 && values2->length())
3892             retValue2 = values2.release();
3893         return true;
3894     }
3895     if (value) {
3896         retValue1 = value.release();
3897         retValue2 = value2.release();
3898         return true;
3899     }
3900     return false;
3901 }
3902
3903 PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
3904 {
3905     CSSParserValue* value = m_valueList->current();
3906     if (validUnit(value, FTime))
3907         return createPrimitiveNumericValue(value);
3908     return 0;
3909 }
3910
3911 PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
3912 {
3913     CSSParserValue* value = m_valueList->current();
3914     if (value->id == CSSValueNormal || value->id == CSSValueAlternate || value->id == CSSValueReverse || value->id == CSSValueAlternateReverse)
3915         return cssValuePool().createIdentifierValue(value->id);
3916     return 0;
3917 }
3918
3919 PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
3920 {
3921     CSSParserValue* value = m_valueList->current();
3922     if (validUnit(value, FTime | FNonNeg))
3923         return createPrimitiveNumericValue(value);
3924     return 0;
3925 }
3926
3927 PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
3928 {
3929     CSSParserValue* value = m_valueList->current();
3930     if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
3931         return cssValuePool().createIdentifierValue(value->id);
3932     return 0;
3933 }
3934
3935 PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
3936 {
3937     CSSParserValue* value = m_valueList->current();
3938     if (value->id == CSSValueInfinite)
3939         return cssValuePool().createIdentifierValue(value->id);
3940     if (validUnit(value, FNumber | FNonNeg))
3941         return createPrimitiveNumericValue(value);
3942     return 0;
3943 }
3944
3945 PassRefPtr<CSSValue> CSSParser::parseAnimationName()
3946 {
3947     CSSParserValue* value = m_valueList->current();
3948     if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
3949         if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
3950             return cssValuePool().createIdentifierValue(CSSValueNone);
3951         } else {
3952             return createPrimitiveStringValue(value);