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/message_loop/message_loop.h" 7 #include "base/prefs/pref_service.h" 8 #include "chrome/browser/profiles/profile.h" 9 #include "chrome/browser/sync/profile_sync_service.h" 10 #include "chrome/browser/sync/test/integration/bookmarks_helper.h" 11 #include "chrome/browser/sync/test/integration/preferences_helper.h" 12 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h" 13 #include "chrome/browser/sync/test/integration/sync_test.h" 14 #include "chrome/common/chrome_switches.h" 15 #include "chrome/common/pref_names.h" 16 #include "components/bookmarks/browser/bookmark_model.h" 17 #include "sync/test/fake_server/fake_server_verifier.h" 18 19 using bookmarks_helper::AddFolder; 20 using bookmarks_helper::AddURL; 21 using bookmarks_helper::GetOtherNode; 22 using bookmarks_helper::ModelMatchesVerifier; 23 using bookmarks_helper::Move; 24 using bookmarks_helper::Remove; 25 using sync_integration_test_util::AwaitCommitActivityCompletion; 26 27 namespace { 28 const char kUrl1[] = "http://www.google.com"; 29 const char kUrl2[] = "http://map.google.com"; 30 const char kUrl3[] = "http://plus.google.com"; 31 } // anonymous namespace 32 33 class SingleClientBackupRollbackTest : public SyncTest { 34 public: 35 SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {} 36 virtual ~SingleClientBackupRollbackTest() {} 37 38 void DisableBackup() { 39 CommandLine::ForCurrentProcess()->AppendSwitch( 40 switches::kSyncDisableBackup); 41 } 42 43 void EnableRollback() { 44 CommandLine::ForCurrentProcess()->AppendSwitch( 45 switches::kSyncEnableRollback); 46 } 47 48 private: 49 DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest); 50 }; 51 52 class BackupModeChecker { 53 public: 54 explicit BackupModeChecker(ProfileSyncService* service, 55 base::TimeDelta timeout) 56 : pss_(service), 57 timeout_(timeout) {} 58 59 bool Wait() { 60 expiration_ = base::TimeTicks::Now() + timeout_; 61 base::MessageLoop::current()->PostDelayedTask( 62 FROM_HERE, 63 base::Bind(&BackupModeChecker::PeriodicCheck, base::Unretained(this)), 64 base::TimeDelta::FromSeconds(1)); 65 base::MessageLoop::current()->Run(); 66 return IsBackupComplete(); 67 } 68 69 private: 70 void PeriodicCheck() { 71 if (IsBackupComplete() || base::TimeTicks::Now() > expiration_) { 72 base::MessageLoop::current()->Quit(); 73 } else { 74 base::MessageLoop::current()->PostDelayedTask( 75 FROM_HERE, 76 base::Bind(&BackupModeChecker::PeriodicCheck, base::Unretained(this)), 77 base::TimeDelta::FromSeconds(1)); 78 } 79 } 80 81 bool IsBackupComplete() { 82 return pss_->backend_mode() == ProfileSyncService::BACKUP && 83 pss_->ShouldPushChanges(); 84 } 85 86 ProfileSyncService* pss_; 87 base::TimeDelta timeout_; 88 base::TimeTicks expiration_; 89 }; 90 91 #if defined(ENABLE_PRE_SYNC_BACKUP) 92 #define MAYBE_TestBackupRollback TestBackupRollback 93 #else 94 #define MAYBE_TestBackupRollback DISABLED_TestBackupRollback 95 #endif 96 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 97 MAYBE_TestBackupRollback) { 98 EnableRollback(); 99 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 100 101 // Starting state: 102 // other_node 103 // -> top 104 // -> tier1_a 105 // -> http://mail.google.com "tier1_a_url0" 106 // -> tier1_b 107 // -> http://www.nhl.com "tier1_b_url0" 108 const BookmarkNode* top = AddFolder(0, GetOtherNode(0), 0, "top"); 109 const BookmarkNode* tier1_a = AddFolder(0, top, 0, "tier1_a"); 110 const BookmarkNode* tier1_b = AddFolder(0, top, 1, "tier1_b"); 111 ASSERT_TRUE(AddURL(0, tier1_a, 0, "tier1_a_url0", 112 GURL("http://mail.google.com"))); 113 ASSERT_TRUE(AddURL(0, tier1_b, 0, "tier1_b_url0", 114 GURL("http://www.nhl.com"))); 115 116 BackupModeChecker checker(GetSyncService(0), 117 base::TimeDelta::FromSeconds(15)); 118 ASSERT_TRUE(checker.Wait()); 119 120 // Setup sync, wait for its completion, and make sure changes were synced. 121 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 122 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 123 ASSERT_TRUE(ModelMatchesVerifier(0)); 124 125 // Made bookmark changes while sync is on. 126 Move(0, tier1_a->GetChild(0), tier1_b, 1); 127 Remove(0, tier1_b, 0); 128 ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c")); 129 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 130 ASSERT_TRUE(ModelMatchesVerifier(0)); 131 132 // Let server to return rollback command on next sync request. 133 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 134 135 // Make another change to trigger downloading of rollback command. 136 Remove(0, tier1_b, 0); 137 138 // Wait for sync to switch to backup mode after finishing rollback. 139 ASSERT_TRUE(checker.Wait()); 140 141 // Verify bookmarks are restored. 142 ASSERT_EQ(1, tier1_a->child_count()); 143 const BookmarkNode* url1 = tier1_a->GetChild(0); 144 ASSERT_EQ(GURL("http://mail.google.com"), url1->url()); 145 146 ASSERT_EQ(1, tier1_b->child_count()); 147 const BookmarkNode* url2 = tier1_b->GetChild(0); 148 ASSERT_EQ(GURL("http://www.nhl.com"), url2->url()); 149 } 150 151 #if defined(ENABLE_PRE_SYNC_BACKUP) 152 #define MAYBE_TestPrefBackupRollback TestPrefBackupRollback 153 #else 154 #define MAYBE_TestPrefBackupRollback DISABLED_TestPrefBackupRollback 155 #endif 156 // Verify local preferences are not affected by preferences in backup DB under 157 // backup mode. 158 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 159 MAYBE_TestPrefBackupRollback) { 160 EnableRollback(); 161 162 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 163 164 preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl1); 165 166 BackupModeChecker checker(GetSyncService(0), 167 base::TimeDelta::FromSeconds(15)); 168 ASSERT_TRUE(checker.Wait()); 169 170 // Shut down backup, then change preference. 171 GetSyncService(0)->StartStopBackupForTesting(); 172 preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl2); 173 174 // Restart backup. Preference shouldn't change after backup starts. 175 GetSyncService(0)->StartStopBackupForTesting(); 176 ASSERT_TRUE(checker.Wait()); 177 ASSERT_EQ(kUrl2, 178 preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage)); 179 180 // Start sync and change preference. 181 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 182 preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl3); 183 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 184 ASSERT_TRUE(ModelMatchesVerifier(0)); 185 186 // Let server return rollback command on next sync request. 187 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 188 189 // Make another change to trigger downloading of rollback command. 190 preferences_helper::ChangeStringPref(0, prefs::kHomePage, ""); 191 192 // Wait for sync to switch to backup mode after finishing rollback. 193 ASSERT_TRUE(checker.Wait()); 194 195 // Verify preference is restored. 196 ASSERT_EQ(kUrl2, 197 preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage)); 198 } 199 200 #if defined(ENABLE_PRE_SYNC_BACKUP) 201 #define MAYBE_RollbackNoBackup RollbackNoBackup 202 #else 203 #define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup 204 #endif 205 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 206 MAYBE_RollbackNoBackup) { 207 EnableRollback(); 208 209 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 210 211 // Setup sync, wait for its completion, and make sure changes were synced. 212 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 213 214 // Starting state: 215 // other_node 216 // -> http://mail.google.com "url0" 217 // -> http://www.nhl.com "url1" 218 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0", 219 GURL("http://mail.google.com"))); 220 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1", 221 GURL("http://www.nhl.com"))); 222 223 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 224 ASSERT_TRUE(ModelMatchesVerifier(0)); 225 226 // Let server to return rollback command on next sync request. 227 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 228 229 // Make another change to trigger downloading of rollback command. 230 Remove(0, GetOtherNode(0), 0); 231 232 // Wait for sync to switch to backup mode after finishing rollback. 233 BackupModeChecker checker(GetSyncService(0), 234 base::TimeDelta::FromSeconds(15)); 235 ASSERT_TRUE(checker.Wait()); 236 237 // Without backup DB, bookmarks added during sync shouldn't be removed. 238 ASSERT_EQ(1, GetOtherNode(0)->child_count()); 239 ASSERT_EQ(GURL("http://www.nhl.com"), 240 GetOtherNode(0)->GetChild(0)->url()); 241 } 242 243 #if defined(ENABLE_PRE_SYNC_BACKUP) 244 #define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering 245 #else 246 #define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering 247 #endif 248 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 249 MAYBE_DontChangeBookmarkOrdering) { 250 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 251 252 const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test"); 253 ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1))); 254 ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2))); 255 ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3))); 256 257 BackupModeChecker checker(GetSyncService(0), 258 base::TimeDelta::FromSeconds(15)); 259 ASSERT_TRUE(checker.Wait()); 260 261 // Restart backup. 262 GetSyncService(0)->StartStopBackupForTesting(); 263 GetSyncService(0)->StartStopBackupForTesting(); 264 ASSERT_TRUE(checker.Wait()); 265 266 // Verify bookmarks are unchanged. 267 ASSERT_EQ(3, sub_folder->child_count()); 268 ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url()); 269 ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url()); 270 ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url()); 271 } 272 273