blob: 187ac6496735190cfc43e223aaf73dcb7d3a7d64 [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 "base/feature_list.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "chrome/browser/themes/browser_theme_pack.h"
#include "chrome/browser/themes/custom_theme_supplier.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/common/chrome_features.h"
#include "chrome/grit/theme_resources.h"
#include "components/grit/components_scaled_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
#include "ui/native_theme/native_theme.h"
#if BUILDFLAG(IS_LINUX)
#include "ui/linux/linux_ui.h"
#endif
namespace {
using TP = ThemeProperties;
// The default theme if we've gone to the theme gallery and installed the
// "Default" theme. We have to detect this case specifically. (By the time we
// realize we've installed the default theme, we already have an extension
// unpacked on the filesystem.)
constexpr char kDefaultThemeGalleryID[] = "hkacjpbfdknhflllbcmjibkdeoafencn";
} // namespace
const char ThemeHelper::kDefaultThemeID[] = "";
// static
bool ThemeHelper::IsExtensionTheme(const CustomThemeSupplier* theme_supplier) {
return theme_supplier && theme_supplier->get_theme_type() ==
ui::ColorProviderKey::ThemeInitializerSupplier::
ThemeType::kExtension;
}
// static
bool ThemeHelper::IsAutogeneratedTheme(
const CustomThemeSupplier* theme_supplier) {
return theme_supplier && theme_supplier->get_theme_type() ==
ui::ColorProviderKey::ThemeInitializerSupplier::
ThemeType::kAutogenerated;
}
// static
bool ThemeHelper::IsDefaultTheme(const CustomThemeSupplier* theme_supplier) {
if (!theme_supplier) {
return true;
}
using Type = ui::ColorProviderKey::ThemeInitializerSupplier::ThemeType;
if (theme_supplier->get_theme_type() != Type::kExtension) {
return false;
}
const std::string& id = theme_supplier->extension_id();
return id == kDefaultThemeID || id == kDefaultThemeGalleryID;
}
// static
bool ThemeHelper::IsCustomTheme(const CustomThemeSupplier* theme_supplier) {
return IsExtensionTheme(theme_supplier) ||
IsAutogeneratedTheme(theme_supplier);
}
// static
bool ThemeHelper::HasCustomImage(int id,
const CustomThemeSupplier* theme_supplier) {
return BrowserThemePack::IsPersistentImageID(id) && theme_supplier &&
theme_supplier->HasCustomImage(id);
}
ThemeHelper::ThemeHelper() = default;
ThemeHelper::~ThemeHelper() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
int ThemeHelper::GetDisplayProperty(
int id,
const CustomThemeSupplier* theme_supplier) const {
int result = 0;
if (theme_supplier && theme_supplier->GetDisplayProperty(id, &result)) {
return result;
}
return GetDefaultDisplayProperty(id);
}
base::RefCountedMemory* ThemeHelper::GetRawData(
int id,
const CustomThemeSupplier* theme_supplier,
ui::ResourceScaleFactor scale_factor) const {
// Check to see whether we should substitute some images.
int ntp_alternate =
GetDisplayProperty(TP::NTP_LOGO_ALTERNATE, theme_supplier);
if (id == IDR_PRODUCT_LOGO && ntp_alternate != 0) {
id = IDR_PRODUCT_LOGO_WHITE;
}
base::RefCountedMemory* data = nullptr;
if (theme_supplier) {
data = theme_supplier->GetRawData(id, scale_factor);
}
if (!data) {
data =
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
id, ui::k100Percent);
}
return data;
}
color_utils::HSL ThemeHelper::GetTint(
int id,
bool incognito,
const CustomThemeSupplier* theme_supplier) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
color_utils::HSL hsl;
if (theme_supplier && theme_supplier->GetTint(id, &hsl)) {
return hsl;
}
return TP::GetDefaultTint(id, incognito, UseDarkModeColors(theme_supplier));
}
gfx::ImageSkia* ThemeHelper::GetImageSkiaNamed(
int id,
bool incognito,
const CustomThemeSupplier* theme_supplier) const {
gfx::Image image = GetImageNamed(id, incognito, theme_supplier);
if (image.IsEmpty()) {
return nullptr;
}
// TODO(pkotwicz): Remove this const cast. The gfx::Image interface returns
// its images const. GetImageSkiaNamed() also should but has many callsites.
return const_cast<gfx::ImageSkia*>(image.ToImageSkia());
}
bool ThemeHelper::ShouldUseNativeFrame(
const CustomThemeSupplier* theme_supplier) const {
return false;
}
int ThemeHelper::GetDefaultDisplayProperty(int id) const {
switch (id) {
case TP::NTP_BACKGROUND_ALIGNMENT:
return TP::ALIGN_CENTER;
case TP::NTP_BACKGROUND_TILING:
return TP::NO_REPEAT;
case TP::NTP_LOGO_ALTERNATE:
return 0;
case TP::SHOULD_FILL_BACKGROUND_TAB_COLOR:
return 1;
default:
return -1;
}
}
// static
bool ThemeHelper::UseDarkModeColors(const CustomThemeSupplier* theme_supplier) {
// Dark mode is disabled for custom themes so they apply atop a predictable
// state.
return !IsCustomTheme(theme_supplier) &&
theme_supplier->GetNativeTheme()->preferred_color_scheme() ==
ui::NativeTheme::PreferredColorScheme::kDark;
}
gfx::Image ThemeHelper::GetImageNamed(
int id,
bool incognito,
const CustomThemeSupplier* theme_supplier) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
int adjusted_id = id;
if (incognito) {
if (id == IDR_THEME_FRAME) {
adjusted_id = IDR_THEME_FRAME_INCOGNITO;
} else if (id == IDR_THEME_FRAME_INACTIVE) {
adjusted_id = IDR_THEME_FRAME_INCOGNITO_INACTIVE;
}
}
gfx::Image image;
if (theme_supplier) {
image = theme_supplier->GetImageNamed(adjusted_id);
}
if (image.IsEmpty()) {
image = ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
adjusted_id);
}
return image;
}