test_profile_sync_service.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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 3// found in the LICENSE file. 4 5#include "chrome/browser/sync/test_profile_sync_service.h" 6 7#include "chrome/browser/chrome_notification_types.h" 8#include "chrome/browser/signin/signin_manager.h" 9#include "chrome/browser/signin/signin_manager_factory.h" 10#include "chrome/browser/sync/glue/data_type_controller.h" 11#include "chrome/browser/sync/glue/sync_backend_host.h" 12#include "chrome/browser/sync/profile_sync_components_factory.h" 13#include "chrome/browser/sync/test/test_http_bridge_factory.h" 14#include "sync/internal_api/public/sessions/sync_session_snapshot.h" 15#include "sync/internal_api/public/test/test_user_share.h" 16#include "sync/internal_api/public/user_share.h" 17#include "sync/js/js_reply_handler.h" 18#include "sync/protocol/encryption.pb.h" 19#include "sync/syncable/directory.h" 20 21using syncer::InternalComponentsFactory; 22using syncer::ModelSafeRoutingInfo; 23using syncer::TestInternalComponentsFactory; 24using syncer::sessions::ModelNeutralState; 25using syncer::sessions::SyncSessionSnapshot; 26using syncer::sessions::SyncSourceInfo; 27using syncer::UserShare; 28using syncer::syncable::Directory; 29using syncer::DEVICE_INFO; 30using syncer::EXPERIMENTS; 31using syncer::NIGORI; 32using syncer::PRIORITY_PREFERENCES; 33 34namespace browser_sync { 35 36SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest( 37 Profile* profile, 38 const base::WeakPtr<SyncPrefs>& sync_prefs, 39 syncer::TestIdFactory& id_factory, 40 base::Closure& callback, 41 bool set_initial_sync_ended_on_init, 42 bool synchronous_init, 43 bool fail_initial_download, 44 syncer::StorageOption storage_option) 45 : browser_sync::SyncBackendHost( 46 profile->GetDebugName(), profile, sync_prefs), 47 weak_ptr_factory_(this), 48 id_factory_(id_factory), 49 callback_(callback), 50 fail_initial_download_(fail_initial_download), 51 set_initial_sync_ended_on_init_(set_initial_sync_ended_on_init), 52 synchronous_init_(synchronous_init), 53 storage_option_(storage_option) {} 54 55SyncBackendHostForProfileSyncTest::~SyncBackendHostForProfileSyncTest() {} 56 57namespace { 58 59scoped_ptr<syncer::HttpPostProviderFactory> MakeTestHttpBridgeFactory() { 60 return scoped_ptr<syncer::HttpPostProviderFactory>( 61 new browser_sync::TestHttpBridgeFactory()); 62} 63 64} // namespace 65 66void SyncBackendHostForProfileSyncTest::InitCore( 67 const DoInitializeOptions& options) { 68 DoInitializeOptions test_options = options; 69 test_options.make_http_bridge_factory_fn = 70 base::Bind(&MakeTestHttpBridgeFactory); 71 test_options.credentials.email = "testuser@gmail.com"; 72 test_options.credentials.sync_token = "token"; 73 test_options.restored_key_for_bootstrapping = ""; 74 syncer::StorageOption storage = storage_option_; 75 76 // It'd be nice if we avoided creating the InternalComponentsFactory in the 77 // first place, but SyncBackendHost will have created one by now so we must 78 // free it. Grab the switches to pass on first. 79 InternalComponentsFactory::Switches factory_switches = 80 test_options.internal_components_factory->GetSwitches(); 81 delete test_options.internal_components_factory; 82 83 test_options.internal_components_factory = 84 new TestInternalComponentsFactory(factory_switches, storage); 85 86 SyncBackendHost::InitCore(test_options); 87 if (synchronous_init_ && !base::MessageLoop::current()->is_running()) { 88 // The SyncBackend posts a task to the current loop when 89 // initialization completes. 90 base::MessageLoop::current()->Run(); 91 } 92} 93 94void SyncBackendHostForProfileSyncTest::UpdateCredentials( 95 const syncer::SyncCredentials& credentials) { 96 // If we had failed the initial download, complete initialization now. 97 if (!initial_download_closure_.is_null()) { 98 initial_download_closure_.Run(); 99 initial_download_closure_.Reset(); 100 } 101} 102 103void SyncBackendHostForProfileSyncTest::RequestConfigureSyncer( 104 syncer::ConfigureReason reason, 105 syncer::ModelTypeSet to_download, 106 syncer::ModelTypeSet to_purge, 107 syncer::ModelTypeSet to_journal, 108 syncer::ModelTypeSet to_unapply, 109 syncer::ModelTypeSet to_ignore, 110 const syncer::ModelSafeRoutingInfo& routing_info, 111 const base::Callback<void(syncer::ModelTypeSet, 112 syncer::ModelTypeSet)>& ready_task, 113 const base::Closure& retry_callback) { 114 syncer::ModelTypeSet failed_configuration_types; 115 if (fail_initial_download_) 116 failed_configuration_types = to_download; 117 118 // The first parameter there should be the set of enabled types. That's not 119 // something we have access to from this strange test harness. We'll just 120 // send back the list of newly configured types instead and hope it doesn't 121 // break anything. 122 FinishConfigureDataTypesOnFrontendLoop( 123 syncer::Difference(to_download, failed_configuration_types), 124 syncer::Difference(to_download, failed_configuration_types), 125 failed_configuration_types, 126 ready_task); 127} 128 129void SyncBackendHostForProfileSyncTest 130 ::HandleSyncManagerInitializationOnFrontendLoop( 131 const syncer::WeakHandle<syncer::JsBackend>& js_backend, 132 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 133 debug_info_listener, 134 syncer::ModelTypeSet restored_types) { 135 // Here's our opportunity to pretend to do things that the SyncManager would 136 // normally do during initialization, but can't because this is a test. 137 // Set up any nodes the test wants around before model association. 138 if (!callback_.is_null()) { 139 callback_.Run(); 140 } 141 142 // Pretend we downloaded initial updates and set initial sync ended bits 143 // if we were asked to. 144 if (set_initial_sync_ended_on_init_) { 145 UserShare* user_share = GetUserShare(); 146 Directory* directory = user_share->directory.get(); 147 148 if (!directory->InitialSyncEndedForType(NIGORI)) { 149 syncer::TestUserShare::CreateRoot(NIGORI, user_share); 150 151 // A side effect of adding the NIGORI node (normally done by the 152 // syncer) is a decryption attempt, which will fail the first time. 153 } 154 155 if (!directory->InitialSyncEndedForType(DEVICE_INFO)) { 156 syncer::TestUserShare::CreateRoot(DEVICE_INFO, user_share); 157 } 158 159 if (!directory->InitialSyncEndedForType(EXPERIMENTS)) { 160 syncer::TestUserShare::CreateRoot(EXPERIMENTS, user_share); 161 } 162 163 if (!directory->InitialSyncEndedForType(PRIORITY_PREFERENCES)) { 164 syncer::TestUserShare::CreateRoot(PRIORITY_PREFERENCES, user_share); 165 } 166 167 restored_types = syncer::ModelTypeSet::All(); 168 } 169 170 initial_download_closure_ = base::Bind( 171 &SyncBackendHostForProfileSyncTest::ContinueInitialization, 172 weak_ptr_factory_.GetWeakPtr(), 173 js_backend, 174 debug_info_listener, 175 restored_types); 176 if (fail_initial_download_) { 177 frontend()->OnSyncConfigureRetry(); 178 if (synchronous_init_) 179 base::MessageLoop::current()->Quit(); 180 } else { 181 initial_download_closure_.Run(); 182 initial_download_closure_.Reset(); 183 } 184} 185 186void SyncBackendHostForProfileSyncTest::ContinueInitialization( 187 const syncer::WeakHandle<syncer::JsBackend>& js_backend, 188 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 189 debug_info_listener, 190 syncer::ModelTypeSet restored_types) { 191 SyncBackendHost::HandleSyncManagerInitializationOnFrontendLoop( 192 js_backend, debug_info_listener, restored_types); 193} 194 195} // namespace browser_sync 196 197syncer::TestIdFactory* TestProfileSyncService::id_factory() { 198 return &id_factory_; 199} 200 201browser_sync::SyncBackendHostForProfileSyncTest* 202 TestProfileSyncService::GetBackendForTest() { 203 return static_cast<browser_sync::SyncBackendHostForProfileSyncTest*>( 204 ProfileSyncService::GetBackendForTest()); 205} 206 207TestProfileSyncService::TestProfileSyncService( 208 ProfileSyncComponentsFactory* factory, 209 Profile* profile, 210 SigninManagerBase* signin, 211 ProfileSyncService::StartBehavior behavior, 212 bool synchronous_backend_initialization) 213 : ProfileSyncService(factory, 214 profile, 215 signin, 216 behavior), 217 synchronous_backend_initialization_( 218 synchronous_backend_initialization), 219 synchronous_sync_configuration_(false), 220 set_initial_sync_ended_on_init_(true), 221 fail_initial_download_(false), 222 storage_option_(syncer::STORAGE_IN_MEMORY) { 223 SetSyncSetupCompleted(); 224} 225 226TestProfileSyncService::~TestProfileSyncService() { 227} 228 229// static 230BrowserContextKeyedService* TestProfileSyncService::BuildAutoStartAsyncInit( 231 content::BrowserContext* context) { 232 Profile* profile = static_cast<Profile*>(context); 233 SigninManagerBase* signin = 234 SigninManagerFactory::GetForProfile(profile); 235 ProfileSyncComponentsFactoryMock* factory = 236 new ProfileSyncComponentsFactoryMock(); 237 return new TestProfileSyncService( 238 factory, profile, signin, ProfileSyncService::AUTO_START, false); 239} 240 241ProfileSyncComponentsFactoryMock* 242TestProfileSyncService::components_factory_mock() { 243 // We always create a mock factory, see Build* routines. 244 return static_cast<ProfileSyncComponentsFactoryMock*>(factory()); 245} 246 247void TestProfileSyncService::RequestAccessToken() { 248 ProfileSyncService::RequestAccessToken(); 249 if (synchronous_backend_initialization_) { 250 base::MessageLoop::current()->Run(); 251 } 252} 253 254void TestProfileSyncService::OnGetTokenFailure( 255 const OAuth2TokenService::Request* request, 256 const GoogleServiceAuthError& error) { 257 ProfileSyncService::OnGetTokenFailure(request, error); 258 if (synchronous_backend_initialization_) { 259 base::MessageLoop::current()->Quit(); 260 } 261} 262 263 264void TestProfileSyncService::OnBackendInitialized( 265 const syncer::WeakHandle<syncer::JsBackend>& backend, 266 const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& 267 debug_info_listener, 268 bool success) { 269 ProfileSyncService::OnBackendInitialized(backend, 270 debug_info_listener, 271 success); 272 273 // TODO(akalin): Figure out a better way to do this. 274 if (synchronous_backend_initialization_) { 275 base::MessageLoop::current()->Quit(); 276 } 277} 278 279void TestProfileSyncService::OnConfigureDone( 280 const browser_sync::DataTypeManager::ConfigureResult& result) { 281 ProfileSyncService::OnConfigureDone(result); 282 if (!synchronous_sync_configuration_) 283 base::MessageLoop::current()->Quit(); 284} 285 286UserShare* TestProfileSyncService::GetUserShare() const { 287 return backend_->GetUserShare(); 288} 289 290void TestProfileSyncService::dont_set_initial_sync_ended_on_init() { 291 set_initial_sync_ended_on_init_ = false; 292} 293void TestProfileSyncService::set_synchronous_sync_configuration() { 294 synchronous_sync_configuration_ = true; 295} 296void TestProfileSyncService::fail_initial_download() { 297 fail_initial_download_ = true; 298} 299void TestProfileSyncService::set_storage_option( 300 syncer::StorageOption storage_option) { 301 storage_option_ = storage_option; 302} 303 304void TestProfileSyncService::CreateBackend() { 305 backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( 306 profile(), 307 sync_prefs_.AsWeakPtr(), 308 id_factory_, 309 callback_, 310 set_initial_sync_ended_on_init_, 311 synchronous_backend_initialization_, 312 fail_initial_download_, 313 storage_option_)); 314} 315 316scoped_ptr<OAuth2TokenService::Request> FakeOAuth2TokenService::StartRequest( 317 const OAuth2TokenService::ScopeSet& scopes, 318 OAuth2TokenService::Consumer* consumer) { 319 // Ensure token in question is cached and never expires. Request will succeed 320 // without network IO. 321 RegisterCacheEntry(GetRefreshToken(), scopes, "access_token", 322 base::Time::Max()); 323 return ProfileOAuth2TokenService::StartRequest(scopes, consumer); 324} 325 326BrowserContextKeyedService* FakeOAuth2TokenService::BuildTokenService( 327 content::BrowserContext* context) { 328 Profile* profile = static_cast<Profile*>(context); 329 330 FakeOAuth2TokenService* service = 331 new FakeOAuth2TokenService(context->GetRequestContext()); 332 service->Initialize(profile); 333 return service; 334} 335