blob: c1c11cf98b2f5124b1de022008dabd6b4021d4d0 [file] [log] [blame]
// Copyright 2015 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/sync_service_factory.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/trusted_vault/trusted_vault_service_factory.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/webdata_services/web_data_service_factory.h"
#include "chrome/common/buildflags.h"
#include "chrome/test/base/testing_profile.h"
#include "components/commerce/core/commerce_feature_list.h"
#include "components/data_sharing/public/features.h"
#include "components/saved_tab_groups/public/features.h"
#include "components/spellcheck/spellcheck_buildflags.h"
#include "components/sync/base/command_line_switches.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/features.h"
#include "components/sync/service/sync_service_impl.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/buildflags/buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(ENABLE_SPELLCHECK)
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#endif // BUILDFLAG(ENABLE_SPELLCHECK)
#if BUILDFLAG(IS_CHROMEOS)
#include "ash/constants/ash_features.h"
#include "chrome/browser/ash/app_list/app_list_syncable_service_factory.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/floating_sso/floating_sso_service_factory.h"
#include "chrome/browser/sync/wifi_configuration_sync_service_factory.h"
#include "chromeos/ash/components/dbus/shill/shill_clients.h"
#include "chromeos/ash/components/dbus/shill/shill_manager_client.h"
#include "chromeos/ash/components/network/network_handler_test_helper.h"
#include "chromeos/ash/components/sync_wifi/wifi_configuration_sync_service.h"
#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
#endif
class SyncServiceFactoryTest : public testing::Test {
public:
void SetUp() override {
#if BUILDFLAG(IS_CHROMEOS)
app_list::AppListSyncableServiceFactory::SetUseInTesting(true);
// Cookie sync is only enabled for the primary profile, but for these tests
// there is no real benefit in setting up a fully logged in ChromeOS user.
ash::floating_sso::FloatingSsoServiceFactory::GetInstance()
->AllowNonPrimaryProfileForTests();
#endif // BUILDFLAG(IS_CHROMEOS)
TestingProfile::Builder builder;
builder.AddTestingFactory(FaviconServiceFactory::GetInstance(),
FaviconServiceFactory::GetDefaultFactory());
builder.AddTestingFactory(HistoryServiceFactory::GetInstance(),
HistoryServiceFactory::GetDefaultFactory());
builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
SyncServiceFactory::GetDefaultFactory());
builder.AddTestingFactory(
TemplateURLServiceFactory::GetInstance(),
base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor));
builder.AddTestingFactory(TrustedVaultServiceFactory::GetInstance(),
TrustedVaultServiceFactory::GetDefaultFactory());
// Some services will only be created if there is a WebDataService.
builder.AddTestingFactory(WebDataServiceFactory::GetInstance(),
WebDataServiceFactory::GetDefaultFactory());
#if BUILDFLAG(ENABLE_SPELLCHECK)
builder.AddTestingFactory(
SpellcheckServiceFactory::GetInstance(),
base::BindRepeating(base::BindLambdaForTesting(
[](content::BrowserContext* browser_context) {
return std::unique_ptr<KeyedService>(
std::make_unique<SpellcheckService>(browser_context));
})));
#endif // BUILDFLAG(ENABLE_SPELLCHECK)
profile_ = builder.Build();
}
void TearDown() override {
#if BUILDFLAG(IS_CHROMEOS)
app_list::AppListSyncableServiceFactory::SetUseInTesting(false);
#endif // BUILDFLAG(IS_CHROMEOS)
// There may tasks in flight referencing fields owned by the test fixture.
// Make sure they are flushed now to prevent memory safety errors, e.g.
// use-after-destruction errors.
task_environment_.RunUntilIdle();
}
protected:
SyncServiceFactoryTest() = default;
~SyncServiceFactoryTest() override = default;
// Returns the collection of default datatypes.
syncer::DataTypeSet DefaultDatatypes() {
static_assert(55 == syncer::GetNumDataTypes(),
"When adding a new type, you probably want to add it here as "
"well (assuming it is already enabled). Check similar "
"function in "
"ios/c/b/sync/model/sync_service_factory_unittest.cc");
syncer::DataTypeSet datatypes;
// These preprocessor conditions and their order should be in sync with
// preprocessor conditions in ChromeSyncClient::CreateDataTypeControllers:
// ChromeSyncClient types.
datatypes.Put(syncer::READING_LIST);
datatypes.Put(syncer::SECURITY_EVENTS);
datatypes.Put(syncer::SUPERVISED_USER_SETTINGS);
#if BUILDFLAG(ENABLE_EXTENSIONS)
datatypes.Put(syncer::APPS);
datatypes.Put(syncer::EXTENSIONS);
datatypes.Put(syncer::EXTENSION_SETTINGS);
datatypes.Put(syncer::APP_SETTINGS);
datatypes.Put(syncer::WEB_APPS);
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
#if !BUILDFLAG(IS_ANDROID)
datatypes.Put(syncer::THEMES);
datatypes.Put(syncer::SEARCH_ENGINES);
#endif // !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \
BUILDFLAG(IS_WIN)
datatypes.Put(syncer::SAVED_TAB_GROUP);
#elif BUILDFLAG(IS_ANDROID)
if (base::FeatureList::IsEnabled(tab_groups::kTabGroupSyncAndroid)) {
datatypes.Put(syncer::SAVED_TAB_GROUP);
}
#endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) ||
// BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
datatypes.Put(syncer::DICTIONARY);
#endif
#if BUILDFLAG(IS_CHROMEOS)
datatypes.Put(syncer::APP_LIST);
if (arc::IsArcAllowedForProfile(profile())) {
datatypes.Put(syncer::ARC_PACKAGE);
}
if (ash::features::IsFloatingSsoAllowed()) {
datatypes.Put(syncer::COOKIES);
}
datatypes.Put(syncer::OS_PREFERENCES);
datatypes.Put(syncer::OS_PRIORITY_PREFERENCES);
datatypes.Put(syncer::PRINTERS);
if (ash::features::IsOAuthIppEnabled()) {
datatypes.Put(syncer::PRINTERS_AUTHORIZATION_SERVERS);
}
datatypes.Put(syncer::WIFI_CONFIGURATIONS);
datatypes.Put(syncer::WORKSPACE_DESK);
#endif // BUILDFLAG(IS_CHROMEOS)
// Common types. This excludes PASSWORDS,
// INCOMING_PASSWORD_SHARING_INVITATION and
// INCOMING_PASSWORD_SHARING_INVITATION, because the password store factory
// is null for testing and hence no controller gets instantiated for those
// types.
datatypes.Put(syncer::AUTOFILL);
datatypes.Put(syncer::AUTOFILL_PROFILE);
if (base::FeatureList::IsEnabled(
syncer::kSyncAutofillWalletCredentialData)) {
datatypes.Put(syncer::AUTOFILL_WALLET_CREDENTIAL);
}
datatypes.Put(syncer::AUTOFILL_WALLET_DATA);
datatypes.Put(syncer::AUTOFILL_WALLET_METADATA);
datatypes.Put(syncer::AUTOFILL_WALLET_OFFER);
datatypes.Put(syncer::AUTOFILL_WALLET_USAGE);
datatypes.Put(syncer::BOOKMARKS);
if (base::FeatureList::IsEnabled(commerce::kProductSpecifications)) {
datatypes.Put(syncer::PRODUCT_COMPARISON);
}
datatypes.Put(syncer::CONTACT_INFO);
datatypes.Put(syncer::DEVICE_INFO);
datatypes.Put(syncer::HISTORY);
datatypes.Put(syncer::HISTORY_DELETE_DIRECTIVES);
datatypes.Put(syncer::PREFERENCES);
datatypes.Put(syncer::PRIORITY_PREFERENCES);
datatypes.Put(syncer::SESSIONS);
datatypes.Put(syncer::USER_EVENTS);
datatypes.Put(syncer::USER_CONSENTS);
datatypes.Put(syncer::SEND_TAB_TO_SELF);
datatypes.Put(syncer::SHARING_MESSAGE);
#if !BUILDFLAG(IS_ANDROID)
datatypes.Put(syncer::WEBAUTHN_CREDENTIAL);
#endif // !BUILDFLAG(IS_ANDROID)
if (base::FeatureList::IsEnabled(
data_sharing::features::kDataSharingFeature)) {
datatypes.Put(syncer::COLLABORATION_GROUP);
datatypes.Put(syncer::SHARED_TAB_GROUP_DATA);
}
#if BUILDFLAG(IS_ANDROID)
if (base::FeatureList::IsEnabled(syncer::kWebApkBackupAndRestoreBackend)) {
datatypes.Put(syncer::WEB_APKS);
}
#endif // BUILDFLAG(IS_ANDROID)
// syncer::PLUS_ADDRESS and syncer::PLUS_ADDRESS_SETTING are excluded
// because GoogleGroupsManagerFactory is null for testing and hence no
// controller gets instantiated for the type.
if (base::FeatureList::IsEnabled(syncer::kSyncAutofillLoyaltyCard)) {
datatypes.Put(syncer::AUTOFILL_VALUABLE);
}
if (base::FeatureList::IsEnabled(syncer::kSyncSharedTabGroupAccountData)) {
datatypes.Put(syncer::SHARED_TAB_GROUP_ACCOUNT_DATA);
}
return datatypes;
}
Profile* profile() { return profile_.get(); }
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfile> profile_;
#if BUILDFLAG(IS_CHROMEOS)
// Fake network stack is required for WIFI_CONFIGURATIONS datatype. It's also
// used by `network_config_helper_`
ash::NetworkHandlerTestHelper network_handler_test_helper_;
// Sets up and tears down the Chrome OS networking mojo service as needed
// for the WIFI_CONFIGURATIONS sync service.
ash::network_config::CrosNetworkConfigTestHelper network_config_helper_;
#endif
};
// Verify that the disable sync flag disables creation of the sync service.
TEST_F(SyncServiceFactoryTest, DisableSyncFlag) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(syncer::kDisableSync);
EXPECT_EQ(nullptr, SyncServiceFactory::GetForProfile(profile()));
}
// Verify that a normal (no command line flags) SyncServiceImpl can be created
// and properly initialized.
TEST_F(SyncServiceFactoryTest, CreateSyncServiceImplDefault) {
syncer::SyncServiceImpl* sync_service =
SyncServiceFactory::GetAsSyncServiceImplForProfileForTesting(profile());
syncer::DataTypeSet types = sync_service->GetRegisteredDataTypesForTest();
const syncer::DataTypeSet default_types = DefaultDatatypes();
EXPECT_EQ(default_types.size(), types.size());
for (syncer::DataType type : default_types) {
EXPECT_TRUE(types.Has(type))
<< syncer::DataTypeToDebugString(type) << " not found in datatypes map";
}
}