color_provider_manager.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/color/color_provider_manager.h"
  5. #include <algorithm>
  6. #include "base/bind.h"
  7. #include "base/check.h"
  8. #include "base/no_destructor.h"
  9. #include "build/build_config.h"
  10. #include "third_party/abseil-cpp/absl/types/optional.h"
  11. #include "ui/color/color_provider.h"
  12. #include "ui/color/color_provider_utils.h"
  13. #if !BUILDFLAG(IS_ANDROID)
  14. #include "ui/color/color_mixers.h"
  15. #endif
  16. namespace ui {
  17. namespace {
  18. // Cache at most 5 ColorProviders to prevent unbounded storage from user_color.
  19. constexpr size_t kCacheSize = 5;
  20. class GlobalManager : public ColorProviderManager {
  21. public:
  22. explicit GlobalManager(size_t cache_size = kCacheSize)
  23. : ColorProviderManager(cache_size) {}
  24. GlobalManager(const GlobalManager&) = delete;
  25. GlobalManager& operator=(const GlobalManager&) = delete;
  26. ~GlobalManager() override = default;
  27. };
  28. static_assert(sizeof(GlobalManager) == sizeof(ColorProviderManager),
  29. "Global manager is intended to provide constructor visibility to "
  30. "absl::optional, nothing more.");
  31. absl::optional<GlobalManager>& GetGlobalManager() {
  32. static base::NoDestructor<absl::optional<GlobalManager>> manager;
  33. return *manager;
  34. }
  35. } // namespace
  36. ColorProviderManager::InitializerSupplier::InitializerSupplier() = default;
  37. ColorProviderManager::InitializerSupplier::~InitializerSupplier() = default;
  38. ColorProviderManager::ThemeInitializerSupplier::ThemeInitializerSupplier(
  39. ThemeType theme_type)
  40. : theme_type_(theme_type) {}
  41. ColorProviderManager::Key::Key()
  42. : Key(ColorMode::kLight,
  43. ContrastMode::kNormal,
  44. SystemTheme::kDefault,
  45. FrameType::kChromium,
  46. absl::nullopt,
  47. nullptr) {}
  48. ColorProviderManager::Key::Key(
  49. ColorMode color_mode,
  50. ContrastMode contrast_mode,
  51. SystemTheme system_theme,
  52. FrameType frame_type,
  53. absl::optional<SkColor> user_color,
  54. scoped_refptr<ThemeInitializerSupplier> custom_theme)
  55. : color_mode(color_mode),
  56. contrast_mode(contrast_mode),
  57. elevation_mode(ElevationMode::kLow),
  58. system_theme(system_theme),
  59. frame_type(frame_type),
  60. user_color(user_color),
  61. custom_theme(std::move(custom_theme)) {}
  62. ColorProviderManager::Key::Key(const Key&) = default;
  63. ColorProviderManager::Key& ColorProviderManager::Key::operator=(const Key&) =
  64. default;
  65. ColorProviderManager::Key::~Key() = default;
  66. ColorProviderManager::ColorProviderManager(size_t cache_size)
  67. : color_providers_(cache_size) {
  68. ResetColorProviderInitializerList();
  69. }
  70. ColorProviderManager::~ColorProviderManager() = default;
  71. // static
  72. ColorProviderManager& ColorProviderManager::Get() {
  73. absl::optional<GlobalManager>& manager = GetGlobalManager();
  74. if (!manager.has_value()) {
  75. manager.emplace();
  76. #if !BUILDFLAG(IS_ANDROID)
  77. manager.value().AppendColorProviderInitializer(
  78. base::BindRepeating(AddColorMixers));
  79. #endif // !BUILDFLAG(IS_ANDROID)
  80. }
  81. return manager.value();
  82. }
  83. // static
  84. ColorProviderManager& ColorProviderManager::GetForTesting(size_t cache_size) {
  85. absl::optional<GlobalManager>& manager = GetGlobalManager();
  86. if (!manager.has_value())
  87. manager.emplace(cache_size);
  88. return manager.value();
  89. }
  90. // static
  91. void ColorProviderManager::ResetForTesting() {
  92. GetGlobalManager().reset();
  93. }
  94. void ColorProviderManager::ResetColorProviderInitializerList() {
  95. ResetColorProviderCache();
  96. initializer_list_ = std::make_unique<ColorProviderInitializerList>();
  97. initializer_subscriptions_.clear();
  98. }
  99. void ColorProviderManager::ResetColorProviderCache() {
  100. if (!color_providers_.empty())
  101. color_providers_.Clear();
  102. }
  103. void ColorProviderManager::AppendColorProviderInitializer(
  104. ColorProviderInitializerList::CallbackType initializer) {
  105. DCHECK(initializer_list_);
  106. ResetColorProviderCache();
  107. initializer_subscriptions_.push_back(
  108. initializer_list_->Add(std::move(initializer)));
  109. }
  110. ColorProvider* ColorProviderManager::GetColorProviderFor(Key key) {
  111. auto iter = color_providers_.Get(key);
  112. if (iter == color_providers_.end()) {
  113. auto provider = std::make_unique<ColorProvider>();
  114. DCHECK(initializer_list_);
  115. if (!initializer_list_->empty())
  116. initializer_list_->Notify(provider.get(), key);
  117. provider->GenerateColorMap();
  118. iter = color_providers_.Put(key, std::move(provider));
  119. }
  120. ColorProvider* provider = iter->second.get();
  121. DCHECK(provider);
  122. return provider;
  123. }
  124. } // namespace ui