Home | History | Annotate | Download | only in sync
      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