OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
All rights reserved. |
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> | 5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | 8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
9 * Copyright (C) 2012 Intel Corporation. All rights reserved. | 9 * Copyright (C) 2012 Intel Corporation. All rights reserved. |
10 * | 10 * |
11 * This library is free software; you can redistribute it and/or | 11 * This library is free software; you can redistribute it and/or |
12 * modify it under the terms of the GNU Library General Public | 12 * modify it under the terms of the GNU Library General Public |
13 * License as published by the Free Software Foundation; either | 13 * License as published by the Free Software Foundation; either |
14 * version 2 of the License, or (at your option) any later version. | 14 * version 2 of the License, or (at your option) any later version. |
15 * | 15 * |
16 * This library is distributed in the hope that it will be useful, | 16 * This library is distributed in the hope that it will be useful, |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 * Library General Public License for more details. | 19 * Library General Public License for more details. |
20 * | 20 * |
21 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
24 * Boston, MA 02110-1301, USA. | 24 * Boston, MA 02110-1301, USA. |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 #include "core/css/parser/CSSPropertyParser.h" | 28 #include "core/css/parser/CSSPropertyParser.h" |
| 29 #include "RuntimeEnabledFeatures.h" |
| 30 #include "core/rendering/RenderTheme.h" |
| 31 #include "core/svg/SVGPaint.h" |
| 32 |
| 33 using namespace std; |
29 | 34 |
30 namespace WebCore { | 35 namespace WebCore { |
31 | 36 |
32 CSSPropertyParser::CSSPropertyParser(OwnPtr<CSSParserValueList>& valueList, | 37 CSSPropertyParser::CSSPropertyParser(OwnPtr<CSSParserValueList>& valueList, |
33 const CSSParserContext& context, bool inViewport, bool savedImportant, | 38 const CSSParserContext& context, bool inViewport, bool savedImportant, |
34 ParsedPropertyVector& parsedProperties, bool& hasFontFaceOnlyValues) | 39 ParsedPropertyVector& parsedProperties, bool& hasFontFaceOnlyValues) |
35 : m_valueList(valueList) | 40 : m_valueList(valueList) |
36 , m_context(context) | 41 , m_context(context) |
37 , m_inViewport(inViewport) | 42 , m_inViewport(inViewport) |
38 , m_important(savedImportant) // See comment in header, should be removed. | 43 , m_important(savedImportant) // See comment in header, should be removed. |
39 , m_parsedProperties(parsedProperties) | 44 , m_parsedProperties(parsedProperties) |
40 , m_hasFontFaceOnlyValues(hasFontFaceOnlyValues) | 45 , m_hasFontFaceOnlyValues(hasFontFaceOnlyValues) |
41 , m_inParseShorthand(0) | 46 , m_inParseShorthand(0) |
42 , m_currentShorthand(CSSPropertyInvalid) | 47 , m_currentShorthand(CSSPropertyInvalid) |
43 , m_implicitShorthand(false) | 48 , m_implicitShorthand(false) |
44 { | 49 { |
45 } | 50 } |
46 | 51 |
47 CSSPropertyParser::~CSSPropertyParser() | 52 CSSPropertyParser::~CSSPropertyParser() |
48 { | 53 { |
49 } | 54 } |
50 | 55 |
| 56 bool CSSPropertyParser::isSystemColor(int id) |
| 57 { |
| 58 return (id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSS
ValueMenu; |
| 59 } |
| 60 |
| 61 bool CSSPropertyParser::parseSVGValue(CSSPropertyID propId, bool important) |
| 62 { |
| 63 CSSParserValue* value = m_valueList->current(); |
| 64 if (!value) |
| 65 return false; |
| 66 |
| 67 CSSValueID id = value->id; |
| 68 |
| 69 bool validPrimitive = false; |
| 70 RefPtrWillBeRawPtr<CSSValue> parsedValue; |
| 71 |
| 72 switch (propId) { |
| 73 /* The comment to the right defines all valid value of these |
| 74 * properties as defined in SVG 1.1, Appendix N. Property index */ |
| 75 case CSSPropertyAlignmentBaseline: |
| 76 // auto | baseline | before-edge | text-before-edge | middle | |
| 77 // central | after-edge | text-after-edge | ideographic | alphabetic | |
| 78 // hanging | mathematical | inherit |
| 79 if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle |
| 80 || (id >= CSSValueBeforeEdge && id <= CSSValueMathematical)) |
| 81 validPrimitive = true; |
| 82 break; |
| 83 |
| 84 case CSSPropertyBaselineShift: |
| 85 // baseline | super | sub | <percentage> | <length> | inherit |
| 86 if (id == CSSValueBaseline || id == CSSValueSub |
| 87 || id >= CSSValueSuper) |
| 88 validPrimitive = true; |
| 89 else |
| 90 validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMo
de); |
| 91 break; |
| 92 |
| 93 case CSSPropertyDominantBaseline: |
| 94 // auto | use-script | no-change | reset-size | ideographic | |
| 95 // alphabetic | hanging | mathematical | central | middle | |
| 96 // text-after-edge | text-before-edge | inherit |
| 97 if (id == CSSValueAuto || id == CSSValueMiddle |
| 98 || (id >= CSSValueUseScript && id <= CSSValueResetSize) |
| 99 || (id >= CSSValueCentral && id <= CSSValueMathematical)) |
| 100 validPrimitive = true; |
| 101 break; |
| 102 |
| 103 case CSSPropertyEnableBackground: |
| 104 // accumulate | new [x] [y] [width] [height] | inherit |
| 105 if (id == CSSValueAccumulate) // TODO : new |
| 106 validPrimitive = true; |
| 107 break; |
| 108 |
| 109 case CSSPropertyMarkerStart: |
| 110 case CSSPropertyMarkerMid: |
| 111 case CSSPropertyMarkerEnd: |
| 112 case CSSPropertyMask: |
| 113 if (id == CSSValueNone) { |
| 114 validPrimitive = true; |
| 115 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { |
| 116 parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveV
alue::CSS_URI); |
| 117 if (parsedValue) |
| 118 m_valueList->next(); |
| 119 } |
| 120 break; |
| 121 |
| 122 case CSSPropertyClipRule: // nonzero | evenodd | inherit |
| 123 case CSSPropertyFillRule: |
| 124 if (id == CSSValueNonzero || id == CSSValueEvenodd) |
| 125 validPrimitive = true; |
| 126 break; |
| 127 |
| 128 case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit |
| 129 validPrimitive = validUnit(value, FNumber | FNonNeg, SVGAttributeMode); |
| 130 break; |
| 131 |
| 132 case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit |
| 133 if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel) |
| 134 validPrimitive = true; |
| 135 break; |
| 136 |
| 137 case CSSPropertyStrokeLinecap: // butt | round | square | inherit |
| 138 if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare) |
| 139 validPrimitive = true; |
| 140 break; |
| 141 |
| 142 case CSSPropertyStrokeOpacity: // <opacity-value> | inherit |
| 143 case CSSPropertyFillOpacity: |
| 144 case CSSPropertyStopOpacity: |
| 145 case CSSPropertyFloodOpacity: |
| 146 validPrimitive = (!id && validUnit(value, FNumber | FPercent, SVGAttribu
teMode)); |
| 147 break; |
| 148 |
| 149 case CSSPropertyShapeRendering: |
| 150 // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit |
| 151 if (id == CSSValueAuto || id == CSSValueOptimizespeed |
| 152 || id == CSSValueCrispedges || id == CSSValueGeometricprecision) |
| 153 validPrimitive = true; |
| 154 break; |
| 155 |
| 156 case CSSPropertyImageRendering: // auto | optimizeSpeed | |
| 157 case CSSPropertyColorRendering: // optimizeQuality | inherit |
| 158 if (id == CSSValueAuto || id == CSSValueOptimizespeed |
| 159 || id == CSSValueOptimizequality) |
| 160 validPrimitive = true; |
| 161 break; |
| 162 |
| 163 case CSSPropertyBufferedRendering: // auto | dynamic | static |
| 164 if (id == CSSValueAuto || id == CSSValueDynamic || id == CSSValueStatic) |
| 165 validPrimitive = true; |
| 166 break; |
| 167 |
| 168 case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit |
| 169 if (id == CSSValueAuto || id == CSSValueSrgb) |
| 170 validPrimitive = true; |
| 171 break; |
| 172 |
| 173 case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit |
| 174 case CSSPropertyColorInterpolationFilters: |
| 175 if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb) |
| 176 validPrimitive = true; |
| 177 break; |
| 178 |
| 179 /* Start of supported CSS properties with validation. This is needed for par
seShortHand to work |
| 180 * correctly and allows optimization in applyRule(..) |
| 181 */ |
| 182 |
| 183 case CSSPropertyTextAnchor: // start | middle | end | inherit |
| 184 if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd) |
| 185 validPrimitive = true; |
| 186 break; |
| 187 |
| 188 case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit |
| 189 if (id == CSSValueAuto) { |
| 190 validPrimitive = true; |
| 191 break; |
| 192 } |
| 193 /* fallthrough intentional */ |
| 194 case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_
per SVG 1.1 spec) | inherit |
| 195 if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimi
tiveValue::CSS_NUMBER) { |
| 196 parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveV
alue::CSS_DEG); |
| 197 |
| 198 if (parsedValue) |
| 199 m_valueList->next(); |
| 200 } |
| 201 break; |
| 202 |
| 203 case CSSPropertyFill: // <paint> | inherit |
| 204 case CSSPropertyStroke: // <paint> | inherit |
| 205 { |
| 206 if (id == CSSValueNone) { |
| 207 parsedValue = SVGPaint::createNone(); |
| 208 } else if (id == CSSValueCurrentcolor) { |
| 209 parsedValue = SVGPaint::createCurrentColor(); |
| 210 } else if (isSystemColor(id)) { |
| 211 parsedValue = SVGPaint::createColor(RenderTheme::theme().systemC
olor(id)); |
| 212 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { |
| 213 RGBA32 c = Color::transparent; |
| 214 if (m_valueList->next()) { |
| 215 if (parseColorFromValue(m_valueList->current(), c)) |
| 216 parsedValue = SVGPaint::createURIAndColor(value->string,
c); |
| 217 else if (m_valueList->current()->id == CSSValueNone) |
| 218 parsedValue = SVGPaint::createURIAndNone(value->string); |
| 219 else if (m_valueList->current()->id == CSSValueCurrentcolor) |
| 220 parsedValue = SVGPaint::createURIAndCurrentColor(value->
string); |
| 221 } |
| 222 if (!parsedValue) |
| 223 parsedValue = SVGPaint::createURI(value->string); |
| 224 } else { |
| 225 parsedValue = parseSVGPaint(); |
| 226 } |
| 227 |
| 228 if (parsedValue) |
| 229 m_valueList->next(); |
| 230 } |
| 231 break; |
| 232 |
| 233 case CSSPropertyStopColor: // TODO : icccolor |
| 234 case CSSPropertyFloodColor: |
| 235 case CSSPropertyLightingColor: |
| 236 if (isSystemColor(id)) |
| 237 parsedValue = SVGColor::createFromColor(RenderTheme::theme().systemC
olor(id)); |
| 238 else if ((id >= CSSValueAqua && id <= CSSValueTransparent) |
| 239 || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen) || id == C
SSValueGrey) |
| 240 parsedValue = SVGColor::createFromString(value->string); |
| 241 else if (id == CSSValueCurrentcolor) |
| 242 parsedValue = SVGColor::createCurrentColor(); |
| 243 else // TODO : svgcolor (iccColor) |
| 244 parsedValue = parseSVGColor(); |
| 245 |
| 246 if (parsedValue) |
| 247 m_valueList->next(); |
| 248 |
| 249 break; |
| 250 |
| 251 case CSSPropertyPaintOrder: |
| 252 if (!RuntimeEnabledFeatures::svgPaintOrderEnabled()) |
| 253 return false; |
| 254 |
| 255 if (m_valueList->size() == 1 && id == CSSValueNormal) |
| 256 validPrimitive = true; |
| 257 else if ((parsedValue = parsePaintOrder())) |
| 258 m_valueList->next(); |
| 259 break; |
| 260 |
| 261 case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit |
| 262 if (id == CSSValueNone || id == CSSValueNonScalingStroke) |
| 263 validPrimitive = true; |
| 264 break; |
| 265 |
| 266 case CSSPropertyWritingMode: |
| 267 // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit |
| 268 if (id == CSSValueLrTb || id == CSSValueRlTb || id == CSSValueTbRl || id
== CSSValueLr || id == CSSValueRl || id == CSSValueTb) |
| 269 validPrimitive = true; |
| 270 break; |
| 271 |
| 272 case CSSPropertyStrokeWidth: // <length> | inherit |
| 273 case CSSPropertyStrokeDashoffset: |
| 274 validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMode); |
| 275 break; |
| 276 case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit |
| 277 if (id == CSSValueNone) |
| 278 validPrimitive = true; |
| 279 else |
| 280 parsedValue = parseSVGStrokeDasharray(); |
| 281 |
| 282 break; |
| 283 |
| 284 case CSSPropertyKerning: // auto | normal | <length> | inherit |
| 285 if (id == CSSValueAuto || id == CSSValueNormal) |
| 286 validPrimitive = true; |
| 287 else |
| 288 validPrimitive = validUnit(value, FLength, SVGAttributeMode); |
| 289 break; |
| 290 |
| 291 case CSSPropertyClipPath: // <uri> | none | inherit |
| 292 case CSSPropertyFilter: |
| 293 if (id == CSSValueNone) { |
| 294 validPrimitive = true; |
| 295 } else if (value->unit == CSSPrimitiveValue::CSS_URI) { |
| 296 parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitive
Value::UnitTypes) value->unit); |
| 297 if (parsedValue) |
| 298 m_valueList->next(); |
| 299 } |
| 300 break; |
| 301 case CSSPropertyMaskType: // luminance | alpha | inherit |
| 302 if (id == CSSValueLuminance || id == CSSValueAlpha) |
| 303 validPrimitive = true; |
| 304 break; |
| 305 |
| 306 /* shorthand properties */ |
| 307 case CSSPropertyMarker: { |
| 308 ShorthandScope scope(this, propId); |
| 309 CSSPropertyParser::ImplicitScope implicitScope(this, PropertyImplicit); |
| 310 if (!parseValue(CSSPropertyMarkerStart, important)) |
| 311 return false; |
| 312 if (m_valueList->current()) { |
| 313 rollbackLastProperties(1); |
| 314 return false; |
| 315 } |
| 316 CSSValue* value = m_parsedProperties.last().value(); |
| 317 addProperty(CSSPropertyMarkerMid, value, important); |
| 318 addProperty(CSSPropertyMarkerEnd, value, important); |
| 319 return true; |
| 320 } |
| 321 default: |
| 322 // If you crash here, it's because you added a css property and are not
handling it |
| 323 // in either this switch statement or the one in CSSPropertyParser::pars
eValue |
| 324 ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); |
| 325 return false; |
| 326 } |
| 327 |
| 328 if (validPrimitive) { |
| 329 if (id) |
| 330 parsedValue = CSSPrimitiveValue::createIdentifier(id); |
| 331 else if (value->unit == CSSPrimitiveValue::CSS_STRING) |
| 332 parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitive
Value::UnitTypes) value->unit); |
| 333 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <=
CSSPrimitiveValue::CSS_KHZ) |
| 334 parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitive
Value::UnitTypes) value->unit); |
| 335 else if (value->unit >= CSSParserValue::Q_EMS) |
| 336 parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fV
alue, CSSPrimitiveValue::CSS_EMS); |
| 337 if (isCalculation(value)) { |
| 338 // FIXME calc() http://webkit.org/b/16662 : actually create a CSSPri
mitiveValue here, ie |
| 339 // parsedValue = CSSPrimitiveValue::create(m_parsedCalculation.relea
se()); |
| 340 m_parsedCalculation.release(); |
| 341 parsedValue = nullptr; |
| 342 } |
| 343 m_valueList->next(); |
| 344 } |
| 345 if (!parsedValue || (m_valueList->current() && !inShorthand())) |
| 346 return false; |
| 347 |
| 348 addProperty(propId, parsedValue.release(), important); |
| 349 return true; |
| 350 } |
| 351 |
| 352 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGStrokeDasharray() |
| 353 { |
| 354 RefPtrWillBeRawPtr<CSSValueList> ret = CSSValueList::createCommaSeparated(); |
| 355 CSSParserValue* value = m_valueList->current(); |
| 356 bool validPrimitive = true; |
| 357 while (value) { |
| 358 validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, SVGAttri
buteMode); |
| 359 if (!validPrimitive) |
| 360 break; |
| 361 if (value->id) |
| 362 ret->append(CSSPrimitiveValue::createIdentifier(value->id)); |
| 363 else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <=
CSSPrimitiveValue::CSS_KHZ) |
| 364 ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveVa
lue::UnitTypes) value->unit)); |
| 365 value = m_valueList->next(); |
| 366 if (value && value->unit == CSSParserValue::Operator && value->iValue ==
',') |
| 367 value = m_valueList->next(); |
| 368 } |
| 369 if (!validPrimitive) |
| 370 return nullptr; |
| 371 return ret.release(); |
| 372 } |
| 373 |
| 374 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGPaint() |
| 375 { |
| 376 RGBA32 c = Color::transparent; |
| 377 if (!parseColorFromValue(m_valueList->current(), c)) |
| 378 return SVGPaint::createUnknown(); |
| 379 return SVGPaint::createColor(Color(c)); |
| 380 } |
| 381 |
| 382 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGColor() |
| 383 { |
| 384 RGBA32 c = Color::transparent; |
| 385 if (!parseColorFromValue(m_valueList->current(), c)) |
| 386 return nullptr; |
| 387 return SVGColor::createFromColor(Color(c)); |
| 388 } |
| 389 |
| 390 // normal | [ fill || stroke || markers ] |
| 391 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parsePaintOrder() const |
| 392 { |
| 393 if (m_valueList->size() > 3) |
| 394 return nullptr; |
| 395 |
| 396 CSSParserValue* value = m_valueList->current(); |
| 397 if (!value) |
| 398 return nullptr; |
| 399 |
| 400 RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSep
arated(); |
| 401 |
| 402 // The default paint-order is: Fill, Stroke, Markers. |
| 403 bool seenFill = false, seenStroke = false, seenMarkers = false; |
| 404 |
| 405 do { |
| 406 switch (value->id) { |
| 407 case CSSValueNormal: |
| 408 // normal inside [fill || stroke || markers] not valid |
| 409 return nullptr; |
| 410 case CSSValueFill: |
| 411 if (seenFill) |
| 412 return nullptr; |
| 413 |
| 414 seenFill = true; |
| 415 break; |
| 416 case CSSValueStroke: |
| 417 if (seenStroke) |
| 418 return nullptr; |
| 419 |
| 420 seenStroke = true; |
| 421 break; |
| 422 case CSSValueMarkers: |
| 423 if (seenMarkers) |
| 424 return nullptr; |
| 425 |
| 426 seenMarkers = true; |
| 427 break; |
| 428 default: |
| 429 return nullptr; |
| 430 } |
| 431 |
| 432 parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); |
| 433 } while ((value = m_valueList->next())); |
| 434 |
| 435 // fill out the rest of the paint order |
| 436 if (!seenFill) |
| 437 parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueFill)); |
| 438 if (!seenStroke) |
| 439 parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke)
); |
| 440 if (!seenMarkers) |
| 441 parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers
)); |
| 442 |
| 443 return parsedValues.release(); |
| 444 } |
| 445 |
51 } // namespace WebCore | 446 } // namespace WebCore |
OLD | NEW |