1 // Copyright (c) 2011 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/test_profile_sync_service.h" 6 7 #include "chrome/browser/sync/abstract_profile_sync_service_test.h" 8 #include "chrome/browser/sync/engine/syncapi.h" 9 #include "chrome/browser/sync/glue/data_type_controller.h" 10 #include "chrome/browser/sync/glue/sync_backend_host.h" 11 #include "chrome/browser/sync/profile_sync_factory.h" 12 #include "chrome/browser/sync/sessions/session_state.h" 13 #include "chrome/browser/sync/syncable/directory_manager.h" 14 #include "chrome/browser/sync/syncable/syncable.h" 15 #include "chrome/test/sync/test_http_bridge_factory.h" 16 17 using browser_sync::ModelSafeRoutingInfo; 18 using browser_sync::sessions::ErrorCounters; 19 using browser_sync::sessions::SyncSourceInfo; 20 using browser_sync::sessions::SyncerStatus; 21 using browser_sync::sessions::SyncSessionSnapshot; 22 using syncable::DirectoryManager; 23 using syncable::ModelType; 24 using syncable::ScopedDirLookup; 25 using sync_api::UserShare; 26 27 namespace browser_sync { 28 29 using ::testing::_; 30 SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest( 31 Profile* profile, 32 bool set_initial_sync_ended_on_init, 33 bool synchronous_init) 34 : browser_sync::SyncBackendHost(profile), 35 synchronous_init_(synchronous_init) { 36 ON_CALL(*this, RequestNudge(_)).WillByDefault( 37 testing::Invoke(this, 38 &SyncBackendHostForProfileSyncTest:: 39 SimulateSyncCycleCompletedInitialSyncEnded)); 40 EXPECT_CALL(*this, RequestNudge(_)).Times(testing::AnyNumber()); 41 } 42 43 SyncBackendHostForProfileSyncTest::~SyncBackendHostForProfileSyncTest() {} 44 45 void SyncBackendHostForProfileSyncTest::ConfigureDataTypes( 46 const DataTypeController::TypeMap& data_type_controllers, 47 const syncable::ModelTypeSet& types, 48 CancelableTask* ready_task) { 49 SetAutofillMigrationState(syncable::MIGRATED); 50 SyncBackendHost::ConfigureDataTypes( 51 data_type_controllers, types, ready_task); 52 } 53 54 void SyncBackendHostForProfileSyncTest:: 55 SimulateSyncCycleCompletedInitialSyncEnded( 56 const tracked_objects::Location& location) { 57 syncable::ModelTypeBitSet sync_ended; 58 ModelSafeRoutingInfo enabled_types; 59 GetModelSafeRoutingInfo(&enabled_types); 60 std::string download_progress_markers[syncable::MODEL_TYPE_COUNT]; 61 for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); 62 i != enabled_types.end(); ++i) { 63 sync_ended.set(i->first); 64 } 65 core_->HandleSyncCycleCompletedOnFrontendLoop(new SyncSessionSnapshot( 66 SyncerStatus(), ErrorCounters(), 0, false, 67 sync_ended, download_progress_markers, false, false, 0, 0, false, 68 SyncSourceInfo())); 69 } 70 71 sync_api::HttpPostProviderFactory* 72 SyncBackendHostForProfileSyncTest::MakeHttpBridgeFactory( 73 net::URLRequestContextGetter* getter) { 74 return new browser_sync::TestHttpBridgeFactory; 75 } 76 77 void SyncBackendHostForProfileSyncTest::InitCore( 78 const Core::DoInitializeOptions& options) { 79 std::wstring user = L"testuser (at) gmail.com"; 80 core_loop()->PostTask( 81 FROM_HERE, 82 NewRunnableMethod(core_.get(), 83 &SyncBackendHost::Core::DoInitializeForTest, 84 user, 85 options.http_bridge_factory, 86 options.delete_sync_data_folder)); 87 88 // TODO(akalin): Figure out a better way to do this. 89 if (synchronous_init_) { 90 // The SyncBackend posts a task to the current loop when 91 // initialization completes. 92 MessageLoop::current()->Run(); 93 } 94 } 95 96 JsBackend* SyncBackendHostForProfileSyncTest::GetJsBackend() { 97 // Return a non-NULL result only when the overridden function does. 98 if (SyncBackendHost::GetJsBackend()) { 99 return this; 100 } else { 101 NOTREACHED(); 102 return NULL; 103 } 104 } 105 106 void SyncBackendHostForProfileSyncTest::SetParentJsEventRouter( 107 JsEventRouter* router) { 108 core_->SetParentJsEventRouter(router); 109 } 110 111 void SyncBackendHostForProfileSyncTest::RemoveParentJsEventRouter() { 112 core_->RemoveParentJsEventRouter(); 113 } 114 115 const JsEventRouter* 116 SyncBackendHostForProfileSyncTest::GetParentJsEventRouter() const { 117 return core_->GetParentJsEventRouter(); 118 } 119 120 void SyncBackendHostForProfileSyncTest::ProcessMessage( 121 const std::string& name, const JsArgList& args, 122 const JsEventHandler* sender) { 123 if (name.find("delay") != name.npos) { 124 core_->RouteJsEvent(name, args, sender); 125 } else { 126 core_->RouteJsEventOnFrontendLoop(name, args, sender); 127 } 128 } 129 130 void SyncBackendHostForProfileSyncTest::StartConfiguration(Callback0::Type*) { 131 SyncBackendHost::FinishConfigureDataTypesOnFrontendLoop(); 132 } 133 134 void SyncBackendHostForProfileSyncTest:: 135 SetDefaultExpectationsForWorkerCreation(ProfileMock* profile) { 136 EXPECT_CALL(*profile, GetPasswordStore(testing::_)). 137 WillOnce(testing::Return((PasswordStore*)NULL)); 138 } 139 140 void SyncBackendHostForProfileSyncTest::SetHistoryServiceExpectations( 141 ProfileMock* profile) { 142 EXPECT_CALL(*profile, GetHistoryService(testing::_)). 143 WillOnce(testing::Return((HistoryService*)NULL)); 144 } 145 146 } // namespace browser_sync 147 148 browser_sync::TestIdFactory* TestProfileSyncService::id_factory() { 149 return &id_factory_; 150 } 151 152 browser_sync::SyncBackendHostForProfileSyncTest* 153 TestProfileSyncService::GetBackendForTest() { 154 return static_cast<browser_sync::SyncBackendHostForProfileSyncTest*>( 155 ProfileSyncService::GetBackendForTest()); 156 } 157 158 TestProfileSyncService::TestProfileSyncService( 159 ProfileSyncFactory* factory, 160 Profile* profile, 161 const std::string& test_user, 162 bool synchronous_backend_initialization, 163 Task* initial_condition_setup_task) 164 : ProfileSyncService(factory, profile, test_user), 165 synchronous_backend_initialization_( 166 synchronous_backend_initialization), 167 synchronous_sync_configuration_(false), 168 initial_condition_setup_task_(initial_condition_setup_task), 169 set_initial_sync_ended_on_init_(true) { 170 RegisterPreferences(); 171 SetSyncSetupCompleted(); 172 } 173 174 TestProfileSyncService::~TestProfileSyncService() {} 175 176 void TestProfileSyncService::SetInitialSyncEndedForEnabledTypes() { 177 UserShare* user_share = GetUserShare(); 178 DirectoryManager* dir_manager = user_share->dir_manager.get(); 179 180 ScopedDirLookup dir(dir_manager, user_share->name); 181 if (!dir.good()) 182 FAIL(); 183 184 ModelSafeRoutingInfo enabled_types; 185 backend_->GetModelSafeRoutingInfo(&enabled_types); 186 for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); 187 i != enabled_types.end(); ++i) { 188 dir->set_initial_sync_ended_for_type(i->first, true); 189 } 190 } 191 192 void TestProfileSyncService::OnBackendInitialized() { 193 // Set this so below code can access GetUserShare(). 194 backend_initialized_ = true; 195 196 // Set up any nodes the test wants around before model association. 197 if (initial_condition_setup_task_) { 198 initial_condition_setup_task_->Run(); 199 initial_condition_setup_task_ = NULL; 200 } 201 202 // Pretend we downloaded initial updates and set initial sync ended bits 203 // if we were asked to. 204 bool send_passphrase_required = false; 205 if (set_initial_sync_ended_on_init_) { 206 UserShare* user_share = GetUserShare(); 207 DirectoryManager* dir_manager = user_share->dir_manager.get(); 208 209 ScopedDirLookup dir(dir_manager, user_share->name); 210 if (!dir.good()) 211 FAIL(); 212 213 if (!dir->initial_sync_ended_for_type(syncable::NIGORI)) { 214 ProfileSyncServiceTestHelper::CreateRoot( 215 syncable::NIGORI, GetUserShare(), 216 id_factory()); 217 218 // A side effect of adding the NIGORI mode (normally done by the syncer) 219 // is a decryption attempt, which will fail the first time. 220 send_passphrase_required = true; 221 } 222 223 SetInitialSyncEndedForEnabledTypes(); 224 } 225 226 ProfileSyncService::OnBackendInitialized(); 227 if (send_passphrase_required) 228 OnPassphraseRequired(true); 229 230 // TODO(akalin): Figure out a better way to do this. 231 if (synchronous_backend_initialization_) { 232 MessageLoop::current()->Quit(); 233 } 234 } 235 236 void TestProfileSyncService::Observe(NotificationType type, 237 const NotificationSource& source, 238 const NotificationDetails& details) { 239 ProfileSyncService::Observe(type, source, details); 240 if (type == NotificationType::SYNC_CONFIGURE_DONE && 241 !synchronous_sync_configuration_) { 242 MessageLoop::current()->Quit(); 243 } 244 } 245 246 void TestProfileSyncService::dont_set_initial_sync_ended_on_init() { 247 set_initial_sync_ended_on_init_ = false; 248 } 249 void TestProfileSyncService::set_synchronous_sync_configuration() { 250 synchronous_sync_configuration_ = true; 251 } 252 253 void TestProfileSyncService::CreateBackend() { 254 backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( 255 profile(), 256 set_initial_sync_ended_on_init_, 257 synchronous_backend_initialization_)); 258 } 259 260 std::string TestProfileSyncService::GetLsidForAuthBootstraping() { 261 return "foo"; 262 } 263