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