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