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