| Index: third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp | 
| diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp | 
| index 5774399e232491a1d0095b3ba8f4f89fa9240981..7091dc6f1d12df160dd619817674d9ce0530ab45 100644 | 
| --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp | 
| +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp | 
| @@ -358,6 +358,134 @@ static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange | 
| return nullptr; | 
| } | 
|  | 
| +static int clampRGBComponent(const CSSPrimitiveValue& value) | 
| +{ | 
| +    double result = value.getDoubleValue(); | 
| +    // TODO(timloh): Multiply by 2.55 and round instead of floor. | 
| +    if (value.isPercentage()) | 
| +        result *= 2.56; | 
| +    return clampTo<int>(result, 0, 255); | 
| +} | 
| + | 
| +static bool parseRGBParameters(CSSParserTokenRange& range, RGBA32& result, bool parseAlpha) | 
| +{ | 
| +    ASSERT(range.peek().functionId() == CSSValueRgb || range.peek().functionId() == CSSValueRgba); | 
| +    CSSParserTokenRange args = consumeFunction(range); | 
| +    RefPtrWillBeRawPtr<CSSPrimitiveValue> colorParameter = consumeInteger(args); | 
| +    if (!colorParameter) | 
| +        colorParameter = consumePercent(args, ValueRangeAll); | 
| +    if (!colorParameter) | 
| +        return false; | 
| +    const bool isPercent = colorParameter->isPercentage(); | 
| +    int colorArray[3]; | 
| +    colorArray[0] = clampRGBComponent(*colorParameter); | 
| +    for (int i = 1; i < 3; i++) { | 
| +        if (!consumeCommaIncludingWhitespace(args)) | 
| +            return false; | 
| +        colorParameter = isPercent ? consumePercent(args, ValueRangeAll) : consumeInteger(args); | 
| +        if (!colorParameter) | 
| +            return false; | 
| +        colorArray[i] = clampRGBComponent(*colorParameter); | 
| +    } | 
| +    if (parseAlpha) { | 
| +        if (!consumeCommaIncludingWhitespace(args)) | 
| +            return false; | 
| +        double alpha; | 
| +        if (!consumeNumberRaw(args, alpha)) | 
| +            return false; | 
| +        // Convert the floating pointer number of alpha to an integer in the range [0, 256), | 
| +        // with an equal distribution across all 256 values. | 
| +        int alphaComponent = static_cast<int>(clampTo<double>(alpha, 0.0, 1.0) * nextafter(256.0, 0.0)); | 
| +        result = makeRGBA(colorArray[0], colorArray[1], colorArray[2], alphaComponent); | 
| +    } else { | 
| +        result = makeRGB(colorArray[0], colorArray[1], colorArray[2]); | 
| +    } | 
| +    return args.atEnd(); | 
| +} | 
| + | 
| +static bool parseHSLParameters(CSSParserTokenRange& range, RGBA32& result, bool parseAlpha) | 
| +{ | 
| +    ASSERT(range.peek().functionId() == CSSValueHsl || range.peek().functionId() == CSSValueHsla); | 
| +    CSSParserTokenRange args = consumeFunction(range); | 
| +    RefPtrWillBeRawPtr<CSSPrimitiveValue> hslValue = consumeNumber(args, ValueRangeAll); | 
| +    if (!hslValue) | 
| +        return false; | 
| +    double colorArray[3]; | 
| +    colorArray[0] = (((hslValue->getIntValue() % 360) + 360) % 360) / 360.0; | 
| +    for (int i = 1; i < 3; i++) { | 
| +        if (!consumeCommaIncludingWhitespace(args)) | 
| +            return false; | 
| +        hslValue = consumePercent(args, ValueRangeAll); | 
| +        if (!hslValue) | 
| +            return false; | 
| +        double doubleValue = hslValue->getDoubleValue(); | 
| +        colorArray[i] = clampTo<double>(doubleValue, 0.0, 100.0) / 100.0; // Needs to be value between 0 and 1.0. | 
| +    } | 
| +    double alpha = 1.0; | 
| +    if (parseAlpha) { | 
| +        if (!consumeCommaIncludingWhitespace(args)) | 
| +            return false; | 
| +        if (!consumeNumberRaw(args, alpha)) | 
| +            return false; | 
| +        alpha = clampTo<double>(alpha, 0.0, 1.0); | 
| +    } | 
| +    result = makeRGBAFromHSLA(colorArray[0], colorArray[1], colorArray[2], alpha); | 
| +    return args.atEnd(); | 
| +} | 
| + | 
| +static bool parseHexColor(CSSParserTokenRange& range, RGBA32& result, bool acceptQuirkyColors) | 
| +{ | 
| +    const CSSParserToken& token = range.peek(); | 
| +    String color; | 
| +    if (acceptQuirkyColors) { | 
| +        if (token.type() == NumberToken && token.numericValueType() == IntegerValueType | 
| +            && token.numericValue() >= 0. && token.numericValue() < 1000000.) { // e.g. 112233 | 
| +            color = String::format("%06d", static_cast<int>(token.numericValue())); | 
| +        } else if (token.type() == DimensionToken) { // e.g. 0001FF | 
| +            color = String::number(static_cast<int>(token.numericValue())) + String(token.value()); | 
| +            if (color.length() > 6) | 
| +                return false; | 
| +            while (color.length() < 6) | 
| +                color = "0" + color; | 
| +        } else if (token.type() == IdentToken) { // e.g. FF0000 | 
| +            color = token.value(); | 
| +        } | 
| +    } | 
| +    if (token.type() == HashToken) | 
| +        color = token.value(); | 
| +    if (!Color::parseHexColor(color, result)) | 
| +        return false; | 
| +    range.consumeIncludingWhitespace(); | 
| +    return true; | 
| +} | 
| + | 
| +static bool parseColorFunction(CSSParserTokenRange& range, RGBA32& result) | 
| +{ | 
| +    CSSValueID functionId = range.peek().functionId(); | 
| +    if (functionId < CSSValueRgb || functionId > CSSValueHsla) | 
| +        return false; | 
| +    CSSParserTokenRange colorRange = range; | 
| +    if ((functionId <= CSSValueRgba && !parseRGBParameters(colorRange, result, functionId == CSSValueRgba)) | 
| +        || (functionId >= CSSValueHsl && !parseHSLParameters(colorRange, result, functionId == CSSValueHsla))) | 
| +        return false; | 
| +    range = colorRange; | 
| +    return true; | 
| +} | 
| + | 
| +static PassRefPtrWillBeRawPtr<CSSValue> consumeColor(CSSParserTokenRange& range, const CSSParserContext& context, bool acceptQuirkyColors = false) | 
| +{ | 
| +    CSSValueID id = range.peek().id(); | 
| +    if (CSSPropertyParser::isColorKeyword(id)) { | 
| +        if (!isValueAllowedInMode(id, context.mode())) | 
| +            return nullptr; | 
| +        return consumeIdent(range); | 
| +    } | 
| +    RGBA32 color = Color::transparent; | 
| +    if (!parseHexColor(range, color, acceptQuirkyColors) && !parseColorFunction(range, color)) | 
| +        return nullptr; | 
| +    return cssValuePool().createColorValue(color); | 
| +} | 
| + | 
| static inline bool isCSSWideKeyword(const CSSValueID& id) | 
| { | 
| return id == CSSValueInitial || id == CSSValueInherit || id == CSSValueUnset || id == CSSValueDefault; | 
| @@ -1301,6 +1429,11 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty | 
| case CSSPropertyOrphans: | 
| case CSSPropertyWidows: | 
| return consumeWidowsOrOrphans(m_range); | 
| +    case CSSPropertyWebkitTextFillColor: | 
| +    case CSSPropertyWebkitTapHighlightColor: | 
| +        return consumeColor(m_range, m_context); | 
| +    case CSSPropertyColor: | 
| +        return consumeColor(m_range, m_context, inQuirksMode()); | 
| default: | 
| return nullptr; | 
| } | 
|  |