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_impl.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/feature_list.h"
12 #include "base/location.h"
13 #include "base/logging.h"
14 #include "base/task_runner_util.h"
15 #include "build/build_config.h"
16 #include "components/invalidation/impl/invalidation_switches.h"
17 #include "components/invalidation/public/invalidation_service.h"
18 #include "components/invalidation/public/topic_invalidation_map.h"
19 #include "components/sync/base/bind_to_task_runner.h"
20 #include "components/sync/base/invalidation_helper.h"
21 #include "components/sync/base/sync_prefs.h"
22 #include "components/sync/driver/active_devices_provider.h"
23 #include "components/sync/driver/glue/sync_engine_backend.h"
24 #include "components/sync/driver/sync_driver_switches.h"
25 #include "components/sync/engine/data_type_activation_response.h"
26 #include "components/sync/engine/engine_components_factory.h"
27 #include "components/sync/engine/engine_components_factory_impl.h"
28 #include "components/sync/engine/events/protocol_event.h"
29 #include "components/sync/engine/net/http_bridge.h"
30 #include "components/sync/engine/sync_engine_host.h"
31 #include "components/sync/engine/sync_string_conversions.h"
32 #include "components/sync/invalidations/fcm_handler.h"
33 #include "components/sync/invalidations/switches.h"
34 #include "components/sync/invalidations/sync_invalidations_service.h"
35 
36 namespace syncer {
37 
SyncEngineImpl(const std::string & name,invalidation::InvalidationService * invalidator,SyncInvalidationsService * sync_invalidations_service,std::unique_ptr<ActiveDevicesProvider> active_devices_provider,const base::WeakPtr<SyncPrefs> & sync_prefs,const base::FilePath & sync_data_folder,scoped_refptr<base::SequencedTaskRunner> sync_task_runner)38 SyncEngineImpl::SyncEngineImpl(
39     const std::string& name,
40     invalidation::InvalidationService* invalidator,
41     SyncInvalidationsService* sync_invalidations_service,
42     std::unique_ptr<ActiveDevicesProvider> active_devices_provider,
43     const base::WeakPtr<SyncPrefs>& sync_prefs,
44     const base::FilePath& sync_data_folder,
45     scoped_refptr<base::SequencedTaskRunner> sync_task_runner)
46     : sync_task_runner_(std::move(sync_task_runner)),
47       name_(name),
48       sync_prefs_(sync_prefs),
49       invalidator_(invalidator),
50       sync_invalidations_service_(sync_invalidations_service),
51 #if defined(OS_ANDROID)
52       sessions_invalidation_enabled_(false),
53 #else
54       sessions_invalidation_enabled_(true),
55 #endif
56       active_devices_provider_(std::move(active_devices_provider)) {
57   backend_ = base::MakeRefCounted<SyncEngineBackend>(
58       name_, sync_data_folder, weak_ptr_factory_.GetWeakPtr());
59 }
60 
~SyncEngineImpl()61 SyncEngineImpl::~SyncEngineImpl() {
62   DCHECK(!backend_ && !host_) << "Must call Shutdown before destructor.";
63 }
64 
Initialize(InitParams params)65 void SyncEngineImpl::Initialize(InitParams params) {
66   DCHECK(params.host);
67 
68   host_ = params.host;
69 
70   sync_task_runner_->PostTask(
71       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoInitialize, backend_,
72                                 std::move(params)));
73 
74   // If the new invalidations system (SyncInvalidationsService) is fully
75   // enabled, then the SyncService doesn't need to communicate with the old
76   // InvalidationService anymore.
77   if (invalidator_ &&
78       base::FeatureList::IsEnabled(switches::kSyncSendInterestedDataTypes) &&
79       base::FeatureList::IsEnabled(switches::kUseSyncInvalidations) &&
80       base::FeatureList::IsEnabled(
81           switches::kUseSyncInvalidationsForWalletAndOffer)) {
82     DCHECK(!invalidation_handler_registered_);
83     invalidator_->RegisterInvalidationHandler(this);
84     bool success = invalidator_->UpdateInterestedTopics(this, /*topics=*/{});
85     DCHECK(success);
86     invalidator_->UnregisterInvalidationHandler(this);
87     invalidator_ = nullptr;
88   }
89 }
90 
IsInitialized() const91 bool SyncEngineImpl::IsInitialized() const {
92   return initialized_;
93 }
94 
TriggerRefresh(const ModelTypeSet & types)95 void SyncEngineImpl::TriggerRefresh(const ModelTypeSet& types) {
96   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
97   sync_task_runner_->PostTask(
98       FROM_HERE,
99       base::BindOnce(&SyncEngineBackend::DoRefreshTypes, backend_, types));
100 }
101 
UpdateCredentials(const SyncCredentials & credentials)102 void SyncEngineImpl::UpdateCredentials(const SyncCredentials& credentials) {
103   sync_task_runner_->PostTask(
104       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoUpdateCredentials,
105                                 backend_, credentials));
106 }
107 
InvalidateCredentials()108 void SyncEngineImpl::InvalidateCredentials() {
109   sync_task_runner_->PostTask(
110       FROM_HERE,
111       base::BindOnce(&SyncEngineBackend::DoInvalidateCredentials, backend_));
112 }
113 
StartConfiguration()114 void SyncEngineImpl::StartConfiguration() {
115   sync_task_runner_->PostTask(
116       FROM_HERE,
117       base::BindOnce(&SyncEngineBackend::DoStartConfiguration, backend_));
118 }
119 
StartSyncingWithServer()120 void SyncEngineImpl::StartSyncingWithServer() {
121   DVLOG(1) << name_ << ": SyncEngineImpl::StartSyncingWithServer called.";
122   base::Time last_poll_time = sync_prefs_->GetLastPollTime();
123   // If there's no known last poll time (e.g. on initial start-up), we treat
124   // this as if a poll just happened.
125   if (last_poll_time.is_null()) {
126     last_poll_time = base::Time::Now();
127     sync_prefs_->SetLastPollTime(last_poll_time);
128   }
129   sync_task_runner_->PostTask(
130       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoStartSyncing, backend_,
131                                 last_poll_time));
132 }
133 
SetEncryptionPassphrase(const std::string & passphrase)134 void SyncEngineImpl::SetEncryptionPassphrase(const std::string& passphrase) {
135   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
136   sync_task_runner_->PostTask(
137       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoSetEncryptionPassphrase,
138                                 backend_, passphrase));
139 }
140 
SetDecryptionPassphrase(const std::string & passphrase)141 void SyncEngineImpl::SetDecryptionPassphrase(const std::string& passphrase) {
142   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
143   sync_task_runner_->PostTask(
144       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoSetDecryptionPassphrase,
145                                 backend_, passphrase));
146 }
147 
AddTrustedVaultDecryptionKeys(const std::vector<std::vector<uint8_t>> & keys,base::OnceClosure done_cb)148 void SyncEngineImpl::AddTrustedVaultDecryptionKeys(
149     const std::vector<std::vector<uint8_t>>& keys,
150     base::OnceClosure done_cb) {
151   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
152   sync_task_runner_->PostTaskAndReply(
153       FROM_HERE,
154       base::BindOnce(&SyncEngineBackend::DoAddTrustedVaultDecryptionKeys,
155                      backend_, keys),
156       std::move(done_cb));
157 }
158 
StopSyncingForShutdown()159 void SyncEngineImpl::StopSyncingForShutdown() {
160   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
161 
162   // Stop getting messages from the sync thread.
163   weak_ptr_factory_.InvalidateWeakPtrs();
164   // Immediately stop sending messages to the host.
165   host_ = nullptr;
166 
167   backend_->ShutdownOnUIThread();
168 }
169 
Shutdown(ShutdownReason reason)170 void SyncEngineImpl::Shutdown(ShutdownReason reason) {
171   // StopSyncingForShutdown() (which nulls out |host_|) should be
172   // called first.
173   DCHECK(!host_);
174 
175   if (invalidation_handler_registered_) {
176     if (reason != BROWSER_SHUTDOWN) {
177       bool success = invalidator_->UpdateInterestedTopics(this, /*topics=*/{});
178       DCHECK(success);
179     }
180     invalidator_->UnregisterInvalidationHandler(this);
181     invalidator_ = nullptr;
182   }
183   if (sync_invalidations_service_) {
184     // It's safe to call RemoveListener even if AddListener wasn't called
185     // before.
186     sync_invalidations_service_->RemoveListener(this);
187     sync_invalidations_service_ = nullptr;
188   }
189   last_enabled_types_.Clear();
190   invalidation_handler_registered_ = false;
191 
192   active_devices_provider_->SetActiveDevicesChangedCallback(
193       base::RepeatingClosure());
194 
195   model_type_connector_.reset();
196 
197   // Shut down and destroy SyncManager.
198   sync_task_runner_->PostTask(
199       FROM_HERE,
200       base::BindOnce(&SyncEngineBackend::DoShutdown, backend_, reason));
201 
202   // Ensure that |backend_| destroyed inside Sync sequence, not inside current
203   // one.
204   sync_task_runner_->ReleaseSoon(FROM_HERE, std::move(backend_));
205 }
206 
ConfigureDataTypes(ConfigureParams params)207 void SyncEngineImpl::ConfigureDataTypes(ConfigureParams params) {
208   sync_task_runner_->PostTask(
209       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoPurgeDisabledTypes,
210                                 backend_, params.to_purge));
211   sync_task_runner_->PostTask(
212       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoConfigureSyncer, backend_,
213                                 std::move(params)));
214 }
215 
ActivateDataType(ModelType type,std::unique_ptr<DataTypeActivationResponse> activation_response)216 void SyncEngineImpl::ActivateDataType(
217     ModelType type,
218     std::unique_ptr<DataTypeActivationResponse> activation_response) {
219   model_type_connector_->ConnectDataType(type, std::move(activation_response));
220 }
221 
DeactivateDataType(ModelType type)222 void SyncEngineImpl::DeactivateDataType(ModelType type) {
223   model_type_connector_->DisconnectDataType(type);
224 }
225 
ActivateProxyDataType(ModelType type)226 void SyncEngineImpl::ActivateProxyDataType(ModelType type) {
227   model_type_connector_->ConnectProxyType(type);
228 }
229 
DeactivateProxyDataType(ModelType type)230 void SyncEngineImpl::DeactivateProxyDataType(ModelType type) {
231   model_type_connector_->DisconnectProxyType(type);
232 }
233 
GetDetailedStatus() const234 const SyncEngineImpl::Status& SyncEngineImpl::GetDetailedStatus() const {
235   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
236   DCHECK(IsInitialized());
237   return cached_status_;
238 }
239 
HasUnsyncedItemsForTest(base::OnceCallback<void (bool)> cb) const240 void SyncEngineImpl::HasUnsyncedItemsForTest(
241     base::OnceCallback<void(bool)> cb) const {
242   DCHECK(IsInitialized());
243   base::PostTaskAndReplyWithResult(
244       sync_task_runner_.get(), FROM_HERE,
245       base::BindOnce(&SyncEngineBackend::HasUnsyncedItemsForTest, backend_),
246       std::move(cb));
247 }
248 
RequestBufferedProtocolEventsAndEnableForwarding()249 void SyncEngineImpl::RequestBufferedProtocolEventsAndEnableForwarding() {
250   sync_task_runner_->PostTask(
251       FROM_HERE,
252       base::BindOnce(
253           &SyncEngineBackend::SendBufferedProtocolEventsAndEnableForwarding,
254           backend_));
255 }
256 
DisableProtocolEventForwarding()257 void SyncEngineImpl::DisableProtocolEventForwarding() {
258   sync_task_runner_->PostTask(
259       FROM_HERE,
260       base::BindOnce(&SyncEngineBackend::DisableProtocolEventForwarding,
261                      backend_));
262 }
263 
FinishConfigureDataTypesOnFrontendLoop(const ModelTypeSet enabled_types,const ModelTypeSet succeeded_configuration_types,const ModelTypeSet failed_configuration_types,base::OnceCallback<void (ModelTypeSet,ModelTypeSet)> ready_task)264 void SyncEngineImpl::FinishConfigureDataTypesOnFrontendLoop(
265     const ModelTypeSet enabled_types,
266     const ModelTypeSet succeeded_configuration_types,
267     const ModelTypeSet failed_configuration_types,
268     base::OnceCallback<void(ModelTypeSet, ModelTypeSet)> ready_task) {
269   last_enabled_types_ = enabled_types;
270   SendInterestedTopicsToInvalidator();
271 
272   if (!ready_task.is_null()) {
273     std::move(ready_task)
274         .Run(succeeded_configuration_types, failed_configuration_types);
275   }
276 }
277 
HandleInitializationSuccessOnFrontendLoop(ModelTypeSet initial_types,const WeakHandle<JsBackend> js_backend,const WeakHandle<DataTypeDebugInfoListener> debug_info_listener,std::unique_ptr<ModelTypeConnector> model_type_connector,const std::string & birthday,const std::string & bag_of_chips)278 void SyncEngineImpl::HandleInitializationSuccessOnFrontendLoop(
279     ModelTypeSet initial_types,
280     const WeakHandle<JsBackend> js_backend,
281     const WeakHandle<DataTypeDebugInfoListener> debug_info_listener,
282     std::unique_ptr<ModelTypeConnector> model_type_connector,
283     const std::string& birthday,
284     const std::string& bag_of_chips) {
285   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
286 
287   model_type_connector_ = std::move(model_type_connector);
288 
289   initialized_ = true;
290 
291   if (invalidator_) {
292     invalidator_->RegisterInvalidationHandler(this);
293     invalidation_handler_registered_ = true;
294 
295     // Fake a state change to initialize the SyncManager's cached invalidator
296     // state.
297     // TODO(crbug.com/1132868): Do this for the new invalidations as well.
298     OnInvalidatorStateChange(invalidator_->GetInvalidatorState());
299   }
300 
301   if (sync_invalidations_service_) {
302     sync_invalidations_service_->AddListener(this);
303   }
304 
305   active_devices_provider_->SetActiveDevicesChangedCallback(base::BindRepeating(
306       &SyncEngineImpl::OnActiveDevicesChanged, weak_ptr_factory_.GetWeakPtr()));
307 
308   // Initialize active devices count.
309   OnActiveDevicesChanged();
310 
311   host_->OnEngineInitialized(initial_types, js_backend, debug_info_listener,
312                              birthday, bag_of_chips, /*success=*/true);
313 }
314 
HandleInitializationFailureOnFrontendLoop()315 void SyncEngineImpl::HandleInitializationFailureOnFrontendLoop() {
316   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
317   host_->OnEngineInitialized(ModelTypeSet(), WeakHandle<JsBackend>(),
318                              WeakHandle<DataTypeDebugInfoListener>(),
319                              /*birthday=*/"", /*bag_of_chips=*/"",
320                              /*success=*/false);
321 }
322 
HandleSyncCycleCompletedOnFrontendLoop(const SyncCycleSnapshot & snapshot)323 void SyncEngineImpl::HandleSyncCycleCompletedOnFrontendLoop(
324     const SyncCycleSnapshot& snapshot) {
325   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
326 
327   // Process any changes to the datatypes we're syncing.
328   // TODO(sync): add support for removing types.
329   if (IsInitialized()) {
330     host_->OnSyncCycleCompleted(snapshot);
331   }
332 }
333 
HandleActionableErrorEventOnFrontendLoop(const SyncProtocolError & sync_error)334 void SyncEngineImpl::HandleActionableErrorEventOnFrontendLoop(
335     const SyncProtocolError& sync_error) {
336   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
337   host_->OnActionableError(sync_error);
338 }
339 
HandleMigrationRequestedOnFrontendLoop(ModelTypeSet types)340 void SyncEngineImpl::HandleMigrationRequestedOnFrontendLoop(
341     ModelTypeSet types) {
342   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
343   host_->OnMigrationNeededForTypes(types);
344 }
345 
OnInvalidatorStateChange(InvalidatorState state)346 void SyncEngineImpl::OnInvalidatorStateChange(InvalidatorState state) {
347   sync_task_runner_->PostTask(
348       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoOnInvalidatorStateChange,
349                                 backend_, state));
350 }
351 
OnIncomingInvalidation(const TopicInvalidationMap & invalidation_map)352 void SyncEngineImpl::OnIncomingInvalidation(
353     const TopicInvalidationMap& invalidation_map) {
354   sync_task_runner_->PostTask(
355       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoOnIncomingInvalidation,
356                                 backend_, invalidation_map));
357 }
358 
GetOwnerName() const359 std::string SyncEngineImpl::GetOwnerName() const {
360   return "SyncEngineImpl";
361 }
362 
HandleConnectionStatusChangeOnFrontendLoop(ConnectionStatus status)363 void SyncEngineImpl::HandleConnectionStatusChangeOnFrontendLoop(
364     ConnectionStatus status) {
365   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
366   DVLOG(1) << "Connection status changed: " << ConnectionStatusToString(status);
367   host_->OnConnectionStatusChange(status);
368 }
369 
HandleProtocolEventOnFrontendLoop(std::unique_ptr<ProtocolEvent> event)370 void SyncEngineImpl::HandleProtocolEventOnFrontendLoop(
371     std::unique_ptr<ProtocolEvent> event) {
372   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
373   host_->OnProtocolEvent(*event);
374 }
375 
UpdateInvalidationVersions(const std::map<ModelType,int64_t> & invalidation_versions)376 void SyncEngineImpl::UpdateInvalidationVersions(
377     const std::map<ModelType, int64_t>& invalidation_versions) {
378   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
379   sync_prefs_->UpdateInvalidationVersions(invalidation_versions);
380 }
381 
HandleSyncStatusChanged(const SyncStatus & status)382 void SyncEngineImpl::HandleSyncStatusChanged(const SyncStatus& status) {
383   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
384   const bool backed_off_types_changed =
385       (status.backed_off_types != cached_status_.backed_off_types);
386   cached_status_ = status;
387   if (backed_off_types_changed) {
388     host_->OnBackedOffTypesChanged();
389   }
390 }
391 
OnCookieJarChanged(bool account_mismatch,bool empty_jar,base::OnceClosure callback)392 void SyncEngineImpl::OnCookieJarChanged(bool account_mismatch,
393                                         bool empty_jar,
394                                         base::OnceClosure callback) {
395   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
396   sync_task_runner_->PostTask(
397       FROM_HERE,
398       base::BindOnce(&SyncEngineBackend::DoOnCookieJarChanged, backend_,
399                      account_mismatch, empty_jar, std::move(callback)));
400 }
401 
SetInvalidationsForSessionsEnabled(bool enabled)402 void SyncEngineImpl::SetInvalidationsForSessionsEnabled(bool enabled) {
403   sessions_invalidation_enabled_ = enabled;
404   SendInterestedTopicsToInvalidator();
405 }
406 
GetNigoriNodeForDebugging(AllNodesCallback callback)407 void SyncEngineImpl::GetNigoriNodeForDebugging(AllNodesCallback callback) {
408   DCHECK(backend_);
409   sync_task_runner_->PostTask(
410       FROM_HERE,
411       base::BindOnce(&SyncEngineBackend::GetNigoriNodeForDebugging, backend_,
412                      BindToCurrentSequence(std::move(callback))));
413 }
414 
OnInvalidatorClientIdChange(const std::string & client_id)415 void SyncEngineImpl::OnInvalidatorClientIdChange(const std::string& client_id) {
416   sync_task_runner_->PostTask(
417       FROM_HERE,
418       base::BindOnce(&SyncEngineBackend::DoOnInvalidatorClientIdChange,
419                      backend_, client_id));
420 }
421 
OnInvalidationReceived(const std::string & payload)422 void SyncEngineImpl::OnInvalidationReceived(const std::string& payload) {
423   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
424   // TODO(crbug.com/1082122): check that sync engine is fully initialized.
425   sync_task_runner_->PostTask(
426       FROM_HERE, base::BindOnce(&SyncEngineBackend::DoOnInvalidationReceived,
427                                 backend_, payload));
428 }
429 
OnCookieJarChangedDoneOnFrontendLoop(base::OnceClosure callback)430 void SyncEngineImpl::OnCookieJarChangedDoneOnFrontendLoop(
431     base::OnceClosure callback) {
432   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
433   std::move(callback).Run();
434 }
435 
SendInterestedTopicsToInvalidator()436 void SyncEngineImpl::SendInterestedTopicsToInvalidator() {
437   if (!invalidator_) {
438     return;
439   }
440 
441   // No need to register invalidations for CommitOnlyTypes().
442   ModelTypeSet invalidation_enabled_types(
443       Difference(last_enabled_types_, CommitOnlyTypes()));
444   if (!sessions_invalidation_enabled_) {
445     invalidation_enabled_types.Remove(syncer::SESSIONS);
446   }
447   // switches::kUseSyncInvalidations means that the new invalidations system is
448   // used for all data types except Wallet and Offer, so only keep these types.
449   if (base::FeatureList::IsEnabled(switches::kSyncSendInterestedDataTypes) &&
450       base::FeatureList::IsEnabled(switches::kUseSyncInvalidations)) {
451     invalidation_enabled_types.RetainAll(
452         {AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER});
453   }
454 
455   bool success = invalidator_->UpdateInterestedTopics(
456       this, ModelTypeSetToTopicSet(invalidation_enabled_types));
457   DCHECK(success);
458 }
459 
OnActiveDevicesChanged()460 void SyncEngineImpl::OnActiveDevicesChanged() {
461   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
462   sync_task_runner_->PostTask(
463       FROM_HERE,
464       base::BindOnce(
465           &SyncEngineBackend::DoOnActiveDevicesChanged, backend_,
466           active_devices_provider_->CountActiveDevicesIfAvailable()));
467 }
468 
469 }  // namespace syncer
470