| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/sync/test_profile_sync_service.h" |
| |
| #include "chrome/browser/signin/signin_manager.h" |
| #include "chrome/browser/signin/signin_manager_factory.h" |
| #include "chrome/browser/sync/glue/data_type_controller.h" |
| #include "chrome/browser/sync/glue/sync_backend_host.h" |
| #include "chrome/browser/sync/profile_sync_components_factory.h" |
| #include "chrome/browser/sync/test/test_http_bridge_factory.h" |
| #include "chrome/common/chrome_notification_types.h" |
| #include "sync/internal_api/public/sessions/sync_session_snapshot.h" |
| #include "sync/internal_api/public/test/test_user_share.h" |
| #include "sync/internal_api/public/user_share.h" |
| #include "sync/js/js_reply_handler.h" |
| #include "sync/protocol/encryption.pb.h" |
| #include "sync/syncable/directory.h" |
| |
| using syncer::InternalComponentsFactory; |
| using syncer::ModelSafeRoutingInfo; |
| using syncer::TestInternalComponentsFactory; |
| using syncer::sessions::ModelNeutralState; |
| using syncer::sessions::SyncSessionSnapshot; |
| using syncer::sessions::SyncSourceInfo; |
| using syncer::UserShare; |
| using syncer::syncable::Directory; |
| using syncer::DEVICE_INFO; |
| using syncer::EXPERIMENTS; |
| using syncer::NIGORI; |
| using syncer::PRIORITY_PREFERENCES; |
| |
| namespace browser_sync { |
| |
| SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest( |
| Profile* profile, |
| const base::WeakPtr<SyncPrefs>& sync_prefs, |
| const base::WeakPtr<InvalidatorStorage>& invalidator_storage, |
| syncer::TestIdFactory& id_factory, |
| base::Closure& callback, |
| bool set_initial_sync_ended_on_init, |
| bool synchronous_init, |
| bool fail_initial_download, |
| syncer::StorageOption storage_option) |
| : browser_sync::SyncBackendHost( |
| profile->GetDebugName(), profile, sync_prefs, invalidator_storage), |
| weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| id_factory_(id_factory), |
| callback_(callback), |
| fail_initial_download_(fail_initial_download), |
| set_initial_sync_ended_on_init_(set_initial_sync_ended_on_init), |
| synchronous_init_(synchronous_init), |
| storage_option_(storage_option) {} |
| |
| SyncBackendHostForProfileSyncTest::~SyncBackendHostForProfileSyncTest() {} |
| |
| namespace { |
| |
| scoped_ptr<syncer::HttpPostProviderFactory> MakeTestHttpBridgeFactory() { |
| return scoped_ptr<syncer::HttpPostProviderFactory>( |
| new browser_sync::TestHttpBridgeFactory()); |
| } |
| |
| } // namespace |
| |
| void SyncBackendHostForProfileSyncTest::InitCore( |
| const DoInitializeOptions& options) { |
| DoInitializeOptions test_options = options; |
| test_options.make_http_bridge_factory_fn = |
| base::Bind(&MakeTestHttpBridgeFactory); |
| test_options.credentials.email = "[email protected]"; |
| test_options.credentials.sync_token = "token"; |
| test_options.restored_key_for_bootstrapping = ""; |
| syncer::StorageOption storage = storage_option_; |
| |
| // It'd be nice if we avoided creating the InternalComponentsFactory in the |
| // first place, but SyncBackendHost will have created one by now so we must |
| // free it. Grab the switches to pass on first. |
| InternalComponentsFactory::Switches factory_switches = |
| test_options.internal_components_factory->GetSwitches(); |
| delete test_options.internal_components_factory; |
| |
| test_options.internal_components_factory = |
| new TestInternalComponentsFactory(factory_switches, storage); |
| |
| SyncBackendHost::InitCore(test_options); |
| if (synchronous_init_) { |
| // The SyncBackend posts a task to the current loop when |
| // initialization completes. |
| MessageLoop::current()->Run(); |
| } |
| } |
| |
| void SyncBackendHostForProfileSyncTest::UpdateCredentials( |
| const syncer::SyncCredentials& credentials) { |
| // If we had failed the initial download, complete initialization now. |
| if (!initial_download_closure_.is_null()) { |
| initial_download_closure_.Run(); |
| initial_download_closure_.Reset(); |
| } |
| } |
| |
| void SyncBackendHostForProfileSyncTest::RequestConfigureSyncer( |
| syncer::ConfigureReason reason, |
| syncer::ModelTypeSet types_to_config, |
| syncer::ModelTypeSet failed_types, |
| const syncer::ModelSafeRoutingInfo& routing_info, |
| const base::Callback<void(syncer::ModelTypeSet)>& ready_task, |
| const base::Closure& retry_callback) { |
| syncer::ModelTypeSet failed_configuration_types; |
| if (fail_initial_download_) |
| failed_configuration_types = types_to_config; |
| |
| FinishConfigureDataTypesOnFrontendLoop(failed_configuration_types, |
| ready_task); |
| } |
| |
| void SyncBackendHostForProfileSyncTest |
| ::HandleSyncManagerInitializationOnFrontendLoop( |
| const syncer::WeakHandle<syncer::JsBackend>& js_backend, |
| const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& |
| debug_info_listener, |
| syncer::ModelTypeSet restored_types) { |
| // Here's our opportunity to pretend to do things that the SyncManager would |
| // normally do during initialization, but can't because this is a test. |
| // Set up any nodes the test wants around before model association. |
| if (!callback_.is_null()) { |
| callback_.Run(); |
| } |
| |
| // Pretend we downloaded initial updates and set initial sync ended bits |
| // if we were asked to. |
| if (set_initial_sync_ended_on_init_) { |
| UserShare* user_share = GetUserShare(); |
| Directory* directory = user_share->directory.get(); |
| |
| if (!directory->InitialSyncEndedForType(NIGORI)) { |
| syncer::TestUserShare::CreateRoot(NIGORI, user_share); |
| |
| // A side effect of adding the NIGORI node (normally done by the |
| // syncer) is a decryption attempt, which will fail the first time. |
| } |
| |
| if (!directory->InitialSyncEndedForType(DEVICE_INFO)) { |
| syncer::TestUserShare::CreateRoot(DEVICE_INFO, user_share); |
| } |
| |
| if (!directory->InitialSyncEndedForType(EXPERIMENTS)) { |
| syncer::TestUserShare::CreateRoot(EXPERIMENTS, user_share); |
| } |
| |
| if (!directory->InitialSyncEndedForType(PRIORITY_PREFERENCES)) { |
| syncer::TestUserShare::CreateRoot(PRIORITY_PREFERENCES, user_share); |
| } |
| |
| restored_types = syncer::ModelTypeSet::All(); |
| } |
| |
| initial_download_closure_ = base::Bind( |
| &SyncBackendHostForProfileSyncTest::ContinueInitialization, |
| weak_ptr_factory_.GetWeakPtr(), |
| js_backend, |
| debug_info_listener, |
| restored_types); |
| if (fail_initial_download_) { |
| frontend()->OnSyncConfigureRetry(); |
| if (synchronous_init_) |
| MessageLoop::current()->Quit(); |
| } else { |
| initial_download_closure_.Run(); |
| initial_download_closure_.Reset(); |
| } |
| } |
| |
| void SyncBackendHostForProfileSyncTest::EmitOnInvalidatorStateChange( |
| syncer::InvalidatorState state) { |
| frontend()->OnInvalidatorStateChange(state); |
| } |
| |
| void SyncBackendHostForProfileSyncTest::EmitOnIncomingInvalidation( |
| const syncer::ObjectIdInvalidationMap& invalidation_map) { |
| frontend()->OnIncomingInvalidation(invalidation_map); |
| } |
| |
| void SyncBackendHostForProfileSyncTest::ContinueInitialization( |
| const syncer::WeakHandle<syncer::JsBackend>& js_backend, |
| const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& |
| debug_info_listener, |
| syncer::ModelTypeSet restored_types) { |
| SyncBackendHost::HandleSyncManagerInitializationOnFrontendLoop( |
| js_backend, debug_info_listener, restored_types); |
| } |
| |
| } // namespace browser_sync |
| |
| syncer::TestIdFactory* TestProfileSyncService::id_factory() { |
| return &id_factory_; |
| } |
| |
| browser_sync::SyncBackendHostForProfileSyncTest* |
| TestProfileSyncService::GetBackendForTest() { |
| return static_cast<browser_sync::SyncBackendHostForProfileSyncTest*>( |
| ProfileSyncService::GetBackendForTest()); |
| } |
| |
| TestProfileSyncService::TestProfileSyncService( |
| ProfileSyncComponentsFactory* factory, |
| Profile* profile, |
| SigninManager* signin, |
| ProfileSyncService::StartBehavior behavior, |
| bool synchronous_backend_initialization) |
| : ProfileSyncService(factory, |
| profile, |
| signin, |
| behavior), |
| synchronous_backend_initialization_( |
| synchronous_backend_initialization), |
| synchronous_sync_configuration_(false), |
| set_initial_sync_ended_on_init_(true), |
| fail_initial_download_(false), |
| storage_option_(syncer::STORAGE_IN_MEMORY) { |
| SetSyncSetupCompleted(); |
| } |
| |
| TestProfileSyncService::~TestProfileSyncService() { |
| } |
| |
| // static |
| ProfileKeyedService* TestProfileSyncService::BuildAutoStartAsyncInit( |
| Profile* profile) { |
| SigninManager* signin = SigninManagerFactory::GetForProfile(profile); |
| ProfileSyncComponentsFactoryMock* factory = |
| new ProfileSyncComponentsFactoryMock(); |
| return new TestProfileSyncService( |
| factory, profile, signin, ProfileSyncService::AUTO_START, false); |
| } |
| |
| ProfileSyncComponentsFactoryMock* |
| TestProfileSyncService::components_factory_mock() { |
| // We always create a mock factory, see Build* routines. |
| return static_cast<ProfileSyncComponentsFactoryMock*>(factory()); |
| } |
| |
| void TestProfileSyncService::OnBackendInitialized( |
| const syncer::WeakHandle<syncer::JsBackend>& backend, |
| const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& |
| debug_info_listener, |
| bool success) { |
| ProfileSyncService::OnBackendInitialized(backend, |
| debug_info_listener, |
| success); |
| |
| // TODO(akalin): Figure out a better way to do this. |
| if (synchronous_backend_initialization_) { |
| MessageLoop::current()->Quit(); |
| } |
| } |
| |
| void TestProfileSyncService::OnConfigureDone( |
| const browser_sync::DataTypeManager::ConfigureResult& result) { |
| ProfileSyncService::OnConfigureDone(result); |
| if (!synchronous_sync_configuration_) |
| MessageLoop::current()->Quit(); |
| } |
| |
| UserShare* TestProfileSyncService::GetUserShare() const { |
| return backend_->GetUserShare(); |
| } |
| |
| void TestProfileSyncService::dont_set_initial_sync_ended_on_init() { |
| set_initial_sync_ended_on_init_ = false; |
| } |
| void TestProfileSyncService::set_synchronous_sync_configuration() { |
| synchronous_sync_configuration_ = true; |
| } |
| void TestProfileSyncService::fail_initial_download() { |
| fail_initial_download_ = true; |
| } |
| void TestProfileSyncService::set_storage_option( |
| syncer::StorageOption storage_option) { |
| storage_option_ = storage_option; |
| } |
| |
| void TestProfileSyncService::CreateBackend() { |
| backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( |
| profile(), |
| sync_prefs_.AsWeakPtr(), |
| invalidator_storage_.AsWeakPtr(), |
| id_factory_, |
| callback_, |
| set_initial_sync_ended_on_init_, |
| synchronous_backend_initialization_, |
| fail_initial_download_, |
| storage_option_)); |
| } |