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