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