Commit f84c000f authored by Rune Lillesveen's avatar Rune Lillesveen Committed by Commit Bot

Filter highlight pseudo element properties.

The css-pseudo specification lists which properties applies to which
pseudo elements. For ::marker and ::first-letter we were already using
the CascadeFilter. This CL uses the filter for highlight pseudo elements
like ::selection and ::target-text, which share the same set of
properties which apply.

This means we stop retrieving resources for CSS properties which don't
apply to these pseudo elements. Additionally, block all resource
fetching for the ::target-text element since resource fetching can be
used by an external stylesheet in combination with a text fragment url
to detect text content on a page.

Bug: 1136817
Change-Id: I8b19db8535882e6b20f6319cd2a9f5219e7c9538
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2489657
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Reviewed-by: default avatarAnders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821283}
parent ec6be3dd
...@@ -37,6 +37,8 @@ def validate_property(prop): ...@@ -37,6 +37,8 @@ def validate_property(prop):
'Only longhands can be valid_for_cue [%s]' % name 'Only longhands can be valid_for_cue [%s]' % name
assert not prop['valid_for_marker'] or prop['is_longhand'], \ assert not prop['valid_for_marker'] or prop['is_longhand'], \
'Only longhands can be valid_for_marker [%s]' % name 'Only longhands can be valid_for_marker [%s]' % name
assert not prop['valid_for_highlight'] or prop['is_longhand'], \
'Only longhands can be valid_for_highlight [%s]' % name
def validate_alias(alias): def validate_alias(alias):
......
...@@ -51,6 +51,7 @@ namespace {{namespace}} { ...@@ -51,6 +51,7 @@ namespace {{namespace}} {
(property.is_border and 'kBorder' or ''), (property.is_border and 'kBorder' or ''),
(property.computed_value_comparable and 'kComputedValueComparable' or ''), (property.computed_value_comparable and 'kComputedValueComparable' or ''),
(property.tree_scoped_value and 'kTreeScopedValue' or ''), (property.tree_scoped_value and 'kTreeScopedValue' or ''),
(property.valid_for_highlight and 'kValidForHighlight' or ''),
] | reject('==', '') | join(' | ') %} ] | reject('==', '') | join(' | ') %}
{% set ctor_args = (not is_alias and [property_id, flags, separator] or []) %} {% set ctor_args = (not is_alias and [property_id, flags, separator] or []) %}
// {{property.name}} // {{property.name}}
......
...@@ -479,6 +479,14 @@ ...@@ -479,6 +479,14 @@
valid_type: "bool", valid_type: "bool",
}, },
// - valid_for_highlight: true
//
// https://drafts.csswg.org/css-pseudo-4/#highlight-styling
valid_for_highlight: {
default: false,
valid_type: "bool",
},
// - is_border // - is_border
// The property, when used by the author, will disable any native // The property, when used by the author, will disable any native
// appearance on UI elements. // appearance on UI elements.
...@@ -714,6 +722,7 @@ ...@@ -714,6 +722,7 @@
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_marker: true, valid_for_marker: true,
valid_for_highlight: true,
}, },
{ {
name: "direction", name: "direction",
...@@ -969,6 +978,7 @@ ...@@ -969,6 +978,7 @@
keywords: ["auto", "none"], keywords: ["auto", "none"],
typedom_types: ["Keyword"], typedom_types: ["Keyword"],
default_value: "auto", default_value: "auto",
valid_for_highlight: true,
}, },
{ {
name: "-webkit-locale", name: "-webkit-locale",
...@@ -1201,6 +1211,7 @@ ...@@ -1201,6 +1211,7 @@
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_highlight: true,
is_background: true, is_background: true,
}, },
{ {
...@@ -1742,6 +1753,7 @@ ...@@ -1742,6 +1753,7 @@
style_builder_custom_functions: ["initial", "inherit", "value"], style_builder_custom_functions: ["initial", "inherit", "value"],
keywords: ["auto", "currentcolor"], keywords: ["auto", "currentcolor"],
typedom_types: ["Keyword"], typedom_types: ["Keyword"],
valid_for_highlight: true,
}, },
{ {
name: "clear", name: "clear",
...@@ -1823,6 +1835,7 @@ ...@@ -1823,6 +1835,7 @@
type_name: "Vector<AtomicString>", type_name: "Vector<AtomicString>",
default_value: "Vector<AtomicString, 0>()", default_value: "Vector<AtomicString, 0>()",
field_template: "external", field_template: "external",
valid_for_highlight: true,
}, },
{ {
name: "column-fill", name: "column-fill",
...@@ -1919,7 +1932,8 @@ ...@@ -1919,7 +1932,8 @@
], ],
default_value: "auto", default_value: "auto",
style_builder_custom_functions: ["initial", "inherit", "value"], style_builder_custom_functions: ["initial", "inherit", "value"],
typedom_types: ["Keyword"] typedom_types: ["Keyword"],
valid_for_highlight: true,
}, },
{ {
name: "cx", name: "cx",
...@@ -1988,6 +2002,7 @@ ...@@ -1988,6 +2002,7 @@
getter: "FillPaint", getter: "FillPaint",
converter: "ConvertSVGPaint", converter: "ConvertSVGPaint",
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_highlight: true,
}, },
{ {
name: "fill-opacity", name: "fill-opacity",
...@@ -3474,6 +3489,7 @@ ...@@ -3474,6 +3489,7 @@
getter: "StrokePaint", getter: "StrokePaint",
converter: "ConvertSVGPaint", converter: "ConvertSVGPaint",
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_highlight: true,
}, },
{ {
name: "stroke-dasharray", name: "stroke-dasharray",
...@@ -3542,7 +3558,8 @@ ...@@ -3542,7 +3558,8 @@
inherited: true, inherited: true,
svg: true, svg: true,
converter: "ConvertUnzoomedLength", converter: "ConvertUnzoomedLength",
typedom_types: ["Length", "Percentage"] typedom_types: ["Length", "Percentage"],
valid_for_highlight: true,
}, },
{ {
name: "table-layout", name: "table-layout",
...@@ -3632,6 +3649,7 @@ ...@@ -3632,6 +3649,7 @@
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_highlight: true,
computed_value_comparable: true, computed_value_comparable: true,
}, },
{ {
...@@ -3647,6 +3665,7 @@ ...@@ -3647,6 +3665,7 @@
converter: "ConvertFlags<TextDecoration>", converter: "ConvertFlags<TextDecoration>",
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_highlight: true,
computed_value_comparable: true, computed_value_comparable: true,
}, },
{ {
...@@ -3661,6 +3680,7 @@ ...@@ -3661,6 +3680,7 @@
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_marker: true, valid_for_marker: true,
valid_for_highlight: true,
computed_value_comparable: true, computed_value_comparable: true,
}, },
{ {
...@@ -3673,6 +3693,7 @@ ...@@ -3673,6 +3693,7 @@
default_value: "solid", default_value: "solid",
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_highlight: true,
computed_value_comparable: true, computed_value_comparable: true,
}, },
{ {
...@@ -3689,6 +3710,7 @@ ...@@ -3689,6 +3710,7 @@
keywords: ["auto", "from-font"], keywords: ["auto", "from-font"],
typedom_types: ["Keyword", "Length", "Percentage"], typedom_types: ["Keyword", "Length", "Percentage"],
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_highlight: true,
computed_value_comparable: true, computed_value_comparable: true,
}, },
{ {
...@@ -3744,6 +3766,7 @@ ...@@ -3744,6 +3766,7 @@
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_marker: true, valid_for_marker: true,
valid_for_highlight: true,
}, },
{ {
name: "text-size-adjust", name: "text-size-adjust",
...@@ -4461,6 +4484,7 @@ ...@@ -4461,6 +4484,7 @@
style_builder_template: "color", style_builder_template: "color",
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_marker: true, valid_for_marker: true,
valid_for_highlight: true,
}, },
{ {
name: "-webkit-text-emphasis-position", name: "-webkit-text-emphasis-position",
...@@ -4493,6 +4517,7 @@ ...@@ -4493,6 +4517,7 @@
computed_style_custom_functions: ["getter"], computed_style_custom_functions: ["getter"],
converter: "ConvertStyleColor", converter: "ConvertStyleColor",
style_builder_template: "color", style_builder_template: "color",
valid_for_highlight: true,
}, },
{ {
name: "-webkit-text-security", name: "-webkit-text-security",
...@@ -4516,6 +4541,7 @@ ...@@ -4516,6 +4541,7 @@
computed_style_custom_functions: ["getter"], computed_style_custom_functions: ["getter"],
converter: "ConvertStyleColor", converter: "ConvertStyleColor",
style_builder_template: "color", style_builder_template: "color",
valid_for_highlight: true,
}, },
{ {
name: "-webkit-text-stroke-width", name: "-webkit-text-stroke-width",
...@@ -4526,6 +4552,7 @@ ...@@ -4526,6 +4552,7 @@
default_value: "0", default_value: "0",
type_name: "float", type_name: "float",
converter: "ConvertTextStrokeWidth", converter: "ConvertTextStrokeWidth",
valid_for_highlight: true,
}, },
{ {
name: "-webkit-transform-origin-x", name: "-webkit-transform-origin-x",
...@@ -5744,6 +5771,7 @@ ...@@ -5744,6 +5771,7 @@
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_marker: true, valid_for_marker: true,
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-caret-color", name: "-internal-visited-caret-color",
...@@ -5761,6 +5789,7 @@ ...@@ -5761,6 +5789,7 @@
style_builder_template_args: { style_builder_template_args: {
initial_color: "StyleAutoColor::AutoColor", initial_color: "StyleAutoColor::AutoColor",
}, },
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-column-rule-color", name: "-internal-visited-column-rule-color",
...@@ -5794,6 +5823,7 @@ ...@@ -5794,6 +5823,7 @@
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-border-left-color", name: "-internal-visited-border-left-color",
...@@ -5906,6 +5936,7 @@ ...@@ -5906,6 +5936,7 @@
getter: "FillPaint", getter: "FillPaint",
converter: "ConvertSVGPaint", converter: "ConvertSVGPaint",
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-outline-color", name: "-internal-visited-outline-color",
...@@ -5933,6 +5964,7 @@ ...@@ -5933,6 +5964,7 @@
getter: "StrokePaint", getter: "StrokePaint",
converter: "ConvertSVGPaint", converter: "ConvertSVGPaint",
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-text-decoration-color", name: "-internal-visited-text-decoration-color",
...@@ -5949,6 +5981,7 @@ ...@@ -5949,6 +5981,7 @@
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_first_letter: true, valid_for_first_letter: true,
valid_for_cue: true, valid_for_cue: true,
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-text-emphasis-color", name: "-internal-visited-text-emphasis-color",
...@@ -5964,6 +5997,7 @@ ...@@ -5964,6 +5997,7 @@
converter: "ConvertStyleColor", converter: "ConvertStyleColor",
style_builder_template: "visited_color", style_builder_template: "visited_color",
affected_by_forced_colors: true, affected_by_forced_colors: true,
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-text-fill-color", name: "-internal-visited-text-fill-color",
...@@ -5978,6 +6012,7 @@ ...@@ -5978,6 +6012,7 @@
computed_style_custom_functions: ["getter", "setter"], computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertStyleColor", converter: "ConvertStyleColor",
style_builder_template: "visited_color", style_builder_template: "visited_color",
valid_for_highlight: true,
}, },
{ {
name: "-internal-visited-text-stroke-color", name: "-internal-visited-text-stroke-color",
...@@ -5992,6 +6027,7 @@ ...@@ -5992,6 +6027,7 @@
computed_style_custom_functions: ["getter", "setter"], computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertStyleColor", converter: "ConvertStyleColor",
style_builder_template: "visited_color", style_builder_template: "visited_color",
valid_for_highlight: true,
}, },
// Name: -internal-empty-line-height: // Name: -internal-empty-line-height:
......
...@@ -56,6 +56,7 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty { ...@@ -56,6 +56,7 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
bool IsValidForFirstLetter() const { return flags_ & kValidForFirstLetter; } bool IsValidForFirstLetter() const { return flags_ & kValidForFirstLetter; }
bool IsValidForCue() const { return flags_ & kValidForCue; } bool IsValidForCue() const { return flags_ & kValidForCue; }
bool IsValidForMarker() const { return flags_ & kValidForMarker; } bool IsValidForMarker() const { return flags_ & kValidForMarker; }
bool IsValidForHighlight() const { return flags_ & kValidForHighlight; }
bool IsSurrogate() const { return flags_ & kSurrogate; } bool IsSurrogate() const { return flags_ & kSurrogate; }
bool AffectsFont() const { return flags_ & kAffectsFont; } bool AffectsFont() const { return flags_ & kAffectsFont; }
bool IsBackground() const { return flags_ & kBackground; } bool IsBackground() const { return flags_ & kBackground; }
...@@ -152,6 +153,8 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty { ...@@ -152,6 +153,8 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
kComputedValueComparable = 1 << 18, kComputedValueComparable = 1 << 18,
// Set if the property values are tree-scoped references. // Set if the property values are tree-scoped references.
kTreeScopedValue = 1 << 19, kTreeScopedValue = 1 << 19,
// https://drafts.csswg.org/css-pseudo-4/#highlight-styling
kValidForHighlight = 1 << 20,
}; };
constexpr CSSProperty(CSSPropertyID property_id, constexpr CSSProperty(CSSPropertyID property_id,
......
...@@ -35,7 +35,8 @@ class CORE_EXPORT Variable : public Longhand { ...@@ -35,7 +35,8 @@ class CORE_EXPORT Variable : public Longhand {
protected: protected:
explicit constexpr Variable(CSSProperty::Flags flags) explicit constexpr Variable(CSSProperty::Flags flags)
: Longhand(CSSPropertyID::kVariable, : Longhand(CSSPropertyID::kVariable,
kProperty | kValidForFirstLetter | kValidForMarker | flags, kProperty | kValidForFirstLetter | kValidForMarker |
kValidForHighlight | flags,
'\0') {} '\0') {}
}; };
......
...@@ -24,6 +24,8 @@ CascadeFilter AddValidPropertiesFilter( ...@@ -24,6 +24,8 @@ CascadeFilter AddValidPropertiesFilter(
return filter.Add(CSSProperty::kValidForFirstLetter, false); return filter.Add(CSSProperty::kValidForFirstLetter, false);
case ValidPropertyFilter::kMarker: case ValidPropertyFilter::kMarker:
return filter.Add(CSSProperty::kValidForMarker, false); return filter.Add(CSSProperty::kValidForMarker, false);
case ValidPropertyFilter::kHighlight:
return filter.Add(CSSProperty::kValidForHighlight, false);
} }
} }
......
...@@ -453,6 +453,25 @@ TEST_F(CascadeExpansionTest, FilterMarker) { ...@@ -453,6 +453,25 @@ TEST_F(CascadeExpansionTest, FilterMarker) {
EXPECT_TRUE(e.AtEnd()); EXPECT_TRUE(e.AtEnd());
} }
TEST_F(CascadeExpansionTest, FilterHighlight) {
MatchResult result;
result.FinishAddingUARules();
result.FinishAddingUserRules();
result.AddMatchedProperties(
ParseDeclarationBlock("display:block;background-color:lime;"),
CSSSelector::kMatchAll, ValidPropertyFilter::kHighlight);
result.FinishAddingAuthorRulesForTreeScope(GetDocument());
auto e = ExpansionAt(result, 0);
ASSERT_FALSE(e.AtEnd());
EXPECT_EQ(CSSPropertyID::kBackgroundColor, e.Id());
e.Next();
ASSERT_FALSE(e.AtEnd());
EXPECT_EQ(CSSPropertyID::kInternalVisitedBackgroundColor, e.Id());
e.Next();
EXPECT_TRUE(e.AtEnd());
}
TEST_F(CascadeExpansionTest, FilterAllNonInherited) { TEST_F(CascadeExpansionTest, FilterAllNonInherited) {
MatchResult result; MatchResult result;
result.FinishAddingUARules(); result.FinishAddingUARules();
......
...@@ -120,12 +120,11 @@ SVGResource* ElementStyleResources::GetSVGResourceFromValue( ...@@ -120,12 +120,11 @@ SVGResource* ElementStyleResources::GetSVGResourceFromValue(
return nullptr; return nullptr;
} }
void ElementStyleResources::LoadPendingSVGResources( void ElementStyleResources::LoadPendingSVGResources(ComputedStyle& style) {
ComputedStyle* computed_style) { if (!style.HasFilter())
if (!computed_style->HasFilter())
return; return;
FilterOperations::FilterOperationVector& filter_operations = FilterOperations::FilterOperationVector& filter_operations =
computed_style->MutableFilter().Operations(); style.MutableFilter().Operations();
for (const auto& filter_operation : filter_operations) { for (const auto& filter_operation : filter_operations) {
auto* reference_operation = auto* reference_operation =
DynamicTo<ReferenceFilterOperation>(filter_operation.Get()); DynamicTo<ReferenceFilterOperation>(filter_operation.Get());
...@@ -147,7 +146,7 @@ static bool BackgroundLayerMayBeSprite(const FillLayer& background_layer) { ...@@ -147,7 +146,7 @@ static bool BackgroundLayerMayBeSprite(const FillLayer& background_layer) {
} }
StyleImage* ElementStyleResources::LoadPendingImage( StyleImage* ElementStyleResources::LoadPendingImage(
ComputedStyle* style, ComputedStyle& style,
StylePendingImage* pending_image, StylePendingImage* pending_image,
FetchParameters::ImageRequestBehavior image_request_behavior, FetchParameters::ImageRequestBehavior image_request_behavior,
CrossOriginAttributeValue cross_origin) { CrossOriginAttributeValue cross_origin) {
...@@ -158,7 +157,7 @@ StyleImage* ElementStyleResources::LoadPendingImage( ...@@ -158,7 +157,7 @@ StyleImage* ElementStyleResources::LoadPendingImage(
if (CSSPaintValue* paint_value = pending_image->CssPaintValue()) { if (CSSPaintValue* paint_value = pending_image->CssPaintValue()) {
auto* image = MakeGarbageCollected<StyleGeneratedImage>(*paint_value); auto* image = MakeGarbageCollected<StyleGeneratedImage>(*paint_value);
style->AddPaintImage(image); style.AddPaintImage(image);
return image; return image;
} }
...@@ -178,7 +177,7 @@ StyleImage* ElementStyleResources::LoadPendingImage( ...@@ -178,7 +177,7 @@ StyleImage* ElementStyleResources::LoadPendingImage(
return nullptr; return nullptr;
} }
void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { void ElementStyleResources::LoadPendingImages(ComputedStyle& style) {
// We must loop over the properties and then look at the style to see if // We must loop over the properties and then look at the style to see if
// a pending image exists, and only load that image. For example: // a pending image exists, and only load that image. For example:
// //
...@@ -200,7 +199,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -200,7 +199,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
for (CSSPropertyID property : pending_image_properties_) { for (CSSPropertyID property : pending_image_properties_) {
switch (property) { switch (property) {
case CSSPropertyID::kBackgroundImage: { case CSSPropertyID::kBackgroundImage: {
for (FillLayer* background_layer = &style->AccessBackgroundLayers(); for (FillLayer* background_layer = &style.AccessBackgroundLayers();
background_layer; background_layer = background_layer->Next()) { background_layer; background_layer = background_layer->Next()) {
StyleImage* background_image = background_layer->GetImage(); StyleImage* background_image = background_layer->GetImage();
if (background_image && background_image->IsPendingImage()) { if (background_image && background_image->IsPendingImage()) {
...@@ -228,7 +227,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -228,7 +227,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
} }
case CSSPropertyID::kContent: { case CSSPropertyID::kContent: {
for (ContentData* content_data = for (ContentData* content_data =
const_cast<ContentData*>(style->GetContentData()); const_cast<ContentData*>(style.GetContentData());
content_data; content_data = content_data->Next()) { content_data; content_data = content_data->Next()) {
if (content_data->IsImage()) { if (content_data->IsImage()) {
StyleImage* image = To<ImageContentData>(content_data)->GetImage(); StyleImage* image = To<ImageContentData>(content_data)->GetImage();
...@@ -243,7 +242,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -243,7 +242,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
break; break;
} }
case CSSPropertyID::kCursor: { case CSSPropertyID::kCursor: {
if (CursorList* cursor_list = style->Cursors()) { if (CursorList* cursor_list = style.Cursors()) {
for (wtf_size_t i = 0; i < cursor_list->size(); ++i) { for (wtf_size_t i = 0; i < cursor_list->size(); ++i) {
CursorData& current_cursor = cursor_list->at(i); CursorData& current_cursor = cursor_list->at(i);
if (StyleImage* image = current_cursor.GetImage()) { if (StyleImage* image = current_cursor.GetImage()) {
...@@ -258,25 +257,25 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -258,25 +257,25 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
break; break;
} }
case CSSPropertyID::kListStyleImage: { case CSSPropertyID::kListStyleImage: {
if (style->ListStyleImage() && if (style.ListStyleImage() &&
style->ListStyleImage()->IsPendingImage()) { style.ListStyleImage()->IsPendingImage()) {
style->SetListStyleImage(LoadPendingImage( style.SetListStyleImage(LoadPendingImage(
style, To<StylePendingImage>(style->ListStyleImage()), style, To<StylePendingImage>(style.ListStyleImage()),
FetchParameters::kNone)); FetchParameters::kNone));
} }
break; break;
} }
case CSSPropertyID::kBorderImageSource: { case CSSPropertyID::kBorderImageSource: {
if (style->BorderImageSource() && if (style.BorderImageSource() &&
style->BorderImageSource()->IsPendingImage()) { style.BorderImageSource()->IsPendingImage()) {
style->SetBorderImageSource(LoadPendingImage( style.SetBorderImageSource(LoadPendingImage(
style, To<StylePendingImage>(style->BorderImageSource()), style, To<StylePendingImage>(style.BorderImageSource()),
FetchParameters::kNone)); FetchParameters::kNone));
} }
break; break;
} }
case CSSPropertyID::kWebkitBoxReflect: { case CSSPropertyID::kWebkitBoxReflect: {
if (StyleReflection* reflection = style->BoxReflect()) { if (StyleReflection* reflection = style.BoxReflect()) {
const NinePieceImage& mask_image = reflection->Mask(); const NinePieceImage& mask_image = reflection->Mask();
if (mask_image.GetImage() && if (mask_image.GetImage() &&
mask_image.GetImage()->IsPendingImage()) { mask_image.GetImage()->IsPendingImage()) {
...@@ -292,16 +291,16 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -292,16 +291,16 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
break; break;
} }
case CSSPropertyID::kWebkitMaskBoxImageSource: { case CSSPropertyID::kWebkitMaskBoxImageSource: {
if (style->MaskBoxImageSource() && if (style.MaskBoxImageSource() &&
style->MaskBoxImageSource()->IsPendingImage()) { style.MaskBoxImageSource()->IsPendingImage()) {
style->SetMaskBoxImageSource(LoadPendingImage( style.SetMaskBoxImageSource(LoadPendingImage(
style, To<StylePendingImage>(style->MaskBoxImageSource()), style, To<StylePendingImage>(style.MaskBoxImageSource()),
FetchParameters::kNone)); FetchParameters::kNone));
} }
break; break;
} }
case CSSPropertyID::kWebkitMaskImage: { case CSSPropertyID::kWebkitMaskImage: {
for (FillLayer* mask_layer = &style->AccessMaskLayers(); mask_layer; for (FillLayer* mask_layer = &style.AccessMaskLayers(); mask_layer;
mask_layer = mask_layer->Next()) { mask_layer = mask_layer->Next()) {
if (mask_layer->GetImage() && if (mask_layer->GetImage() &&
mask_layer->GetImage()->IsPendingImage()) { mask_layer->GetImage()->IsPendingImage()) {
...@@ -313,10 +312,10 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -313,10 +312,10 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
break; break;
} }
case CSSPropertyID::kShapeOutside: case CSSPropertyID::kShapeOutside:
if (style->ShapeOutside() && style->ShapeOutside()->GetImage() && if (style.ShapeOutside() && style.ShapeOutside()->GetImage() &&
style->ShapeOutside()->GetImage()->IsPendingImage()) { style.ShapeOutside()->GetImage()->IsPendingImage()) {
style->ShapeOutside()->SetImage(LoadPendingImage( style.ShapeOutside()->SetImage(LoadPendingImage(
style, To<StylePendingImage>(style->ShapeOutside()->GetImage()), style, To<StylePendingImage>(style.ShapeOutside()->GetImage()),
FetchParameters::kNone, kCrossOriginAttributeAnonymous)); FetchParameters::kNone, kCrossOriginAttributeAnonymous));
} }
break; break;
...@@ -327,7 +326,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) { ...@@ -327,7 +326,7 @@ void ElementStyleResources::LoadPendingImages(ComputedStyle* style) {
} }
void ElementStyleResources::LoadPendingResources( void ElementStyleResources::LoadPendingResources(
ComputedStyle* computed_style) { ComputedStyle& computed_style) {
LoadPendingImages(computed_style); LoadPendingImages(computed_style);
LoadPendingSVGResources(computed_style); LoadPendingSVGResources(computed_style);
} }
......
...@@ -74,17 +74,17 @@ class ElementStyleResources { ...@@ -74,17 +74,17 @@ class ElementStyleResources {
const cssvalue::CSSURIValue&, const cssvalue::CSSURIValue&,
AllowExternal = kDontAllowExternalResource) const; AllowExternal = kDontAllowExternalResource) const;
void LoadPendingResources(ComputedStyle*); void LoadPendingResources(ComputedStyle&);
private: private:
StyleImage* GeneratedOrPendingFromValue(CSSPropertyID, StyleImage* GeneratedOrPendingFromValue(CSSPropertyID,
const CSSImageGeneratorValue&); const CSSImageGeneratorValue&);
void LoadPendingSVGResources(ComputedStyle*); void LoadPendingSVGResources(ComputedStyle&);
void LoadPendingImages(ComputedStyle*); void LoadPendingImages(ComputedStyle&);
StyleImage* LoadPendingImage( StyleImage* LoadPendingImage(
ComputedStyle*, ComputedStyle&,
StylePendingImage*, StylePendingImage*,
FetchParameters::ImageRequestBehavior, FetchParameters::ImageRequestBehavior,
CrossOriginAttributeValue = kCrossOriginAttributeNotSet); CrossOriginAttributeValue = kCrossOriginAttributeNotSet);
......
...@@ -50,7 +50,7 @@ struct CORE_EXPORT MatchedProperties { ...@@ -50,7 +50,7 @@ struct CORE_EXPORT MatchedProperties {
struct Data { struct Data {
unsigned link_match_type : 2; unsigned link_match_type : 2;
unsigned valid_property_filter : 2; unsigned valid_property_filter : 3;
CascadeOrigin origin; CascadeOrigin origin;
// This is approximately equivalent to the 'shadow-including tree order'. // This is approximately equivalent to the 'shadow-including tree order'.
// It can be used to evaluate the 'Shadow Tree' criteria. Note that the // It can be used to evaluate the 'Shadow Tree' criteria. Note that the
......
...@@ -1434,6 +1434,8 @@ bool StyleResolver::ApplyAnimatedStyle(StyleResolverState& state, ...@@ -1434,6 +1434,8 @@ bool StyleResolver::ApplyAnimatedStyle(StyleResolverState& state,
filter = filter.Add(CSSProperty::kIsAffectedByForcedColors, true); filter = filter.Add(CSSProperty::kIsAffectedByForcedColors, true);
if (state.Style()->StyleType() == kPseudoIdMarker) if (state.Style()->StyleType() == kPseudoIdMarker)
filter = filter.Add(CSSProperty::kValidForMarker, false); filter = filter.Add(CSSProperty::kValidForMarker, false);
if (IsHighlightPseudoElement(state.Style()->StyleType()))
filter = filter.Add(CSSProperty::kValidForHighlight, false);
filter = filter.Add(CSSProperty::kAnimation, true); filter = filter.Add(CSSProperty::kAnimation, true);
cascade.Apply(filter); cascade.Apply(filter);
......
...@@ -155,7 +155,13 @@ void StyleResolverState::LoadPendingResources() { ...@@ -155,7 +155,13 @@ void StyleResolverState::LoadPendingResources() {
StyleRef().IsEnsuredOutsideFlatTree()) StyleRef().IsEnsuredOutsideFlatTree())
return; return;
element_style_resources_.LoadPendingResources(Style()); if (StyleRef().StyleType() == kPseudoIdTargetText) {
// Do not load any resources for ::target-text since that could leak text
// content to external stylesheets.
return;
}
element_style_resources_.LoadPendingResources(StyleRef());
} }
const FontDescription& StyleResolverState::ParentFontDescription() const { const FontDescription& StyleResolverState::ParentFontDescription() const {
......
...@@ -593,6 +593,64 @@ TEST_F(StyleResolverTest, NoFetchForAtPage) { ...@@ -593,6 +593,64 @@ TEST_F(StyleResolverTest, NoFetchForAtPage) {
EXPECT_TRUE(To<CSSImageValue>(bg_img_list->Item(0)).IsCachePending()); EXPECT_TRUE(To<CSSImageValue>(bg_img_list->Item(0)).IsCachePending());
} }
TEST_F(StyleResolverTest, NoFetchForHighlightPseudoElements) {
ScopedCSSTargetTextPseudoElementForTest scoped_feature(true);
GetDocument().body()->setInnerHTML(R"HTML(
<style>
body::target-text, body::selection {
color: green;
background-image: url(bg-img.png);
cursor: url(cursor.ico), auto;
}
</style>
)HTML");
UpdateAllLifecyclePhasesForTest();
auto* body = GetDocument().body();
ASSERT_TRUE(body);
const auto* element_style = body->GetComputedStyle();
ASSERT_TRUE(element_style);
scoped_refptr<ComputedStyle> target_text_style =
GetDocument().GetStyleResolver().PseudoStyleForElement(
GetDocument().body(), PseudoElementStyleRequest(kPseudoIdTargetText),
element_style, element_style);
ASSERT_TRUE(target_text_style);
scoped_refptr<ComputedStyle> selection_style =
GetDocument().GetStyleResolver().PseudoStyleForElement(
GetDocument().body(), PseudoElementStyleRequest(kPseudoIdSelection),
element_style, element_style);
ASSERT_TRUE(selection_style);
// Check that we don't fetch the cursor url() for ::target-text.
CursorList* cursor_list = target_text_style->Cursors();
ASSERT_TRUE(cursor_list->size());
CursorData& current_cursor = cursor_list->at(0);
StyleImage* image = current_cursor.GetImage();
ASSERT_TRUE(image);
EXPECT_TRUE(image->IsPendingImage());
for (const auto* pseudo_style :
{target_text_style.get(), selection_style.get()}) {
// Check that the color applies.
EXPECT_EQ(Color(0, 128, 0),
pseudo_style->VisitedDependentColor(GetCSSPropertyColor()));
// Check that the background-image does not apply.
const CSSValue* computed_value = ComputedStyleUtils::ComputedPropertyValue(
GetCSSPropertyBackgroundImage(), *pseudo_style);
const CSSValueList* list = DynamicTo<CSSValueList>(computed_value);
ASSERT_TRUE(list);
ASSERT_EQ(1u, list->length());
const auto* keyword = DynamicTo<CSSIdentifierValue>(list->Item(0));
ASSERT_TRUE(keyword);
EXPECT_EQ(CSSValueID::kNone, keyword->GetValueID());
}
}
TEST_F(StyleResolverTest, CSSMarkerPseudoElement) { TEST_F(StyleResolverTest, CSSMarkerPseudoElement) {
GetDocument().body()->setInnerHTML(R"HTML( GetDocument().body()->setInnerHTML(R"HTML(
<style> <style>
......
...@@ -51,14 +51,23 @@ static inline ValidPropertyFilter DetermineValidPropertyFilter( ...@@ -51,14 +51,23 @@ static inline ValidPropertyFilter DetermineValidPropertyFilter(
const CSSSelector& selector) { const CSSSelector& selector) {
for (const CSSSelector* component = &selector; component; for (const CSSSelector* component = &selector; component;
component = component->TagHistory()) { component = component->TagHistory()) {
if (component->GetPseudoType() == CSSSelector::kPseudoCue || if (component->Match() == CSSSelector::kPseudoElement &&
(component->Match() == CSSSelector::kPseudoElement && component->Value() == TextTrackCue::CueShadowPseudoId()) {
component->Value() == TextTrackCue::CueShadowPseudoId()))
return ValidPropertyFilter::kCue; return ValidPropertyFilter::kCue;
if (component->GetPseudoType() == CSSSelector::kPseudoFirstLetter) }
return ValidPropertyFilter::kFirstLetter; switch (component->GetPseudoType()) {
if (component->GetPseudoType() == CSSSelector::kPseudoMarker) case CSSSelector::kPseudoCue:
return ValidPropertyFilter::kMarker; return ValidPropertyFilter::kCue;
case CSSSelector::kPseudoFirstLetter:
return ValidPropertyFilter::kFirstLetter;
case CSSSelector::kPseudoMarker:
return ValidPropertyFilter::kMarker;
case CSSSelector::kPseudoSelection:
case CSSSelector::kPseudoTargetText:
return ValidPropertyFilter::kHighlight;
default:
break;
}
} }
return ValidPropertyFilter::kNoFilter; return ValidPropertyFilter::kNoFilter;
} }
......
...@@ -58,6 +58,10 @@ enum class ValidPropertyFilter : unsigned { ...@@ -58,6 +58,10 @@ enum class ValidPropertyFilter : unsigned {
// Defined in a ::marker pseudo-element scope. Only properties listed in // Defined in a ::marker pseudo-element scope. Only properties listed in
// https://drafts.csswg.org/css-pseudo-4/#marker-pseudo are valid. // https://drafts.csswg.org/css-pseudo-4/#marker-pseudo are valid.
kMarker, kMarker,
// Defined in a highlight pseudo-element scope like ::selection and
// ::target-text. Only properties listed in
// https://drafts.csswg.org/css-pseudo-4/#highlight-styling are valid.
kHighlight,
}; };
class CSSSelector; class CSSSelector;
...@@ -151,8 +155,8 @@ class CORE_EXPORT RuleData : public GarbageCollected<RuleData> { ...@@ -151,8 +155,8 @@ class CORE_EXPORT RuleData : public GarbageCollected<RuleData> {
unsigned specificity_ : 24; unsigned specificity_ : 24;
unsigned link_match_type_ : 2; unsigned link_match_type_ : 2;
unsigned has_document_security_origin_ : 1; unsigned has_document_security_origin_ : 1;
unsigned valid_property_filter_ : 2; unsigned valid_property_filter_ : 3;
// 29 bits above // 30 bits above
// Use plain array instead of a Vector to minimize memory overhead. // Use plain array instead of a Vector to minimize memory overhead.
unsigned descendant_selector_identifier_hashes_[kMaximumIdentifierCount]; unsigned descendant_selector_identifier_hashes_[kMaximumIdentifierCount];
}; };
......
...@@ -80,6 +80,10 @@ enum PseudoId : uint8_t { ...@@ -80,6 +80,10 @@ enum PseudoId : uint8_t {
kFirstInternalPseudoId = kPseudoIdFirstLineInherited, kFirstInternalPseudoId = kPseudoIdFirstLineInherited,
}; };
inline bool IsHighlightPseudoElement(PseudoId pseudo_id) {
return pseudo_id == kPseudoIdSelection || pseudo_id == kPseudoIdTargetText;
}
enum class OutlineIsAuto : bool { kOff = false, kOn = true }; enum class OutlineIsAuto : bool { kOff = false, kOn = true };
// Random visual rendering model attributes. Not inherited. // Random visual rendering model attributes. Not inherited.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment