blob: 9c4a83ab8e6bd05627b19827fcca27a55bfa74ea [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/browser_sync/profile_sync_components_factory_impl.h"
#include <utility>
#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_wallet_data_type_controller.h"
#include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
#include "components/autofill/core/browser/webdata/autofill_data_type_controller.h"
#include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/browser/webdata/web_data_model_type_controller.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/browser_sync/browser_sync_switches.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/dom_distiller/core/dom_distiller_features.h"
#include "components/history/core/browser/history_delete_directives_data_type_controller.h"
#include "components/history/core/browser/typed_url_data_type_controller.h"
#include "components/history/core/browser/typed_url_model_type_controller.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/sync/browser/password_data_type_controller.h"
#include "components/prefs/pref_service.h"
#include "components/reading_list/features/reading_list_switches.h"
#include "components/sync/base/report_unrecoverable_error.h"
#include "components/sync/device_info/local_device_info_provider_impl.h"
#include "components/sync/driver/async_directory_type_controller.h"
#include "components/sync/driver/data_type_manager_impl.h"
#include "components/sync/driver/glue/sync_backend_host_impl.h"
#include "components/sync/driver/model_type_controller.h"
#include "components/sync/driver/proxy_data_type_controller.h"
#include "components/sync/driver/sync_client.h"
#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/engine/attachments/attachment_downloader.h"
#include "components/sync/engine/attachments/attachment_uploader.h"
#include "components/sync/engine/sync_engine.h"
#include "components/sync/model/attachments/attachment_service.h"
#include "components/sync_bookmarks/bookmark_change_processor.h"
#include "components/sync_bookmarks/bookmark_data_type_controller.h"
#include "components/sync_bookmarks/bookmark_model_associator.h"
#include "components/sync_bookmarks/bookmark_model_type_controller.h"
#include "components/sync_sessions/session_data_type_controller.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "google_apis/gaia/oauth2_token_service_request.h"
#include "net/url_request/url_request_context_getter.h"
using base::FeatureList;
using bookmarks::BookmarkModel;
using sync_bookmarks::BookmarkChangeProcessor;
using sync_bookmarks::BookmarkDataTypeController;
using sync_bookmarks::BookmarkModelAssociator;
using sync_sessions::SessionDataTypeController;
using syncer::AsyncDirectoryTypeController;
using syncer::DataTypeController;
using syncer::DataTypeManager;
using syncer::DataTypeManagerImpl;
using syncer::DataTypeManagerObserver;
using syncer::ModelTypeController;
using syncer::ProxyDataTypeController;
namespace browser_sync {
namespace {
syncer::ModelTypeSet GetDisabledTypesFromCommandLine(
const base::CommandLine& command_line) {
syncer::ModelTypeSet disabled_types;
std::string disabled_types_str =
command_line.GetSwitchValueASCII(switches::kDisableSyncTypes);
disabled_types = syncer::ModelTypeSetFromString(disabled_types_str);
return disabled_types;
}
syncer::ModelTypeSet GetEnabledTypesFromCommandLine(
const base::CommandLine& command_line) {
return syncer::ModelTypeSet();
}
} // namespace
ProfileSyncComponentsFactoryImpl::ProfileSyncComponentsFactoryImpl(
syncer::SyncClient* sync_client,
version_info::Channel channel,
const std::string& version,
bool is_tablet,
const base::CommandLine& command_line,
const char* history_disabled_pref,
const GURL& sync_service_url,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
OAuth2TokenService* token_service,
net::URLRequestContextGetter* url_request_context_getter,
const scoped_refptr<autofill::AutofillWebDataService>& web_data_service,
const scoped_refptr<password_manager::PasswordStore>& password_store)
: sync_client_(sync_client),
channel_(channel),
version_(version),
is_tablet_(is_tablet),
command_line_(command_line),
history_disabled_pref_(history_disabled_pref),
sync_service_url_(sync_service_url),
ui_thread_(ui_thread),
db_thread_(db_thread),
token_service_(token_service),
url_request_context_getter_(url_request_context_getter),
web_data_service_(web_data_service),
password_store_(password_store),
weak_factory_(this) {
DCHECK(token_service_);
DCHECK(url_request_context_getter_);
}
ProfileSyncComponentsFactoryImpl::~ProfileSyncComponentsFactoryImpl() {}
void ProfileSyncComponentsFactoryImpl::RegisterDataTypes(
syncer::SyncService* sync_service,
const RegisterDataTypesMethod& register_platform_types_method) {
syncer::ModelTypeSet disabled_types =
GetDisabledTypesFromCommandLine(command_line_);
syncer::ModelTypeSet enabled_types =
GetEnabledTypesFromCommandLine(command_line_);
RegisterCommonDataTypes(sync_service, disabled_types, enabled_types);
if (!register_platform_types_method.is_null())
register_platform_types_method.Run(sync_service, disabled_types,
enabled_types);
}
void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes(
syncer::SyncService* sync_service,
syncer::ModelTypeSet disabled_types,
syncer::ModelTypeSet enabled_types) {
base::Closure error_callback =
base::Bind(&syncer::ReportUnrecoverableError, channel_);
// TODO(stanisc): can DEVICE_INFO be one of disabled datatypes?
// Use an error callback that always uploads a stacktrace if it can to help
// get USS as stable as possible.
sync_service->RegisterDataTypeController(
std::make_unique<ModelTypeController>(syncer::DEVICE_INFO, sync_client_,
ui_thread_));
// These features are enabled only if there's a DB thread to post tasks to.
if (db_thread_) {
// Autocomplete sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::AUTOFILL)) {
if (FeatureList::IsEnabled(switches::kSyncUSSAutocomplete)) {
sync_service->RegisterDataTypeController(
std::make_unique<autofill::WebDataModelTypeController>(
syncer::AUTOFILL, sync_client_, db_thread_, web_data_service_,
base::Bind(
&autofill::AutocompleteSyncBridge::FromWebDataService)));
} else {
sync_service->RegisterDataTypeController(
std::make_unique<AutofillDataTypeController>(
db_thread_, error_callback, sync_client_, web_data_service_));
}
}
// Autofill sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::AUTOFILL_PROFILE)) {
sync_service->RegisterDataTypeController(
std::make_unique<AutofillProfileDataTypeController>(
db_thread_, error_callback, sync_client_, web_data_service_));
}
// Wallet data sync is enabled by default, but behind a syncer experiment
// enforced by the datatype controller. Register unless explicitly disabled.
bool wallet_disabled = disabled_types.Has(syncer::AUTOFILL_WALLET_DATA);
if (!wallet_disabled) {
sync_service->RegisterDataTypeController(
std::make_unique<AutofillWalletDataTypeController>(
syncer::AUTOFILL_WALLET_DATA, db_thread_, error_callback,
sync_client_, web_data_service_));
}
// Wallet metadata sync depends on Wallet data sync. Register if Wallet data
// is syncing and metadata sync is not explicitly disabled.
if (!wallet_disabled &&
!disabled_types.Has(syncer::AUTOFILL_WALLET_METADATA)) {
sync_service->RegisterDataTypeController(
std::make_unique<AutofillWalletDataTypeController>(
syncer::AUTOFILL_WALLET_METADATA, db_thread_, error_callback,
sync_client_, web_data_service_));
}
}
// Bookmark sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::BOOKMARKS)) {
if (FeatureList::IsEnabled(switches::kSyncUSSBookmarks)) {
sync_service->RegisterDataTypeController(
std::make_unique<sync_bookmarks::BookmarkModelTypeController>(
sync_client_));
} else {
sync_service->RegisterDataTypeController(
std::make_unique<BookmarkDataTypeController>(error_callback,
sync_client_));
}
}
// These features are enabled only if history is not disabled.
if (!sync_client_->GetPrefService()->GetBoolean(history_disabled_pref_)) {
// TypedUrl sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::TYPED_URLS)) {
if (base::FeatureList::IsEnabled(switches::kSyncUSSTypedURL)) {
sync_service->RegisterDataTypeController(
std::make_unique<history::TypedURLModelTypeController>(
sync_client_, history_disabled_pref_));
} else {
sync_service->RegisterDataTypeController(
std::make_unique<TypedUrlDataTypeController>(
error_callback, sync_client_, history_disabled_pref_));
}
}
// Delete directive sync is enabled by default.
if (!disabled_types.Has(syncer::HISTORY_DELETE_DIRECTIVES)) {
sync_service->RegisterDataTypeController(
std::make_unique<HistoryDeleteDirectivesDataTypeController>(
error_callback, sync_client_));
}
// Session sync is enabled by default. This is disabled if history is
// disabled because the tab sync data is added to the web history on the
// server.
if (!disabled_types.Has(syncer::PROXY_TABS)) {
sync_service->RegisterDataTypeController(
std::make_unique<ProxyDataTypeController>(syncer::PROXY_TABS));
sync_service->RegisterDataTypeController(
std::make_unique<SessionDataTypeController>(
error_callback, sync_client_,
sync_service->GetLocalDeviceInfoProvider(),
history_disabled_pref_));
}
// Favicon sync is enabled by default. Register unless explicitly disabled.
if (!disabled_types.Has(syncer::FAVICON_IMAGES) &&
!disabled_types.Has(syncer::FAVICON_TRACKING)) {
// crbug/384552. We disable error uploading for this data types for now.
sync_service->RegisterDataTypeController(
std::make_unique<AsyncDirectoryTypeController>(
syncer::FAVICON_IMAGES, base::Closure(), sync_client_,
syncer::GROUP_UI, ui_thread_));
sync_service->RegisterDataTypeController(
std::make_unique<AsyncDirectoryTypeController>(
syncer::FAVICON_TRACKING, base::Closure(), sync_client_,
syncer::GROUP_UI, ui_thread_));
}
}
// Password sync is enabled by default. Register unless explicitly
// disabled.
if (!disabled_types.Has(syncer::PASSWORDS)) {
sync_service->RegisterDataTypeController(
std::make_unique<PasswordDataTypeController>(
error_callback, sync_client_,
sync_client_->GetPasswordStateChangedCallback(), password_store_));
}
if (!disabled_types.Has(syncer::PREFERENCES)) {
if (!override_prefs_controller_to_uss_for_test_) {
sync_service->RegisterDataTypeController(
std::make_unique<AsyncDirectoryTypeController>(
syncer::PREFERENCES, error_callback, sync_client_,
syncer::GROUP_UI, ui_thread_));
} else {
sync_service->RegisterDataTypeController(
std::make_unique<ModelTypeController>(syncer::PREFERENCES,
sync_client_, ui_thread_));
}
}
if (!disabled_types.Has(syncer::PRIORITY_PREFERENCES)) {
sync_service->RegisterDataTypeController(
std::make_unique<AsyncDirectoryTypeController>(
syncer::PRIORITY_PREFERENCES, error_callback, sync_client_,
syncer::GROUP_UI, ui_thread_));
}
// Article sync is disabled by default. Register only if explicitly enabled.
if (dom_distiller::IsEnableSyncArticlesSet()) {
sync_service->RegisterDataTypeController(
std::make_unique<AsyncDirectoryTypeController>(
syncer::ARTICLES, error_callback, sync_client_, syncer::GROUP_UI,
ui_thread_));
}
#if defined(OS_CHROMEOS)
if (!disabled_types.Has(syncer::PRINTERS)) {
sync_service->RegisterDataTypeController(
std::make_unique<ModelTypeController>(syncer::PRINTERS, sync_client_,
ui_thread_));
}
#endif
// Reading list sync is enabled by default only on iOS. Register unless
// Reading List or Reading List Sync is explicitly disabled.
if (!disabled_types.Has(syncer::READING_LIST) &&
reading_list::switches::IsReadingListEnabled()) {
sync_service->RegisterDataTypeController(
std::make_unique<ModelTypeController>(syncer::READING_LIST,
sync_client_, ui_thread_));
}
if (!disabled_types.Has(syncer::USER_EVENTS) &&
FeatureList::IsEnabled(switches::kSyncUserEvents)) {
sync_service->RegisterDataTypeController(
std::make_unique<ModelTypeController>(syncer::USER_EVENTS, sync_client_,
ui_thread_));
}
}
DataTypeManager* ProfileSyncComponentsFactoryImpl::CreateDataTypeManager(
syncer::ModelTypeSet initial_types,
const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
debug_info_listener,
const DataTypeController::TypeMap* controllers,
const syncer::DataTypeEncryptionHandler* encryption_handler,
syncer::ModelTypeConfigurer* configurer,
DataTypeManagerObserver* observer) {
return new DataTypeManagerImpl(sync_client_, initial_types,
debug_info_listener, controllers,
encryption_handler, configurer, observer);
}
syncer::SyncEngine* ProfileSyncComponentsFactoryImpl::CreateSyncEngine(
const std::string& name,
invalidation::InvalidationService* invalidator,
const base::WeakPtr<syncer::SyncPrefs>& sync_prefs,
const base::FilePath& sync_data_folder) {
return new syncer::SyncBackendHostImpl(name, sync_client_, invalidator,
sync_prefs, sync_data_folder);
}
std::unique_ptr<syncer::LocalDeviceInfoProvider>
ProfileSyncComponentsFactoryImpl::CreateLocalDeviceInfoProvider() {
return std::make_unique<syncer::LocalDeviceInfoProviderImpl>(
channel_, version_, is_tablet_);
}
class TokenServiceProvider
: public OAuth2TokenServiceRequest::TokenServiceProvider {
public:
TokenServiceProvider(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
OAuth2TokenService* token_service);
// OAuth2TokenServiceRequest::TokenServiceProvider implementation.
scoped_refptr<base::SingleThreadTaskRunner> GetTokenServiceTaskRunner()
override;
OAuth2TokenService* GetTokenService() override;
private:
~TokenServiceProvider() override;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
OAuth2TokenService* token_service_;
};
TokenServiceProvider::TokenServiceProvider(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
OAuth2TokenService* token_service)
: task_runner_(task_runner), token_service_(token_service) {}
TokenServiceProvider::~TokenServiceProvider() {}
scoped_refptr<base::SingleThreadTaskRunner>
TokenServiceProvider::GetTokenServiceTaskRunner() {
return task_runner_;
}
OAuth2TokenService* TokenServiceProvider::GetTokenService() {
return token_service_;
}
std::unique_ptr<syncer::AttachmentService>
ProfileSyncComponentsFactoryImpl::CreateAttachmentService(
std::unique_ptr<syncer::AttachmentStoreForSync> attachment_store,
const syncer::UserShare& user_share,
const std::string& store_birthday,
syncer::ModelType model_type,
syncer::AttachmentService::Delegate* delegate) {
std::unique_ptr<syncer::AttachmentUploader> attachment_uploader;
std::unique_ptr<syncer::AttachmentDownloader> attachment_downloader;
// Only construct an AttachmentUploader and AttachmentDownload if we have sync
// credentials. We may not have sync credentials because there may not be a
// signed in sync user.
if (!user_share.sync_credentials.account_id.empty() &&
!user_share.sync_credentials.scope_set.empty()) {
scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>
token_service_provider(
new TokenServiceProvider(ui_thread_, token_service_));
// TODO(maniscalco): Use shared (one per profile) thread-safe instances of
// AttachmentUploader and AttachmentDownloader instead of creating a new one
// per AttachmentService (bug 369536).
attachment_uploader = syncer::AttachmentUploader::Create(
sync_service_url_, url_request_context_getter_,
user_share.sync_credentials.account_id,
user_share.sync_credentials.scope_set, token_service_provider,
store_birthday, model_type);
token_service_provider =
new TokenServiceProvider(ui_thread_, token_service_);
attachment_downloader = syncer::AttachmentDownloader::Create(
sync_service_url_, url_request_context_getter_,
user_share.sync_credentials.account_id,
user_share.sync_credentials.scope_set, token_service_provider,
store_birthday, model_type);
}
// It is important that the initial backoff delay is relatively large. For
// whatever reason, the server may fail all requests for a short period of
// time. When this happens we don't want to overwhelm the server with
// requests so we use a large initial backoff.
const base::TimeDelta initial_backoff_delay =
base::TimeDelta::FromMinutes(30);
const base::TimeDelta max_backoff_delay = base::TimeDelta::FromHours(4);
return syncer::AttachmentService::Create(
std::move(attachment_store), std::move(attachment_uploader),
std::move(attachment_downloader), delegate, initial_backoff_delay,
max_backoff_delay);
}
syncer::SyncApiComponentFactory::SyncComponents
ProfileSyncComponentsFactoryImpl::CreateBookmarkSyncComponents(
syncer::SyncService* sync_service,
std::unique_ptr<syncer::DataTypeErrorHandler> error_handler) {
BookmarkModel* bookmark_model =
sync_service->GetSyncClient()->GetBookmarkModel();
syncer::UserShare* user_share = sync_service->GetUserShare();
// TODO(akalin): We may want to propagate this switch up eventually.
#if defined(OS_ANDROID) || defined(OS_IOS)
const bool kExpectMobileBookmarksFolder = true;
#else
const bool kExpectMobileBookmarksFolder = false;
#endif
BookmarkModelAssociator* model_associator = new BookmarkModelAssociator(
bookmark_model, sync_service->GetSyncClient(), user_share,
error_handler->Copy(), kExpectMobileBookmarksFolder);
BookmarkChangeProcessor* change_processor =
new BookmarkChangeProcessor(sync_service->GetSyncClient(),
model_associator, std::move(error_handler));
return SyncComponents(model_associator, change_processor);
}
// static
void ProfileSyncComponentsFactoryImpl::OverridePrefsForUssTest(bool use_uss) {
override_prefs_controller_to_uss_for_test_ = use_uss;
}
bool ProfileSyncComponentsFactoryImpl::
override_prefs_controller_to_uss_for_test_ = false;
} // namespace browser_sync