OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sync/internal_api/sync_manager_impl.h" | 5 #include "sync/internal_api/sync_manager_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 } | 285 } |
286 | 286 |
287 void SyncManagerImpl::ThrowUnrecoverableError() { | 287 void SyncManagerImpl::ThrowUnrecoverableError() { |
288 DCHECK(thread_checker_.CalledOnValidThread()); | 288 DCHECK(thread_checker_.CalledOnValidThread()); |
289 ReadTransaction trans(FROM_HERE, GetUserShare()); | 289 ReadTransaction trans(FROM_HERE, GetUserShare()); |
290 trans.GetWrappedTrans()->OnUnrecoverableError( | 290 trans.GetWrappedTrans()->OnUnrecoverableError( |
291 FROM_HERE, "Simulating unrecoverable error for testing purposes."); | 291 FROM_HERE, "Simulating unrecoverable error for testing purposes."); |
292 } | 292 } |
293 | 293 |
294 ModelTypeSet SyncManagerImpl::InitialSyncEndedTypes() { | 294 ModelTypeSet SyncManagerImpl::InitialSyncEndedTypes() { |
295 DCHECK(initialized_); | |
tim (not reviewing)
2012/07/26 22:33:48
It still seems wrong from a client of SyncManager
rlarocque
2012/07/26 22:52:20
My first instinct was to downgrade this to a DCHEC
tim (not reviewing)
2012/07/27 01:54:32
True re: asserting on a pointer we're about to der
rlarocque
2012/07/27 17:47:19
Resolved offline.
| |
296 return directory()->initial_sync_ended_types(); | 295 return directory()->initial_sync_ended_types(); |
297 } | 296 } |
298 | 297 |
299 ModelTypeSet SyncManagerImpl::GetTypesWithEmptyProgressMarkerToken( | 298 ModelTypeSet SyncManagerImpl::GetTypesWithEmptyProgressMarkerToken( |
300 ModelTypeSet types) { | 299 ModelTypeSet types) { |
301 DCHECK(initialized_); | |
302 ModelTypeSet result; | 300 ModelTypeSet result; |
303 for (ModelTypeSet::Iterator i = types.First(); i.Good(); i.Inc()) { | 301 for (ModelTypeSet::Iterator i = types.First(); i.Good(); i.Inc()) { |
304 sync_pb::DataTypeProgressMarker marker; | 302 sync_pb::DataTypeProgressMarker marker; |
305 directory()->GetDownloadProgress(i.Get(), &marker); | 303 directory()->GetDownloadProgress(i.Get(), &marker); |
306 | 304 |
307 if (marker.token().empty()) | 305 if (marker.token().empty()) |
308 result.Put(i.Get()); | 306 result.Put(i.Get()); |
309 | 307 |
310 } | 308 } |
311 return result; | 309 return result; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 } | 360 } |
363 | 361 |
364 bool SyncManagerImpl::Init( | 362 bool SyncManagerImpl::Init( |
365 const FilePath& database_location, | 363 const FilePath& database_location, |
366 const WeakHandle<JsEventHandler>& event_handler, | 364 const WeakHandle<JsEventHandler>& event_handler, |
367 const std::string& sync_server_and_path, | 365 const std::string& sync_server_and_path, |
368 int port, | 366 int port, |
369 bool use_ssl, | 367 bool use_ssl, |
370 const scoped_refptr<base::TaskRunner>& blocking_task_runner, | 368 const scoped_refptr<base::TaskRunner>& blocking_task_runner, |
371 scoped_ptr<HttpPostProviderFactory> post_factory, | 369 scoped_ptr<HttpPostProviderFactory> post_factory, |
372 const ModelSafeRoutingInfo& model_safe_routing_info, | |
373 const std::vector<ModelSafeWorker*>& workers, | 370 const std::vector<ModelSafeWorker*>& workers, |
374 ExtensionsActivityMonitor* extensions_activity_monitor, | 371 ExtensionsActivityMonitor* extensions_activity_monitor, |
375 SyncManager::ChangeDelegate* change_delegate, | 372 SyncManager::ChangeDelegate* change_delegate, |
376 const SyncCredentials& credentials, | 373 const SyncCredentials& credentials, |
377 scoped_ptr<SyncNotifier> sync_notifier, | 374 scoped_ptr<SyncNotifier> sync_notifier, |
378 const std::string& restored_key_for_bootstrapping, | 375 const std::string& restored_key_for_bootstrapping, |
379 scoped_ptr<InternalComponentsFactory> internal_components_factory, | 376 scoped_ptr<InternalComponentsFactory> internal_components_factory, |
380 Encryptor* encryptor, | 377 Encryptor* encryptor, |
381 UnrecoverableErrorHandler* unrecoverable_error_handler, | 378 UnrecoverableErrorHandler* unrecoverable_error_handler, |
382 ReportUnrecoverableErrorFunction report_unrecoverable_error_function) { | 379 ReportUnrecoverableErrorFunction report_unrecoverable_error_function) { |
383 CHECK(!initialized_); | 380 CHECK(!initialized_); |
384 DCHECK(thread_checker_.CalledOnValidThread()); | 381 DCHECK(thread_checker_.CalledOnValidThread()); |
385 DCHECK(post_factory.get()); | 382 DCHECK(post_factory.get()); |
383 DCHECK(!credentials.email.empty()); | |
384 DCHECK(!credentials.sync_token.empty()); | |
386 DVLOG(1) << "SyncManager starting Init..."; | 385 DVLOG(1) << "SyncManager starting Init..."; |
387 | 386 |
388 weak_handle_this_ = MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()); | 387 weak_handle_this_ = MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()); |
389 | 388 |
390 blocking_task_runner_ = blocking_task_runner; | 389 blocking_task_runner_ = blocking_task_runner; |
391 | 390 |
392 change_delegate_ = change_delegate; | 391 change_delegate_ = change_delegate; |
393 | 392 |
394 sync_notifier_ = sync_notifier.Pass(); | 393 sync_notifier_ = sync_notifier.Pass(); |
395 | 394 |
396 AddObserver(&js_sync_manager_observer_); | 395 AddObserver(&js_sync_manager_observer_); |
397 SetJsEventHandler(event_handler); | 396 SetJsEventHandler(event_handler); |
398 | 397 |
399 AddObserver(&debug_info_event_listener_); | 398 AddObserver(&debug_info_event_listener_); |
400 | 399 |
401 database_path_ = database_location.Append( | 400 database_path_ = database_location.Append( |
402 syncable::Directory::kSyncDatabaseFilename); | 401 syncable::Directory::kSyncDatabaseFilename); |
403 encryptor_ = encryptor; | 402 encryptor_ = encryptor; |
404 unrecoverable_error_handler_ = unrecoverable_error_handler; | 403 unrecoverable_error_handler_ = unrecoverable_error_handler; |
405 report_unrecoverable_error_function_ = report_unrecoverable_error_function; | 404 report_unrecoverable_error_function_ = report_unrecoverable_error_function; |
406 | 405 |
407 FilePath absolute_db_path(database_path_); | 406 FilePath absolute_db_path(database_path_); |
408 file_util::AbsolutePath(&absolute_db_path); | 407 file_util::AbsolutePath(&absolute_db_path); |
409 scoped_ptr<syncable::DirectoryBackingStore> backing_store = | 408 scoped_ptr<syncable::DirectoryBackingStore> backing_store = |
410 internal_components_factory->BuildDirectoryBackingStore( | 409 internal_components_factory->BuildDirectoryBackingStore( |
411 credentials.email, absolute_db_path).Pass(); | 410 credentials.email, absolute_db_path).Pass(); |
412 | 411 |
413 DCHECK(backing_store.get()); | 412 DCHECK(backing_store.get()); |
413 share_.name = credentials.email; | |
414 share_.directory.reset( | 414 share_.directory.reset( |
415 new syncable::Directory(encryptor_, | 415 new syncable::Directory(encryptor_, |
416 unrecoverable_error_handler_, | 416 unrecoverable_error_handler_, |
417 report_unrecoverable_error_function_, | 417 report_unrecoverable_error_function_, |
418 backing_store.release())); | 418 backing_store.release())); |
419 | 419 |
420 connection_manager_.reset(new SyncAPIServerConnectionManager( | 420 connection_manager_.reset(new SyncAPIServerConnectionManager( |
421 sync_server_and_path, port, use_ssl, post_factory.release())); | 421 sync_server_and_path, port, use_ssl, post_factory.release())); |
422 | 422 |
423 net::NetworkChangeNotifier::AddIPAddressObserver(this); | 423 net::NetworkChangeNotifier::AddIPAddressObserver(this); |
424 observing_ip_address_changes_ = true; | 424 observing_ip_address_changes_ = true; |
425 | 425 |
426 connection_manager_->AddListener(this); | 426 connection_manager_->AddListener(this); |
427 | 427 |
428 DVLOG(1) << "Username: " << username_for_share(); | |
429 if (!OpenDirectory()) { | |
430 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | |
431 OnInitializationComplete( | |
432 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), | |
433 false, syncer::ModelTypeSet())); | |
434 return false; | |
435 } | |
tim (not reviewing)
2012/07/26 22:33:48
Yay, this looks way nicer.
| |
436 | |
437 // Retrieve and set the sync notifier state. | |
438 std::string unique_id = directory()->cache_guid(); | |
439 DVLOG(1) << "Read notification unique ID: " << unique_id; | |
440 allstatus_.SetUniqueId(unique_id); | |
441 sync_notifier_->SetUniqueId(unique_id); | |
442 | |
443 std::string state = directory()->GetNotificationState(); | |
444 if (VLOG_IS_ON(1)) { | |
445 std::string encoded_state; | |
446 base::Base64Encode(state, &encoded_state); | |
447 DVLOG(1) << "Read notification state: " << encoded_state; | |
448 } | |
449 | |
450 // TODO(tim): Remove once invalidation state has been migrated to new | |
451 // InvalidationStateTracker store. Bug 124140. | |
452 sync_notifier_->SetStateDeprecated(state); | |
453 | |
454 connection_manager_->set_auth_token(credentials.sync_token); | |
455 sync_notifier_->UpdateCredentials(credentials.email, | |
tim (not reviewing)
2012/07/26 22:33:48
If we can get rid of the initialized_ special logi
rlarocque
2012/07/26 22:52:20
The scheduler doesn't exist at this point, so the
tim (not reviewing)
2012/07/27 01:54:32
Oh, right, you mentioned that above too. Can we t
rlarocque
2012/07/27 17:47:19
Done.
I also moved the IPAddressChangeObserver re
| |
456 credentials.sync_token); | |
457 | |
428 // Build a SyncSessionContext and store the worker in it. | 458 // Build a SyncSessionContext and store the worker in it. |
429 DVLOG(1) << "Sync is bringing up SyncSessionContext."; | 459 DVLOG(1) << "Sync is bringing up SyncSessionContext."; |
430 std::vector<SyncEngineEventListener*> listeners; | 460 std::vector<SyncEngineEventListener*> listeners; |
431 listeners.push_back(&allstatus_); | 461 listeners.push_back(&allstatus_); |
432 listeners.push_back(this); | 462 listeners.push_back(this); |
433 session_context_ = internal_components_factory->BuildContext( | 463 session_context_ = internal_components_factory->BuildContext( |
434 connection_manager_.get(), | 464 connection_manager_.get(), |
435 directory(), | 465 directory(), |
436 model_safe_routing_info, | |
437 workers, | 466 workers, |
438 extensions_activity_monitor, | 467 extensions_activity_monitor, |
439 &throttled_data_type_tracker_, | 468 &throttled_data_type_tracker_, |
440 listeners, | 469 listeners, |
441 &debug_info_event_listener_, | 470 &debug_info_event_listener_, |
442 &traffic_recorder_).Pass(); | 471 &traffic_recorder_).Pass(); |
443 session_context_->set_account_name(credentials.email); | 472 session_context_->set_account_name(credentials.email); |
444 scheduler_ = internal_components_factory->BuildScheduler( | 473 scheduler_ = internal_components_factory->BuildScheduler( |
445 name_, session_context_.get()).Pass(); | 474 name_, session_context_.get()).Pass(); |
446 | 475 |
447 bool success = SignIn(credentials); | 476 scheduler_->Start(SyncScheduler::CONFIGURATION_MODE); |
448 | 477 |
449 if (success) { | 478 initialized_ = true; |
450 scheduler_->Start(SyncScheduler::CONFIGURATION_MODE); | |
451 | 479 |
452 initialized_ = true; | 480 // Cryptographer should only be accessed while holding a |
481 // transaction. Grabbing the user share for the transaction | |
482 // checks the initialization state, so this must come after | |
483 // |initialized_| is set to true. | |
484 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
485 trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); | |
486 trans.GetCryptographer()->AddObserver(this); | |
453 | 487 |
454 // Unapplied datatypes (those that do not have initial sync ended set) get | |
455 // re-downloaded during any configuration. But, it's possible for a datatype | |
456 // to have a progress marker but not have initial sync ended yet, making | |
457 // it a candidate for migration. This is a problem, as the DataTypeManager | |
458 // does not support a migration while it's already in the middle of a | |
459 // configuration. As a result, any partially synced datatype can stall the | |
460 // DTM, waiting for the configuration to complete, which it never will due | |
461 // to the migration error. In addition, a partially synced nigori will | |
462 // trigger the migration logic before the backend is initialized, resulting | |
463 // in crashes. We therefore detect and purge any partially synced types as | |
464 // part of initialization. | |
465 if (!PurgePartiallySyncedTypes()) | |
466 success = false; | |
467 | |
468 // Cryptographer should only be accessed while holding a | |
469 // transaction. Grabbing the user share for the transaction | |
470 // checks the initialization state, so this must come after | |
471 // |initialized_| is set to true. | |
472 ReadTransaction trans(FROM_HERE, GetUserShare()); | |
473 trans.GetCryptographer()->Bootstrap(restored_key_for_bootstrapping); | |
474 trans.GetCryptographer()->AddObserver(this); | |
475 } | |
476 | |
477 // Notify that initialization is complete. Note: This should be the last to | |
478 // execute if |signed_in| is false. Reason being in that case we would | |
479 // post a task to shutdown sync. But if this function posts any other tasks | |
480 // on the UI thread and if shutdown wins then that tasks would execute on | |
481 // a freed pointer. This is because UI thread is not shut down. | |
482 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, | 488 FOR_EACH_OBSERVER(SyncManager::Observer, observers_, |
483 OnInitializationComplete( | 489 OnInitializationComplete( |
484 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), | 490 MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()), |
485 success)); | 491 true, InitialSyncEndedTypes())); |
486 if (!success) | |
487 return false; | |
488 | 492 |
489 sync_notifier_->AddObserver(this); | 493 sync_notifier_->AddObserver(this); |
490 | 494 return true; |
491 return success; | |
492 } | 495 } |
493 | 496 |
494 void SyncManagerImpl::RefreshNigori(const std::string& chrome_version, | 497 void SyncManagerImpl::RefreshNigori(const std::string& chrome_version, |
495 const base::Closure& done_callback) { | 498 const base::Closure& done_callback) { |
496 DCHECK(initialized_); | 499 DCHECK(initialized_); |
497 DCHECK(thread_checker_.CalledOnValidThread()); | 500 DCHECK(thread_checker_.CalledOnValidThread()); |
498 GetSessionName( | 501 GetSessionName( |
499 blocking_task_runner_, | 502 blocking_task_runner_, |
500 base::Bind( | 503 base::Bind( |
501 &SyncManagerImpl::UpdateCryptographerAndNigoriCallback, | 504 &SyncManagerImpl::UpdateCryptographerAndNigoriCallback, |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr())); | 660 MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr())); |
658 | 661 |
659 syncable::DirOpenResult open_result = syncable::NOT_INITIALIZED; | 662 syncable::DirOpenResult open_result = syncable::NOT_INITIALIZED; |
660 open_result = directory()->Open(username_for_share(), this, | 663 open_result = directory()->Open(username_for_share(), this, |
661 transaction_observer); | 664 transaction_observer); |
662 if (open_result != syncable::OPENED) { | 665 if (open_result != syncable::OPENED) { |
663 LOG(ERROR) << "Could not open share for:" << username_for_share(); | 666 LOG(ERROR) << "Could not open share for:" << username_for_share(); |
664 return false; | 667 return false; |
665 } | 668 } |
666 | 669 |
670 // Unapplied datatypes (those that do not have initial sync ended set) get | |
671 // re-downloaded during any configuration. But, it's possible for a datatype | |
672 // to have a progress marker but not have initial sync ended yet, making | |
673 // it a candidate for migration. This is a problem, as the DataTypeManager | |
674 // does not support a migration while it's already in the middle of a | |
675 // configuration. As a result, any partially synced datatype can stall the | |
676 // DTM, waiting for the configuration to complete, which it never will due | |
677 // to the migration error. In addition, a partially synced nigori will | |
678 // trigger the migration logic before the backend is initialized, resulting | |
679 // in crashes. We therefore detect and purge any partially synced types as | |
680 // part of initialization. | |
681 if (!PurgePartiallySyncedTypes()) | |
682 return false; | |
683 | |
667 connection_manager_->set_client_id(directory()->cache_guid()); | 684 connection_manager_->set_client_id(directory()->cache_guid()); |
668 return true; | 685 return true; |
669 } | 686 } |
670 | 687 |
671 bool SyncManagerImpl::SignIn(const SyncCredentials& credentials) { | |
672 DCHECK(thread_checker_.CalledOnValidThread()); | |
673 DCHECK(share_.name.empty()); | |
674 share_.name = credentials.email; | |
675 | |
676 DVLOG(1) << "Signing in user: " << username_for_share(); | |
677 if (!OpenDirectory()) | |
678 return false; | |
679 | |
680 // Retrieve and set the sync notifier state. This should be done | |
681 // only after OpenDirectory is called. | |
682 std::string unique_id = directory()->cache_guid(); | |
683 std::string state = directory()->GetNotificationState(); | |
684 DVLOG(1) << "Read notification unique ID: " << unique_id; | |
685 if (VLOG_IS_ON(1)) { | |
686 std::string encoded_state; | |
687 base::Base64Encode(state, &encoded_state); | |
688 DVLOG(1) << "Read notification state: " << encoded_state; | |
689 } | |
690 allstatus_.SetUniqueId(unique_id); | |
691 sync_notifier_->SetUniqueId(unique_id); | |
692 // TODO(tim): Remove once invalidation state has been migrated to new | |
693 // InvalidationStateTracker store. Bug 124140. | |
694 sync_notifier_->SetStateDeprecated(state); | |
695 | |
696 UpdateCredentials(credentials); | |
697 return true; | |
698 } | |
699 | |
700 bool SyncManagerImpl::PurgePartiallySyncedTypes() { | 688 bool SyncManagerImpl::PurgePartiallySyncedTypes() { |
701 ModelTypeSet partially_synced_types = ModelTypeSet::All(); | 689 ModelTypeSet partially_synced_types = ModelTypeSet::All(); |
702 partially_synced_types.RemoveAll(InitialSyncEndedTypes()); | 690 partially_synced_types.RemoveAll(InitialSyncEndedTypes()); |
703 partially_synced_types.RemoveAll(GetTypesWithEmptyProgressMarkerToken( | 691 partially_synced_types.RemoveAll(GetTypesWithEmptyProgressMarkerToken( |
704 ModelTypeSet::All())); | 692 ModelTypeSet::All())); |
705 | 693 |
706 UMA_HISTOGRAM_COUNTS("Sync.PartiallySyncedTypes", | 694 UMA_HISTOGRAM_COUNTS("Sync.PartiallySyncedTypes", |
707 partially_synced_types.Size()); | 695 partially_synced_types.Size()); |
708 if (partially_synced_types.Empty()) | 696 if (partially_synced_types.Empty()) |
709 return true; | 697 return true; |
710 return directory()->PurgeEntriesWithTypeIn(partially_synced_types); | 698 return directory()->PurgeEntriesWithTypeIn(partially_synced_types); |
711 } | 699 } |
712 | 700 |
713 void SyncManagerImpl::UpdateCredentials( | 701 void SyncManagerImpl::UpdateCredentials( |
714 const SyncCredentials& credentials) { | 702 const SyncCredentials& credentials) { |
715 DCHECK(thread_checker_.CalledOnValidThread()); | 703 DCHECK(thread_checker_.CalledOnValidThread()); |
716 DCHECK_EQ(credentials.email, share_.name); | 704 DCHECK_EQ(credentials.email, share_.name); |
717 DCHECK(!credentials.email.empty()); | 705 DCHECK(!credentials.email.empty()); |
718 DCHECK(!credentials.sync_token.empty()); | 706 DCHECK(!credentials.sync_token.empty()); |
719 | 707 |
720 observing_ip_address_changes_ = true; | 708 observing_ip_address_changes_ = true; |
721 if (connection_manager_->set_auth_token(credentials.sync_token)) { | 709 if (connection_manager_->set_auth_token(credentials.sync_token)) { |
722 sync_notifier_->UpdateCredentials( | 710 sync_notifier_->UpdateCredentials( |
723 credentials.email, credentials.sync_token); | 711 credentials.email, credentials.sync_token); |
724 if (initialized_) { | 712 if (initialized_) { |
tim (not reviewing)
2012/07/26 22:33:48
Do we actually need this if (initialized_) block a
rlarocque
2012/07/26 22:52:20
See comment above.
| |
725 scheduler_->OnCredentialsUpdated(); | 713 scheduler_->OnCredentialsUpdated(); |
726 } | 714 } |
727 } | 715 } |
728 } | 716 } |
729 | 717 |
730 void SyncManagerImpl::UpdateEnabledTypes( | 718 void SyncManagerImpl::UpdateEnabledTypes( |
731 const ModelTypeSet& enabled_types) { | 719 const ModelTypeSet& enabled_types) { |
732 DCHECK(thread_checker_.CalledOnValidThread()); | 720 DCHECK(thread_checker_.CalledOnValidThread()); |
733 sync_notifier_->UpdateEnabledTypes(enabled_types); | 721 sync_notifier_->UpdateEnabledTypes(enabled_types); |
734 } | 722 } |
(...skipping 1156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1891 int SyncManagerImpl::GetDefaultNudgeDelay() { | 1879 int SyncManagerImpl::GetDefaultNudgeDelay() { |
1892 return kDefaultNudgeDelayMilliseconds; | 1880 return kDefaultNudgeDelayMilliseconds; |
1893 } | 1881 } |
1894 | 1882 |
1895 // static. | 1883 // static. |
1896 int SyncManagerImpl::GetPreferencesNudgeDelay() { | 1884 int SyncManagerImpl::GetPreferencesNudgeDelay() { |
1897 return kPreferencesNudgeDelayMilliseconds; | 1885 return kPreferencesNudgeDelayMilliseconds; |
1898 } | 1886 } |
1899 | 1887 |
1900 } // namespace syncer | 1888 } // namespace syncer |
OLD | NEW |