Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / components / sync_driver / data_type_manager_impl.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/sync_driver/data_type_manager_impl.h"
6
7 #include <algorithm>
8 #include <functional>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/compiler_specific.h"
14 #include "base/debug/trace_event.h"
15 #include "base/logging.h"
16 #include "base/metrics/histogram.h"
17 #include "base/strings/stringprintf.h"
18 #include "components/sync_driver/data_type_controller.h"
19 #include "components/sync_driver/data_type_encryption_handler.h"
20 #include "components/sync_driver/data_type_manager_observer.h"
21 #include "components/sync_driver/data_type_status_table.h"
22 #include "sync/internal_api/public/data_type_debug_info_listener.h"
23
24 namespace sync_driver {
25
26 namespace {
27
28 DataTypeStatusTable::TypeErrorMap
29 GenerateCryptoErrorsForTypes(syncer::ModelTypeSet encrypted_types) {
30   DataTypeStatusTable::TypeErrorMap crypto_errors;
31   for (syncer::ModelTypeSet::Iterator iter = encrypted_types.First();
32          iter.Good(); iter.Inc()) {
33     crypto_errors[iter.Get()] = syncer::SyncError(
34         FROM_HERE,
35         syncer::SyncError::CRYPTO_ERROR,
36         "",
37         iter.Get());
38   }
39   return crypto_errors;
40 }
41
42 }  // namespace
43
44 DataTypeManagerImpl::AssociationTypesInfo::AssociationTypesInfo() {}
45 DataTypeManagerImpl::AssociationTypesInfo::~AssociationTypesInfo() {}
46
47 DataTypeManagerImpl::DataTypeManagerImpl(
48     const base::Closure& unrecoverable_error_method,
49     const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
50         debug_info_listener,
51     const DataTypeController::TypeMap* controllers,
52     const DataTypeEncryptionHandler* encryption_handler,
53     BackendDataTypeConfigurer* configurer,
54     DataTypeManagerObserver* observer)
55     : configurer_(configurer),
56       controllers_(controllers),
57       state_(DataTypeManager::STOPPED),
58       needs_reconfigure_(false),
59       last_configure_reason_(syncer::CONFIGURE_REASON_UNKNOWN),
60       debug_info_listener_(debug_info_listener),
61       model_association_manager_(controllers, this),
62       observer_(observer),
63       encryption_handler_(encryption_handler),
64       unrecoverable_error_method_(unrecoverable_error_method),
65       weak_ptr_factory_(this) {
66   DCHECK(configurer_);
67   DCHECK(observer_);
68 }
69
70 DataTypeManagerImpl::~DataTypeManagerImpl() {}
71
72 void DataTypeManagerImpl::Configure(syncer::ModelTypeSet desired_types,
73                                     syncer::ConfigureReason reason) {
74   if (reason == syncer::CONFIGURE_REASON_BACKUP_ROLLBACK)
75     desired_types.PutAll(syncer::ControlTypes());
76   else
77     desired_types.PutAll(syncer::CoreTypes());
78
79   // Only allow control types and types that have controllers.
80   syncer::ModelTypeSet filtered_desired_types;
81   for (syncer::ModelTypeSet::Iterator type = desired_types.First();
82       type.Good(); type.Inc()) {
83     DataTypeController::TypeMap::const_iterator iter =
84         controllers_->find(type.Get());
85     if (syncer::IsControlType(type.Get()) ||
86         iter != controllers_->end()) {
87       if (iter != controllers_->end()) {
88         if (!iter->second->ReadyForStart() &&
89             !data_type_status_table_.GetUnreadyErrorTypes().Has(
90                 type.Get())) {
91           // Add the type to the unready types set to prevent purging it. It's
92           // up to the datatype controller to, if necessary, explicitly
93           // mark the type as broken to trigger a purge.
94           syncer::SyncError error(FROM_HERE,
95                                   syncer::SyncError::UNREADY_ERROR,
96                                   "Datatype not ready at config time.",
97                                   type.Get());
98           std::map<syncer::ModelType, syncer::SyncError> errors;
99           errors[type.Get()] = error;
100           data_type_status_table_.UpdateFailedDataTypes(errors);
101         } else if (iter->second->ReadyForStart()) {
102           data_type_status_table_.ResetUnreadyErrorFor(type.Get());
103         }
104       }
105       filtered_desired_types.Put(type.Get());
106     }
107   }
108   ConfigureImpl(filtered_desired_types, reason);
109 }
110
111 void DataTypeManagerImpl::ReenableType(syncer::ModelType type) {
112   // TODO(zea): move the "should we reconfigure" logic into the datatype handler
113   // itself.
114   // Only reconfigure if the type actually had a data type or unready error.
115   if (!data_type_status_table_.ResetDataTypeErrorFor(type) &&
116       !data_type_status_table_.ResetUnreadyErrorFor(type)) {
117     return;
118   }
119
120   // Only reconfigure if the type is actually desired.
121   if (!last_requested_types_.Has(type))
122     return;
123
124   DVLOG(1) << "Reenabling " << syncer::ModelTypeToString(type);
125   needs_reconfigure_ = true;
126   last_configure_reason_ = syncer::CONFIGURE_REASON_PROGRAMMATIC;
127   ProcessReconfigure();
128 }
129
130 void DataTypeManagerImpl::ResetDataTypeErrors() {
131   data_type_status_table_.Reset();
132 }
133
134 void DataTypeManagerImpl::PurgeForMigration(
135     syncer::ModelTypeSet undesired_types,
136     syncer::ConfigureReason reason) {
137   syncer::ModelTypeSet remainder = Difference(last_requested_types_,
138                                               undesired_types);
139   ConfigureImpl(remainder, reason);
140 }
141
142 void DataTypeManagerImpl::ConfigureImpl(
143     syncer::ModelTypeSet desired_types,
144     syncer::ConfigureReason reason) {
145   DCHECK_NE(reason, syncer::CONFIGURE_REASON_UNKNOWN);
146   DVLOG(1) << "Configuring for " << syncer::ModelTypeSetToString(desired_types)
147            << " with reason " << reason;
148   if (state_ == STOPPING) {
149     // You can not set a configuration while stopping.
150     LOG(ERROR) << "Configuration set while stopping.";
151     return;
152   }
153
154   // TODO(zea): consider not performing a full configuration once there's a
155   // reliable way to determine if the requested set of enabled types matches the
156   // current set.
157
158   last_requested_types_ = desired_types;
159   last_configure_reason_ = reason;
160   // Only proceed if we're in a steady state or retrying.
161   if (state_ != STOPPED && state_ != CONFIGURED && state_ != RETRYING) {
162     DVLOG(1) << "Received configure request while configuration in flight. "
163              << "Postponing until current configuration complete.";
164     needs_reconfigure_ = true;
165     return;
166   }
167
168   Restart(reason);
169 }
170
171 BackendDataTypeConfigurer::DataTypeConfigStateMap
172 DataTypeManagerImpl::BuildDataTypeConfigStateMap(
173     const syncer::ModelTypeSet& types_being_configured) const {
174   // 1. Get the failed types (due to fatal, crypto, and unready errors).
175   // 2. Add the difference between last_requested_types_ and the failed types
176   //    as CONFIGURE_INACTIVE.
177   // 3. Flip |types_being_configured| to CONFIGURE_ACTIVE.
178   // 4. Set non-enabled user types as DISABLED.
179   // 5. Set the fatal, crypto, and unready types to their respective states.
180   syncer::ModelTypeSet error_types =
181       data_type_status_table_.GetFailedTypes();
182   syncer::ModelTypeSet fatal_types =
183       data_type_status_table_.GetFatalErrorTypes();
184   syncer::ModelTypeSet crypto_types =
185       data_type_status_table_.GetCryptoErrorTypes();
186   syncer::ModelTypeSet unready_types=
187       data_type_status_table_.GetUnreadyErrorTypes();
188
189   // Types with persistence errors are only purged/resynced when they're
190   // actively being configured.
191   syncer::ModelTypeSet persistence_types =
192       data_type_status_table_.GetPersistenceErrorTypes();
193   persistence_types.RetainAll(types_being_configured);
194
195   // Types with unready errors do not count as unready if they've been disabled.
196   unready_types.RetainAll(last_requested_types_);
197
198   syncer::ModelTypeSet enabled_types = last_requested_types_;
199   enabled_types.RemoveAll(error_types);
200   syncer::ModelTypeSet disabled_types =
201       syncer::Difference(
202           syncer::Union(syncer::UserTypes(), syncer::ControlTypes()),
203           enabled_types);
204   syncer::ModelTypeSet to_configure = syncer::Intersection(
205       enabled_types, types_being_configured);
206   DVLOG(1) << "Enabling: " << syncer::ModelTypeSetToString(enabled_types);
207   DVLOG(1) << "Configuring: " << syncer::ModelTypeSetToString(to_configure);
208   DVLOG(1) << "Disabling: " << syncer::ModelTypeSetToString(disabled_types);
209
210   BackendDataTypeConfigurer::DataTypeConfigStateMap config_state_map;
211   BackendDataTypeConfigurer::SetDataTypesState(
212       BackendDataTypeConfigurer::CONFIGURE_INACTIVE, enabled_types,
213       &config_state_map);
214   BackendDataTypeConfigurer::SetDataTypesState(
215       BackendDataTypeConfigurer::CONFIGURE_ACTIVE, to_configure,
216       &config_state_map);
217   BackendDataTypeConfigurer::SetDataTypesState(
218       BackendDataTypeConfigurer::CONFIGURE_CLEAN, persistence_types,
219         &config_state_map);
220   BackendDataTypeConfigurer::SetDataTypesState(
221       BackendDataTypeConfigurer::DISABLED, disabled_types,
222       &config_state_map);
223   BackendDataTypeConfigurer::SetDataTypesState(
224       BackendDataTypeConfigurer::FATAL, fatal_types,
225       &config_state_map);
226   BackendDataTypeConfigurer::SetDataTypesState(
227       BackendDataTypeConfigurer::CRYPTO, crypto_types,
228         &config_state_map);
229   BackendDataTypeConfigurer::SetDataTypesState(
230       BackendDataTypeConfigurer::UNREADY, unready_types,
231         &config_state_map);
232   return config_state_map;
233 }
234
235 void DataTypeManagerImpl::Restart(syncer::ConfigureReason reason) {
236   DVLOG(1) << "Restarting...";
237
238   // Check for new or resolved data type crypto errors.
239   if (encryption_handler_->IsPassphraseRequired()) {
240     syncer::ModelTypeSet encrypted_types =
241         encryption_handler_->GetEncryptedDataTypes();
242     encrypted_types.RetainAll(last_requested_types_);
243     encrypted_types.RemoveAll(
244         data_type_status_table_.GetCryptoErrorTypes());
245     DataTypeStatusTable::TypeErrorMap crypto_errors =
246         GenerateCryptoErrorsForTypes(encrypted_types);
247     data_type_status_table_.UpdateFailedDataTypes(crypto_errors);
248   } else {
249     data_type_status_table_.ResetCryptoErrors();
250   }
251
252   syncer::ModelTypeSet failed_types =
253       data_type_status_table_.GetFailedTypes();
254   syncer::ModelTypeSet enabled_types =
255       syncer::Difference(last_requested_types_, failed_types);
256
257   last_restart_time_ = base::Time::Now();
258   configuration_stats_.clear();
259
260   DCHECK(state_ == STOPPED || state_ == CONFIGURED || state_ == RETRYING);
261
262   // Starting from a "steady state" (stopped or configured) state
263   // should send a start notification.
264   if (state_ == STOPPED || state_ == CONFIGURED)
265     NotifyStart();
266
267   state_ = DOWNLOAD_PENDING;
268   download_types_queue_ = PrioritizeTypes(enabled_types);
269   association_types_queue_ = std::queue<AssociationTypesInfo>();
270
271   model_association_manager_.Initialize(enabled_types);
272
273   // Tell the backend about the new set of data types we wish to sync.
274   // The task will be invoked when updates are downloaded.
275   configurer_->ConfigureDataTypes(
276       reason,
277       BuildDataTypeConfigStateMap(download_types_queue_.front()),
278       base::Bind(&DataTypeManagerImpl::DownloadReady,
279                  weak_ptr_factory_.GetWeakPtr(),
280                  base::Time::Now(),
281                  download_types_queue_.front(),
282                  syncer::ModelTypeSet()),
283       base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
284                  weak_ptr_factory_.GetWeakPtr()));
285 }
286
287 syncer::ModelTypeSet DataTypeManagerImpl::GetPriorityTypes() const {
288   syncer::ModelTypeSet high_priority_types;
289   high_priority_types.PutAll(syncer::PriorityCoreTypes());
290   high_priority_types.PutAll(syncer::PriorityUserTypes());
291   return high_priority_types;
292 }
293
294 TypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes(
295     const syncer::ModelTypeSet& types) {
296   syncer::ModelTypeSet high_priority_types = GetPriorityTypes();
297   high_priority_types.RetainAll(types);
298
299   syncer::ModelTypeSet low_priority_types =
300       syncer::Difference(types, high_priority_types);
301
302   TypeSetPriorityList result;
303   if (!high_priority_types.Empty())
304     result.push(high_priority_types);
305   if (!low_priority_types.Empty())
306     result.push(low_priority_types);
307
308   // Could be empty in case of purging for migration, sync nothing, etc.
309   // Configure empty set to purge data from backend.
310   if (result.empty())
311     result.push(syncer::ModelTypeSet());
312
313   return result;
314 }
315
316 void DataTypeManagerImpl::ProcessReconfigure() {
317   DCHECK(needs_reconfigure_);
318
319   // Wait for current download and association to finish.
320   if (!(download_types_queue_.empty() && association_types_queue_.empty()))
321     return;
322
323   // An attempt was made to reconfigure while we were already configuring.
324   // This can be because a passphrase was accepted or the user changed the
325   // set of desired types. Either way, |last_requested_types_| will contain
326   // the most recent set of desired types, so we just call configure.
327   // Note: we do this whether or not GetControllersNeedingStart is true,
328   // because we may need to stop datatypes.
329   DVLOG(1) << "Reconfiguring due to previous configure attempt occuring while"
330            << " busy.";
331
332   // Note: ConfigureImpl is called directly, rather than posted, in order to
333   // ensure that any purging/unapplying/journaling happens while the set of
334   // failed types is still up to date. If stack unwinding were to be done
335   // via PostTask, the failed data types may be reset before the purging was
336   // performed.
337   state_ = RETRYING;
338   needs_reconfigure_ = false;
339   ConfigureImpl(last_requested_types_, last_configure_reason_);
340 }
341
342 void DataTypeManagerImpl::OnDownloadRetry() {
343   DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
344   observer_->OnConfigureRetry();
345 }
346
347 void DataTypeManagerImpl::DownloadReady(
348     base::Time download_start_time,
349     syncer::ModelTypeSet types_to_download,
350     syncer::ModelTypeSet high_priority_types_before,
351     syncer::ModelTypeSet first_sync_types,
352     syncer::ModelTypeSet failed_configuration_types) {
353   DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
354
355   // Persistence errors are reset after each backend configuration attempt
356   // during which they would have been purged.
357   data_type_status_table_.ResetPersistenceErrorsFrom(types_to_download);
358
359   // Ignore |failed_configuration_types| if we need to reconfigure
360   // anyway.
361   if (needs_reconfigure_) {
362     download_types_queue_ = TypeSetPriorityList();
363     ProcessReconfigure();
364     return;
365   }
366
367   if (!failed_configuration_types.Empty()) {
368     if (!unrecoverable_error_method_.is_null())
369       unrecoverable_error_method_.Run();
370     DataTypeStatusTable::TypeErrorMap errors;
371     for (syncer::ModelTypeSet::Iterator iter =
372              failed_configuration_types.First(); iter.Good(); iter.Inc()) {
373       syncer::SyncError error(
374           FROM_HERE,
375           syncer::SyncError::UNRECOVERABLE_ERROR,
376           "Backend failed to download type.",
377           iter.Get());
378       errors[iter.Get()] = error;
379     }
380     data_type_status_table_.UpdateFailedDataTypes(errors);
381     Abort(UNRECOVERABLE_ERROR);
382     return;
383   }
384
385   state_ = CONFIGURING;
386
387   // Pop and associate download-ready types.
388   syncer::ModelTypeSet ready_types = types_to_download;
389   CHECK(!download_types_queue_.empty());
390   download_types_queue_.pop();
391   syncer::ModelTypeSet new_types_to_download;
392   if (!download_types_queue_.empty())
393     new_types_to_download = download_types_queue_.front();
394
395   AssociationTypesInfo association_info;
396   association_info.types = ready_types;
397   association_info.first_sync_types = first_sync_types;
398   association_info.download_start_time = download_start_time;
399   association_info.download_ready_time = base::Time::Now();
400   association_info.high_priority_types_before = high_priority_types_before;
401   association_types_queue_.push(association_info);
402   if (association_types_queue_.size() == 1u)
403     StartNextAssociation();
404
405   // Download types of low priority while configuring types of high priority.
406   if (!new_types_to_download.Empty()) {
407     configurer_->ConfigureDataTypes(
408         last_configure_reason_,
409         BuildDataTypeConfigStateMap(new_types_to_download),
410         base::Bind(&DataTypeManagerImpl::DownloadReady,
411                    weak_ptr_factory_.GetWeakPtr(),
412                    base::Time::Now(),
413                    new_types_to_download,
414                    syncer::Union(ready_types, high_priority_types_before)),
415         base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
416                    weak_ptr_factory_.GetWeakPtr()));
417   }
418 }
419
420 void DataTypeManagerImpl::StartNextAssociation() {
421   CHECK(!association_types_queue_.empty());
422
423   association_types_queue_.front().association_request_time =
424       base::Time::Now();
425   model_association_manager_.StartAssociationAsync(
426       association_types_queue_.front().types);
427 }
428
429 void DataTypeManagerImpl::OnSingleDataTypeWillStop(
430     syncer::ModelType type,
431     const syncer::SyncError& error) {
432   configurer_->DeactivateDataType(type);
433   if (error.IsSet()) {
434     DataTypeStatusTable::TypeErrorMap failed_types;
435     failed_types[type] = error;
436     data_type_status_table_.UpdateFailedDataTypes(
437             failed_types);
438
439     // Unrecoverable errors will shut down the entire backend, so no need to
440     // reconfigure.
441     if (error.error_type() != syncer::SyncError::UNRECOVERABLE_ERROR) {
442       needs_reconfigure_ = true;
443       last_configure_reason_ = syncer::CONFIGURE_REASON_PROGRAMMATIC;
444       ProcessReconfigure();
445     }
446   }
447 }
448
449 void DataTypeManagerImpl::OnSingleDataTypeAssociationDone(
450     syncer::ModelType type,
451     const syncer::DataTypeAssociationStats& association_stats) {
452   DCHECK(!association_types_queue_.empty());
453   DataTypeController::TypeMap::const_iterator c_it = controllers_->find(type);
454   DCHECK(c_it != controllers_->end());
455   if (c_it->second->state() == DataTypeController::RUNNING) {
456     // Tell the backend about the change processor for this type so it can
457     // begin routing changes to it.
458     configurer_->ActivateDataType(type, c_it->second->model_safe_group(),
459                                   c_it->second->GetChangeProcessor());
460   }
461
462   if (!debug_info_listener_.IsInitialized())
463     return;
464
465   AssociationTypesInfo& info = association_types_queue_.front();
466   configuration_stats_.push_back(syncer::DataTypeConfigurationStats());
467   configuration_stats_.back().model_type = type;
468   configuration_stats_.back().association_stats = association_stats;
469   if (info.types.Has(type)) {
470     // Times in |info| only apply to non-slow types.
471     configuration_stats_.back().download_wait_time =
472         info.download_start_time - last_restart_time_;
473     if (info.first_sync_types.Has(type)) {
474       configuration_stats_.back().download_time =
475           info.download_ready_time - info.download_start_time;
476     }
477     configuration_stats_.back().association_wait_time_for_high_priority =
478         info.association_request_time - info.download_ready_time;
479     configuration_stats_.back().high_priority_types_configured_before =
480         info.high_priority_types_before;
481     configuration_stats_.back().same_priority_types_configured_before =
482         info.configured_types;
483     info.configured_types.Put(type);
484   }
485 }
486
487 void DataTypeManagerImpl::OnModelAssociationDone(
488     const DataTypeManager::ConfigureResult& result) {
489   DCHECK(state_ == STOPPING || state_ == CONFIGURING);
490
491   if (state_ == STOPPING)
492     return;
493
494   // Ignore abort/unrecoverable error if we need to reconfigure anyways.
495   if (needs_reconfigure_) {
496     association_types_queue_ = std::queue<AssociationTypesInfo>();
497     ProcessReconfigure();
498     return;
499   }
500
501   if (result.status == ABORTED || result.status == UNRECOVERABLE_ERROR) {
502     Abort(result.status);
503     return;
504   }
505
506   DCHECK(result.status == OK);
507
508   CHECK(!association_types_queue_.empty());
509   association_types_queue_.pop();
510   if (!association_types_queue_.empty()) {
511     StartNextAssociation();
512   } else if (download_types_queue_.empty()) {
513     state_ = CONFIGURED;
514     NotifyDone(result);
515   }
516 }
517
518 void DataTypeManagerImpl::Stop() {
519   if (state_ == STOPPED)
520     return;
521
522   bool need_to_notify =
523       state_ == DOWNLOAD_PENDING || state_ == CONFIGURING;
524   StopImpl();
525
526   if (need_to_notify) {
527     ConfigureResult result(ABORTED,
528                            last_requested_types_);
529     NotifyDone(result);
530   }
531 }
532
533 void DataTypeManagerImpl::Abort(ConfigureStatus status) {
534   DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
535
536   StopImpl();
537
538   DCHECK_NE(OK, status);
539   ConfigureResult result(status,
540                          last_requested_types_);
541   NotifyDone(result);
542 }
543
544 void DataTypeManagerImpl::StopImpl() {
545   state_ = STOPPING;
546
547   // Invalidate weak pointer to drop download callbacks.
548   weak_ptr_factory_.InvalidateWeakPtrs();
549
550   // Stop all data types. This may trigger association callback but the
551   // callback will do nothing because state is set to STOPPING above.
552   model_association_manager_.Stop();
553
554   state_ = STOPPED;
555 }
556
557 void DataTypeManagerImpl::NotifyStart() {
558   observer_->OnConfigureStart();
559 }
560
561 void DataTypeManagerImpl::NotifyDone(const ConfigureResult& raw_result) {
562   AddToConfigureTime();
563
564   ConfigureResult result = raw_result;
565   result.data_type_status_table = data_type_status_table_;
566
567   DVLOG(1) << "Total time spent configuring: "
568            << configure_time_delta_.InSecondsF() << "s";
569   switch (result.status) {
570     case DataTypeManager::OK:
571       DVLOG(1) << "NotifyDone called with result: OK";
572       UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.OK",
573                                configure_time_delta_);
574       if (debug_info_listener_.IsInitialized() &&
575           !configuration_stats_.empty()) {
576         debug_info_listener_.Call(
577             FROM_HERE,
578             &syncer::DataTypeDebugInfoListener::OnDataTypeConfigureComplete,
579             configuration_stats_);
580       }
581       configuration_stats_.clear();
582       break;
583     case DataTypeManager::ABORTED:
584       DVLOG(1) << "NotifyDone called with result: ABORTED";
585       UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.ABORTED",
586                                configure_time_delta_);
587       break;
588     case DataTypeManager::UNRECOVERABLE_ERROR:
589       DVLOG(1) << "NotifyDone called with result: UNRECOVERABLE_ERROR";
590       UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.UNRECOVERABLE_ERROR",
591                                configure_time_delta_);
592       break;
593     case DataTypeManager::UNKNOWN:
594       NOTREACHED();
595       break;
596   }
597   observer_->OnConfigureDone(result);
598 }
599
600 DataTypeManager::State DataTypeManagerImpl::state() const {
601   return state_;
602 }
603
604 void DataTypeManagerImpl::AddToConfigureTime() {
605   DCHECK(!last_restart_time_.is_null());
606   configure_time_delta_ += (base::Time::Now() - last_restart_time_);
607 }
608
609 }  // namespace sync_driver