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.
5 #include "base/file_util.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/prefs/pref_service.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
10 #include "chrome/browser/signin/fake_signin_manager.h"
11 #include "chrome/browser/signin/profile_oauth2_token_service.h"
12 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
13 #include "chrome/browser/signin/signin_manager.h"
14 #include "chrome/browser/signin/signin_manager_factory.h"
15 #include "chrome/browser/sync/glue/data_type_manager.h"
16 #include "chrome/browser/sync/glue/data_type_manager_mock.h"
17 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
18 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
19 #include "chrome/browser/sync/profile_sync_service_factory.h"
20 #include "chrome/browser/sync/profile_sync_test_util.h"
21 #include "chrome/browser/sync/sync_prefs.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/notification_source.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "content/public/test/test_utils.h"
28 #include "google_apis/gaia/gaia_auth_consumer.h"
29 #include "google_apis/gaia/gaia_constants.h"
30 #include "google_apis/gaia/oauth2_token_service.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
34 using browser_sync::DataTypeManager;
35 using browser_sync::DataTypeManagerMock;
36 using browser_sync::SyncBackendHostMock;
37 using content::BrowserThread;
39 using testing::AnyNumber;
41 using testing::InvokeArgument;
43 using testing::Return;
45 ACTION_P(InvokeOnConfigureStart, pss) {
46 ProfileSyncService* service =
47 static_cast<ProfileSyncService*>(pss);
48 service->OnConfigureStart();
51 ACTION_P2(InvokeOnConfigureDone, pss, result) {
52 ProfileSyncService* service =
53 static_cast<ProfileSyncService*>(pss);
54 DataTypeManager::ConfigureResult configure_result =
55 static_cast<DataTypeManager::ConfigureResult>(result);
56 service->OnConfigureDone(configure_result);
59 class ProfileSyncServiceStartupTest : public testing::Test {
61 ProfileSyncServiceStartupTest()
62 : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD |
63 content::TestBrowserThreadBundle::REAL_FILE_THREAD |
64 content::TestBrowserThreadBundle::REAL_IO_THREAD),
67 virtual ~ProfileSyncServiceStartupTest() {
70 virtual void SetUp() {
71 profile_ = CreateProfile();
74 virtual scoped_ptr<TestingProfile> CreateProfile() {
75 TestingProfile::Builder builder;
76 builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
77 FakeSigninManagerBase::Build);
78 builder.AddTestingFactory(
79 ProfileOAuth2TokenServiceFactory::GetInstance(),
80 FakeProfileOAuth2TokenService::BuildAutoIssuingTokenService);
81 builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(),
83 return builder.Build();
86 virtual void TearDown() {
87 sync_->RemoveObserver(&observer_);
91 static BrowserContextKeyedService* BuildService(
92 content::BrowserContext* browser_context) {
93 Profile* profile = static_cast<Profile*>(browser_context);
94 return new ProfileSyncService(
95 new ProfileSyncComponentsFactoryMock(),
97 SigninManagerFactory::GetForProfile(profile),
98 ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
99 ProfileSyncService::MANUAL_START);
102 void CreateSyncService() {
103 sync_ = static_cast<ProfileSyncService*>(
104 ProfileSyncServiceFactory::GetForProfile(profile_.get()));
105 sync_->AddObserver(&observer_);
108 void IssueTestTokens() {
109 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get())
110 ->UpdateCredentials("test_user@gmail.com", "oauth2_login_token");
113 ProfileSyncComponentsFactoryMock* components_factory_mock() {
114 return static_cast<ProfileSyncComponentsFactoryMock*>(sync_->factory());
118 DataTypeManagerMock* SetUpDataTypeManager() {
119 DataTypeManagerMock* data_type_manager = new DataTypeManagerMock();
120 EXPECT_CALL(*components_factory_mock(),
121 CreateDataTypeManager(_, _, _, _, _, _)).
122 WillOnce(Return(data_type_manager));
123 return data_type_manager;
126 browser_sync::SyncBackendHostMock* SetUpSyncBackendHost() {
127 browser_sync::SyncBackendHostMock* sync_backend_host =
128 new browser_sync::SyncBackendHostMock();
129 EXPECT_CALL(*components_factory_mock(),
130 CreateSyncBackendHost(_, _, _)).
131 WillOnce(Return(sync_backend_host));
132 return sync_backend_host;
135 content::TestBrowserThreadBundle thread_bundle_;
136 scoped_ptr<TestingProfile> profile_;
137 ProfileSyncService* sync_;
138 ProfileSyncServiceObserverMock observer_;
139 ProfileSyncComponentsFactoryMock* mock_components_factory_;
142 class ProfileSyncServiceStartupCrosTest : public ProfileSyncServiceStartupTest {
144 virtual void SetUp() {
145 ProfileSyncServiceStartupTest::SetUp();
146 sync_ = static_cast<ProfileSyncService*>(
147 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
148 profile_.get(), BuildCrosService));
149 sync_->AddObserver(&observer_);
152 static BrowserContextKeyedService* BuildCrosService(
153 content::BrowserContext* context) {
154 Profile* profile = static_cast<Profile*>(context);
155 SigninManagerBase* signin =
156 SigninManagerFactory::GetForProfile(profile);
157 profile->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
158 "test_user@gmail.com");
159 ProfileOAuth2TokenService* oauth2_token_service =
160 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
161 signin->Initialize(profile, NULL);
162 EXPECT_FALSE(signin->GetAuthenticatedUsername().empty());
163 return new ProfileSyncService(
164 new ProfileSyncComponentsFactoryMock(),
167 oauth2_token_service,
168 ProfileSyncService::AUTO_START);
172 TEST_F(ProfileSyncServiceStartupTest, StartFirstTime) {
173 // We've never completed startup.
174 profile_->GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
175 SigninManagerFactory::GetForProfile(
176 profile_.get())->Initialize(profile_.get(), NULL);
178 SetUpSyncBackendHost();
179 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
180 EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
182 // Should not actually start, rather just clean things up and wait
184 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
187 // Preferences should be back to defaults.
188 EXPECT_EQ(0, profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime));
189 EXPECT_FALSE(profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted));
190 Mock::VerifyAndClearExpectations(data_type_manager);
192 // Then start things up.
193 EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(1);
194 EXPECT_CALL(*data_type_manager, state()).
195 WillOnce(Return(DataTypeManager::CONFIGURED)).
196 WillOnce(Return(DataTypeManager::CONFIGURED));
197 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
198 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
200 sync_->SetSetupInProgress(true);
202 // Simulate successful signin as test_user.
203 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
204 "test_user@gmail.com");
205 sync_->signin()->SetAuthenticatedUsername("test_user@gmail.com");
206 GoogleServiceSigninSuccessDetails details("test_user@gmail.com", "");
207 content::NotificationService::current()->Notify(
208 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
209 content::Source<Profile>(profile_.get()),
210 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
212 // Create some tokens in the token service.
215 // Simulate the UI telling sync it has finished setting up.
216 sync_->SetSetupInProgress(false);
217 EXPECT_TRUE(sync_->ShouldPushChanges());
220 // TODO(pavely): Reenable test once android is switched to oauth2.
221 TEST_F(ProfileSyncServiceStartupTest, DISABLED_StartNoCredentials) {
222 // We've never completed startup.
223 profile_->GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
224 SigninManagerFactory::GetForProfile(
225 profile_.get())->Initialize(profile_.get(), NULL);
228 // Should not actually start, rather just clean things up and wait
230 EXPECT_CALL(*components_factory_mock(),
231 CreateDataTypeManager(_, _, _, _, _, _)).Times(0);
232 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
235 // Preferences should be back to defaults.
236 EXPECT_EQ(0, profile_->GetPrefs()->GetInt64(prefs::kSyncLastSyncedTime));
237 EXPECT_FALSE(profile_->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted));
239 // Then start things up.
240 sync_->SetSetupInProgress(true);
242 // Simulate successful signin as test_user.
243 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
244 "test_user@gmail.com");
245 sync_->signin()->SetAuthenticatedUsername("test_user@gmail.com");
246 GoogleServiceSigninSuccessDetails details("test_user@gmail.com", "");
247 content::NotificationService::current()->Notify(
248 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
249 content::Source<Profile>(profile_.get()),
250 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
251 ProfileOAuth2TokenService* token_service =
252 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
253 token_service->LoadCredentials("test_user@gmail.com");
255 sync_->SetSetupInProgress(false);
256 // ProfileSyncService should try to start by requesting access token.
257 // This request should fail as login token was not issued.
258 EXPECT_FALSE(sync_->ShouldPushChanges());
259 EXPECT_EQ(GoogleServiceAuthError::USER_NOT_SIGNED_UP,
260 sync_->GetAuthError().state());
263 // TODO(pavely): Reenable test once android is switched to oauth2.
264 TEST_F(ProfileSyncServiceStartupTest, DISABLED_StartInvalidCredentials) {
265 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
266 "test_user@gmail.com");
267 SigninManagerFactory::GetForProfile(
268 profile_.get())->Initialize(profile_.get(), NULL);
270 SyncBackendHostMock* mock_sbh = SetUpSyncBackendHost();
272 // Tell the backend to stall while downloading control types (simulating an
274 mock_sbh->set_fail_initial_download(true);
276 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
277 EXPECT_CALL(*data_type_manager, Configure(_, _)).Times(0);
279 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
281 EXPECT_FALSE(sync_->sync_initialized());
282 Mock::VerifyAndClearExpectations(data_type_manager);
284 // Update the credentials, unstalling the backend.
285 EXPECT_CALL(*data_type_manager, Configure(_, _));
286 EXPECT_CALL(*data_type_manager, state()).
287 WillRepeatedly(Return(DataTypeManager::CONFIGURED));
288 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
289 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
290 sync_->SetSetupInProgress(true);
292 // Simulate successful signin.
293 GoogleServiceSigninSuccessDetails details("test_user@gmail.com",
295 content::NotificationService::current()->Notify(
296 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
297 content::Source<Profile>(profile_.get()),
298 content::Details<const GoogleServiceSigninSuccessDetails>(&details));
300 sync_->SetSetupInProgress(false);
302 // Verify we successfully finish startup and configuration.
303 EXPECT_TRUE(sync_->ShouldPushChanges());
306 TEST_F(ProfileSyncServiceStartupCrosTest, StartCrosNoCredentials) {
307 EXPECT_CALL(*components_factory_mock(),
308 CreateDataTypeManager(_, _, _, _, _, _)).Times(0);
309 EXPECT_CALL(*components_factory_mock(),
310 CreateSyncBackendHost(_, _, _)).Times(0);
311 profile_->GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
312 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
315 // Sync should not start because there are no tokens yet.
316 EXPECT_FALSE(sync_->ShouldPushChanges());
317 sync_->SetSetupInProgress(false);
319 // Sync should not start because there are still no tokens.
320 EXPECT_FALSE(sync_->ShouldPushChanges());
323 TEST_F(ProfileSyncServiceStartupCrosTest, StartFirstTime) {
324 SetUpSyncBackendHost();
325 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
326 profile_->GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
327 EXPECT_CALL(*data_type_manager, Configure(_, _));
328 EXPECT_CALL(*data_type_manager, state()).
329 WillRepeatedly(Return(DataTypeManager::CONFIGURED));
330 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
331 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
335 EXPECT_TRUE(sync_->ShouldPushChanges());
338 TEST_F(ProfileSyncServiceStartupTest, StartNormal) {
339 // Pre load the tokens
340 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
341 "test_user@gmail.com");
342 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
343 profile_.get(), NULL);
345 sync_->SetSyncSetupCompleted();
346 SetUpSyncBackendHost();
347 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
348 EXPECT_CALL(*data_type_manager, Configure(_, _));
349 EXPECT_CALL(*data_type_manager, state()).
350 WillRepeatedly(Return(DataTypeManager::CONFIGURED));
351 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
352 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
359 // Test that we can recover from a case where a bug in the code resulted in
360 // OnUserChoseDatatypes not being properly called and datatype preferences
361 // therefore being left unset.
362 TEST_F(ProfileSyncServiceStartupTest, StartRecoverDatatypePrefs) {
363 // Clear the datatype preference fields (simulating bug 154940).
364 profile_->GetPrefs()->ClearPref(prefs::kSyncKeepEverythingSynced);
365 syncer::ModelTypeSet user_types = syncer::UserTypes();
366 for (syncer::ModelTypeSet::Iterator iter = user_types.First();
367 iter.Good(); iter.Inc()) {
368 profile_->GetPrefs()->ClearPref(
369 browser_sync::SyncPrefs::GetPrefNameForDataType(iter.Get()));
372 // Pre load the tokens
373 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
374 "test_user@gmail.com");
375 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
376 profile_.get(), NULL);
378 sync_->SetSyncSetupCompleted();
379 SetUpSyncBackendHost();
380 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
381 EXPECT_CALL(*data_type_manager, Configure(_, _));
382 EXPECT_CALL(*data_type_manager, state()).
383 WillRepeatedly(Return(DataTypeManager::CONFIGURED));
384 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
385 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
390 EXPECT_TRUE(profile_->GetPrefs()->GetBoolean(
391 prefs::kSyncKeepEverythingSynced));
394 // Verify that the recovery of datatype preferences doesn't overwrite a valid
395 // case where only bookmarks are enabled.
396 TEST_F(ProfileSyncServiceStartupTest, StartDontRecoverDatatypePrefs) {
397 // Explicitly set Keep Everything Synced to false and have only bookmarks
399 profile_->GetPrefs()->SetBoolean(prefs::kSyncKeepEverythingSynced, false);
401 // Pre load the tokens
402 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
403 "test_user@gmail.com");
404 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
405 profile_.get(), NULL);
407 sync_->SetSyncSetupCompleted();
408 SetUpSyncBackendHost();
409 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
410 EXPECT_CALL(*data_type_manager, Configure(_, _));
411 EXPECT_CALL(*data_type_manager, state()).
412 WillRepeatedly(Return(DataTypeManager::CONFIGURED));
413 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
414 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
418 EXPECT_FALSE(profile_->GetPrefs()->GetBoolean(
419 prefs::kSyncKeepEverythingSynced));
422 TEST_F(ProfileSyncServiceStartupTest, ManagedStartup) {
423 // Service should not be started by Initialize() since it's managed.
424 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
425 "test_user@gmail.com");
426 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
427 profile_.get(), NULL);
430 // Disable sync through policy.
431 profile_->GetPrefs()->SetBoolean(prefs::kSyncManaged, true);
432 EXPECT_CALL(*components_factory_mock(),
433 CreateDataTypeManager(_, _, _, _, _, _)).Times(0);
434 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
439 TEST_F(ProfileSyncServiceStartupTest, SwitchManaged) {
440 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
441 "test_user@gmail.com");
442 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
443 profile_.get(), NULL);
445 sync_->SetSyncSetupCompleted();
446 SetUpSyncBackendHost();
447 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
448 EXPECT_CALL(*data_type_manager, Configure(_, _));
449 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
453 // The service should stop when switching to managed mode.
454 Mock::VerifyAndClearExpectations(data_type_manager);
455 EXPECT_CALL(*data_type_manager, state()).
456 WillOnce(Return(DataTypeManager::CONFIGURED));
457 EXPECT_CALL(*data_type_manager, Stop()).Times(1);
458 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
459 profile_->GetPrefs()->SetBoolean(prefs::kSyncManaged, true);
461 // When switching back to unmanaged, the state should change, but the service
462 // should not start up automatically (kSyncSetupCompleted will be false).
463 Mock::VerifyAndClearExpectations(data_type_manager);
464 EXPECT_CALL(*components_factory_mock(),
465 CreateDataTypeManager(_, _, _, _, _, _)).Times(0);
466 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
467 profile_->GetPrefs()->ClearPref(prefs::kSyncManaged);
470 TEST_F(ProfileSyncServiceStartupTest, StartFailure) {
471 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
472 "test_user@gmail.com");
473 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
474 profile_.get(), NULL);
476 sync_->SetSyncSetupCompleted();
477 SetUpSyncBackendHost();
478 DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
479 DataTypeManager::ConfigureStatus status = DataTypeManager::ABORTED;
480 syncer::SyncError error(
482 syncer::SyncError::DATATYPE_ERROR,
483 "Association failed.",
485 std::map<syncer::ModelType, syncer::SyncError> errors;
486 errors[syncer::BOOKMARKS] = error;
487 DataTypeManager::ConfigureResult result(
489 syncer::ModelTypeSet(),
491 syncer::ModelTypeSet(),
492 syncer::ModelTypeSet());
493 EXPECT_CALL(*data_type_manager, Configure(_, _)).
495 DoAll(InvokeOnConfigureStart(sync_),
496 InvokeOnConfigureDone(sync_, result)));
497 EXPECT_CALL(*data_type_manager, state()).
498 WillOnce(Return(DataTypeManager::STOPPED));
499 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
502 EXPECT_TRUE(sync_->HasUnrecoverableError());
505 TEST_F(ProfileSyncServiceStartupTest, StartDownloadFailed) {
506 // Pre load the tokens
507 profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
508 "test_user@gmail.com");
509 SigninManagerFactory::GetForProfile(profile_.get())->Initialize(
510 profile_.get(), NULL);
512 SyncBackendHostMock* mock_sbh = SetUpSyncBackendHost();
513 mock_sbh->set_fail_initial_download(true);
515 profile_->GetPrefs()->ClearPref(prefs::kSyncHasSetupCompleted);
517 EXPECT_CALL(observer_, OnStateChanged()).Times(AnyNumber());
520 sync_->SetSetupInProgress(true);
522 sync_->SetSetupInProgress(false);
523 EXPECT_FALSE(sync_->sync_initialized());