This source file includes following definitions.
- report_unrecoverable_error_function
- weak_ptr_factory_
- OnSyncCycleCompleted
- DoRefreshTypes
- OnControlTypesDownloadRetry
- OnInitializationComplete
- OnConnectionStatusChange
- OnPassphraseRequired
- OnPassphraseAccepted
- OnBootstrapTokenUpdated
- OnEncryptedTypesChanged
- OnEncryptionComplete
- OnCryptographerStateChanged
- OnPassphraseTypeChanged
- OnActionableError
- OnMigrationRequested
- OnProtocolEvent
- DoOnInvalidatorStateChange
- DoOnIncomingInvalidation
- DoInitialize
- DoUpdateCredentials
- DoStartSyncing
- DoSetEncryptionPassphrase
- DoInitialProcessControlTypes
- DoFinishInitialProcessControlTypes
- DoSetDecryptionPassphrase
- DoEnableEncryptEverything
- ShutdownOnUIThread
- DoShutdown
- DoDestroySyncManager
- DoConfigureSyncer
- DoFinishConfigureDataTypes
- DoRetryConfiguration
- SendBufferedProtocolEventsAndEnableForwarding
- DisableProtocolEventForwarding
- DeleteSyncDataFolder
- StartSavingChanges
- SaveChanges
#include "chrome/browser/sync/glue/sync_backend_host_core.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/sync/glue/device_info.h"
#include "chrome/browser/sync/glue/sync_backend_registrar.h"
#include "chrome/browser/sync/glue/synced_device_tracker.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "sync/internal_api/public/events/protocol_event.h"
#include "sync/internal_api/public/http_post_provider_factory.h"
#include "sync/internal_api/public/internal_components_factory.h"
#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
#include "sync/internal_api/public/sync_manager.h"
#include "sync/internal_api/public/sync_manager_factory.h"
#define SLOG(severity) LOG(severity) << name_ << ": "
#define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
static const int kSaveChangesIntervalSeconds = 10;
namespace syncer {
class InternalComponentsFactory;
}
namespace {
enum SyncBackendInitState {
SETUP_COMPLETED_FOUND_RESTORED_TYPES = 0,
SETUP_COMPLETED_NO_RESTORED_TYPES,
FIRST_SETUP_NO_RESTORED_TYPES,
FIRST_SETUP_RESTORED_TYPES,
SYNC_BACKEND_INIT_STATE_COUNT
};
}
namespace browser_sync {
DoInitializeOptions::DoInitializeOptions(
base::MessageLoop* sync_loop,
SyncBackendRegistrar* registrar,
const syncer::ModelSafeRoutingInfo& routing_info,
const std::vector<scoped_refptr<syncer::ModelSafeWorker> >& workers,
const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity,
const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
const GURL& service_url,
scoped_ptr<syncer::HttpPostProviderFactory> http_bridge_factory,
const syncer::SyncCredentials& credentials,
const std::string& invalidator_client_id,
scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
bool delete_sync_data_folder,
const std::string& restored_key_for_bootstrapping,
const std::string& restored_keystore_key_for_bootstrapping,
scoped_ptr<syncer::InternalComponentsFactory> internal_components_factory,
scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
syncer::ReportUnrecoverableErrorFunction
report_unrecoverable_error_function)
: sync_loop(sync_loop),
registrar(registrar),
routing_info(routing_info),
workers(workers),
extensions_activity(extensions_activity),
event_handler(event_handler),
service_url(service_url),
http_bridge_factory(http_bridge_factory.Pass()),
credentials(credentials),
invalidator_client_id(invalidator_client_id),
sync_manager_factory(sync_manager_factory.Pass()),
delete_sync_data_folder(delete_sync_data_folder),
restored_key_for_bootstrapping(restored_key_for_bootstrapping),
restored_keystore_key_for_bootstrapping(
restored_keystore_key_for_bootstrapping),
internal_components_factory(internal_components_factory.Pass()),
unrecoverable_error_handler(unrecoverable_error_handler.Pass()),
report_unrecoverable_error_function(
report_unrecoverable_error_function) {
}
DoInitializeOptions::~DoInitializeOptions() {}
DoConfigureSyncerTypes::DoConfigureSyncerTypes() {}
DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {}
SyncBackendHostCore::SyncBackendHostCore(
const std::string& name,
const base::FilePath& sync_data_folder_path,
bool has_sync_setup_completed,
const base::WeakPtr<SyncBackendHostImpl>& backend)
: name_(name),
sync_data_folder_path_(sync_data_folder_path),
host_(backend),
sync_loop_(NULL),
registrar_(NULL),
has_sync_setup_completed_(has_sync_setup_completed),
forward_protocol_events_(false),
weak_ptr_factory_(this) {
DCHECK(backend.get());
}
SyncBackendHostCore::~SyncBackendHostCore() {
DCHECK(!sync_manager_.get());
}
void SyncBackendHostCore::OnSyncCycleCompleted(
const syncer::sessions::SyncSessionSnapshot& snapshot) {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop,
snapshot);
}
void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->RefreshTypes(types);
}
void SyncBackendHostCore::OnControlTypesDownloadRetry() {
host_.Call(FROM_HERE,
&SyncBackendHostImpl::HandleControlTypesDownloadRetry);
}
void SyncBackendHostCore::OnInitializationComplete(
const syncer::WeakHandle<syncer::JsBackend>& js_backend,
const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
debug_info_listener,
bool success,
const syncer::ModelTypeSet restored_types) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
if (!success) {
DoDestroySyncManager();
host_.Call(FROM_HERE,
&SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
return;
}
sync_manager_->GetEncryptionHandler()->AddObserver(this);
sync_loop_->PostTask(FROM_HERE,
base::Bind(&SyncBackendHostCore::StartSavingChanges,
weak_ptr_factory_.GetWeakPtr()));
js_backend_ = js_backend;
debug_info_listener_ = debug_info_listener;
SyncBackendInitState backend_init_state;
if (has_sync_setup_completed_ && !restored_types.Empty()) {
backend_init_state = SETUP_COMPLETED_FOUND_RESTORED_TYPES;
} else if (has_sync_setup_completed_ && restored_types.Empty()) {
backend_init_state = SETUP_COMPLETED_NO_RESTORED_TYPES;
} else if (!has_sync_setup_completed_ && restored_types.Empty()) {
backend_init_state = FIRST_SETUP_NO_RESTORED_TYPES;
} else {
backend_init_state = FIRST_SETUP_RESTORED_TYPES;
}
UMA_HISTOGRAM_ENUMERATION("Sync.BackendInitializeRestoreState",
backend_init_state,
SYNC_BACKEND_INIT_STATE_COUNT);
registrar_->SetInitialTypes(restored_types);
syncer::ConfigureReason reason =
restored_types.Empty() ?
syncer::CONFIGURE_REASON_NEW_CLIENT :
syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes(
syncer::ControlTypes(), syncer::ModelTypeSet());
syncer::ModelSafeRoutingInfo routing_info;
registrar_->GetModelSafeRoutingInfo(&routing_info);
SDVLOG(1) << "Control Types "
<< syncer::ModelTypeSetToString(new_control_types)
<< " added; calling ConfigureSyncer";
syncer::ModelTypeSet types_to_purge =
syncer::Difference(syncer::ModelTypeSet::All(),
GetRoutingInfoTypes(routing_info));
sync_manager_->ConfigureSyncer(
reason,
new_control_types,
types_to_purge,
syncer::ModelTypeSet(),
syncer::ModelTypeSet(),
routing_info,
base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&SyncBackendHostCore::OnControlTypesDownloadRetry,
weak_ptr_factory_.GetWeakPtr()));
}
void SyncBackendHostCore::OnConnectionStatusChange(
syncer::ConnectionStatus status) {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status);
}
void SyncBackendHostCore::OnPassphraseRequired(
syncer::PassphraseRequiredReason reason,
const sync_pb::EncryptedData& pending_keys) {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys);
}
void SyncBackendHostCore::OnPassphraseAccepted() {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::NotifyPassphraseAccepted);
}
void SyncBackendHostCore::OnBootstrapTokenUpdated(
const std::string& bootstrap_token,
syncer::BootstrapTokenType type) {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(FROM_HERE,
&SyncBackendHostImpl::PersistEncryptionBootstrapToken,
bootstrap_token,
type);
}
void SyncBackendHostCore::OnEncryptedTypesChanged(
syncer::ModelTypeSet encrypted_types,
bool encrypt_everything) {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::NotifyEncryptedTypesChanged,
encrypted_types, encrypt_everything);
}
void SyncBackendHostCore::OnEncryptionComplete() {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::NotifyEncryptionComplete);
}
void SyncBackendHostCore::OnCryptographerStateChanged(
syncer::Cryptographer* cryptographer) {
}
void SyncBackendHostCore::OnPassphraseTypeChanged(
syncer::PassphraseType type, base::Time passphrase_time) {
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop,
type, passphrase_time);
}
void SyncBackendHostCore::OnActionableError(
const syncer::SyncProtocolError& sync_error) {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop,
sync_error);
}
void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop,
types);
}
void SyncBackendHostCore::OnProtocolEvent(
const syncer::ProtocolEvent& event) {
if (forward_protocol_events_) {
scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone());
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
event_clone.release());
}
}
void SyncBackendHostCore::DoOnInvalidatorStateChange(
syncer::InvalidatorState state) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->OnInvalidatorStateChange(state);
}
void SyncBackendHostCore::DoOnIncomingInvalidation(
const syncer::ObjectIdInvalidationMap& invalidation_map) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->OnIncomingInvalidation(invalidation_map);
}
void SyncBackendHostCore::DoInitialize(
scoped_ptr<DoInitializeOptions> options) {
DCHECK(!sync_loop_);
sync_loop_ = options->sync_loop;
DCHECK(sync_loop_);
chrome::VersionInfo version_info;
options->http_bridge_factory->Init(
DeviceInfo::MakeUserAgentForSyncApi(version_info));
if (options->delete_sync_data_folder) {
DeleteSyncDataFolder();
}
if (!base::CreateDirectory(sync_data_folder_path_)) {
DLOG(FATAL) << "Sync Data directory creation failed.";
}
DCHECK(!registrar_);
registrar_ = options->registrar;
DCHECK(registrar_);
sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_);
sync_manager_->AddObserver(this);
sync_manager_->Init(sync_data_folder_path_,
options->event_handler,
options->service_url.host() + options->service_url.path(),
options->service_url.EffectiveIntPort(),
options->service_url.SchemeIsSecure(),
options->http_bridge_factory.Pass(),
options->workers,
options->extensions_activity,
options->registrar ,
options->credentials,
options->invalidator_client_id,
options->restored_key_for_bootstrapping,
options->restored_keystore_key_for_bootstrapping,
options->internal_components_factory.get(),
&encryptor_,
options->unrecoverable_error_handler.Pass(),
options->report_unrecoverable_error_function,
&stop_syncing_signal_);
if (sync_manager_) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSyncThrowUnrecoverableError)) {
sync_manager_->ThrowUnrecoverableError();
}
}
}
void SyncBackendHostCore::DoUpdateCredentials(
const syncer::SyncCredentials& credentials) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
if (sync_manager_) {
sync_manager_->UpdateCredentials(credentials);
}
}
void SyncBackendHostCore::DoStartSyncing(
const syncer::ModelSafeRoutingInfo& routing_info) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->StartSyncingNormally(routing_info);
}
void SyncBackendHostCore::DoSetEncryptionPassphrase(
const std::string& passphrase,
bool is_explicit) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(
passphrase, is_explicit);
}
void SyncBackendHostCore::DoInitialProcessControlTypes() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
DVLOG(1) << "Initilalizing Control Types";
sync_manager_->GetEncryptionHandler()->Init();
if (!sync_manager_->GetUserShare()) {
DVLOG(1) << "Skipping initialization of DeviceInfo";
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
return;
}
if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) {
LOG(ERROR) << "Failed to download control types";
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop);
return;
}
synced_device_tracker_.reset(
new SyncedDeviceTracker(sync_manager_->GetUserShare(),
sync_manager_->cache_guid()));
synced_device_tracker_->InitLocalDeviceInfo(
base::Bind(&SyncBackendHostCore::DoFinishInitialProcessControlTypes,
weak_ptr_factory_.GetWeakPtr()));
}
void SyncBackendHostCore::DoFinishInitialProcessControlTypes() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
registrar_->ActivateDataType(syncer::DEVICE_INFO,
syncer::GROUP_PASSIVE,
synced_device_tracker_.get(),
sync_manager_->GetUserShare());
base::WeakPtr<syncer::SyncCore> sync_core = sync_manager_->GetSyncCore();
sync_core.get();
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop,
js_backend_,
debug_info_listener_,
syncer::SyncCoreProxy(base::MessageLoopProxy::current(), sync_core));
js_backend_.Reset();
debug_info_listener_.Reset();
}
void SyncBackendHostCore::DoSetDecryptionPassphrase(
const std::string& passphrase) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(
passphrase);
}
void SyncBackendHostCore::DoEnableEncryptEverything() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->GetEncryptionHandler()->EnableEncryptEverything();
}
void SyncBackendHostCore::ShutdownOnUIThread() {
stop_syncing_signal_.Signal();
release_request_context_signal_.Signal();
}
void SyncBackendHostCore::DoShutdown(bool sync_disabled) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
registrar_->DeactivateDataType(syncer::DEVICE_INFO);
synced_device_tracker_.reset();
DoDestroySyncManager();
registrar_ = NULL;
if (sync_disabled)
DeleteSyncDataFolder();
host_.Reset();
weak_ptr_factory_.InvalidateWeakPtrs();
}
void SyncBackendHostCore::DoDestroySyncManager() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
if (sync_manager_) {
save_changes_timer_.reset();
sync_manager_->RemoveObserver(this);
sync_manager_->ShutdownOnSyncThread();
sync_manager_.reset();
}
}
void SyncBackendHostCore::DoConfigureSyncer(
syncer::ConfigureReason reason,
const DoConfigureSyncerTypes& config_types,
const syncer::ModelSafeRoutingInfo routing_info,
const base::Callback<void(syncer::ModelTypeSet,
syncer::ModelTypeSet)>& ready_task,
const base::Closure& retry_callback) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->ConfigureSyncer(
reason,
config_types.to_download,
config_types.to_purge,
config_types.to_journal,
config_types.to_unapply,
routing_info,
base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes,
weak_ptr_factory_.GetWeakPtr(),
config_types.to_download,
ready_task),
base::Bind(&SyncBackendHostCore::DoRetryConfiguration,
weak_ptr_factory_.GetWeakPtr(),
retry_callback));
}
void SyncBackendHostCore::DoFinishConfigureDataTypes(
syncer::ModelTypeSet types_to_config,
const base::Callback<void(syncer::ModelTypeSet,
syncer::ModelTypeSet)>& ready_task) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
syncer::ModelSafeRoutingInfo routing_info;
registrar_->GetModelSafeRoutingInfo(&routing_info);
syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info);
enabled_types.RemoveAll(syncer::ProxyTypes());
const syncer::ModelTypeSet failed_configuration_types =
Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
const syncer::ModelTypeSet succeeded_configuration_types =
Difference(types_to_config, failed_configuration_types);
host_.Call(FROM_HERE,
&SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop,
enabled_types,
succeeded_configuration_types,
failed_configuration_types,
ready_task);
}
void SyncBackendHostCore::DoRetryConfiguration(
const base::Closure& retry_callback) {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
host_.Call(FROM_HERE,
&SyncBackendHostImpl::RetryConfigurationOnFrontendLoop,
retry_callback);
}
void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
forward_protocol_events_ = true;
if (sync_manager_) {
std::vector<syncer::ProtocolEvent*> buffered_events;
sync_manager_->GetBufferedProtocolEvents().release(&buffered_events);
for (std::vector<syncer::ProtocolEvent*>::iterator it =
buffered_events.begin(); it != buffered_events.end(); ++it) {
host_.Call(
FROM_HERE,
&SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
*it);
}
}
}
void SyncBackendHostCore::DisableProtocolEventForwarding() {
forward_protocol_events_ = false;
}
void SyncBackendHostCore::DeleteSyncDataFolder() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
if (base::DirectoryExists(sync_data_folder_path_)) {
if (!base::DeleteFile(sync_data_folder_path_, true))
SLOG(DFATAL) << "Could not delete the Sync Data folder.";
}
}
void SyncBackendHostCore::StartSavingChanges() {
if (!sync_loop_)
return;
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
DCHECK(!save_changes_timer_.get());
save_changes_timer_.reset(new base::RepeatingTimer<SyncBackendHostCore>());
save_changes_timer_->Start(FROM_HERE,
base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds),
this, &SyncBackendHostCore::SaveChanges);
}
void SyncBackendHostCore::SaveChanges() {
DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
sync_manager_->SaveChanges();
}
}