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