[go: nahoru, domu]

Blob Blame History Raw
diff -up chromium-126.0.6478.26/ash/style/ash_color_mixer_unittest.cc.mee chromium-126.0.6478.26/ash/style/ash_color_mixer_unittest.cc
--- chromium-126.0.6478.26/ash/style/ash_color_mixer_unittest.cc.mee	2024-05-29 18:00:44.000000000 +0200
+++ chromium-126.0.6478.26/ash/style/ash_color_mixer_unittest.cc	2024-06-03 16:22:10.549568854 +0200
@@ -37,6 +37,9 @@ void InitializeColorProvider(const ui::C
   // Roughly mimics the ColorMixer configuration for Ash.
   ash::AddCrosStylesColorMixer(&color_provider, key);
   ash::AddAshColorMixer(&color_provider, key);
+
+  // Populates the color map with computed color values.
+  color_provider.GenerateColorMap();
 }
 
 // Initializes the `color_provider` with `seed_color` and the relevant
diff -up chromium-126.0.6478.26/chrome/browser/chrome_content_browser_client_browsertest.cc.mee chromium-126.0.6478.26/chrome/browser/chrome_content_browser_client_browsertest.cc
--- chromium-126.0.6478.26/chrome/browser/chrome_content_browser_client_browsertest.cc.mee	2024-05-29 18:00:52.000000000 +0200
+++ chromium-126.0.6478.26/chrome/browser/chrome_content_browser_client_browsertest.cc	2024-06-03 16:22:10.550568873 +0200
@@ -602,6 +602,7 @@ class PrefersColorSchemeTest
     explicit MockColorProviderSource(bool is_dark) {
       key_.color_mode = is_dark ? ui::ColorProviderKey::ColorMode::kDark
                                 : ui::ColorProviderKey::ColorMode::kLight;
+      provider_.GenerateColorMap();
     }
     MockColorProviderSource(const MockColorProviderSource&) = delete;
     MockColorProviderSource& operator=(const MockColorProviderSource&) = delete;
diff -up chromium-126.0.6478.26/chrome/browser/themes/browser_theme_pack_unittest.cc.mee chromium-126.0.6478.26/chrome/browser/themes/browser_theme_pack_unittest.cc
--- chromium-126.0.6478.26/chrome/browser/themes/browser_theme_pack_unittest.cc.mee	2024-05-29 18:00:57.000000000 +0200
+++ chromium-126.0.6478.26/chrome/browser/themes/browser_theme_pack_unittest.cc	2024-06-03 16:22:10.550568873 +0200
@@ -750,6 +750,7 @@ TEST_F(BrowserThemePackTest, TestCreateC
                                 "omnibox_background": [120, 140, 160] })";
   LoadColorJSON(color_json);
   theme_pack().AddColorMixers(&provider, ui::ColorProviderKey());
+  provider.GenerateColorMap();
   EXPECT_EQ(SkColorSetRGB(0, 20, 40), provider.GetColor(kColorToolbar));
   EXPECT_EQ(SkColorSetRGB(60, 80, 100), provider.GetColor(kColorOmniboxText));
   EXPECT_EQ(SkColorSetRGB(120, 140, 160),
diff -up chromium-126.0.6478.26/chrome/browser/ui/color/material_new_tab_page_color_mixer_unittest.cc.mee chromium-126.0.6478.26/chrome/browser/ui/color/material_new_tab_page_color_mixer_unittest.cc
--- chromium-126.0.6478.26/chrome/browser/ui/color/material_new_tab_page_color_mixer_unittest.cc.mee	2024-05-29 18:00:58.000000000 +0200
+++ chromium-126.0.6478.26/chrome/browser/ui/color/material_new_tab_page_color_mixer_unittest.cc	2024-06-03 16:22:10.551568891 +0200
@@ -26,6 +26,7 @@ class MaterialNewTabPageColorMixerTest :
   void AddMaterialColorMixers() {
     AddColorMixers(&color_provider_, color_provider_key_);
     AddChromeColorMixers(&color_provider_, color_provider_key_);
+    color_provider_.GenerateColorMap();
   }
 
  private:
diff -up chromium-126.0.6478.26/chrome/browser/ui/color/new_tab_page_color_mixer_unittest.cc.mee chromium-126.0.6478.26/chrome/browser/ui/color/new_tab_page_color_mixer_unittest.cc
--- chromium-126.0.6478.26/chrome/browser/ui/color/new_tab_page_color_mixer_unittest.cc.mee	2024-05-29 18:00:58.000000000 +0200
+++ chromium-126.0.6478.26/chrome/browser/ui/color/new_tab_page_color_mixer_unittest.cc	2024-06-03 16:22:10.551568891 +0200
@@ -33,6 +33,7 @@ TEST(NewTabPageColorMixer, LightAndDarkT
     if (color_utils::IsDark(toolbar_color))
       key.color_mode = ui::ColorProviderKey::ColorMode::kDark;
     AddNewTabPageColorMixer(&provider, key);
+    provider.GenerateColorMap();
 
     EXPECT_EQ(provider.GetColor(kColorToolbar), toolbar_color);
     EXPECT_EQ(provider.GetColor(kColorNewTabPageBackground), toolbar_color);
@@ -51,6 +52,7 @@ TEST(NewTabPageColorMixer, CustomColorCo
   key.custom_theme =
       base::WrapRefCounted(new CustomThemeSupplier(ThemeType::kAutogenerated));
   AddNewTabPageColorMixer(&provider, key);
+  provider.GenerateColorMap();
 
   EXPECT_EQ(provider.GetColor(kColorToolbar), gfx::kGoogleGreen300);
   EXPECT_EQ(provider.GetColor(kColorNewTabPageBackground),
@@ -72,6 +74,7 @@ TEST(NewTabPageColorMixer, DefaultColorC
   key.custom_theme =
       base::WrapRefCounted(new CustomThemeSupplier(ThemeType::kAutogenerated));
   AddNewTabPageColorMixer(&provider, key);
+  provider.GenerateColorMap();
 
   EXPECT_EQ(provider.GetColor(kColorToolbar), kSampleToolbarColor);
   EXPECT_EQ(provider.GetColor(kColorNewTabPageBackground), kSampleToolbarColor);
diff -up chromium-126.0.6478.26/chrome/browser/ui/color/tools/dump_colors.cc.mee chromium-126.0.6478.26/chrome/browser/ui/color/tools/dump_colors.cc
--- chromium-126.0.6478.26/chrome/browser/ui/color/tools/dump_colors.cc.mee	2024-05-29 18:00:58.000000000 +0200
+++ chromium-126.0.6478.26/chrome/browser/ui/color/tools/dump_colors.cc	2024-06-03 16:22:10.551568891 +0200
@@ -56,6 +56,7 @@ int main(int argc, const char* argv[]) {
     ui::AddColorMixers(provider, key);
     color::AddComponentsColorMixers(provider, key);
     AddChromeColorMixers(provider, key);
+    provider->GenerateColorMap();
   };
   ui::ColorProvider light_provider, dark_provider, light_high_contrast_provider,
       dark_high_contrast_provider;
diff -up chromium-126.0.6478.26/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc.mee chromium-126.0.6478.26/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc
--- chromium-126.0.6478.26/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc.mee	2024-05-29 18:00:59.000000000 +0200
+++ chromium-126.0.6478.26/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc	2024-06-03 16:22:10.552568911 +0200
@@ -117,7 +117,7 @@ class MockLogoService : public search_pr
 
 class MockColorProviderSource : public ui::ColorProviderSource {
  public:
-  MockColorProviderSource() = default;
+  MockColorProviderSource() { color_provider_.GenerateColorMap(); }
   MockColorProviderSource(const MockColorProviderSource&) = delete;
   MockColorProviderSource& operator=(const MockColorProviderSource&) = delete;
   ~MockColorProviderSource() override = default;
diff -up chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_browsertest.cc.mee chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_browsertest.cc
--- chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_browsertest.cc.mee	2024-05-29 18:01:13.000000000 +0200
+++ chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_browsertest.cc	2024-06-03 16:22:10.553568929 +0200
@@ -6300,7 +6300,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplSt
 
 class MockColorProviderSource : public ui::ColorProviderSource {
  public:
-  MockColorProviderSource() = default;
+  MockColorProviderSource() { provider_.GenerateColorMap(); }
   MockColorProviderSource(const MockColorProviderSource&) = delete;
   MockColorProviderSource& operator=(const MockColorProviderSource&) = delete;
   ~MockColorProviderSource() override = default;
diff -up chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_unittest.cc.mee chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_unittest.cc
--- chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_unittest.cc.mee	2024-05-29 18:01:13.000000000 +0200
+++ chromium-126.0.6478.26/content/browser/web_contents/web_contents_impl_unittest.cc	2024-06-03 16:22:10.554568949 +0200
@@ -337,7 +337,7 @@ class MockPageBroadcast : public TestPag
 
 class TestColorProviderSource : public ui::ColorProviderSource {
  public:
-  TestColorProviderSource() = default;
+  TestColorProviderSource() { provider_.GenerateColorMap(); }
 
   const ui::ColorProvider* GetColorProvider() const override {
     return &provider_;
diff -up chromium-126.0.6478.26/content/public/test/render_view_test.cc.mee chromium-126.0.6478.26/content/public/test/render_view_test.cc
--- chromium-126.0.6478.26/content/public/test/render_view_test.cc.mee	2024-05-29 18:01:14.000000000 +0200
+++ chromium-126.0.6478.26/content/public/test/render_view_test.cc	2024-06-03 16:22:10.554568949 +0200
@@ -150,7 +150,7 @@ class FailingURLLoaderFactory : public n
 
 class MockColorProviderSource : public ui::ColorProviderSource {
  public:
-  explicit MockColorProviderSource() = default;
+  explicit MockColorProviderSource() { provider_.GenerateColorMap(); }
   MockColorProviderSource(const MockColorProviderSource&) = delete;
   MockColorProviderSource& operator=(const MockColorProviderSource&) = delete;
   ~MockColorProviderSource() override = default;
diff -up chromium-126.0.6478.26/extensions/browser/extension_host.cc.mee chromium-126.0.6478.26/extensions/browser/extension_host.cc
--- chromium-126.0.6478.26/extensions/browser/extension_host.cc.mee	2024-05-29 18:01:22.000000000 +0200
+++ chromium-126.0.6478.26/extensions/browser/extension_host.cc	2024-06-03 16:22:10.555568967 +0200
@@ -58,7 +58,7 @@ namespace {
 // the UI-less extension background page.
 class NoOpColorProviderSource : public ui::ColorProviderSource {
  public:
-  NoOpColorProviderSource() = default;
+  NoOpColorProviderSource() { color_provider_.GenerateColorMap(); }
   NoOpColorProviderSource(const NoOpColorProviderSource&) = delete;
   NoOpColorProviderSource& operator=(const NoOpColorProviderSource&) = delete;
   ~NoOpColorProviderSource() override = default;
diff -up chromium-126.0.6478.26/third_party/blink/renderer/core/layout/layout_theme.cc.mee chromium-126.0.6478.26/third_party/blink/renderer/core/layout/layout_theme.cc
--- chromium-126.0.6478.26/third_party/blink/renderer/core/layout/layout_theme.cc.mee	2024-05-29 18:01:39.000000000 +0200
+++ chromium-126.0.6478.26/third_party/blink/renderer/core/layout/layout_theme.cc	2024-06-03 16:22:10.555568967 +0200
@@ -677,7 +677,7 @@ Color LayoutTheme::SystemColorFromColorP
     CSSValueID css_value_id,
     mojom::blink::ColorScheme color_scheme,
     const ui::ColorProvider* color_provider) const {
-  CHECK(color_provider->HasMixers());
+  CHECK(!color_provider->IsColorMapEmpty());
   SkColor system_theme_color;
   switch (css_value_id) {
     case CSSValueID::kActivetext:
diff -up chromium-126.0.6478.26/ui/base/models/image_model_unittest.cc.mee chromium-126.0.6478.26/ui/base/models/image_model_unittest.cc
--- chromium-126.0.6478.26/ui/base/models/image_model_unittest.cc.mee	2024-05-29 18:02:31.000000000 +0200
+++ chromium-126.0.6478.26/ui/base/models/image_model_unittest.cc	2024-06-03 16:22:10.555568967 +0200
@@ -224,6 +224,7 @@ TEST(ImageModelTest, ShouldRasterizeEmpt
 
 TEST(ImageModelTest, ShouldRasterizeVectorIcon) {
   ui::ColorProvider color_provider;
+  color_provider.GenerateColorMap();
   gfx::ImageSkia image_skia =
       ui::ImageModel::FromVectorIcon(vector_icons::kSyncIcon)
           .Rasterize(&color_provider);
diff -up chromium-126.0.6478.26/ui/color/color_provider.cc.mee chromium-126.0.6478.26/ui/color/color_provider.cc
--- chromium-126.0.6478.26/ui/color/color_provider.cc.mee	2024-06-03 16:03:15.596432761 +0200
+++ chromium-126.0.6478.26/ui/color/color_provider.cc	2024-06-03 16:22:10.555568967 +0200
@@ -4,7 +4,6 @@
 
 #include "ui/color/color_provider.h"
 
-#include <forward_list>
 #include <map>
 #include <set>
 #include <utility>
@@ -18,106 +17,6 @@
 
 namespace ui {
 
-////////////////////////////////////////////////////////////////////////////////
-// ColorProvider::ColorProviderInternal:
-
-class ColorProvider::ColorProviderInternal {
- public:
-  using Mixers = std::forward_list<ColorMixer>;
-
-  ColorProviderInternal() = default;
-  ColorProviderInternal(const ColorProviderInternal&) = delete;
-  ColorProviderInternal& operator=(const ColorProviderInternal&) = delete;
-  ~ColorProviderInternal() = default;
-
-  ColorMixer& AddMixer() {
-    color_map_.clear();
-    mixers_.emplace_after(
-        first_postprocessing_mixer_,
-        base::BindRepeating([](const ColorMixer* mixer) { return mixer; },
-                            GetLastNonPostprocessingMixer()),
-        base::BindRepeating(&ColorProvider::ColorProviderInternal::
-                                GetLastNonPostprocessingMixer,
-                            base::Unretained(this)));
-
-    return *std::next(first_postprocessing_mixer_, 1);
-  }
-
-  ColorMixer& AddPostprocessingMixer() {
-    color_map_.clear();
-    if (first_postprocessing_mixer_ == mixers_.before_begin()) {
-      // The first postprocessing mixer points to the last regular mixer.
-      auto previous_mixer_getter = base::BindRepeating(
-          &ColorProvider::ColorProviderInternal::GetLastNonPostprocessingMixer,
-          base::Unretained(this));
-      mixers_.emplace_front(previous_mixer_getter, previous_mixer_getter);
-      first_postprocessing_mixer_ = mixers_.begin();
-    } else {
-      // Other postprocessing mixers point to the next postprocessing mixer.
-      auto previous_mixer_getter =
-          base::BindRepeating([](const ColorMixer* mixer) { return mixer; },
-                              base::Unretained(&mixers_.front()));
-      mixers_.emplace_front(previous_mixer_getter, previous_mixer_getter);
-    }
-    return mixers_.front();
-  }
-
-  SkColor GetColor(ColorId id) const {
-    auto i = color_map_.find(id);
-    if (i == color_map_.end()) {
-      if (mixers_.empty()) {
-        DVLOG(2) << "ColorProvider::GetColor: No mixers defined!";
-        return gfx::kPlaceholderColor;
-      }
-      DVLOG(2) << "ColorProvider::GetColor: Computing color for ColorId: "
-               << ColorIdName(id);
-      const SkColor color = mixers_.front().GetResultColor(id);
-      if (color == gfx::kPlaceholderColor) {
-        return gfx::kPlaceholderColor;
-      }
-      i = color_map_.insert({id, color}).first;
-    }
-
-    DVLOG(2) << "ColorProvider::GetColor: ColorId: " << ColorIdName(id)
-             << " Value: " << SkColorName(i->second);
-    return i->second;
-  }
-
-  const ColorMixer* GetLastNonPostprocessingMixer() const {
-    const auto it = std::next(first_postprocessing_mixer_, 1);
-    return (it == mixers_.cend()) ? nullptr : &(*it);
-  }
-
-  bool HasMixers() const { return !mixers_.empty(); }
-
-  void SetColorForTesting(ColorId id, SkColor color) { color_map_[id] = color; }
-
-  void GenerateColorMapForTesting() {
-    for (const auto& mixer : mixers_) {
-      const auto mixer_color_ids = mixer.GetDefinedColorIds();
-      for (const auto color_id : mixer_color_ids) {
-        GetColor(color_id);
-      }
-    }
-  }
-
-  const ColorProvider::ColorMap& color_map_for_testing() { return color_map_; }
-
- private:
-  // The entire color pipeline, in reverse order (that is, the "last" mixer is
-  // at the front).
-  Mixers mixers_;
-
-  // The first mixer in the chain that is a "postprocessing" mixer.
-  Mixers::iterator first_postprocessing_mixer_ = mixers_.before_begin();
-
-  // A cached map of ColorId => SkColor mappings for this provider.
-  mutable ColorMap color_map_;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// ColorProvider:
-
 ColorProvider::ColorProvider() = default;
 
 ColorProvider::ColorProvider(ColorProvider&&) = default;
@@ -127,31 +26,96 @@ ColorProvider& ColorProvider::operator=(
 ColorProvider::~ColorProvider() = default;
 
 ColorMixer& ColorProvider::AddMixer() {
-  return internal_->AddMixer();
+  DCHECK(!color_map_);
+
+  mixers_.emplace_after(
+      first_postprocessing_mixer_,
+      base::BindRepeating([](const ColorMixer* mixer) { return mixer; },
+                          GetLastNonPostprocessingMixer()),
+      base::BindRepeating(&ColorProvider::GetLastNonPostprocessingMixer,
+                          base::Unretained(this)));
+
+  return *std::next(first_postprocessing_mixer_, 1);
 }
 
 ColorMixer& ColorProvider::AddPostprocessingMixer() {
-  return internal_->AddPostprocessingMixer();
+  DCHECK(!color_map_);
+
+  if (first_postprocessing_mixer_ == mixers_.before_begin()) {
+    // The first postprocessing mixer points to the last regular mixer.
+    auto previous_mixer_getter = base::BindRepeating(
+        &ColorProvider::GetLastNonPostprocessingMixer, base::Unretained(this));
+    mixers_.emplace_front(previous_mixer_getter, previous_mixer_getter);
+    first_postprocessing_mixer_ = mixers_.begin();
+  } else {
+    // Other postprocessing mixers point to the next postprocessing mixer.
+    auto previous_mixer_getter =
+        base::BindRepeating([](const ColorMixer* mixer) { return mixer; },
+                            base::Unretained(&mixers_.front()));
+    mixers_.emplace_front(previous_mixer_getter, previous_mixer_getter);
+  }
+  return mixers_.front();
 }
 
 SkColor ColorProvider::GetColor(ColorId id) const {
-  return internal_->GetColor(id);
-}
+  CHECK(color_map_);
+  auto i = color_map_->find(id);
+  return i == color_map_->end() ? gfx::kPlaceholderColor : i->second;
+}
+
+void ColorProvider::GenerateColorMap() {
+  // This should only be called to generate the `color_map_` once.
+  DCHECK(!color_map_);
+
+  if (mixers_.empty())
+    DVLOG(2) << "ColorProvider::GenerateColorMap: No mixers defined!";
+
+  // Iterate over associated mixers and extract the ColorIds defined for this
+  // provider.
+  std::set<ColorId> color_ids;
+  for (const auto& mixer : mixers_) {
+    const auto mixer_color_ids = mixer.GetDefinedColorIds();
+    color_ids.insert(mixer_color_ids.begin(), mixer_color_ids.end());
+  }
+
+  // Iterate through all defined ColorIds and seed the `color_map` with the
+  // computed values. Use a std::map rather than a base::flat_map since it has
+  // frequent inserts and could grow very large.
+  std::map<ColorId, SkColor> color_map;
+  for (const auto& color_id : color_ids) {
+    SkColor resulting_color = mixers_.front().GetResultColor(color_id);
+    DVLOG(2) << "GenerateColorMap:"
+             << " Color Id: " << ColorIdName(color_id)
+             << " Resulting Color: " << SkColorName(resulting_color);
+    color_map.insert({color_id, resulting_color});
+  }
+
+  // Construct the color_map_.
+  color_map_ = ColorMap(color_map.begin(), color_map.end());
 
-bool ColorProvider::HasMixers() const {
-  return internal_->HasMixers();
+  // Clear away all associated mixers as these are no longer needed.
+  mixers_.clear();
+  first_postprocessing_mixer_ = mixers_.before_begin();
 }
 
-void ColorProvider::SetColorForTesting(ColorId id, SkColor color) {
-  internal_->SetColorForTesting(id, color);  // IN-TEST
+bool ColorProvider::IsColorMapEmpty() const {
+  DCHECK(color_map_);
+  return color_map_->empty();
 }
 
-void ColorProvider::GenerateColorMapForTesting() {
-  internal_->GenerateColorMapForTesting();  // IN-TEST
+void ColorProvider::SetColorForTesting(ColorId id, SkColor color) {
+  if (color_map_) {
+    (*color_map_)[id] = color;
+  } else {
+    if (mixers_.empty())
+      AddMixer();
+    (*std::next(first_postprocessing_mixer_, 1))[id] = {color};
+  }
 }
 
-const ColorProvider::ColorMap& ColorProvider::color_map_for_testing() {
-  return internal_->color_map_for_testing();  // IN-TEST
+const ColorMixer* ColorProvider::GetLastNonPostprocessingMixer() const {
+  const auto it = std::next(first_postprocessing_mixer_, 1);
+  return (it == mixers_.cend()) ? nullptr : &(*it);
 }
 
 }  // namespace ui
diff -up chromium-126.0.6478.26/ui/color/color_provider.h.mee chromium-126.0.6478.26/ui/color/color_provider.h
--- chromium-126.0.6478.26/ui/color/color_provider.h.mee	2024-06-03 16:13:48.739166275 +0200
+++ chromium-126.0.6478.26/ui/color/color_provider.h	2024-06-03 16:22:10.555568967 +0200
@@ -5,11 +5,12 @@
 #ifndef UI_COLOR_COLOR_PROVIDER_H_
 #define UI_COLOR_COLOR_PROVIDER_H_
 
-#include <map>
+#include <forward_list>
 #include <memory>
 #include <optional>
 
 #include "base/component_export.h"
+#include "base/containers/flat_map.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_mixer.h"
@@ -24,7 +25,7 @@ namespace ui {
 // TODO(pkasting): Figure out ownership model and lifetime.
 class COMPONENT_EXPORT(COLOR) ColorProvider {
  public:
-  using ColorMap = std::map<ColorId, SkColor>;
+  using ColorMap = base::flat_map<ColorId, SkColor>;
 
   ColorProvider();
   ColorProvider(const ColorProvider&) = delete;
@@ -48,25 +49,39 @@ class COMPONENT_EXPORT(COLOR) ColorProvi
   // |id|.
   SkColor GetColor(ColorId id) const;
 
-  // Returns true if mixers is not empty. It's the case for some browser
+  // Generates the `color_map_` used by this provider for all ColorIds defined
+  // by attached mixers. After the map is generated attached mixers and their
+  // associated objects are discarded. Mixers should not be added to the
+  // provider after this has been called.
+  void GenerateColorMap();
+
+  // Returns true if the color_map_ is empty. It's the case for some browser
   // tests that run in single process mode but access colors that are
   // initialized on renderer process launch, for example, controls in
   // NaiveThemeBase and its children classes. Please see more details:
   // https://crbug.com/1376775.
-  bool HasMixers() const;
+  bool IsColorMapEmpty() const;
 
   void SetColorForTesting(ColorId id, SkColor color);
-  void GenerateColorMapForTesting();
-  const ColorMap& color_map_for_testing();
+  const ColorMap& color_map_for_testing() { return *color_map_; }
 
  private:
-  // ColorProviderInternal provides the actual implementation of ColorProvider.
-  // It's non-movable and non-copyable so that ColorMixer's callbacks can safely
-  // bind to it.
-  class ColorProviderInternal;
+  using Mixers = std::forward_list<ColorMixer>;
 
-  std::unique_ptr<ColorProviderInternal> internal_ =
-      std::make_unique<ColorProviderInternal>();
+  // Returns the last mixer in the chain that is not a "postprocessing" mixer,
+  // or nullptr.
+  const ColorMixer* GetLastNonPostprocessingMixer() const;
+
+  // The entire color pipeline, in reverse order (that is, the "last" mixer is
+  // at the front).
+  Mixers mixers_;
+
+  // The first mixer in the chain that is a "postprocessing" mixer.
+  Mixers::iterator first_postprocessing_mixer_ = mixers_.before_begin();
+
+  // A cached map of ColorId => SkColor mappings for this provider. This will be
+  // generated in the call to `GenerateColorMap()`.
+  std::optional<ColorMap> color_map_;
 };
 
 }  // namespace ui
diff -up chromium-126.0.6478.26/ui/color/color_provider_manager.cc.mee chromium-126.0.6478.26/ui/color/color_provider_manager.cc
--- chromium-126.0.6478.26/ui/color/color_provider_manager.cc.mee	2024-05-29 18:02:31.000000000 +0200
+++ chromium-126.0.6478.26/ui/color/color_provider_manager.cc	2024-06-03 16:22:10.556568986 +0200
@@ -109,6 +109,7 @@ ColorProvider* ColorProviderManager::Get
     if (!initializer_list_->empty())
       initializer_list_->Notify(provider.get(), key);
 
+    provider->GenerateColorMap();
     RecordTimeSpentInitializingColorProvider(timer.Elapsed());
     ++num_providers_initialized_;
 
diff -up chromium-126.0.6478.26/ui/color/color_provider_unittest.cc.mee chromium-126.0.6478.26/ui/color/color_provider_unittest.cc
--- chromium-126.0.6478.26/ui/color/color_provider_unittest.cc.mee	2024-05-29 18:02:31.000000000 +0200
+++ chromium-126.0.6478.26/ui/color/color_provider_unittest.cc	2024-06-03 16:22:10.556568986 +0200
@@ -17,6 +17,7 @@ namespace {
 // Tests that when there are no mixers, GetColor() returns a placeholder value.
 TEST(ColorProviderTest, GetColorNoMixers) {
   ColorProvider provider;
+  provider.GenerateColorMap();
   EXPECT_EQ(gfx::kPlaceholderColor, provider.GetColor(kColorTest0));
 }
 
@@ -25,6 +26,7 @@ TEST(ColorProviderTest, GetColorNoMixers
 TEST(ColorProviderTest, SingleMixer) {
   ColorProvider provider;
   provider.AddMixer()[kColorTest0] = {SK_ColorGREEN};
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorGREEN, provider.GetColor(kColorTest0));
   EXPECT_EQ(gfx::kPlaceholderColor, provider.GetColor(kColorTest1));
 }
@@ -35,6 +37,7 @@ TEST(ColorProviderTest, NonOverlappingMi
   ColorProvider provider;
   provider.AddMixer()[kColorTest0] = {SK_ColorGREEN};
   provider.AddMixer()[kColorTest1] = {SK_ColorRED};
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorGREEN, provider.GetColor(kColorTest0));
   EXPECT_EQ(SK_ColorRED, provider.GetColor(kColorTest1));
 }
@@ -45,6 +48,7 @@ TEST(ColorProviderTest, OverlappingMixer
   ColorProvider provider;
   provider.AddMixer()[kColorTest0] = {SK_ColorGREEN};
   provider.AddMixer()[kColorTest0] = {SK_ColorRED};
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorRED, provider.GetColor(kColorTest0));
 }
 
@@ -55,6 +59,7 @@ TEST(ColorProviderTest, WithProcessing)
   provider.AddMixer()[kColorTest0] = {SK_ColorBLACK};
   provider.AddPostprocessingMixer()[kColorTest0] =
       GetColorWithMaxContrast(FromTransformInput());
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorWHITE, provider.GetColor(kColorTest0));
 }
 
@@ -65,6 +70,7 @@ TEST(ColorProviderTest, WithProcessingAd
   provider.AddPostprocessingMixer()[kColorTest0] =
       GetColorWithMaxContrast(FromTransformInput());
   provider.AddMixer()[kColorTest0] = {SK_ColorBLACK};
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorWHITE, provider.GetColor(kColorTest0));
 }
 
@@ -76,6 +82,7 @@ TEST(ColorProviderTest, Redefinition) {
   mixer0[kColorTest0] = {SK_ColorBLACK};
   mixer0[kColorTest1] = AlphaBlend(SK_ColorRED, kColorTest0, 0x01);
   provider.AddMixer()[kColorTest0] = {SK_ColorWHITE};
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorWHITE, provider.GetColor(kColorTest0));
   EXPECT_FALSE(color_utils::IsDark(provider.GetColor(kColorTest1)));
 }
@@ -90,6 +97,7 @@ TEST(ColorProviderTest, RedefinitionWith
   provider.AddMixer()[kColorTest0] = {SK_ColorWHITE};
   provider.AddPostprocessingMixer()[kColorTest0] =
       GetColorWithMaxContrast(FromTransformInput());
+  provider.GenerateColorMap();
   EXPECT_NE(SK_ColorWHITE, provider.GetColor(kColorTest0));
   EXPECT_FALSE(color_utils::IsDark(provider.GetColor(kColorTest1)));
 }
@@ -97,6 +105,7 @@ TEST(ColorProviderTest, RedefinitionWith
 TEST(ColorProviderTest, SetColorForTesting) {
   ColorProvider provider;
   provider.SetColorForTesting(kColorTest0, SK_ColorGREEN);
+  provider.GenerateColorMap();
   EXPECT_EQ(SK_ColorGREEN, provider.GetColor(kColorTest0));
   EXPECT_EQ(gfx::kPlaceholderColor, provider.GetColor(kColorTest1));
   provider.SetColorForTesting(kColorTest1, SK_ColorBLUE);
diff -up chromium-126.0.6478.26/ui/color/color_provider_utils.cc.mee chromium-126.0.6478.26/ui/color/color_provider_utils.cc
--- chromium-126.0.6478.26/ui/color/color_provider_utils.cc.mee	2024-05-29 18:02:31.000000000 +0200
+++ chromium-126.0.6478.26/ui/color/color_provider_utils.cc	2024-06-03 16:22:10.556568986 +0200
@@ -367,6 +367,7 @@ ColorProvider CreateColorProviderFromRen
 
   for (const auto& table : kRendererColorIdMap)
     mixer[table.color_id] = {renderer_color_map.at(table.renderer_color_id)};
+  color_provider.GenerateColorMap();
 
   return color_provider;
 }
@@ -425,6 +426,7 @@ ColorProvider CreateEmulatedForcedColors
   mixer[kColorSeparator] = {kColorMidground};
   CompleteDefaultNonWebNativeRendererColorIdsDefinition(mixer);
 
+  color_provider.GenerateColorMap();
   return color_provider;
 }
 
@@ -479,6 +481,7 @@ ColorProvider CreateEmulatedForcedColors
   mixer[kColorWebNativeControlSliderHovered] = {SK_ColorCYAN};
   mixer[kColorWebNativeControlSliderPressed] = {SK_ColorCYAN};
 
+  color_provider.GenerateColorMap();
   return color_provider;
 }
 
@@ -652,6 +655,7 @@ ColorProvider COMPONENT_EXPORT(COLOR)
         SkColorSetRGB(0x37, 0x93, 0xFF)};
   }
 
+  color_provider.GenerateColorMap();
   return color_provider;
 }
 
diff -up chromium-126.0.6478.26/ui/color/color_provider_utils_unittest.cc.mee chromium-126.0.6478.26/ui/color/color_provider_utils_unittest.cc
--- chromium-126.0.6478.26/ui/color/color_provider_utils_unittest.cc.mee	2024-05-29 18:02:31.000000000 +0200
+++ chromium-126.0.6478.26/ui/color/color_provider_utils_unittest.cc	2024-06-03 16:22:10.556568986 +0200
@@ -49,6 +49,7 @@ TEST_F(ColorProviderUtilsTest, RendererC
   ui::ColorMixer& mixer = color_provider.AddMixer();
   for (int i = ui::kUiColorsStart + 1; i < ui::kUiColorsEnd; ++i)
     mixer[i] = {static_cast<SkColor>(i)};
+  color_provider.GenerateColorMap();
 
   // The size of the RendererColorMap should match number of defined
   // RendererColorIds.
@@ -60,7 +61,6 @@ TEST_F(ColorProviderUtilsTest, RendererC
   // also match the number of defined RendererColorIds.
   auto new_color_provider =
       ui::CreateColorProviderFromRendererColorMap(renderer_color_map);
-  new_color_provider.GenerateColorMapForTesting();
   EXPECT_EQ(kTotaltRendererColorIds,
             new_color_provider.color_map_for_testing().size());
 }
@@ -73,6 +73,7 @@ TEST_F(ColorProviderUtilsTest, ColorProv
   for (int i = ui::kUiColorsStart + 1; i < ui::kUiColorsEnd; ++i) {
     mixer[i] = {static_cast<SkColor>(i)};
   }
+  color_provider.GenerateColorMap();
 
   // A renderer color map generated from its source provider should have
   // equivalent mappings.
@@ -84,6 +85,7 @@ TEST_F(ColorProviderUtilsTest, ColorProv
   // Providers with different renderer color mappings should not be flagged as
   // equivalent.
   ui::ColorProvider new_color_provider;
+  new_color_provider.GenerateColorMap();
   EXPECT_FALSE(IsRendererColorMappingEquivalent(&new_color_provider,
                                                 renderer_color_map));
 }
@@ -119,6 +121,7 @@ TEST_F(ColorProviderUtilsTest, DefaultBl
   ui::ColorProvider random_color_provider;
   ui::ColorMixer& mixer = random_color_provider.AddMixer();
   mixer[ui::kColorPrimaryBackground] = {SK_ColorWHITE};
+  random_color_provider.GenerateColorMap();
   ui::RendererColorMap random_color_map =
       ui::CreateRendererColorMap(random_color_provider);
 
diff -up chromium-126.0.6478.26/ui/color/sys_color_mixer_unittest.cc.mee chromium-126.0.6478.26/ui/color/sys_color_mixer_unittest.cc
--- chromium-126.0.6478.26/ui/color/sys_color_mixer_unittest.cc.mee	2024-05-29 18:02:31.000000000 +0200
+++ chromium-126.0.6478.26/ui/color/sys_color_mixer_unittest.cc	2024-06-03 16:22:10.556568986 +0200
@@ -36,6 +36,7 @@ class SysColorMixerTest
 
     AddRefColorMixer(&color_provider_, key);
     AddSysColorMixer(&color_provider_, key);
+    color_provider_.GenerateColorMap();
   }
 
  protected:
diff -up chromium-126.0.6478.26/ui/native_theme/native_theme_base.cc.mee chromium-126.0.6478.26/ui/native_theme/native_theme_base.cc
--- chromium-126.0.6478.26/ui/native_theme/native_theme_base.cc.mee	2024-05-29 18:02:32.000000000 +0200
+++ chromium-126.0.6478.26/ui/native_theme/native_theme_base.cc	2024-06-03 16:22:10.556568986 +0200
@@ -1763,9 +1763,8 @@ bool NativeThemeBase::IsColorPipelineSup
     ControlColorId color_id) const {
   // Color providers are not yet supported on Android so we need to check that
   // the color_provider is not null here.
-  if (!color_provider || !color_provider->HasMixers()) {
+  if (!color_provider || color_provider->IsColorMapEmpty())
     return false;
-  }
 
   static constexpr auto kControlColorIdsSet =
       base::MakeFixedFlatSet<ControlColorId>({kBorder,
diff -up chromium-126.0.6478.26/ui/native_theme/native_theme_fluent_unittest.cc.mee chromium-126.0.6478.26/ui/native_theme/native_theme_fluent_unittest.cc
--- chromium-126.0.6478.26/ui/native_theme/native_theme_fluent_unittest.cc.mee	2024-05-29 18:02:32.000000000 +0200
+++ chromium-126.0.6478.26/ui/native_theme/native_theme_fluent_unittest.cc	2024-06-03 16:22:10.556568986 +0200
@@ -134,6 +134,7 @@ TEST_P(NativeThemeFluentTest, VerifyArro
 TEST_F(NativeThemeFluentTest, PaintThumbRoundedCorners) {
   cc::RecordPaintCanvas canvas;
   ColorProvider color_provider;
+  color_provider.GenerateColorMap();
   constexpr gfx::Rect kRect(15, 100);
   // `is_web_test` is `false` by default.
   const NativeTheme::ScrollbarThumbExtraParams extra_params;
diff -up chromium-126.0.6478.26/ui/wm/core/shadow_controller_unittest.cc.mee chromium-126.0.6478.26/ui/wm/core/shadow_controller_unittest.cc
--- chromium-126.0.6478.26/ui/wm/core/shadow_controller_unittest.cc.mee	2024-05-29 18:02:32.000000000 +0200
+++ chromium-126.0.6478.26/ui/wm/core/shadow_controller_unittest.cc	2024-06-03 16:22:10.556568986 +0200
@@ -285,6 +285,7 @@ TEST_F(ShadowControllerTest, SetColorsMa
   mixer[ui::kColorShadowValueAmbientShadowElevationTwelve] = {SK_ColorRED};
   mixer[ui::kColorShadowValueKeyShadowElevationTwentyFour] = {SK_ColorGREEN};
   mixer[ui::kColorShadowValueAmbientShadowElevationTwentyFour] = {SK_ColorBLUE};
+  color_provider.GenerateColorMap();
 
   shadow->SetElevationToColorsMap(
       ShadowController::GenerateShadowColorsMap(&color_provider));