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/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 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 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 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 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 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 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 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 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 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 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 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> 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 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 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 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 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> 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> 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> 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> 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 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 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 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 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 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 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. 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 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 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 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 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 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 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 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 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 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 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 1168 void BisonCSSParser::clearProperties() 1169 { 1170 m_parsedProperties.clear(); 1171 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; 1172 } 1173 1174 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId) 1175 { 1176 m_id = propId; 1177 } 1178 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: 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 1307 CSSTransformValue::TransformOperationType type() const { return m_type; } 1308 unsigned argCount() const { return m_argCount; } 1309 CSSPropertyParser::Units unit() const { return m_unit; } 1310 1311 bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; } 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 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 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 1405 void BisonCSSParser::ensureLineEndings() 1406 { 1407 if (!m_lineEndings) 1408 m_lineEndings = lineEndings(*m_source); 1409 } 1410 1411 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName) 1412 { 1413 CSSParserSelector* selector = new CSSParserSelector(tagQName); 1414 m_floatingSelectors.append(selector); 1415 return selector; 1416 } 1417 1418 CSSParserSelector* BisonCSSParser::createFloatingSelector() 1419 { 1420 CSSParserSelector* selector = new CSSParserSelector; 1421 m_floatingSelectors.append(selector); 1422 return selector; 1423 } 1424 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 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 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 1452 CSSParserValueList* BisonCSSParser::createFloatingValueList() 1453 { 1454 CSSParserValueList* list = new CSSParserValueList; 1455 m_floatingValueLists.append(list); 1456 return list; 1457 } 1458 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 1469 CSSParserFunction* BisonCSSParser::createFloatingFunction() 1470 { 1471 CSSParserFunction* function = new CSSParserFunction; 1472 m_floatingFunctions.append(function); 1473 return function; 1474 } 1475 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 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 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 1504 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values) 1505 { 1506 m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values); 1507 return m_floatingMediaQueryExp.get(); 1508 } 1509 1510 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression) 1511 { 1512 ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp); 1513 return m_floatingMediaQueryExp.release(); 1514 } 1515 1516 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList() 1517 { 1518 m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >); 1519 return m_floatingMediaQueryExpList.get(); 1520 } 1521 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 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 1534 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions) 1535 { 1536 return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions); 1537 } 1538 1539 MediaQuery* BisonCSSParser::createFloatingNotAllQuery() 1540 { 1541 return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList())); 1542 } 1543 1544 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query) 1545 { 1546 ASSERT_UNUSED(query, query == m_floatingMediaQuery); 1547 return m_floatingMediaQuery.release(); 1548 } 1549 1550 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector() 1551 { 1552 m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >()); 1553 return m_floatingKeyframeVector.get(); 1554 } 1555 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 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 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 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 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 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 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 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 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 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> 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 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 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 1719 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError) 1720 { 1721 // FIXME: error reporting temporatily disabled. 1722 } 1723 1724 bool BisonCSSParser::isLoggingErrors() 1725 { 1726 return m_logErrors && !m_ignoreErrors; 1727 } 1728 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1986 void BisonCSSParser::startDeclarationsForMarginBox() 1987 { 1988 m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size(); 1989 } 1990 1991 void BisonCSSParser::endDeclarationsForMarginBox() 1992 { 1993 rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox); 1994 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; 1995 } 1996 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 2014 void BisonCSSParser::invalidBlockHit() 2015 { 2016 if (m_styleSheet && !m_hadSyntacticallyValidCSSRule) 2017 m_styleSheet->setHasSyntacticallyValidCSSHeader(false); 2018 } 2019 2020 void BisonCSSParser::startRule() 2021 { 2022 if (!m_observer) 2023 return; 2024 2025 ASSERT(m_ruleHasHeader); 2026 m_ruleHasHeader = false; 2027 } 2028 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 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 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 2062 void BisonCSSParser::startSelector() 2063 { 2064 if (m_observer) 2065 m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset()); 2066 } 2067 2068 void BisonCSSParser::endSelector() 2069 { 2070 if (m_observer) 2071 m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset()); 2072 } 2073 2074 void BisonCSSParser::startRuleBody() 2075 { 2076 if (m_observer) 2077 m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset()); 2078 } 2079 2080 void BisonCSSParser::startProperty() 2081 { 2082 resumeErrorLogging(); 2083 if (m_observer) 2084 m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset()); 2085 } 2086 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 2094 void BisonCSSParser::startEndUnknownRule() 2095 { 2096 if (m_observer) 2097 m_observer->startEndUnknownRule(); 2098 } 2099 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