1 // Copyright 2014 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/startup_controller.h" 6 7 #include "base/command_line.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/run_loop.h" 10 #include "base/time/time.h" 11 #include "chrome/browser/defaults.h" 12 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 13 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" 14 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 15 #include "chrome/browser/sync/supervised_user_signin_manager_wrapper.h" 16 #include "chrome/common/chrome_switches.h" 17 #include "chrome/test/base/testing_profile.h" 18 #include "components/sync_driver/sync_prefs.h" 19 #include "testing/gtest/include/gtest/gtest.h" 20 21 namespace browser_sync { 22 23 static const char kTestUser[] = "test (at) gmail.com"; 24 static const char kTestToken[] = "testToken"; 25 26 // These are coupled to the implementation of StartupController's 27 // GetBackendInitializationStateString which is used by about:sync. We use it 28 // as a convenient way to verify internal state and that the class is 29 // outputting the correct values for the debug string. 30 static const char kStateStringStarted[] = "Started"; 31 static const char kStateStringDeferred[] = "Deferred"; 32 static const char kStateStringNotStarted[] = "Not started"; 33 34 class FakeSupervisedUserSigninManagerWrapper 35 : public SupervisedUserSigninManagerWrapper { 36 public: 37 FakeSupervisedUserSigninManagerWrapper() 38 : SupervisedUserSigninManagerWrapper(NULL, NULL) {} 39 virtual std::string GetEffectiveUsername() const OVERRIDE { 40 return account_; 41 } 42 43 virtual std::string GetAccountIdToUse() const OVERRIDE { 44 return account_; 45 } 46 47 void set_account(const std::string& account) { account_ = account; } 48 49 private: 50 std::string account_; 51 }; 52 53 class StartupControllerTest : public testing::Test { 54 public: 55 StartupControllerTest() : started_(false) {} 56 57 virtual void SetUp() OVERRIDE { 58 profile_.reset(new TestingProfile()); 59 sync_prefs_.reset(new sync_driver::SyncPrefs(profile_->GetPrefs())); 60 token_service_.reset(static_cast<FakeProfileOAuth2TokenService*>( 61 BuildFakeProfileOAuth2TokenService(profile_.get()))); 62 signin_.reset(new FakeSupervisedUserSigninManagerWrapper()); 63 64 ProfileSyncServiceStartBehavior behavior = 65 browser_defaults::kSyncAutoStarts ? AUTO_START : MANUAL_START; 66 base::Closure fake_start_backend = base::Bind( 67 &StartupControllerTest::FakeStartBackend, base::Unretained(this)); 68 controller_.reset(new StartupController(behavior, token_service(), 69 sync_prefs_.get(), signin_.get(), 70 fake_start_backend)); 71 controller_->Reset(syncer::UserTypes()); 72 controller_->OverrideFallbackTimeoutForTest( 73 base::TimeDelta::FromSeconds(0)); 74 } 75 76 virtual void TearDown() OVERRIDE { 77 controller_.reset(); 78 signin_.reset(); 79 token_service_->Shutdown(); 80 token_service_.reset(); 81 sync_prefs_.reset(); 82 started_ = false; 83 } 84 85 void FakeStartBackend() { 86 started_ = true; 87 } 88 89 bool started() const { return started_; } 90 void clear_started() { started_ = false; } 91 StartupController* controller() { return controller_.get(); } 92 FakeSupervisedUserSigninManagerWrapper* signin() { return signin_.get(); } 93 FakeProfileOAuth2TokenService* token_service() { 94 return token_service_.get(); 95 } 96 sync_driver::SyncPrefs* sync_prefs() { return sync_prefs_.get(); } 97 Profile* profile() { return profile_.get(); } 98 99 private: 100 bool started_; 101 base::MessageLoop message_loop_; 102 scoped_ptr<StartupController> controller_; 103 scoped_ptr<FakeSupervisedUserSigninManagerWrapper> signin_; 104 scoped_ptr<FakeProfileOAuth2TokenService> token_service_; 105 scoped_ptr<sync_driver::SyncPrefs> sync_prefs_; 106 scoped_ptr<TestingProfile> profile_; 107 }; 108 109 // Test that sync doesn't start until all conditions are met. 110 TEST_F(StartupControllerTest, Basic) { 111 controller()->TryStart(); 112 EXPECT_FALSE(started()); 113 sync_prefs()->SetSyncSetupCompleted(); 114 controller()->TryStart(); 115 EXPECT_FALSE(started()); 116 signin()->set_account(kTestUser); 117 controller()->TryStart(); 118 EXPECT_FALSE(started()); 119 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 120 const bool deferred_start = !CommandLine::ForCurrentProcess()-> 121 HasSwitch(switches::kSyncDisableDeferredStartup); 122 controller()->TryStart(); 123 EXPECT_EQ(!deferred_start, started()); 124 std::string state(controller()->GetBackendInitializationStateString()); 125 EXPECT_TRUE(deferred_start ? state == kStateStringDeferred : 126 state == kStateStringStarted); 127 } 128 129 // Test that sync doesn't when suppressed even if all other conditons are met. 130 TEST_F(StartupControllerTest, Suppressed) { 131 sync_prefs()->SetSyncSetupCompleted(); 132 sync_prefs()->SetStartSuppressed(true); 133 signin()->set_account(kTestUser); 134 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 135 controller()->TryStart(); 136 EXPECT_FALSE(started()); 137 EXPECT_EQ(kStateStringNotStarted, 138 controller()->GetBackendInitializationStateString()); 139 } 140 141 // Test that sync doesn't when managed even if all other conditons are met. 142 TEST_F(StartupControllerTest, Managed) { 143 sync_prefs()->SetSyncSetupCompleted(); 144 sync_prefs()->SetManagedForTest(true); 145 signin()->set_account(kTestUser); 146 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 147 controller()->TryStart(); 148 EXPECT_FALSE(started()); 149 EXPECT_EQ(kStateStringNotStarted, 150 controller()->GetBackendInitializationStateString()); 151 } 152 153 // Test that sync doesn't start until all conditions are met and a 154 // data type triggers sync startup. 155 TEST_F(StartupControllerTest, DataTypeTriggered) { 156 sync_prefs()->SetSyncSetupCompleted(); 157 signin()->set_account(kTestUser); 158 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 159 controller()->TryStart(); 160 EXPECT_FALSE(started()); 161 EXPECT_EQ(kStateStringDeferred, 162 controller()->GetBackendInitializationStateString()); 163 controller()->OnDataTypeRequestsSyncStartup(syncer::SESSIONS); 164 EXPECT_TRUE(started()); 165 EXPECT_EQ(kStateStringStarted, 166 controller()->GetBackendInitializationStateString()); 167 168 // The fallback timer shouldn't result in another invocation of the closure 169 // we passed to the StartupController. 170 clear_started(); 171 base::RunLoop().RunUntilIdle(); 172 EXPECT_FALSE(started()); 173 } 174 175 // Test that the fallback timer starts sync in the event all 176 // conditions are met and no data type requests sync. 177 TEST_F(StartupControllerTest, FallbackTimer) { 178 sync_prefs()->SetSyncSetupCompleted(); 179 signin()->set_account(kTestUser); 180 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 181 controller()->TryStart(); 182 EXPECT_FALSE(started()); 183 base::RunLoop().RunUntilIdle(); 184 EXPECT_TRUE(started()); 185 } 186 187 // Test that we start immediately if sessions is disabled. 188 TEST_F(StartupControllerTest, NoDeferralWithoutSessionsSync) { 189 syncer::ModelTypeSet types(syncer::UserTypes()); 190 // Disabling sessions means disabling 4 types due to groupings. 191 types.Remove(syncer::SESSIONS); 192 types.Remove(syncer::PROXY_TABS); 193 types.Remove(syncer::TYPED_URLS); 194 types.Remove(syncer::SUPERVISED_USER_SETTINGS); 195 sync_prefs()->SetKeepEverythingSynced(false); 196 sync_prefs()->SetPreferredDataTypes(syncer::UserTypes(), types); 197 controller()->Reset(syncer::UserTypes()); 198 sync_prefs()->SetSyncSetupCompleted(); 199 signin()->set_account(kTestUser); 200 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 201 controller()->TryStart(); 202 EXPECT_TRUE(started()); 203 } 204 205 // Sanity check that the fallback timer doesn't fire before startup 206 // conditions are met. 207 TEST_F(StartupControllerTest, FallbackTimerWaits) { 208 controller()->TryStart(); 209 EXPECT_FALSE(started()); 210 base::RunLoop().RunUntilIdle(); 211 EXPECT_FALSE(started()); 212 } 213 214 // Test that sync starts when the user first asks to setup sync (which 215 // may be implicit due to the platform). 216 TEST_F(StartupControllerTest, FirstSetup) { 217 signin()->set_account(kTestUser); 218 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 219 controller()->TryStart(); 220 221 if (browser_defaults::kSyncAutoStarts) { 222 EXPECT_TRUE(started()); 223 } else { 224 controller()->set_setup_in_progress(true); 225 controller()->TryStart(); 226 EXPECT_TRUE(started()); 227 } 228 } 229 230 TEST_F(StartupControllerTest, Reset) { 231 sync_prefs()->SetSyncSetupCompleted(); 232 signin()->set_account(kTestUser); 233 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 234 controller()->TryStart(); 235 const bool deferred_start = !CommandLine::ForCurrentProcess()-> 236 HasSwitch(switches::kSyncDisableDeferredStartup); 237 EXPECT_EQ(!deferred_start, started()); 238 controller()->OnDataTypeRequestsSyncStartup(syncer::SESSIONS); 239 EXPECT_TRUE(started()); 240 clear_started(); 241 controller()->Reset(syncer::UserTypes()); 242 EXPECT_FALSE(started()); 243 controller()->TryStart(); 244 // Restart is not deferred. 245 EXPECT_TRUE(started()); 246 } 247 248 // Test that setup-in-progress tracking is persistent across a Reset. 249 TEST_F(StartupControllerTest, ResetDuringSetup) { 250 signin()->set_account(kTestUser); 251 token_service()->IssueRefreshTokenForUser(kTestUser, kTestToken); 252 253 // Simulate UI telling us setup is in progress. 254 controller()->set_setup_in_progress(true); 255 256 // This could happen if the UI triggers a stop-syncing permanently call. 257 controller()->Reset(syncer::UserTypes()); 258 259 // From the UI's point of view, setup is still in progress. 260 EXPECT_TRUE(controller()->setup_in_progress()); 261 } 262 263 } // namespace browser_sync 264