| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/browser_sync/common_controller_builder.h" |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/feature_list.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/task/task_traits.h" |
| #include "base/task/thread_pool.h" |
| #include "components/autofill/core/browser/payments/autofill_wallet_data_type_controller.h" |
| #include "components/autofill/core/browser/webdata/addresses/autofill_profile_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/addresses/contact_info_data_type_controller.h" |
| #include "components/autofill/core/browser/webdata/addresses/contact_info_local_data_batch_uploader.h" |
| #include "components/autofill/core/browser/webdata/addresses/contact_info_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/autocomplete/autocomplete_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" |
| #include "components/autofill/core/browser/webdata/payments/autofill_wallet_credential_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/payments/autofill_wallet_metadata_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/payments/autofill_wallet_offer_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/payments/autofill_wallet_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/payments/autofill_wallet_usage_data_sync_bridge.h" |
| #include "components/autofill/core/browser/webdata/valuables/valuable_data_type_controller.h" |
| #include "components/autofill/core/browser/webdata/valuables/valuable_sync_bridge.h" |
| #include "components/collaboration/public/collaboration_service.h" |
| #include "components/collaboration/public/data_type_controller/collaboration_group_data_type_controller.h" |
| #include "components/collaboration/public/data_type_controller/shared_tab_group_account_data_type_controller.h" |
| #include "components/collaboration/public/data_type_controller/shared_tab_group_data_type_controller.h" |
| #include "components/commerce/core/commerce_feature_list.h" |
| #include "components/commerce/core/product_specifications/product_specifications_service.h" |
| #include "components/consent_auditor/consent_auditor.h" |
| #include "components/data_sharing/public/data_sharing_service.h" |
| #include "components/data_sharing/public/features.h" |
| #include "components/history/core/browser/sync/history_data_type_controller.h" |
| #include "components/history/core/browser/sync/history_delete_directives_data_type_controller.h" |
| #include "components/password_manager/core/browser/password_store/password_store_interface.h" |
| #include "components/password_manager/core/browser/sharing/incoming_password_sharing_invitation_data_type_controller.h" |
| #include "components/password_manager/core/browser/sharing/outgoing_password_sharing_invitation_data_type_controller.h" |
| #include "components/password_manager/core/browser/sharing/password_receiver_service.h" |
| #include "components/password_manager/core/browser/sharing/password_sender_service.h" |
| #include "components/password_manager/core/browser/sync/password_data_type_controller.h" |
| #include "components/password_manager/core/browser/sync/password_local_data_batch_uploader.h" |
| #include "components/plus_addresses/settings/plus_address_setting_service.h" |
| #include "components/plus_addresses/sync_utils/plus_address_data_type_controller.h" |
| #include "components/plus_addresses/webdata/plus_address_webdata_service.h" |
| #include "components/power_bookmarks/core/power_bookmark_features.h" |
| #include "components/power_bookmarks/core/power_bookmark_service.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/reading_list/core/dual_reading_list_model.h" |
| #include "components/reading_list/core/reading_list_local_data_batch_uploader.h" |
| #include "components/saved_tab_groups/public/tab_group_sync_service.h" |
| #include "components/search_engines/template_url_service.h" |
| #include "components/send_tab_to_self/send_tab_to_self_data_type_controller.h" |
| #include "components/send_tab_to_self/send_tab_to_self_sync_service.h" |
| #include "components/sharing_message/sharing_message_bridge.h" |
| #include "components/sharing_message/sharing_message_data_type_controller.h" |
| #include "components/signin/public/base/signin_switches.h" |
| #include "components/sync/base/data_type.h" |
| #include "components/sync/base/features.h" |
| #include "components/sync/base/report_unrecoverable_error.h" |
| #include "components/sync/model/forwarding_data_type_controller_delegate.h" |
| #include "components/sync/model/proxy_data_type_controller_delegate.h" |
| #include "components/sync/service/data_type_controller.h" |
| #include "components/sync_bookmarks/bookmark_data_type_controller.h" |
| #include "components/sync_bookmarks/bookmark_local_data_batch_uploader.h" |
| #include "components/sync_bookmarks/bookmark_sync_service.h" |
| #include "components/sync_device_info/device_info_sync_service.h" |
| #include "components/sync_preferences/pref_service_syncable.h" |
| #include "components/sync_sessions/session_data_type_controller.h" |
| #include "components/sync_sessions/session_sync_service.h" |
| #include "components/sync_user_events/user_event_data_type_controller.h" |
| #include "components/sync_user_events/user_event_service.h" |
| #include "components/variations/service/google_groups_manager.h" |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| #include "components/webauthn/core/browser/passkey_data_type_controller.h" |
| #include "components/webauthn/core/browser/passkey_model.h" |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| #if BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| #include "components/supervised_user/core/browser/supervised_user_settings_data_type_controller.h" |
| #include "components/supervised_user/core/browser/supervised_user_settings_service.h" |
| #endif // BUILDFLAG(ENABLE_SUPERVISED_USER) |
| |
| namespace browser_sync { |
| |
| namespace { |
| |
| using syncer::DataTypeController; |
| using syncer::SyncableServiceBasedDataTypeController; |
| |
| // These helper functions only wrap the factory functions of the bridges. This |
| // way, it simplifies life for the compiler which cannot directly cast |
| // "WeakPtr<DataTypeSyncBridge> (AutofillWebDataService*)" to |
| // "WeakPtr<DataTypeControllerDelegate> (AutofillWebDataService*)". |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutocompleteDelegateFromDataService(autofill::AutofillWebDataService* service) { |
| return autofill::AutocompleteSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| #if !BUILDFLAG(IS_IOS) |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillLoyaltyCardDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::ValuableSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| #endif |
| |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillProfileDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::AutofillProfileSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillWalletCredentialDataDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::AutofillWalletCredentialSyncBridge::FromWebDataService( |
| service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillWalletDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::AutofillWalletSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillWalletMetadataDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::AutofillWalletMetadataSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillWalletOfferDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::AutofillWalletOfferSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| #if !BUILDFLAG(IS_IOS) |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| AutofillWalletUsageDataDelegateFromDataService( |
| autofill::AutofillWebDataService* service) { |
| return autofill::AutofillWalletUsageDataSyncBridge::FromWebDataService( |
| service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| #endif |
| |
| base::WeakPtr<syncer::DataTypeControllerDelegate> |
| ContactInfoDelegateFromDataService(autofill::AutofillWebDataService* service) { |
| return autofill::ContactInfoSyncBridge::FromWebDataService(service) |
| ->change_processor() |
| ->GetControllerDelegate(); |
| } |
| |
| // Helper function that deals will null (e.g. tests, iOS webview). |
| base::WeakPtr<syncer::SyncableService> SyncableServiceForPrefs( |
| sync_preferences::PrefServiceSyncable* prefs_service, |
| syncer::DataType type) { |
| return prefs_service ? prefs_service->GetSyncableService(type)->AsWeakPtr() |
| : nullptr; |
| } |
| |
| bool ArePreferencesAllowedInTransportMode() { |
| if (!base::FeatureList::IsEnabled( |
| switches::kEnablePreferencesAccountStorage)) { |
| return false; |
| } |
| #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) |
| return base::FeatureList::IsEnabled( |
| syncer::kReplaceSyncPromosWithSignInPromos); |
| #else |
| return true; |
| #endif |
| } |
| |
| } // namespace |
| |
| CommonControllerBuilder::CommonControllerBuilder() = default; |
| |
| CommonControllerBuilder::~CommonControllerBuilder() = default; |
| |
| void CommonControllerBuilder::SetAddressDataManagerGetter( |
| base::RepeatingCallback<autofill::AddressDataManager*()> |
| address_data_manager_getter) { |
| address_data_manager_getter_ = std::move(address_data_manager_getter); |
| } |
| |
| void CommonControllerBuilder::SetAutofillWebDataService( |
| const scoped_refptr<base::SequencedTaskRunner>& ui_thread, |
| const scoped_refptr<autofill::AutofillWebDataService>& |
| web_data_service_on_disk, |
| const scoped_refptr<autofill::AutofillWebDataService>& |
| web_data_service_in_memory) { |
| autofill_web_data_ui_thread_.Set(ui_thread); |
| profile_autofill_web_data_service_.Set(web_data_service_on_disk); |
| account_autofill_web_data_service_.Set(web_data_service_in_memory); |
| } |
| |
| void CommonControllerBuilder::SetBookmarkModel( |
| bookmarks::BookmarkModel* bookmark_model) { |
| bookmark_model_.Set(bookmark_model); |
| } |
| |
| void CommonControllerBuilder::SetBookmarkSyncService( |
| sync_bookmarks::BookmarkSyncService* |
| local_or_syncable_bookmark_sync_service, |
| sync_bookmarks::BookmarkSyncService* account_bookmark_sync_service) { |
| local_or_syncable_bookmark_sync_service_.Set( |
| local_or_syncable_bookmark_sync_service); |
| account_bookmark_sync_service_.Set(account_bookmark_sync_service); |
| } |
| |
| void CommonControllerBuilder::SetConsentAuditor( |
| consent_auditor::ConsentAuditor* consent_auditor) { |
| consent_auditor_.Set(consent_auditor); |
| } |
| |
| void CommonControllerBuilder::SetCollaborationService( |
| collaboration::CollaborationService* collaboration_service) { |
| collaboration_service_.Set(collaboration_service); |
| } |
| |
| void CommonControllerBuilder::SetDataSharingService( |
| data_sharing::DataSharingService* data_sharing_service) { |
| data_sharing_service_.Set(data_sharing_service); |
| } |
| |
| void CommonControllerBuilder::SetDeviceInfoSyncService( |
| syncer::DeviceInfoSyncService* device_info_sync_service) { |
| device_info_sync_service_.Set(device_info_sync_service); |
| } |
| |
| void CommonControllerBuilder::SetFaviconService( |
| favicon::FaviconService* favicon_service) { |
| favicon_service_.Set(favicon_service); |
| } |
| |
| void CommonControllerBuilder::SetGoogleGroupsManager( |
| GoogleGroupsManager* google_groups_manager) { |
| google_groups_manager_.Set(google_groups_manager); |
| } |
| |
| void CommonControllerBuilder::SetHistoryService( |
| history::HistoryService* history_service) { |
| history_service_.Set(history_service); |
| } |
| |
| void CommonControllerBuilder::SetIdentityManager( |
| signin::IdentityManager* identity_manager) { |
| identity_manager_.Set(identity_manager); |
| } |
| |
| void CommonControllerBuilder::SetDataTypeStoreService( |
| syncer::DataTypeStoreService* data_type_store_service) { |
| data_type_store_service_.Set(data_type_store_service); |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| void CommonControllerBuilder::SetPasskeyModel( |
| webauthn::PasskeyModel* passkey_model) { |
| passkey_model_.Set(passkey_model); |
| } |
| #endif // !BUILDFLAG(IS_ANDROID) |
| |
| void CommonControllerBuilder::SetPasswordReceiverService( |
| password_manager::PasswordReceiverService* password_receiver_service) { |
| password_receiver_service_.Set(password_receiver_service); |
| } |
| |
| void CommonControllerBuilder::SetPasswordSenderService( |
| password_manager::PasswordSenderService* password_sender_service) { |
| password_sender_service_.Set(password_sender_service); |
| } |
| |
| void CommonControllerBuilder::SetPasswordStore( |
| const scoped_refptr<password_manager::PasswordStoreInterface>& |
| profile_password_store, |
| const scoped_refptr<password_manager::PasswordStoreInterface>& |
| account_password_store) { |
| profile_password_store_.Set(profile_password_store); |
| account_password_store_.Set(account_password_store); |
| } |
| |
| void CommonControllerBuilder::SetPlusAddressServices( |
| plus_addresses::PlusAddressSettingService* plus_address_setting_service, |
| const scoped_refptr<plus_addresses::PlusAddressWebDataService>& |
| plus_address_webdata_service) { |
| plus_address_setting_service_.Set(plus_address_setting_service); |
| plus_address_webdata_service_.Set(plus_address_webdata_service); |
| } |
| |
| void CommonControllerBuilder::SetPowerBookmarkService( |
| power_bookmarks::PowerBookmarkService* power_bookmark_service) { |
| power_bookmark_service_.Set(power_bookmark_service); |
| } |
| |
| void CommonControllerBuilder::SetPrefService(PrefService* pref_service) { |
| pref_service_.Set(pref_service); |
| } |
| |
| void CommonControllerBuilder::SetPrefServiceSyncable( |
| sync_preferences::PrefServiceSyncable* pref_service_syncable) { |
| pref_service_syncable_.Set(pref_service_syncable); |
| } |
| |
| void CommonControllerBuilder::SetProductSpecificationsService( |
| commerce::ProductSpecificationsService* product_specifications_service) { |
| product_specifications_service_.Set(product_specifications_service); |
| } |
| |
| void CommonControllerBuilder::SetDualReadingListModel( |
| reading_list::DualReadingListModel* dual_reading_list_model) { |
| dual_reading_list_model_.Set(dual_reading_list_model); |
| } |
| |
| void CommonControllerBuilder::SetSendTabToSelfSyncService( |
| send_tab_to_self::SendTabToSelfSyncService* send_tab_to_self_sync_service) { |
| send_tab_to_self_sync_service_.Set(send_tab_to_self_sync_service); |
| } |
| |
| void CommonControllerBuilder::SetSessionSyncService( |
| sync_sessions::SessionSyncService* session_sync_service) { |
| session_sync_service_.Set(session_sync_service); |
| } |
| |
| void CommonControllerBuilder::SetSharingMessageBridge( |
| SharingMessageBridge* sharing_message_bridge) { |
| sharing_message_bridge_.Set(sharing_message_bridge); |
| } |
| |
| #if BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| void CommonControllerBuilder::SetSupervisedUserSettingsService( |
| supervised_user::SupervisedUserSettingsService* |
| supervised_user_settings_service) { |
| supervised_user_settings_service_.Set(supervised_user_settings_service); |
| } |
| #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| |
| void CommonControllerBuilder::SetTabGroupSyncService( |
| tab_groups::TabGroupSyncService* tab_group_sync_service) { |
| tab_group_sync_service_.Set(tab_group_sync_service); |
| } |
| |
| void CommonControllerBuilder::SetTemplateURLService( |
| TemplateURLService* template_url_service) { |
| template_url_service_.Set(template_url_service); |
| } |
| |
| void CommonControllerBuilder::SetUserEventService( |
| syncer::UserEventService* user_event_service) { |
| user_event_service_.Set(user_event_service); |
| } |
| |
| std::vector<std::unique_ptr<syncer::DataTypeController>> |
| CommonControllerBuilder::Build(syncer::DataTypeSet disabled_types, |
| syncer::SyncService* sync_service, |
| version_info::Channel channel) { |
| std::vector<std::unique_ptr<syncer::DataTypeController>> controllers; |
| |
| const base::RepeatingClosure dump_stack = |
| base::BindRepeating(&syncer::ReportUnrecoverableError, channel); |
| |
| // Same delegate for full-sync or transport mode. |
| controllers.push_back(std::make_unique<DataTypeController>( |
| syncer::DEVICE_INFO, |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| device_info_sync_service_.value()->GetControllerDelegate().get()), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| device_info_sync_service_.value()->GetControllerDelegate().get()))); |
| |
| // These features are enabled only if there's a web data service on disk. |
| if (profile_autofill_web_data_service_.value()) { |
| if (!disabled_types.Has(syncer::AUTOFILL)) { |
| // Note: Transport mode is not and will not be supported. |
| controllers.push_back(std::make_unique<DataTypeController>( |
| syncer::AUTOFILL, |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| profile_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| &AutocompleteDelegateFromDataService, |
| base::RetainedRef( |
| profile_autofill_web_data_service_.value()))), |
| /*delegate_for_transport_mode=*/nullptr)); |
| } |
| |
| if (!disabled_types.Has(syncer::AUTOFILL_PROFILE)) { |
| // Note: Transport mode is not and will not be supported - support is |
| // coming via CONTACT_INFO instead. |
| controllers.push_back(std::make_unique<syncer::DataTypeController>( |
| syncer::AUTOFILL_PROFILE, |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| profile_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| &AutofillProfileDelegateFromDataService, |
| base::RetainedRef( |
| profile_autofill_web_data_service_.value()))), |
| /*delegate_for_transport_mode=*/nullptr)); |
| } |
| |
| if (!disabled_types.Has(syncer::CONTACT_INFO)) { |
| // The same delegate is used for full sync and transport mode. |
| controllers.push_back( |
| std::make_unique<autofill::ContactInfoDataTypeController>( |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| profile_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| &ContactInfoDelegateFromDataService, |
| base::RetainedRef( |
| profile_autofill_web_data_service_.value()))), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| profile_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| &ContactInfoDelegateFromDataService, |
| base::RetainedRef( |
| profile_autofill_web_data_service_.value()))), |
| sync_service, identity_manager_.value(), |
| std::make_unique<autofill::ContactInfoLocalDataBatchUploader>( |
| std::move(address_data_manager_getter_)))); |
| } |
| |
| if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA)) { |
| controllers.push_back(CreateWalletDataTypeController( |
| syncer::AUTOFILL_WALLET_DATA, |
| base::BindRepeating(&AutofillWalletDelegateFromDataService), |
| sync_service, /*with_transport_mode_support=*/true)); |
| } |
| |
| // Wallet metadata sync depends on Wallet data sync. |
| if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) && |
| !disabled_types.Has(syncer::AUTOFILL_WALLET_METADATA)) { |
| controllers.push_back(CreateWalletDataTypeController( |
| syncer::AUTOFILL_WALLET_METADATA, |
| base::BindRepeating(&AutofillWalletMetadataDelegateFromDataService), |
| sync_service, /*with_transport_mode_support=*/ |
| base::FeatureList::IsEnabled( |
| syncer::kReplaceSyncPromosWithSignInPromos))); |
| } |
| |
| // Wallet offer sync depends on Wallet data sync. |
| if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) && |
| !disabled_types.Has(syncer::AUTOFILL_WALLET_OFFER)) { |
| controllers.push_back(CreateWalletDataTypeController( |
| syncer::AUTOFILL_WALLET_OFFER, |
| base::BindRepeating(&AutofillWalletOfferDelegateFromDataService), |
| sync_service, /*with_transport_mode_support=*/ |
| base::FeatureList::IsEnabled( |
| syncer::kReplaceSyncPromosWithSignInPromos))); |
| } |
| |
| // Wallet usage data sync depends on Wallet data sync. |
| #if !BUILDFLAG(IS_IOS) |
| if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) && |
| !disabled_types.Has(syncer::AUTOFILL_WALLET_USAGE)) { |
| controllers.push_back(CreateWalletDataTypeController( |
| syncer::AUTOFILL_WALLET_USAGE, |
| base::BindRepeating(&AutofillWalletUsageDataDelegateFromDataService), |
| sync_service, /*with_transport_mode_support=*/true)); |
| } |
| #endif |
| |
| // Wallet credential data sync depends on Wallet data sync. |
| if (base::FeatureList::IsEnabled( |
| syncer::kSyncAutofillWalletCredentialData) && |
| !disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) && |
| !disabled_types.Has(syncer::AUTOFILL_WALLET_CREDENTIAL)) { |
| controllers.push_back(CreateWalletDataTypeController( |
| syncer::AUTOFILL_WALLET_CREDENTIAL, |
| base::BindRepeating( |
| &AutofillWalletCredentialDataDelegateFromDataService), |
| sync_service, /*with_transport_mode_support=*/true)); |
| } |
| } |
| |
| if (!disabled_types.Has(syncer::BOOKMARKS)) { |
| // Services can be null in tests. |
| if (local_or_syncable_bookmark_sync_service_.value() && |
| favicon_service_.value()) { |
| auto full_mode_delegate = |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| local_or_syncable_bookmark_sync_service_.value() |
| ->GetBookmarkSyncControllerDelegate(favicon_service_.value()) |
| .get()); |
| auto transport_mode_delegate = |
| account_bookmark_sync_service_.value() |
| ? std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| account_bookmark_sync_service_.value() |
| ->GetBookmarkSyncControllerDelegate( |
| favicon_service_.value()) |
| .get()) |
| : nullptr; |
| controllers.push_back( |
| std::make_unique<sync_bookmarks::BookmarkDataTypeController>( |
| std::move(full_mode_delegate), std::move(transport_mode_delegate), |
| std::make_unique<sync_bookmarks::BookmarkLocalDataBatchUploader>( |
| bookmark_model_.value(), pref_service_.value()))); |
| } |
| |
| if (!disabled_types.Has(syncer::POWER_BOOKMARK) && |
| power_bookmark_service_.value() && |
| base::FeatureList::IsEnabled(power_bookmarks::kPowerBookmarkBackend)) { |
| // TODO(crbug.com/40261319): Support transport mode for POWER_BOOKMARK. |
| controllers.push_back(std::make_unique<DataTypeController>( |
| syncer::POWER_BOOKMARK, |
| power_bookmark_service_.value()->CreateSyncControllerDelegate(), |
| /*delegate_for_transport_mode=*/nullptr)); |
| } |
| } |
| |
| if (!disabled_types.Has(syncer::PRODUCT_COMPARISON) && |
| product_specifications_service_.value() && |
| base::FeatureList::IsEnabled(commerce::kProductSpecifications)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| product_specifications_service_.value() |
| ->GetSyncControllerDelegate() |
| .get(); |
| controllers.push_back(std::make_unique<DataTypeController>( |
| syncer::PRODUCT_COMPARISON, |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode= */ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate))); |
| } |
| |
| if (!disabled_types.Has(syncer::HISTORY)) { |
| controllers.push_back(std::make_unique<history::HistoryDataTypeController>( |
| sync_service, identity_manager_.value(), history_service_.value(), |
| pref_service_.value())); |
| } |
| |
| if (!disabled_types.Has(syncer::HISTORY_DELETE_DIRECTIVES)) { |
| controllers.push_back( |
| std::make_unique<history::HistoryDeleteDirectivesDataTypeController>( |
| dump_stack, sync_service, data_type_store_service_.value(), |
| history_service_.value(), pref_service_.value())); |
| } |
| |
| if (!disabled_types.Has(syncer::SESSIONS)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| session_sync_service_.value()->GetControllerDelegate().get(); |
| auto full_sync_mode_delegate = |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate); |
| auto transport_mode_delegate = |
| base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) |
| ? std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate) |
| : nullptr; |
| controllers.push_back( |
| std::make_unique<sync_sessions::SessionDataTypeController>( |
| sync_service, pref_service_.value(), |
| std::move(full_sync_mode_delegate), |
| std::move(transport_mode_delegate))); |
| } |
| |
| if (!disabled_types.Has(syncer::PASSWORDS)) { |
| if (profile_password_store_.value()) { |
| // |profile_password_store_| can be null in tests. |
| controllers.push_back(std::make_unique< |
| password_manager::PasswordDataTypeController>( |
| profile_password_store_.value()->CreateSyncControllerDelegate(), |
| account_password_store_.value() |
| ? account_password_store_.value()->CreateSyncControllerDelegate() |
| : nullptr, |
| std::make_unique<password_manager::PasswordLocalDataBatchUploader>( |
| profile_password_store_.value(), |
| account_password_store_.value()))); |
| |
| // Couple password sharing invitations with password data type. |
| if (!disabled_types.Has(syncer::INCOMING_PASSWORD_SHARING_INVITATION) && |
| password_receiver_service_.value()) { |
| controllers.push_back( |
| std::make_unique< |
| password_manager:: |
| IncomingPasswordSharingInvitationDataTypeController>( |
| sync_service, password_receiver_service_.value(), |
| pref_service_.value())); |
| } |
| |
| if (!disabled_types.Has(syncer::OUTGOING_PASSWORD_SHARING_INVITATION) && |
| password_sender_service_.value()) { |
| controllers.push_back( |
| std::make_unique< |
| password_manager:: |
| OutgoingPasswordSharingInvitationDataTypeController>( |
| sync_service, password_sender_service_.value(), |
| pref_service_.value())); |
| } |
| } |
| } |
| |
| // `plus_address_webdata_service_` is null on iOS WebView. |
| // `kEnterprisePlusAddressServerUrl` is checked to prevent enabling the |
| // feature in dev builds via the field trial config. |
| if (!disabled_types.Has(syncer::PLUS_ADDRESS) && |
| plus_address_webdata_service_.value() && google_groups_manager_.value()) { |
| controllers.push_back( |
| std::make_unique<plus_addresses::PlusAddressDataTypeController>( |
| syncer::PLUS_ADDRESS, |
| /*delegate_for_full_sync_mode=*/ |
| plus_address_webdata_service_.value()->GetSyncControllerDelegate(), |
| /*delegate_for_transport_mode=*/ |
| plus_address_webdata_service_.value()->GetSyncControllerDelegate(), |
| sync_service, identity_manager_.value(), |
| google_groups_manager_.value())); |
| } |
| |
| // `plus_address_setting_service_` is null on iOS WebView. |
| // `kEnterprisePlusAddressServerUrl` is checked to prevent enabling the |
| // feature in dev builds via the field trial config. |
| if (!disabled_types.Has(syncer::PLUS_ADDRESS_SETTING) && |
| plus_address_setting_service_.value() && google_groups_manager_.value()) { |
| controllers.push_back( |
| std::make_unique<plus_addresses::PlusAddressDataTypeController>( |
| syncer::PLUS_ADDRESS_SETTING, |
| /*delegate_for_full_sync_mode=*/ |
| plus_address_setting_service_.value()->GetSyncControllerDelegate(), |
| /*delegate_for_transport_mode=*/ |
| plus_address_setting_service_.value()->GetSyncControllerDelegate(), |
| sync_service, identity_manager_.value(), |
| google_groups_manager_.value())); |
| } |
| |
| if (!disabled_types.Has(syncer::PREFERENCES)) { |
| controllers.push_back( |
| std::make_unique<SyncableServiceBasedDataTypeController>( |
| syncer::PREFERENCES, |
| data_type_store_service_.value()->GetStoreFactory(), |
| SyncableServiceForPrefs(pref_service_syncable_.value(), |
| syncer::PREFERENCES), |
| dump_stack, |
| ArePreferencesAllowedInTransportMode() |
| ? SyncableServiceBasedDataTypeController::DelegateMode:: |
| kTransportModeWithSingleModel |
| : SyncableServiceBasedDataTypeController::DelegateMode:: |
| kLegacyFullSyncModeOnly)); |
| } |
| |
| if (!disabled_types.Has(syncer::PRIORITY_PREFERENCES)) { |
| controllers.push_back( |
| std::make_unique<SyncableServiceBasedDataTypeController>( |
| syncer::PRIORITY_PREFERENCES, |
| data_type_store_service_.value()->GetStoreFactory(), |
| SyncableServiceForPrefs(pref_service_syncable_.value(), |
| syncer::PRIORITY_PREFERENCES), |
| dump_stack, |
| ArePreferencesAllowedInTransportMode() |
| ? SyncableServiceBasedDataTypeController::DelegateMode:: |
| kTransportModeWithSingleModel |
| : SyncableServiceBasedDataTypeController::DelegateMode:: |
| kLegacyFullSyncModeOnly)); |
| } |
| |
| if (!disabled_types.Has(syncer::SAVED_TAB_GROUP) && |
| tab_group_sync_service_.value()) { |
| syncer::DataTypeControllerDelegate* delegate = |
| tab_group_sync_service_.value() |
| ->GetSavedTabGroupControllerDelegate() |
| .get(); |
| |
| controllers.push_back(std::make_unique<syncer::DataTypeController>( |
| syncer::SAVED_TAB_GROUP, |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate))); |
| } |
| |
| bool data_sharing_enabled = |
| data_sharing::features::IsDataSharingFunctionalityEnabled(); |
| if (!disabled_types.Has(syncer::SHARED_TAB_GROUP_DATA) && |
| tab_group_sync_service_.value() && data_sharing_enabled) { |
| syncer::DataTypeControllerDelegate* delegate = |
| tab_group_sync_service_.value() |
| ->GetSharedTabGroupControllerDelegate() |
| .get(); |
| |
| controllers.push_back( |
| std::make_unique<collaboration::SharedTabGroupDataTypeController>( |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| sync_service, collaboration_service_.value())); |
| } |
| |
| if (!disabled_types.Has(syncer::SHARING_MESSAGE) && |
| sharing_message_bridge_.value()) { |
| syncer::DataTypeControllerDelegate* sharing_message_delegate = |
| sharing_message_bridge_.value()->GetControllerDelegate().get(); |
| controllers.push_back(std::make_unique<SharingMessageDataTypeController>( |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| sharing_message_delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| sharing_message_delegate))); |
| } |
| |
| if (!disabled_types.Has(syncer::READING_LIST)) { |
| // The transport-mode delegate may or may not be null depending on |
| // platform and feature toggle state. |
| syncer::DataTypeControllerDelegate* delegate_for_transport_mode = |
| dual_reading_list_model_.value() |
| ->GetSyncControllerDelegateForTransportMode() |
| .get(); |
| |
| controllers.push_back(std::make_unique<DataTypeController>( |
| syncer::READING_LIST, |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| dual_reading_list_model_.value() |
| ->GetSyncControllerDelegate() |
| .get()), |
| /*delegate_for_transport_mode=*/ |
| delegate_for_transport_mode |
| ? std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate_for_transport_mode) |
| : nullptr, |
| std::make_unique<reading_list::ReadingListLocalDataBatchUploader>( |
| dual_reading_list_model_.value()))); |
| } |
| |
| if (!disabled_types.Has(syncer::SEARCH_ENGINES) && |
| template_url_service_.value()) { |
| controllers.push_back( |
| std::make_unique<syncer::SyncableServiceBasedDataTypeController>( |
| syncer::SEARCH_ENGINES, |
| data_type_store_service_.value()->GetStoreFactory(), |
| template_url_service_.value()->AsWeakPtr(), dump_stack, |
| base::FeatureList::IsEnabled( |
| syncer::kSeparateLocalAndAccountSearchEngines) |
| ? syncer::SyncableServiceBasedDataTypeController::DelegateMode:: |
| kTransportModeWithSingleModel |
| : syncer::SyncableServiceBasedDataTypeController::DelegateMode:: |
| kLegacyFullSyncModeOnly)); |
| } |
| |
| if (!disabled_types.Has(syncer::USER_EVENTS)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| user_event_service_.value()->GetControllerDelegate().get(); |
| |
| controllers.push_back(std::make_unique<syncer::UserEventDataTypeController>( |
| sync_service, |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) |
| ? std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate) |
| : nullptr)); |
| } |
| |
| if (!disabled_types.Has(syncer::SEND_TAB_TO_SELF)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| send_tab_to_self_sync_service_.value()->GetControllerDelegate().get(); |
| controllers.push_back( |
| std::make_unique<send_tab_to_self::SendTabToSelfDataTypeController>( |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate))); |
| } |
| |
| if (!disabled_types.Has(syncer::USER_CONSENTS)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| consent_auditor_.value()->GetControllerDelegate().get(); |
| |
| // Forward both full-sync and transport-only modes to the same delegate, |
| // since behavior for USER_CONSENTS does not differ (they are always |
| // persisted). |
| controllers.push_back(std::make_unique<DataTypeController>( |
| syncer::USER_CONSENTS, |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate))); |
| } |
| |
| #if !BUILDFLAG(IS_IOS) |
| if (!disabled_types.Has(syncer::AUTOFILL_VALUABLE) && |
| base::FeatureList::IsEnabled(syncer::kSyncAutofillLoyaltyCard)) { |
| controllers.push_back( |
| std::make_unique<autofill::AutofillValuableDataTypeController>( |
| syncer::AUTOFILL_VALUABLE, |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| account_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| &AutofillLoyaltyCardDelegateFromDataService, |
| base::RetainedRef( |
| account_autofill_web_data_service_.value()))), |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| account_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| &AutofillLoyaltyCardDelegateFromDataService, |
| base::RetainedRef( |
| account_autofill_web_data_service_.value()))))); |
| } |
| #endif |
| |
| if (!disabled_types.Has(syncer::SHARED_TAB_GROUP_ACCOUNT_DATA) && |
| base::FeatureList::IsEnabled(syncer::kSyncSharedTabGroupAccountData) && |
| tab_group_sync_service_.value() && data_sharing_enabled) { |
| syncer::DataTypeControllerDelegate* delegate = |
| tab_group_sync_service_.value() |
| ->GetSharedTabGroupAccountControllerDelegate() |
| .get(); |
| |
| controllers.push_back( |
| std::make_unique< |
| collaboration::SharedTabGroupAccountDataTypeController>( |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| sync_service, collaboration_service_.value())); |
| } |
| |
| if (!disabled_types.Has(syncer::SHARED_COMMENT) && |
| base::FeatureList::IsEnabled(syncer::kSyncSharedComment)) { |
| // TODO(crbug.com/433556051): In a future CL, register the type, i.e. |
| // instantiate the DataTypeController. There is more than one way to go |
| // about it, but one option is: |
| // - Create a trivial implementation of DataTypeSyncBridge which lives in |
| // your feature's directory. It should have synchronous access to your |
| // data model (e.g. DualReadingListModel) and be (indirectly) owned by a |
| // CoolKeyedService (often the model itself). |
| // - Expose CoolKeyedService::GetControllerDelegate() which calls |
| // bridge->change_processor()->GetControllerDelegate(). |
| // - Inject CoolKeyedService in this class and call GetControllerDelegate() |
| // on it to create the DataTypeController. |
| // In following CLs implement the bridge and keep adding unit tests. |
| } |
| |
| #if !BUILDFLAG(IS_ANDROID) |
| if (!disabled_types.Has(syncer::WEBAUTHN_CREDENTIAL)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| passkey_model_.value()->GetDataTypeControllerDelegate().get(); |
| |
| controllers.push_back(std::make_unique<webauthn::PasskeyDataTypeController>( |
| sync_service, |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate))); |
| } |
| #endif |
| |
| #if BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| if (supervised_user_settings_service_.value()) { |
| controllers.push_back( |
| std::make_unique<SupervisedUserSettingsDataTypeController>( |
| dump_stack, data_type_store_service_.value()->GetStoreFactory(), |
| supervised_user_settings_service_.value()->AsWeakPtr(), |
| pref_service_.value())); |
| } |
| #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| |
| // `data_sharing_service_` is null on iOS WebView. |
| if (data_sharing_service_.value() && data_sharing_enabled && |
| !disabled_types.Has(syncer::COLLABORATION_GROUP)) { |
| syncer::DataTypeControllerDelegate* delegate = |
| data_sharing_service_.value() |
| ->GetCollaborationGroupControllerDelegate() |
| .get(); |
| |
| controllers.push_back( |
| std::make_unique<collaboration::CollaborationGroupDataTypeController>( |
| /*delegate_for_full_sync_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| /*delegate_for_transport_mode=*/ |
| std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( |
| delegate), |
| sync_service, collaboration_service_.value())); |
| } |
| |
| return controllers; |
| } |
| |
| std::unique_ptr<DataTypeController> |
| CommonControllerBuilder::CreateWalletDataTypeController( |
| syncer::DataType type, |
| const base::RepeatingCallback< |
| base::WeakPtr<syncer::DataTypeControllerDelegate>( |
| autofill::AutofillWebDataService*)>& delegate_from_web_data, |
| syncer::SyncService* sync_service, |
| bool with_transport_mode_support) { |
| // Transport mode should be supported, except for METADATA and OFFER where |
| // support is still work in progress, see crbug.com/1448894 and |
| // crbug.com/1448895. |
| CHECK(with_transport_mode_support || |
| type == syncer::AUTOFILL_WALLET_METADATA || |
| type == syncer::AUTOFILL_WALLET_OFFER); |
| auto delegate_for_full_sync_mode = |
| std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| profile_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| delegate_from_web_data, |
| base::RetainedRef(profile_autofill_web_data_service_.value()))); |
| auto delegate_for_transport_mode = |
| with_transport_mode_support |
| ? std::make_unique<syncer::ProxyDataTypeControllerDelegate>( |
| account_autofill_web_data_service_.value()->GetDBTaskRunner(), |
| base::BindRepeating( |
| delegate_from_web_data, |
| base::RetainedRef( |
| account_autofill_web_data_service_.value()))) |
| : nullptr; |
| return std::make_unique<AutofillWalletDataTypeController>( |
| type, std::move(delegate_for_full_sync_mode), |
| std::move(delegate_for_transport_mode), pref_service_.value(), |
| sync_service); |
| } |
| |
| } // namespace browser_sync |