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