[go: nahoru, domu]

Resolve internal forced colors properties before used value time

This CL moves the re-resolution of internal forced colors properties
(specifically 'internal-forced-color', 'internal-forced-visited-color'
and 'internal-forced-background-color') to occur before used value
time. This is necessary because work is being done to remove system
colors from being stored in the NativeTheme to being accessed from
color providers that are associated with the Page(see CL:4898493). To
access the color providers, we need to pass them from the document to
the LayoutTheme::SystemColor method.

However, this is problematic in StyleColor::Resolve, where we currently
pass a boolean flag(`is_forced_colors`) to resolve the initial values
for these forced color properties at used value time(see: CL:2529950).
This was done because the initial values for these properties are
defined as system colors in css_properties.json5
(e.g. StyleColor(CSSValueID::kCanvas)). These values are only computed
once, so we need to recompute them to ensure they pick up the correct
color on theme change.

We want to remove this flag to avoid resolving any system colors at
used value time, which will allow us to pass nullptr instead of a color
provider when resolving colors in StyleColor::Resolve, since we do not
have an easy way to access the provider at this point in the rendering
pipeline.

To solve this, we re-resolve the initial values of these properties in
the StyleAdjuster class to avoid the need for re-resolution at used
value time. Also, we propagate the `internal-forced-background-color`
from the root to the viewport when forced colors is enabled.

Bug: 1430181
Change-Id: I5c12bff59c8ae7d760ffc34dd6d4d2d050bf0019
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5181788
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Reviewed-by: Alison Maher <almaher@microsoft.com>
Commit-Queue: Sam Davis Omekara <samomekarajr@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1258657}
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index e877b57..76c5227 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -4983,7 +4983,7 @@
   bool result_is_current_color;
   blink::Color result = style.InternalForcedBackgroundColor().ResolveWithAlpha(
       forced_current_color, style.UsedColorScheme(), alpha,
-      &result_is_current_color, /* is_forced_color */ true);
+      &result_is_current_color);
 
   if (is_current_color) {
     *is_current_color = alpha_is_current_color || result_is_current_color;
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 4f5636b6..d4b3d9b8 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -839,7 +839,8 @@
   }
 }
 
-void StyleAdjuster::AdjustForForcedColorsMode(ComputedStyleBuilder& builder) {
+void StyleAdjuster::AdjustForForcedColorsMode(ComputedStyleBuilder& builder,
+                                              Element* element) {
   if (!builder.InForcedColorsMode() ||
       builder.ForcedColorAdjust() != EForcedColorAdjust::kAuto) {
     return;
@@ -856,6 +857,36 @@
   if (!builder.HasUrlBackgroundImage()) {
     builder.ClearBackgroundImage();
   }
+
+  mojom::blink::ColorScheme color_scheme = mojom::blink::ColorScheme::kLight;
+  if (element &&
+      element->GetDocument().GetStyleEngine().GetPreferredColorScheme() ==
+          mojom::blink::PreferredColorScheme::kDark) {
+    color_scheme = mojom::blink::ColorScheme::kDark;
+  }
+  const ui::ColorProvider* color_provider =
+      element ? element->GetDocument().GetColorProviderForPainting(color_scheme)
+              : nullptr;
+
+  // Re-resolve some internal forced color properties whose initial
+  // values are system colors. This is necessary to ensure we get
+  // the correct computed value from the color provider for the
+  // system color when the theme changes.
+  if (builder.InternalForcedBackgroundColor().IsSystemColor()) {
+    builder.SetInternalForcedBackgroundColor(
+        builder.InternalForcedBackgroundColor().ResolveSystemColor(
+            color_scheme, color_provider));
+  }
+  if (builder.InternalForcedColor().IsSystemColor()) {
+    builder.SetInternalForcedColor(
+        builder.InternalForcedColor().ResolveSystemColor(color_scheme,
+                                                         color_provider));
+  }
+  if (builder.InternalForcedVisitedColor().IsSystemColor()) {
+    builder.SetInternalForcedVisitedColor(
+        builder.InternalForcedVisitedColor().ResolveSystemColor(
+            color_scheme, color_provider));
+  }
 }
 
 void StyleAdjuster::AdjustForPrefersDefaultScrollbarStyles(
@@ -1053,7 +1084,7 @@
 
   // A subset of CSS properties should be forced at computed value time:
   // https://drafts.csswg.org/css-color-adjust-1/#forced-colors-properties.
-  AdjustForForcedColorsMode(builder);
+  AdjustForForcedColorsMode(builder, element);
 
   // Let the theme also have a crack at adjusting the style.
   LayoutTheme::GetTheme().AdjustStyle(element, builder);
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.h b/third_party/blink/renderer/core/css/resolver/style_adjuster.h
index 1d43433..bcbeb054 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.h
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.h
@@ -54,7 +54,7 @@
                                          Element* element,
                                          bool is_svg_root);
   static void AdjustOverflow(ComputedStyleBuilder&, Element* element);
-  static void AdjustForForcedColorsMode(ComputedStyleBuilder&);
+  static void AdjustForForcedColorsMode(ComputedStyleBuilder&, Element* element);
   static void AdjustForPrefersDefaultScrollbarStyles(Element* element,
                                                      ComputedStyleBuilder&);
   static void AdjustForSVGTextElement(ComputedStyleBuilder&);
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 ce29d02..226b617b 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -2819,6 +2819,24 @@
       new_viewport_style_builder.AccessBackgroundLayers() = background_layers;
       new_viewport_style_builder.SetImageRendering(image_rendering);
     }
+
+    // https://github.com/w3c/csswg-drafts/issues/6307
+    // In forced colors mode, the internal forced background color is
+    // propagated from the root element to the viewport.
+    if (IsForcedColorsModeEnabled()) {
+      Color internal_forced_background_color =
+          document_element_style
+              ? document_element_style->VisitedDependentColor(
+                    GetCSSPropertyInternalForcedBackgroundColor())
+              : Color::kTransparent;
+      if (viewport_style.VisitedDependentColor(
+              GetCSSPropertyInternalForcedBackgroundColor()) !=
+          internal_forced_background_color) {
+        changed = true;
+        new_viewport_style_builder.SetInternalForcedBackgroundColor(
+            StyleColor(internal_forced_background_color));
+      }
+    }
   }
 
   // Overflow
diff --git a/third_party/blink/renderer/core/css/style_color.cc b/third_party/blink/renderer/core/css/style_color.cc
index 0efdbb6..cad00c6 100644
--- a/third_party/blink/renderer/core/css/style_color.cc
+++ b/third_party/blink/renderer/core/css/style_color.cc
@@ -228,8 +228,7 @@
 
 Color StyleColor::Resolve(const Color& current_color,
                           mojom::blink::ColorScheme color_scheme,
-                          bool* is_current_color,
-                          bool is_forced_color) const {
+                          bool* is_current_color) const {
   if (IsUnresolvedColorMixFunction()) {
     return color_or_unresolved_color_mix_.unresolved_color_mix->Resolve(
         current_color);
@@ -241,8 +240,7 @@
   if (IsCurrentColor()) {
     return current_color;
   }
-  if (EffectiveColorKeyword() != CSSValueID::kInvalid ||
-      (is_forced_color && IsSystemColorIncludingDeprecated())) {
+  if (EffectiveColorKeyword() != CSSValueID::kInvalid) {
     return ColorFromKeyword(color_keyword_, color_scheme);
   }
   return GetColor();
@@ -251,16 +249,23 @@
 Color StyleColor::ResolveWithAlpha(Color current_color,
                                    mojom::blink::ColorScheme color_scheme,
                                    int alpha,
-                                   bool* is_current_color,
-                                   bool is_forced_color) const {
-  Color color =
-      Resolve(current_color, color_scheme, is_current_color, is_forced_color);
+                                   bool* is_current_color) const {
+  Color color = Resolve(current_color, color_scheme, is_current_color);
   // TODO(crbug.com/1333988) This looks unfriendly to CSS Color 4.
   return Color(color.Red(), color.Green(), color.Blue(), alpha);
 }
 
+StyleColor StyleColor::ResolveSystemColor(
+    mojom::blink::ColorScheme color_scheme,
+    const ui::ColorProvider* color_provider) const {
+  CHECK(IsSystemColor());
+  Color color = ColorFromKeyword(color_keyword_, color_scheme, color_provider);
+  return StyleColor(color, color_keyword_);
+}
+
 Color StyleColor::ColorFromKeyword(CSSValueID keyword,
-                                   mojom::blink::ColorScheme color_scheme) {
+                                   mojom::blink::ColorScheme color_scheme,
+                                   const ui::ColorProvider* color_provider) {
   if (const char* value_name = getValueName(keyword)) {
     if (const NamedColor* named_color = FindColor(
             value_name, static_cast<wtf_size_t>(strlen(value_name)))) {
@@ -271,7 +276,7 @@
   // TODO(samomekarajr): Pass in the actual color provider from the Page via the
   // Document.
   return LayoutTheme::GetTheme().SystemColor(keyword, color_scheme,
-                                             /*color_provider=*/nullptr);
+                                             color_provider);
 }
 
 bool StyleColor::IsColorKeyword(CSSValueID id) {
diff --git a/third_party/blink/renderer/core/css/style_color.h b/third_party/blink/renderer/core/css/style_color.h
index 03a0a2d..d3cc784 100644
--- a/third_party/blink/renderer/core/css/style_color.h
+++ b/third_party/blink/renderer/core/css/style_color.h
@@ -40,6 +40,10 @@
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
+namespace ui {
+class ColorProvider;
+}
+
 namespace blink {
 
 class CORE_EXPORT StyleColor {
@@ -173,23 +177,32 @@
 
   Color Resolve(const Color& current_color,
                 mojom::blink::ColorScheme color_scheme,
-                bool* is_current_color = nullptr,
-                bool is_forced_color = false) const;
+                bool* is_current_color = nullptr) const;
 
   // Resolve and override the resolved color's alpha channel as specified by
   // |alpha|.
   Color ResolveWithAlpha(Color current_color,
                          mojom::blink::ColorScheme color_scheme,
                          int alpha,
-                         bool* is_current_color = nullptr,
-                         bool is_forced_color = false) const;
+                         bool* is_current_color = nullptr) const;
+
+  // Re-resolve the current system color keyword. This is needed in cases such
+  // as forced colors mode because initial values for some internal forced
+  // colors properties are system colors so we need to re-resolve them to ensure
+  // they pick up the correct color on theme change.
+  StyleColor ResolveSystemColor(mojom::blink::ColorScheme color_scheme,
+                                const ui::ColorProvider* color_provider) const;
 
   bool IsNumeric() const {
     return EffectiveColorKeyword() == CSSValueID::kInvalid;
   }
 
-  static Color ColorFromKeyword(CSSValueID,
-                                mojom::blink::ColorScheme color_scheme);
+  // TODO(samomekarajr): Take out the default value for color_provider once all
+  // call sites are touched in subsequent change.
+  static Color ColorFromKeyword(
+      CSSValueID,
+      mojom::blink::ColorScheme color_scheme,
+      const ui::ColorProvider* color_provider = nullptr);
   static bool IsColorKeyword(CSSValueID);
   static bool IsSystemColorIncludingDeprecated(CSSValueID);
   static bool IsSystemColor(CSSValueID);
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index b96f7071..66391d7 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -2584,8 +2584,7 @@
     return GetCurrentColor(is_current_color);
   }
   return InternalForcedColor().Resolve(blink::Color(), UsedColorScheme(),
-                                       is_current_color,
-                                       /* is_forced_color */ true);
+                                       is_current_color);
 }
 
 blink::Color ComputedStyle::GetInternalForcedVisitedCurrentColor(
@@ -2595,8 +2594,7 @@
     return GetInternalVisitedCurrentColor(is_current_color);
   }
   return InternalForcedVisitedColor().Resolve(blink::Color(), UsedColorScheme(),
-                                              is_current_color,
-                                              /* is_forced_color */ true);
+                                              is_current_color);
 }
 
 bool ComputedStyle::ShadowListHasCurrentColor(const ShadowList* shadow_list) {