blob: e0e0c01bb491507548ed2422f900e3db98cceed3 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/themes/theme_local_data_batch_uploader.h"
#include <variant>
#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/themes/theme_service_utils.h"
#include "chrome/browser/themes/theme_syncable_service.h"
#include "chrome/browser/ui/webui/cr_components/theme_color_picker/customize_chrome_colors.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/features.h"
#include "components/sync/protocol/theme_specifics.pb.h"
#include "components/sync/service/local_data_description.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
std::string BuildTitle(const sync_pb::ThemeSpecifics& specifics) {
if (specifics.use_custom_theme()) {
return specifics.custom_theme_name();
}
if (specifics.has_ntp_background() &&
!specifics.ntp_background().attribution_line_1().empty()) {
return specifics.ntp_background().attribution_line_1();
}
if (specifics.has_grayscale_theme_enabled()) {
return l10n_util::GetStringUTF8(IDS_NTP_CUSTOMIZE_GREY_DEFAULT_LABEL);
}
if (specifics.has_user_color_theme()) {
auto it = std::ranges::find_if(
kDynamicCustomizeChromeColors,
[&](const DynamicColorInfo& dynamic_color) {
return dynamic_color.color == specifics.user_color_theme().color() &&
dynamic_color.variant ==
ProtoEnumToBrowserColorVariant(
specifics.user_color_theme().browser_color_variant());
});
if (it != kDynamicCustomizeChromeColors.end()) {
return l10n_util::GetStringFUTF8(IDS_NTP_COLORS_BATCH_UPLOAD_DESCRIPTION,
l10n_util::GetStringUTF16(it->label_id));
}
}
return l10n_util::GetStringUTF8(IDS_NTP_CUSTOMIZE_COLOR_PICKER_LABEL);
}
} // namespace
// static
const char ThemeLocalDataBatchUploader::kThemesLocalDataItemModelId[] =
"current-theme";
ThemeLocalDataBatchUploader::ThemeLocalDataBatchUploader(
ThemeLocalDataBatchUploaderDelegate* delegate)
: delegate_(delegate) {
CHECK(delegate_);
}
void ThemeLocalDataBatchUploader::GetLocalDataDescription(
base::OnceCallback<void(syncer::LocalDataDescription)> callback) {
syncer::LocalDataDescription desc;
desc.type = syncer::THEMES;
if (!base::FeatureList::IsEnabled(syncer::kThemesBatchUpload)) {
std::move(callback).Run(desc);
return;
}
// Avoid offering batch upload for local default theme.
std::optional<sync_pb::ThemeSpecifics> specifics =
GetNonDefaultSavedLocalTheme();
base::UmaHistogramBoolean("Theme.BatchUpload.HasLocalTheme",
specifics.has_value());
if (specifics.has_value()) {
syncer::LocalDataItemModel item;
item.id = kThemesLocalDataItemModelId;
item.title = BuildTitle(*specifics);
desc.local_data_models.push_back(std::move(item));
}
std::move(callback).Run(std::move(desc));
}
void ThemeLocalDataBatchUploader::TriggerLocalDataMigration() {
CHECK(base::FeatureList::IsEnabled(syncer::kThemesBatchUpload));
// Avoid migrating local default theme.
if (GetNonDefaultSavedLocalTheme()) {
delegate_->ApplySavedLocalThemeIfExistsAndClear();
base::UmaHistogramBoolean("Theme.BatchUpload.LocalThemeMigrationTriggered",
true);
}
}
void ThemeLocalDataBatchUploader::TriggerLocalDataMigrationForItems(
std::vector<syncer::LocalDataItemModel::DataId> items) {
if (items.empty()) {
return;
}
CHECK_EQ(items.size(), 1U);
CHECK_EQ(std::get<std::string>(items[0]), kThemesLocalDataItemModelId);
TriggerLocalDataMigration();
}
std::optional<sync_pb::ThemeSpecifics>
ThemeLocalDataBatchUploader::GetNonDefaultSavedLocalTheme() const {
std::optional<sync_pb::ThemeSpecifics> specifics =
delegate_->GetSavedLocalTheme();
return (specifics && ThemeSyncableService::HasNonDefaultTheme(*specifics))
? specifics
: std::nullopt;
}