Commit f70f4435 authored by akalin@chromium.org's avatar akalin@chromium.org

[Sync] Make SyncBackendHost::Core use a WeakHandle to its host

This removes a lot of boilerplate with checking host_ (which was never
[locally] thread-safe, anyway).

Make as many things in SyncBackendHost private as possible.

BUG=103410,107279
TEST=


Review URL: http://codereview.chromium.org/8938013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114597 0039d316-1c4b-4281-b951-d872f2087c98
parent 1723bdc2
......@@ -60,30 +60,31 @@ using sync_api::SyncCredentials;
SyncBackendHost::SyncBackendHost(const std::string& name,
Profile* profile,
const base::WeakPtr<SyncPrefs>& sync_prefs)
: core_(new Core(name, ALLOW_THIS_IN_INITIALIZER_LIST(this))),
initialization_state_(NOT_ATTEMPTED),
: weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
sync_thread_("Chrome_SyncThread"),
frontend_loop_(MessageLoop::current()),
profile_(profile),
sync_prefs_(sync_prefs),
name_(name),
core_(new Core(name, profile_->GetPath().Append(kSyncDataFolderName),
weak_ptr_factory_.GetWeakPtr())),
initialization_state_(NOT_ATTEMPTED),
sync_prefs_(sync_prefs),
sync_notifier_factory_(
content::GetUserAgent(GURL()),
profile_->GetRequestContext(),
sync_prefs,
*CommandLine::ForCurrentProcess()),
frontend_(NULL),
sync_data_folder_path_(
profile_->GetPath().Append(kSyncDataFolderName)),
last_auth_error_(AuthError::None()) {
}
SyncBackendHost::SyncBackendHost()
: initialization_state_(NOT_ATTEMPTED),
: weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
sync_thread_("Chrome_SyncThread"),
frontend_loop_(MessageLoop::current()),
profile_(NULL),
name_("Unknown"),
initialization_state_(NOT_ATTEMPTED),
sync_notifier_factory_(
content::GetUserAgent(GURL()),
NULL,
......@@ -98,6 +99,15 @@ SyncBackendHost::~SyncBackendHost() {
DCHECK(!registrar_.get());
}
namespace {
sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory(
const scoped_refptr<net::URLRequestContextGetter>& getter) {
return new HttpBridgeFactory(getter);
}
} // namespace
void SyncBackendHost::Initialize(
SyncFrontend* frontend,
const WeakHandle<JsEventHandler>& event_handler,
......@@ -122,23 +132,20 @@ void SyncBackendHost::Initialize(
profile_,
sync_thread_.message_loop()));
initialization_state_ = CREATING_SYNC_MANAGER;
InitCore(Core::DoInitializeOptions(
InitCore(DoInitializeOptions(
sync_thread_.message_loop(),
registrar_.get(),
event_handler,
sync_service_url,
profile_->GetRequestContext(),
base::Bind(&MakeHttpBridgeFactory,
make_scoped_refptr(profile_->GetRequestContext())),
credentials,
&sync_notifier_factory_,
delete_sync_data_folder,
sync_prefs_->GetEncryptionBootstrapToken(),
false));
}
void SyncBackendHost::InitCore(const Core::DoInitializeOptions& options) {
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoInitialize, core_.get(),options));
}
void SyncBackendHost::UpdateCredentials(const SyncCredentials& credentials) {
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoUpdateCredentials, core_.get(),
......@@ -380,13 +387,175 @@ void SyncBackendHost::GetModelSafeRoutingInfo(
}
}
void SyncBackendHost::InitCore(const DoInitializeOptions& options) {
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoInitialize, core_.get(),options));
}
void SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop(
SyncSessionSnapshot* snapshot) {
if (!frontend_)
return;
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
last_snapshot_.reset(snapshot);
SDVLOG(1) << "Got snapshot " << snapshot->ToString();
const syncable::ModelTypeSet to_migrate =
snapshot->syncer_status.types_needing_local_migration;
if (!to_migrate.Empty())
frontend_->OnMigrationNeededForTypes(to_migrate);
// Process any changes to the datatypes we're syncing.
// TODO(sync): add support for removing types.
if (initialized())
AddExperimentalTypes();
// If we are waiting for a configuration change, check here to see
// if this sync cycle has initialized all of the types we've been
// waiting for.
if (pending_download_state_.get()) {
scoped_ptr<PendingConfigureDataTypesState> state(
pending_download_state_.release());
const syncable::ModelTypeSet types_to_add = state->types_to_add;
const syncable::ModelTypeSet added_types = state->added_types;
DCHECK(types_to_add.HasAll(added_types));
const syncable::ModelTypeSet initial_sync_ended =
snapshot->initial_sync_ended;
const syncable::ModelTypeSet failed_configuration_types =
Difference(added_types, initial_sync_ended);
SDVLOG(1)
<< "Added types: "
<< syncable::ModelTypeSetToString(added_types)
<< ", configured types: "
<< syncable::ModelTypeSetToString(initial_sync_ended)
<< ", failed configuration types: "
<< syncable::ModelTypeSetToString(failed_configuration_types);
state->ready_task.Run(failed_configuration_types);
if (!failed_configuration_types.Empty())
return;
}
if (initialized())
frontend_->OnSyncCycleCompleted();
}
void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() {
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
// Nudge the syncer. This is necessary for both datatype addition/deletion.
//
// Deletions need a nudge in order to ensure the deletion occurs in a timely
// manner (see issue 56416).
//
// In the case of additions, on the next sync cycle, the syncer should
// notice that the routing info has changed and start the process of
// downloading updates for newly added data types. Once this is
// complete, the configure_state_.ready_task_ is run via an
// OnInitializationComplete notification.
SDVLOG(1) << "Syncer in config mode. SBH executing "
<< "FinishConfigureDataTypesOnFrontendLoop";
if (pending_config_mode_state_->added_types.Empty() &&
!core_->sync_manager()->InitialSyncEndedForAllEnabledTypes()) {
syncable::ModelTypeSet enabled_types;
ModelSafeRoutingInfo routing_info;
registrar_->GetModelSafeRoutingInfo(&routing_info);
for (ModelSafeRoutingInfo::const_iterator i = routing_info.begin();
i != routing_info.end(); ++i) {
enabled_types.Put(i->first);
}
// TODO(tim): Log / UMA / count this somehow?
// Add only the types with empty progress markers. Note: it is possible
// that some types have their initial_sync_ended be false but with non
// empty progress marker. Which is ok as the rest of the changes would
// be downloaded on a regular nudge and initial_sync_ended should be set
// to true. However this is a very corner case. So it is not explicitly
// handled.
pending_config_mode_state_->added_types =
sync_api::GetTypesWithEmptyProgressMarkerToken(enabled_types,
GetUserShare());
}
// If we've added types, we always want to request a nudge/config (even if
// the initial sync is ended), in case we could not decrypt the data.
if (pending_config_mode_state_->added_types.Empty()) {
SDVLOG(1) << "No new types added; calling ready_task directly";
// No new types - just notify the caller that the types are available.
const syncable::ModelTypeSet failed_configuration_types;
pending_config_mode_state_->ready_task.Run(failed_configuration_types);
} else {
pending_download_state_.reset(pending_config_mode_state_.release());
// Always configure nigori if it's enabled.
syncable::ModelTypeSet types_to_config =
pending_download_state_->added_types;
if (IsNigoriEnabled()) {
// Note: Nigori is the only type that gets added with a nonempty
// progress marker during config. If the server returns a migration
// error then we will go into unrecoverable error. We dont handle it
// explicitly because server might help us out here by not sending a
// migraiton error for nigori during config.
types_to_config.Put(syncable::NIGORI);
}
SDVLOG(1) << "Types "
<< syncable::ModelTypeSetToString(types_to_config)
<< " added; calling DoRequestConfig";
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoRequestConfig,
core_.get(),
types_to_config,
pending_download_state_->reason));
}
pending_config_mode_state_.reset();
// Notify the SyncManager about the new types.
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoUpdateEnabledTypes, core_.get()));
}
bool SyncBackendHost::IsDownloadingNigoriForTest() const {
return initialization_state_ == DOWNLOADING_NIGORI;
}
SyncBackendHost::DoInitializeOptions::DoInitializeOptions(
MessageLoop* sync_loop,
SyncBackendRegistrar* registrar,
const WeakHandle<JsEventHandler>& event_handler,
const GURL& service_url,
MakeHttpBridgeFactoryFn make_http_bridge_factory_fn,
const sync_api::SyncCredentials& credentials,
sync_notifier::SyncNotifierFactory* sync_notifier_factory,
bool delete_sync_data_folder,
const std::string& restored_key_for_bootstrapping,
bool setup_for_test_mode)
: sync_loop(sync_loop),
registrar(registrar),
event_handler(event_handler),
service_url(service_url),
make_http_bridge_factory_fn(make_http_bridge_factory_fn),
credentials(credentials),
sync_notifier_factory(sync_notifier_factory),
delete_sync_data_folder(delete_sync_data_folder),
restored_key_for_bootstrapping(restored_key_for_bootstrapping),
setup_for_test_mode(setup_for_test_mode) {
}
SyncBackendHost::DoInitializeOptions::~DoInitializeOptions() {}
SyncBackendHost::Core::Core(const std::string& name,
SyncBackendHost* backend)
const FilePath& sync_data_folder_path,
const base::WeakPtr<SyncBackendHost>& backend)
: name_(name),
sync_data_folder_path_(sync_data_folder_path),
host_(backend),
sync_loop_(NULL),
registrar_(NULL) {
DCHECK(host_);
DCHECK(backend.get());
}
SyncBackendHost::Core::~Core() {
......@@ -394,15 +563,22 @@ SyncBackendHost::Core::~Core() {
DCHECK(!sync_loop_);
}
SyncBackendHost::PendingConfigureDataTypesState::
PendingConfigureDataTypesState()
: reason(sync_api::CONFIGURE_REASON_UNKNOWN) {}
SyncBackendHost::PendingConfigureDataTypesState::
~PendingConfigureDataTypesState() {}
void SyncBackendHost::Core::OnSyncCycleCompleted(
const SyncSessionSnapshot* snapshot) {
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE, base::Bind(
&Core::HandleSyncCycleCompletedOnFrontendLoop,
this,
new SyncSessionSnapshot(*snapshot)));
host_.Call(
FROM_HERE,
&SyncBackendHost::HandleSyncCycleCompletedOnFrontendLoop,
new SyncSessionSnapshot(*snapshot));
}
......@@ -410,10 +586,10 @@ void SyncBackendHost::Core::OnInitializationComplete(
const WeakHandle<JsBackend>& js_backend,
bool success) {
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE,
base::Bind(&Core::HandleInitializationCompletedOnFrontendLoop, this,
js_backend, success));
host_.Call(
FROM_HERE,
&SyncBackendHost::HandleInitializationCompletedOnFrontendLoop,
js_backend, success);
if (success) {
// Initialization is complete, so we can schedule recurring SaveChanges.
......@@ -426,9 +602,9 @@ void SyncBackendHost::Core::OnAuthError(const AuthError& auth_error) {
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
// Post to our core loop so we can modify state. Could be on another thread.
host_->frontend_loop_->PostTask(FROM_HERE,
base::Bind(&Core::HandleAuthErrorEventOnFrontendLoop, this, auth_error));
host_.Call(
FROM_HERE,
&SyncBackendHost::HandleAuthErrorEventOnFrontendLoop, auth_error);
}
void SyncBackendHost::Core::OnPassphraseRequired(
......@@ -436,8 +612,9 @@ void SyncBackendHost::Core::OnPassphraseRequired(
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE,
base::Bind(&Core::NotifyPassphraseRequired, this, reason));
host_.Call(
FROM_HERE,
&SyncBackendHost::NotifyPassphraseRequired, reason);
}
void SyncBackendHost::Core::OnPassphraseAccepted(
......@@ -445,40 +622,45 @@ void SyncBackendHost::Core::OnPassphraseAccepted(
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE,
base::Bind(&Core::NotifyPassphraseAccepted, this, bootstrap_token));
host_.Call(
FROM_HERE,
&SyncBackendHost::NotifyPassphraseAccepted, bootstrap_token);
}
void SyncBackendHost::Core::OnStopSyncingPermanently() {
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE, base::Bind(
&Core::HandleStopSyncingPermanentlyOnFrontendLoop, this));
host_.Call(
FROM_HERE,
&SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop);
}
void SyncBackendHost::Core::OnUpdatedToken(const std::string& token) {
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE, base::Bind(
&Core::NotifyUpdatedToken, this, token));
host_.Call(
FROM_HERE,
&SyncBackendHost::NotifyUpdatedToken, token);
}
void SyncBackendHost::Core::OnClearServerDataFailed() {
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE, base::Bind(
&Core::HandleClearServerDataFailedOnFrontendLoop, this));
host_.Call(
FROM_HERE,
&SyncBackendHost::HandleClearServerDataFailedOnFrontendLoop);
}
void SyncBackendHost::Core::OnClearServerDataSucceeded() {
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(FROM_HERE, base::Bind(
&Core::HandleClearServerDataSucceededOnFrontendLoop, this));
host_.Call(
FROM_HERE,
&SyncBackendHost::HandleClearServerDataSucceededOnFrontendLoop);
}
void SyncBackendHost::Core::OnEncryptedTypesChanged(
......@@ -488,10 +670,10 @@ void SyncBackendHost::Core::OnEncryptedTypesChanged(
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
// NOTE: We're in a transaction.
host_->frontend_loop_->PostTask(
host_.Call(
FROM_HERE,
base::Bind(&Core::NotifyEncryptedTypesChanged, this,
encrypted_types, encrypt_everything));
&SyncBackendHost::NotifyEncryptedTypesChanged,
encrypted_types, encrypt_everything);
}
void SyncBackendHost::Core::OnEncryptionComplete() {
......@@ -499,9 +681,9 @@ void SyncBackendHost::Core::OnEncryptionComplete() {
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
// NOTE: We're in a transaction.
host_->frontend_loop_->PostTask(
host_.Call(
FROM_HERE,
base::Bind(&Core::NotifyEncryptionComplete, this));
&SyncBackendHost::NotifyEncryptionComplete);
}
void SyncBackendHost::Core::OnActionableError(
......@@ -509,36 +691,12 @@ void SyncBackendHost::Core::OnActionableError(
if (!sync_loop_)
return;
DCHECK_EQ(MessageLoop::current(), sync_loop_);
host_->frontend_loop_->PostTask(
host_.Call(
FROM_HERE,
base::Bind(&Core::HandleActionableErrorEventOnFrontendLoop, this,
sync_error));
&SyncBackendHost::HandleActionableErrorEventOnFrontendLoop,
sync_error);
}
SyncBackendHost::Core::DoInitializeOptions::DoInitializeOptions(
MessageLoop* sync_loop,
SyncBackendRegistrar* registrar,
const WeakHandle<JsEventHandler>& event_handler,
const GURL& service_url,
const scoped_refptr<net::URLRequestContextGetter>&
request_context_getter,
const sync_api::SyncCredentials& credentials,
bool delete_sync_data_folder,
const std::string& restored_key_for_bootstrapping,
bool setup_for_test_mode)
: sync_loop(sync_loop),
registrar(registrar),
event_handler(event_handler),
service_url(service_url),
request_context_getter(request_context_getter),
credentials(credentials),
delete_sync_data_folder(delete_sync_data_folder),
restored_key_for_bootstrapping(restored_key_for_bootstrapping),
setup_for_test_mode(setup_for_test_mode) {
}
SyncBackendHost::Core::DoInitializeOptions::~DoInitializeOptions() {}
// Helper to construct a user agent string (ASCII) suitable for use by
// the syncapi for any HTTP communication. This string is used by the sync
// backend for classifying client types when calculating statistics.
......@@ -582,7 +740,7 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
// Make sure that the directory exists before initializing the backend.
// If it already exists, this will do no harm.
bool success = file_util::CreateDirectory(host_->sync_data_folder_path());
bool success = file_util::CreateDirectory(sync_data_folder_path_);
DCHECK(success);
DCHECK(!registrar_);
......@@ -591,19 +749,18 @@ void SyncBackendHost::Core::DoInitialize(const DoInitializeOptions& options) {
sync_manager_.reset(new sync_api::SyncManager(name_));
sync_manager_->AddObserver(this);
const FilePath& path_str = host_->sync_data_folder_path();
success = sync_manager_->Init(
path_str,
sync_data_folder_path_,
options.event_handler,
options.service_url.host() + options.service_url.path(),
options.service_url.EffectiveIntPort(),
options.service_url.SchemeIsSecure(),
host_->MakeHttpBridgeFactory(options.request_context_getter),
options.make_http_bridge_factory_fn.Run(),
options.registrar /* as ModelSafeWorkerRegistrar */,
options.registrar /* as SyncManager::ChangeDelegate */,
MakeUserAgentForSyncApi(),
options.credentials,
host_->sync_notifier_factory_.CreateSyncNotifier(),
options.sync_notifier_factory->CreateSyncNotifier(),
options.restored_key_for_bootstrapping,
options.setup_for_test_mode);
LOG_IF(ERROR, !success) << "Syncapi initialization failed!";
......@@ -680,7 +837,7 @@ void SyncBackendHost::Core::DoShutdown(bool sync_disabled) {
sync_loop_ = NULL;
host_ = NULL;
host_.Reset();
}
void SyncBackendHost::Core::DoRequestConfig(
......@@ -698,35 +855,17 @@ void SyncBackendHost::Core::DoStartConfiguration(
void SyncBackendHost::Core::DeleteSyncDataFolder() {
DCHECK_EQ(MessageLoop::current(), sync_loop_);
if (file_util::DirectoryExists(host_->sync_data_folder_path())) {
if (!file_util::Delete(host_->sync_data_folder_path(), true))
if (file_util::DirectoryExists(sync_data_folder_path_)) {
if (!file_util::Delete(sync_data_folder_path_, true))
SLOG(DFATAL) << "Could not delete the Sync Data folder.";
}
}
void SyncBackendHost::Core::FinishConfigureDataTypes() {
DCHECK_EQ(MessageLoop::current(), sync_loop_);
if (!host_ || !host_->frontend_)
return;
host_->frontend_loop_->PostTask(FROM_HERE, base::Bind(
&SyncBackendHost::Core::FinishConfigureDataTypesOnFrontendLoop, this));
}
void SyncBackendHost::Core::HandleInitializationCompletedOnFrontendLoop(
const WeakHandle<JsBackend>& js_backend,
bool success) {
if (!host_)
return;
host_->HandleInitializationCompletedOnFrontendLoop(js_backend, success);
}
void SyncBackendHost::Core::HandleNigoriConfigurationCompletedOnFrontendLoop(
const WeakHandle<JsBackend>& js_backend,
const syncable::ModelTypeSet failed_configuration_types) {
if (!host_)
return;
host_->HandleInitializationCompletedOnFrontendLoop(
js_backend, failed_configuration_types.Empty());
host_.Call(
FROM_HERE,
&SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop);
}
void SyncBackendHost::Core::StartSavingChanges() {
......@@ -744,147 +883,6 @@ void SyncBackendHost::Core::SaveChanges() {
sync_manager_->SaveChanges();
}
void SyncBackendHost::Core::HandleActionableErrorEventOnFrontendLoop(
const browser_sync::SyncProtocolError& sync_error) {
if (!host_ || !host_->frontend_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->frontend_->OnActionableError(sync_error);
}
void SyncBackendHost::Core::HandleAuthErrorEventOnFrontendLoop(
const GoogleServiceAuthError& new_auth_error) {
if (!host_ || !host_->frontend_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->last_auth_error_ = new_auth_error;
host_->frontend_->OnAuthError();
}
void SyncBackendHost::Core::NotifyPassphraseRequired(
sync_api::PassphraseRequiredReason reason) {
if (!host_ || !host_->frontend_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->frontend_->OnPassphraseRequired(reason);
}
void SyncBackendHost::Core::NotifyPassphraseAccepted(
const std::string& bootstrap_token) {
if (!host_ || !host_->frontend_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->PersistEncryptionBootstrapToken(bootstrap_token);
host_->frontend_->OnPassphraseAccepted();
}
void SyncBackendHost::Core::NotifyUpdatedToken(const std::string& token) {
if (!host_)
return;
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
TokenAvailableDetails details(GaiaConstants::kSyncService, token);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_TOKEN_UPDATED,
content::Source<Profile>(host_->profile_),
content::Details<const TokenAvailableDetails>(&details));
}
void SyncBackendHost::Core::NotifyEncryptedTypesChanged(
syncable::ModelTypeSet encrypted_types,
bool encrypt_everything) {
if (!host_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->frontend_->OnEncryptedTypesChanged(
encrypted_types, encrypt_everything);
}
void SyncBackendHost::Core::NotifyEncryptionComplete() {
if (!host_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->frontend_->OnEncryptionComplete();
}
void SyncBackendHost::Core::HandleSyncCycleCompletedOnFrontendLoop(
SyncSessionSnapshot* snapshot) {
if (!host_ || !host_->frontend_)
return;
DCHECK_EQ(MessageLoop::current(), host_->frontend_loop_);
host_->last_snapshot_.reset(snapshot);
SDVLOG(1) << "Got snapshot " << snapshot->ToString();
const syncable::ModelTypeSet to_migrate =
snapshot->syncer_status.types_needing_local_migration;
if (!to_migrate.Empty())
host_->frontend_->OnMigrationNeededForTypes(to_migrate);
// Process any changes to the datatypes we're syncing.
// TODO(sync): add support for removing types.
if (host_->initialized())
host_->AddExperimentalTypes();
// If we are waiting for a configuration change, check here to see
// if this sync cycle has initialized all of the types we've been
// waiting for.
if (host_->pending_download_state_.get()) {
scoped_ptr<PendingConfigureDataTypesState> state(
host_->pending_download_state_.release());
const syncable::ModelTypeSet types_to_add = state->types_to_add;
const syncable::ModelTypeSet added_types = state->added_types;
DCHECK(types_to_add.HasAll(added_types));
const syncable::ModelTypeSet initial_sync_ended =
snapshot->initial_sync_ended;
const syncable::ModelTypeSet failed_configuration_types =
Difference(added_types, initial_sync_ended);
SDVLOG(1)
<< "Added types: "
<< syncable::ModelTypeSetToString(added_types)
<< ", configured types: "
<< syncable::ModelTypeSetToString(initial_sync_ended)
<< ", failed configuration types: "
<< syncable::ModelTypeSetToString(failed_configuration_types);
state->ready_task.Run(failed_configuration_types);
if (!failed_configuration_types.Empty())
return;
}
if (host_->initialized())
host_->frontend_->OnSyncCycleCompleted();
}
void SyncBackendHost::Core::HandleStopSyncingPermanentlyOnFrontendLoop() {
if (!host_ || !host_->frontend_)
return;
host_->frontend_->OnStopSyncingPermanently();
}
void SyncBackendHost::Core::HandleClearServerDataSucceededOnFrontendLoop() {
if (!host_ || !host_->frontend_)
return;
host_->frontend_->OnClearServerDataSucceeded();
}
void SyncBackendHost::Core::HandleClearServerDataFailedOnFrontendLoop() {
if (!host_ || !host_->frontend_)
return;
host_->frontend_->OnClearServerDataFailed();
}
void SyncBackendHost::Core::FinishConfigureDataTypesOnFrontendLoop() {
if (!host_)
return;
host_->FinishConfigureDataTypesOnFrontendLoop();
}
void SyncBackendHost::AddExperimentalTypes() {
CHECK(initialized());
syncable::ModelTypeSet to_add;
......@@ -928,9 +926,9 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop(
sync_api::CONFIGURE_REASON_NEW_CLIENT,
// Calls back into this function.
base::Bind(
&SyncBackendHost::Core::
&SyncBackendHost::
HandleNigoriConfigurationCompletedOnFrontendLoop,
core_.get(), js_backend),
weak_ptr_factory_.GetWeakPtr(), js_backend),
true);
break;
case DOWNLOADING_NIGORI:
......@@ -939,9 +937,9 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop(
// if necessary.
RefreshEncryption(
base::Bind(
&SyncBackendHost::Core::
&SyncBackendHost::
HandleInitializationCompletedOnFrontendLoop,
core_.get(), js_backend, true));
weak_ptr_factory_.GetWeakPtr(), js_backend, true));
break;
case REFRESHING_ENCRYPTION:
initialization_state_ = INITIALIZED;
......@@ -962,99 +960,104 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop(
}
}
void SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop() {
void SyncBackendHost::PersistEncryptionBootstrapToken(
const std::string& token) {
CHECK(sync_prefs_.get());
sync_prefs_->SetEncryptionBootstrapToken(token);
}
void SyncBackendHost::HandleActionableErrorEventOnFrontendLoop(
const browser_sync::SyncProtocolError& sync_error) {
if (!frontend_)
return;
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
// Nudge the syncer. This is necessary for both datatype addition/deletion.
//
// Deletions need a nudge in order to ensure the deletion occurs in a timely
// manner (see issue 56416).
//
// In the case of additions, on the next sync cycle, the syncer should
// notice that the routing info has changed and start the process of
// downloading updates for newly added data types. Once this is
// complete, the configure_state_.ready_task_ is run via an
// OnInitializationComplete notification.
frontend_->OnActionableError(sync_error);
}
SDVLOG(1) << "Syncer in config mode. SBH executing "
<< "FinishConfigureDataTypesOnFrontendLoop";
void SyncBackendHost::NotifyPassphraseRequired(
sync_api::PassphraseRequiredReason reason) {
if (!frontend_)
return;
if (pending_config_mode_state_->added_types.Empty() &&
!core_->sync_manager()->InitialSyncEndedForAllEnabledTypes()) {
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
syncable::ModelTypeSet enabled_types;
ModelSafeRoutingInfo routing_info;
registrar_->GetModelSafeRoutingInfo(&routing_info);
for (ModelSafeRoutingInfo::const_iterator i = routing_info.begin();
i != routing_info.end(); ++i) {
enabled_types.Put(i->first);
}
frontend_->OnPassphraseRequired(reason);
}
// TODO(tim): Log / UMA / count this somehow?
// Add only the types with empty progress markers. Note: it is possible
// that some types have their initial_sync_ended be false but with non
// empty progress marker. Which is ok as the rest of the changes would
// be downloaded on a regular nudge and initial_sync_ended should be set
// to true. However this is a very corner case. So it is not explicitly
// handled.
pending_config_mode_state_->added_types =
sync_api::GetTypesWithEmptyProgressMarkerToken(enabled_types,
GetUserShare());
}
void SyncBackendHost::NotifyPassphraseAccepted(
const std::string& bootstrap_token) {
if (!frontend_)
return;
// If we've added types, we always want to request a nudge/config (even if
// the initial sync is ended), in case we could not decrypt the data.
if (pending_config_mode_state_->added_types.Empty()) {
SDVLOG(1) << "No new types added; calling ready_task directly";
// No new types - just notify the caller that the types are available.
const syncable::ModelTypeSet failed_configuration_types;
pending_config_mode_state_->ready_task.Run(failed_configuration_types);
} else {
pending_download_state_.reset(pending_config_mode_state_.release());
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
// Always configure nigori if it's enabled.
syncable::ModelTypeSet types_to_config =
pending_download_state_->added_types;
if (IsNigoriEnabled()) {
// Note: Nigori is the only type that gets added with a nonempty
// progress marker during config. If the server returns a migration
// error then we will go into unrecoverable error. We dont handle it
// explicitly because server might help us out here by not sending a
// migraiton error for nigori during config.
types_to_config.Put(syncable::NIGORI);
}
SDVLOG(1) << "Types " << syncable::ModelTypeSetToString(types_to_config)
<< " added; calling DoRequestConfig";
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoRequestConfig,
core_.get(),
types_to_config,
pending_download_state_->reason));
}
PersistEncryptionBootstrapToken(bootstrap_token);
frontend_->OnPassphraseAccepted();
}
pending_config_mode_state_.reset();
void SyncBackendHost::NotifyUpdatedToken(const std::string& token) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
TokenAvailableDetails details(GaiaConstants::kSyncService, token);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_TOKEN_UPDATED,
content::Source<Profile>(profile_),
content::Details<const TokenAvailableDetails>(&details));
}
// Notify the SyncManager about the new types.
sync_thread_.message_loop()->PostTask(FROM_HERE,
base::Bind(&SyncBackendHost::Core::DoUpdateEnabledTypes, core_.get()));
void SyncBackendHost::NotifyEncryptedTypesChanged(
syncable::ModelTypeSet encrypted_types,
bool encrypt_everything) {
if (!frontend_)
return;
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
frontend_->OnEncryptedTypesChanged(
encrypted_types, encrypt_everything);
}
sync_api::HttpPostProviderFactory* SyncBackendHost::MakeHttpBridgeFactory(
const scoped_refptr<net::URLRequestContextGetter>& getter) {
return new HttpBridgeFactory(getter);
void SyncBackendHost::NotifyEncryptionComplete() {
if (!frontend_)
return;
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
frontend_->OnEncryptionComplete();
}
void SyncBackendHost::PersistEncryptionBootstrapToken(
const std::string& token) {
CHECK(sync_prefs_.get());
sync_prefs_->SetEncryptionBootstrapToken(token);
void SyncBackendHost::HandleStopSyncingPermanentlyOnFrontendLoop() {
if (!frontend_)
return;
frontend_->OnStopSyncingPermanently();
}
SyncBackendHost::PendingConfigureDataTypesState::
PendingConfigureDataTypesState()
: reason(sync_api::CONFIGURE_REASON_UNKNOWN) {}
void SyncBackendHost::HandleClearServerDataSucceededOnFrontendLoop() {
if (!frontend_)
return;
frontend_->OnClearServerDataSucceeded();
}
SyncBackendHost::PendingConfigureDataTypesState::
~PendingConfigureDataTypesState() {}
void SyncBackendHost::HandleClearServerDataFailedOnFrontendLoop() {
if (!frontend_)
return;
frontend_->OnClearServerDataFailed();
}
void SyncBackendHost::HandleAuthErrorEventOnFrontendLoop(
const GoogleServiceAuthError& new_auth_error) {
if (!frontend_)
return;
DCHECK_EQ(MessageLoop::current(), frontend_loop_);
last_auth_error_ = new_auth_error;
frontend_->OnAuthError();
}
void SyncBackendHost::HandleNigoriConfigurationCompletedOnFrontendLoop(
const WeakHandle<JsBackend>& js_backend,
const syncable::ModelTypeSet failed_configuration_types) {
HandleInitializationCompletedOnFrontendLoop(
js_backend, failed_configuration_types.Empty());
}
namespace {
......
......@@ -231,10 +231,6 @@ class SyncBackendHost {
const GoogleServiceAuthError& GetAuthError() const;
const sessions::SyncSessionSnapshot* GetLastSessionSnapshot() const;
const FilePath& sync_data_folder_path() const {
return sync_data_folder_path_;
}
// Determines if the underlying sync engine has made any local changes to
// items that have not yet been synced with the server.
// ONLY CALL THIS IF OnInitializationComplete was called!
......@@ -254,6 +250,58 @@ class SyncBackendHost {
void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) const;
protected:
// The types and functions below are protected so that test
// subclasses can use them.
//
// TODO(akalin): Figure out a better way for tests to hook into
// SyncBackendHost.
typedef base::Callback<sync_api::HttpPostProviderFactory*(void)>
MakeHttpBridgeFactoryFn;
struct DoInitializeOptions {
DoInitializeOptions(
MessageLoop* sync_loop,
SyncBackendRegistrar* registrar,
const WeakHandle<JsEventHandler>& event_handler,
const GURL& service_url,
MakeHttpBridgeFactoryFn make_http_bridge_factory_fn,
const sync_api::SyncCredentials& credentials,
sync_notifier::SyncNotifierFactory* sync_notifier_factory,
bool delete_sync_data_folder,
const std::string& restored_key_for_bootstrapping,
bool setup_for_test_mode);
~DoInitializeOptions();
MessageLoop* sync_loop;
SyncBackendRegistrar* registrar;
WeakHandle<JsEventHandler> event_handler;
GURL service_url;
// Overridden by tests.
MakeHttpBridgeFactoryFn make_http_bridge_factory_fn;
sync_api::SyncCredentials credentials;
sync_notifier::SyncNotifierFactory* const sync_notifier_factory;
std::string lsid;
bool delete_sync_data_folder;
std::string restored_key_for_bootstrapping;
bool setup_for_test_mode;
};
// Allows tests to perform alternate core initialization work.
virtual void InitCore(const DoInitializeOptions& options);
// Called from Core::OnSyncCycleCompleted to handle updating frontend
// thread components.
void HandleSyncCycleCompletedOnFrontendLoop(
sessions::SyncSessionSnapshot* snapshot);
// Called to finish the job of ConfigureDataTypes once the syncer is in
// configuration mode.
void FinishConfigureDataTypesOnFrontendLoop();
bool IsDownloadingNigoriForTest() const;
private:
// An enum representing the steps to initializing the SyncBackendHost.
enum InitializationState {
NOT_ATTEMPTED,
......@@ -274,7 +322,9 @@ class SyncBackendHost {
class Core : public base::RefCountedThreadSafe<SyncBackendHost::Core>,
public sync_api::SyncManager::Observer {
public:
Core(const std::string& name, SyncBackendHost* backend);
Core(const std::string& name,
const FilePath& sync_data_folder_path,
const base::WeakPtr<SyncBackendHost>& backend);
// SyncManager::Observer implementation. The Core just acts like an air
// traffic controller here, forwarding incoming messages to appropriate
......@@ -301,32 +351,6 @@ class SyncBackendHost {
virtual void OnActionableError(
const browser_sync::SyncProtocolError& sync_error) OVERRIDE;
struct DoInitializeOptions {
DoInitializeOptions(
MessageLoop* sync_loop,
SyncBackendRegistrar* registrar,
const WeakHandle<JsEventHandler>& event_handler,
const GURL& service_url,
const scoped_refptr<net::URLRequestContextGetter>&
request_context_getter,
const sync_api::SyncCredentials& credentials,
bool delete_sync_data_folder,
const std::string& restored_key_for_bootstrapping,
bool setup_for_test_mode);
~DoInitializeOptions();
MessageLoop* sync_loop;
SyncBackendRegistrar* registrar;
WeakHandle<JsEventHandler> event_handler;
GURL service_url;
scoped_refptr<net::URLRequestContextGetter> request_context_getter;
sync_api::SyncCredentials credentials;
std::string lsid;
bool delete_sync_data_folder;
std::string restored_key_for_bootstrapping;
bool setup_for_test_mode;
};
// Note:
//
// The Do* methods are the various entry points from our
......@@ -407,18 +431,6 @@ class SyncBackendHost {
// A callback from the SyncerThread when it is safe to continue config.
void FinishConfigureDataTypes();
// Called to handle updating frontend thread components whenever we may
// need to alert the frontend that the backend is intialized.
void HandleInitializationCompletedOnFrontendLoop(
const WeakHandle<JsBackend>& js_backend,
bool success);
// Called when configuration of the Nigori node has completed as
// part of the initialization process.
void HandleNigoriConfigurationCompletedOnFrontendLoop(
const WeakHandle<JsBackend>& js_backend,
syncable::ModelTypeSet failed_configuration_types);
private:
friend class base::RefCountedThreadSafe<SyncBackendHost::Core>;
friend class SyncBackendHostForProfileSyncTest;
......@@ -439,52 +451,14 @@ class SyncBackendHost {
// initialization.
void SaveChanges();
// Let the front end handle the actionable error event.
void HandleActionableErrorEventOnFrontendLoop(
const browser_sync::SyncProtocolError& sync_error);
// Dispatched to from OnAuthError to handle updating frontend UI
// components.
void HandleAuthErrorEventOnFrontendLoop(
const GoogleServiceAuthError& new_auth_error);
// Invoked when a passphrase is required to decrypt a set of Nigori keys,
// or for encrypting. |reason| denotes why the passhrase was required.
void NotifyPassphraseRequired(sync_api::PassphraseRequiredReason reason);
// Invoked when the passphrase provided by the user has been accepted.
void NotifyPassphraseAccepted(const std::string& bootstrap_token);
// Invoked when an updated token is available from the sync server.
void NotifyUpdatedToken(const std::string& token);
// Invoked when the set of encrypted types or the encrypt
// everything flag changes.
void NotifyEncryptedTypesChanged(
syncable::ModelTypeSet encrypted_types,
bool encrypt_everything);
// Invoked when sync finishes encrypting new datatypes.
void NotifyEncryptionComplete();
// Called from Core::OnSyncCycleCompleted to handle updating frontend
// thread components.
void HandleSyncCycleCompletedOnFrontendLoop(
sessions::SyncSessionSnapshot* snapshot);
void HandleStopSyncingPermanentlyOnFrontendLoop();
// Called to handle success/failure of clearing server data
void HandleClearServerDataSucceededOnFrontendLoop();
void HandleClearServerDataFailedOnFrontendLoop();
void FinishConfigureDataTypesOnFrontendLoop();
// Name used for debugging.
const std::string name_;
// Our parent SyncBackendHost
SyncBackendHost* host_;
// Path of the folder that stores the sync data files.
const FilePath sync_data_folder_path_;
// Our parent SyncBackendHost.
WeakHandle<SyncBackendHost> host_;
// The loop where all the sync backend operations happen.
// Non-NULL only between calls to DoInitialize() and DoShutdown().
......@@ -503,6 +477,24 @@ class SyncBackendHost {
DISALLOW_COPY_AND_ASSIGN(Core);
};
struct PendingConfigureDataTypesState {
PendingConfigureDataTypesState();
~PendingConfigureDataTypesState();
// The ready_task will be run when configuration is done with the
// set of all types that failed configuration (i.e., if its
// argument is non-empty, then an error was encountered).
base::Callback<void(syncable::ModelTypeSet)> ready_task;
// The set of types that we are waiting to be initially synced in a
// configuration cycle.
syncable::ModelTypeSet types_to_add;
// Additional details about which types were added.
syncable::ModelTypeSet added_types;
sync_api::ConfigureReason reason;
};
// Checks if we have received a notice to turn on experimental datatypes
// (via the nigori node) and informs the frontend if that is the case.
// Note: it is illegal to call this before the backend is initialized.
......@@ -515,50 +507,54 @@ class SyncBackendHost {
const WeakHandle<JsBackend>& js_backend,
bool success);
// Called to finish the job of ConfigureDataTypes once the syncer is in
// configuration mode.
void FinishConfigureDataTypesOnFrontendLoop();
// Allows tests to perform alternate core initialization work.
virtual void InitCore(const Core::DoInitializeOptions& options);
// Factory method for HttpPostProviderFactories. Should be
// thread-safe.
virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory(
const scoped_refptr<net::URLRequestContextGetter>& getter);
// Helpers to persist a token that can be used to bootstrap sync encryption
// across browser restart to avoid requiring the user to re-enter their
// passphrase. |token| must be valid UTF-8 as we use the PrefService for
// storage.
void PersistEncryptionBootstrapToken(const std::string& token);
// Our core, which communicates directly to the syncapi.
scoped_refptr<Core> core_;
// For convenience, checks if initialization state is INITIALIZED.
bool initialized() const { return initialization_state_ == INITIALIZED; }
InitializationState initialization_state_;
// Let the front end handle the actionable error event.
void HandleActionableErrorEventOnFrontendLoop(
const browser_sync::SyncProtocolError& sync_error);
private:
struct PendingConfigureDataTypesState {
PendingConfigureDataTypesState();
~PendingConfigureDataTypesState();
// Invoked when a passphrase is required to decrypt a set of Nigori keys,
// or for encrypting. |reason| denotes why the passhrase was required.
void NotifyPassphraseRequired(sync_api::PassphraseRequiredReason reason);
// The ready_task will be run when configuration is done with the
// set of all types that failed configuration (i.e., if its
// argument is non-empty, then an error was encountered).
base::Callback<void(syncable::ModelTypeSet)> ready_task;
// Invoked when the passphrase provided by the user has been accepted.
void NotifyPassphraseAccepted(const std::string& bootstrap_token);
// The set of types that we are waiting to be initially synced in a
// configuration cycle.
syncable::ModelTypeSet types_to_add;
// Invoked when an updated token is available from the sync server.
void NotifyUpdatedToken(const std::string& token);
// Additional details about which types were added.
syncable::ModelTypeSet added_types;
sync_api::ConfigureReason reason;
};
// Invoked when the set of encrypted types or the encrypt
// everything flag changes.
void NotifyEncryptedTypesChanged(
syncable::ModelTypeSet encrypted_types,
bool encrypt_everything);
// For convenience, checks if initialization state is INITIALIZED.
bool initialized() const { return initialization_state_ == INITIALIZED; }
// Invoked when sync finishes encrypting new datatypes.
void NotifyEncryptionComplete();
void HandleStopSyncingPermanentlyOnFrontendLoop();
// Called to handle success/failure of clearing server data
void HandleClearServerDataSucceededOnFrontendLoop();
void HandleClearServerDataFailedOnFrontendLoop();
// Dispatched to from OnAuthError to handle updating frontend UI
// components.
void HandleAuthErrorEventOnFrontendLoop(
const GoogleServiceAuthError& new_auth_error);
// Called when configuration of the Nigori node has completed as
// part of the initialization process.
void HandleNigoriConfigurationCompletedOnFrontendLoop(
const WeakHandle<JsBackend>& js_backend,
syncable::ModelTypeSet failed_configuration_types);
// Must be called on |frontend_loop_|. |done_callback| is called on
// |frontend_loop_|.
......@@ -568,6 +564,8 @@ class SyncBackendHost {
// initialization is done yet.
void StopSyncManagerForShutdown(const base::Closure& closure);
base::WeakPtrFactory<SyncBackendHost> weak_ptr_factory_;
// A thread where all the sync operations happen.
base::Thread sync_thread_;
......@@ -577,11 +575,16 @@ class SyncBackendHost {
Profile* const profile_;
const base::WeakPtr<SyncPrefs> sync_prefs_;
// Name used for debugging (set from profile_->GetDebugName()).
const std::string name_;
// Our core, which communicates directly to the syncapi.
scoped_refptr<Core> core_;
InitializationState initialization_state_;
const base::WeakPtr<SyncPrefs> sync_prefs_;
sync_notifier::SyncNotifierFactory sync_notifier_factory_;
scoped_ptr<SyncBackendRegistrar> registrar_;
......@@ -589,9 +592,6 @@ class SyncBackendHost {
// The frontend which we serve (and are owned by).
SyncFrontend* frontend_;
// Path of the folder that stores the sync data files.
FilePath sync_data_folder_path_;
scoped_ptr<PendingConfigureDataTypesState> pending_download_state_;
scoped_ptr<PendingConfigureDataTypesState> pending_config_mode_state_;
......
......@@ -66,21 +66,25 @@ void SyncBackendHostForProfileSyncTest::
if (!fail_initial_download_)
sync_ended = syncable::ModelTypeSet::All();
std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot(
HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot(
SyncerStatus(), ErrorCounters(), 0, false,
sync_ended, download_progress_markers, false, false, 0, 0, 0, false,
SyncSourceInfo(), 0, base::Time::Now()));
}
sync_api::HttpPostProviderFactory*
SyncBackendHostForProfileSyncTest::MakeHttpBridgeFactory(
const scoped_refptr<net::URLRequestContextGetter>& getter) {
return new browser_sync::TestHttpBridgeFactory;
namespace {
sync_api::HttpPostProviderFactory* MakeTestHttpBridgeFactory() {
return new browser_sync::TestHttpBridgeFactory();
}
} // namespace
void SyncBackendHostForProfileSyncTest::InitCore(
const Core::DoInitializeOptions& options) {
Core::DoInitializeOptions test_options = options;
const DoInitializeOptions& options) {
DoInitializeOptions test_options = options;
test_options.make_http_bridge_factory_fn =
base::Bind(&MakeTestHttpBridgeFactory);
test_options.credentials.email = "testuser@gmail.com";
test_options.credentials.sync_token = "token";
test_options.restored_key_for_bootstrapping = "";
......@@ -97,13 +101,13 @@ void SyncBackendHostForProfileSyncTest::InitCore(
void SyncBackendHostForProfileSyncTest::StartConfiguration(
const base::Closure& callback) {
SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop();
if (initialization_state_ == DOWNLOADING_NIGORI) {
if (IsDownloadingNigoriForTest()) {
syncable::ModelTypeSet sync_ended;
if (!fail_initial_download_)
sync_ended.Put(syncable::NIGORI);
std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot(
HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot(
SyncerStatus(), ErrorCounters(), 0, false,
sync_ended, download_progress_markers, false, false, 0, 0, 0, false,
SyncSourceInfo(), 0, base::Time::Now()));
......
......@@ -45,9 +45,6 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
void SimulateSyncCycleCompletedInitialSyncEnded(
const tracked_objects::Location&);
virtual sync_api::HttpPostProviderFactory* MakeHttpBridgeFactory(
const scoped_refptr<net::URLRequestContextGetter>& getter) OVERRIDE;
virtual void StartConfiguration(const base::Closure& callback) OVERRIDE;
static void SetDefaultExpectationsForWorkerCreation(ProfileMock* profile);
......@@ -55,7 +52,7 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
static void SetHistoryServiceExpectations(ProfileMock* profile);
protected:
virtual void InitCore(const Core::DoInitializeOptions& options) OVERRIDE;
virtual void InitCore(const DoInitializeOptions& options) OVERRIDE;
private:
bool synchronous_init_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment