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