blob: a0933fab3503745af37cc255af6ee2b7ea849a9d [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/color/color_provider_manager.h"
#include <algorithm>
#include <optional>
#include <utility>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/timer/elapsed_timer.h"
#include "build/build_config.h"
#include "ui/color/color_metrics.h"
#include "ui/color/color_provider.h"
#include "ui/color/color_provider_key.h"
#include "ui/color/color_provider_utils.h"
#if !BUILDFLAG(IS_ANDROID)
#include "ui/color/color_mixers.h"
#endif
namespace ui {
namespace {
class GlobalManager : public ColorProviderManager {
public:
GlobalManager() = default;
GlobalManager(const GlobalManager&) = delete;
GlobalManager& operator=(const GlobalManager&) = delete;
~GlobalManager() override = default;
};
static_assert(sizeof(GlobalManager) == sizeof(ColorProviderManager),
"Global manager is intended to provide constructor visibility to "
"std::optional, nothing more.");
std::optional<GlobalManager>& GetGlobalManager() {
static base::NoDestructor<std::optional<GlobalManager>> manager;
return *manager;
}
} // namespace
ColorProviderManager::ColorProviderManager() {
ResetColorProviderInitializerList();
}
ColorProviderManager::~ColorProviderManager() = default;
// static
ColorProviderManager& ColorProviderManager::Get() {
std::optional<GlobalManager>& manager = GetGlobalManager();
if (!manager.has_value()) {
manager.emplace();
#if !BUILDFLAG(IS_ANDROID)
manager.value().AppendColorProviderInitializer(
base::BindRepeating(AddColorMixers));
#endif // !BUILDFLAG(IS_ANDROID)
}
return manager.value();
}
// static
ColorProviderManager& ColorProviderManager::GetForTesting() {
std::optional<GlobalManager>& manager = GetGlobalManager();
if (!manager.has_value())
manager.emplace();
return manager.value();
}
// static
void ColorProviderManager::ResetForTesting() {
GetGlobalManager().reset();
}
void ColorProviderManager::ResetColorProviderInitializerList() {
ResetColorProviderCache();
initializer_list_ = std::make_unique<ColorProviderInitializerList>();
initializer_subscriptions_.clear();
}
void ColorProviderManager::ResetColorProviderCache() {
if (!color_providers_.empty())
color_providers_.clear();
}
void ColorProviderManager::AppendColorProviderInitializer(
ColorProviderInitializerList::CallbackType initializer) {
DCHECK(initializer_list_);
ResetColorProviderCache();
initializer_subscriptions_.push_back(
initializer_list_->Add(std::move(initializer)));
}
ColorProvider* ColorProviderManager::GetColorProviderFor(ColorProviderKey key) {
auto iter = color_providers_.find(key);
if (iter == color_providers_.end()) {
base::ElapsedTimer timer;
auto provider = std::make_unique<ColorProvider>();
DCHECK(initializer_list_);
if (!initializer_list_->empty())
initializer_list_->Notify(provider.get(), key);
provider->GenerateColorMap();
RecordTimeSpentInitializingColorProvider(timer.Elapsed());
++num_providers_initialized_;
iter = color_providers_.emplace(key, std::move(provider)).first;
RecordColorProviderCacheSize(static_cast<int>(color_providers_.size()));
}
ColorProvider* provider = iter->second.get();
DCHECK(provider);
return provider;
}
} // namespace ui