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