15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/backend_migrator.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/configure_reason.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/read_transaction.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/sync.pb.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/directory.h" // TODO(tim): Bug 131130.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::ModelTypeSet;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::ModelTypeToString;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MigrationObserver::~MigrationObserver() {}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackendMigrator::BackendMigrator(const std::string& name,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 syncer::UserShare* user_share,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 ProfileSyncService* service,
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 sync_driver::DataTypeManager* manager,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const base::Closure &migration_done_callback)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : name_(name), user_share_(user_share), service_(service),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      manager_(manager), state_(IDLE),
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      migration_done_callback_(migration_done_callback),
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackendMigrator::~BackendMigrator() {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper macros to log with the syncer thread name; useful when there
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are multiple syncer threads involved.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SLOG(severity) LOG(severity) << name_ << ": "
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::MigrateTypes(syncer::ModelTypeSet types) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ModelTypeSet old_to_migrate = to_migrate_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_migrate_.PutAll(types);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SDVLOG(1) << "MigrateTypes called with " << ModelTypeSetToString(types)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ", old_to_migrate = " << ModelTypeSetToString(old_to_migrate)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << ", to_migrate_ = " << ModelTypeSetToString(to_migrate_);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_to_migrate.Equals(to_migrate_)) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SDVLOG(1) << "MigrateTypes called with no new types; ignoring";
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == IDLE)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeState(WAITING_TO_START);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == WAITING_TO_START) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!TryStart())
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SDVLOG(1) << "Manager not configured; waiting";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(state_, WAITING_TO_START);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're already migrating, interrupt the current migration.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestartMigration();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::AddMigrationObserver(MigrationObserver* observer) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  migration_observers_.AddObserver(observer);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackendMigrator::HasMigrationObserver(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MigrationObserver* observer) const {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return migration_observers_.HasObserver(observer);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::RemoveMigrationObserver(MigrationObserver* observer) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  migration_observers_.RemoveObserver(observer);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::ChangeState(State new_state) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = new_state;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(MigrationObserver, migration_observers_,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OnMigrationStateChange());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BackendMigrator::TryStart() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, WAITING_TO_START);
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (manager_->state() == sync_driver::DataTypeManager::CONFIGURED) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RestartMigration();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::RestartMigration() {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll now disable any running types that need to be migrated.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeState(DISABLING_TYPES);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SDVLOG(1) << "BackendMigrator disabling types "
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ModelTypeSetToString(to_migrate_);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  manager_->PurgeForMigration(to_migrate_, syncer::CONFIGURE_REASON_MIGRATION);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::OnConfigureDone(
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const sync_driver::DataTypeManager::ConfigureResult& result) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == IDLE)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |manager_|'s methods aren't re-entrant, and we're notified from
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them, so post a task to avoid problems.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SDVLOG(1) << "Posting OnConfigureDoneImpl";
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&BackendMigrator::OnConfigureDoneImpl,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(), result));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::ModelTypeSet GetUnsyncedDataTypes(syncer::UserShare* user_share) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ReadTransaction trans(FROM_HERE, user_share);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::ModelTypeSet unsynced_data_types;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = syncer::FIRST_REAL_MODEL_TYPE;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i < syncer::MODEL_TYPE_COUNT; ++i) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType type = syncer::ModelTypeFromInt(i);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_pb::DataTypeProgressMarker progress_marker;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    trans.GetDirectory()->GetDownloadProgress(type, &progress_marker);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (progress_marker.token().empty()) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsynced_data_types.Put(type);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return unsynced_data_types;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BackendMigrator::OnConfigureDoneImpl(
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const sync_driver::DataTypeManager::ConfigureResult& result) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SDVLOG(1) << "OnConfigureDone with requested types "
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ModelTypeSetToString(result.requested_types)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", status " << result.status
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ", and to_migrate_ = " << ModelTypeSetToString(to_migrate_);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == WAITING_TO_START) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!TryStart())
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SDVLOG(1) << "Manager still not configured; still waiting";
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(state_, WAITING_TO_START);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ModelTypeSet intersection =
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Intersection(result.requested_types, to_migrate_);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This intersection check is to determine if our disable request
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was interrupted by a user changing preferred types.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == DISABLING_TYPES && !intersection.Empty()) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SDVLOG(1) << "Disable request interrupted by user changing types";
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RestartMigration();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (result.status != sync_driver::DataTypeManager::OK) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this fails, and we're disabling types, a type may or may not be
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // disabled until the user restarts the browser.  If this wasn't an abort,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // any failure will be reported as an unrecoverable error to the UI. If it
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // was an abort, then typically things are shutting down anyway. There isn't
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // much we can do in any case besides wait until a restart to try again.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The server will send down MIGRATION_DONE again for types needing
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // migration as the type will still be enabled on restart.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SLOG(WARNING) << "Unable to migrate, configuration failed!";
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeState(IDLE);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_migrate_.Clear();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == DISABLING_TYPES) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::ModelTypeSet unsynced_types =
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetUnsyncedDataTypes(user_share_);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!unsynced_types.HasAll(to_migrate_)) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SLOG(WARNING) << "Set of unsynced types: "
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << syncer::ModelTypeSetToString(unsynced_types)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << " does not contain types to migrate: "
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << syncer::ModelTypeSetToString(to_migrate_)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << "; not re-enabling yet";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeState(REENABLING_TYPES);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't use |to_migrate_| for the re-enabling because the user
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // may have chosen to disable types during the migration.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModelTypeSet full_set = service_->GetPreferredDataTypes();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SDVLOG(1) << "BackendMigrator re-enabling types: "
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << syncer::ModelTypeSetToString(full_set);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    manager_->Configure(full_set, syncer::CONFIGURE_REASON_MIGRATION);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (state_ == REENABLING_TYPES) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're done!
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeState(IDLE);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SDVLOG(1) << "BackendMigrator: Migration complete for: "
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << syncer::ModelTypeSetToString(to_migrate_);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_migrate_.Clear();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!migration_done_callback_.is_null())
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      migration_done_callback_.Run();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BackendMigrator::State BackendMigrator::state() const {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::ModelTypeSet BackendMigrator::GetPendingMigrationTypesForTest() const {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return to_migrate_;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef SDVLOG
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef SLOG
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};  // namespace browser_sync
226