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