blob: 1f9b069f431157456389b75875f9c640a0f004cd [file]
// Copyright 2026 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/sync/cross_device_theme_tracker_factory.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_selections.h"
#include "chrome/browser/sync/data_type_store_service_factory.h"
#include "chrome/browser/sync/device_info_sync_service_factory.h"
#include "chrome/common/channel_info.h"
#include "components/sync/base/report_unrecoverable_error.h"
#include "components/sync/model/client_tag_based_data_type_processor.h"
#include "components/sync/model/data_type_store_service.h"
#include "components/sync_device_info/device_info_sync_service.h"
#include "components/themes/cross_device/cross_device_theme_sync_bridge.h"
#include "components/themes/cross_device/features.h"
#include "components/themes/cross_device/theme_translation.h"
#if BUILDFLAG(IS_ANDROID)
#include "chrome/browser/sync/cross_device_theme_tracker_android.h"
#endif
namespace {
template <typename RemoteSpecifics, typename LocalSpecifics>
void RegisterBridgeHelper(
syncer::DataType type,
base::RepeatingCallback<themes::DeviceThemeInfo<LocalSpecifics>(
const RemoteSpecifics&)> translate_cb,
themes::CrossDeviceThemeTracker<LocalSpecifics>* tracker,
syncer::DataTypeStoreService* store_service,
version_info::Channel channel) {
syncer::RepeatingDataTypeStoreFactory store_factory =
store_service->GetStoreFactory();
auto processor = std::make_unique<syncer::ClientTagBasedDataTypeProcessor>(
type, base::BindRepeating(&syncer::ReportUnrecoverableError, channel));
auto bridge = std::make_unique<
themes::CrossDeviceThemeSyncBridge<RemoteSpecifics, LocalSpecifics>>(
type, std::move(translate_cb),
base::BindRepeating(
&themes::CrossDeviceThemeTracker<LocalSpecifics>::UpdateThemeInfo,
base::Unretained(tracker)),
base::BindRepeating(
&themes::CrossDeviceThemeTracker<LocalSpecifics>::RemoveThemeInfo,
base::Unretained(tracker)),
base::BindRepeating(
&themes::CrossDeviceThemeTracker<LocalSpecifics>::OnBridgeSyncStarted,
base::Unretained(tracker), type),
base::BindRepeating(&themes::CrossDeviceThemeTracker<
LocalSpecifics>::OnBridgeSyncDisabled,
base::Unretained(tracker), type),
std::move(processor), store_factory);
tracker->RegisterBridge(type, std::move(bridge));
}
} // namespace
// static
themes::CrossDeviceThemeTracker<
CrossDeviceThemeTrackerFactory::LocalThemeSpecifics>*
CrossDeviceThemeTrackerFactory::GetForProfile(Profile* profile) {
return static_cast<themes::CrossDeviceThemeTracker<LocalThemeSpecifics>*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
CrossDeviceThemeTrackerFactory* CrossDeviceThemeTrackerFactory::GetInstance() {
static base::NoDestructor<CrossDeviceThemeTrackerFactory> instance;
return instance.get();
}
CrossDeviceThemeTrackerFactory::CrossDeviceThemeTrackerFactory()
: ProfileKeyedServiceFactory(
"CrossDeviceThemeTracker",
ProfileSelections::Builder()
.WithRegular(ProfileSelection::kOriginalOnly)
.WithGuest(ProfileSelection::kOriginalOnly)
.Build()) {
DependsOn(DeviceInfoSyncServiceFactory::GetInstance());
DependsOn(DataTypeStoreServiceFactory::GetInstance());
}
CrossDeviceThemeTrackerFactory::~CrossDeviceThemeTrackerFactory() = default;
std::unique_ptr<KeyedService>
CrossDeviceThemeTrackerFactory::BuildServiceInstanceForBrowserContext(
content::BrowserContext* context) const {
if (!base::FeatureList::IsEnabled(themes::kCrossDeviceThemeTracker)) {
return nullptr;
}
Profile* profile = Profile::FromBrowserContext(context);
syncer::DeviceInfoSyncService* device_info_sync_service =
DeviceInfoSyncServiceFactory::GetForProfile(profile);
syncer::DeviceInfoTracker* device_info_tracker =
device_info_sync_service
? device_info_sync_service->GetDeviceInfoTracker()
: nullptr;
syncer::DataTypeStoreService* store_service =
DataTypeStoreServiceFactory::GetForProfile(profile);
version_info::Channel channel = chrome::GetChannel();
#if BUILDFLAG(IS_ANDROID)
auto tracker = std::make_unique<themes::CrossDeviceThemeTrackerAndroid>(
device_info_tracker);
#else
auto tracker =
std::make_unique<themes::CrossDeviceThemeTracker<LocalThemeSpecifics>>(
device_info_tracker);
#endif
#if BUILDFLAG(IS_ANDROID)
// Construct Desktop bridge.
RegisterBridgeHelper<sync_pb::ThemeSpecifics, LocalThemeSpecifics>(
syncer::THEMES, base::BindRepeating(&themes::TranslateDesktop),
tracker.get(), store_service, channel);
#else
// Construct Android bridge.
RegisterBridgeHelper<sync_pb::ThemeAndroidSpecifics, LocalThemeSpecifics>(
syncer::THEMES_ANDROID, base::BindRepeating(&themes::TranslateAndroid),
tracker.get(), store_service, channel);
#endif
// Construct iOS bridge.
RegisterBridgeHelper<sync_pb::ThemeIosSpecifics, LocalThemeSpecifics>(
syncer::THEMES_IOS, base::BindRepeating(&themes::TranslateIos),
tracker.get(), store_service, channel);
return tracker;
}