// Copyright (c) 2011 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/sync/abstract_profile_sync_service_test.h" #include "chrome/browser/sync/engine/syncapi.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_factory.h" #include "chrome/browser/sync/sessions/session_state.h" #include "chrome/browser/sync/syncable/directory_manager.h" #include "chrome/browser/sync/syncable/syncable.h" #include "chrome/test/sync/test_http_bridge_factory.h" using browser_sync::ModelSafeRoutingInfo; using browser_sync::sessions::ErrorCounters; using browser_sync::sessions::SyncSourceInfo; using browser_sync::sessions::SyncerStatus; using browser_sync::sessions::SyncSessionSnapshot; using syncable::DirectoryManager; using syncable::ModelType; using syncable::ScopedDirLookup; using sync_api::UserShare; namespace browser_sync { using ::testing::_; SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest( Profile* profile, bool set_initial_sync_ended_on_init, bool synchronous_init) : browser_sync::SyncBackendHost(profile), synchronous_init_(synchronous_init) { ON_CALL(*this, RequestNudge(_)).WillByDefault( testing::Invoke(this, &SyncBackendHostForProfileSyncTest:: SimulateSyncCycleCompletedInitialSyncEnded)); EXPECT_CALL(*this, RequestNudge(_)).Times(testing::AnyNumber()); } SyncBackendHostForProfileSyncTest::~SyncBackendHostForProfileSyncTest() {} void SyncBackendHostForProfileSyncTest::ConfigureDataTypes( const DataTypeController::TypeMap& data_type_controllers, const syncable::ModelTypeSet& types, CancelableTask* ready_task) { SetAutofillMigrationState(syncable::MIGRATED); SyncBackendHost::ConfigureDataTypes( data_type_controllers, types, ready_task); } void SyncBackendHostForProfileSyncTest:: SimulateSyncCycleCompletedInitialSyncEnded( const tracked_objects::Location& location) { syncable::ModelTypeBitSet sync_ended; ModelSafeRoutingInfo enabled_types; GetModelSafeRoutingInfo(&enabled_types); std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); i != enabled_types.end(); ++i) { sync_ended.set(i->first); } core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot( SyncerStatus(), ErrorCounters(), 0, false, sync_ended, download_progress_markers, false, false, 0, 0, false, SyncSourceInfo())); } sync_api::HttpPostProviderFactory* SyncBackendHostForProfileSyncTest::MakeHttpBridgeFactory( net::URLRequestContextGetter* getter) { return new browser_sync::TestHttpBridgeFactory; } void SyncBackendHostForProfileSyncTest::InitCore( const Core::DoInitializeOptions& options) { std::wstring user = L"testuser@gmail.com"; core_loop()->PostTask( FROM_HERE, NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoInitializeForTest, user, options.http_bridge_factory, options.delete_sync_data_folder)); // TODO(akalin): Figure out a better way to do this. if (synchronous_init_) { // The SyncBackend posts a task to the current loop when // initialization completes. MessageLoop::current()->Run(); } } JsBackend* SyncBackendHostForProfileSyncTest::GetJsBackend() { // Return a non-NULL result only when the overridden function does. if (SyncBackendHost::GetJsBackend()) { return this; } else { NOTREACHED(); return NULL; } } void SyncBackendHostForProfileSyncTest::SetParentJsEventRouter( JsEventRouter* router) { core_->SetParentJsEventRouter(router); } void SyncBackendHostForProfileSyncTest::RemoveParentJsEventRouter() { core_->RemoveParentJsEventRouter(); } const JsEventRouter* SyncBackendHostForProfileSyncTest::GetParentJsEventRouter() const { return core_->GetParentJsEventRouter(); } void SyncBackendHostForProfileSyncTest::ProcessMessage( const std::string& name, const JsArgList& args, const JsEventHandler* sender) { if (name.find("delay") != name.npos) { core_->RouteJsEvent(name, args, sender); } else { core_->RouteJsEventOnFrontendLoop(name, args, sender); } } void SyncBackendHostForProfileSyncTest::StartConfiguration(Callback0::Type*) { SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop(); } void SyncBackendHostForProfileSyncTest:: SetDefaultExpectationsForWorkerCreation(ProfileMock* profile) { EXPECT_CALL(*profile, GetPasswordStore(testing::_)). WillOnce(testing::Return((PasswordStore*)NULL)); } void SyncBackendHostForProfileSyncTest::SetHistoryServiceExpectations( ProfileMock* profile) { EXPECT_CALL(*profile, GetHistoryService(testing::_)). WillOnce(testing::Return((HistoryService*)NULL)); } } // namespace browser_sync browser_sync::TestIdFactory* TestProfileSyncService::id_factory() { return &id_factory_; } browser_sync::SyncBackendHostForProfileSyncTest* TestProfileSyncService::GetBackendForTest() { return static_cast<browser_sync::SyncBackendHostForProfileSyncTest*>( ProfileSyncService::GetBackendForTest()); } TestProfileSyncService::TestProfileSyncService( ProfileSyncFactory* factory, Profile* profile, const std::string& test_user, bool synchronous_backend_initialization, Task* initial_condition_setup_task) : ProfileSyncService(factory, profile, test_user), synchronous_backend_initialization_( synchronous_backend_initialization), synchronous_sync_configuration_(false), initial_condition_setup_task_(initial_condition_setup_task), set_initial_sync_ended_on_init_(true) { RegisterPreferences(); SetSyncSetupCompleted(); } TestProfileSyncService::~TestProfileSyncService() {} void TestProfileSyncService::SetInitialSyncEndedForEnabledTypes() { UserShare* user_share = GetUserShare(); DirectoryManager* dir_manager = user_share->dir_manager.get(); ScopedDirLookup dir(dir_manager, user_share->name); if (!dir.good()) FAIL(); ModelSafeRoutingInfo enabled_types; backend_->GetModelSafeRoutingInfo(&enabled_types); for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); i != enabled_types.end(); ++i) { dir->set_initial_sync_ended_for_type(i->first, true); } } void TestProfileSyncService::OnBackendInitialized() { // Set this so below code can access GetUserShare(). backend_initialized_ = true; // Set up any nodes the test wants around before model association. if (initial_condition_setup_task_) { initial_condition_setup_task_->Run(); initial_condition_setup_task_ = NULL; } // Pretend we downloaded initial updates and set initial sync ended bits // if we were asked to. bool send_passphrase_required = false; if (set_initial_sync_ended_on_init_) { UserShare* user_share = GetUserShare(); DirectoryManager* dir_manager = user_share->dir_manager.get(); ScopedDirLookup dir(dir_manager, user_share->name); if (!dir.good()) FAIL(); if (!dir->initial_sync_ended_for_type(syncable::NIGORI)) { ProfileSyncServiceTestHelper::CreateRoot( syncable::NIGORI, GetUserShare(), id_factory()); // A side effect of adding the NIGORI mode (normally done by the syncer) // is a decryption attempt, which will fail the first time. send_passphrase_required = true; } SetInitialSyncEndedForEnabledTypes(); } ProfileSyncService::OnBackendInitialized(); if (send_passphrase_required) OnPassphraseRequired(true); // TODO(akalin): Figure out a better way to do this. if (synchronous_backend_initialization_) { MessageLoop::current()->Quit(); } } void TestProfileSyncService::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { ProfileSyncService::Observe(type, source, details); if (type == NotificationType::SYNC_CONFIGURE_DONE && !synchronous_sync_configuration_) { MessageLoop::current()->Quit(); } } 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::CreateBackend() { backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( profile(), set_initial_sync_ended_on_init_, synchronous_backend_initialization_)); } std::string TestProfileSyncService::GetLsidForAuthBootstraping() { return "foo"; }