LazyLoad: Fix lazyloading of pseudo css background styles
This CL passes PseudoElement to StyleResolverState, so that
ElementStyleResources::LoadPendingResources() can listen on the
appropriate pseudo element to defer and lazyload the background image.
(cherry picked from commit 9b78d5ebfc641eb10eb77b335314b1d0273c61e4)
Bug: 950503
Change-Id: Ieab6c4284ac6d405ba49d0d2535d3b05ce95fea2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1632595
Commit-Queue: rajendrant <rajendrant@chromium.org>
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#665713}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1642246
Reviewed-by: rajendrant <rajendrant@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#56}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/third_party/blink/renderer/core/animation/animation_test_helper.cc b/third_party/blink/renderer/core/animation/animation_test_helper.cc
index f69c570..a913190 100644
--- a/third_party/blink/renderer/core/animation/animation_test_helper.cc
+++ b/third_party/blink/renderer/core/animation/animation_test_helper.cc
@@ -43,7 +43,8 @@
// require our callers to propertly register every animation they pass in
// here, which the current tests do not do.
auto style = ComputedStyle::Create();
- StyleResolverState state(document, element, style.get(), style.get());
+ StyleResolverState state(document, element, nullptr /* pseudo_element */,
+ style.get(), style.get());
state.SetStyle(style);
CSSInterpolationTypesMap map(state.GetDocument().GetPropertyRegistry(),
state.GetDocument());
diff --git a/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
index 8bdbfd10..eb6ff4ed 100644
--- a/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
@@ -275,7 +275,8 @@
TEST_F(CSSVariableResolverTest, NeedsResolutionClearedByResolver) {
const ComputedStyle* initial = &ComputedStyle::InitialStyle();
- StyleResolverState state(GetDocument(), nullptr, initial, initial);
+ StyleResolverState state(GetDocument(), nullptr /* element */,
+ nullptr /* pseudo_element */, initial, initial);
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
style->InheritFrom(*initial);
@@ -462,7 +463,8 @@
using CSSUnsetValue = cssvalue::CSSUnsetValue;
const ComputedStyle* initial = &ComputedStyle::InitialStyle();
- StyleResolverState state(GetDocument(), nullptr, initial, initial);
+ StyleResolverState state(GetDocument(), nullptr /* element */,
+ nullptr /* pseudo_element */, initial, initial);
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
style->InheritFrom(*initial);
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
index 69184f84f..9278785 100644
--- a/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
+++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/css/css_uri_value.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -54,8 +55,11 @@
using namespace cssvalue;
ElementStyleResources::ElementStyleResources(Element& element,
- float device_scale_factor)
- : element_(&element), device_scale_factor_(device_scale_factor) {}
+ float device_scale_factor,
+ PseudoElement* pseudo_element)
+ : element_(&element),
+ device_scale_factor_(device_scale_factor),
+ pseudo_element_(pseudo_element) {}
StyleImage* ElementStyleResources::GetStyleImage(CSSPropertyID property,
const CSSValue& value) {
@@ -217,8 +221,10 @@
StyleImage* new_image =
LoadPendingImage(style, To<StylePendingImage>(background_image),
image_request_optimization);
- if (new_image && new_image->IsLazyloadPossiblyDeferred())
- LazyLoadImageObserver::StartMonitoring(element_);
+ if (new_image && new_image->IsLazyloadPossiblyDeferred()) {
+ LazyLoadImageObserver::StartMonitoring(
+ pseudo_element_ ? pseudo_element_ : element_.Get());
+ }
background_layer->SetImage(new_image);
}
}
diff --git a/third_party/blink/renderer/core/css/resolver/element_style_resources.h b/third_party/blink/renderer/core/css/resolver/element_style_resources.h
index 72e025d..a61766b3 100644
--- a/third_party/blink/renderer/core/css/resolver/element_style_resources.h
+++ b/third_party/blink/renderer/core/css/resolver/element_style_resources.h
@@ -41,6 +41,7 @@
class CSSValue;
class ComputedStyle;
class Element;
+class PseudoElement;
class SVGResource;
class StyleImage;
class StylePendingImage;
@@ -58,7 +59,9 @@
STACK_ALLOCATED();
public:
- ElementStyleResources(Element&, float device_scale_factor);
+ ElementStyleResources(Element&,
+ float device_scale_factor,
+ PseudoElement* pseudo_element);
StyleImage* GetStyleImage(CSSPropertyID, const CSSValue&);
StyleImage* CachedOrPendingFromValue(CSSPropertyID, const CSSImageValue&);
@@ -88,6 +91,7 @@
Member<Element> element_;
HashSet<CSSPropertyID> pending_image_properties_;
float device_scale_factor_;
+ Member<PseudoElement> pseudo_element_;
DISALLOW_COPY_AND_ASSIGN(ElementStyleResources);
};
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index a56192af..6a77809f 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -719,7 +719,8 @@
ElementResolveContext element_context(*element);
- StyleResolverState state(GetDocument(), element_context, default_parent,
+ StyleResolverState state(GetDocument(), element_context,
+ nullptr /* pseudo_element */, default_parent,
default_layout_parent);
const ComputedStyle* base_computed_style =
@@ -860,7 +861,8 @@
const CSSValue* value) {
// TODO(alancutter): Avoid creating a StyleResolverState just to apply a
// single value on a ComputedStyle.
- StyleResolverState state(element.GetDocument(), &element, parent_style,
+ StyleResolverState state(element.GetDocument(), &element,
+ nullptr /* pseudo_element */, parent_style,
parent_style);
state.SetStyle(ComputedStyle::Clone(base_style));
if (value) {
@@ -962,8 +964,10 @@
if (!element)
return nullptr;
- StyleResolverState state(GetDocument(), element, parent_style,
- parent_layout_object_style);
+ StyleResolverState state(
+ GetDocument(), element,
+ element->GetPseudoElement(pseudo_style_request.pseudo_id), parent_style,
+ parent_layout_object_style);
if (!PseudoStyleForElementInternal(*element, pseudo_style_request, state)) {
if (pseudo_style_request.type == PseudoStyleRequest::kForRenderer)
return nullptr;
@@ -982,7 +986,8 @@
scoped_refptr<ComputedStyle> initial_style =
InitialStyleForElement(GetDocument());
StyleResolverState state(GetDocument(), GetDocument().documentElement(),
- initial_style.get(), initial_style.get());
+ nullptr /* pseudo_element */, initial_style.get(),
+ initial_style.get());
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
const ComputedStyle* root_element_style =
@@ -1076,7 +1081,8 @@
StyleRuleList* StyleResolver::StyleRulesForElement(Element* element,
unsigned rules_to_include) {
DCHECK(element);
- StyleResolverState state(GetDocument(), element);
+ StyleResolverState state(GetDocument(), element,
+ nullptr /* pseudo_element */);
ElementRuleCollector collector(state.ElementContext(), selector_filter_,
state.Style());
collector.SetMode(SelectorChecker::kCollectingStyleRules);
@@ -1090,7 +1096,8 @@
PseudoId pseudo_id,
unsigned rules_to_include) {
DCHECK(element);
- StyleResolverState state(GetDocument(), element);
+ StyleResolverState state(GetDocument(), element,
+ nullptr /* pseudo_element */);
ElementRuleCollector collector(state.ElementContext(), selector_filter_,
state.Style());
collector.SetMode(SelectorChecker::kCollectingCSSRules);
@@ -1978,7 +1985,8 @@
};
// TODO(timloh): This is weird, the style is being used as its own parent
- StyleResolverState state(GetDocument(), nullptr, style, style);
+ StyleResolverState state(GetDocument(), nullptr /* element */,
+ nullptr /* pseudo_element */, style, style);
state.SetStyle(style);
for (const CSSProperty* property : properties) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
index 2effcd7..9726e5e 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -33,6 +33,7 @@
StyleResolverState::StyleResolverState(
Document& document,
const ElementResolveContext& element_context,
+ PseudoElement* pseudo_element,
const ComputedStyle* parent_style,
const ComputedStyle* layout_parent_style)
: element_context_(element_context),
@@ -46,7 +47,9 @@
apply_property_to_visited_link_style_(false),
has_dir_auto_attribute_(false),
font_builder_(&document),
- element_style_resources_(*GetElement(), document.DevicePixelRatio()) {
+ element_style_resources_(*GetElement(),
+ document.DevicePixelRatio(),
+ pseudo_element) {
DCHECK(!!parent_style_ == !!layout_parent_style_);
if (!parent_style_) {
@@ -64,11 +67,13 @@
StyleResolverState::StyleResolverState(Document& document,
Element* element,
+ PseudoElement* pseudo_element,
const ComputedStyle* parent_style,
const ComputedStyle* layout_parent_style)
: StyleResolverState(document,
element ? ElementResolveContext(*element)
: ElementResolveContext(document),
+ pseudo_element,
parent_style,
layout_parent_style) {}
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
index f86cf27..e56cdd3 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -42,6 +42,7 @@
class ComputedStyle;
class FontDescription;
+class PseudoElement;
// A per-element object which wraps an ElementResolveContext. It collects state
// throughout the process of computing the style. It also gives convenient
@@ -52,10 +53,12 @@
public:
StyleResolverState(Document&,
const ElementResolveContext&,
+ PseudoElement* pseudo_element,
const ComputedStyle* parent_style,
const ComputedStyle* layout_parent_style);
StyleResolverState(Document&,
Element*,
+ PseudoElement* pseudo_element,
const ComputedStyle* parent_style = nullptr,
const ComputedStyle* layout_parent_style = nullptr);
~StyleResolverState();
diff --git a/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc b/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
index 6eb71c3..be795514 100644
--- a/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
+++ b/third_party/blink/renderer/core/html/lazy_load_image_observer_test.cc
@@ -9,6 +9,7 @@
#include "base/optional.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/html_element.h"
@@ -57,9 +58,18 @@
GetDocument().UpdateStyleAndLayoutTree();
}
- void ExpectCSSBackgroundImageDeferredState(bool deferred) {
- const ComputedStyle* deferred_image_style =
- GetDocument().getElementById("deferred_image")->GetComputedStyle();
+ const ComputedStyle* GetElementComputedStyle(const Element& element,
+ PseudoId pseudo_id) {
+ if (pseudo_id == kPseudoIdNone)
+ return element.GetComputedStyle();
+ return element.GetPseudoElement(pseudo_id)->GetComputedStyle();
+ }
+
+ void ExpectCSSBackgroundImageDeferredState(const char* element_id,
+ PseudoId pseudo_id,
+ bool deferred) {
+ const ComputedStyle* deferred_image_style = GetElementComputedStyle(
+ *GetDocument().getElementById(element_id), pseudo_id);
EXPECT_TRUE(deferred_image_style->HasBackgroundImage());
bool is_background_image_found = false;
for (const FillLayer* background_layer =
@@ -75,6 +85,51 @@
EXPECT_TRUE(is_background_image_found);
}
+ void VerifyCSSBackgroundImageInPseudoStyleDeferred(
+ const char* style,
+ const char* deferred_div_classes,
+ const Vector<PseudoId>& background_pseudo_ids) {
+ bool is_lazyload_image_enabled = GetParam();
+ SetLazyLoadEnabled(is_lazyload_image_enabled);
+ SimRequest image_resource("https://example.com/img.png", "image/png");
+ LoadMainResource(String::Format(R"HTML(
+ <html>
+ <head>
+ <style>
+ %s
+ </style>
+ </head>
+ <body>
+ <div style='height:10000px;'></div>
+ <div id="deferred_image" class="%s"></div>
+ </body>
+ </html>
+ )HTML",
+ style, deferred_div_classes));
+
+ if (!is_lazyload_image_enabled)
+ image_resource.Complete(ReadTestImage());
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ for (const auto& pseudo_id : background_pseudo_ids) {
+ ExpectCSSBackgroundImageDeferredState("deferred_image", pseudo_id,
+ is_lazyload_image_enabled);
+ }
+ if (is_lazyload_image_enabled) {
+ // Scroll down until the background image is visible.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 10000), kProgrammaticScroll);
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ image_resource.Complete(ReadTestImage());
+ for (const auto& pseudo_id : background_pseudo_ids) {
+ ExpectCSSBackgroundImageDeferredState("deferred_image", pseudo_id,
+ false);
+ }
+ }
+ }
+
void VerifyImageElementWithDimensionDeferred(const char* img_attribute) {
bool is_lazyload_image_enabled = GetParam();
SetLazyLoadEnabled(is_lazyload_image_enabled);
@@ -135,7 +190,8 @@
Compositor().BeginFrame();
test::RunPendingTasks();
- ExpectCSSBackgroundImageDeferredState(is_lazyload_image_enabled);
+ ExpectCSSBackgroundImageDeferredState("deferred_image", kPseudoIdNone,
+ is_lazyload_image_enabled);
if (is_lazyload_image_enabled) {
// Scroll down until the background image is visible.
@@ -144,10 +200,60 @@
Compositor().BeginFrame();
test::RunPendingTasks();
image_resource.Complete(ReadTestImage());
- ExpectCSSBackgroundImageDeferredState(false);
+ ExpectCSSBackgroundImageDeferredState("deferred_image", kPseudoIdNone,
+ false);
}
}
+TEST_P(LazyLoadImagesSimTest, CSSBackgroundImagePseudoStyleBefore) {
+ VerifyCSSBackgroundImageInPseudoStyleDeferred(R"HTML(
+ .pseudo-element::before {
+ content: '';
+ height: 50px;
+ background-image: url('img.png');
+ })HTML",
+ "pseudo-element",
+ {kPseudoIdBefore});
+}
+
+TEST_P(LazyLoadImagesSimTest, CSSBackgroundImagePseudoStyleAfter) {
+ VerifyCSSBackgroundImageInPseudoStyleDeferred(R"HTML(
+ .pseudo-element::after {
+ content: '';
+ height: 50px;
+ background-image: url('img.png');
+ })HTML",
+ "pseudo-element",
+ {kPseudoIdAfter});
+}
+
+TEST_P(LazyLoadImagesSimTest, CSSBackgroundImagePseudoStyleBeforeBlock) {
+ VerifyCSSBackgroundImageInPseudoStyleDeferred(R"HTML(
+ .pseudo-element::before {
+ content: '';
+ display: block;
+ height: 50px;
+ width: 50px;
+ background-image: url('img.png');
+ })HTML",
+ "pseudo-element",
+ {kPseudoIdBefore});
+}
+
+TEST_P(LazyLoadImagesSimTest,
+ CSSBackgroundImagePseudoStyleBeforeAndAfterBlock) {
+ VerifyCSSBackgroundImageInPseudoStyleDeferred(R"HTML(
+ .pseudo-element::before {
+ content: '';
+ display: block;
+ height: 50px;
+ width: 50px;
+ background-image: url('img.png');
+ })HTML",
+ "pseudo-element",
+ {kPseudoIdBefore});
+}
+
TEST_P(LazyLoadImagesSimTest, LargeImageHeight100Width100) {
VerifyImageElementWithDimensionDeferred("height='100px' width='100px'");
}
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc
index 04d7d61..8ad4313 100644
--- a/third_party/blink/renderer/core/style/computed_style_test.cc
+++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -503,8 +503,9 @@
dummy_page_holder_->GetDocument().GetSettings()->SetPreferredColorScheme(
PreferredColorScheme::kDark);
- StyleResolverState state(dummy_page_holder_->GetDocument(), nullptr, initial,
- initial);
+ StyleResolverState state(dummy_page_holder_->GetDocument(),
+ nullptr /* element */, nullptr /* pseudo_element */,
+ initial, initial);
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
state.SetStyle(style);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc
index d840e5182..9f03fb2c 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc
@@ -336,9 +336,9 @@
// Must set font in case the filter uses any font-relative units (em, ex)
filter_style->SetFont(font_for_filter_);
- StyleResolverState resolver_state(style_resolution_host->GetDocument(),
- style_resolution_host, filter_style.get(),
- filter_style.get());
+ StyleResolverState resolver_state(
+ style_resolution_host->GetDocument(), style_resolution_host,
+ nullptr /* pseudo_element */, filter_style.get(), filter_style.get());
resolver_state.SetStyle(filter_style);
StyleBuilder::ApplyProperty(GetCSSPropertyFilter(), resolver_state,