1 // Copyright 2013 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/glue/sync_engine_backend.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/files/file_util.h"
12 #include "base/location.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/threading/sequenced_task_runner_handle.h"
16 #include "components/invalidation/public/invalidation_util.h"
17 #include "components/invalidation/public/topic_invalidation_map.h"
18 #include "components/sync/base/invalidation_adapter.h"
19 #include "components/sync/base/legacy_directory_deletion.h"
20 #include "components/sync/base/sync_base_switches.h"
21 #include "components/sync/driver/configure_context.h"
22 #include "components/sync/driver/model_type_controller.h"
23 #include "components/sync/driver/sync_driver_switches.h"
24 #include "components/sync/engine/cycle/sync_cycle_snapshot.h"
25 #include "components/sync/engine/engine_components_factory.h"
26 #include "components/sync/engine/events/protocol_event.h"
27 #include "components/sync/engine/net/http_post_provider_factory.h"
28 #include "components/sync/engine/sync_manager.h"
29 #include "components/sync/engine/sync_manager_factory.h"
30 #include "components/sync/invalidations/switches.h"
31 #include "components/sync/model_impl/forwarding_model_type_controller_delegate.h"
32 #include "components/sync/nigori/nigori_model_type_processor.h"
33 #include "components/sync/nigori/nigori_storage_impl.h"
34 #include "components/sync/nigori/nigori_sync_bridge_impl.h"
35 #include "components/sync/protocol/sync_invalidations_payload.pb.h"
36 
37 // Helper macros to log with the syncer thread name; useful when there
38 // are multiple syncers involved.
39 
40 #define SLOG(severity) LOG(severity) << name_ << ": "
41 
42 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": "
43 
44 namespace net {
45 class URLFetcher;
46 }
47 
48 namespace syncer {
49 
50 class EngineComponentsFactory;
51 
52 namespace {
53 
54 const base::FilePath::CharType kNigoriStorageFilename[] =
55     FILE_PATH_LITERAL("Nigori.bin");
56 
57 class SyncInvalidationAdapter : public InvalidationInterface {
58  public:
SyncInvalidationAdapter(const std::string & payload)59   explicit SyncInvalidationAdapter(const std::string& payload)
60       : payload_(payload) {}
61   ~SyncInvalidationAdapter() override = default;
62 
IsUnknownVersion() const63   bool IsUnknownVersion() const override { return true; }
64 
GetPayload() const65   const std::string& GetPayload() const override { return payload_; }
66 
GetVersion() const67   int64_t GetVersion() const override {
68     // TODO(crbug.com/1102322): implement versions. This method is not called
69     // until IsUnknownVersion() returns true.
70     NOTREACHED();
71     return 0;
72   }
73 
Acknowledge()74   void Acknowledge() override { NOTIMPLEMENTED(); }
75 
Drop()76   void Drop() override { NOTIMPLEMENTED(); }
77 
78  private:
79   const std::string payload_;
80 };
81 
82 }  // namespace
83 
SyncEngineBackend(const std::string & name,const base::FilePath & sync_data_folder,const base::WeakPtr<SyncEngineImpl> & host)84 SyncEngineBackend::SyncEngineBackend(const std::string& name,
85                                      const base::FilePath& sync_data_folder,
86                                      const base::WeakPtr<SyncEngineImpl>& host)
87     : name_(name), sync_data_folder_(sync_data_folder), host_(host) {
88   DCHECK(host);
89   // This is constructed on the UI thread but used from another thread.
90   DETACH_FROM_SEQUENCE(sequence_checker_);
91 }
92 
~SyncEngineBackend()93 SyncEngineBackend::~SyncEngineBackend() {
94   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
95 }
96 
OnSyncCycleCompleted(const SyncCycleSnapshot & snapshot)97 void SyncEngineBackend::OnSyncCycleCompleted(
98     const SyncCycleSnapshot& snapshot) {
99   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
100   host_.Call(FROM_HERE, &SyncEngineImpl::HandleSyncCycleCompletedOnFrontendLoop,
101              snapshot);
102 }
103 
DoRefreshTypes(ModelTypeSet types)104 void SyncEngineBackend::DoRefreshTypes(ModelTypeSet types) {
105   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
106   sync_manager_->RefreshTypes(types);
107 }
108 
OnInitializationComplete(const WeakHandle<JsBackend> & js_backend,const WeakHandle<DataTypeDebugInfoListener> & debug_info_listener,bool success)109 void SyncEngineBackend::OnInitializationComplete(
110     const WeakHandle<JsBackend>& js_backend,
111     const WeakHandle<DataTypeDebugInfoListener>& debug_info_listener,
112     bool success) {
113   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
114 
115   if (!success) {
116     DoDestroySyncManager();
117     host_.Call(FROM_HERE,
118                &SyncEngineImpl::HandleInitializationFailureOnFrontendLoop);
119     return;
120   }
121 
122   // Hang on to these for a while longer.  We're not ready to hand them back to
123   // the UI thread yet.
124   js_backend_ = js_backend;
125   debug_info_listener_ = debug_info_listener;
126 
127   LoadAndConnectNigoriController();
128 
129   ConfigureReason reason = sync_manager_->InitialSyncEndedTypes().Empty()
130                                ? CONFIGURE_REASON_NEW_CLIENT
131                                : CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE;
132 
133   ModelTypeSet new_control_types =
134       Difference(ControlTypes(), sync_manager_->InitialSyncEndedTypes());
135 
136   SDVLOG(1) << "Control Types " << ModelTypeSetToString(new_control_types)
137             << " added; calling ConfigureSyncer";
138 
139   sync_manager_->ConfigureSyncer(
140       reason, new_control_types, SyncManager::SyncFeatureState::INITIALIZING,
141       base::BindOnce(&SyncEngineBackend::DoInitialProcessControlTypes,
142                      weak_ptr_factory_.GetWeakPtr()));
143 }
144 
OnConnectionStatusChange(ConnectionStatus status)145 void SyncEngineBackend::OnConnectionStatusChange(ConnectionStatus status) {
146   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
147   host_.Call(FROM_HERE,
148              &SyncEngineImpl::HandleConnectionStatusChangeOnFrontendLoop,
149              status);
150 }
151 
OnSyncStatusChanged(const SyncStatus & status)152 void SyncEngineBackend::OnSyncStatusChanged(const SyncStatus& status) {
153   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
154   host_.Call(FROM_HERE, &SyncEngineImpl::HandleSyncStatusChanged, status);
155 }
156 
OnActionableError(const SyncProtocolError & sync_error)157 void SyncEngineBackend::OnActionableError(const SyncProtocolError& sync_error) {
158   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
159   host_.Call(FROM_HERE,
160              &SyncEngineImpl::HandleActionableErrorEventOnFrontendLoop,
161              sync_error);
162 }
163 
OnMigrationRequested(ModelTypeSet types)164 void SyncEngineBackend::OnMigrationRequested(ModelTypeSet types) {
165   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
166   host_.Call(FROM_HERE, &SyncEngineImpl::HandleMigrationRequestedOnFrontendLoop,
167              types);
168 }
169 
OnProtocolEvent(const ProtocolEvent & event)170 void SyncEngineBackend::OnProtocolEvent(const ProtocolEvent& event) {
171   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
172   if (forward_protocol_events_) {
173     std::unique_ptr<ProtocolEvent> event_clone(event.Clone());
174     host_.Call(FROM_HERE, &SyncEngineImpl::HandleProtocolEventOnFrontendLoop,
175                base::Passed(std::move(event_clone)));
176   }
177 }
178 
DoOnInvalidatorStateChange(InvalidatorState state)179 void SyncEngineBackend::DoOnInvalidatorStateChange(InvalidatorState state) {
180   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
181   sync_manager_->SetInvalidatorEnabled(state == INVALIDATIONS_ENABLED);
182 }
183 
ShouldIgnoreRedundantInvalidation(const Invalidation & invalidation,ModelType type)184 bool SyncEngineBackend::ShouldIgnoreRedundantInvalidation(
185     const Invalidation& invalidation,
186     ModelType type) {
187   bool fcm_invalidation = base::FeatureList::IsEnabled(
188       invalidation::switches::kFCMInvalidationsForSyncDontCheckVersion);
189   bool redundant_invalidation = false;
190   auto last_invalidation = last_invalidation_versions_.find(type);
191   if (!invalidation.is_unknown_version() &&
192       last_invalidation != last_invalidation_versions_.end() &&
193       invalidation.version() <= last_invalidation->second) {
194     DVLOG(1) << "Ignoring redundant invalidation for "
195              << ModelTypeToString(type) << " with version "
196              << invalidation.version() << ", last seen version was "
197              << last_invalidation->second;
198     redundant_invalidation = true;
199     UMA_HISTOGRAM_ENUMERATION("Sync.RedundantInvalidationPerModelType", type,
200                               static_cast<int>(syncer::ModelType::NUM_ENTRIES));
201   } else {
202     UMA_HISTOGRAM_ENUMERATION("Sync.NonRedundantInvalidationPerModelType", type,
203                               static_cast<int>(syncer::ModelType::NUM_ENTRIES));
204   }
205 
206   return !fcm_invalidation && redundant_invalidation;
207 }
208 
DoOnIncomingInvalidation(const TopicInvalidationMap & invalidation_map)209 void SyncEngineBackend::DoOnIncomingInvalidation(
210     const TopicInvalidationMap& invalidation_map) {
211   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
212 
213   for (const Topic& topic : invalidation_map.GetTopics()) {
214     ModelType type;
215     if (!NotificationTypeToRealModelType(topic, &type)) {
216       DLOG(WARNING) << "Notification has invalid topic: " << topic;
217     } else {
218       UMA_HISTOGRAM_ENUMERATION("Sync.InvalidationPerModelType",
219                                 ModelTypeHistogramValue(type));
220       SingleObjectInvalidationSet invalidation_set =
221           invalidation_map.ForTopic(topic);
222       for (Invalidation invalidation : invalidation_set) {
223         if (ShouldIgnoreRedundantInvalidation(invalidation, type)) {
224           continue;
225         }
226 
227         std::unique_ptr<InvalidationInterface> inv_adapter(
228             new InvalidationAdapter(invalidation));
229         sync_manager_->OnIncomingInvalidation(type, std::move(inv_adapter));
230         if (!invalidation.is_unknown_version())
231           last_invalidation_versions_[type] = invalidation.version();
232       }
233     }
234   }
235 
236   host_.Call(FROM_HERE, &SyncEngineImpl::UpdateInvalidationVersions,
237              last_invalidation_versions_);
238 }
239 
DoInitialize(SyncEngine::InitParams params)240 void SyncEngineBackend::DoInitialize(SyncEngine::InitParams params) {
241   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
242 
243   // Make sure that the directory exists before initializing the backend.
244   // If it already exists, this will do no harm.
245   if (!base::CreateDirectory(sync_data_folder_)) {
246     DLOG(FATAL) << "Sync Data directory creation failed.";
247   }
248 
249   // Load the previously persisted set of invalidation versions into memory.
250   last_invalidation_versions_ = params.invalidation_versions;
251 
252   authenticated_account_id_ = params.authenticated_account_id;
253 
254   auto nigori_processor = std::make_unique<NigoriModelTypeProcessor>();
255   nigori_controller_ = std::make_unique<ModelTypeController>(
256       NIGORI, std::make_unique<ForwardingModelTypeControllerDelegate>(
257                   nigori_processor->GetControllerDelegate().get()));
258   sync_encryption_handler_ = std::make_unique<NigoriSyncBridgeImpl>(
259       std::move(nigori_processor),
260       std::make_unique<NigoriStorageImpl>(
261           sync_data_folder_.Append(kNigoriStorageFilename), &encryptor_),
262       &encryptor_, base::BindRepeating(&Nigori::GenerateScryptSalt),
263       params.restored_key_for_bootstrapping,
264       params.restored_keystore_key_for_bootstrapping);
265 
266   sync_manager_ = params.sync_manager_factory->CreateSyncManager(name_);
267   sync_manager_->AddObserver(this);
268 
269   SyncManager::InitArgs args;
270   args.event_handler = params.event_handler;
271   args.service_url = params.service_url;
272   args.enable_local_sync_backend = params.enable_local_sync_backend;
273   args.local_sync_backend_folder = params.local_sync_backend_folder;
274   args.post_factory = std::move(params.http_factory_getter).Run();
275   args.encryption_observer_proxy = std::move(params.encryption_observer_proxy);
276   args.extensions_activity = params.extensions_activity.get();
277   args.authenticated_account_id = params.authenticated_account_id;
278   args.invalidator_client_id = params.invalidator_client_id;
279   args.engine_components_factory = std::move(params.engine_components_factory);
280   args.encryption_handler = sync_encryption_handler_.get();
281   args.cancelation_signal = &stop_syncing_signal_;
282   args.poll_interval = params.poll_interval;
283   args.cache_guid = params.cache_guid;
284   args.birthday = params.birthday;
285   args.bag_of_chips = params.bag_of_chips;
286   args.sync_status_observers.push_back(this);
287   sync_manager_->Init(&args);
288 }
289 
DoUpdateCredentials(const SyncCredentials & credentials)290 void SyncEngineBackend::DoUpdateCredentials(
291     const SyncCredentials& credentials) {
292   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
293   // UpdateCredentials can be called during backend initialization, possibly
294   // when backend initialization has failed but hasn't notified the UI thread
295   // yet. In that case, the sync manager may have been destroyed on another
296   // thread before this task was executed, so we do nothing.
297   if (sync_manager_) {
298     sync_manager_->UpdateCredentials(credentials);
299   }
300 }
301 
DoInvalidateCredentials()302 void SyncEngineBackend::DoInvalidateCredentials() {
303   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
304   if (sync_manager_) {
305     sync_manager_->InvalidateCredentials();
306   }
307 }
308 
DoStartConfiguration()309 void SyncEngineBackend::DoStartConfiguration() {
310   sync_manager_->StartConfiguration();
311 }
312 
DoStartSyncing(base::Time last_poll_time)313 void SyncEngineBackend::DoStartSyncing(base::Time last_poll_time) {
314   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
315   sync_manager_->StartSyncingNormally(last_poll_time);
316 }
317 
DoSetEncryptionPassphrase(const std::string & passphrase)318 void SyncEngineBackend::DoSetEncryptionPassphrase(
319     const std::string& passphrase) {
320   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
321   sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase(passphrase);
322 }
323 
DoAddTrustedVaultDecryptionKeys(const std::vector<std::vector<uint8_t>> & keys)324 void SyncEngineBackend::DoAddTrustedVaultDecryptionKeys(
325     const std::vector<std::vector<uint8_t>>& keys) {
326   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
327   sync_manager_->GetEncryptionHandler()->AddTrustedVaultDecryptionKeys(keys);
328 }
329 
DoInitialProcessControlTypes()330 void SyncEngineBackend::DoInitialProcessControlTypes() {
331   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
332 
333   DVLOG(1) << "Initilalizing Control Types";
334 
335   // Initialize encryption.
336   if (!sync_manager_->GetEncryptionHandler()->Init()) {
337     host_.Call(FROM_HERE,
338                &SyncEngineImpl::HandleInitializationFailureOnFrontendLoop);
339     return;
340   }
341 
342   if (!sync_manager_->InitialSyncEndedTypes().HasAll(ControlTypes())) {
343     LOG(ERROR) << "Failed to download control types";
344     host_.Call(FROM_HERE,
345                &SyncEngineImpl::HandleInitializationFailureOnFrontendLoop);
346     return;
347   }
348 
349   host_.Call(
350       FROM_HERE, &SyncEngineImpl::HandleInitializationSuccessOnFrontendLoop,
351       sync_manager_->GetEnabledTypes(), js_backend_, debug_info_listener_,
352       base::Passed(sync_manager_->GetModelTypeConnectorProxy()),
353       sync_manager_->birthday(), sync_manager_->bag_of_chips());
354 
355   js_backend_.Reset();
356   debug_info_listener_.Reset();
357 }
358 
DoSetDecryptionPassphrase(const std::string & passphrase)359 void SyncEngineBackend::DoSetDecryptionPassphrase(
360     const std::string& passphrase) {
361   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
362   sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase(passphrase);
363 }
364 
ShutdownOnUIThread()365 void SyncEngineBackend::ShutdownOnUIThread() {
366   // This will cut short any blocking network tasks, cut short any in-progress
367   // sync cycles, and prevent the creation of new blocking network tasks and new
368   // sync cycles.  If there was an in-progress network request, it would have
369   // had a reference to the RequestContextGetter.  This reference will be
370   // dropped by the time this function returns.
371   //
372   // It is safe to call this even if Sync's backend classes have not been
373   // initialized yet.  Those classes will receive the message when the sync
374   // thread finally getes around to constructing them.
375   stop_syncing_signal_.Signal();
376 }
377 
DoShutdown(ShutdownReason reason)378 void SyncEngineBackend::DoShutdown(ShutdownReason reason) {
379   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
380 
381   // Having no |sync_manager_| means that initialization was failed and NIGORI
382   // wasn't connected and started.
383   // TODO(crbug.com/922900): this logic seems fragile, maybe initialization and
384   // connecting of NIGORI needs refactoring.
385   if (nigori_controller_ && sync_manager_) {
386     sync_manager_->GetModelTypeConnector()->DisconnectDataType(NIGORI);
387     nigori_controller_->Stop(reason, base::DoNothing());
388   }
389   DoDestroySyncManager();
390 
391   if (reason == DISABLE_SYNC) {
392     DeleteLegacyDirectoryFilesAndNigoriStorage(sync_data_folder_);
393   }
394 
395   host_.Reset();
396   weak_ptr_factory_.InvalidateWeakPtrs();
397 }
398 
DoDestroySyncManager()399 void SyncEngineBackend::DoDestroySyncManager() {
400   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
401 
402   if (sync_manager_) {
403     sync_manager_->RemoveObserver(this);
404     sync_manager_->ShutdownOnSyncThread();
405     sync_manager_.reset();
406   }
407 }
408 
DoPurgeDisabledTypes(const ModelTypeSet & to_purge)409 void SyncEngineBackend::DoPurgeDisabledTypes(const ModelTypeSet& to_purge) {
410   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
411   if (to_purge.Has(NIGORI)) {
412     // We are using USS implementation of Nigori and someone asked us to purge
413     // it's data. For regular datatypes it's controlled DataTypeManager, but
414     // for Nigori we need to do it here.
415     // TODO(crbug.com/922900): try to find better way to implement this logic,
416     // it's likely happen only due to BackendMigrator.
417     sync_manager_->GetModelTypeConnector()->DisconnectDataType(NIGORI);
418     nigori_controller_->Stop(ShutdownReason::DISABLE_SYNC, base::DoNothing());
419     LoadAndConnectNigoriController();
420   }
421 }
422 
DoConfigureSyncer(ModelTypeConfigurer::ConfigureParams params)423 void SyncEngineBackend::DoConfigureSyncer(
424     ModelTypeConfigurer::ConfigureParams params) {
425   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
426   DCHECK(!params.ready_task.is_null());
427 
428   base::OnceClosure chained_ready_task(
429       base::BindOnce(&SyncEngineBackend::DoFinishConfigureDataTypes,
430                      weak_ptr_factory_.GetWeakPtr(), params.to_download,
431                      std::move(params.ready_task)));
432 
433   sync_manager_->ConfigureSyncer(params.reason, params.to_download,
434                                  params.is_sync_feature_enabled
435                                      ? SyncManager::SyncFeatureState::ON
436                                      : SyncManager::SyncFeatureState::OFF,
437                                  std::move(chained_ready_task));
438 }
439 
DoFinishConfigureDataTypes(ModelTypeSet types_to_config,base::OnceCallback<void (ModelTypeSet,ModelTypeSet)> ready_task)440 void SyncEngineBackend::DoFinishConfigureDataTypes(
441     ModelTypeSet types_to_config,
442     base::OnceCallback<void(ModelTypeSet, ModelTypeSet)> ready_task) {
443   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
444 
445   // Update the enabled types for the bridge and sync manager.
446   // TODO(crbug.com/1140938): track |enabled_types| directly in SyncEngineImpl.
447   ModelTypeSet enabled_types = sync_manager_->GetEnabledTypes();
448   enabled_types.RemoveAll(ProxyTypes());
449 
450   const ModelTypeSet failed_configuration_types =
451       Difference(types_to_config, sync_manager_->InitialSyncEndedTypes());
452   const ModelTypeSet succeeded_configuration_types =
453       Difference(types_to_config, failed_configuration_types);
454   host_.Call(FROM_HERE, &SyncEngineImpl::FinishConfigureDataTypesOnFrontendLoop,
455              enabled_types, succeeded_configuration_types,
456              failed_configuration_types, std::move(ready_task));
457 }
458 
SendBufferedProtocolEventsAndEnableForwarding()459 void SyncEngineBackend::SendBufferedProtocolEventsAndEnableForwarding() {
460   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
461   forward_protocol_events_ = true;
462 
463   if (sync_manager_) {
464     // Grab our own copy of the buffered events.
465     // The buffer is not modified by this operation.
466     std::vector<std::unique_ptr<ProtocolEvent>> buffered_events =
467         sync_manager_->GetBufferedProtocolEvents();
468 
469     // Send them all over the fence to the host.
470     for (auto& event : buffered_events) {
471       host_.Call(FROM_HERE, &SyncEngineImpl::HandleProtocolEventOnFrontendLoop,
472                  base::Passed(std::move(event)));
473     }
474   }
475 }
476 
DisableProtocolEventForwarding()477 void SyncEngineBackend::DisableProtocolEventForwarding() {
478   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
479   forward_protocol_events_ = false;
480 }
481 
DoOnCookieJarChanged(bool account_mismatch,bool empty_jar,base::OnceClosure callback)482 void SyncEngineBackend::DoOnCookieJarChanged(bool account_mismatch,
483                                              bool empty_jar,
484                                              base::OnceClosure callback) {
485   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
486   sync_manager_->OnCookieJarChanged(account_mismatch, empty_jar);
487   if (!callback.is_null()) {
488     host_.Call(FROM_HERE, &SyncEngineImpl::OnCookieJarChangedDoneOnFrontendLoop,
489                std::move(callback));
490   }
491 }
492 
DoOnInvalidatorClientIdChange(const std::string & client_id)493 void SyncEngineBackend::DoOnInvalidatorClientIdChange(
494     const std::string& client_id) {
495   if (base::FeatureList::IsEnabled(switches::kSyncE2ELatencyMeasurement)) {
496     // Don't populate the ID, if client participates in latency measurement
497     // experiment.
498     return;
499   }
500   sync_manager_->UpdateInvalidationClientId(client_id);
501 }
502 
DoOnInvalidationReceived(const std::string & payload)503 void SyncEngineBackend::DoOnInvalidationReceived(const std::string& payload) {
504   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
505   DCHECK(base::FeatureList::IsEnabled(switches::kSyncSendInterestedDataTypes) &&
506          base::FeatureList::IsEnabled(switches::kUseSyncInvalidations));
507 
508   sync_pb::SyncInvalidationsPayload payload_message;
509   // TODO(crbug.com/1119804): Track parsing failures in a histogram.
510   if (!payload_message.ParseFromString(payload)) {
511     return;
512   }
513   for (const auto& data_type_invalidation :
514        payload_message.data_type_invalidations()) {
515     const int field_number = data_type_invalidation.data_type_id();
516     ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
517     if (!IsRealDataType(model_type)) {
518       DLOG(WARNING) << "Unknown field number " << field_number;
519       continue;
520     }
521 
522     // TODO(crbug.com/1119798): Use only enabled data types.
523     std::unique_ptr<InvalidationInterface> inv_adapter =
524         std::make_unique<SyncInvalidationAdapter>(payload_message.hint());
525     sync_manager_->OnIncomingInvalidation(model_type, std::move(inv_adapter));
526   }
527 }
528 
DoOnActiveDevicesChanged(size_t active_devices)529 void SyncEngineBackend::DoOnActiveDevicesChanged(size_t active_devices) {
530   // If |active_devices| is 0, then current client doesn't know if there are any
531   // other devices. It's safer to consider that there are some other active
532   // devices.
533   const bool single_client = active_devices == 1;
534   sync_manager_->UpdateSingleClientStatus(single_client);
535 }
536 
GetNigoriNodeForDebugging(AllNodesCallback callback)537 void SyncEngineBackend::GetNigoriNodeForDebugging(AllNodesCallback callback) {
538   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
539   nigori_controller_->GetAllNodes(std::move(callback));
540 }
541 
HasUnsyncedItemsForTest() const542 bool SyncEngineBackend::HasUnsyncedItemsForTest() const {
543   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
544   DCHECK(sync_manager_);
545   return sync_manager_->HasUnsyncedItemsForTest();
546 }
547 
LoadAndConnectNigoriController()548 void SyncEngineBackend::LoadAndConnectNigoriController() {
549   // The controller for Nigori is not exposed to the UI thread or the
550   // DataTypeManager, so we need to start it here manually.
551   ConfigureContext configure_context;
552   configure_context.authenticated_account_id = authenticated_account_id_;
553   configure_context.cache_guid = sync_manager_->cache_guid();
554   // TODO(crbug.com/922900): investigate whether we want to use
555   // kTransportOnly in Butter mode.
556   configure_context.sync_mode = SyncMode::kFull;
557   configure_context.configuration_start_time = base::Time::Now();
558   nigori_controller_->LoadModels(configure_context, base::DoNothing());
559   DCHECK_EQ(nigori_controller_->state(), DataTypeController::MODEL_LOADED);
560   // TODO(crbug.com/922900): Do we need to call RegisterDataType() for Nigori?
561   sync_manager_->GetModelTypeConnector()->ConnectDataType(
562       NIGORI, nigori_controller_->ActivateManuallyForNigori());
563 }
564 
565 }  // namespace syncer
566