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