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 "base/basictypes.h"
6#include "base/command_line.h"
7#include "base/compiler_specific.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/run_loop.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/utf_string_conversions.h"
12#include "base/values.h"
13#include "chrome/browser/invalidation/fake_invalidation_service.h"
14#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
15#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
16#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
17#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18#include "chrome/browser/signin/signin_manager_factory.h"
19#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
20#include "chrome/browser/sync/profile_sync_components_factory_mock.h"
21#include "chrome/browser/sync/supervised_user_signin_manager_wrapper.h"
22#include "chrome/common/chrome_switches.h"
23#include "chrome/common/pref_names.h"
24#include "chrome/grit/generated_resources.h"
25#include "chrome/test/base/testing_browser_process.h"
26#include "chrome/test/base/testing_pref_service_syncable.h"
27#include "chrome/test/base/testing_profile.h"
28#include "chrome/test/base/testing_profile_manager.h"
29#include "components/invalidation/invalidation_service.h"
30#include "components/invalidation/profile_invalidation_provider.h"
31#include "components/signin/core/browser/signin_manager.h"
32#include "components/sync_driver/data_type_manager.h"
33#include "components/sync_driver/pref_names.h"
34#include "components/sync_driver/sync_prefs.h"
35#include "content/public/test/test_browser_thread_bundle.h"
36#include "google_apis/gaia/gaia_constants.h"
37#include "testing/gmock/include/gmock/gmock.h"
38#include "testing/gtest/include/gtest/gtest.h"
39#include "ui/base/l10n/l10n_util.h"
40
41namespace content {
42class BrowserContext;
43}
44
45namespace browser_sync {
46
47namespace {
48
49class FakeDataTypeManager : public sync_driver::DataTypeManager {
50 public:
51  explicit FakeDataTypeManager(sync_driver::DataTypeManagerObserver* observer)
52     : observer_(observer) {}
53  virtual ~FakeDataTypeManager() {};
54
55  virtual void Configure(syncer::ModelTypeSet desired_types,
56                         syncer::ConfigureReason reason) OVERRIDE {
57    sync_driver::DataTypeManager::ConfigureResult result;
58    result.status = sync_driver::DataTypeManager::OK;
59    observer_->OnConfigureDone(result);
60  }
61
62  virtual void ReenableType(syncer::ModelType type) OVERRIDE {}
63  virtual void ResetDataTypeErrors() OVERRIDE {}
64  virtual void PurgeForMigration(syncer::ModelTypeSet undesired_types,
65                                 syncer::ConfigureReason reason) OVERRIDE {}
66  virtual void Stop() OVERRIDE {};
67  virtual State state() const OVERRIDE {
68    return sync_driver::DataTypeManager::CONFIGURED;
69  };
70
71 private:
72  sync_driver::DataTypeManagerObserver* observer_;
73};
74
75ACTION(ReturnNewDataTypeManager) {
76  return new FakeDataTypeManager(arg4);
77}
78
79using testing::Return;
80using testing::StrictMock;
81using testing::_;
82
83class TestProfileSyncServiceObserver : public ProfileSyncServiceObserver {
84 public:
85  explicit TestProfileSyncServiceObserver(ProfileSyncService* service)
86      : service_(service), first_setup_in_progress_(false) {}
87  virtual void OnStateChanged() OVERRIDE {
88    first_setup_in_progress_ = service_->FirstSetupInProgress();
89  }
90  bool first_setup_in_progress() const { return first_setup_in_progress_; }
91 private:
92  ProfileSyncService* service_;
93  bool first_setup_in_progress_;
94};
95
96// A variant of the SyncBackendHostMock that won't automatically
97// call back when asked to initialized.  Allows us to test things
98// that could happen while backend init is in progress.
99class SyncBackendHostNoReturn : public SyncBackendHostMock {
100  virtual void Initialize(
101      sync_driver::SyncFrontend* frontend,
102      scoped_ptr<base::Thread> sync_thread,
103      const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
104      const GURL& service_url,
105      const syncer::SyncCredentials& credentials,
106      bool delete_sync_data_folder,
107      scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
108      scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
109      syncer::ReportUnrecoverableErrorFunction
110          report_unrecoverable_error_function,
111      syncer::NetworkResources* network_resources) OVERRIDE {}
112};
113
114class SyncBackendHostMockCollectDeleteDirParam : public SyncBackendHostMock {
115 public:
116  explicit SyncBackendHostMockCollectDeleteDirParam(
117      std::vector<bool>* delete_dir_param)
118     : delete_dir_param_(delete_dir_param) {}
119
120  virtual void Initialize(
121      sync_driver::SyncFrontend* frontend,
122      scoped_ptr<base::Thread> sync_thread,
123      const syncer::WeakHandle<syncer::JsEventHandler>& event_handler,
124      const GURL& service_url,
125      const syncer::SyncCredentials& credentials,
126      bool delete_sync_data_folder,
127      scoped_ptr<syncer::SyncManagerFactory> sync_manager_factory,
128      scoped_ptr<syncer::UnrecoverableErrorHandler> unrecoverable_error_handler,
129      syncer::ReportUnrecoverableErrorFunction
130          report_unrecoverable_error_function,
131      syncer::NetworkResources* network_resources) OVERRIDE {
132    delete_dir_param_->push_back(delete_sync_data_folder);
133    SyncBackendHostMock::Initialize(frontend, sync_thread.Pass(),
134                                    event_handler, service_url, credentials,
135                                    delete_sync_data_folder,
136                                    sync_manager_factory.Pass(),
137                                    unrecoverable_error_handler.Pass(),
138                                    report_unrecoverable_error_function,
139                                    network_resources);
140  }
141
142 private:
143  std::vector<bool>* delete_dir_param_;
144};
145
146ACTION(ReturnNewSyncBackendHostMock) {
147  return new browser_sync::SyncBackendHostMock();
148}
149
150ACTION(ReturnNewSyncBackendHostNoReturn) {
151  return new browser_sync::SyncBackendHostNoReturn();
152}
153
154ACTION_P(ReturnNewMockHostCollectDeleteDirParam, delete_dir_param) {
155  return new browser_sync::SyncBackendHostMockCollectDeleteDirParam(
156      delete_dir_param);
157}
158
159KeyedService* BuildFakeProfileInvalidationProvider(
160    content::BrowserContext* context) {
161  return new invalidation::ProfileInvalidationProvider(
162      scoped_ptr<invalidation::InvalidationService>(
163          new invalidation::FakeInvalidationService));
164}
165
166// A test harness that uses a real ProfileSyncService and in most cases a
167// MockSyncBackendHost.
168//
169// This is useful if we want to test the ProfileSyncService and don't care about
170// testing the SyncBackendHost.
171class ProfileSyncServiceTest : public ::testing::Test {
172 protected:
173  ProfileSyncServiceTest()
174      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
175        profile_manager_(TestingBrowserProcess::GetGlobal()) {}
176  virtual ~ProfileSyncServiceTest() {}
177
178  virtual void SetUp() OVERRIDE {
179    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
180        switches::kSyncDeferredStartupTimeoutSeconds, "0");
181
182    CHECK(profile_manager_.SetUp());
183
184    TestingProfile::TestingFactories testing_facotries;
185    testing_facotries.push_back(
186            std::make_pair(ProfileOAuth2TokenServiceFactory::GetInstance(),
187                           BuildAutoIssuingFakeProfileOAuth2TokenService));
188    testing_facotries.push_back(
189            std::make_pair(
190                invalidation::ProfileInvalidationProviderFactory::GetInstance(),
191                BuildFakeProfileInvalidationProvider));
192
193    profile_ = profile_manager_.CreateTestingProfile(
194        "sync-service-test", scoped_ptr<PrefServiceSyncable>(),
195        base::UTF8ToUTF16("sync-service-test"), 0, std::string(),
196        testing_facotries);
197  }
198
199  virtual void TearDown() OVERRIDE {
200    // Kill the service before the profile.
201    if (service_)
202      service_->Shutdown();
203
204    service_.reset();
205  }
206
207  void IssueTestTokens() {
208    ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
209        ->UpdateCredentials("test", "oauth2_login_token");
210  }
211
212  void CreateService(ProfileSyncServiceStartBehavior behavior) {
213    SigninManagerBase* signin =
214        SigninManagerFactory::GetForProfile(profile_);
215    signin->SetAuthenticatedUsername("test");
216    ProfileOAuth2TokenService* oauth2_token_service =
217        ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
218    components_factory_ = new ProfileSyncComponentsFactoryMock();
219    service_.reset(new ProfileSyncService(
220        scoped_ptr<ProfileSyncComponentsFactory>(components_factory_),
221        profile_,
222        make_scoped_ptr(new SupervisedUserSigninManagerWrapper(profile_,
223                                                               signin)),
224        oauth2_token_service,
225        behavior));
226    service_->SetClearingBrowseringDataForTesting(
227        base::Bind(&ProfileSyncServiceTest::ClearBrowsingDataCallback,
228                   base::Unretained(this)));
229  }
230
231#if defined(OS_WIN) || defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
232  void CreateServiceWithoutSignIn() {
233    CreateService(browser_sync::AUTO_START);
234    SigninManagerFactory::GetForProfile(profile())->SignOut(
235        signin_metrics::SIGNOUT_TEST);
236  }
237#endif
238
239  void ShutdownAndDeleteService() {
240    if (service_)
241      service_->Shutdown();
242    service_.reset();
243  }
244
245  void InitializeForNthSync() {
246    // Set first sync time before initialize to disable backup.
247    sync_driver::SyncPrefs sync_prefs(service()->profile()->GetPrefs());
248    sync_prefs.SetFirstSyncTime(base::Time::Now());
249    service_->Initialize();
250  }
251
252  void InitializeForFirstSync() {
253    service_->Initialize();
254  }
255
256  void ExpectDataTypeManagerCreation(int times) {
257    EXPECT_CALL(*components_factory_, CreateDataTypeManager(_, _, _, _, _))
258        .Times(times)
259        .WillRepeatedly(ReturnNewDataTypeManager());
260  }
261
262  void ExpectSyncBackendHostCreation(int times) {
263    EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _))
264        .Times(times)
265        .WillRepeatedly(ReturnNewSyncBackendHostMock());
266  }
267
268  void ExpectSyncBackendHostCreationCollectDeleteDir(
269      int times, std::vector<bool> *delete_dir_param) {
270    EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _))
271        .Times(times)
272        .WillRepeatedly(ReturnNewMockHostCollectDeleteDirParam(
273            delete_dir_param));
274  }
275
276  void PrepareDelayedInitSyncBackendHost() {
277    EXPECT_CALL(*components_factory_, CreateSyncBackendHost(_, _, _, _, _)).
278        WillOnce(ReturnNewSyncBackendHostNoReturn());
279  }
280
281  TestingProfile* profile() {
282    return profile_;
283  }
284
285  ProfileSyncService* service() {
286    return service_.get();
287  }
288
289  ProfileSyncComponentsFactoryMock* components_factory() {
290    return components_factory_;
291  }
292
293  void ClearBrowsingDataCallback(BrowsingDataRemover::Observer* observer,
294                                 Profile* profile,
295                                 base::Time start,
296                                 base::Time end) {
297    EXPECT_EQ(profile_, profile);
298    clear_browsing_date_start_ = start;
299  }
300
301 protected:
302  void PumpLoop() {
303    base::RunLoop run_loop;
304    base::MessageLoop::current()->PostTask(
305        FROM_HERE, run_loop.QuitClosure());
306    run_loop.Run();
307  }
308
309  // The requested start time when ClearBrowsingDataCallback is called.
310  base::Time clear_browsing_date_start_;
311
312 private:
313  content::TestBrowserThreadBundle thread_bundle_;
314  TestingProfileManager profile_manager_;
315  TestingProfile* profile_;
316  scoped_ptr<ProfileSyncService> service_;
317
318  // Pointer to the components factory.  Not owned.  May be null.
319  ProfileSyncComponentsFactoryMock* components_factory_;
320};
321
322// Verify that the server URLs are sane.
323TEST_F(ProfileSyncServiceTest, InitialState) {
324  CreateService(browser_sync::AUTO_START);
325  InitializeForNthSync();
326  const std::string& url = service()->sync_service_url().spec();
327  EXPECT_TRUE(url == ProfileSyncService::kSyncServerUrl ||
328              url == ProfileSyncService::kDevServerUrl);
329}
330
331// Verify a successful initialization.
332TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) {
333  profile()->GetTestingPrefService()->SetManagedPref(
334      sync_driver::prefs::kSyncManaged, new base::FundamentalValue(false));
335  IssueTestTokens();
336  CreateService(browser_sync::AUTO_START);
337  ExpectDataTypeManagerCreation(1);
338  ExpectSyncBackendHostCreation(1);
339  InitializeForNthSync();
340  EXPECT_FALSE(service()->IsManaged());
341  EXPECT_TRUE(service()->sync_initialized());
342  EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
343}
344
345
346// Verify that the SetSetupInProgress function call updates state
347// and notifies observers.
348TEST_F(ProfileSyncServiceTest, SetupInProgress) {
349  CreateService(browser_sync::AUTO_START);
350  InitializeForNthSync();
351
352  TestProfileSyncServiceObserver observer(service());
353  service()->AddObserver(&observer);
354
355  service()->SetSetupInProgress(true);
356  EXPECT_TRUE(observer.first_setup_in_progress());
357  service()->SetSetupInProgress(false);
358  EXPECT_FALSE(observer.first_setup_in_progress());
359
360  service()->RemoveObserver(&observer);
361}
362
363// Verify that disable by enterprise policy works.
364TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) {
365  profile()->GetTestingPrefService()->SetManagedPref(
366      sync_driver::prefs::kSyncManaged, new base::FundamentalValue(true));
367  IssueTestTokens();
368  CreateService(browser_sync::AUTO_START);
369  InitializeForNthSync();
370  EXPECT_TRUE(service()->IsManaged());
371  EXPECT_FALSE(service()->sync_initialized());
372}
373
374// Verify that disable by enterprise policy works even after the backend has
375// been initialized.
376TEST_F(ProfileSyncServiceTest, DisabledByPolicyAfterInit) {
377  IssueTestTokens();
378  CreateService(browser_sync::AUTO_START);
379  ExpectDataTypeManagerCreation(1);
380  ExpectSyncBackendHostCreation(1);
381  InitializeForNthSync();
382
383  EXPECT_FALSE(service()->IsManaged());
384  EXPECT_TRUE(service()->sync_initialized());
385
386  profile()->GetTestingPrefService()->SetManagedPref(
387      sync_driver::prefs::kSyncManaged, new base::FundamentalValue(true));
388
389  EXPECT_TRUE(service()->IsManaged());
390  EXPECT_FALSE(service()->sync_initialized());
391}
392
393// Exercies the ProfileSyncService's code paths related to getting shut down
394// before the backend initialize call returns.
395TEST_F(ProfileSyncServiceTest, AbortedByShutdown) {
396  CreateService(browser_sync::AUTO_START);
397  PrepareDelayedInitSyncBackendHost();
398
399  IssueTestTokens();
400  InitializeForNthSync();
401  EXPECT_FALSE(service()->sync_initialized());
402
403  ShutdownAndDeleteService();
404}
405
406// Test StopAndSuppress() before we've initialized the backend.
407TEST_F(ProfileSyncServiceTest, EarlyStopAndSuppress) {
408  CreateService(browser_sync::AUTO_START);
409  IssueTestTokens();
410
411  service()->StopAndSuppress();
412  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
413      sync_driver::prefs::kSyncSuppressStart));
414
415  // Because of supression, this should fail.
416  InitializeForNthSync();
417  EXPECT_FALSE(service()->sync_initialized());
418
419  // Remove suppression.  This should be enough to allow init to happen.
420  ExpectDataTypeManagerCreation(1);
421  ExpectSyncBackendHostCreation(1);
422  service()->UnsuppressAndStart();
423  EXPECT_TRUE(service()->sync_initialized());
424  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
425      sync_driver::prefs::kSyncSuppressStart));
426}
427
428// Test StopAndSuppress() after we've initialized the backend.
429TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) {
430  CreateService(browser_sync::AUTO_START);
431  IssueTestTokens();
432  ExpectDataTypeManagerCreation(1);
433  ExpectSyncBackendHostCreation(1);
434  InitializeForNthSync();
435
436  EXPECT_TRUE(service()->sync_initialized());
437  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
438      sync_driver::prefs::kSyncSuppressStart));
439
440  testing::Mock::VerifyAndClearExpectations(components_factory());
441
442  service()->StopAndSuppress();
443  EXPECT_FALSE(service()->sync_initialized());
444  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
445      sync_driver::prefs::kSyncSuppressStart));
446
447  ExpectDataTypeManagerCreation(1);
448  ExpectSyncBackendHostCreation(1);
449
450  service()->UnsuppressAndStart();
451  EXPECT_TRUE(service()->sync_initialized());
452  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
453      sync_driver::prefs::kSyncSuppressStart));
454}
455
456// Certain ProfileSyncService tests don't apply to Chrome OS, for example
457// things that deal with concepts like "signing out" and policy.
458#if !defined (OS_CHROMEOS)
459TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOut) {
460  CreateService(browser_sync::AUTO_START);
461  ExpectDataTypeManagerCreation(1);
462  ExpectSyncBackendHostCreation(1);
463  IssueTestTokens();
464  InitializeForNthSync();
465
466  EXPECT_TRUE(service()->sync_initialized());
467  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
468      sync_driver::prefs::kSyncSuppressStart));
469
470  SigninManagerFactory::GetForProfile(profile())->SignOut(
471      signin_metrics::SIGNOUT_TEST);
472  EXPECT_FALSE(service()->sync_initialized());
473}
474#endif  // !defined(OS_CHROMEOS)
475
476TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) {
477  CreateService(browser_sync::AUTO_START);
478  IssueTestTokens();
479  ExpectDataTypeManagerCreation(1);
480  ExpectSyncBackendHostCreation(1);
481  InitializeForNthSync();
482
483  // Initial status.
484  ProfileSyncService::SyncTokenStatus token_status =
485      service()->GetSyncTokenStatus();
486  EXPECT_EQ(syncer::CONNECTION_NOT_ATTEMPTED, token_status.connection_status);
487  EXPECT_TRUE(token_status.connection_status_update_time.is_null());
488  EXPECT_TRUE(token_status.token_request_time.is_null());
489  EXPECT_TRUE(token_status.token_receive_time.is_null());
490
491  // Simulate an auth error.
492  service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR);
493
494  // The token request will take the form of a posted task.  Run it.
495  base::RunLoop loop;
496  loop.RunUntilIdle();
497
498  token_status = service()->GetSyncTokenStatus();
499  EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR, token_status.connection_status);
500  EXPECT_FALSE(token_status.connection_status_update_time.is_null());
501  EXPECT_FALSE(token_status.token_request_time.is_null());
502  EXPECT_FALSE(token_status.token_receive_time.is_null());
503  EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
504            token_status.last_get_token_error);
505  EXPECT_TRUE(token_status.next_token_request_time.is_null());
506
507  // Simulate successful connection.
508  service()->OnConnectionStatusChange(syncer::CONNECTION_OK);
509  token_status = service()->GetSyncTokenStatus();
510  EXPECT_EQ(syncer::CONNECTION_OK, token_status.connection_status);
511}
512
513#if defined(ENABLE_PRE_SYNC_BACKUP)
514TEST_F(ProfileSyncServiceTest, DontStartBackupOnBrowserStart) {
515  CreateServiceWithoutSignIn();
516  InitializeForFirstSync();
517  PumpLoop();
518  EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
519}
520
521TEST_F(ProfileSyncServiceTest, BackupBeforeFirstSync) {
522  CreateServiceWithoutSignIn();
523  ExpectDataTypeManagerCreation(2);
524  std::vector<bool> delete_dir_param;
525  ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param);
526  InitializeForFirstSync();
527
528  SigninManagerFactory::GetForProfile(profile())
529      ->SetAuthenticatedUsername("test");
530  IssueTestTokens();
531  PumpLoop();
532
533  // At this time, backup is finished. Task is posted to start sync again.
534  EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
535  EXPECT_TRUE(service()->ShouldPushChanges());
536  EXPECT_EQ(1u, delete_dir_param.size());
537  EXPECT_TRUE(delete_dir_param[0]);
538
539  // Pump loop to start sync.
540  PumpLoop();
541  EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
542  EXPECT_EQ(2u, delete_dir_param.size());
543  EXPECT_TRUE(delete_dir_param[0]);
544}
545
546// Test backup is done again on browser start if user signed in last session
547// but backup didn't finish when last session was closed.
548TEST_F(ProfileSyncServiceTest, ResumeBackupIfAborted) {
549  IssueTestTokens();
550  CreateService(AUTO_START);
551  ExpectDataTypeManagerCreation(2);
552  std::vector<bool> delete_dir_param;
553  ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param);
554  InitializeForFirstSync();
555  PumpLoop();
556
557  // At this time, backup is finished. Task is posted to start sync again.
558  EXPECT_EQ(ProfileSyncService::BACKUP, service()->backend_mode());
559  EXPECT_TRUE(service()->ShouldPushChanges());
560  EXPECT_EQ(1u, delete_dir_param.size());
561  EXPECT_TRUE(delete_dir_param[0]);
562
563  // Pump loop to start sync.
564  PumpLoop();
565  EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
566  EXPECT_EQ(2u, delete_dir_param.size());
567  EXPECT_TRUE(delete_dir_param[0]);
568}
569
570TEST_F(ProfileSyncServiceTest, Rollback) {
571  CreateService(browser_sync::MANUAL_START);
572  service()->SetSyncSetupCompleted();
573  ExpectDataTypeManagerCreation(2);
574  std::vector<bool> delete_dir_param;
575  ExpectSyncBackendHostCreationCollectDeleteDir(2, &delete_dir_param);
576  IssueTestTokens();
577  InitializeForNthSync();
578  EXPECT_TRUE(service()->sync_initialized());
579  EXPECT_EQ(ProfileSyncService::SYNC, service()->backend_mode());
580
581  // First sync time should be recorded.
582  sync_driver::SyncPrefs sync_prefs(service()->profile()->GetPrefs());
583  base::Time first_sync_time = sync_prefs.GetFirstSyncTime();
584  EXPECT_FALSE(first_sync_time.is_null());
585
586  syncer::SyncProtocolError client_cmd;
587  client_cmd.action = syncer::DISABLE_SYNC_AND_ROLLBACK;
588  service()->OnActionableError(client_cmd);
589  EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
590
591  // Pump loop to run rollback.
592  PumpLoop();
593  EXPECT_EQ(ProfileSyncService::ROLLBACK, service()->backend_mode());
594
595  // Browser data should be cleared during rollback.
596  EXPECT_EQ(first_sync_time, clear_browsing_date_start_);
597
598  client_cmd.action = syncer::ROLLBACK_DONE;
599  service()->OnActionableError(client_cmd);
600  EXPECT_EQ(ProfileSyncService::IDLE, service()->backend_mode());
601
602  // First sync time is erased after rollback is done.
603  EXPECT_TRUE(sync_prefs.GetFirstSyncTime().is_null());
604
605  EXPECT_EQ(2u, delete_dir_param.size());
606  EXPECT_FALSE(delete_dir_param[0]);
607  EXPECT_FALSE(delete_dir_param[1]);
608}
609
610#endif
611
612TEST_F(ProfileSyncServiceTest, GetSyncServiceURL) {
613  // See that we can override the URL with a flag.
614  CommandLine command_line(
615      base::FilePath(base::FilePath(FILE_PATH_LITERAL("chrome.exe"))));
616  command_line.AppendSwitchASCII(switches::kSyncServiceURL, "https://foo/bar");
617  EXPECT_EQ("https://foo/bar",
618            ProfileSyncService::GetSyncServiceURL(command_line).spec());
619}
620
621// Verify that LastSyncedTime is cleared when the user signs out.
622TEST_F(ProfileSyncServiceTest, ClearLastSyncedTimeOnSignOut) {
623  IssueTestTokens();
624  CreateService(AUTO_START);
625  ExpectDataTypeManagerCreation(1);
626  ExpectSyncBackendHostCreation(1);
627  InitializeForNthSync();
628  EXPECT_TRUE(service()->sync_initialized());
629  EXPECT_EQ(l10n_util::GetStringUTF16(IDS_SYNC_TIME_JUST_NOW),
630            service()->GetLastSyncedTimeString());
631
632  // Sign out.
633  service()->DisableForUser();
634  PumpLoop();
635
636  EXPECT_EQ(l10n_util::GetStringUTF16(IDS_SYNC_TIME_NEVER),
637            service()->GetLastSyncedTimeString());
638}
639
640}  // namespace
641}  // namespace browser_sync
642