Home | History | Annotate | Download | only in integration
      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 "base/command_line.h"
      6 #include "base/files/file_util.h"
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "base/run_loop.h"
     10 #include "base/test/test_timeouts.h"
     11 #include "chrome/browser/browsing_data/browsing_data_remover.h"
     12 #include "chrome/browser/profiles/profile.h"
     13 #include "chrome/browser/sync/profile_sync_service.h"
     14 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
     15 #include "chrome/browser/sync/test/integration/preferences_helper.h"
     16 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
     17 #include "chrome/browser/sync/test/integration/sync_test.h"
     18 #include "chrome/common/chrome_switches.h"
     19 #include "chrome/common/pref_names.h"
     20 #include "components/bookmarks/browser/bookmark_model.h"
     21 #include "sync/internal_api/public/util/sync_db_util.h"
     22 #include "sync/test/fake_server/fake_server_verifier.h"
     23 #include "sync/util/time.h"
     24 
     25 using bookmarks_helper::AddFolder;
     26 using bookmarks_helper::AddURL;
     27 using bookmarks_helper::GetOtherNode;
     28 using bookmarks_helper::ModelMatchesVerifier;
     29 using bookmarks_helper::Move;
     30 using bookmarks_helper::Remove;
     31 using sync_integration_test_util::AwaitCommitActivityCompletion;
     32 
     33 namespace {
     34 const char kUrl1[] = "http://www.google.com";
     35 const char kUrl2[] = "http://map.google.com";
     36 const char kUrl3[] = "http://plus.google.com";
     37 }  // anonymous namespace
     38 
     39 class SingleClientBackupRollbackTest : public SyncTest {
     40  public:
     41   SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {}
     42   virtual ~SingleClientBackupRollbackTest() {}
     43 
     44   void DisableBackup() {
     45     CommandLine::ForCurrentProcess()->AppendSwitch(
     46           switches::kSyncDisableBackup);
     47   }
     48 
     49   void DisableRollback() {
     50     CommandLine::ForCurrentProcess()->AppendSwitch(
     51           switches::kSyncDisableRollback);
     52   }
     53 
     54   base::Time GetBackupDbLastModified() {
     55     base::RunLoop run_loop;
     56 
     57     base::Time backup_time;
     58     syncer::CheckSyncDbLastModifiedTime(
     59         GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
     60         base::MessageLoopProxy::current(),
     61         base::Bind(&SingleClientBackupRollbackTest::CheckDbCallback,
     62                    base::Unretained(this), &backup_time));
     63     base::MessageLoopProxy::current()->PostTask(
     64         FROM_HERE, run_loop.QuitClosure());
     65     run_loop.Run();
     66     return backup_time;
     67   }
     68 
     69  private:
     70   void CheckDbCallback(base::Time* time_out, base::Time time_in) {
     71     *time_out = syncer::ProtoTimeToTime(syncer::TimeToProtoTime(time_in));
     72   }
     73 
     74   DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest);
     75 };
     76 
     77 // Waits until the ProfileSyncService's backend is in IDLE mode.
     78 class SyncBackendStoppedChecker : public ProfileSyncServiceBase::Observer {
     79  public:
     80   explicit SyncBackendStoppedChecker(ProfileSyncService* service)
     81       : pss_(service),
     82         timeout_(TestTimeouts::action_max_timeout()),
     83         done_(false) {}
     84 
     85   virtual void OnStateChanged() OVERRIDE {
     86     if (ProfileSyncService::IDLE == pss_->backend_mode()) {
     87       done_ = true;
     88       run_loop_.Quit();
     89     }
     90   }
     91 
     92   bool Wait() {
     93     pss_->AddObserver(this);
     94     if (ProfileSyncService::IDLE == pss_->backend_mode())
     95       return true;
     96     base::MessageLoop::current()->PostDelayedTask(
     97         FROM_HERE,
     98         run_loop_.QuitClosure(),
     99         timeout_);
    100     run_loop_.Run();
    101     pss_->RemoveObserver(this);
    102     return done_;
    103   }
    104 
    105  private:
    106 
    107   ProfileSyncService* const pss_;
    108   const base::TimeDelta timeout_;
    109   base::RunLoop run_loop_;
    110   bool done_;
    111 };
    112 
    113 // Waits until a rollback finishes.
    114 class SyncRollbackChecker : public ProfileSyncServiceBase::Observer,
    115                             public BrowsingDataRemover::Observer {
    116  public:
    117   explicit SyncRollbackChecker(ProfileSyncService* service)
    118       : pss_(service),
    119         timeout_(TestTimeouts::action_max_timeout()),
    120         rollback_started_(false),
    121         clear_done_(false) {}
    122 
    123   // ProfileSyncServiceBase::Observer implementation.
    124   virtual void OnStateChanged() OVERRIDE {
    125     if (ProfileSyncService::ROLLBACK == pss_->backend_mode()) {
    126       rollback_started_ = true;
    127       if (clear_done_)
    128         run_loop_.Quit();
    129     }
    130   }
    131 
    132   // BrowsingDataRemoverObserver::Observer implementation.
    133   virtual void OnBrowsingDataRemoverDone() OVERRIDE {
    134     clear_done_ = true;
    135     if (rollback_started_) {
    136       run_loop_.Quit();
    137     }
    138   }
    139 
    140   bool Wait() {
    141     pss_->AddObserver(this);
    142     pss_->SetBrowsingDataRemoverObserverForTesting(this);
    143     base::MessageLoop::current()->PostDelayedTask(
    144         FROM_HERE,
    145         run_loop_.QuitClosure(),
    146         timeout_);
    147     run_loop_.Run();
    148     pss_->RemoveObserver(this);
    149     return rollback_started_ && clear_done_;
    150   }
    151 
    152   ProfileSyncService* const pss_;
    153   const base::TimeDelta timeout_;
    154   base::RunLoop run_loop_;
    155   bool rollback_started_;
    156   bool clear_done_;
    157 };
    158 
    159 #if defined(ENABLE_PRE_SYNC_BACKUP)
    160 #define MAYBE_TestBackup TestBackup
    161 #else
    162 #define MAYBE_TestBackup DISABLED_TestBackup
    163 #endif
    164 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    165                        MAYBE_TestBackup) {
    166   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
    167 
    168   // Setup sync, wait for its completion, and make sure changes were synced.
    169   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    170   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    171   ASSERT_TRUE(ModelMatchesVerifier(0));
    172 
    173   // Verify backup DB is created and backup time is set on device info.
    174   base::Time backup_time = GetBackupDbLastModified();
    175   ASSERT_FALSE(backup_time.is_null());
    176   ASSERT_EQ(backup_time, GetSyncService(0)->GetDeviceBackupTimeForTesting());
    177 }
    178 
    179 #if defined(ENABLE_PRE_SYNC_BACKUP)
    180 #define MAYBE_TestBackupDisabled TestBackupDisabled
    181 #else
    182 #define MAYBE_TestBackupDisabled DISABLED_TestBackupDisabled
    183 #endif
    184 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    185                        MAYBE_TestBackupDisabled) {
    186   DisableBackup();
    187 
    188   // Setup sync, wait for its completion, and make sure changes were synced.
    189   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    190   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    191   ASSERT_TRUE(ModelMatchesVerifier(0));
    192 
    193   // Verify backup DB is not created and backup time is not set on device info.
    194   ASSERT_FALSE(base::PathExists(
    195       GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup"))));
    196   ASSERT_TRUE(GetSyncService(0)->GetDeviceBackupTimeForTesting().is_null());
    197 }
    198 
    199 #if defined(ENABLE_PRE_SYNC_BACKUP)
    200 #define MAYBE_TestRollback TestRollback
    201 #else
    202 #define MAYBE_TestRollback DISABLED_TestRollback
    203 #endif
    204 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    205                        MAYBE_TestRollback) {
    206   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
    207 
    208   // Starting state:
    209   // other_node
    210   //    -> top
    211   //      -> tier1_a
    212   //        -> http://mail.google.com  "tier1_a_url0"
    213   //      -> tier1_b
    214   //        -> http://www.nhl.com "tier1_b_url0"
    215   const BookmarkNode* top = AddFolder(0, GetOtherNode(0), 0, "top");
    216   const BookmarkNode* tier1_a = AddFolder(0, top, 0, "tier1_a");
    217   const BookmarkNode* tier1_b = AddFolder(0, top, 1, "tier1_b");
    218   ASSERT_TRUE(AddURL(0, tier1_a, 0, "tier1_a_url0",
    219                      GURL("http://mail.google.com")));
    220   ASSERT_TRUE(AddURL(0, tier1_b, 0, "tier1_b_url0",
    221                      GURL("http://www.nhl.com")));
    222 
    223   // Setup sync, wait for its completion, and make sure changes were synced.
    224   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    225   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    226   ASSERT_TRUE(ModelMatchesVerifier(0));
    227 
    228   // Made bookmark changes while sync is on.
    229   Move(0, tier1_a->GetChild(0), tier1_b, 1);
    230   Remove(0, tier1_b, 0);
    231   ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c"));
    232   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    233   ASSERT_TRUE(ModelMatchesVerifier(0));
    234 
    235   // Let server to return rollback command on next sync request.
    236   GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
    237 
    238   // Make another change to trigger downloading of rollback command.
    239   Remove(0, tier1_b, 0);
    240 
    241   // Wait for rollback to finish and sync backend is completely shut down.
    242   SyncRollbackChecker rollback_checker(GetSyncService(0));
    243   ASSERT_TRUE(rollback_checker.Wait());
    244   SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
    245   ASSERT_TRUE(shutdown_checker.Wait());
    246 
    247   // Verify bookmarks are restored.
    248   ASSERT_EQ(1, tier1_a->child_count());
    249   const BookmarkNode* url1 = tier1_a->GetChild(0);
    250   ASSERT_EQ(GURL("http://mail.google.com"), url1->url());
    251 
    252   ASSERT_EQ(1, tier1_b->child_count());
    253   const BookmarkNode* url2 = tier1_b->GetChild(0);
    254   ASSERT_EQ(GURL("http://www.nhl.com"), url2->url());
    255 }
    256 
    257 #if defined(ENABLE_PRE_SYNC_BACKUP)
    258 #define MAYBE_TestRollbackDisabled TestRollbackDisabled
    259 #else
    260 #define MAYBE_TestRollbackDisabled DISABLED_TestRollbackDisabled
    261 #endif
    262 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    263                        MAYBE_TestRollbackDisabled) {
    264   DisableRollback();
    265 
    266   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
    267 
    268   // Starting state:
    269   // other_node
    270   //    -> http://mail.google.com  "url0"
    271   //    -> http://www.nhl.com "url1"
    272   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
    273                      GURL("http://mail.google.com")));
    274   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
    275                      GURL("http://www.nhl.com")));
    276 
    277   // Setup sync, wait for its completion, and make sure changes were synced.
    278   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    279   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    280   ASSERT_TRUE(ModelMatchesVerifier(0));
    281 
    282   // Made bookmark changes while sync is on.
    283   Remove(0, GetOtherNode(0), 1);
    284   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2",
    285                      GURL("http://www.yahoo.com")));
    286   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
    287   ASSERT_TRUE(ModelMatchesVerifier(0));
    288 
    289   // Let server to return rollback command on next sync request.
    290   GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
    291 
    292   // Make another change to trigger downloading of rollback command.
    293   Remove(0, GetOtherNode(0), 0);
    294 
    295   // Wait for sync backend is completely shut down.
    296   SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
    297   ASSERT_TRUE(shutdown_checker.Wait());
    298 
    299   // With rollback disabled, bookmarks in backup DB should not be restored.
    300   // Only bookmark added during sync is present.
    301   ASSERT_EQ(1, GetOtherNode(0)->child_count());
    302   ASSERT_EQ(GURL("http://www.yahoo.com"),
    303             GetOtherNode(0)->GetChild(0)->url());
    304 }
    305 
    306 #if defined(ENABLE_PRE_SYNC_BACKUP)
    307 #define MAYBE_TestSyncDisabled TestSyncDisabled
    308 #else
    309 #define MAYBE_TestSyncDisabled DISABLED_TestSyncDisabled
    310 #endif
    311 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    312                        MAYBE_TestSyncDisabled) {
    313   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
    314 
    315   // Starting state:
    316   // other_node
    317   //    -> http://mail.google.com  "url0"
    318   //    -> http://www.nhl.com "url1"
    319   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
    320                      GURL("http://mail.google.com")));
    321   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
    322                      GURL("http://www.nhl.com")));
    323 
    324   // Setup sync, wait for its completion, and make sure changes were synced.
    325   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    326   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    327   ASSERT_TRUE(ModelMatchesVerifier(0));
    328 
    329   // Made bookmark changes while sync is on.
    330   Remove(0, GetOtherNode(0), 1);
    331   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2",
    332                      GURL("http://www.yahoo.com")));
    333   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
    334   ASSERT_TRUE(ModelMatchesVerifier(0));
    335 
    336   // Let server to return birthday error on next sync request.
    337   GetFakeServer()->TriggerError(sync_pb::SyncEnums::NOT_MY_BIRTHDAY);
    338 
    339   // Make another change to trigger downloading of rollback command.
    340   Remove(0, GetOtherNode(0), 0);
    341 
    342   // Wait sync backend is completely shut down.
    343   SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
    344   ASSERT_TRUE(shutdown_checker.Wait());
    345 
    346   // Shouldn't restore bookmarks with sign-out only.
    347   ASSERT_EQ(1, GetOtherNode(0)->child_count());
    348   ASSERT_EQ(GURL("http://www.yahoo.com"),
    349             GetOtherNode(0)->GetChild(0)->url());
    350 }
    351 
    352 #if defined(ENABLE_PRE_SYNC_BACKUP)
    353 #define MAYBE_RollbackNoBackup RollbackNoBackup
    354 #else
    355 #define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup
    356 #endif
    357 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    358                        MAYBE_RollbackNoBackup) {
    359   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
    360 
    361   // Starting state:
    362   // other_node
    363   //    -> http://mail.google.com  "url0"
    364   //    -> http://www.nhl.com "url1"
    365   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
    366                      GURL("http://mail.google.com")));
    367 
    368   // Setup sync, wait for its completion, and make sure changes were synced.
    369   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    370   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
    371   ASSERT_TRUE(ModelMatchesVerifier(0));
    372 
    373   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
    374                      GURL("http://www.nhl.com")));
    375 
    376   // Delete backup DB.
    377   base::DeleteFile(
    378       GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
    379       true);
    380 
    381   // Let server to return rollback command on next sync request.
    382   GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
    383 
    384   // Make another change to trigger downloading of rollback command.
    385   Remove(0, GetOtherNode(0), 0);
    386 
    387   // Wait for rollback to finish and sync backend is completely shut down.
    388   SyncRollbackChecker rollback_checker(GetSyncService(0));
    389   ASSERT_TRUE(rollback_checker.Wait());
    390   SyncBackendStoppedChecker checker(GetSyncService(0));
    391   ASSERT_TRUE(checker.Wait());
    392 
    393   // Without backup DB, bookmarks remain at the state when sync stops.
    394   ASSERT_EQ(1, GetOtherNode(0)->child_count());
    395   ASSERT_EQ(GURL("http://www.nhl.com"),
    396             GetOtherNode(0)->GetChild(0)->url());
    397 }
    398 
    399 #if defined(ENABLE_PRE_SYNC_BACKUP)
    400 #define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering
    401 #else
    402 #define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering
    403 #endif
    404 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
    405                        MAYBE_DontChangeBookmarkOrdering) {
    406   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
    407 
    408   const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test");
    409   ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1)));
    410   ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2)));
    411   ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3)));
    412 
    413   // Setup sync, wait for its completion, and make sure changes were synced.
    414   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
    415   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    416   ASSERT_TRUE(ModelMatchesVerifier(0));
    417 
    418   // Made bookmark changes while sync is on.
    419   Remove(0, sub_folder, 0);
    420   Remove(0, sub_folder, 0);
    421   ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
    422   ASSERT_TRUE(ModelMatchesVerifier(0));
    423 
    424   // Let server to return rollback command on next sync request.
    425   GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
    426 
    427   // Make another change to trigger downloading of rollback command.
    428   Remove(0, sub_folder, 0);
    429 
    430   // Wait for rollback to finish and sync backend is completely shut down.
    431   SyncRollbackChecker rollback_checker(GetSyncService(0));
    432   ASSERT_TRUE(rollback_checker.Wait());
    433   SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
    434   ASSERT_TRUE(shutdown_checker.Wait());
    435 
    436   // Verify bookmarks are unchanged.
    437   ASSERT_EQ(3, sub_folder->child_count());
    438   ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url());
    439   ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url());
    440   ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url());
    441 }
    442