1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 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)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/sync_driver/data_type_manager_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/sync_driver/data_type_controller.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/sync_driver/data_type_encryption_handler.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/sync_driver/data_type_manager_observer.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/sync_driver/data_type_status_table.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sync/internal_api/public/data_type_debug_info_listener.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace sync_driver {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciDataTypeStatusTable::TypeErrorMap
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)GenerateCryptoErrorsForTypes(syncer::ModelTypeSet encrypted_types) {
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DataTypeStatusTable::TypeErrorMap crypto_errors;
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (syncer::ModelTypeSet::Iterator iter = encrypted_types.First();
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)         iter.Good(); iter.Inc()) {
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    crypto_errors[iter.Get()] = syncer::SyncError(
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        FROM_HERE,
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        syncer::SyncError::CRYPTO_ERROR,
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "",
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        iter.Get());
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return crypto_errors;
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DataTypeManagerImpl::AssociationTypesInfo::AssociationTypesInfo() {}
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DataTypeManagerImpl::AssociationTypesInfo::~AssociationTypesInfo() {}
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DataTypeManagerImpl::DataTypeManagerImpl(
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::Closure& unrecoverable_error_method,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        debug_info_listener,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DataTypeController::TypeMap* controllers,
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const DataTypeEncryptionHandler* encryption_handler,
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    BackendDataTypeConfigurer* configurer,
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DataTypeManagerObserver* observer)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : configurer_(configurer),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controllers_(controllers),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(DataTypeManager::STOPPED),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      needs_reconfigure_(false),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_configure_reason_(syncer::CONFIGURE_REASON_UNKNOWN),
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      debug_info_listener_(debug_info_listener),
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      model_association_manager_(controllers, this),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      observer_(observer),
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      encryption_handler_(encryption_handler),
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      unrecoverable_error_method_(unrecoverable_error_method),
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(configurer_);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(observer_);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DataTypeManagerImpl::~DataTypeManagerImpl() {}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DataTypeManagerImpl::Configure(syncer::ModelTypeSet desired_types,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    syncer::ConfigureReason reason) {
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (reason == syncer::CONFIGURE_REASON_BACKUP_ROLLBACK)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    desired_types.PutAll(syncer::ControlTypes());
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    desired_types.PutAll(syncer::CoreTypes());
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only allow control types and types that have controllers.
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::ModelTypeSet filtered_desired_types;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (syncer::ModelTypeSet::Iterator type = desired_types.First();
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      type.Good(); type.Inc()) {
836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    DataTypeController::TypeMap::const_iterator iter =
846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        controllers_->find(type.Get());
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (syncer::IsControlType(type.Get()) ||
866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        iter != controllers_->end()) {
876d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      if (iter != controllers_->end()) {
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (!iter->second->ReadyForStart() &&
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            !data_type_status_table_.GetUnreadyErrorTypes().Has(
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                type.Get())) {
916d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          // Add the type to the unready types set to prevent purging it. It's
926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          // up to the datatype controller to, if necessary, explicitly
936d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          // mark the type as broken to trigger a purge.
946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          syncer::SyncError error(FROM_HERE,
956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  syncer::SyncError::UNREADY_ERROR,
966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  "Datatype not ready at config time.",
976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  type.Get());
986d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          std::map<syncer::ModelType, syncer::SyncError> errors;
996d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          errors[type.Get()] = error;
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          data_type_status_table_.UpdateFailedDataTypes(errors);
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        } else if (iter->second->ReadyForStart()) {
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          data_type_status_table_.ResetUnreadyErrorFor(type.Get());
1036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        }
1046d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      }
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      filtered_desired_types.Put(type.Get());
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ConfigureImpl(filtered_desired_types, reason);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void DataTypeManagerImpl::ReenableType(syncer::ModelType type) {
11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // TODO(zea): move the "should we reconfigure" logic into the datatype handler
11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // itself.
11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Only reconfigure if the type actually had a data type or unready error.
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!data_type_status_table_.ResetDataTypeErrorFor(type) &&
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !data_type_status_table_.ResetUnreadyErrorFor(type)) {
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Only reconfigure if the type is actually desired.
12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!last_requested_types_.Has(type))
12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return;
12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DVLOG(1) << "Reenabling " << syncer::ModelTypeToString(type);
12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  needs_reconfigure_ = true;
12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  last_configure_reason_ = syncer::CONFIGURE_REASON_PROGRAMMATIC;
12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ProcessReconfigure();
12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DataTypeManagerImpl::ResetDataTypeErrors() {
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  data_type_status_table_.Reset();
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::PurgeForMigration(
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    syncer::ModelTypeSet undesired_types,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ConfigureReason reason) {
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet remainder = Difference(last_requested_types_,
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              undesired_types);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureImpl(remainder, reason);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::ConfigureImpl(
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    syncer::ModelTypeSet desired_types,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ConfigureReason reason) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(reason, syncer::CONFIGURE_REASON_UNKNOWN);
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(1) << "Configuring for " << syncer::ModelTypeSetToString(desired_types)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << " with reason " << reason;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STOPPING) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // You can not set a configuration while stopping.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Configuration set while stopping.";
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1546d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // TODO(zea): consider not performing a full configuration once there's a
1556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // reliable way to determine if the requested set of enabled types matches the
1566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // current set.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_requested_types_ = desired_types;
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  last_configure_reason_ = reason;
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Only proceed if we're in a steady state or retrying.
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (state_ != STOPPED && state_ != CONFIGURED && state_ != RETRYING) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Received configure request while configuration in flight. "
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "Postponing until current configuration complete.";
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    needs_reconfigure_ = true;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Restart(reason);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)BackendDataTypeConfigurer::DataTypeConfigStateMap
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DataTypeManagerImpl::BuildDataTypeConfigStateMap(
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const syncer::ModelTypeSet& types_being_configured) const {
1746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // 1. Get the failed types (due to fatal, crypto, and unready errors).
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // 2. Add the difference between last_requested_types_ and the failed types
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  //    as CONFIGURE_INACTIVE.
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // 3. Flip |types_being_configured| to CONFIGURE_ACTIVE.
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // 4. Set non-enabled user types as DISABLED.
1796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // 5. Set the fatal, crypto, and unready types to their respective states.
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet error_types =
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      data_type_status_table_.GetFailedTypes();
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet fatal_types =
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      data_type_status_table_.GetFatalErrorTypes();
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet crypto_types =
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      data_type_status_table_.GetCryptoErrorTypes();
1866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  syncer::ModelTypeSet unready_types=
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      data_type_status_table_.GetUnreadyErrorTypes();
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Types with persistence errors are only purged/resynced when they're
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actively being configured.
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet persistence_types =
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      data_type_status_table_.GetPersistenceErrorTypes();
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  persistence_types.RetainAll(types_being_configured);
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Types with unready errors do not count as unready if they've been disabled.
1966d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  unready_types.RetainAll(last_requested_types_);
1976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet enabled_types = last_requested_types_;
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  enabled_types.RemoveAll(error_types);
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet disabled_types =
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      syncer::Difference(
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          syncer::Union(syncer::UserTypes(), syncer::ControlTypes()),
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          enabled_types);
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet to_configure = syncer::Intersection(
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      enabled_types, types_being_configured);
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(1) << "Enabling: " << syncer::ModelTypeSetToString(enabled_types);
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(1) << "Configuring: " << syncer::ModelTypeSetToString(to_configure);
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(1) << "Disabling: " << syncer::ModelTypeSetToString(disabled_types);
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BackendDataTypeConfigurer::DataTypeConfigStateMap config_state_map;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BackendDataTypeConfigurer::SetDataTypesState(
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BackendDataTypeConfigurer::CONFIGURE_INACTIVE, enabled_types,
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &config_state_map);
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BackendDataTypeConfigurer::SetDataTypesState(
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BackendDataTypeConfigurer::CONFIGURE_ACTIVE, to_configure,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &config_state_map);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BackendDataTypeConfigurer::SetDataTypesState(
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      BackendDataTypeConfigurer::CONFIGURE_CLEAN, persistence_types,
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        &config_state_map);
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  BackendDataTypeConfigurer::SetDataTypesState(
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BackendDataTypeConfigurer::DISABLED, disabled_types,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &config_state_map);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BackendDataTypeConfigurer::SetDataTypesState(
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BackendDataTypeConfigurer::FATAL, fatal_types,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &config_state_map);
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BackendDataTypeConfigurer::SetDataTypesState(
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BackendDataTypeConfigurer::CRYPTO, crypto_types,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &config_state_map);
2296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  BackendDataTypeConfigurer::SetDataTypesState(
2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      BackendDataTypeConfigurer::UNREADY, unready_types,
2316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        &config_state_map);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return config_state_map;
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::Restart(syncer::ConfigureReason reason) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Restarting...";
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Check for new or resolved data type crypto errors.
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (encryption_handler_->IsPassphraseRequired()) {
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    syncer::ModelTypeSet encrypted_types =
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        encryption_handler_->GetEncryptedDataTypes();
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    encrypted_types.RetainAll(last_requested_types_);
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    encrypted_types.RemoveAll(
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        data_type_status_table_.GetCryptoErrorTypes());
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DataTypeStatusTable::TypeErrorMap crypto_errors =
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        GenerateCryptoErrorsForTypes(encrypted_types);
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data_type_status_table_.UpdateFailedDataTypes(crypto_errors);
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data_type_status_table_.ResetCryptoErrors();
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet failed_types =
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      data_type_status_table_.GetFailedTypes();
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet enabled_types =
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      syncer::Difference(last_requested_types_, failed_types);
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_restart_time_ = base::Time::Now();
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  configuration_stats_.clear();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(state_ == STOPPED || state_ == CONFIGURED || state_ == RETRYING);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starting from a "steady state" (stopped or configured) state
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should send a start notification.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STOPPED || state_ == CONFIGURED)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyStart();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  state_ = DOWNLOAD_PENDING;
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  download_types_queue_ = PrioritizeTypes(enabled_types);
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_types_queue_ = std::queue<AssociationTypesInfo>();
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  model_association_manager_.Initialize(enabled_types);
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the backend about the new set of data types we wish to sync.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The task will be invoked when updates are downloaded.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  configurer_->ConfigureDataTypes(
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reason,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      BuildDataTypeConfigStateMap(download_types_queue_.front()),
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DataTypeManagerImpl::DownloadReady,
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr(),
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 base::Time::Now(),
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 download_types_queue_.front(),
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 syncer::ModelTypeSet()),
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochsyncer::ModelTypeSet DataTypeManagerImpl::GetPriorityTypes() const {
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet high_priority_types;
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  high_priority_types.PutAll(syncer::PriorityCoreTypes());
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  high_priority_types.PutAll(syncer::PriorityUserTypes());
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return high_priority_types;
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes(
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const syncer::ModelTypeSet& types) {
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet high_priority_types = GetPriorityTypes();
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  high_priority_types.RetainAll(types);
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  syncer::ModelTypeSet low_priority_types =
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      syncer::Difference(types, high_priority_types);
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TypeSetPriorityList result;
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!high_priority_types.Empty())
304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result.push(high_priority_types);
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!low_priority_types.Empty())
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result.push(low_priority_types);
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Could be empty in case of purging for migration, sync nothing, etc.
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Configure empty set to purge data from backend.
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result.empty())
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result.push(syncer::ModelTypeSet());
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DataTypeManagerImpl::ProcessReconfigure() {
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(needs_reconfigure_);
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Wait for current download and association to finish.
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!(download_types_queue_.empty() && association_types_queue_.empty()))
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An attempt was made to reconfigure while we were already configuring.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can be because a passphrase was accepted or the user changed the
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set of desired types. Either way, |last_requested_types_| will contain
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the most recent set of desired types, so we just call configure.
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: we do this whether or not GetControllersNeedingStart is true,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because we may need to stop datatypes.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Reconfiguring due to previous configure attempt occuring while"
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " busy.";
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Note: ConfigureImpl is called directly, rather than posted, in order to
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // ensure that any purging/unapplying/journaling happens while the set of
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // failed types is still up to date. If stack unwinding were to be done
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // via PostTask, the failed data types may be reset before the purging was
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // performed.
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  state_ = RETRYING;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  needs_reconfigure_ = false;
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ConfigureImpl(last_requested_types_, last_configure_reason_);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::OnDownloadRetry() {
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->OnConfigureRetry();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::DownloadReady(
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::Time download_start_time,
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    syncer::ModelTypeSet types_to_download,
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    syncer::ModelTypeSet high_priority_types_before,
351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    syncer::ModelTypeSet first_sync_types,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelTypeSet failed_configuration_types) {
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Persistence errors are reset after each backend configuration attempt
356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // during which they would have been purged.
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  data_type_status_table_.ResetPersistenceErrorsFrom(types_to_download);
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore |failed_configuration_types| if we need to reconfigure
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // anyway.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (needs_reconfigure_) {
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    download_types_queue_ = TypeSetPriorityList();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessReconfigure();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!failed_configuration_types.Empty()) {
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!unrecoverable_error_method_.is_null())
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      unrecoverable_error_method_.Run();
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DataTypeStatusTable::TypeErrorMap errors;
3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    for (syncer::ModelTypeSet::Iterator iter =
3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)             failed_configuration_types.First(); iter.Good(); iter.Inc()) {
3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      syncer::SyncError error(
3746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          FROM_HERE,
3756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          syncer::SyncError::UNRECOVERABLE_ERROR,
3766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          "Backend failed to download type.",
3776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          iter.Get());
3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      errors[iter.Get()] = error;
3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data_type_status_table_.UpdateFailedDataTypes(errors);
3816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Abort(UNRECOVERABLE_ERROR);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = CONFIGURING;
386b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Pop and associate download-ready types.
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet ready_types = types_to_download;
38934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  CHECK(!download_types_queue_.empty());
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  download_types_queue_.pop();
391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  syncer::ModelTypeSet new_types_to_download;
392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!download_types_queue_.empty())
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    new_types_to_download = download_types_queue_.front();
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AssociationTypesInfo association_info;
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_info.types = ready_types;
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_info.first_sync_types = first_sync_types;
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_info.download_start_time = download_start_time;
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_info.download_ready_time = base::Time::Now();
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_info.high_priority_types_before = high_priority_types_before;
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_types_queue_.push(association_info);
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (association_types_queue_.size() == 1u)
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    StartNextAssociation();
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Download types of low priority while configuring types of high priority.
406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!new_types_to_download.Empty()) {
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    configurer_->ConfigureDataTypes(
408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        last_configure_reason_,
409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        BuildDataTypeConfigStateMap(new_types_to_download),
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&DataTypeManagerImpl::DownloadReady,
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   base::Time::Now(),
413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   new_types_to_download,
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   syncer::Union(ready_types, high_priority_types_before)),
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DataTypeManagerImpl::StartNextAssociation() {
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!association_types_queue_.empty());
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_types_queue_.front().association_request_time =
424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Time::Now();
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  model_association_manager_.StartAssociationAsync(
426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      association_types_queue_.front().types);
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DataTypeManagerImpl::OnSingleDataTypeWillStop(
4306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    syncer::ModelType type,
4316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const syncer::SyncError& error) {
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  configurer_->DeactivateDataType(type);
4336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (error.IsSet()) {
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DataTypeStatusTable::TypeErrorMap failed_types;
4356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    failed_types[type] = error;
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    data_type_status_table_.UpdateFailedDataTypes(
4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            failed_types);
4386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Unrecoverable errors will shut down the entire backend, so no need to
4406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // reconfigure.
4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (error.error_type() != syncer::SyncError::UNRECOVERABLE_ERROR) {
4426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      needs_reconfigure_ = true;
44303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      last_configure_reason_ = syncer::CONFIGURE_REASON_PROGRAMMATIC;
4446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ProcessReconfigure();
4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
4466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DataTypeManagerImpl::OnSingleDataTypeAssociationDone(
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    syncer::ModelType type,
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const syncer::DataTypeAssociationStats& association_stats) {
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!association_types_queue_.empty());
453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DataTypeController::TypeMap::const_iterator c_it = controllers_->find(type);
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(c_it != controllers_->end());
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (c_it->second->state() == DataTypeController::RUNNING) {
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Tell the backend about the change processor for this type so it can
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // begin routing changes to it.
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    configurer_->ActivateDataType(type, c_it->second->model_safe_group(),
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                  c_it->second->GetChangeProcessor());
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!debug_info_listener_.IsInitialized())
463868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AssociationTypesInfo& info = association_types_queue_.front();
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  configuration_stats_.push_back(syncer::DataTypeConfigurationStats());
46768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  configuration_stats_.back().model_type = type;
46868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  configuration_stats_.back().association_stats = association_stats;
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (info.types.Has(type)) {
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Times in |info| only apply to non-slow types.
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    configuration_stats_.back().download_wait_time =
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        info.download_start_time - last_restart_time_;
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (info.first_sync_types.Has(type)) {
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      configuration_stats_.back().download_time =
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          info.download_ready_time - info.download_start_time;
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    configuration_stats_.back().association_wait_time_for_high_priority =
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        info.association_request_time - info.download_ready_time;
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    configuration_stats_.back().high_priority_types_configured_before =
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        info.high_priority_types_before;
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    configuration_stats_.back().same_priority_types_configured_before =
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        info.configured_types;
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    info.configured_types.Put(type);
484868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::OnModelAssociationDone(
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DataTypeManager::ConfigureResult& result) {
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(state_ == STOPPING || state_ == CONFIGURING);
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (state_ == STOPPING)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Ignore abort/unrecoverable error if we need to reconfigure anyways.
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (needs_reconfigure_) {
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    association_types_queue_ = std::queue<AssociationTypesInfo>();
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ProcessReconfigure();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result.status == ABORTED || result.status == UNRECOVERABLE_ERROR) {
5026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Abort(result.status);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(result.status == OK);
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
50834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  CHECK(!association_types_queue_.empty());
509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  association_types_queue_.pop();
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!association_types_queue_.empty()) {
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    StartNextAssociation();
512868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (download_types_queue_.empty()) {
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    state_ = CONFIGURED;
5146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NotifyDone(result);
515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::Stop() {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STOPPED)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool need_to_notify =
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      state_ == DOWNLOAD_PENDING || state_ == CONFIGURING;
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StopImpl();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (need_to_notify) {
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ConfigureResult result(ABORTED,
5286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                           last_requested_types_);
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NotifyDone(result);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void DataTypeManagerImpl::Abort(ConfigureStatus status) {
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  StopImpl();
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(OK, status);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureResult result(status,
5406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                         last_requested_types_);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyDone(result);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DataTypeManagerImpl::StopImpl() {
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  state_ = STOPPING;
546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Invalidate weak pointer to drop download callbacks.
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Stop all data types. This may trigger association callback but the
551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // callback will do nothing because state is set to STOPPING above.
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  model_association_manager_.Stop();
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  state_ = STOPPED;
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::NotifyStart() {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->OnConfigureStart();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DataTypeManagerImpl::NotifyDone(const ConfigureResult& raw_result) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddToConfigureTime();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ConfigureResult result = raw_result;
5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  result.data_type_status_table = data_type_status_table_;
5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Total time spent configuring: "
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << configure_time_delta_.InSecondsF() << "s";
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (result.status) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DataTypeManager::OK:
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "NotifyDone called with result: OK";
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.OK",
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               configure_time_delta_);
57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (debug_info_listener_.IsInitialized() &&
57568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          !configuration_stats_.empty()) {
57668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        debug_info_listener_.Call(
57768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            FROM_HERE,
57868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            &syncer::DataTypeDebugInfoListener::OnDataTypeConfigureComplete,
57968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            configuration_stats_);
58068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
58168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      configuration_stats_.clear();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DataTypeManager::ABORTED:
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "NotifyDone called with result: ABORTED";
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.ABORTED",
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               configure_time_delta_);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DataTypeManager::UNRECOVERABLE_ERROR:
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "NotifyDone called with result: UNRECOVERABLE_ERROR";
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.UNRECOVERABLE_ERROR",
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               configure_time_delta_);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case DataTypeManager::UNKNOWN:
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->OnConfigureDone(result);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DataTypeManager::State DataTypeManagerImpl::state() const {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DataTypeManagerImpl::AddToConfigureTime() {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!last_restart_time_.is_null());
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  configure_time_delta_ += (base::Time::Now() - last_restart_time_);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace sync_driver
610