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_impl.h" | |
6 | |
7 #include <map> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "base/command_line.h" | |
12 #include "base/feature_list.h" | |
13 #include "base/location.h" | |
14 #include "base/logging.h" | |
15 #include "base/threading/thread_task_runner_handle.h" | |
16 #include "components/invalidation/public/invalidation_service.h" | |
17 #include "components/invalidation/public/object_id_invalidation_map.h" | |
18 #include "components/signin/core/browser/signin_client.h" | |
19 #include "components/sync/base/experiments.h" | |
20 #include "components/sync/base/sync_string_conversions.h" | |
21 #include "components/sync/core/activation_context.h" | |
22 #include "components/sync/core/base_transaction.h" | |
23 #include "components/sync/core/http_bridge.h" | |
24 #include "components/sync/core/internal_components_factory.h" | |
25 #include "components/sync/core/internal_components_factory_impl.h" | |
26 #include "components/sync/core/sync_manager.h" | |
27 #include "components/sync/core/sync_manager_factory.h" | |
28 #include "components/sync/engine/events/protocol_event.h" | |
29 #include "components/sync_driver/glue/sync_backend_host_core.h" | |
30 #include "components/sync_driver/glue/sync_backend_registrar.h" | |
31 #include "components/sync_driver/invalidation_helper.h" | |
32 #include "components/sync_driver/sync_client.h" | |
33 #include "components/sync_driver/sync_driver_switches.h" | |
34 #include "components/sync_driver/sync_frontend.h" | |
35 #include "components/sync_driver/sync_prefs.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 using syncer::InternalComponentsFactory; | |
45 | |
46 namespace browser_sync { | |
47 | |
48 SyncBackendHostImpl::SyncBackendHostImpl( | |
49 const std::string& name, | |
50 sync_driver::SyncClient* sync_client, | |
51 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, | |
52 invalidation::InvalidationService* invalidator, | |
53 const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs, | |
54 const base::FilePath& sync_folder) | |
55 : frontend_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
56 sync_client_(sync_client), | |
57 ui_thread_(ui_thread), | |
58 name_(name), | |
59 initialized_(false), | |
60 sync_prefs_(sync_prefs), | |
61 frontend_(NULL), | |
62 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE), | |
63 invalidator_(invalidator), | |
64 invalidation_handler_registered_(false), | |
65 weak_ptr_factory_(this) { | |
66 core_ = new SyncBackendHostCore(name_, sync_folder, | |
67 sync_prefs_->IsFirstSetupComplete(), | |
68 weak_ptr_factory_.GetWeakPtr()); | |
69 } | |
70 | |
71 SyncBackendHostImpl::~SyncBackendHostImpl() { | |
72 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor."; | |
73 DCHECK(!registrar_.get()); | |
74 } | |
75 | |
76 void SyncBackendHostImpl::Initialize( | |
77 sync_driver::SyncFrontend* frontend, | |
78 std::unique_ptr<base::Thread> sync_thread, | |
79 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread, | |
80 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread, | |
81 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, | |
82 const GURL& sync_service_url, | |
83 const std::string& sync_user_agent, | |
84 const syncer::SyncCredentials& credentials, | |
85 bool delete_sync_data_folder, | |
86 std::unique_ptr<syncer::SyncManagerFactory> sync_manager_factory, | |
87 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>& | |
88 unrecoverable_error_handler, | |
89 const base::Closure& report_unrecoverable_error_function, | |
90 const HttpPostProviderFactoryGetter& http_post_provider_factory_getter, | |
91 std::unique_ptr<syncer::SyncEncryptionHandler::NigoriState> | |
92 saved_nigori_state) { | |
93 registrar_.reset(new browser_sync::SyncBackendRegistrar( | |
94 name_, sync_client_, std::move(sync_thread), ui_thread_, db_thread, | |
95 file_thread)); | |
96 CHECK(registrar_->sync_thread()); | |
97 | |
98 frontend_ = frontend; | |
99 DCHECK(frontend); | |
100 | |
101 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers; | |
102 registrar_->GetWorkers(&workers); | |
103 | |
104 InternalComponentsFactory::Switches factory_switches = { | |
105 InternalComponentsFactory::ENCRYPTION_KEYSTORE, | |
106 InternalComponentsFactory::BACKOFF_NORMAL | |
107 }; | |
108 | |
109 base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); | |
110 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) { | |
111 factory_switches.backoff_override = | |
112 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE; | |
113 } | |
114 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) { | |
115 factory_switches.pre_commit_updates_policy = | |
116 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE; | |
117 } | |
118 | |
119 std::map<syncer::ModelType, int64_t> invalidation_versions; | |
120 sync_prefs_->GetInvalidationVersions(&invalidation_versions); | |
121 | |
122 std::unique_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions( | |
123 registrar_->sync_thread()->message_loop(), registrar_.get(), workers, | |
124 sync_client_->GetExtensionsActivity(), event_handler, sync_service_url, | |
125 sync_user_agent, http_post_provider_factory_getter.Run( | |
126 core_->GetRequestContextCancelationSignal()), | |
127 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "", | |
128 std::move(sync_manager_factory), delete_sync_data_folder, | |
129 sync_prefs_->GetEncryptionBootstrapToken(), | |
130 sync_prefs_->GetKeystoreEncryptionBootstrapToken(), | |
131 std::unique_ptr<InternalComponentsFactory>( | |
132 new syncer::InternalComponentsFactoryImpl(factory_switches)), | |
133 unrecoverable_error_handler, report_unrecoverable_error_function, | |
134 std::move(saved_nigori_state), invalidation_versions)); | |
135 InitCore(std::move(init_opts)); | |
136 } | |
137 | |
138 void SyncBackendHostImpl::TriggerRefresh(const syncer::ModelTypeSet& types) { | |
139 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
140 registrar_->sync_thread()->task_runner()->PostTask( | |
141 FROM_HERE, | |
142 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types)); | |
143 } | |
144 | |
145 void SyncBackendHostImpl::UpdateCredentials( | |
146 const syncer::SyncCredentials& credentials) { | |
147 DCHECK(registrar_->sync_thread()->IsRunning()); | |
148 registrar_->sync_thread()->task_runner()->PostTask( | |
149 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials, | |
150 core_.get(), credentials)); | |
151 } | |
152 | |
153 void SyncBackendHostImpl::StartSyncingWithServer() { | |
154 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called."; | |
155 | |
156 syncer::ModelSafeRoutingInfo routing_info; | |
157 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
158 | |
159 registrar_->sync_thread()->task_runner()->PostTask( | |
160 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(), | |
161 routing_info, sync_prefs_->GetLastPollTime())); | |
162 } | |
163 | |
164 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase, | |
165 bool is_explicit) { | |
166 DCHECK(registrar_->sync_thread()->IsRunning()); | |
167 if (!IsNigoriEnabled()) { | |
168 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori" | |
169 " is disabled."; | |
170 return; | |
171 } | |
172 | |
173 // We should never be called with an empty passphrase. | |
174 DCHECK(!passphrase.empty()); | |
175 | |
176 // This should only be called by the frontend. | |
177 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
178 | |
179 // SetEncryptionPassphrase should never be called if we are currently | |
180 // encrypted with an explicit passphrase. | |
181 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE || | |
182 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE); | |
183 | |
184 // Post an encryption task on the syncer thread. | |
185 registrar_->sync_thread()->task_runner()->PostTask( | |
186 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase, | |
187 core_.get(), passphrase, is_explicit)); | |
188 } | |
189 | |
190 bool SyncBackendHostImpl::SetDecryptionPassphrase( | |
191 const std::string& passphrase) { | |
192 if (!IsNigoriEnabled()) { | |
193 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori" | |
194 " is disabled."; | |
195 return false; | |
196 } | |
197 | |
198 // We should never be called with an empty passphrase. | |
199 DCHECK(!passphrase.empty()); | |
200 | |
201 // This should only be called by the frontend. | |
202 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
203 | |
204 // This should only be called when we have cached pending keys. | |
205 DCHECK(cached_pending_keys_.has_blob()); | |
206 | |
207 // Check the passphrase that was provided against our local cache of the | |
208 // cryptographer's pending keys. If this was unsuccessful, the UI layer can | |
209 // immediately call OnPassphraseRequired without showing the user a spinner. | |
210 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase)) | |
211 return false; | |
212 | |
213 // Post a decryption task on the syncer thread. | |
214 registrar_->sync_thread()->task_runner()->PostTask( | |
215 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase, | |
216 core_.get(), passphrase)); | |
217 | |
218 // Since we were able to decrypt the cached pending keys with the passphrase | |
219 // provided, we immediately alert the UI layer that the passphrase was | |
220 // accepted. This will avoid the situation where a user enters a passphrase, | |
221 // clicks OK, immediately reopens the advanced settings dialog, and gets an | |
222 // unnecessary prompt for a passphrase. | |
223 // Note: It is not guaranteed that the passphrase will be accepted by the | |
224 // syncer thread, since we could receive a new nigori node while the task is | |
225 // pending. This scenario is a valid race, and SetDecryptionPassphrase can | |
226 // trigger a new OnPassphraseRequired if it needs to. | |
227 NotifyPassphraseAccepted(); | |
228 return true; | |
229 } | |
230 | |
231 void SyncBackendHostImpl::StopSyncingForShutdown() { | |
232 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
233 | |
234 // Immediately stop sending messages to the frontend. | |
235 frontend_ = NULL; | |
236 | |
237 DCHECK(registrar_->sync_thread()->IsRunning()); | |
238 | |
239 registrar_->RequestWorkerStopOnUIThread(); | |
240 | |
241 core_->ShutdownOnUIThread(); | |
242 } | |
243 | |
244 std::unique_ptr<base::Thread> SyncBackendHostImpl::Shutdown( | |
245 syncer::ShutdownReason reason) { | |
246 // StopSyncingForShutdown() (which nulls out |frontend_|) should be | |
247 // called first. | |
248 DCHECK(!frontend_); | |
249 DCHECK(registrar_->sync_thread()->IsRunning()); | |
250 | |
251 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN); | |
252 | |
253 if (invalidation_handler_registered_) { | |
254 if (reason == syncer::DISABLE_SYNC) { | |
255 UnregisterInvalidationIds(); | |
256 } | |
257 invalidator_->UnregisterInvalidationHandler(this); | |
258 invalidator_ = NULL; | |
259 } | |
260 invalidation_handler_registered_ = false; | |
261 | |
262 model_type_connector_.reset(); | |
263 | |
264 // Shut down and destroy sync manager. | |
265 registrar_->sync_thread()->task_runner()->PostTask( | |
266 FROM_HERE, | |
267 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason)); | |
268 core_ = NULL; | |
269 | |
270 // Worker cleanup. | |
271 SyncBackendRegistrar* detached_registrar = registrar_.release(); | |
272 detached_registrar->sync_thread()->task_runner()->PostTask( | |
273 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown, | |
274 base::Unretained(detached_registrar))); | |
275 | |
276 if (sync_thread_claimed) | |
277 return detached_registrar->ReleaseSyncThread(); | |
278 else | |
279 return std::unique_ptr<base::Thread>(); | |
280 } | |
281 | |
282 void SyncBackendHostImpl::UnregisterInvalidationIds() { | |
283 if (invalidation_handler_registered_) { | |
284 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this, | |
285 syncer::ObjectIdSet())); | |
286 } | |
287 } | |
288 | |
289 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes( | |
290 syncer::ConfigureReason reason, | |
291 const DataTypeConfigStateMap& config_state_map, | |
292 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>& | |
293 ready_task, | |
294 const base::Callback<void()>& retry_callback) { | |
295 // Only one configure is allowed at a time. This is guaranteed by our | |
296 // callers. The SyncBackendHostImpl requests one configure as the backend is | |
297 // initializing and waits for it to complete. After initialization, all | |
298 // configurations will pass through the DataTypeManager, which is careful to | |
299 // never send a new configure request until the current request succeeds. | |
300 | |
301 // The SyncBackendRegistrar's routing info will be updated by adding the | |
302 // types_to_add to the list then removing types_to_remove. Any types which | |
303 // are not in either of those sets will remain untouched. | |
304 // | |
305 // Types which were not in the list previously are not fully downloaded, so we | |
306 // must ask the syncer to download them. Any newly supported datatypes will | |
307 // not have been in that routing info list, so they will be among the types | |
308 // downloaded if they are enabled. | |
309 // | |
310 // The SyncBackendRegistrar's state was initially derived from the types | |
311 // detected to have been downloaded in the database. Afterwards it is | |
312 // modified only by this function. We expect it to remain in sync with the | |
313 // backend because configuration requests are never aborted; they are retried | |
314 // until they succeed or the backend is shut down. | |
315 | |
316 syncer::ModelTypeSet disabled_types = | |
317 GetDataTypesInState(DISABLED, config_state_map); | |
318 syncer::ModelTypeSet fatal_types = | |
319 GetDataTypesInState(FATAL, config_state_map); | |
320 syncer::ModelTypeSet crypto_types = | |
321 GetDataTypesInState(CRYPTO, config_state_map); | |
322 syncer::ModelTypeSet unready_types = | |
323 GetDataTypesInState(UNREADY, config_state_map); | |
324 | |
325 disabled_types.PutAll(fatal_types); | |
326 disabled_types.PutAll(crypto_types); | |
327 disabled_types.PutAll(unready_types); | |
328 | |
329 syncer::ModelTypeSet active_types = | |
330 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map); | |
331 syncer::ModelTypeSet clean_first_types = | |
332 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map); | |
333 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes( | |
334 syncer::Union(active_types, clean_first_types), | |
335 disabled_types); | |
336 types_to_download.PutAll(clean_first_types); | |
337 types_to_download.RemoveAll(syncer::ProxyTypes()); | |
338 if (!types_to_download.Empty()) | |
339 types_to_download.Put(syncer::NIGORI); | |
340 | |
341 // TODO(sync): crbug.com/137550. | |
342 // It's dangerous to configure types that have progress markers. Types with | |
343 // progress markers can trigger a MIGRATION_DONE response. We are not | |
344 // prepared to handle a migration during a configure, so we must ensure that | |
345 // all our types_to_download actually contain no data before we sync them. | |
346 // | |
347 // One common way to end up in this situation used to be types which | |
348 // downloaded some or all of their data but have not applied it yet. We avoid | |
349 // problems with those types by purging the data of any such partially synced | |
350 // types soon after we load the directory. | |
351 // | |
352 // Another possible scenario is that we have newly supported or newly enabled | |
353 // data types being downloaded here but the nigori type, which is always | |
354 // included in any GetUpdates request, requires migration. The server has | |
355 // code to detect this scenario based on the configure reason, the fact that | |
356 // the nigori type is the only requested type which requires migration, and | |
357 // that the requested types list includes at least one non-nigori type. It | |
358 // will not send a MIGRATION_DONE response in that case. We still need to be | |
359 // careful to not send progress markers for non-nigori types, though. If a | |
360 // non-nigori type in the request requires migration, a MIGRATION_DONE | |
361 // response will be sent. | |
362 | |
363 syncer::ModelSafeRoutingInfo routing_info; | |
364 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
365 | |
366 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes(); | |
367 syncer::ModelTypeSet types_to_purge = | |
368 syncer::Difference(syncer::ModelTypeSet::All(), current_types); | |
369 syncer::ModelTypeSet inactive_types = | |
370 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map); | |
371 types_to_purge.RemoveAll(inactive_types); | |
372 types_to_purge.RemoveAll(unready_types); | |
373 | |
374 // If a type has already been disabled and unapplied or journaled, it will | |
375 // not be part of the |types_to_purge| set, and therefore does not need | |
376 // to be acted on again. | |
377 fatal_types.RetainAll(types_to_purge); | |
378 syncer::ModelTypeSet unapply_types = | |
379 syncer::Union(crypto_types, clean_first_types); | |
380 unapply_types.RetainAll(types_to_purge); | |
381 | |
382 DCHECK(syncer::Intersection(current_types, fatal_types).Empty()); | |
383 DCHECK(syncer::Intersection(current_types, crypto_types).Empty()); | |
384 DCHECK(current_types.HasAll(types_to_download)); | |
385 | |
386 SDVLOG(1) << "Types " | |
387 << syncer::ModelTypeSetToString(types_to_download) | |
388 << " added; calling DoConfigureSyncer"; | |
389 // Divide up the types into their corresponding actions (each is mutually | |
390 // exclusive): | |
391 // - Types which have just been added to the routing info (types_to_download): | |
392 // are downloaded. | |
393 // - Types which have encountered a fatal error (fatal_types) are deleted | |
394 // from the directory and journaled in the delete journal. | |
395 // - Types which have encountered a cryptographer error (crypto_types) are | |
396 // unapplied (local state is purged but sync state is not). | |
397 // - All other types not in the routing info (types just disabled) are deleted | |
398 // from the directory. | |
399 // - Everything else (enabled types and already disabled types) is not | |
400 // touched. | |
401 RequestConfigureSyncer(reason, | |
402 types_to_download, | |
403 types_to_purge, | |
404 fatal_types, | |
405 unapply_types, | |
406 inactive_types, | |
407 routing_info, | |
408 ready_task, | |
409 retry_callback); | |
410 | |
411 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty()); | |
412 DCHECK(syncer::Intersection(active_types, fatal_types).Empty()); | |
413 DCHECK(syncer::Intersection(active_types, unapply_types).Empty()); | |
414 DCHECK(syncer::Intersection(active_types, inactive_types).Empty()); | |
415 return syncer::Difference(active_types, types_to_download); | |
416 } | |
417 | |
418 void SyncBackendHostImpl::EnableEncryptEverything() { | |
419 registrar_->sync_thread()->task_runner()->PostTask( | |
420 FROM_HERE, | |
421 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get())); | |
422 } | |
423 | |
424 void SyncBackendHostImpl::ActivateDirectoryDataType( | |
425 syncer::ModelType type, | |
426 syncer::ModelSafeGroup group, | |
427 sync_driver::ChangeProcessor* change_processor) { | |
428 registrar_->ActivateDataType(type, group, change_processor, GetUserShare()); | |
429 } | |
430 | |
431 void SyncBackendHostImpl::DeactivateDirectoryDataType(syncer::ModelType type) { | |
432 registrar_->DeactivateDataType(type); | |
433 } | |
434 | |
435 void SyncBackendHostImpl::ActivateNonBlockingDataType( | |
436 syncer::ModelType type, | |
437 std::unique_ptr<syncer_v2::ActivationContext> activation_context) { | |
438 registrar_->RegisterNonBlockingType(type); | |
439 if (activation_context->data_type_state.initial_sync_done()) | |
440 registrar_->AddRestoredNonBlockingType(type); | |
441 model_type_connector_->ConnectType(type, std::move(activation_context)); | |
442 } | |
443 | |
444 void SyncBackendHostImpl::DeactivateNonBlockingDataType( | |
445 syncer::ModelType type) { | |
446 model_type_connector_->DisconnectType(type); | |
447 } | |
448 | |
449 syncer::UserShare* SyncBackendHostImpl::GetUserShare() const { | |
450 return core_->sync_manager()->GetUserShare(); | |
451 } | |
452 | |
453 SyncBackendHostImpl::Status SyncBackendHostImpl::GetDetailedStatus() { | |
454 DCHECK(initialized()); | |
455 return core_->sync_manager()->GetDetailedStatus(); | |
456 } | |
457 | |
458 syncer::sessions::SyncSessionSnapshot | |
459 SyncBackendHostImpl::GetLastSessionSnapshot() const { | |
460 return last_snapshot_; | |
461 } | |
462 | |
463 bool SyncBackendHostImpl::HasUnsyncedItems() const { | |
464 DCHECK(initialized()); | |
465 return core_->sync_manager()->HasUnsyncedItems(); | |
466 } | |
467 | |
468 bool SyncBackendHostImpl::IsNigoriEnabled() const { | |
469 return registrar_.get() && registrar_->IsNigoriEnabled(); | |
470 } | |
471 | |
472 syncer::PassphraseType SyncBackendHostImpl::GetPassphraseType() const { | |
473 return cached_passphrase_type_; | |
474 } | |
475 | |
476 base::Time SyncBackendHostImpl::GetExplicitPassphraseTime() const { | |
477 return cached_explicit_passphrase_time_; | |
478 } | |
479 | |
480 bool SyncBackendHostImpl::IsCryptographerReady( | |
481 const syncer::BaseTransaction* trans) const { | |
482 return initialized() && trans->GetCryptographer() && | |
483 trans->GetCryptographer()->is_ready(); | |
484 } | |
485 | |
486 void SyncBackendHostImpl::GetModelSafeRoutingInfo( | |
487 syncer::ModelSafeRoutingInfo* out) const { | |
488 if (initialized()) { | |
489 CHECK(registrar_.get()); | |
490 registrar_->GetModelSafeRoutingInfo(out); | |
491 } else { | |
492 NOTREACHED(); | |
493 } | |
494 } | |
495 | |
496 void SyncBackendHostImpl::FlushDirectory() const { | |
497 DCHECK(initialized()); | |
498 registrar_->sync_thread()->task_runner()->PostTask( | |
499 FROM_HERE, base::Bind(&SyncBackendHostCore::SaveChanges, core_)); | |
500 } | |
501 | |
502 void SyncBackendHostImpl::RequestBufferedProtocolEventsAndEnableForwarding() { | |
503 registrar_->sync_thread()->task_runner()->PostTask( | |
504 FROM_HERE, | |
505 base::Bind( | |
506 &SyncBackendHostCore::SendBufferedProtocolEventsAndEnableForwarding, | |
507 core_)); | |
508 } | |
509 | |
510 void SyncBackendHostImpl::DisableProtocolEventForwarding() { | |
511 registrar_->sync_thread()->task_runner()->PostTask( | |
512 FROM_HERE, | |
513 base::Bind(&SyncBackendHostCore::DisableProtocolEventForwarding, core_)); | |
514 } | |
515 | |
516 void SyncBackendHostImpl::EnableDirectoryTypeDebugInfoForwarding() { | |
517 DCHECK(initialized()); | |
518 registrar_->sync_thread()->task_runner()->PostTask( | |
519 FROM_HERE, | |
520 base::Bind(&SyncBackendHostCore::EnableDirectoryTypeDebugInfoForwarding, | |
521 core_)); | |
522 } | |
523 | |
524 void SyncBackendHostImpl::DisableDirectoryTypeDebugInfoForwarding() { | |
525 DCHECK(initialized()); | |
526 registrar_->sync_thread()->task_runner()->PostTask( | |
527 FROM_HERE, | |
528 base::Bind(&SyncBackendHostCore::DisableDirectoryTypeDebugInfoForwarding, | |
529 core_)); | |
530 } | |
531 | |
532 void SyncBackendHostImpl::GetAllNodesForTypes( | |
533 syncer::ModelTypeSet types, | |
534 base::Callback<void(const std::vector<syncer::ModelType>&, | |
535 ScopedVector<base::ListValue>)> callback) { | |
536 DCHECK(initialized()); | |
537 registrar_->sync_thread()->task_runner()->PostTask( | |
538 FROM_HERE, base::Bind(&SyncBackendHostCore::GetAllNodesForTypes, core_, | |
539 types, frontend_task_runner_, callback)); | |
540 } | |
541 | |
542 void SyncBackendHostImpl::InitCore( | |
543 std::unique_ptr<DoInitializeOptions> options) { | |
544 registrar_->sync_thread()->task_runner()->PostTask( | |
545 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(), | |
546 base::Passed(&options))); | |
547 } | |
548 | |
549 void SyncBackendHostImpl::RequestConfigureSyncer( | |
550 syncer::ConfigureReason reason, | |
551 syncer::ModelTypeSet to_download, | |
552 syncer::ModelTypeSet to_purge, | |
553 syncer::ModelTypeSet to_journal, | |
554 syncer::ModelTypeSet to_unapply, | |
555 syncer::ModelTypeSet to_ignore, | |
556 const syncer::ModelSafeRoutingInfo& routing_info, | |
557 const base::Callback<void(syncer::ModelTypeSet, | |
558 syncer::ModelTypeSet)>& ready_task, | |
559 const base::Closure& retry_callback) { | |
560 DoConfigureSyncerTypes config_types; | |
561 config_types.to_download = to_download; | |
562 config_types.to_purge = to_purge; | |
563 config_types.to_journal = to_journal; | |
564 config_types.to_unapply = to_unapply; | |
565 registrar_->sync_thread()->task_runner()->PostTask( | |
566 FROM_HERE, | |
567 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason, | |
568 config_types, routing_info, ready_task, retry_callback)); | |
569 } | |
570 | |
571 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop( | |
572 const syncer::ModelTypeSet enabled_types, | |
573 const syncer::ModelTypeSet succeeded_configuration_types, | |
574 const syncer::ModelTypeSet failed_configuration_types, | |
575 const base::Callback<void(syncer::ModelTypeSet, | |
576 syncer::ModelTypeSet)>& ready_task) { | |
577 if (!frontend_) | |
578 return; | |
579 | |
580 if (invalidator_) { | |
581 CHECK(invalidator_->UpdateRegisteredInvalidationIds( | |
582 this, ModelTypeSetToObjectIdSet(enabled_types))); | |
583 } | |
584 | |
585 if (!ready_task.is_null()) | |
586 ready_task.Run(succeeded_configuration_types, failed_configuration_types); | |
587 } | |
588 | |
589 void SyncBackendHostImpl::AddExperimentalTypes() { | |
590 CHECK(initialized()); | |
591 syncer::Experiments experiments; | |
592 if (core_->sync_manager()->ReceivedExperiment(&experiments)) | |
593 frontend_->OnExperimentsChanged(experiments); | |
594 } | |
595 | |
596 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop( | |
597 const syncer::WeakHandle<syncer::JsBackend> js_backend, | |
598 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener> | |
599 debug_info_listener, | |
600 std::unique_ptr<syncer_v2::ModelTypeConnector> model_type_connector, | |
601 const std::string& cache_guid) { | |
602 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
603 | |
604 model_type_connector_ = std::move(model_type_connector); | |
605 | |
606 if (!frontend_) | |
607 return; | |
608 | |
609 initialized_ = true; | |
610 | |
611 if (invalidator_) { | |
612 invalidator_->RegisterInvalidationHandler(this); | |
613 invalidation_handler_registered_ = true; | |
614 | |
615 // Fake a state change to initialize the SyncManager's cached invalidator | |
616 // state. | |
617 OnInvalidatorStateChange(invalidator_->GetInvalidatorState()); | |
618 } | |
619 | |
620 // Now that we've downloaded the control types, we can see if there are any | |
621 // experimental types to enable. This should be done before we inform | |
622 // the frontend to ensure they're visible in the customize screen. | |
623 AddExperimentalTypes(); | |
624 frontend_->OnBackendInitialized(js_backend, | |
625 debug_info_listener, | |
626 cache_guid, | |
627 true); | |
628 } | |
629 | |
630 void SyncBackendHostImpl::HandleInitializationFailureOnFrontendLoop() { | |
631 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
632 if (!frontend_) | |
633 return; | |
634 | |
635 frontend_->OnBackendInitialized( | |
636 syncer::WeakHandle<syncer::JsBackend>(), | |
637 syncer::WeakHandle<syncer::DataTypeDebugInfoListener>(), | |
638 "", | |
639 false); | |
640 } | |
641 | |
642 void SyncBackendHostImpl::HandleSyncCycleCompletedOnFrontendLoop( | |
643 const syncer::sessions::SyncSessionSnapshot& snapshot) { | |
644 if (!frontend_) | |
645 return; | |
646 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
647 | |
648 last_snapshot_ = snapshot; | |
649 | |
650 SDVLOG(1) << "Got snapshot " << snapshot.ToString(); | |
651 | |
652 if (!snapshot.poll_finish_time().is_null()) | |
653 sync_prefs_->SetLastPollTime(snapshot.poll_finish_time()); | |
654 | |
655 // Process any changes to the datatypes we're syncing. | |
656 // TODO(sync): add support for removing types. | |
657 if (initialized()) | |
658 AddExperimentalTypes(); | |
659 | |
660 if (initialized()) | |
661 frontend_->OnSyncCycleCompleted(); | |
662 } | |
663 | |
664 void SyncBackendHostImpl::RetryConfigurationOnFrontendLoop( | |
665 const base::Closure& retry_callback) { | |
666 SDVLOG(1) << "Failed to complete configuration, informing of retry."; | |
667 retry_callback.Run(); | |
668 } | |
669 | |
670 void SyncBackendHostImpl::PersistEncryptionBootstrapToken( | |
671 const std::string& token, | |
672 syncer::BootstrapTokenType token_type) { | |
673 CHECK(sync_prefs_.get()); | |
674 if (token_type == syncer::PASSPHRASE_BOOTSTRAP_TOKEN) | |
675 sync_prefs_->SetEncryptionBootstrapToken(token); | |
676 else | |
677 sync_prefs_->SetKeystoreEncryptionBootstrapToken(token); | |
678 } | |
679 | |
680 void SyncBackendHostImpl::HandleActionableErrorEventOnFrontendLoop( | |
681 const syncer::SyncProtocolError& sync_error) { | |
682 if (!frontend_) | |
683 return; | |
684 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
685 frontend_->OnActionableError(sync_error); | |
686 } | |
687 | |
688 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop( | |
689 syncer::ModelTypeSet types) { | |
690 if (!frontend_) | |
691 return; | |
692 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
693 frontend_->OnMigrationNeededForTypes(types); | |
694 } | |
695 | |
696 void SyncBackendHostImpl::OnInvalidatorStateChange( | |
697 syncer::InvalidatorState state) { | |
698 registrar_->sync_thread()->task_runner()->PostTask( | |
699 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnInvalidatorStateChange, | |
700 core_.get(), state)); | |
701 } | |
702 | |
703 void SyncBackendHostImpl::OnIncomingInvalidation( | |
704 const syncer::ObjectIdInvalidationMap& invalidation_map) { | |
705 registrar_->sync_thread()->task_runner()->PostTask( | |
706 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnIncomingInvalidation, | |
707 core_.get(), invalidation_map)); | |
708 } | |
709 | |
710 std::string SyncBackendHostImpl::GetOwnerName() const { | |
711 return "SyncBackendHostImpl"; | |
712 } | |
713 | |
714 bool SyncBackendHostImpl::CheckPassphraseAgainstCachedPendingKeys( | |
715 const std::string& passphrase) const { | |
716 DCHECK(cached_pending_keys_.has_blob()); | |
717 DCHECK(!passphrase.empty()); | |
718 syncer::Nigori nigori; | |
719 nigori.InitByDerivation("localhost", "dummy", passphrase); | |
720 std::string plaintext; | |
721 bool result = nigori.Decrypt(cached_pending_keys_.blob(), &plaintext); | |
722 DVLOG_IF(1, result) << "Passphrase failed to decrypt pending keys."; | |
723 return result; | |
724 } | |
725 | |
726 void SyncBackendHostImpl::NotifyPassphraseRequired( | |
727 syncer::PassphraseRequiredReason reason, | |
728 sync_pb::EncryptedData pending_keys) { | |
729 if (!frontend_) | |
730 return; | |
731 | |
732 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
733 | |
734 // Update our cache of the cryptographer's pending keys. | |
735 cached_pending_keys_ = pending_keys; | |
736 | |
737 frontend_->OnPassphraseRequired(reason, pending_keys); | |
738 } | |
739 | |
740 void SyncBackendHostImpl::NotifyPassphraseAccepted() { | |
741 if (!frontend_) | |
742 return; | |
743 | |
744 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
745 | |
746 // Clear our cache of the cryptographer's pending keys. | |
747 cached_pending_keys_.clear_blob(); | |
748 frontend_->OnPassphraseAccepted(); | |
749 } | |
750 | |
751 void SyncBackendHostImpl::NotifyEncryptedTypesChanged( | |
752 syncer::ModelTypeSet encrypted_types, | |
753 bool encrypt_everything) { | |
754 if (!frontend_) | |
755 return; | |
756 | |
757 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
758 frontend_->OnEncryptedTypesChanged( | |
759 encrypted_types, encrypt_everything); | |
760 } | |
761 | |
762 void SyncBackendHostImpl::NotifyEncryptionComplete() { | |
763 if (!frontend_) | |
764 return; | |
765 | |
766 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
767 frontend_->OnEncryptionComplete(); | |
768 } | |
769 | |
770 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop( | |
771 syncer::PassphraseType type, | |
772 base::Time explicit_passphrase_time) { | |
773 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
774 DVLOG(1) << "Passphrase type changed to " | |
775 << syncer::PassphraseTypeToString(type); | |
776 cached_passphrase_type_ = type; | |
777 cached_explicit_passphrase_time_ = explicit_passphrase_time; | |
778 } | |
779 | |
780 void SyncBackendHostImpl::HandleLocalSetPassphraseEncryptionOnFrontendLoop( | |
781 const syncer::SyncEncryptionHandler::NigoriState& nigori_state) { | |
782 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
783 frontend_->OnLocalSetPassphraseEncryption(nigori_state); | |
784 } | |
785 | |
786 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop( | |
787 syncer::ConnectionStatus status) { | |
788 if (!frontend_) | |
789 return; | |
790 | |
791 DCHECK(frontend_task_runner_->BelongsToCurrentThread()); | |
792 | |
793 DVLOG(1) << "Connection status changed: " | |
794 << syncer::ConnectionStatusToString(status); | |
795 frontend_->OnConnectionStatusChange(status); | |
796 } | |
797 | |
798 void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop( | |
799 syncer::ProtocolEvent* event) { | |
800 std::unique_ptr<syncer::ProtocolEvent> scoped_event(event); | |
801 if (!frontend_) | |
802 return; | |
803 frontend_->OnProtocolEvent(*scoped_event); | |
804 } | |
805 | |
806 void SyncBackendHostImpl::HandleDirectoryCommitCountersUpdatedOnFrontendLoop( | |
807 syncer::ModelType type, | |
808 const syncer::CommitCounters& counters) { | |
809 if (!frontend_) | |
810 return; | |
811 frontend_->OnDirectoryTypeCommitCounterUpdated(type, counters); | |
812 } | |
813 | |
814 void SyncBackendHostImpl::HandleDirectoryUpdateCountersUpdatedOnFrontendLoop( | |
815 syncer::ModelType type, | |
816 const syncer::UpdateCounters& counters) { | |
817 if (!frontend_) | |
818 return; | |
819 frontend_->OnDirectoryTypeUpdateCounterUpdated(type, counters); | |
820 } | |
821 | |
822 void SyncBackendHostImpl::HandleDirectoryStatusCountersUpdatedOnFrontendLoop( | |
823 syncer::ModelType type, | |
824 const syncer::StatusCounters& counters) { | |
825 if (!frontend_) | |
826 return; | |
827 frontend_->OnDirectoryTypeStatusCounterUpdated(type, counters); | |
828 } | |
829 | |
830 void SyncBackendHostImpl::UpdateInvalidationVersions( | |
831 const std::map<syncer::ModelType, int64_t>& invalidation_versions) { | |
832 sync_prefs_->UpdateInvalidationVersions(invalidation_versions); | |
833 } | |
834 | |
835 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() { | |
836 return registrar_->sync_thread()->message_loop(); | |
837 } | |
838 | |
839 void SyncBackendHostImpl::RefreshTypesForTest(syncer::ModelTypeSet types) { | |
840 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
841 | |
842 registrar_->sync_thread()->task_runner()->PostTask( | |
843 FROM_HERE, | |
844 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types)); | |
845 } | |
846 | |
847 void SyncBackendHostImpl::ClearServerData( | |
848 const syncer::SyncManager::ClearServerDataCallback& callback) { | |
849 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
850 registrar_->sync_thread()->task_runner()->PostTask( | |
851 FROM_HERE, base::Bind(&SyncBackendHostCore::DoClearServerData, | |
852 core_.get(), callback)); | |
853 } | |
854 | |
855 void SyncBackendHostImpl::OnCookieJarChanged(bool account_mismatch, | |
856 bool empty_jar) { | |
857 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
858 registrar_->sync_thread()->task_runner()->PostTask( | |
859 FROM_HERE, base::Bind(&SyncBackendHostCore::DoOnCookieJarChanged, | |
860 core_.get(), account_mismatch, empty_jar)); | |
861 } | |
862 | |
863 void SyncBackendHostImpl::ClearServerDataDoneOnFrontendLoop( | |
864 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) { | |
865 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
866 frontend_callback.Run(); | |
867 } | |
868 | |
869 } // namespace browser_sync | |
870 | |
871 #undef SDVLOG | |
872 | |
873 #undef SLOG | |
OLD | NEW |