- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / test / integration / two_client_typed_urls_sync_test.cc
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/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
15 using typed_urls_helper::AddUrlToHistory;
16 using typed_urls_helper::AddUrlToHistoryWithTimestamp;
17 using typed_urls_helper::AddUrlToHistoryWithTransition;
18 using typed_urls_helper::AreVisitsEqual;
19 using typed_urls_helper::AreVisitsUnique;
20 using typed_urls_helper::AssertAllProfilesHaveSameURLsAsVerifier;
21 using typed_urls_helper::AssertURLRowVectorsAreEqual;
22 using typed_urls_helper::DeleteUrlFromHistory;
23 using typed_urls_helper::GetTypedUrlsFromClient;
24 using typed_urls_helper::GetUrlFromClient;
25 using typed_urls_helper::GetVisitsFromClient;
26 using typed_urls_helper::RemoveVisitsFromClient;
27
28 class 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
72 IN_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
91 IN_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
123 IN_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
161 IN_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
190 IN_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
222 IN_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
253 IN_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
294 IN_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).
332 IN_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).
369 IN_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
403 IN_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
444 IN_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 }