OLD | NEW |
| (Empty) |
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_backend_host_core.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/files/file_util.h" | |
11 #include "base/location.h" | |
12 #include "base/single_thread_task_runner.h" | |
13 #include "components/data_use_measurement/core/data_use_user_data.h" | |
14 #include "components/invalidation/public/invalidation_util.h" | |
15 #include "components/invalidation/public/object_id_invalidation_map.h" | |
16 #include "components/sync/core/http_post_provider_factory.h" | |
17 #include "components/sync/core/internal_components_factory.h" | |
18 #include "components/sync/core/sync_manager.h" | |
19 #include "components/sync/core/sync_manager_factory.h" | |
20 #include "components/sync/engine/events/protocol_event.h" | |
21 #include "components/sync/sessions/commit_counters.h" | |
22 #include "components/sync/sessions/status_counters.h" | |
23 #include "components/sync/sessions/sync_session_snapshot.h" | |
24 #include "components/sync/sessions/update_counters.h" | |
25 #include "components/sync_driver/glue/sync_backend_registrar.h" | |
26 #include "components/sync_driver/invalidation_adapter.h" | |
27 #include "components/sync_driver/local_device_info_provider_impl.h" | |
28 #include "url/gurl.h" | |
29 | |
30 // Helper macros to log with the syncer thread name; useful when there | |
31 // are multiple syncers involved. | |
32 | |
33 #define SLOG(severity) LOG(severity) << name_ << ": " | |
34 | |
35 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": " | |
36 | |
37 static const int kSaveChangesIntervalSeconds = 10; | |
38 | |
39 namespace syncer { | |
40 class InternalComponentsFactory; | |
41 } // namespace syncer | |
42 | |
43 namespace net { | |
44 class URLFetcher; | |
45 } | |
46 | |
47 namespace { | |
48 | |
49 void BindFetcherToDataTracker(net::URLFetcher* fetcher) { | |
50 data_use_measurement::DataUseUserData::AttachToFetcher( | |
51 fetcher, data_use_measurement::DataUseUserData::SYNC); | |
52 } | |
53 | |
54 } // namespace | |
55 | |
56 namespace browser_sync { | |
57 | |
58 DoInitializeOptions::DoInitializeOptions( | |
59 base::MessageLoop* sync_loop, | |
60 SyncBackendRegistrar* registrar, | |
61 const std::vector<scoped_refptr<syncer::ModelSafeWorker>>& workers, | |
62 const scoped_refptr<syncer::ExtensionsActivity>& extensions_activity, | |
63 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, | |
64 const GURL& service_url, | |
65 const std::string& sync_user_agent, | |
66 std::unique_ptr<syncer::HttpPostProviderFactory> http_bridge_factory, | |
67 const syncer::SyncCredentials& credentials, | |
68 const std::string& invalidator_client_id, | |
69 std::unique_ptr<syncer::SyncManagerFactory> sync_manager_factory, | |
70 bool delete_sync_data_folder, | |
71 const std::string& restored_key_for_bootstrapping, | |
72 const std::string& restored_keystore_key_for_bootstrapping, | |
73 std::unique_ptr<syncer::InternalComponentsFactory> | |
74 internal_components_factory, | |
75 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>& | |
76 unrecoverable_error_handler, | |
77 const base::Closure& report_unrecoverable_error_function, | |
78 std::unique_ptr<syncer::SyncEncryptionHandler::NigoriState> | |
79 saved_nigori_state, | |
80 const std::map<syncer::ModelType, int64_t>& invalidation_versions) | |
81 : sync_loop(sync_loop), | |
82 registrar(registrar), | |
83 workers(workers), | |
84 extensions_activity(extensions_activity), | |
85 event_handler(event_handler), | |
86 service_url(service_url), | |
87 sync_user_agent(sync_user_agent), | |
88 http_bridge_factory(std::move(http_bridge_factory)), | |
89 credentials(credentials), | |
90 invalidator_client_id(invalidator_client_id), | |
91 sync_manager_factory(std::move(sync_manager_factory)), | |
92 delete_sync_data_folder(delete_sync_data_folder), | |
93 restored_key_for_bootstrapping(restored_key_for_bootstrapping), | |
94 restored_keystore_key_for_bootstrapping( | |
95 restored_keystore_key_for_bootstrapping), | |
96 internal_components_factory(std::move(internal_components_factory)), | |
97 unrecoverable_error_handler(unrecoverable_error_handler), | |
98 report_unrecoverable_error_function(report_unrecoverable_error_function), | |
99 saved_nigori_state(std::move(saved_nigori_state)), | |
100 invalidation_versions(invalidation_versions) {} | |
101 | |
102 DoInitializeOptions::~DoInitializeOptions() {} | |
103 | |
104 DoConfigureSyncerTypes::DoConfigureSyncerTypes() {} | |
105 | |
106 DoConfigureSyncerTypes::DoConfigureSyncerTypes( | |
107 const DoConfigureSyncerTypes& other) = default; | |
108 | |
109 DoConfigureSyncerTypes::~DoConfigureSyncerTypes() {} | |
110 | |
111 SyncBackendHostCore::SyncBackendHostCore( | |
112 const std::string& name, | |
113 const base::FilePath& sync_data_folder_path, | |
114 bool has_sync_setup_completed, | |
115 const base::WeakPtr<SyncBackendHostImpl>& backend) | |
116 : name_(name), | |
117 sync_data_folder_path_(sync_data_folder_path), | |
118 host_(backend), | |
119 sync_loop_(NULL), | |
120 registrar_(NULL), | |
121 has_sync_setup_completed_(has_sync_setup_completed), | |
122 forward_protocol_events_(false), | |
123 forward_type_info_(false), | |
124 weak_ptr_factory_(this) { | |
125 DCHECK(backend.get()); | |
126 } | |
127 | |
128 SyncBackendHostCore::~SyncBackendHostCore() { | |
129 DCHECK(!sync_manager_.get()); | |
130 } | |
131 | |
132 void SyncBackendHostCore::OnSyncCycleCompleted( | |
133 const syncer::sessions::SyncSessionSnapshot& snapshot) { | |
134 if (!sync_loop_) | |
135 return; | |
136 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
137 | |
138 host_.Call( | |
139 FROM_HERE, | |
140 &SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop, | |
141 snapshot); | |
142 } | |
143 | |
144 void SyncBackendHostCore::DoRefreshTypes(syncer::ModelTypeSet types) { | |
145 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
146 sync_manager_->RefreshTypes(types); | |
147 } | |
148 | |
149 void SyncBackendHostCore::OnInitializationComplete( | |
150 const syncer::WeakHandle<syncer::JsBackend>& js_backend, | |
151 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& | |
152 debug_info_listener, | |
153 bool success, | |
154 const syncer::ModelTypeSet restored_types) { | |
155 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
156 | |
157 if (!success) { | |
158 DoDestroySyncManager(syncer::STOP_SYNC); | |
159 host_.Call(FROM_HERE, | |
160 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); | |
161 return; | |
162 } | |
163 | |
164 // Register for encryption related changes now. We have to do this before | |
165 // the initializing downloading control types or initializing the encryption | |
166 // handler in order to receive notifications triggered during encryption | |
167 // startup. | |
168 sync_manager_->GetEncryptionHandler()->AddObserver(this); | |
169 | |
170 // Sync manager initialization is complete, so we can schedule recurring | |
171 // SaveChanges. | |
172 sync_loop_->task_runner()->PostTask( | |
173 FROM_HERE, base::Bind(&SyncBackendHostCore::StartSavingChanges, | |
174 weak_ptr_factory_.GetWeakPtr())); | |
175 | |
176 // Hang on to these for a while longer. We're not ready to hand them back to | |
177 // the UI thread yet. | |
178 js_backend_ = js_backend; | |
179 debug_info_listener_ = debug_info_listener; | |
180 | |
181 // Before proceeding any further, we need to download the control types and | |
182 // purge any partial data (ie. data downloaded for a type that was on its way | |
183 // to being initially synced, but didn't quite make it.). The following | |
184 // configure cycle will take care of this. It depends on the registrar state | |
185 // which we initialize below to ensure that we don't perform any downloads if | |
186 // all control types have already completed their initial sync. | |
187 registrar_->SetInitialTypes(restored_types); | |
188 | |
189 syncer::ConfigureReason reason = | |
190 restored_types.Empty() ? | |
191 syncer::CONFIGURE_REASON_NEW_CLIENT : | |
192 syncer::CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE; | |
193 | |
194 syncer::ModelTypeSet new_control_types = registrar_->ConfigureDataTypes( | |
195 syncer::ControlTypes(), syncer::ModelTypeSet()); | |
196 syncer::ModelSafeRoutingInfo routing_info; | |
197 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
198 SDVLOG(1) << "Control Types " | |
199 << syncer::ModelTypeSetToString(new_control_types) | |
200 << " added; calling ConfigureSyncer"; | |
201 | |
202 syncer::ModelTypeSet types_to_purge = | |
203 syncer::Difference(syncer::ModelTypeSet::All(), | |
204 GetRoutingInfoTypes(routing_info)); | |
205 | |
206 sync_manager_->ConfigureSyncer( | |
207 reason, | |
208 new_control_types, | |
209 types_to_purge, | |
210 syncer::ModelTypeSet(), | |
211 syncer::ModelTypeSet(), | |
212 routing_info, | |
213 base::Bind(&SyncBackendHostCore::DoInitialProcessControlTypes, | |
214 weak_ptr_factory_.GetWeakPtr()), | |
215 base::Closure()); | |
216 } | |
217 | |
218 void SyncBackendHostCore::OnConnectionStatusChange( | |
219 syncer::ConnectionStatus status) { | |
220 if (!sync_loop_) | |
221 return; | |
222 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
223 host_.Call( | |
224 FROM_HERE, | |
225 &SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop, status); | |
226 } | |
227 | |
228 void SyncBackendHostCore::OnPassphraseRequired( | |
229 syncer::PassphraseRequiredReason reason, | |
230 const sync_pb::EncryptedData& pending_keys) { | |
231 if (!sync_loop_) | |
232 return; | |
233 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
234 host_.Call( | |
235 FROM_HERE, | |
236 &SyncBackendHostImpl::NotifyPassphraseRequired, reason, pending_keys); | |
237 } | |
238 | |
239 void SyncBackendHostCore::OnPassphraseAccepted() { | |
240 if (!sync_loop_) | |
241 return; | |
242 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
243 host_.Call( | |
244 FROM_HERE, | |
245 &SyncBackendHostImpl::NotifyPassphraseAccepted); | |
246 } | |
247 | |
248 void SyncBackendHostCore::OnBootstrapTokenUpdated( | |
249 const std::string& bootstrap_token, | |
250 syncer::BootstrapTokenType type) { | |
251 if (!sync_loop_) | |
252 return; | |
253 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
254 host_.Call(FROM_HERE, | |
255 &SyncBackendHostImpl::PersistEncryptionBootstrapToken, | |
256 bootstrap_token, | |
257 type); | |
258 } | |
259 | |
260 void SyncBackendHostCore::OnEncryptedTypesChanged( | |
261 syncer::ModelTypeSet encrypted_types, | |
262 bool encrypt_everything) { | |
263 if (!sync_loop_) | |
264 return; | |
265 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
266 // NOTE: We're in a transaction. | |
267 host_.Call( | |
268 FROM_HERE, | |
269 &SyncBackendHostImpl::NotifyEncryptedTypesChanged, | |
270 encrypted_types, encrypt_everything); | |
271 } | |
272 | |
273 void SyncBackendHostCore::OnEncryptionComplete() { | |
274 if (!sync_loop_) | |
275 return; | |
276 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
277 // NOTE: We're in a transaction. | |
278 host_.Call( | |
279 FROM_HERE, | |
280 &SyncBackendHostImpl::NotifyEncryptionComplete); | |
281 } | |
282 | |
283 void SyncBackendHostCore::OnCryptographerStateChanged( | |
284 syncer::Cryptographer* cryptographer) { | |
285 // Do nothing. | |
286 } | |
287 | |
288 void SyncBackendHostCore::OnPassphraseTypeChanged( | |
289 syncer::PassphraseType type, base::Time passphrase_time) { | |
290 host_.Call( | |
291 FROM_HERE, | |
292 &SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop, | |
293 type, passphrase_time); | |
294 } | |
295 | |
296 void SyncBackendHostCore::OnLocalSetPassphraseEncryption( | |
297 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) { | |
298 host_.Call( | |
299 FROM_HERE, | |
300 &SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop, | |
301 nigori_state); | |
302 } | |
303 | |
304 void SyncBackendHostCore::OnCommitCountersUpdated( | |
305 syncer::ModelType type, | |
306 const syncer::CommitCounters& counters) { | |
307 host_.Call( | |
308 FROM_HERE, | |
309 &SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop, | |
310 type, counters); | |
311 } | |
312 | |
313 void SyncBackendHostCore::OnUpdateCountersUpdated( | |
314 syncer::ModelType type, | |
315 const syncer::UpdateCounters& counters) { | |
316 host_.Call( | |
317 FROM_HERE, | |
318 &SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop, | |
319 type, counters); | |
320 } | |
321 | |
322 void SyncBackendHostCore::OnStatusCountersUpdated( | |
323 syncer::ModelType type, | |
324 const syncer::StatusCounters& counters) { | |
325 host_.Call( | |
326 FROM_HERE, | |
327 &SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop, | |
328 type, counters); | |
329 } | |
330 | |
331 void SyncBackendHostCore::OnActionableError( | |
332 const syncer::SyncProtocolError& sync_error) { | |
333 if (!sync_loop_) | |
334 return; | |
335 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
336 host_.Call( | |
337 FROM_HERE, | |
338 &SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop, | |
339 sync_error); | |
340 } | |
341 | |
342 void SyncBackendHostCore::OnMigrationRequested(syncer::ModelTypeSet types) { | |
343 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
344 host_.Call( | |
345 FROM_HERE, | |
346 &SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop, | |
347 types); | |
348 } | |
349 | |
350 void SyncBackendHostCore::OnProtocolEvent( | |
351 const syncer::ProtocolEvent& event) { | |
352 // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr. | |
353 if (forward_protocol_events_) { | |
354 std::unique_ptr<syncer::ProtocolEvent> event_clone(event.Clone()); | |
355 host_.Call( | |
356 FROM_HERE, | |
357 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop, | |
358 event_clone.release()); | |
359 } | |
360 } | |
361 | |
362 void SyncBackendHostCore::DoOnInvalidatorStateChange( | |
363 syncer::InvalidatorState state) { | |
364 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
365 sync_manager_->SetInvalidatorEnabled(state == syncer::INVALIDATIONS_ENABLED); | |
366 } | |
367 | |
368 void SyncBackendHostCore::DoOnIncomingInvalidation( | |
369 const syncer::ObjectIdInvalidationMap& invalidation_map) { | |
370 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
371 | |
372 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds(); | |
373 for (const invalidation::ObjectId& object_id : ids) { | |
374 syncer::ModelType type; | |
375 if (!NotificationTypeToRealModelType(object_id.name(), &type)) { | |
376 DLOG(WARNING) << "Notification has invalid id: " | |
377 << syncer::ObjectIdToString(object_id); | |
378 } else { | |
379 syncer::SingleObjectInvalidationSet invalidation_set = | |
380 invalidation_map.ForObject(object_id); | |
381 for (syncer::Invalidation invalidation : invalidation_set) { | |
382 auto last_invalidation = last_invalidation_versions_.find(type); | |
383 if (!invalidation.is_unknown_version() && | |
384 last_invalidation != last_invalidation_versions_.end() && | |
385 invalidation.version() <= last_invalidation->second) { | |
386 DVLOG(1) << "Ignoring redundant invalidation for " | |
387 << syncer::ModelTypeToString(type) << " with version " | |
388 << invalidation.version() << ", last seen version was " | |
389 << last_invalidation->second; | |
390 continue; | |
391 } | |
392 std::unique_ptr<syncer::InvalidationInterface> inv_adapter( | |
393 new InvalidationAdapter(invalidation)); | |
394 sync_manager_->OnIncomingInvalidation(type, std::move(inv_adapter)); | |
395 if (!invalidation.is_unknown_version()) | |
396 last_invalidation_versions_[type] = invalidation.version(); | |
397 } | |
398 } | |
399 } | |
400 | |
401 host_.Call( | |
402 FROM_HERE, | |
403 &SyncBackendHostImpl::UpdateInvalidationVersions, | |
404 last_invalidation_versions_); | |
405 } | |
406 | |
407 void SyncBackendHostCore::DoInitialize( | |
408 std::unique_ptr<DoInitializeOptions> options) { | |
409 DCHECK(!sync_loop_); | |
410 sync_loop_ = options->sync_loop; | |
411 DCHECK(sync_loop_); | |
412 | |
413 // Finish initializing the HttpBridgeFactory. We do this here because | |
414 // building the user agent may block on some platforms. | |
415 options->http_bridge_factory->Init(options->sync_user_agent, | |
416 base::Bind(&BindFetcherToDataTracker)); | |
417 | |
418 // Blow away the partial or corrupt sync data folder before doing any more | |
419 // initialization, if necessary. | |
420 if (options->delete_sync_data_folder) { | |
421 DeleteSyncDataFolder(); | |
422 } | |
423 | |
424 // Make sure that the directory exists before initializing the backend. | |
425 // If it already exists, this will do no harm. | |
426 if (!base::CreateDirectory(sync_data_folder_path_)) { | |
427 DLOG(FATAL) << "Sync Data directory creation failed."; | |
428 } | |
429 | |
430 // Load the previously persisted set of invalidation versions into memory. | |
431 last_invalidation_versions_ = options->invalidation_versions; | |
432 | |
433 DCHECK(!registrar_); | |
434 registrar_ = options->registrar; | |
435 DCHECK(registrar_); | |
436 | |
437 sync_manager_ = options->sync_manager_factory->CreateSyncManager(name_); | |
438 sync_manager_->AddObserver(this); | |
439 | |
440 syncer::SyncManager::InitArgs args; | |
441 args.database_location = sync_data_folder_path_; | |
442 args.event_handler = options->event_handler; | |
443 args.service_url = options->service_url; | |
444 args.post_factory = std::move(options->http_bridge_factory); | |
445 args.workers = options->workers; | |
446 args.extensions_activity = options->extensions_activity.get(); | |
447 args.change_delegate = options->registrar; // as SyncManager::ChangeDelegate | |
448 args.credentials = options->credentials; | |
449 args.invalidator_client_id = options->invalidator_client_id; | |
450 args.restored_key_for_bootstrapping = options->restored_key_for_bootstrapping; | |
451 args.restored_keystore_key_for_bootstrapping = | |
452 options->restored_keystore_key_for_bootstrapping; | |
453 args.internal_components_factory = | |
454 std::move(options->internal_components_factory); | |
455 args.encryptor = &encryptor_; | |
456 args.unrecoverable_error_handler = options->unrecoverable_error_handler; | |
457 args.report_unrecoverable_error_function = | |
458 options->report_unrecoverable_error_function; | |
459 args.cancelation_signal = &stop_syncing_signal_; | |
460 args.saved_nigori_state = std::move(options->saved_nigori_state); | |
461 sync_manager_->Init(&args); | |
462 } | |
463 | |
464 void SyncBackendHostCore::DoUpdateCredentials( | |
465 const syncer::SyncCredentials& credentials) { | |
466 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
467 // UpdateCredentials can be called during backend initialization, possibly | |
468 // when backend initialization has failed but hasn't notified the UI thread | |
469 // yet. In that case, the sync manager may have been destroyed on the sync | |
470 // thread before this task was executed, so we do nothing. | |
471 if (sync_manager_) { | |
472 sync_manager_->UpdateCredentials(credentials); | |
473 } | |
474 } | |
475 | |
476 void SyncBackendHostCore::DoStartSyncing( | |
477 const syncer::ModelSafeRoutingInfo& routing_info, | |
478 base::Time last_poll_time) { | |
479 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
480 sync_manager_->StartSyncingNormally(routing_info, last_poll_time); | |
481 } | |
482 | |
483 void SyncBackendHostCore::DoSetEncryptionPassphrase( | |
484 const std::string& passphrase, | |
485 bool is_explicit) { | |
486 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
487 sync_manager_->GetEncryptionHandler()->SetEncryptionPassphrase( | |
488 passphrase, is_explicit); | |
489 } | |
490 | |
491 void SyncBackendHostCore::DoInitialProcessControlTypes() { | |
492 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
493 | |
494 DVLOG(1) << "Initilalizing Control Types"; | |
495 | |
496 // Initialize encryption. | |
497 sync_manager_->GetEncryptionHandler()->Init(); | |
498 | |
499 // Note: experiments are currently handled via SBH::AddExperimentalTypes, | |
500 // which is called at the end of every sync cycle. | |
501 // TODO(zea): eventually add an experiment handler and initialize it here. | |
502 | |
503 if (!sync_manager_->GetUserShare()) { // NULL in some tests. | |
504 DVLOG(1) << "Skipping initialization of DeviceInfo"; | |
505 host_.Call( | |
506 FROM_HERE, | |
507 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); | |
508 return; | |
509 } | |
510 | |
511 if (!sync_manager_->InitialSyncEndedTypes().HasAll(syncer::ControlTypes())) { | |
512 LOG(ERROR) << "Failed to download control types"; | |
513 host_.Call( | |
514 FROM_HERE, | |
515 &SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop); | |
516 return; | |
517 } | |
518 | |
519 host_.Call(FROM_HERE, | |
520 &SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop, | |
521 js_backend_, debug_info_listener_, | |
522 base::Passed(sync_manager_->GetModelTypeConnectorProxy()), | |
523 sync_manager_->cache_guid()); | |
524 | |
525 js_backend_.Reset(); | |
526 debug_info_listener_.Reset(); | |
527 } | |
528 | |
529 void SyncBackendHostCore::DoSetDecryptionPassphrase( | |
530 const std::string& passphrase) { | |
531 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
532 sync_manager_->GetEncryptionHandler()->SetDecryptionPassphrase( | |
533 passphrase); | |
534 } | |
535 | |
536 void SyncBackendHostCore::DoEnableEncryptEverything() { | |
537 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
538 sync_manager_->GetEncryptionHandler()->EnableEncryptEverything(); | |
539 } | |
540 | |
541 void SyncBackendHostCore::ShutdownOnUIThread() { | |
542 // This will cut short any blocking network tasks, cut short any in-progress | |
543 // sync cycles, and prevent the creation of new blocking network tasks and new | |
544 // sync cycles. If there was an in-progress network request, it would have | |
545 // had a reference to the RequestContextGetter. This reference will be | |
546 // dropped by the time this function returns. | |
547 // | |
548 // It is safe to call this even if Sync's backend classes have not been | |
549 // initialized yet. Those classes will receive the message when the sync | |
550 // thread finally getes around to constructing them. | |
551 stop_syncing_signal_.Signal(); | |
552 | |
553 // This will drop the HttpBridgeFactory's reference to the | |
554 // RequestContextGetter. Once this has been called, the HttpBridgeFactory can | |
555 // no longer be used to create new HttpBridge instances. We can get away with | |
556 // this because the stop_syncing_signal_ has already been signalled, which | |
557 // guarantees that the ServerConnectionManager will no longer attempt to | |
558 // create new connections. | |
559 release_request_context_signal_.Signal(); | |
560 } | |
561 | |
562 void SyncBackendHostCore::DoShutdown(syncer::ShutdownReason reason) { | |
563 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
564 | |
565 DoDestroySyncManager(reason); | |
566 | |
567 registrar_ = NULL; | |
568 | |
569 if (reason == syncer::DISABLE_SYNC) | |
570 DeleteSyncDataFolder(); | |
571 | |
572 host_.Reset(); | |
573 weak_ptr_factory_.InvalidateWeakPtrs(); | |
574 } | |
575 | |
576 void SyncBackendHostCore::DoDestroySyncManager(syncer::ShutdownReason reason) { | |
577 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
578 if (sync_manager_) { | |
579 DisableDirectoryTypeDebugInfoForwarding(); | |
580 save_changes_timer_.reset(); | |
581 sync_manager_->RemoveObserver(this); | |
582 sync_manager_->ShutdownOnSyncThread(reason); | |
583 sync_manager_.reset(); | |
584 } | |
585 } | |
586 | |
587 void SyncBackendHostCore::DoConfigureSyncer( | |
588 syncer::ConfigureReason reason, | |
589 const DoConfigureSyncerTypes& config_types, | |
590 const syncer::ModelSafeRoutingInfo routing_info, | |
591 const base::Callback<void(syncer::ModelTypeSet, | |
592 syncer::ModelTypeSet)>& ready_task, | |
593 const base::Closure& retry_callback) { | |
594 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
595 DCHECK(!ready_task.is_null()); | |
596 DCHECK(!retry_callback.is_null()); | |
597 base::Closure chained_ready_task( | |
598 base::Bind(&SyncBackendHostCore::DoFinishConfigureDataTypes, | |
599 weak_ptr_factory_.GetWeakPtr(), | |
600 config_types.to_download, | |
601 ready_task)); | |
602 base::Closure chained_retry_task( | |
603 base::Bind(&SyncBackendHostCore::DoRetryConfiguration, | |
604 weak_ptr_factory_.GetWeakPtr(), | |
605 retry_callback)); | |
606 sync_manager_->ConfigureSyncer(reason, | |
607 config_types.to_download, | |
608 config_types.to_purge, | |
609 config_types.to_journal, | |
610 config_types.to_unapply, | |
611 routing_info, | |
612 chained_ready_task, | |
613 chained_retry_task); | |
614 } | |
615 | |
616 void SyncBackendHostCore::DoFinishConfigureDataTypes( | |
617 syncer::ModelTypeSet types_to_config, | |
618 const base::Callback<void(syncer::ModelTypeSet, | |
619 syncer::ModelTypeSet)>& ready_task) { | |
620 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
621 | |
622 // Update the enabled types for the bridge and sync manager. | |
623 syncer::ModelSafeRoutingInfo routing_info; | |
624 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
625 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routing_info); | |
626 enabled_types.RemoveAll(syncer::ProxyTypes()); | |
627 | |
628 const syncer::ModelTypeSet failed_configuration_types = | |
629 Difference(types_to_config, sync_manager_->InitialSyncEndedTypes()); | |
630 const syncer::ModelTypeSet succeeded_configuration_types = | |
631 Difference(types_to_config, failed_configuration_types); | |
632 host_.Call(FROM_HERE, | |
633 &SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop, | |
634 enabled_types, | |
635 succeeded_configuration_types, | |
636 failed_configuration_types, | |
637 ready_task); | |
638 } | |
639 | |
640 void SyncBackendHostCore::DoRetryConfiguration( | |
641 const base::Closure& retry_callback) { | |
642 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
643 host_.Call(FROM_HERE, | |
644 &SyncBackendHostImpl::RetryConfigurationOnFrontendLoop, | |
645 retry_callback); | |
646 } | |
647 | |
648 void SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding() { | |
649 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
650 forward_protocol_events_ = true; | |
651 | |
652 if (sync_manager_) { | |
653 // Grab our own copy of the buffered events. | |
654 // The buffer is not modified by this operation. | |
655 std::vector<syncer::ProtocolEvent*> buffered_events; | |
656 sync_manager_->GetBufferedProtocolEvents().release(&buffered_events); | |
657 | |
658 // Send them all over the fence to the host. | |
659 for (std::vector<syncer::ProtocolEvent*>::iterator it = | |
660 buffered_events.begin(); it != buffered_events.end(); ++it) { | |
661 // TODO(rlarocque): Make it explicit that host_ takes ownership. | |
662 host_.Call( | |
663 FROM_HERE, | |
664 &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop, | |
665 *it); | |
666 } | |
667 } | |
668 } | |
669 | |
670 void SyncBackendHostCore::DisableProtocolEventForwarding() { | |
671 forward_protocol_events_ = false; | |
672 } | |
673 | |
674 void SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding() { | |
675 DCHECK(sync_manager_); | |
676 | |
677 forward_type_info_ = true; | |
678 | |
679 if (!sync_manager_->HasDirectoryTypeDebugInfoObserver(this)) | |
680 sync_manager_->RegisterDirectoryTypeDebugInfoObserver(this); | |
681 sync_manager_->RequestEmitDebugInfo(); | |
682 } | |
683 | |
684 void SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding() { | |
685 DCHECK(sync_manager_); | |
686 | |
687 if (!forward_type_info_) | |
688 return; | |
689 | |
690 forward_type_info_ = false; | |
691 | |
692 if (sync_manager_->HasDirectoryTypeDebugInfoObserver(this)) | |
693 sync_manager_->UnregisterDirectoryTypeDebugInfoObserver(this); | |
694 } | |
695 | |
696 void SyncBackendHostCore::DeleteSyncDataFolder() { | |
697 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
698 if (base::DirectoryExists(sync_data_folder_path_)) { | |
699 if (!base::DeleteFile(sync_data_folder_path_, true)) | |
700 SLOG(DFATAL) << "Could not delete the Sync Data folder."; | |
701 } | |
702 } | |
703 | |
704 void SyncBackendHostCore::GetAllNodesForTypes( | |
705 syncer::ModelTypeSet types, | |
706 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
707 base::Callback<void(const std::vector<syncer::ModelType>& type, | |
708 ScopedVector<base::ListValue>)> callback) { | |
709 std::vector<syncer::ModelType> types_vector; | |
710 ScopedVector<base::ListValue> node_lists; | |
711 | |
712 syncer::ModelSafeRoutingInfo routes; | |
713 registrar_->GetModelSafeRoutingInfo(&routes); | |
714 syncer::ModelTypeSet enabled_types = GetRoutingInfoTypes(routes); | |
715 | |
716 for (syncer::ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { | |
717 types_vector.push_back(it.Get()); | |
718 if (!enabled_types.Has(it.Get())) { | |
719 node_lists.push_back(new base::ListValue()); | |
720 } else { | |
721 node_lists.push_back( | |
722 sync_manager_->GetAllNodesForType(it.Get()).release()); | |
723 } | |
724 } | |
725 | |
726 task_runner->PostTask( | |
727 FROM_HERE, | |
728 base::Bind(callback, types_vector, base::Passed(&node_lists))); | |
729 } | |
730 | |
731 void SyncBackendHostCore::StartSavingChanges() { | |
732 // We may already be shut down. | |
733 if (!sync_loop_) | |
734 return; | |
735 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
736 DCHECK(!save_changes_timer_.get()); | |
737 save_changes_timer_.reset(new base::RepeatingTimer()); | |
738 save_changes_timer_->Start(FROM_HERE, | |
739 base::TimeDelta::FromSeconds(kSaveChangesIntervalSeconds), | |
740 this, &SyncBackendHostCore::SaveChanges); | |
741 } | |
742 | |
743 void SyncBackendHostCore::SaveChanges() { | |
744 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
745 sync_manager_->SaveChanges(); | |
746 } | |
747 | |
748 void SyncBackendHostCore::DoClearServerData( | |
749 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) { | |
750 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
751 const syncer::SyncManager::ClearServerDataCallback callback = | |
752 base::Bind(&SyncBackendHostCore::ClearServerDataDone, | |
753 weak_ptr_factory_.GetWeakPtr(), frontend_callback); | |
754 sync_manager_->ClearServerData(callback); | |
755 } | |
756 | |
757 void SyncBackendHostCore::DoOnCookieJarChanged(bool account_mismatch, | |
758 bool empty_jar) { | |
759 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
760 sync_manager_->OnCookieJarChanged(account_mismatch, empty_jar); | |
761 } | |
762 | |
763 void SyncBackendHostCore::ClearServerDataDone( | |
764 const base::Closure& frontend_callback) { | |
765 DCHECK(sync_loop_->task_runner()->BelongsToCurrentThread()); | |
766 host_.Call(FROM_HERE, &SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop, | |
767 frontend_callback); | |
768 } | |
769 | |
770 | |
771 } // namespace browser_sync | |
OLD | NEW |