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 "chrome/browser/sync/glue/sync_backend_host_impl.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/location.h" | |
9 #include "base/logging.h" | |
10 #include "base/single_thread_task_runner.h" | |
11 #include "chrome/browser/sync/glue/sync_backend_host_core.h" | |
12 #include "components/invalidation/public/invalidation_service.h" | |
13 #include "components/invalidation/public/object_id_invalidation_map.h" | |
14 #include "components/signin/core/browser/signin_client.h" | |
15 #include "components/sync_driver/glue/sync_backend_registrar.h" | |
16 #include "components/sync_driver/invalidation_helper.h" | |
17 #include "components/sync_driver/sync_client.h" | |
18 #include "components/sync_driver/sync_driver_switches.h" | |
19 #include "components/sync_driver/sync_frontend.h" | |
20 #include "components/sync_driver/sync_prefs.h" | |
21 #include "sync/internal_api/public/activation_context.h" | |
22 #include "sync/internal_api/public/base_transaction.h" | |
23 #include "sync/internal_api/public/events/protocol_event.h" | |
24 #include "sync/internal_api/public/http_bridge.h" | |
25 #include "sync/internal_api/public/internal_components_factory.h" | |
26 #include "sync/internal_api/public/internal_components_factory_impl.h" | |
27 #include "sync/internal_api/public/sync_manager.h" | |
28 #include "sync/internal_api/public/sync_manager_factory.h" | |
29 #include "sync/internal_api/public/util/experiments.h" | |
30 #include "sync/internal_api/public/util/sync_string_conversions.h" | |
31 | |
32 // Helper macros to log with the syncer thread name; useful when there | |
33 // are multiple syncers involved. | |
34 | |
35 #define SLOG(severity) LOG(severity) << name_ << ": " | |
36 | |
37 #define SDVLOG(verbose_level) DVLOG(verbose_level) << name_ << ": " | |
38 | |
39 using syncer::InternalComponentsFactory; | |
40 | |
41 namespace browser_sync { | |
42 | |
43 SyncBackendHostImpl::SyncBackendHostImpl( | |
44 const std::string& name, | |
45 sync_driver::SyncClient* sync_client, | |
46 const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread, | |
47 invalidation::InvalidationService* invalidator, | |
48 const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs, | |
49 const base::FilePath& sync_folder) | |
50 : frontend_loop_(base::MessageLoop::current()), | |
51 sync_client_(sync_client), | |
52 ui_thread_(ui_thread), | |
53 name_(name), | |
54 initialized_(false), | |
55 sync_prefs_(sync_prefs), | |
56 frontend_(NULL), | |
57 cached_passphrase_type_(syncer::IMPLICIT_PASSPHRASE), | |
58 invalidator_(invalidator), | |
59 invalidation_handler_registered_(false), | |
60 weak_ptr_factory_(this) { | |
61 core_ = new SyncBackendHostCore(name_, sync_folder, | |
62 sync_prefs_->HasSyncSetupCompleted(), | |
63 weak_ptr_factory_.GetWeakPtr()); | |
64 } | |
65 | |
66 SyncBackendHostImpl::~SyncBackendHostImpl() { | |
67 DCHECK(!core_.get() && !frontend_) << "Must call Shutdown before destructor."; | |
68 DCHECK(!registrar_.get()); | |
69 } | |
70 | |
71 void SyncBackendHostImpl::Initialize( | |
72 sync_driver::SyncFrontend* frontend, | |
73 scoped_ptr<base::Thread> sync_thread, | |
74 const scoped_refptr<base::SingleThreadTaskRunner>& db_thread, | |
75 const scoped_refptr<base::SingleThreadTaskRunner>& file_thread, | |
76 const syncer::WeakHandle<syncer::JsEventHandler>& event_handler, | |
77 const GURL& sync_service_url, | |
78 const std::string& sync_user_agent, | |
79 const syncer::SyncCredentials& credentials, | |
80 bool delete_sync_data_folder, | |
81 scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory, | |
82 const syncer::WeakHandle<syncer::UnrecoverableErrorHandler>& | |
83 unrecoverable_error_handler, | |
84 const base::Closure& report_unrecoverable_error_function, | |
85 const HttpPostProviderFactoryGetter& http_post_provider_factory_getter, | |
86 scoped_ptr<syncer::SyncEncryptionHandler::NigoriState> saved_nigori_state) { | |
87 registrar_.reset(new browser_sync::SyncBackendRegistrar( | |
88 name_, sync_client_, sync_thread.Pass(), ui_thread_, db_thread, | |
89 file_thread)); | |
90 CHECK(registrar_->sync_thread()); | |
91 | |
92 frontend_ = frontend; | |
93 DCHECK(frontend); | |
94 | |
95 syncer::ModelSafeRoutingInfo routing_info; | |
96 std::vector<scoped_refptr<syncer::ModelSafeWorker> > workers; | |
97 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
98 registrar_->GetWorkers(&workers); | |
99 | |
100 InternalComponentsFactory::Switches factory_switches = { | |
101 InternalComponentsFactory::ENCRYPTION_KEYSTORE, | |
102 InternalComponentsFactory::BACKOFF_NORMAL | |
103 }; | |
104 | |
105 base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); | |
106 if (cl->HasSwitch(switches::kSyncShortInitialRetryOverride)) { | |
107 factory_switches.backoff_override = | |
108 InternalComponentsFactory::BACKOFF_SHORT_INITIAL_RETRY_OVERRIDE; | |
109 } | |
110 if (cl->HasSwitch(switches::kSyncEnableGetUpdateAvoidance)) { | |
111 factory_switches.pre_commit_updates_policy = | |
112 InternalComponentsFactory::FORCE_ENABLE_PRE_COMMIT_UPDATE_AVOIDANCE; | |
113 } | |
114 syncer::PassphraseTransitionClearDataOption clear_data_option = | |
115 syncer::PASSPHRASE_TRANSITION_DO_NOT_CLEAR_DATA; | |
116 if (cl->HasSwitch(switches::kSyncEnableClearDataOnPassphraseEncryption)) | |
117 clear_data_option = syncer::PASSPHRASE_TRANSITION_CLEAR_DATA; | |
118 | |
119 std::map<syncer::ModelType, int64> invalidation_versions; | |
120 sync_prefs_->GetInvalidationVersions(&invalidation_versions); | |
121 | |
122 scoped_ptr<DoInitializeOptions> init_opts(new DoInitializeOptions( | |
123 registrar_->sync_thread()->message_loop(), registrar_.get(), routing_info, | |
124 workers, sync_client_->GetExtensionsActivity(), event_handler, | |
125 sync_service_url, sync_user_agent, | |
126 http_post_provider_factory_getter.Run( | |
127 core_->GetRequestContextCancelationSignal()), | |
128 credentials, invalidator_ ? invalidator_->GetInvalidatorClientId() : "", | |
129 sync_manager_factory.Pass(), delete_sync_data_folder, | |
130 sync_prefs_->GetEncryptionBootstrapToken(), | |
131 sync_prefs_->GetKeystoreEncryptionBootstrapToken(), | |
132 scoped_ptr<InternalComponentsFactory>( | |
133 new syncer::InternalComponentsFactoryImpl(factory_switches)) | |
134 .Pass(), | |
135 unrecoverable_error_handler, report_unrecoverable_error_function, | |
136 saved_nigori_state.Pass(), clear_data_option, invalidation_versions)); | |
137 InitCore(init_opts.Pass()); | |
138 } | |
139 | |
140 void SyncBackendHostImpl::TriggerRefresh(const syncer::ModelTypeSet& types) { | |
141 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
142 registrar_->sync_thread()->task_runner()->PostTask( | |
143 FROM_HERE, | |
144 base::Bind(&SyncBackendHostCore::DoRefreshTypes, core_.get(), types)); | |
145 } | |
146 | |
147 void SyncBackendHostImpl::UpdateCredentials( | |
148 const syncer::SyncCredentials& credentials) { | |
149 DCHECK(registrar_->sync_thread()->IsRunning()); | |
150 registrar_->sync_thread()->task_runner()->PostTask( | |
151 FROM_HERE, base::Bind(&SyncBackendHostCore::DoUpdateCredentials, | |
152 core_.get(), credentials)); | |
153 } | |
154 | |
155 void SyncBackendHostImpl::StartSyncingWithServer() { | |
156 SDVLOG(1) << "SyncBackendHostImpl::StartSyncingWithServer called."; | |
157 | |
158 syncer::ModelSafeRoutingInfo routing_info; | |
159 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
160 | |
161 registrar_->sync_thread()->task_runner()->PostTask( | |
162 FROM_HERE, base::Bind(&SyncBackendHostCore::DoStartSyncing, core_.get(), | |
163 routing_info, sync_prefs_->GetLastPollTime())); | |
164 } | |
165 | |
166 void SyncBackendHostImpl::SetEncryptionPassphrase(const std::string& passphrase, | |
167 bool is_explicit) { | |
168 DCHECK(registrar_->sync_thread()->IsRunning()); | |
169 if (!IsNigoriEnabled()) { | |
170 NOTREACHED() << "SetEncryptionPassphrase must never be called when nigori" | |
171 " is disabled."; | |
172 return; | |
173 } | |
174 | |
175 // We should never be called with an empty passphrase. | |
176 DCHECK(!passphrase.empty()); | |
177 | |
178 // This should only be called by the frontend. | |
179 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
180 | |
181 // SetEncryptionPassphrase should never be called if we are currently | |
182 // encrypted with an explicit passphrase. | |
183 DCHECK(cached_passphrase_type_ == syncer::KEYSTORE_PASSPHRASE || | |
184 cached_passphrase_type_ == syncer::IMPLICIT_PASSPHRASE); | |
185 | |
186 // Post an encryption task on the syncer thread. | |
187 registrar_->sync_thread()->task_runner()->PostTask( | |
188 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetEncryptionPassphrase, | |
189 core_.get(), passphrase, is_explicit)); | |
190 } | |
191 | |
192 bool SyncBackendHostImpl::SetDecryptionPassphrase( | |
193 const std::string& passphrase) { | |
194 if (!IsNigoriEnabled()) { | |
195 NOTREACHED() << "SetDecryptionPassphrase must never be called when nigori" | |
196 " is disabled."; | |
197 return false; | |
198 } | |
199 | |
200 // We should never be called with an empty passphrase. | |
201 DCHECK(!passphrase.empty()); | |
202 | |
203 // This should only be called by the frontend. | |
204 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
205 | |
206 // This should only be called when we have cached pending keys. | |
207 DCHECK(cached_pending_keys_.has_blob()); | |
208 | |
209 // Check the passphrase that was provided against our local cache of the | |
210 // cryptographer's pending keys. If this was unsuccessful, the UI layer can | |
211 // immediately call OnPassphraseRequired without showing the user a spinner. | |
212 if (!CheckPassphraseAgainstCachedPendingKeys(passphrase)) | |
213 return false; | |
214 | |
215 // Post a decryption task on the syncer thread. | |
216 registrar_->sync_thread()->task_runner()->PostTask( | |
217 FROM_HERE, base::Bind(&SyncBackendHostCore::DoSetDecryptionPassphrase, | |
218 core_.get(), passphrase)); | |
219 | |
220 // Since we were able to decrypt the cached pending keys with the passphrase | |
221 // provided, we immediately alert the UI layer that the passphrase was | |
222 // accepted. This will avoid the situation where a user enters a passphrase, | |
223 // clicks OK, immediately reopens the advanced settings dialog, and gets an | |
224 // unnecessary prompt for a passphrase. | |
225 // Note: It is not guaranteed that the passphrase will be accepted by the | |
226 // syncer thread, since we could receive a new nigori node while the task is | |
227 // pending. This scenario is a valid race, and SetDecryptionPassphrase can | |
228 // trigger a new OnPassphraseRequired if it needs to. | |
229 NotifyPassphraseAccepted(); | |
230 return true; | |
231 } | |
232 | |
233 void SyncBackendHostImpl::StopSyncingForShutdown() { | |
234 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
235 | |
236 // Immediately stop sending messages to the frontend. | |
237 frontend_ = NULL; | |
238 | |
239 // Stop non-blocking sync types from sending any more requests to the syncer. | |
240 sync_context_proxy_.reset(); | |
241 | |
242 DCHECK(registrar_->sync_thread()->IsRunning()); | |
243 | |
244 registrar_->RequestWorkerStopOnUIThread(); | |
245 | |
246 core_->ShutdownOnUIThread(); | |
247 } | |
248 | |
249 scoped_ptr<base::Thread> SyncBackendHostImpl::Shutdown( | |
250 syncer::ShutdownReason reason) { | |
251 // StopSyncingForShutdown() (which nulls out |frontend_|) should be | |
252 // called first. | |
253 DCHECK(!frontend_); | |
254 DCHECK(registrar_->sync_thread()->IsRunning()); | |
255 | |
256 bool sync_thread_claimed = (reason != syncer::BROWSER_SHUTDOWN); | |
257 | |
258 if (invalidation_handler_registered_) { | |
259 if (reason == syncer::DISABLE_SYNC) { | |
260 UnregisterInvalidationIds(); | |
261 } | |
262 invalidator_->UnregisterInvalidationHandler(this); | |
263 invalidator_ = NULL; | |
264 } | |
265 invalidation_handler_registered_ = false; | |
266 | |
267 // Shut down and destroy sync manager. | |
268 registrar_->sync_thread()->task_runner()->PostTask( | |
269 FROM_HERE, | |
270 base::Bind(&SyncBackendHostCore::DoShutdown, core_.get(), reason)); | |
271 core_ = NULL; | |
272 | |
273 // Worker cleanup. | |
274 SyncBackendRegistrar* detached_registrar = registrar_.release(); | |
275 detached_registrar->sync_thread()->task_runner()->PostTask( | |
276 FROM_HERE, base::Bind(&SyncBackendRegistrar::Shutdown, | |
277 base::Unretained(detached_registrar))); | |
278 | |
279 if (sync_thread_claimed) | |
280 return detached_registrar->ReleaseSyncThread(); | |
281 else | |
282 return scoped_ptr<base::Thread>(); | |
283 } | |
284 | |
285 void SyncBackendHostImpl::UnregisterInvalidationIds() { | |
286 if (invalidation_handler_registered_) { | |
287 CHECK(invalidator_->UpdateRegisteredInvalidationIds(this, | |
288 syncer::ObjectIdSet())); | |
289 } | |
290 } | |
291 | |
292 syncer::ModelTypeSet SyncBackendHostImpl::ConfigureDataTypes( | |
293 syncer::ConfigureReason reason, | |
294 const DataTypeConfigStateMap& config_state_map, | |
295 const base::Callback<void(syncer::ModelTypeSet, syncer::ModelTypeSet)>& | |
296 ready_task, | |
297 const base::Callback<void()>& retry_callback) { | |
298 // Only one configure is allowed at a time. This is guaranteed by our | |
299 // callers. The SyncBackendHostImpl requests one configure as the backend is | |
300 // initializing and waits for it to complete. After initialization, all | |
301 // configurations will pass through the DataTypeManager, which is careful to | |
302 // never send a new configure request until the current request succeeds. | |
303 | |
304 // The SyncBackendRegistrar's routing info will be updated by adding the | |
305 // types_to_add to the list then removing types_to_remove. Any types which | |
306 // are not in either of those sets will remain untouched. | |
307 // | |
308 // Types which were not in the list previously are not fully downloaded, so we | |
309 // must ask the syncer to download them. Any newly supported datatypes will | |
310 // not have been in that routing info list, so they will be among the types | |
311 // downloaded if they are enabled. | |
312 // | |
313 // The SyncBackendRegistrar's state was initially derived from the types | |
314 // detected to have been downloaded in the database. Afterwards it is | |
315 // modified only by this function. We expect it to remain in sync with the | |
316 // backend because configuration requests are never aborted; they are retried | |
317 // until they succeed or the backend is shut down. | |
318 | |
319 syncer::ModelTypeSet disabled_types = | |
320 GetDataTypesInState(DISABLED, config_state_map); | |
321 syncer::ModelTypeSet fatal_types = | |
322 GetDataTypesInState(FATAL, config_state_map); | |
323 syncer::ModelTypeSet crypto_types = | |
324 GetDataTypesInState(CRYPTO, config_state_map); | |
325 syncer::ModelTypeSet unready_types = | |
326 GetDataTypesInState(UNREADY, config_state_map); | |
327 | |
328 disabled_types.PutAll(fatal_types); | |
329 disabled_types.PutAll(crypto_types); | |
330 disabled_types.PutAll(unready_types); | |
331 | |
332 syncer::ModelTypeSet active_types = | |
333 GetDataTypesInState(CONFIGURE_ACTIVE, config_state_map); | |
334 syncer::ModelTypeSet clean_first_types = | |
335 GetDataTypesInState(CONFIGURE_CLEAN, config_state_map); | |
336 syncer::ModelTypeSet types_to_download = registrar_->ConfigureDataTypes( | |
337 syncer::Union(active_types, clean_first_types), | |
338 disabled_types); | |
339 types_to_download.PutAll(clean_first_types); | |
340 types_to_download.RemoveAll(syncer::ProxyTypes()); | |
341 if (!types_to_download.Empty()) | |
342 types_to_download.Put(syncer::NIGORI); | |
343 | |
344 // TODO(sync): crbug.com/137550. | |
345 // It's dangerous to configure types that have progress markers. Types with | |
346 // progress markers can trigger a MIGRATION_DONE response. We are not | |
347 // prepared to handle a migration during a configure, so we must ensure that | |
348 // all our types_to_download actually contain no data before we sync them. | |
349 // | |
350 // One common way to end up in this situation used to be types which | |
351 // downloaded some or all of their data but have not applied it yet. We avoid | |
352 // problems with those types by purging the data of any such partially synced | |
353 // types soon after we load the directory. | |
354 // | |
355 // Another possible scenario is that we have newly supported or newly enabled | |
356 // data types being downloaded here but the nigori type, which is always | |
357 // included in any GetUpdates request, requires migration. The server has | |
358 // code to detect this scenario based on the configure reason, the fact that | |
359 // the nigori type is the only requested type which requires migration, and | |
360 // that the requested types list includes at least one non-nigori type. It | |
361 // will not send a MIGRATION_DONE response in that case. We still need to be | |
362 // careful to not send progress markers for non-nigori types, though. If a | |
363 // non-nigori type in the request requires migration, a MIGRATION_DONE | |
364 // response will be sent. | |
365 | |
366 syncer::ModelSafeRoutingInfo routing_info; | |
367 registrar_->GetModelSafeRoutingInfo(&routing_info); | |
368 | |
369 syncer::ModelTypeSet current_types = registrar_->GetLastConfiguredTypes(); | |
370 syncer::ModelTypeSet types_to_purge = | |
371 syncer::Difference(syncer::ModelTypeSet::All(), current_types); | |
372 syncer::ModelTypeSet inactive_types = | |
373 GetDataTypesInState(CONFIGURE_INACTIVE, config_state_map); | |
374 types_to_purge.RemoveAll(inactive_types); | |
375 types_to_purge.RemoveAll(unready_types); | |
376 | |
377 // If a type has already been disabled and unapplied or journaled, it will | |
378 // not be part of the |types_to_purge| set, and therefore does not need | |
379 // to be acted on again. | |
380 fatal_types.RetainAll(types_to_purge); | |
381 syncer::ModelTypeSet unapply_types = | |
382 syncer::Union(crypto_types, clean_first_types); | |
383 unapply_types.RetainAll(types_to_purge); | |
384 | |
385 DCHECK(syncer::Intersection(current_types, fatal_types).Empty()); | |
386 DCHECK(syncer::Intersection(current_types, crypto_types).Empty()); | |
387 DCHECK(current_types.HasAll(types_to_download)); | |
388 | |
389 SDVLOG(1) << "Types " | |
390 << syncer::ModelTypeSetToString(types_to_download) | |
391 << " added; calling DoConfigureSyncer"; | |
392 // Divide up the types into their corresponding actions (each is mutually | |
393 // exclusive): | |
394 // - Types which have just been added to the routing info (types_to_download): | |
395 // are downloaded. | |
396 // - Types which have encountered a fatal error (fatal_types) are deleted | |
397 // from the directory and journaled in the delete journal. | |
398 // - Types which have encountered a cryptographer error (crypto_types) are | |
399 // unapplied (local state is purged but sync state is not). | |
400 // - All other types not in the routing info (types just disabled) are deleted | |
401 // from the directory. | |
402 // - Everything else (enabled types and already disabled types) is not | |
403 // touched. | |
404 RequestConfigureSyncer(reason, | |
405 types_to_download, | |
406 types_to_purge, | |
407 fatal_types, | |
408 unapply_types, | |
409 inactive_types, | |
410 routing_info, | |
411 ready_task, | |
412 retry_callback); | |
413 | |
414 DCHECK(syncer::Intersection(active_types, types_to_purge).Empty()); | |
415 DCHECK(syncer::Intersection(active_types, fatal_types).Empty()); | |
416 DCHECK(syncer::Intersection(active_types, unapply_types).Empty()); | |
417 DCHECK(syncer::Intersection(active_types, inactive_types).Empty()); | |
418 return syncer::Difference(active_types, types_to_download); | |
419 } | |
420 | |
421 void SyncBackendHostImpl::EnableEncryptEverything() { | |
422 registrar_->sync_thread()->task_runner()->PostTask( | |
423 FROM_HERE, | |
424 base::Bind(&SyncBackendHostCore::DoEnableEncryptEverything, core_.get())); | |
425 } | |
426 | |
427 void SyncBackendHostImpl::ActivateDirectoryDataType( | |
428 syncer::ModelType type, | |
429 syncer::ModelSafeGroup group, | |
430 sync_driver::ChangeProcessor* change_processor) { | |
431 registrar_->ActivateDataType(type, group, change_processor, GetUserShare()); | |
432 } | |
433 | |
434 void SyncBackendHostImpl::DeactivateDirectoryDataType(syncer::ModelType type) { | |
435 registrar_->DeactivateDataType(type); | |
436 } | |
437 | |
438 void SyncBackendHostImpl::ActivateNonBlockingDataType( | |
439 syncer::ModelType type, | |
440 scoped_ptr<syncer_v2::ActivationContext> activation_context) { | |
441 sync_context_proxy_->ConnectTypeToSync(type, activation_context.Pass()); | |
442 } | |
443 | |
444 void SyncBackendHostImpl::DeactivateNonBlockingDataType( | |
445 syncer::ModelType type) { | |
446 sync_context_proxy_->Disconnect(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()->message_loop()->PostTask(FROM_HERE, | |
499 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_loop_->task_runner(), callback)); | |
540 } | |
541 | |
542 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) { | |
543 registrar_->sync_thread()->task_runner()->PostTask( | |
544 FROM_HERE, base::Bind(&SyncBackendHostCore::DoInitialize, core_.get(), | |
545 base::Passed(&options))); | |
546 } | |
547 | |
548 void SyncBackendHostImpl::RequestConfigureSyncer( | |
549 syncer::ConfigureReason reason, | |
550 syncer::ModelTypeSet to_download, | |
551 syncer::ModelTypeSet to_purge, | |
552 syncer::ModelTypeSet to_journal, | |
553 syncer::ModelTypeSet to_unapply, | |
554 syncer::ModelTypeSet to_ignore, | |
555 const syncer::ModelSafeRoutingInfo& routing_info, | |
556 const base::Callback<void(syncer::ModelTypeSet, | |
557 syncer::ModelTypeSet)>& ready_task, | |
558 const base::Closure& retry_callback) { | |
559 DoConfigureSyncerTypes config_types; | |
560 config_types.to_download = to_download; | |
561 config_types.to_purge = to_purge; | |
562 config_types.to_journal = to_journal; | |
563 config_types.to_unapply = to_unapply; | |
564 registrar_->sync_thread()->task_runner()->PostTask( | |
565 FROM_HERE, | |
566 base::Bind(&SyncBackendHostCore::DoConfigureSyncer, core_.get(), reason, | |
567 config_types, routing_info, ready_task, retry_callback)); | |
568 } | |
569 | |
570 void SyncBackendHostImpl::FinishConfigureDataTypesOnFrontendLoop( | |
571 const syncer::ModelTypeSet enabled_types, | |
572 const syncer::ModelTypeSet succeeded_configuration_types, | |
573 const syncer::ModelTypeSet failed_configuration_types, | |
574 const base::Callback<void(syncer::ModelTypeSet, | |
575 syncer::ModelTypeSet)>& ready_task) { | |
576 if (!frontend_) | |
577 return; | |
578 | |
579 if (invalidator_) { | |
580 CHECK(invalidator_->UpdateRegisteredInvalidationIds( | |
581 this, ModelTypeSetToObjectIdSet(enabled_types))); | |
582 } | |
583 | |
584 if (!ready_task.is_null()) | |
585 ready_task.Run(succeeded_configuration_types, failed_configuration_types); | |
586 } | |
587 | |
588 void SyncBackendHostImpl::AddExperimentalTypes() { | |
589 CHECK(initialized()); | |
590 syncer::Experiments experiments; | |
591 if (core_->sync_manager()->ReceivedExperiment(&experiments)) | |
592 frontend_->OnExperimentsChanged(experiments); | |
593 } | |
594 | |
595 void SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop( | |
596 const syncer::WeakHandle<syncer::JsBackend> js_backend, | |
597 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener> | |
598 debug_info_listener, | |
599 syncer_v2::SyncContextProxy* sync_context_proxy, | |
600 const std::string& cache_guid) { | |
601 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
602 | |
603 if (sync_context_proxy) | |
604 sync_context_proxy_ = sync_context_proxy->Clone(); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
685 frontend_->OnActionableError(sync_error); | |
686 } | |
687 | |
688 void SyncBackendHostImpl::HandleMigrationRequestedOnFrontendLoop( | |
689 syncer::ModelTypeSet types) { | |
690 if (!frontend_) | |
691 return; | |
692 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
758 frontend_->OnEncryptedTypesChanged( | |
759 encrypted_types, encrypt_everything); | |
760 } | |
761 | |
762 void SyncBackendHostImpl::NotifyEncryptionComplete() { | |
763 if (!frontend_) | |
764 return; | |
765 | |
766 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
767 frontend_->OnEncryptionComplete(); | |
768 } | |
769 | |
770 void SyncBackendHostImpl::HandlePassphraseTypeChangedOnFrontendLoop( | |
771 syncer::PassphraseType type, | |
772 base::Time explicit_passphrase_time) { | |
773 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
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_EQ(base::MessageLoop::current(), frontend_loop_); | |
783 frontend_->OnLocalSetPassphraseEncryption(nigori_state); | |
784 } | |
785 | |
786 void SyncBackendHostImpl::HandleConnectionStatusChangeOnFrontendLoop( | |
787 syncer::ConnectionStatus status) { | |
788 if (!frontend_) | |
789 return; | |
790 | |
791 DCHECK_EQ(base::MessageLoop::current(), frontend_loop_); | |
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 scoped_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>& 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::ClearServerDataDoneOnFrontendLoop( | |
856 const syncer::SyncManager::ClearServerDataCallback& frontend_callback) { | |
857 DCHECK(ui_thread_->BelongsToCurrentThread()); | |
858 frontend_callback.Run(); | |
859 } | |
860 | |
861 } // namespace browser_sync | |
862 | |
863 #undef SDVLOG | |
864 | |
865 #undef SLOG | |
OLD | NEW |