This source file includes following definitions.
- weak_ptr_factory_
- MigrateTypes
- AddMigrationObserver
- HasMigrationObserver
- RemoveMigrationObserver
- ChangeState
- TryStart
- RestartMigration
- OnConfigureDone
- GetUnsyncedDataTypes
- OnConfigureDoneImpl
- state
- GetPendingMigrationTypesForTest
#include "chrome/browser/sync/backend_migrator.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/tracked_objects.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "sync/internal_api/public/configure_reason.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/protocol/sync.pb.h"
#include "sync/syncable/directory.h"
using syncer::ModelTypeSet;
namespace browser_sync {
using syncer::ModelTypeToString;
MigrationObserver::~MigrationObserver() {}
BackendMigrator::BackendMigrator(const std::string& name,
syncer::UserShare* user_share,
ProfileSyncService* service,
DataTypeManager* manager,
const base::Closure &migration_done_callback)
: name_(name), user_share_(user_share), service_(service),
manager_(manager), state_(IDLE),
migration_done_callback_(migration_done_callback),
weak_ptr_factory_(this) {
}
BackendMigrator::~BackendMigrator() {
}
#define SLOG(severity) LOG(severity) << name_ << ": "
#define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
void BackendMigrator::MigrateTypes(syncer::ModelTypeSet types) {
const ModelTypeSet old_to_migrate = to_migrate_;
to_migrate_.PutAll(types);
SDVLOG(1) << "MigrateTypes called with " << ModelTypeSetToString(types)
<< ", old_to_migrate = " << ModelTypeSetToString(old_to_migrate)
<< ", to_migrate_ = " << ModelTypeSetToString(to_migrate_);
if (old_to_migrate.Equals(to_migrate_)) {
SDVLOG(1) << "MigrateTypes called with no new types; ignoring";
return;
}
if (state_ == IDLE)
ChangeState(WAITING_TO_START);
if (state_ == WAITING_TO_START) {
if (!TryStart())
SDVLOG(1) << "Manager not configured; waiting";
return;
}
DCHECK_GT(state_, WAITING_TO_START);
RestartMigration();
}
void BackendMigrator::AddMigrationObserver(MigrationObserver* observer) {
migration_observers_.AddObserver(observer);
}
bool BackendMigrator::HasMigrationObserver(
MigrationObserver* observer) const {
return migration_observers_.HasObserver(observer);
}
void BackendMigrator::RemoveMigrationObserver(MigrationObserver* observer) {
migration_observers_.RemoveObserver(observer);
}
void BackendMigrator::ChangeState(State new_state) {
state_ = new_state;
FOR_EACH_OBSERVER(MigrationObserver, migration_observers_,
OnMigrationStateChange());
}
bool BackendMigrator::TryStart() {
DCHECK_EQ(state_, WAITING_TO_START);
if (manager_->state() == DataTypeManager::CONFIGURED) {
RestartMigration();
return true;
}
return false;
}
void BackendMigrator::RestartMigration() {
ChangeState(DISABLING_TYPES);
SDVLOG(1) << "BackendMigrator disabling types "
<< ModelTypeSetToString(to_migrate_);
manager_->PurgeForMigration(to_migrate_, syncer::CONFIGURE_REASON_MIGRATION);
}
void BackendMigrator::OnConfigureDone(
const DataTypeManager::ConfigureResult& result) {
if (state_ == IDLE)
return;
SDVLOG(1) << "Posting OnConfigureDoneImpl";
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&BackendMigrator::OnConfigureDoneImpl,
weak_ptr_factory_.GetWeakPtr(), result));
}
namespace {
syncer::ModelTypeSet GetUnsyncedDataTypes(syncer::UserShare* user_share) {
syncer::ReadTransaction trans(FROM_HERE, user_share);
syncer::ModelTypeSet unsynced_data_types;
for (int i = syncer::FIRST_REAL_MODEL_TYPE;
i < syncer::MODEL_TYPE_COUNT; ++i) {
syncer::ModelType type = syncer::ModelTypeFromInt(i);
sync_pb::DataTypeProgressMarker progress_marker;
trans.GetDirectory()->GetDownloadProgress(type, &progress_marker);
if (progress_marker.token().empty()) {
unsynced_data_types.Put(type);
}
}
return unsynced_data_types;
}
}
void BackendMigrator::OnConfigureDoneImpl(
const DataTypeManager::ConfigureResult& result) {
SDVLOG(1) << "OnConfigureDone with requested types "
<< ModelTypeSetToString(result.requested_types)
<< ", status " << result.status
<< ", and to_migrate_ = " << ModelTypeSetToString(to_migrate_);
if (state_ == WAITING_TO_START) {
if (!TryStart())
SDVLOG(1) << "Manager still not configured; still waiting";
return;
}
DCHECK_GT(state_, WAITING_TO_START);
const ModelTypeSet intersection =
Intersection(result.requested_types, to_migrate_);
if (state_ == DISABLING_TYPES && !intersection.Empty()) {
SDVLOG(1) << "Disable request interrupted by user changing types";
RestartMigration();
return;
}
if (result.status != DataTypeManager::OK) {
SLOG(WARNING) << "Unable to migrate, configuration failed!";
ChangeState(IDLE);
to_migrate_.Clear();
return;
}
if (state_ == DISABLING_TYPES) {
const syncer::ModelTypeSet unsynced_types =
GetUnsyncedDataTypes(user_share_);
if (!unsynced_types.HasAll(to_migrate_)) {
SLOG(WARNING) << "Set of unsynced types: "
<< syncer::ModelTypeSetToString(unsynced_types)
<< " does not contain types to migrate: "
<< syncer::ModelTypeSetToString(to_migrate_)
<< "; not re-enabling yet";
return;
}
ChangeState(REENABLING_TYPES);
const ModelTypeSet full_set = service_->GetPreferredDataTypes();
SDVLOG(1) << "BackendMigrator re-enabling types: "
<< syncer::ModelTypeSetToString(full_set);
manager_->Configure(full_set, syncer::CONFIGURE_REASON_MIGRATION);
} else if (state_ == REENABLING_TYPES) {
ChangeState(IDLE);
SDVLOG(1) << "BackendMigrator: Migration complete for: "
<< syncer::ModelTypeSetToString(to_migrate_);
to_migrate_.Clear();
if (!migration_done_callback_.is_null())
migration_done_callback_.Run();
}
}
BackendMigrator::State BackendMigrator::state() const {
return state_;
}
syncer::ModelTypeSet BackendMigrator::GetPendingMigrationTypesForTest() const {
return to_migrate_;
}
#undef SDVLOG
#undef SLOG
};