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