• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
9  * Copyright (C) 2012 Intel Corporation. All rights reserved.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this library; see the file COPYING.LIB.  If not, write to
23  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24  * Boston, MA 02110-1301, USA.
25  */
26 
27 #include "config.h"
28 #include "core/css/parser/BisonCSSParser.h"
29 
30 #include "core/CSSValueKeywords.h"
31 #include "core/StylePropertyShorthand.h"
32 #include "core/css/CSSArrayFunctionValue.h"
33 #include "core/css/CSSAspectRatioValue.h"
34 #include "core/css/CSSBasicShapes.h"
35 #include "core/css/CSSBorderImage.h"
36 #include "core/css/CSSCanvasValue.h"
37 #include "core/css/CSSCrossfadeValue.h"
38 #include "core/css/CSSCursorImageValue.h"
39 #include "core/css/CSSFontFaceSrcValue.h"
40 #include "core/css/CSSFontFeatureValue.h"
41 #include "core/css/CSSFunctionValue.h"
42 #include "core/css/CSSGradientValue.h"
43 #include "core/css/CSSGridLineNamesValue.h"
44 #include "core/css/CSSGridTemplateAreasValue.h"
45 #include "core/css/CSSImageSetValue.h"
46 #include "core/css/CSSImageValue.h"
47 #include "core/css/CSSInheritedValue.h"
48 #include "core/css/CSSInitialValue.h"
49 #include "core/css/CSSKeyframeRule.h"
50 #include "core/css/CSSKeyframesRule.h"
51 #include "core/css/CSSLineBoxContainValue.h"
52 #include "core/css/CSSPrimitiveValue.h"
53 #include "core/css/CSSPropertySourceData.h"
54 #include "core/css/CSSReflectValue.h"
55 #include "core/css/CSSSelector.h"
56 #include "core/css/CSSShadowValue.h"
57 #include "core/css/CSSStyleSheet.h"
58 #include "core/css/CSSTimingFunctionValue.h"
59 #include "core/css/CSSTransformValue.h"
60 #include "core/css/CSSUnicodeRangeValue.h"
61 #include "core/css/CSSValueList.h"
62 #include "core/css/CSSValuePool.h"
63 #include "core/css/Counter.h"
64 #include "core/css/HashTools.h"
65 #include "core/css/MediaList.h"
66 #include "core/css/MediaQueryExp.h"
67 #include "core/css/Pair.h"
68 #include "core/css/Rect.h"
69 #include "core/css/StylePropertySet.h"
70 #include "core/css/StyleRule.h"
71 #include "core/css/StyleRuleImport.h"
72 #include "core/css/StyleSheetContents.h"
73 #include "core/css/parser/CSSParserIdioms.h"
74 #include "core/dom/Document.h"
75 #include "core/frame/FrameConsole.h"
76 #include "core/frame/FrameHost.h"
77 #include "core/frame/Settings.h"
78 #include "core/html/parser/HTMLParserIdioms.h"
79 #include "core/inspector/InspectorInstrumentation.h"
80 #include "core/rendering/RenderTheme.h"
81 #include "platform/FloatConversion.h"
82 #include "platform/RuntimeEnabledFeatures.h"
83 #include "wtf/BitArray.h"
84 #include "wtf/HexNumber.h"
85 #include "wtf/text/StringBuffer.h"
86 #include "wtf/text/StringBuilder.h"
87 #include "wtf/text/StringImpl.h"
88 #include "wtf/text/TextEncoding.h"
89 #include <limits.h>
90 
91 #define YYDEBUG 0
92 
93 #if YYDEBUG > 0
94 extern int cssyydebug;
95 #endif
96 
97 int cssyyparse(WebCore::BisonCSSParser*);
98 
99 using namespace WTF;
100 
101 namespace WebCore {
102 
103 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
104 
BisonCSSParser(const CSSParserContext & context)105 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
106     : m_context(context)
107     , m_important(false)
108     , m_id(CSSPropertyInvalid)
109     , m_styleSheet(nullptr)
110     , m_supportsCondition(false)
111     , m_selectorListForParseSelector(0)
112     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
113     , m_hadSyntacticallyValidCSSRule(false)
114     , m_logErrors(false)
115     , m_ignoreErrors(false)
116     , m_defaultNamespace(starAtom)
117     , m_observer(0)
118     , m_source(0)
119     , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
120     , m_allowImportRules(true)
121     , m_allowNamespaceDeclarations(true)
122     , m_inViewport(false)
123     , m_tokenizer(*this)
124 {
125 #if YYDEBUG > 0
126     cssyydebug = 1;
127 #endif
128 }
129 
~BisonCSSParser()130 BisonCSSParser::~BisonCSSParser()
131 {
132     clearProperties();
133 
134     deleteAllValues(m_floatingSelectors);
135     deleteAllValues(m_floatingSelectorVectors);
136     deleteAllValues(m_floatingValueLists);
137     deleteAllValues(m_floatingFunctions);
138 }
139 
setupParser(const char * prefix,unsigned prefixLength,const String & string,const char * suffix,unsigned suffixLength)140 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
141 {
142     m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
143     m_ruleHasHeader = true;
144 }
145 
parseSheet(StyleSheetContents * sheet,const String & string,const TextPosition & startPosition,CSSParserObserver * observer,bool logErrors)146 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
147 {
148     setStyleSheet(sheet);
149     m_defaultNamespace = starAtom; // Reset the default namespace.
150     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
151     m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
152     m_ignoreErrors = false;
153     m_tokenizer.m_lineNumber = 0;
154     m_startPosition = startPosition;
155     m_source = &string;
156     m_tokenizer.m_internal = false;
157     setupParser("", string, "");
158     cssyyparse(this);
159     sheet->shrinkToFit();
160     m_source = 0;
161     m_rule = nullptr;
162     m_lineEndings.clear();
163     m_ignoreErrors = false;
164     m_logErrors = false;
165     m_tokenizer.m_internal = true;
166 }
167 
parseRule(StyleSheetContents * sheet,const String & string)168 PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
169 {
170     setStyleSheet(sheet);
171     m_allowNamespaceDeclarations = false;
172     setupParser("@-internal-rule ", string, "");
173     cssyyparse(this);
174     return m_rule.release();
175 }
176 
parseKeyframeRule(StyleSheetContents * sheet,const String & string)177 PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
178 {
179     setStyleSheet(sheet);
180     setupParser("@-internal-keyframe-rule ", string, "");
181     cssyyparse(this);
182     return m_keyframe.release();
183 }
184 
parseKeyframeKeyList(const String & string)185 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
186 {
187     setupParser("@-internal-keyframe-key-list ", string, "");
188     cssyyparse(this);
189     ASSERT(m_valueList);
190     return StyleKeyframe::createKeyList(m_valueList.get());
191 }
192 
parseSupportsCondition(const String & string)193 bool BisonCSSParser::parseSupportsCondition(const String& string)
194 {
195     m_supportsCondition = false;
196     setupParser("@-internal-supports-condition ", string, "");
197     cssyyparse(this);
198     return m_supportsCondition;
199 }
200 
isColorPropertyID(CSSPropertyID propertyId)201 static inline bool isColorPropertyID(CSSPropertyID propertyId)
202 {
203     switch (propertyId) {
204     case CSSPropertyColor:
205     case CSSPropertyBackgroundColor:
206     case CSSPropertyBorderBottomColor:
207     case CSSPropertyBorderLeftColor:
208     case CSSPropertyBorderRightColor:
209     case CSSPropertyBorderTopColor:
210     case CSSPropertyOutlineColor:
211     case CSSPropertyTextLineThroughColor:
212     case CSSPropertyTextOverlineColor:
213     case CSSPropertyTextUnderlineColor:
214     case CSSPropertyWebkitBorderAfterColor:
215     case CSSPropertyWebkitBorderBeforeColor:
216     case CSSPropertyWebkitBorderEndColor:
217     case CSSPropertyWebkitBorderStartColor:
218     case CSSPropertyWebkitColumnRuleColor:
219     case CSSPropertyWebkitTextEmphasisColor:
220     case CSSPropertyWebkitTextFillColor:
221     case CSSPropertyWebkitTextStrokeColor:
222         return true;
223     case CSSPropertyTextDecorationColor:
224         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
225     default:
226         return false;
227     }
228 }
229 
parseColorValue(MutableStylePropertySet * declaration,CSSPropertyID propertyId,const String & string,bool important,CSSParserMode cssParserMode)230 static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
231 {
232     ASSERT(!string.isEmpty());
233     bool quirksMode = isQuirksModeBehavior(cssParserMode);
234     if (!isColorPropertyID(propertyId))
235         return false;
236     CSSParserString cssString;
237     cssString.init(string);
238     CSSValueID valueID = cssValueKeywordID(cssString);
239     bool validPrimitive = false;
240     if (valueID == CSSValueWebkitText) {
241         validPrimitive = true;
242     } else if (valueID == CSSValueCurrentcolor) {
243         validPrimitive = true;
244     } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
245         || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
246         validPrimitive = true;
247     }
248 
249     if (validPrimitive) {
250         RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
251         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
252         return true;
253     }
254     RGBA32 color;
255     if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
256         return false;
257     RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color);
258     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
259     return true;
260 }
261 
isSimpleLengthPropertyID(CSSPropertyID propertyId,bool & acceptsNegativeNumbers)262 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
263 {
264     switch (propertyId) {
265     case CSSPropertyFontSize:
266     case CSSPropertyHeight:
267     case CSSPropertyWidth:
268     case CSSPropertyMinHeight:
269     case CSSPropertyMinWidth:
270     case CSSPropertyPaddingBottom:
271     case CSSPropertyPaddingLeft:
272     case CSSPropertyPaddingRight:
273     case CSSPropertyPaddingTop:
274     case CSSPropertyWebkitLogicalWidth:
275     case CSSPropertyWebkitLogicalHeight:
276     case CSSPropertyWebkitMinLogicalWidth:
277     case CSSPropertyWebkitMinLogicalHeight:
278     case CSSPropertyWebkitPaddingAfter:
279     case CSSPropertyWebkitPaddingBefore:
280     case CSSPropertyWebkitPaddingEnd:
281     case CSSPropertyWebkitPaddingStart:
282         acceptsNegativeNumbers = false;
283         return true;
284     case CSSPropertyShapeMargin:
285         acceptsNegativeNumbers = false;
286         return RuntimeEnabledFeatures::cssShapesEnabled();
287     case CSSPropertyBottom:
288     case CSSPropertyLeft:
289     case CSSPropertyMarginBottom:
290     case CSSPropertyMarginLeft:
291     case CSSPropertyMarginRight:
292     case CSSPropertyMarginTop:
293     case CSSPropertyRight:
294     case CSSPropertyTop:
295     case CSSPropertyWebkitMarginAfter:
296     case CSSPropertyWebkitMarginBefore:
297     case CSSPropertyWebkitMarginEnd:
298     case CSSPropertyWebkitMarginStart:
299         acceptsNegativeNumbers = true;
300         return true;
301     default:
302         return false;
303     }
304 }
305 
306 template <typename CharacterType>
parseSimpleLength(const CharacterType * characters,unsigned length,CSSPrimitiveValue::UnitType & unit,double & number)307 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number)
308 {
309     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
310         length -= 2;
311         unit = CSSPrimitiveValue::CSS_PX;
312     } else if (length > 1 && characters[length - 1] == '%') {
313         length -= 1;
314         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
315     }
316 
317     // We rely on charactersToDouble for validation as well. The function
318     // will set "ok" to "false" if the entire passed-in character range does
319     // not represent a double.
320     bool ok;
321     number = charactersToDouble(characters, length, &ok);
322     return ok;
323 }
324 
parseSimpleLengthValue(MutableStylePropertySet * declaration,CSSPropertyID propertyId,const String & string,bool important,CSSParserMode cssParserMode)325 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
326 {
327     ASSERT(!string.isEmpty());
328     bool acceptsNegativeNumbers = false;
329 
330     // In @viewport, width and height are shorthands, not simple length values.
331     if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
332         return false;
333 
334     unsigned length = string.length();
335     double number;
336     CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
337 
338     if (string.is8Bit()) {
339         if (!parseSimpleLength(string.characters8(), length, unit, number))
340             return false;
341     } else {
342         if (!parseSimpleLength(string.characters16(), length, unit, number))
343             return false;
344     }
345 
346     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
347         bool quirksMode = isQuirksModeBehavior(cssParserMode);
348         if (number && !quirksMode)
349             return false;
350         unit = CSSPrimitiveValue::CSS_PX;
351     }
352     if (number < 0 && !acceptsNegativeNumbers)
353         return false;
354 
355     RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit);
356     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
357     return true;
358 }
359 
isValidKeywordPropertyAndValue(CSSPropertyID propertyId,CSSValueID valueID,const CSSParserContext & parserContext)360 bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, const CSSParserContext& parserContext)
361 {
362     if (valueID == CSSValueInvalid)
363         return false;
364 
365     switch (propertyId) {
366     case CSSPropertyBackgroundRepeatX: // repeat | no-repeat
367     case CSSPropertyBackgroundRepeatY: // repeat | no-repeat
368         return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat;
369     case CSSPropertyBorderCollapse: // collapse | separate
370         return valueID == CSSValueCollapse || valueID == CSSValueSeparate;
371     case CSSPropertyBorderTopStyle: // <border-style>
372     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
373     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
374     case CSSPropertyBorderLeftStyle:
375     case CSSPropertyWebkitBorderAfterStyle:
376     case CSSPropertyWebkitBorderBeforeStyle:
377     case CSSPropertyWebkitBorderEndStyle:
378     case CSSPropertyWebkitBorderStartStyle:
379     case CSSPropertyWebkitColumnRuleStyle:
380         return valueID >= CSSValueNone && valueID <= CSSValueDouble;
381     case CSSPropertyBoxSizing:
382         return valueID == CSSValueBorderBox || valueID == CSSValueContentBox;
383     case CSSPropertyCaptionSide: // top | bottom | left | right
384         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom;
385     case CSSPropertyClear: // none | left | right | both
386         return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth;
387     case CSSPropertyDirection: // ltr | rtl
388         return valueID == CSSValueLtr || valueID == CSSValueRtl;
389     case CSSPropertyDisplay:
390         // inline | block | list-item | inline-block | table |
391         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
392         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
393         // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid | lazy-block
394         return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone
395             || (RuntimeEnabledFeatures::cssGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid));
396     case CSSPropertyEmptyCells: // show | hide
397         return valueID == CSSValueShow || valueID == CSSValueHide;
398     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
399         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter;
400     case CSSPropertyFontStyle: // normal | italic | oblique
401         return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique;
402     case CSSPropertyImageRendering: // auto | optimizeContrast
403         return valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast;
404     case CSSPropertyIsolation: // auto | isolate
405         return RuntimeEnabledFeatures::cssCompositingEnabled()
406             && (valueID == CSSValueAuto || valueID == CSSValueIsolate);
407     case CSSPropertyListStylePosition: // inside | outside
408         return valueID == CSSValueInside || valueID == CSSValueOutside;
409     case CSSPropertyListStyleType:
410         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
411         // for the list of supported list-style-types.
412         return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone;
413     case CSSPropertyObjectFit:
414         return RuntimeEnabledFeatures::objectFitPositionEnabled()
415             && (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown);
416     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto
417         return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble);
418     case CSSPropertyOverflowWrap: // normal | break-word
419     case CSSPropertyWordWrap:
420         return valueID == CSSValueNormal || valueID == CSSValueBreakWord;
421     case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay
422         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay;
423     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y
424         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY;
425     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right
426     case CSSPropertyPageBreakBefore:
427     case CSSPropertyWebkitColumnBreakAfter:
428     case CSSPropertyWebkitColumnBreakBefore:
429         return valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight;
430     case CSSPropertyPageBreakInside: // avoid | auto
431     case CSSPropertyWebkitColumnBreakInside:
432         return valueID == CSSValueAuto || valueID == CSSValueAvoid;
433     case CSSPropertyPointerEvents:
434         // none | visiblePainted | visibleFill | visibleStroke | visible |
435         // painted | fill | stroke | auto | all | bounding-box
436         return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox);
437     case CSSPropertyPosition: // static | relative | absolute | fixed | sticky
438         return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed
439             || (RuntimeEnabledFeatures::cssStickyPositionEnabled() && valueID == CSSValueSticky);
440     case CSSPropertyResize: // none | both | horizontal | vertical | auto
441         return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
442     case CSSPropertyScrollBehavior: // instant | smooth
443         return RuntimeEnabledFeatures::cssomSmoothScrollEnabled()
444             && (valueID == CSSValueInstant || valueID == CSSValueSmooth);
445     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation
446         return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation;
447     case CSSPropertyTableLayout: // auto | fixed
448         return valueID == CSSValueAuto || valueID == CSSValueFixed;
449     case CSSPropertyTextAlignLast:
450         // auto | start | end | left | right | center | justify
451         return RuntimeEnabledFeatures::css3TextEnabled()
452             && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto);
453     case CSSPropertyTextJustify:
454         // auto | none | inter-word | distribute
455         return RuntimeEnabledFeatures::css3TextEnabled()
456             && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone);
457     case CSSPropertyTextLineThroughMode:
458     case CSSPropertyTextOverlineMode:
459     case CSSPropertyTextUnderlineMode:
460         return valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace;
461     case CSSPropertyTextLineThroughStyle:
462     case CSSPropertyTextOverlineStyle:
463     case CSSPropertyTextUnderlineStyle:
464         return valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave;
465     case CSSPropertyTextOverflow: // clip | ellipsis
466         return valueID == CSSValueClip || valueID == CSSValueEllipsis;
467     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
468         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision;
469     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none
470         return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone;
471     case CSSPropertyTouchActionDelay: // none | script
472         return RuntimeEnabledFeatures::cssTouchActionDelayEnabled()
473             && (valueID == CSSValueScript || valueID == CSSValueNone);
474     case CSSPropertyVisibility: // visible | hidden | collapse
475         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse;
476     case CSSPropertyWebkitAppearance:
477         return (valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone;
478     case CSSPropertyBackfaceVisibility:
479     case CSSPropertyWebkitBackfaceVisibility:
480         return valueID == CSSValueVisible || valueID == CSSValueHidden;
481     case CSSPropertyMixBlendMode:
482         return RuntimeEnabledFeatures::cssCompositingEnabled()
483             && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay
484             || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn
485             || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion
486             || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity);
487     case CSSPropertyWebkitBorderFit:
488         return valueID == CSSValueBorder || valueID == CSSValueLines;
489     case CSSPropertyWebkitBoxAlign:
490         return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline;
491     case CSSPropertyWebkitBoxDecorationBreak:
492         return valueID == CSSValueClone || valueID == CSSValueSlice;
493     case CSSPropertyWebkitBoxDirection:
494         return valueID == CSSValueNormal || valueID == CSSValueReverse;
495     case CSSPropertyWebkitBoxLines:
496         return valueID == CSSValueSingle || valueID == CSSValueMultiple;
497     case CSSPropertyWebkitBoxOrient:
498         return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis;
499     case CSSPropertyWebkitBoxPack:
500         return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify;
501     case CSSPropertyInternalCallback:
502         // This property is only injected programmatically, not parsed from stylesheets.
503         return false;
504     case CSSPropertyColumnFill:
505         return RuntimeEnabledFeatures::regionBasedColumnsEnabled()
506             && (valueID == CSSValueAuto || valueID == CSSValueBalance);
507     case CSSPropertyAlignContent:
508         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
509         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch;
510     case CSSPropertyAlignItems:
511         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
512         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
513     case CSSPropertyAlignSelf:
514         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
515         return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
516     case CSSPropertyFlexDirection:
517         return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse;
518     case CSSPropertyFlexWrap:
519         return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse;
520     case CSSPropertyJustifyContent:
521         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
522         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround;
523     case CSSPropertyFontKerning:
524         return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone;
525     case CSSPropertyWebkitFontSmoothing:
526         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased;
527     case CSSPropertyGridAutoFlow:
528         return RuntimeEnabledFeatures::cssGridLayoutEnabled()
529             && (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn);
530     case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
531         return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace;
532     case CSSPropertyWebkitMarginAfterCollapse:
533     case CSSPropertyWebkitMarginBeforeCollapse:
534     case CSSPropertyWebkitMarginBottomCollapse:
535     case CSSPropertyWebkitMarginTopCollapse:
536         return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard;
537     case CSSPropertyInternalMarqueeDirection:
538         return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
539             || valueID == CSSValueUp || valueID == CSSValueAuto;
540     case CSSPropertyInternalMarqueeStyle:
541         return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate;
542     case CSSPropertyWebkitPrintColorAdjust:
543         return valueID == CSSValueExact || valueID == CSSValueEconomy;
544     case CSSPropertyWebkitRtlOrdering:
545         return valueID == CSSValueLogical || valueID == CSSValueVisual;
546     case CSSPropertyWebkitRubyPosition:
547         return valueID == CSSValueBefore || valueID == CSSValueAfter;
548     case CSSPropertyWebkitTextCombine:
549         return valueID == CSSValueNone || valueID == CSSValueHorizontal;
550     case CSSPropertyWebkitTextEmphasisPosition:
551         return valueID == CSSValueOver || valueID == CSSValueUnder;
552     case CSSPropertyWebkitTextSecurity: // disc | circle | square | none
553         return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone;
554     case CSSPropertyTransformStyle:
555     case CSSPropertyWebkitTransformStyle:
556         return valueID == CSSValueFlat || valueID == CSSValuePreserve3d;
557     case CSSPropertyWebkitUserDrag: // auto | none | element
558         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement;
559     case CSSPropertyWebkitUserModify: // read-only | read-write
560         return valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly;
561     case CSSPropertyWebkitUserSelect: // auto | none | text | all
562         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll;
563     case CSSPropertyWebkitWrapFlow:
564         return RuntimeEnabledFeatures::cssExclusionsEnabled()
565             && (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear);
566     case CSSPropertyWebkitWrapThrough:
567         return RuntimeEnabledFeatures::cssExclusionsEnabled()
568             && (valueID == CSSValueWrap || valueID == CSSValueNone);
569     case CSSPropertyWebkitWritingMode:
570         return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt;
571     case CSSPropertyWhiteSpace: // normal | pre | nowrap
572         return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
573     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
574         return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord;
575     default:
576         ASSERT_NOT_REACHED();
577         return false;
578     }
579     return false;
580 }
581 
isKeywordPropertyID(CSSPropertyID propertyId)582 bool isKeywordPropertyID(CSSPropertyID propertyId)
583 {
584     switch (propertyId) {
585     case CSSPropertyMixBlendMode:
586     case CSSPropertyIsolation:
587     case CSSPropertyBackgroundRepeatX:
588     case CSSPropertyBackgroundRepeatY:
589     case CSSPropertyBorderBottomStyle:
590     case CSSPropertyBorderCollapse:
591     case CSSPropertyBorderLeftStyle:
592     case CSSPropertyBorderRightStyle:
593     case CSSPropertyBorderTopStyle:
594     case CSSPropertyBoxSizing:
595     case CSSPropertyCaptionSide:
596     case CSSPropertyClear:
597     case CSSPropertyDirection:
598     case CSSPropertyDisplay:
599     case CSSPropertyEmptyCells:
600     case CSSPropertyFloat:
601     case CSSPropertyFontStyle:
602     case CSSPropertyImageRendering:
603     case CSSPropertyListStylePosition:
604     case CSSPropertyListStyleType:
605     case CSSPropertyObjectFit:
606     case CSSPropertyOutlineStyle:
607     case CSSPropertyOverflowWrap:
608     case CSSPropertyOverflowX:
609     case CSSPropertyOverflowY:
610     case CSSPropertyPageBreakAfter:
611     case CSSPropertyPageBreakBefore:
612     case CSSPropertyPageBreakInside:
613     case CSSPropertyPointerEvents:
614     case CSSPropertyPosition:
615     case CSSPropertyResize:
616     case CSSPropertyScrollBehavior:
617     case CSSPropertySpeak:
618     case CSSPropertyTableLayout:
619     case CSSPropertyTextAlignLast:
620     case CSSPropertyTextJustify:
621     case CSSPropertyTextLineThroughMode:
622     case CSSPropertyTextLineThroughStyle:
623     case CSSPropertyTextOverflow:
624     case CSSPropertyTextOverlineMode:
625     case CSSPropertyTextOverlineStyle:
626     case CSSPropertyTextRendering:
627     case CSSPropertyTextTransform:
628     case CSSPropertyTextUnderlineMode:
629     case CSSPropertyTextUnderlineStyle:
630     case CSSPropertyTouchActionDelay:
631     case CSSPropertyVisibility:
632     case CSSPropertyWebkitAppearance:
633     case CSSPropertyBackfaceVisibility:
634     case CSSPropertyWebkitBackfaceVisibility:
635     case CSSPropertyWebkitBorderAfterStyle:
636     case CSSPropertyWebkitBorderBeforeStyle:
637     case CSSPropertyWebkitBorderEndStyle:
638     case CSSPropertyWebkitBorderFit:
639     case CSSPropertyWebkitBorderStartStyle:
640     case CSSPropertyWebkitBoxAlign:
641     case CSSPropertyWebkitBoxDecorationBreak:
642     case CSSPropertyWebkitBoxDirection:
643     case CSSPropertyWebkitBoxLines:
644     case CSSPropertyWebkitBoxOrient:
645     case CSSPropertyWebkitBoxPack:
646     case CSSPropertyInternalCallback:
647     case CSSPropertyWebkitColumnBreakAfter:
648     case CSSPropertyWebkitColumnBreakBefore:
649     case CSSPropertyWebkitColumnBreakInside:
650     case CSSPropertyColumnFill:
651     case CSSPropertyWebkitColumnRuleStyle:
652     case CSSPropertyAlignContent:
653     case CSSPropertyFlexDirection:
654     case CSSPropertyFlexWrap:
655     case CSSPropertyJustifyContent:
656     case CSSPropertyFontKerning:
657     case CSSPropertyWebkitFontSmoothing:
658     case CSSPropertyGridAutoFlow:
659     case CSSPropertyWebkitLineBreak:
660     case CSSPropertyWebkitMarginAfterCollapse:
661     case CSSPropertyWebkitMarginBeforeCollapse:
662     case CSSPropertyWebkitMarginBottomCollapse:
663     case CSSPropertyWebkitMarginTopCollapse:
664     case CSSPropertyInternalMarqueeDirection:
665     case CSSPropertyInternalMarqueeStyle:
666     case CSSPropertyWebkitPrintColorAdjust:
667     case CSSPropertyWebkitRtlOrdering:
668     case CSSPropertyWebkitRubyPosition:
669     case CSSPropertyWebkitTextCombine:
670     case CSSPropertyWebkitTextEmphasisPosition:
671     case CSSPropertyWebkitTextSecurity:
672     case CSSPropertyTransformStyle:
673     case CSSPropertyWebkitTransformStyle:
674     case CSSPropertyWebkitUserDrag:
675     case CSSPropertyWebkitUserModify:
676     case CSSPropertyWebkitUserSelect:
677     case CSSPropertyWebkitWrapFlow:
678     case CSSPropertyWebkitWrapThrough:
679     case CSSPropertyWebkitWritingMode:
680     case CSSPropertyWhiteSpace:
681     case CSSPropertyWordBreak:
682     case CSSPropertyWordWrap:
683         return true;
684     case CSSPropertyAlignItems:
685     case CSSPropertyAlignSelf:
686         return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
687     default:
688         return false;
689     }
690 }
691 
parseKeywordValue(MutableStylePropertySet * declaration,CSSPropertyID propertyId,const String & string,bool important,const CSSParserContext & parserContext)692 static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
693 {
694     ASSERT(!string.isEmpty());
695 
696     if (!isKeywordPropertyID(propertyId)) {
697         // All properties accept the values of "initial" and "inherit".
698         String lowerCaseString = string.lower();
699         if (lowerCaseString != "initial" && lowerCaseString != "inherit")
700             return false;
701 
702         // Parse initial/inherit shorthands using the BisonCSSParser.
703         if (shorthandForProperty(propertyId).length())
704             return false;
705     }
706 
707     CSSParserString cssString;
708     cssString.init(string);
709     CSSValueID valueID = cssValueKeywordID(cssString);
710 
711     if (!valueID)
712         return false;
713 
714     RefPtrWillBeRawPtr<CSSValue> value = nullptr;
715     if (valueID == CSSValueInherit)
716         value = cssValuePool().createInheritedValue();
717     else if (valueID == CSSValueInitial)
718         value = cssValuePool().createExplicitInitialValue();
719     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
720         value = cssValuePool().createIdentifierValue(valueID);
721     else
722         return false;
723 
724     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
725     return true;
726 }
727 
728 template <typename CharType>
parseTransformTranslateArguments(CharType * & pos,CharType * end,unsigned expectedCount,CSSTransformValue * transformValue)729 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
730 {
731     while (expectedCount) {
732         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
733         if (delimiter == kNotFound)
734             return false;
735         unsigned argumentLength = static_cast<unsigned>(delimiter);
736         CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
737         double number;
738         if (!parseSimpleLength(pos, argumentLength, unit, number))
739             return false;
740         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
741             return false;
742         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
743         pos += argumentLength + 1;
744         --expectedCount;
745     }
746     return true;
747 }
748 
749 template <typename CharType>
parseTransformNumberArguments(CharType * & pos,CharType * end,unsigned expectedCount,CSSTransformValue * transformValue)750 static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
751 {
752     while (expectedCount) {
753         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
754         if (delimiter == kNotFound)
755             return false;
756         unsigned argumentLength = static_cast<unsigned>(delimiter);
757         bool ok;
758         double number = charactersToDouble(pos, argumentLength, &ok);
759         if (!ok)
760             return false;
761         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER));
762         pos += argumentLength + 1;
763         --expectedCount;
764     }
765     return true;
766 }
767 
768 template <typename CharType>
parseSimpleTransformValue(CharType * & pos,CharType * end)769 static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
770 {
771     static const int shortestValidTransformStringLength = 12;
772 
773     if (end - pos < shortestValidTransformStringLength)
774         return nullptr;
775 
776     const bool isTranslate = toASCIILower(pos[0]) == 't'
777         && toASCIILower(pos[1]) == 'r'
778         && toASCIILower(pos[2]) == 'a'
779         && toASCIILower(pos[3]) == 'n'
780         && toASCIILower(pos[4]) == 's'
781         && toASCIILower(pos[5]) == 'l'
782         && toASCIILower(pos[6]) == 'a'
783         && toASCIILower(pos[7]) == 't'
784         && toASCIILower(pos[8]) == 'e';
785 
786     if (isTranslate) {
787         CSSTransformValue::TransformOperationType transformType;
788         unsigned expectedArgumentCount = 1;
789         unsigned argumentStart = 11;
790         CharType c9 = toASCIILower(pos[9]);
791         if (c9 == 'x' && pos[10] == '(') {
792             transformType = CSSTransformValue::TranslateXTransformOperation;
793         } else if (c9 == 'y' && pos[10] == '(') {
794             transformType = CSSTransformValue::TranslateYTransformOperation;
795         } else if (c9 == 'z' && pos[10] == '(') {
796             transformType = CSSTransformValue::TranslateZTransformOperation;
797         } else if (c9 == '(') {
798             transformType = CSSTransformValue::TranslateTransformOperation;
799             expectedArgumentCount = 2;
800             argumentStart = 10;
801         } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
802             transformType = CSSTransformValue::Translate3DTransformOperation;
803             expectedArgumentCount = 3;
804             argumentStart = 12;
805         } else {
806             return nullptr;
807         }
808         pos += argumentStart;
809         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
810         if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
811             return nullptr;
812         return transformValue.release();
813     }
814 
815     const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
816         && toASCIILower(pos[1]) == 'a'
817         && toASCIILower(pos[2]) == 't'
818         && toASCIILower(pos[3]) == 'r'
819         && toASCIILower(pos[4]) == 'i'
820         && toASCIILower(pos[5]) == 'x'
821         && pos[6] == '3'
822         && toASCIILower(pos[7]) == 'd'
823         && pos[8] == '(';
824 
825     if (isMatrix3d) {
826         pos += 9;
827         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
828         if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
829             return nullptr;
830         return transformValue.release();
831     }
832 
833     const bool isScale3d = toASCIILower(pos[0]) == 's'
834         && toASCIILower(pos[1]) == 'c'
835         && toASCIILower(pos[2]) == 'a'
836         && toASCIILower(pos[3]) == 'l'
837         && toASCIILower(pos[4]) == 'e'
838         && pos[5] == '3'
839         && toASCIILower(pos[6]) == 'd'
840         && pos[7] == '(';
841 
842     if (isScale3d) {
843         pos += 8;
844         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation);
845         if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
846             return nullptr;
847         return transformValue.release();
848     }
849 
850     return nullptr;
851 }
852 
853 template <typename CharType>
parseSimpleTransformList(CharType * & pos,CharType * end)854 static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end)
855 {
856     RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
857     while (pos < end) {
858         while (pos < end && isCSSSpace(*pos))
859             ++pos;
860         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end);
861         if (!transformValue)
862             return nullptr;
863         if (!transformList)
864             transformList = CSSValueList::createSpaceSeparated();
865         transformList->append(transformValue.release());
866         if (pos < end) {
867             if (isCSSSpace(*pos))
868                 return nullptr;
869         }
870     }
871     return transformList.release();
872 }
873 
parseSimpleTransform(MutableStylePropertySet * properties,CSSPropertyID propertyID,const String & string,bool important)874 static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
875 {
876     if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
877         return false;
878     if (string.isEmpty())
879         return false;
880     RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
881     if (string.is8Bit()) {
882         const LChar* pos = string.characters8();
883         const LChar* end = pos + string.length();
884         transformList = parseSimpleTransformList(pos, end);
885         if (!transformList)
886             return false;
887     } else {
888         const UChar* pos = string.characters16();
889         const UChar* end = pos + string.length();
890         transformList = parseSimpleTransformList(pos, end);
891         if (!transformList)
892             return false;
893     }
894     properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
895     return true;
896 }
897 
parseFontFaceValue(const AtomicString & string)898 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string)
899 {
900     if (string.isEmpty())
901         return nullptr;
902     RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create();
903     if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0))
904         return nullptr;
905 
906     RefPtrWillBeRawPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily);
907     if (!fontFamily->isValueList())
908         return nullptr;
909 
910     return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
911 }
912 
parseAnimationTimingFunctionValue(const String & string)913 PassRefPtrWillBeRawPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string)
914 {
915     if (string.isEmpty())
916         return nullptr;
917     RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
918     if (!parseValue(style.get(), CSSPropertyTransitionTimingFunction, string, false, HTMLStandardMode, 0))
919         return nullptr;
920 
921     RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(CSSPropertyTransitionTimingFunction);
922     if (!value || value->isInitialValue() || value->isInheritedValue())
923         return nullptr;
924     CSSValueList* valueList = toCSSValueList(value.get());
925     if (valueList->length() > 1)
926         return nullptr;
927     return valueList->item(0);
928 }
929 
parseValue(MutableStylePropertySet * declaration,CSSPropertyID propertyID,const String & string,bool important,const Document & document)930 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document)
931 {
932     ASSERT(!string.isEmpty());
933 
934     CSSParserContext context(document, UseCounter::getFrom(&document));
935 
936     if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
937         return true;
938     if (parseColorValue(declaration, propertyID, string, important, context.mode()))
939         return true;
940     if (parseKeywordValue(declaration, propertyID, string, important, context))
941         return true;
942 
943     BisonCSSParser parser(context);
944     return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
945 }
946 
parseValue(MutableStylePropertySet * declaration,CSSPropertyID propertyID,const String & string,bool important,CSSParserMode cssParserMode,StyleSheetContents * contextStyleSheet)947 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
948 {
949     ASSERT(!string.isEmpty());
950     if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
951         return true;
952     if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
953         return true;
954 
955     CSSParserContext context(cssParserMode, 0);
956     if (contextStyleSheet) {
957         context = contextStyleSheet->parserContext();
958         context.setMode(cssParserMode);
959     }
960 
961     if (parseKeywordValue(declaration, propertyID, string, important, context))
962         return true;
963     if (parseSimpleTransform(declaration, propertyID, string, important))
964         return true;
965 
966     BisonCSSParser parser(context);
967     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
968 }
969 
parseValue(MutableStylePropertySet * declaration,CSSPropertyID propertyID,const String & string,bool important,StyleSheetContents * contextStyleSheet)970 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
971 {
972     // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty.
973 
974     if (m_context.useCounter())
975         m_context.useCounter()->count(m_context, propertyID);
976 
977     setStyleSheet(contextStyleSheet);
978 
979     setupParser("@-internal-value ", string, "");
980 
981     m_id = propertyID;
982     m_important = important;
983 
984     {
985         StyleDeclarationScope scope(this, declaration);
986         cssyyparse(this);
987     }
988 
989     m_rule = nullptr;
990     m_id = CSSPropertyInvalid;
991 
992     bool ok = false;
993     if (!m_parsedProperties.isEmpty()) {
994         ok = true;
995         declaration->addParsedProperties(m_parsedProperties);
996         clearProperties();
997     }
998 
999     return ok;
1000 }
1001 
1002 // The color will only be changed when string contains a valid CSS color, so callers
1003 // can set it to a default color and ignore the boolean result.
parseColor(RGBA32 & color,const String & string,bool strict)1004 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
1005 {
1006     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
1007     if (CSSPropertyParser::fastParseColor(color, string, strict))
1008         return true;
1009 
1010     BisonCSSParser parser(strictCSSParserContext());
1011 
1012     // In case the fast-path parser didn't understand the color, try the full parser.
1013     if (!parser.parseColor(string))
1014         return false;
1015 
1016     CSSValue* value = parser.m_parsedProperties.first().value();
1017     if (!value->isPrimitiveValue())
1018         return false;
1019 
1020     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1021     if (!primitiveValue->isRGBColor())
1022         return false;
1023 
1024     color = primitiveValue->getRGBA32Value();
1025     return true;
1026 }
1027 
parseColor(const String & string)1028 bool BisonCSSParser::parseColor(const String& string)
1029 {
1030     setupParser("@-internal-decls color:", string, "");
1031     cssyyparse(this);
1032     m_rule = nullptr;
1033 
1034     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1035 }
1036 
parseSystemColor(RGBA32 & color,const String & string)1037 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
1038 {
1039     CSSParserString cssColor;
1040     cssColor.init(string);
1041     CSSValueID id = cssValueKeywordID(cssColor);
1042     if (!CSSPropertyParser::isSystemColor(id))
1043         return false;
1044 
1045     Color parsedColor = RenderTheme::theme().systemColor(id);
1046     color = parsedColor.rgb();
1047     return true;
1048 }
1049 
parseSelector(const String & string,CSSSelectorList & selectorList)1050 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1051 {
1052     m_selectorListForParseSelector = &selectorList;
1053 
1054     setupParser("@-internal-selector ", string, "");
1055 
1056     cssyyparse(this);
1057 
1058     m_selectorListForParseSelector = 0;
1059 }
1060 
parseInlineStyleDeclaration(const String & string,Element * element)1061 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1062 {
1063     Document& document = element->document();
1064     CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
1065     context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
1066     return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
1067 }
1068 
parseDeclaration(const String & string,StyleSheetContents * contextStyleSheet)1069 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1070 {
1071     setStyleSheet(contextStyleSheet);
1072 
1073     setupParser("@-internal-decls ", string, "");
1074     cssyyparse(this);
1075     m_rule = nullptr;
1076 
1077     RefPtr<ImmutableStylePropertySet> style = createStylePropertySet();
1078     clearProperties();
1079     return style.release();
1080 }
1081 
1082 
parseDeclaration(MutableStylePropertySet * declaration,const String & string,CSSParserObserver * observer,StyleSheetContents * contextStyleSheet)1083 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
1084 {
1085     setStyleSheet(contextStyleSheet);
1086 
1087     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
1088 
1089     setupParser("@-internal-decls ", string, "");
1090     if (m_observer) {
1091         m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
1092         m_observer->endRuleHeader(1);
1093         m_observer->startRuleBody(0);
1094     }
1095 
1096     {
1097         StyleDeclarationScope scope(this, declaration);
1098         cssyyparse(this);
1099     }
1100 
1101     m_rule = nullptr;
1102 
1103     bool ok = false;
1104     if (!m_parsedProperties.isEmpty()) {
1105         ok = true;
1106         declaration->addParsedProperties(m_parsedProperties);
1107         clearProperties();
1108     }
1109 
1110     if (m_observer)
1111         m_observer->endRuleBody(string.length(), false);
1112 
1113     return ok;
1114 }
1115 
parseMediaQueryList(const String & string)1116 PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
1117 {
1118     ASSERT(!m_mediaList);
1119 
1120     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1121     // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
1122     setupParser("@-internal-medialist ", string, "");
1123     cssyyparse(this);
1124 
1125     ASSERT(m_mediaList);
1126     return m_mediaList.release();
1127 }
1128 
filterProperties(bool important,const WillBeHeapVector<CSSProperty,256> & input,WillBeHeapVector<CSSProperty,256> & output,size_t & unusedEntries,BitArray<numCSSProperties> & seenProperties)1129 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1130 {
1131     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1132     for (int i = input.size() - 1; i >= 0; --i) {
1133         const CSSProperty& property = input[i];
1134         if (property.isImportant() != important)
1135             continue;
1136         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1137         if (seenProperties.get(propertyIDIndex))
1138             continue;
1139         seenProperties.set(propertyIDIndex);
1140         output[--unusedEntries] = property;
1141     }
1142 }
1143 
createStylePropertySet()1144 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
1145 {
1146     BitArray<numCSSProperties> seenProperties;
1147     size_t unusedEntries = m_parsedProperties.size();
1148     WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
1149 
1150     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1151     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1152     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1153     if (unusedEntries)
1154         results.remove(0, unusedEntries);
1155 
1156     CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
1157 
1158     return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
1159 }
1160 
rollbackLastProperties(int num)1161 void BisonCSSParser::rollbackLastProperties(int num)
1162 {
1163     ASSERT(num >= 0);
1164     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1165     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1166 }
1167 
clearProperties()1168 void BisonCSSParser::clearProperties()
1169 {
1170     m_parsedProperties.clear();
1171     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1172 }
1173 
setCurrentProperty(CSSPropertyID propId)1174 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
1175 {
1176     m_id = propId;
1177 }
1178 
parseValue(CSSPropertyID propId,bool important)1179 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
1180 {
1181     CSSPropertyParser parser(m_valueList, m_context, m_inViewport, m_important, m_parsedProperties, m_ruleHeaderType);
1182     return parser.parseValue(propId, important);
1183 }
1184 
1185 
1186 class TransformOperationInfo {
1187 public:
TransformOperationInfo(const CSSParserString & name)1188     TransformOperationInfo(const CSSParserString& name)
1189         : m_type(CSSTransformValue::UnknownTransformOperation)
1190         , m_argCount(1)
1191         , m_allowSingleArgument(false)
1192         , m_unit(CSSPropertyParser::FUnknown)
1193     {
1194         const UChar* characters;
1195         unsigned nameLength = name.length();
1196 
1197         const unsigned longestNameLength = 12;
1198         UChar characterBuffer[longestNameLength];
1199         if (name.is8Bit()) {
1200             unsigned length = std::min(longestNameLength, nameLength);
1201             const LChar* characters8 = name.characters8();
1202             for (unsigned i = 0; i < length; ++i)
1203                 characterBuffer[i] = characters8[i];
1204             characters = characterBuffer;
1205         } else
1206             characters = name.characters16();
1207 
1208         SWITCH(characters, nameLength) {
1209             CASE("skew(") {
1210                 m_unit = CSSPropertyParser::FAngle;
1211                 m_type = CSSTransformValue::SkewTransformOperation;
1212                 m_allowSingleArgument = true;
1213                 m_argCount = 3;
1214             }
1215             CASE("scale(") {
1216                 m_unit = CSSPropertyParser::FNumber;
1217                 m_type = CSSTransformValue::ScaleTransformOperation;
1218                 m_allowSingleArgument = true;
1219                 m_argCount = 3;
1220             }
1221             CASE("skewx(") {
1222                 m_unit = CSSPropertyParser::FAngle;
1223                 m_type = CSSTransformValue::SkewXTransformOperation;
1224             }
1225             CASE("skewy(") {
1226                 m_unit = CSSPropertyParser::FAngle;
1227                 m_type = CSSTransformValue::SkewYTransformOperation;
1228             }
1229             CASE("matrix(") {
1230                 m_unit = CSSPropertyParser::FNumber;
1231                 m_type = CSSTransformValue::MatrixTransformOperation;
1232                 m_argCount = 11;
1233             }
1234             CASE("rotate(") {
1235                 m_unit = CSSPropertyParser::FAngle;
1236                 m_type = CSSTransformValue::RotateTransformOperation;
1237             }
1238             CASE("scalex(") {
1239                 m_unit = CSSPropertyParser::FNumber;
1240                 m_type = CSSTransformValue::ScaleXTransformOperation;
1241             }
1242             CASE("scaley(") {
1243                 m_unit = CSSPropertyParser::FNumber;
1244                 m_type = CSSTransformValue::ScaleYTransformOperation;
1245             }
1246             CASE("scalez(") {
1247                 m_unit = CSSPropertyParser::FNumber;
1248                 m_type = CSSTransformValue::ScaleZTransformOperation;
1249             }
1250             CASE("scale3d(") {
1251                 m_unit = CSSPropertyParser::FNumber;
1252                 m_type = CSSTransformValue::Scale3DTransformOperation;
1253                 m_argCount = 5;
1254             }
1255             CASE("rotatex(") {
1256                 m_unit = CSSPropertyParser::FAngle;
1257                 m_type = CSSTransformValue::RotateXTransformOperation;
1258             }
1259             CASE("rotatey(") {
1260                 m_unit = CSSPropertyParser::FAngle;
1261                 m_type = CSSTransformValue::RotateYTransformOperation;
1262             }
1263             CASE("rotatez(") {
1264                 m_unit = CSSPropertyParser::FAngle;
1265                 m_type = CSSTransformValue::RotateZTransformOperation;
1266             }
1267             CASE("matrix3d(") {
1268                 m_unit = CSSPropertyParser::FNumber;
1269                 m_type = CSSTransformValue::Matrix3DTransformOperation;
1270                 m_argCount = 31;
1271             }
1272             CASE("rotate3d(") {
1273                 m_unit = CSSPropertyParser::FNumber;
1274                 m_type = CSSTransformValue::Rotate3DTransformOperation;
1275                 m_argCount = 7;
1276             }
1277             CASE("translate(") {
1278                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1279                 m_type = CSSTransformValue::TranslateTransformOperation;
1280                 m_allowSingleArgument = true;
1281                 m_argCount = 3;
1282             }
1283             CASE("translatex(") {
1284                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1285                 m_type = CSSTransformValue::TranslateXTransformOperation;
1286             }
1287             CASE("translatey(") {
1288                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1289                 m_type = CSSTransformValue::TranslateYTransformOperation;
1290             }
1291             CASE("translatez(") {
1292                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1293                 m_type = CSSTransformValue::TranslateZTransformOperation;
1294             }
1295             CASE("perspective(") {
1296                 m_unit = CSSPropertyParser::FNumber;
1297                 m_type = CSSTransformValue::PerspectiveTransformOperation;
1298             }
1299             CASE("translate3d(") {
1300                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1301                 m_type = CSSTransformValue::Translate3DTransformOperation;
1302                 m_argCount = 5;
1303             }
1304         }
1305     }
1306 
type() const1307     CSSTransformValue::TransformOperationType type() const { return m_type; }
argCount() const1308     unsigned argCount() const { return m_argCount; }
unit() const1309     CSSPropertyParser::Units unit() const { return m_unit; }
1310 
unknown() const1311     bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
hasCorrectArgCount(unsigned argCount)1312     bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
1313 
1314 private:
1315     CSSTransformValue::TransformOperationType m_type;
1316     unsigned m_argCount;
1317     bool m_allowSingleArgument;
1318     CSSPropertyParser::Units m_unit;
1319 };
1320 
parseTransform(CSSPropertyID propId)1321 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
1322 {
1323     if (!m_valueList)
1324         return nullptr;
1325 
1326     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1327     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
1328         RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
1329         if (!parsedTransformValue)
1330             return nullptr;
1331 
1332         list->append(parsedTransformValue.release());
1333     }
1334 
1335     return list.release();
1336 }
1337 
parseTransformValue(CSSPropertyID propId,CSSParserValue * value)1338 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
1339 {
1340     if (value->unit != CSSParserValue::Function || !value->function)
1341         return nullptr;
1342 
1343     // Every primitive requires at least one argument.
1344     CSSParserValueList* args = value->function->args.get();
1345     if (!args)
1346         return nullptr;
1347 
1348     // See if the specified primitive is one we understand.
1349     TransformOperationInfo info(value->function->name);
1350     if (info.unknown())
1351         return nullptr;
1352 
1353     if (!info.hasCorrectArgCount(args->size()))
1354         return nullptr;
1355 
1356     // The transform is a list of functional primitives that specify transform operations.
1357     // We collect a list of CSSTransformValues, where each value specifies a single operation.
1358 
1359     // Create the new CSSTransformValue for this operation and add it to our list.
1360     RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
1361 
1362     // Snag our values.
1363     CSSParserValue* a = args->current();
1364     unsigned argNumber = 0;
1365     while (a) {
1366         CSSPropertyParser::Units unit = info.unit();
1367 
1368         if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
1369             // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
1370             if (!validUnit(a, FAngle, HTMLStandardMode))
1371                 return nullptr;
1372         } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
1373             // 3rd param of translate3d() cannot be a percentage
1374             if (!validUnit(a, FLength, HTMLStandardMode))
1375                 return nullptr;
1376         } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
1377             // 1st param of translateZ() cannot be a percentage
1378             if (!validUnit(a, FLength, HTMLStandardMode))
1379                 return nullptr;
1380         } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
1381             // 1st param of perspective() must be a non-negative number (deprecated) or length.
1382             if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
1383                 || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
1384                 return nullptr;
1385         } else if (!validUnit(a, unit, HTMLStandardMode)) {
1386             return nullptr;
1387         }
1388 
1389         // Add the value to the current transform operation.
1390         transformValue->append(createPrimitiveNumericValue(a));
1391 
1392         a = args->next();
1393         if (!a)
1394             break;
1395         if (a->unit != CSSParserValue::Operator || a->iValue != ',')
1396             return nullptr;
1397         a = args->next();
1398 
1399         argNumber++;
1400     }
1401 
1402     return transformValue.release();
1403 }
1404 
ensureLineEndings()1405 void BisonCSSParser::ensureLineEndings()
1406 {
1407     if (!m_lineEndings)
1408         m_lineEndings = lineEndings(*m_source);
1409 }
1410 
createFloatingSelectorWithTagName(const QualifiedName & tagQName)1411 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
1412 {
1413     CSSParserSelector* selector = new CSSParserSelector(tagQName);
1414     m_floatingSelectors.append(selector);
1415     return selector;
1416 }
1417 
createFloatingSelector()1418 CSSParserSelector* BisonCSSParser::createFloatingSelector()
1419 {
1420     CSSParserSelector* selector = new CSSParserSelector;
1421     m_floatingSelectors.append(selector);
1422     return selector;
1423 }
1424 
sinkFloatingSelector(CSSParserSelector * selector)1425 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
1426 {
1427     if (selector) {
1428         size_t index = m_floatingSelectors.reverseFind(selector);
1429         ASSERT(index != kNotFound);
1430         m_floatingSelectors.remove(index);
1431     }
1432     return adoptPtr(selector);
1433 }
1434 
createFloatingSelectorVector()1435 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
1436 {
1437     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
1438     m_floatingSelectorVectors.append(selectorVector);
1439     return selectorVector;
1440 }
1441 
sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector>> * selectorVector)1442 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
1443 {
1444     if (selectorVector) {
1445         size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
1446         ASSERT(index != kNotFound);
1447         m_floatingSelectorVectors.remove(index);
1448     }
1449     return adoptPtr(selectorVector);
1450 }
1451 
createFloatingValueList()1452 CSSParserValueList* BisonCSSParser::createFloatingValueList()
1453 {
1454     CSSParserValueList* list = new CSSParserValueList;
1455     m_floatingValueLists.append(list);
1456     return list;
1457 }
1458 
sinkFloatingValueList(CSSParserValueList * list)1459 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
1460 {
1461     if (list) {
1462         size_t index = m_floatingValueLists.reverseFind(list);
1463         ASSERT(index != kNotFound);
1464         m_floatingValueLists.remove(index);
1465     }
1466     return adoptPtr(list);
1467 }
1468 
createFloatingFunction()1469 CSSParserFunction* BisonCSSParser::createFloatingFunction()
1470 {
1471     CSSParserFunction* function = new CSSParserFunction;
1472     m_floatingFunctions.append(function);
1473     return function;
1474 }
1475 
createFloatingFunction(const CSSParserString & name,PassOwnPtr<CSSParserValueList> args)1476 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
1477 {
1478     CSSParserFunction* function = createFloatingFunction();
1479     function->name = name;
1480     function->args = args;
1481     return function;
1482 }
1483 
sinkFloatingFunction(CSSParserFunction * function)1484 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
1485 {
1486     if (function) {
1487         size_t index = m_floatingFunctions.reverseFind(function);
1488         ASSERT(index != kNotFound);
1489         m_floatingFunctions.remove(index);
1490     }
1491     return adoptPtr(function);
1492 }
1493 
sinkFloatingValue(CSSParserValue & value)1494 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
1495 {
1496     if (value.unit == CSSParserValue::Function) {
1497         size_t index = m_floatingFunctions.reverseFind(value.function);
1498         ASSERT(index != kNotFound);
1499         m_floatingFunctions.remove(index);
1500     }
1501     return value;
1502 }
1503 
createFloatingMediaQueryExp(const AtomicString & mediaFeature,CSSParserValueList * values)1504 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
1505 {
1506     m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
1507     return m_floatingMediaQueryExp.get();
1508 }
1509 
sinkFloatingMediaQueryExp(MediaQueryExp * expression)1510 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
1511 {
1512     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
1513     return m_floatingMediaQueryExp.release();
1514 }
1515 
createFloatingMediaQueryExpList()1516 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
1517 {
1518     m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
1519     return m_floatingMediaQueryExpList.get();
1520 }
1521 
sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp>> * list)1522 PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
1523 {
1524     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
1525     return m_floatingMediaQueryExpList.release();
1526 }
1527 
createFloatingMediaQuery(MediaQuery::Restrictor restrictor,const AtomicString & mediaType,PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp>>> expressions)1528 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1529 {
1530     m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
1531     return m_floatingMediaQuery.get();
1532 }
1533 
createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp>>> expressions)1534 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1535 {
1536     return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions);
1537 }
1538 
createFloatingNotAllQuery()1539 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
1540 {
1541     return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
1542 }
1543 
sinkFloatingMediaQuery(MediaQuery * query)1544 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
1545 {
1546     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
1547     return m_floatingMediaQuery.release();
1548 }
1549 
createFloatingKeyframeVector()1550 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
1551 {
1552     m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
1553     return m_floatingKeyframeVector.get();
1554 }
1555 
sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe>> * keyframeVector)1556 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
1557 {
1558     ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
1559     return m_floatingKeyframeVector.release();
1560 }
1561 
createMediaQuerySet()1562 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
1563 {
1564     RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
1565     MediaQuerySet* result = queries.get();
1566     m_parsedMediaQuerySets.append(queries.release());
1567     return result;
1568 }
1569 
createImportRule(const CSSParserString & url,MediaQuerySet * media)1570 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
1571 {
1572     if (!media || !m_allowImportRules)
1573         return 0;
1574     RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
1575     StyleRuleImport* result = rule.get();
1576     m_parsedRules.append(rule.release());
1577     return result;
1578 }
1579 
createMediaRule(MediaQuerySet * media,RuleList * rules)1580 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
1581 {
1582     m_allowImportRules = m_allowNamespaceDeclarations = false;
1583     RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
1584     if (rules) {
1585         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
1586     } else {
1587         RuleList emptyRules;
1588         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
1589     }
1590     StyleRuleMedia* result = rule.get();
1591     m_parsedRules.append(rule.release());
1592     return result;
1593 }
1594 
createSupportsRule(bool conditionIsSupported,RuleList * rules)1595 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
1596 {
1597     m_allowImportRules = m_allowNamespaceDeclarations = false;
1598 
1599     RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
1600     RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
1601     String conditionText;
1602     unsigned conditionOffset = data->ruleHeaderRange.start + 9;
1603     unsigned conditionLength = data->ruleHeaderRange.length() - 9;
1604 
1605     if (m_tokenizer.is8BitSource())
1606         conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
1607     else
1608         conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
1609 
1610     if (rules) {
1611         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
1612     } else {
1613         RuleList emptyRules;
1614         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
1615     }
1616 
1617     StyleRuleSupports* result = rule.get();
1618     m_parsedRules.append(rule.release());
1619 
1620     return result;
1621 }
1622 
markSupportsRuleHeaderStart()1623 void BisonCSSParser::markSupportsRuleHeaderStart()
1624 {
1625     if (!m_supportsRuleDataStack)
1626         m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
1627 
1628     RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
1629     data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
1630     m_supportsRuleDataStack->append(data);
1631 }
1632 
markSupportsRuleHeaderEnd()1633 void BisonCSSParser::markSupportsRuleHeaderEnd()
1634 {
1635     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1636 
1637     if (m_tokenizer.is8BitSource())
1638         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
1639     else
1640         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
1641 }
1642 
popSupportsRuleData()1643 PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
1644 {
1645     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1646     RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
1647     m_supportsRuleDataStack->removeLast();
1648     return data.release();
1649 }
1650 
createRuleList()1651 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
1652 {
1653     OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
1654     RuleList* listPtr = list.get();
1655 
1656     m_parsedRuleLists.append(list.release());
1657     return listPtr;
1658 }
1659 
appendRule(RuleList * ruleList,StyleRuleBase * rule)1660 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
1661 {
1662     if (rule) {
1663         if (!ruleList)
1664             ruleList = createRuleList();
1665         ruleList->append(rule);
1666     }
1667     return ruleList;
1668 }
1669 
1670 template <typename CharacterType>
makeLower(const CharacterType * input,CharacterType * output,unsigned length)1671 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
1672 {
1673     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
1674     // that can potentially change the length of the string rather than the character
1675     // by character kind. If we don't need Unicode lowercasing, it would be good to
1676     // simplify this function.
1677 
1678     if (charactersAreAllASCII(input, length)) {
1679         // Fast case for all-ASCII.
1680         for (unsigned i = 0; i < length; i++)
1681             output[i] = toASCIILower(input[i]);
1682     } else {
1683         for (unsigned i = 0; i < length; i++)
1684             output[i] = Unicode::toLower(input[i]);
1685     }
1686 }
1687 
tokenToLowerCase(CSSParserString & token)1688 void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
1689 {
1690     // Since it's our internal token, we know that we created it out
1691     // of our writable work buffers. Therefore the const_cast is just
1692     // ugly and not a potential crash.
1693     size_t length = token.length();
1694     if (token.is8Bit()) {
1695         makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
1696     } else {
1697         makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
1698     }
1699 }
1700 
endInvalidRuleHeader()1701 void BisonCSSParser::endInvalidRuleHeader()
1702 {
1703     if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
1704         return;
1705 
1706     CSSParserLocation location;
1707     location.lineNumber = m_tokenizer.m_lineNumber;
1708     location.offset = m_ruleHeaderStartOffset;
1709     if (m_tokenizer.is8BitSource())
1710         location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
1711     else
1712         location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
1713 
1714     reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
1715 
1716     endRuleHeader();
1717 }
1718 
reportError(const CSSParserLocation &,CSSParserError)1719 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
1720 {
1721     // FIXME: error reporting temporatily disabled.
1722 }
1723 
isLoggingErrors()1724 bool BisonCSSParser::isLoggingErrors()
1725 {
1726     return m_logErrors && !m_ignoreErrors;
1727 }
1728 
logError(const String & message,const CSSParserLocation & location)1729 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
1730 {
1731     unsigned lineNumberInStyleSheet;
1732     unsigned columnNumber = 0;
1733     if (InspectorInstrumentation::hasFrontends()) {
1734         ensureLineEndings();
1735         TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
1736         lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
1737         columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
1738     } else {
1739         lineNumberInStyleSheet = location.lineNumber;
1740     }
1741     FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
1742     console.addMessage(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1);
1743 }
1744 
createKeyframesRule(const String & name,PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe>>> popKeyframes,bool isPrefixed)1745 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
1746 {
1747     OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
1748     m_allowImportRules = m_allowNamespaceDeclarations = false;
1749     RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
1750     for (size_t i = 0; i < keyframes->size(); ++i)
1751         rule->parserAppendKeyframe(keyframes->at(i));
1752     rule->setName(name);
1753     rule->setVendorPrefixed(isPrefixed);
1754     StyleRuleKeyframes* rulePtr = rule.get();
1755     m_parsedRules.append(rule.release());
1756     return rulePtr;
1757 }
1758 
recordSelectorStats(const CSSParserContext & context,const CSSSelectorList & selectorList)1759 static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList)
1760 {
1761     if (!context.useCounter())
1762         return;
1763 
1764     for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
1765         for (const CSSSelector* current = selector; current ; current = current->tagHistory()) {
1766             UseCounter::Feature feature = UseCounter::NumberOfFeatures;
1767             switch (current->pseudoType()) {
1768             case CSSSelector::PseudoUnresolved:
1769                 feature = UseCounter::CSSSelectorPseudoUnresolved;
1770                 break;
1771             case CSSSelector::PseudoShadow:
1772                 feature = UseCounter::CSSSelectorPseudoShadow;
1773                 break;
1774             case CSSSelector::PseudoContent:
1775                 feature = UseCounter::CSSSelectorPseudoContent;
1776                 break;
1777             case CSSSelector::PseudoHost:
1778                 feature = UseCounter::CSSSelectorPseudoHost;
1779                 break;
1780             case CSSSelector::PseudoHostContext:
1781                 feature = UseCounter::CSSSelectorPseudoHostContext;
1782                 break;
1783             default:
1784                 break;
1785             }
1786             if (feature != UseCounter::NumberOfFeatures)
1787                 context.useCounter()->count(feature);
1788             if (current->relation() == CSSSelector::ShadowDeep)
1789                 context.useCounter()->count(UseCounter::CSSDeepCombinator);
1790             if (current->selectorList())
1791                 recordSelectorStats(context, *current->selectorList());
1792         }
1793     }
1794 }
1795 
createStyleRule(Vector<OwnPtr<CSSParserSelector>> * selectors)1796 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
1797 {
1798     StyleRule* result = 0;
1799     if (selectors) {
1800         m_allowImportRules = m_allowNamespaceDeclarations = false;
1801         RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
1802         rule->parserAdoptSelectorVector(*selectors);
1803         rule->setProperties(createStylePropertySet());
1804         result = rule.get();
1805         m_parsedRules.append(rule.release());
1806         recordSelectorStats(m_context, result->selectorList());
1807     }
1808     clearProperties();
1809     return result;
1810 }
1811 
createFontFaceRule()1812 StyleRuleBase* BisonCSSParser::createFontFaceRule()
1813 {
1814     m_allowImportRules = m_allowNamespaceDeclarations = false;
1815     for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
1816         CSSProperty& property = m_parsedProperties[i];
1817         if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
1818             property.wrapValueInCommaSeparatedList();
1819         else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
1820             // Unlike font-family property, font-family descriptor in @font-face rule
1821             // has to be a value list with exactly one family name. It cannot have a
1822             // have 'initial' value and cannot 'inherit' from parent.
1823             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
1824             clearProperties();
1825             return 0;
1826         }
1827     }
1828     RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
1829     rule->setProperties(createStylePropertySet());
1830     clearProperties();
1831     StyleRuleFontFace* result = rule.get();
1832     m_parsedRules.append(rule.release());
1833     if (m_styleSheet)
1834         m_styleSheet->setHasFontFaceRule(true);
1835     return result;
1836 }
1837 
addNamespace(const AtomicString & prefix,const AtomicString & uri)1838 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
1839 {
1840     if (!m_styleSheet || !m_allowNamespaceDeclarations)
1841         return;
1842     m_allowImportRules = false;
1843     m_styleSheet->parserAddNamespace(prefix, uri);
1844     if (prefix.isEmpty() && !uri.isNull())
1845         m_defaultNamespace = uri;
1846 }
1847 
determineNameInNamespace(const AtomicString & prefix,const AtomicString & localName)1848 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
1849 {
1850     if (!m_styleSheet)
1851         return QualifiedName(prefix, localName, m_defaultNamespace);
1852     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
1853 }
1854 
rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector * specifiers)1855 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
1856 {
1857     if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
1858         return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
1859     return specifiers;
1860 }
1861 
rewriteSpecifiersWithElementName(const AtomicString & namespacePrefix,const AtomicString & elementName,CSSParserSelector * specifiers,bool tagIsForNamespaceRule)1862 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1863 {
1864     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
1865     QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
1866 
1867     if (specifiers->crossesTreeScopes())
1868         return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1869 
1870     if (specifiers->isContentPseudoElement())
1871         return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1872 
1873     // *:host never matches, so we can't discard the * otherwise we can't tell the
1874     // difference between *:host and just :host.
1875     if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
1876         return specifiers;
1877     if (specifiers->pseudoType() != CSSSelector::PseudoCue)
1878         specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
1879     return specifiers;
1880 }
1881 
rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName & tag,const AtomicString & elementName,CSSParserSelector * specifiers,bool tagIsForNamespaceRule)1882 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1883 {
1884     if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
1885         m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
1886 
1887     CSSParserSelector* lastShadowPseudo = specifiers;
1888     CSSParserSelector* history = specifiers;
1889     while (history->tagHistory()) {
1890         history = history->tagHistory();
1891         if (history->crossesTreeScopes() || history->hasShadowPseudo())
1892             lastShadowPseudo = history;
1893     }
1894 
1895     if (lastShadowPseudo->tagHistory()) {
1896         if (tag != anyQName())
1897             lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1898         return specifiers;
1899     }
1900 
1901     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1902     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1903     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1904     lastShadowPseudo->setTagHistory(elementNameSelector.release());
1905     lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
1906     return specifiers;
1907 }
1908 
rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName & tag,const AtomicString & elementName,CSSParserSelector * specifiers,bool tagIsForNamespaceRule)1909 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1910 {
1911     CSSParserSelector* last = specifiers;
1912     CSSParserSelector* history = specifiers;
1913     while (history->tagHistory()) {
1914         history = history->tagHistory();
1915         if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
1916             last = history;
1917     }
1918 
1919     if (last->tagHistory()) {
1920         if (tag != anyQName())
1921             last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1922         return specifiers;
1923     }
1924 
1925     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1926     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1927     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1928     last->setTagHistory(elementNameSelector.release());
1929     last->setRelation(CSSSelector::SubSelector);
1930     return specifiers;
1931 }
1932 
rewriteSpecifiers(CSSParserSelector * specifiers,CSSParserSelector * newSpecifier)1933 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
1934 {
1935     if (newSpecifier->crossesTreeScopes()) {
1936         // Unknown pseudo element always goes at the top of selector chain.
1937         newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
1938         return newSpecifier;
1939     }
1940     if (newSpecifier->isContentPseudoElement()) {
1941         newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
1942         return newSpecifier;
1943     }
1944     if (specifiers->crossesTreeScopes()) {
1945         // Specifiers for unknown pseudo element go right behind it in the chain.
1946         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
1947         return specifiers;
1948     }
1949     if (specifiers->isContentPseudoElement()) {
1950         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
1951         return specifiers;
1952     }
1953     specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
1954     return specifiers;
1955 }
1956 
createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)1957 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
1958 {
1959     // FIXME: Margin at-rules are ignored.
1960     m_allowImportRules = m_allowNamespaceDeclarations = false;
1961     StyleRulePage* pageRule = 0;
1962     if (pageSelector) {
1963         RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
1964         Vector<OwnPtr<CSSParserSelector> > selectorVector;
1965         selectorVector.append(pageSelector);
1966         rule->parserAdoptSelectorVector(selectorVector);
1967         rule->setProperties(createStylePropertySet());
1968         pageRule = rule.get();
1969         m_parsedRules.append(rule.release());
1970     }
1971     clearProperties();
1972     return pageRule;
1973 }
1974 
createMarginAtRule(CSSSelector::MarginBoxType)1975 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
1976 {
1977     // FIXME: Implement margin at-rule here, using:
1978     //        - marginBox: margin box
1979     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
1980     // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
1981 
1982     endDeclarationsForMarginBox();
1983     return 0; // until this method is implemented.
1984 }
1985 
startDeclarationsForMarginBox()1986 void BisonCSSParser::startDeclarationsForMarginBox()
1987 {
1988     m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
1989 }
1990 
endDeclarationsForMarginBox()1991 void BisonCSSParser::endDeclarationsForMarginBox()
1992 {
1993     rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
1994     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1995 }
1996 
createKeyframe(CSSParserValueList * keys)1997 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
1998 {
1999     OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
2000     if (keyVector->isEmpty())
2001         return 0;
2002 
2003     RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
2004     keyframe->setKeys(keyVector.release());
2005     keyframe->setProperties(createStylePropertySet());
2006 
2007     clearProperties();
2008 
2009     StyleKeyframe* keyframePtr = keyframe.get();
2010     m_parsedKeyframes.append(keyframe.release());
2011     return keyframePtr;
2012 }
2013 
invalidBlockHit()2014 void BisonCSSParser::invalidBlockHit()
2015 {
2016     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
2017         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
2018 }
2019 
startRule()2020 void BisonCSSParser::startRule()
2021 {
2022     if (!m_observer)
2023         return;
2024 
2025     ASSERT(m_ruleHasHeader);
2026     m_ruleHasHeader = false;
2027 }
2028 
endRule(bool valid)2029 void BisonCSSParser::endRule(bool valid)
2030 {
2031     if (!m_observer)
2032         return;
2033 
2034     if (m_ruleHasHeader)
2035         m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
2036     m_ruleHasHeader = true;
2037 }
2038 
startRuleHeader(CSSRuleSourceData::Type ruleType)2039 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
2040 {
2041     resumeErrorLogging();
2042     m_ruleHeaderType = ruleType;
2043     m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
2044     m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
2045     if (m_observer) {
2046         ASSERT(!m_ruleHasHeader);
2047         m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
2048         m_ruleHasHeader = true;
2049     }
2050 }
2051 
endRuleHeader()2052 void BisonCSSParser::endRuleHeader()
2053 {
2054     ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
2055     m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
2056     if (m_observer) {
2057         ASSERT(m_ruleHasHeader);
2058         m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
2059     }
2060 }
2061 
startSelector()2062 void BisonCSSParser::startSelector()
2063 {
2064     if (m_observer)
2065         m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
2066 }
2067 
endSelector()2068 void BisonCSSParser::endSelector()
2069 {
2070     if (m_observer)
2071         m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
2072 }
2073 
startRuleBody()2074 void BisonCSSParser::startRuleBody()
2075 {
2076     if (m_observer)
2077         m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
2078 }
2079 
startProperty()2080 void BisonCSSParser::startProperty()
2081 {
2082     resumeErrorLogging();
2083     if (m_observer)
2084         m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
2085 }
2086 
endProperty(bool isImportantFound,bool isPropertyParsed,CSSParserError errorType)2087 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
2088 {
2089     m_id = CSSPropertyInvalid;
2090     if (m_observer)
2091         m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
2092 }
2093 
startEndUnknownRule()2094 void BisonCSSParser::startEndUnknownRule()
2095 {
2096     if (m_observer)
2097         m_observer->startEndUnknownRule();
2098 }
2099 
createViewportRule()2100 StyleRuleBase* BisonCSSParser::createViewportRule()
2101 {
2102     // Allow @viewport rules from UA stylesheets even if the feature is disabled.
2103     if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
2104         return 0;
2105 
2106     m_allowImportRules = m_allowNamespaceDeclarations = false;
2107 
2108     RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
2109 
2110     rule->setProperties(createStylePropertySet());
2111     clearProperties();
2112 
2113     StyleRuleViewport* result = rule.get();
2114     m_parsedRules.append(rule.release());
2115 
2116     return result;
2117 }
2118 
2119 }
2120