two_client_typed_urls_sync_test.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/i18n/number_formatting.h" 6#include "base/memory/scoped_vector.h" 7#include "base/utf_string_conversions.h" 8#include "chrome/browser/history/history_types.h" 9#include "chrome/browser/sessions/session_service.h" 10#include "chrome/browser/sync/profile_sync_service_harness.h" 11#include "chrome/browser/sync/test/integration/bookmarks_helper.h" 12#include "chrome/browser/sync/test/integration/sync_test.h" 13#include "chrome/browser/sync/test/integration/typed_urls_helper.h" 14 15using typed_urls_helper::AddUrlToHistory; 16using typed_urls_helper::AddUrlToHistoryWithTimestamp; 17using typed_urls_helper::AddUrlToHistoryWithTransition; 18using typed_urls_helper::AreVisitsEqual; 19using typed_urls_helper::AreVisitsUnique; 20using typed_urls_helper::AssertAllProfilesHaveSameURLsAsVerifier; 21using typed_urls_helper::AssertURLRowVectorsAreEqual; 22using typed_urls_helper::DeleteUrlFromHistory; 23using typed_urls_helper::GetTypedUrlsFromClient; 24using typed_urls_helper::GetUrlFromClient; 25using typed_urls_helper::GetVisitsFromClient; 26using typed_urls_helper::RemoveVisitsFromClient; 27 28class TwoClientTypedUrlsSyncTest : public SyncTest { 29 public: 30 TwoClientTypedUrlsSyncTest() : SyncTest(TWO_CLIENT) {} 31 virtual ~TwoClientTypedUrlsSyncTest() {} 32 33 bool CheckClientsEqual() { 34 history::URLRows urls = GetTypedUrlsFromClient(0); 35 history::URLRows urls2 = GetTypedUrlsFromClient(1); 36 AssertURLRowVectorsAreEqual(urls, urls2); 37 // Now check the visits. 38 for (size_t i = 0; i < urls.size() && i < urls2.size(); i++) { 39 history::VisitVector visit1 = GetVisitsFromClient(0, urls[i].id()); 40 history::VisitVector visit2 = GetVisitsFromClient(1, urls2[i].id()); 41 if (!AreVisitsEqual(visit1, visit2)) 42 return false; 43 } 44 return true; 45 } 46 47 bool CheckNoDuplicateVisits() { 48 for (int i = 0; i < num_clients(); ++i) { 49 history::URLRows urls = GetTypedUrlsFromClient(i); 50 for (size_t j = 0; j < urls.size(); ++j) { 51 history::VisitVector visits = GetVisitsFromClient(i, urls[j].id()); 52 if (!AreVisitsUnique(visits)) 53 return false; 54 } 55 } 56 return true; 57 } 58 59 int GetVisitCountForFirstURL(int index) { 60 history::URLRows urls = GetTypedUrlsFromClient(index); 61 if (urls.size() == 0) 62 return 0; 63 else 64 return urls[0].visit_count(); 65 } 66 67 private: 68 DISALLOW_COPY_AND_ASSIGN(TwoClientTypedUrlsSyncTest); 69}; 70 71// TCM: 3728323 72IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, Add) { 73 const string16 kHistoryUrl( 74 ASCIIToUTF16("http://www.add-one-history.google.com/")); 75 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 76 77 // Populate one client with a URL, should sync to the other. 78 GURL new_url(kHistoryUrl); 79 AddUrlToHistory(0, new_url); 80 history::URLRows urls = GetTypedUrlsFromClient(0); 81 ASSERT_EQ(1U, urls.size()); 82 ASSERT_EQ(new_url, urls[0].url()); 83 84 // Let sync finish. 85 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 86 87 // Both clients should have this URL. 88 AssertAllProfilesHaveSameURLsAsVerifier(); 89} 90 91IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, AddExpired) { 92 const string16 kHistoryUrl( 93 ASCIIToUTF16("http://www.add-one-history.google.com/")); 94 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 95 96 // Populate one client with a URL, should sync to the other. 97 GURL new_url(kHistoryUrl); 98 // Create a URL with a timestamp 1 year before today. 99 base::Time timestamp = base::Time::Now() - base::TimeDelta::FromDays(365); 100 AddUrlToHistoryWithTimestamp(0, 101 new_url, 102 content::PAGE_TRANSITION_TYPED, 103 history::SOURCE_BROWSED, 104 timestamp); 105 history::URLRows urls = GetTypedUrlsFromClient(0); 106 ASSERT_EQ(1U, urls.size()); 107 ASSERT_EQ(new_url, urls[0].url()); 108 109 // Let sync finish. 110 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 111 112 // Second client should still have no URLs since this one is expired. 113 urls = GetTypedUrlsFromClient(1); 114 ASSERT_EQ(0U, urls.size()); 115} 116 117// Flake on mac: http://crbug/115526 118#if defined(OS_MACOSX) 119#define MAYBE_AddExpiredThenUpdate DISABLED_AddExpiredThenUpdate 120#else 121#define MAYBE_AddExpiredThenUpdate AddExpiredThenUpdate 122#endif 123IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, MAYBE_AddExpiredThenUpdate) { 124 const string16 kHistoryUrl( 125 ASCIIToUTF16("http://www.add-one-history.google.com/")); 126 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 127 128 // Populate one client with a URL, should sync to the other. 129 GURL new_url(kHistoryUrl); 130 // Create a URL with a timestamp 1 year before today. 131 base::Time timestamp = base::Time::Now() - base::TimeDelta::FromDays(365); 132 AddUrlToHistoryWithTimestamp(0, 133 new_url, 134 content::PAGE_TRANSITION_TYPED, 135 history::SOURCE_BROWSED, 136 timestamp); 137 std::vector<history::URLRow> urls = GetTypedUrlsFromClient(0); 138 ASSERT_EQ(1U, urls.size()); 139 ASSERT_EQ(new_url, urls[0].url()); 140 141 // Let sync finish. 142 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 143 144 // Second client should still have no URLs since this one is expired. 145 urls = GetTypedUrlsFromClient(1); 146 ASSERT_EQ(0U, urls.size()); 147 148 // Now drive an update on the first client. 149 AddUrlToHistory(0, new_url); 150 151 // Let sync finish again. 152 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 153 154 // Second client should have the URL now. 155 urls = GetTypedUrlsFromClient(1); 156 ASSERT_EQ(1U, urls.size()); 157} 158 159// TCM: 3705291 160// flaky, see crbug.com/108511 161IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, DISABLED_AddThenDelete) { 162 const string16 kHistoryUrl( 163 ASCIIToUTF16("http://www.add-one-history.google.com/")); 164 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 165 166 // Populate one client with a URL, should sync to the other. 167 GURL new_url(kHistoryUrl); 168 AddUrlToHistory(0, new_url); 169 history::URLRows urls = GetTypedUrlsFromClient(0); 170 ASSERT_EQ(1U, urls.size()); 171 ASSERT_EQ(new_url, urls[0].url()); 172 173 // Let sync finish. 174 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 175 176 // Both clients should have this URL. 177 AssertAllProfilesHaveSameURLsAsVerifier(); 178 179 // Delete from first client, should delete from second. 180 DeleteUrlFromHistory(0, new_url); 181 182 // Let sync finish. 183 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 184 185 // Neither client should have this URL. 186 AssertAllProfilesHaveSameURLsAsVerifier(); 187} 188 189// TCM: 3643277 190IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, DisableEnableSync) { 191 const string16 kUrl1(ASCIIToUTF16("http://history1.google.com/")); 192 const string16 kUrl2(ASCIIToUTF16("http://history2.google.com/")); 193 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 194 195 // Disable typed url sync for one client, leave it active for the other. 196 GetClient(0)->DisableSyncForDatatype(syncer::TYPED_URLS); 197 198 // Add one URL to non-syncing client, add a different URL to the other, 199 // wait for sync cycle to complete. No data should be exchanged. 200 GURL url1(kUrl1); 201 GURL url2(kUrl2); 202 AddUrlToHistory(0, url1); 203 AddUrlToHistory(1, url2); 204 ASSERT_TRUE(GetClient(1)->AwaitFullSyncCompletion("Added a typed url.")); 205 206 // Make sure that no data was exchanged. 207 history::URLRows post_sync_urls = GetTypedUrlsFromClient(0); 208 ASSERT_EQ(1U, post_sync_urls.size()); 209 ASSERT_EQ(url1, post_sync_urls[0].url()); 210 post_sync_urls = GetTypedUrlsFromClient(1); 211 ASSERT_EQ(1U, post_sync_urls.size()); 212 ASSERT_EQ(url2, post_sync_urls[0].url()); 213 214 // Enable typed url sync, make both URLs are synced to each client. 215 GetClient(0)->EnableSyncForDatatype(syncer::TYPED_URLS); 216 ASSERT_TRUE(AwaitQuiescence()); 217 218 AssertAllProfilesHaveSameURLsAsVerifier(); 219} 220 221// flaky, see crbug.com/108511 222IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, DISABLED_AddOneDeleteOther) { 223 const string16 kHistoryUrl( 224 ASCIIToUTF16("http://www.add-one-delete-history.google.com/")); 225 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 226 227 // Populate one client with a URL, should sync to the other. 228 GURL new_url(kHistoryUrl); 229 AddUrlToHistory(0, new_url); 230 history::URLRows urls = GetTypedUrlsFromClient(0); 231 ASSERT_EQ(1U, urls.size()); 232 ASSERT_EQ(new_url, urls[0].url()); 233 234 // Let sync finish. 235 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 236 237 // Both clients should have this URL. 238 AssertAllProfilesHaveSameURLsAsVerifier(); 239 240 // Now, delete the URL from the second client. 241 DeleteUrlFromHistory(1, new_url); 242 urls = GetTypedUrlsFromClient(0); 243 ASSERT_EQ(1U, urls.size()); 244 245 // Let sync finish. 246 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 247 248 // Both clients should have this URL removed. 249 AssertAllProfilesHaveSameURLsAsVerifier(); 250} 251 252// flaky, see crbug.com/108511 253IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, 254 DISABLED_AddOneDeleteOtherAddAgain) { 255 const string16 kHistoryUrl( 256 ASCIIToUTF16("http://www.add-delete-add-history.google.com/")); 257 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 258 259 // Populate one client with a URL, should sync to the other. 260 GURL new_url(kHistoryUrl); 261 AddUrlToHistory(0, new_url); 262 history::URLRows urls = GetTypedUrlsFromClient(0); 263 ASSERT_EQ(1U, urls.size()); 264 ASSERT_EQ(new_url, urls[0].url()); 265 266 // Let sync finish. 267 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 268 269 // Both clients should have this URL. 270 AssertAllProfilesHaveSameURLsAsVerifier(); 271 272 // Now, delete the URL from the second client. 273 DeleteUrlFromHistory(1, new_url); 274 urls = GetTypedUrlsFromClient(0); 275 ASSERT_EQ(1U, urls.size()); 276 277 // Let sync finish. 278 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 279 280 // Both clients should have this URL removed. 281 AssertAllProfilesHaveSameURLsAsVerifier(); 282 283 // Add it to the first client again, should succeed (tests that the deletion 284 // properly disassociates that URL). 285 AddUrlToHistory(0, new_url); 286 287 // Let sync finish. 288 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 289 290 // Both clients should have this URL added again. 291 AssertAllProfilesHaveSameURLsAsVerifier(); 292} 293 294IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, 295 MergeTypedWithNonTypedDuringAssociation) { 296 ASSERT_TRUE(SetupClients()); 297 GURL new_url("http://history.com"); 298 base::Time timestamp = base::Time::Now(); 299 // Put a non-typed URL in both clients with an identical timestamp. 300 // Then add a typed URL to the second client - this test makes sure that 301 // we properly merge both sets of visits together to end up with the same 302 // set of visits on both ends. 303 AddUrlToHistoryWithTimestamp(0, new_url, content::PAGE_TRANSITION_LINK, 304 history::SOURCE_BROWSED, timestamp); 305 AddUrlToHistoryWithTimestamp(1, new_url, content::PAGE_TRANSITION_LINK, 306 history::SOURCE_BROWSED, timestamp); 307 AddUrlToHistoryWithTimestamp(1, new_url, content::PAGE_TRANSITION_TYPED, 308 history::SOURCE_BROWSED, 309 timestamp + base::TimeDelta::FromSeconds(1)); 310 311 // Now start up sync - URLs should get merged. Fully sync client 1 first, 312 // before syncing client 0, so we have both of client 1's URLs in the sync DB 313 // at the time that client 0 does model association. 314 ASSERT_TRUE(GetClient(1)->SetupSync()) << "SetupSync() failed"; 315 GetClient(1)->AwaitFullSyncCompletion("Initial client sync"); 316 ASSERT_TRUE(GetClient(0)->SetupSync()) << "SetupSync() failed"; 317 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 318 319 ASSERT_TRUE(CheckClientsEqual()); 320 // At this point, we should have no duplicates (total visit count should be 321 // 2). We only need to check client 0 since we already verified that both 322 // clients are identical above. 323 history::URLRows urls = GetTypedUrlsFromClient(0); 324 ASSERT_EQ(1U, urls.size()); 325 ASSERT_EQ(new_url, urls[0].url()); 326 ASSERT_TRUE(CheckNoDuplicateVisits()); 327 ASSERT_EQ(2, GetVisitCountForFirstURL(0)); 328} 329 330// Tests transitioning a URL from non-typed to typed when both clients 331// have already seen that URL (so a merge is required). 332IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, 333 MergeTypedWithNonTypedDuringChangeProcessing) { 334 ASSERT_TRUE(SetupClients()); 335 GURL new_url("http://history.com"); 336 base::Time timestamp = base::Time::Now(); 337 // Setup both clients with the identical typed URL visit. This means we can't 338 // use the verifier in this test, because this will show up as two distinct 339 // visits in the verifier. 340 AddUrlToHistoryWithTimestamp(0, new_url, content::PAGE_TRANSITION_LINK, 341 history::SOURCE_BROWSED, timestamp); 342 AddUrlToHistoryWithTimestamp(1, new_url, content::PAGE_TRANSITION_LINK, 343 history::SOURCE_BROWSED, timestamp); 344 345 // Now start up sync. Neither URL should get synced as they do not look like 346 // typed URLs. 347 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 348 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 349 ASSERT_TRUE(CheckClientsEqual()); 350 history::URLRows urls = GetTypedUrlsFromClient(0); 351 ASSERT_EQ(0U, urls.size()); 352 353 // Now, add a typed visit to the first client. 354 AddUrlToHistoryWithTimestamp(0, new_url, content::PAGE_TRANSITION_TYPED, 355 history::SOURCE_BROWSED, 356 timestamp + base::TimeDelta::FromSeconds(1)); 357 358 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 359 ASSERT_TRUE(CheckClientsEqual()); 360 ASSERT_TRUE(CheckNoDuplicateVisits()); 361 urls = GetTypedUrlsFromClient(0); 362 ASSERT_EQ(1U, urls.size()); 363 ASSERT_EQ(2, GetVisitCountForFirstURL(0)); 364 ASSERT_EQ(2, GetVisitCountForFirstURL(1)); 365} 366 367// Tests transitioning a URL from non-typed to typed when one of the clients 368// has never seen that URL before (so no merge is necessary). 369IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, UpdateToNonTypedURL) { 370 const string16 kHistoryUrl( 371 ASCIIToUTF16("http://www.add-delete-add-history.google.com/")); 372 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 373 374 // Populate one client with a non-typed URL, should not be synced. 375 GURL new_url(kHistoryUrl); 376 AddUrlToHistoryWithTransition(0, new_url, content::PAGE_TRANSITION_LINK, 377 history::SOURCE_BROWSED); 378 history::URLRows urls = GetTypedUrlsFromClient(0); 379 ASSERT_EQ(0U, urls.size()); 380 381 // Let sync finish. 382 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 383 384 // Both clients should have 0 typed URLs. 385 AssertAllProfilesHaveSameURLsAsVerifier(); 386 urls = GetTypedUrlsFromClient(0); 387 ASSERT_EQ(0U, urls.size()); 388 389 // Now, add a typed visit to this URL. 390 AddUrlToHistory(0, new_url); 391 392 // Let sync finish. 393 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 394 395 // Both clients should have this URL as typed and have two visits synced up. 396 ASSERT_TRUE(CheckClientsEqual()); 397 urls = GetTypedUrlsFromClient(0); 398 ASSERT_EQ(1U, urls.size()); 399 ASSERT_EQ(new_url, urls[0].url()); 400 ASSERT_EQ(2, GetVisitCountForFirstURL(0)); 401} 402 403IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, 404 SkipImportedVisits) { 405 406 GURL imported_url("http://imported_url.com"); 407 GURL browsed_url("http://browsed_url.com"); 408 GURL browsed_and_imported_url("http://browsed_and_imported_url.com"); 409 ASSERT_TRUE(SetupClients()); 410 411 // Create 3 items in our first client - 1 imported, one browsed, one with 412 // both imported and browsed entries. 413 AddUrlToHistoryWithTransition(0, imported_url, 414 content::PAGE_TRANSITION_TYPED, 415 history::SOURCE_FIREFOX_IMPORTED); 416 AddUrlToHistoryWithTransition(0, browsed_url, 417 content::PAGE_TRANSITION_TYPED, 418 history::SOURCE_BROWSED); 419 AddUrlToHistoryWithTransition(0, browsed_and_imported_url, 420 content::PAGE_TRANSITION_TYPED, 421 history::SOURCE_FIREFOX_IMPORTED); 422 423 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 424 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 425 history::URLRows urls = GetTypedUrlsFromClient(1); 426 ASSERT_EQ(1U, urls.size()); 427 ASSERT_EQ(browsed_url, urls[0].url()); 428 429 // Now browse to 3rd URL - this should cause it to be synced, even though it 430 // was initially imported. 431 AddUrlToHistoryWithTransition(0, browsed_and_imported_url, 432 content::PAGE_TRANSITION_TYPED, 433 history::SOURCE_BROWSED); 434 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 435 urls = GetTypedUrlsFromClient(1); 436 ASSERT_EQ(2U, urls.size()); 437 438 // Make sure the imported URL didn't make it over. 439 for (size_t i = 0; i < urls.size(); ++i) { 440 ASSERT_NE(imported_url, urls[i].url()); 441 } 442} 443 444IN_PROC_BROWSER_TEST_F(TwoClientTypedUrlsSyncTest, BookmarksWithTypedVisit) { 445 GURL bookmark_url("http://www.bookmark.google.com/"); 446 GURL bookmark_icon_url("http://www.bookmark.google.com/favicon.ico"); 447 ASSERT_TRUE(SetupClients()); 448 // Create a bookmark. 449 const BookmarkNode* node = bookmarks_helper::AddURL( 450 0, bookmarks_helper::IndexedURLTitle(0), bookmark_url); 451 bookmarks_helper::SetFavicon(0, node, bookmark_icon_url, 452 bookmarks_helper::CreateFavicon(SK_ColorWHITE), 453 bookmarks_helper::FROM_UI); 454 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 455 456 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 457 // A row in the DB for client 1 should have been created as a result of the 458 // sync. 459 history::URLRow row; 460 ASSERT_TRUE(GetUrlFromClient(1, bookmark_url, &row)); 461 462 // Now, add a typed visit for client 0 to the bookmark URL and sync it over 463 // - this should not cause a crash. 464 AddUrlToHistory(0, bookmark_url); 465 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); 466 467 AssertAllProfilesHaveSameURLsAsVerifier(); 468 history::URLRows urls = GetTypedUrlsFromClient(0); 469 ASSERT_EQ(1U, urls.size()); 470 ASSERT_EQ(bookmark_url, urls[0].url()); 471 ASSERT_EQ(1, GetVisitCountForFirstURL(0)); 472} 473