single_client_bookmarks_sync_test.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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/strings/utf_string_conversions.h"
6#include "chrome/browser/profiles/profile.h"
7#include "chrome/browser/sync/profile_sync_service.h"
8#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
9#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
10#include "chrome/browser/sync/test/integration/sync_test.h"
11#include "components/bookmarks/browser/bookmark_model.h"
12#include "sync/test/fake_server/bookmark_entity_builder.h"
13#include "sync/test/fake_server/entity_builder_factory.h"
14#include "sync/test/fake_server/fake_server_verifier.h"
15#include "ui/base/layout.h"
16
17using bookmarks_helper::AddFolder;
18using bookmarks_helper::AddURL;
19using bookmarks_helper::CountBookmarksWithTitlesMatching;
20using bookmarks_helper::Create1xFaviconFromPNGFile;
21using bookmarks_helper::GetBookmarkBarNode;
22using bookmarks_helper::GetBookmarkModel;
23using bookmarks_helper::GetOtherNode;
24using bookmarks_helper::ModelMatchesVerifier;
25using bookmarks_helper::Move;
26using bookmarks_helper::Remove;
27using bookmarks_helper::RemoveAll;
28using bookmarks_helper::SetFavicon;
29using bookmarks_helper::SetTitle;
30using sync_integration_test_util::AwaitCommitActivityCompletion;
31
32class SingleClientBookmarksSyncTest : public SyncTest {
33 public:
34  SingleClientBookmarksSyncTest() : SyncTest(SINGLE_CLIENT) {}
35  virtual ~SingleClientBookmarksSyncTest() {}
36
37  // Verify that the local bookmark model (for the Profile corresponding to
38  // |index|) matches the data on the FakeServer. It is assumed that FakeServer
39  // is being used and each bookmark has a unique title. Folders are not
40  // verified.
41  void VerifyBookmarkModelMatchesFakeServer(int index);
42
43 private:
44  DISALLOW_COPY_AND_ASSIGN(SingleClientBookmarksSyncTest);
45};
46
47void SingleClientBookmarksSyncTest::VerifyBookmarkModelMatchesFakeServer(
48    int index) {
49  fake_server::FakeServerVerifier fake_server_verifier(GetFakeServer());
50  std::vector<BookmarkModel::URLAndTitle> local_bookmarks;
51  GetBookmarkModel(index)->GetBookmarks(&local_bookmarks);
52
53  // Verify that the number of local bookmarks matches the number in the
54  // server.
55  ASSERT_TRUE(fake_server_verifier.VerifyEntityCountByType(
56      local_bookmarks.size(),
57      syncer::BOOKMARKS));
58
59  // Verify that all local bookmark titles exist once on the server.
60  std::vector<BookmarkModel::URLAndTitle>::const_iterator it;
61  for (it = local_bookmarks.begin(); it != local_bookmarks.end(); ++it) {
62    ASSERT_TRUE(fake_server_verifier.VerifyEntityCountByTypeAndName(
63        1,
64        syncer::BOOKMARKS,
65        base::UTF16ToUTF8(it->title)));
66  }
67}
68
69IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest, Sanity) {
70  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
71
72  // Starting state:
73  // other_node
74  //    -> top
75  //      -> tier1_a
76  //        -> http://mail.google.com  "tier1_a_url0"
77  //        -> http://www.pandora.com  "tier1_a_url1"
78  //        -> http://www.facebook.com "tier1_a_url2"
79  //      -> tier1_b
80  //        -> http://www.nhl.com "tier1_b_url0"
81  const BookmarkNode* top = AddFolder(0, GetOtherNode(0), 0, L"top");
82  const BookmarkNode* tier1_a = AddFolder(0, top, 0, L"tier1_a");
83  const BookmarkNode* tier1_b = AddFolder(0, top, 1, L"tier1_b");
84  const BookmarkNode* tier1_a_url0 = AddURL(
85      0, tier1_a, 0, L"tier1_a_url0", GURL("http://mail.google.com"));
86  const BookmarkNode* tier1_a_url1 = AddURL(
87      0, tier1_a, 1, L"tier1_a_url1", GURL("http://www.pandora.com"));
88  const BookmarkNode* tier1_a_url2 = AddURL(
89      0, tier1_a, 2, L"tier1_a_url2", GURL("http://www.facebook.com"));
90  const BookmarkNode* tier1_b_url0 = AddURL(
91      0, tier1_b, 0, L"tier1_b_url0", GURL("http://www.nhl.com"));
92
93  // Setup sync, wait for its completion, and make sure changes were synced.
94  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
95  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
96  ASSERT_TRUE(ModelMatchesVerifier(0));
97
98  //  Ultimately we want to end up with the following model; but this test is
99  //  more about the journey than the destination.
100  //
101  //  bookmark_bar
102  //    -> CNN (www.cnn.com)
103  //    -> tier1_a
104  //      -> tier1_a_url2 (www.facebook.com)
105  //      -> tier1_a_url1 (www.pandora.com)
106  //    -> Porsche (www.porsche.com)
107  //    -> Bank of America (www.bankofamerica.com)
108  //    -> Seattle Bubble
109  //  other_node
110  //    -> top
111  //      -> tier1_b
112  //        -> Wired News (www.wired.com)
113  //        -> tier2_b
114  //          -> tier1_b_url0
115  //          -> tier3_b
116  //            -> Toronto Maple Leafs (mapleleafs.nhl.com)
117  //            -> Wynn (www.wynnlasvegas.com)
118  //      -> tier1_a_url0
119  const BookmarkNode* bar = GetBookmarkBarNode(0);
120  const BookmarkNode* cnn = AddURL(0, bar, 0, L"CNN",
121      GURL("http://www.cnn.com"));
122  ASSERT_TRUE(cnn != NULL);
123  Move(0, tier1_a, bar, 1);
124
125  // Wait for the bookmark position change to sync.
126  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
127  ASSERT_TRUE(ModelMatchesVerifier(0));
128
129  const BookmarkNode* porsche = AddURL(0, bar, 2, L"Porsche",
130      GURL("http://www.porsche.com"));
131  // Rearrange stuff in tier1_a.
132  ASSERT_EQ(tier1_a, tier1_a_url2->parent());
133  ASSERT_EQ(tier1_a, tier1_a_url1->parent());
134  Move(0, tier1_a_url2, tier1_a, 0);
135  Move(0, tier1_a_url1, tier1_a, 2);
136
137  // Wait for the rearranged hierarchy to sync.
138  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
139  ASSERT_TRUE(ModelMatchesVerifier(0));
140
141  ASSERT_EQ(1, tier1_a_url0->parent()->GetIndexOf(tier1_a_url0));
142  Move(0, tier1_a_url0, bar, bar->child_count());
143  const BookmarkNode* boa = AddURL(0, bar, bar->child_count(),
144      L"Bank of America", GURL("https://www.bankofamerica.com"));
145  ASSERT_TRUE(boa != NULL);
146  Move(0, tier1_a_url0, top, top->child_count());
147  const BookmarkNode* bubble = AddURL(
148      0, bar, bar->child_count(), L"Seattle Bubble",
149          GURL("http://seattlebubble.com"));
150  ASSERT_TRUE(bubble != NULL);
151  const BookmarkNode* wired = AddURL(0, bar, 2, L"Wired News",
152      GURL("http://www.wired.com"));
153  const BookmarkNode* tier2_b = AddFolder(
154      0, tier1_b, 0, L"tier2_b");
155  Move(0, tier1_b_url0, tier2_b, 0);
156  Move(0, porsche, bar, 0);
157  SetTitle(0, wired, L"News Wired");
158  SetTitle(0, porsche, L"ICanHazPorsche?");
159
160  // Wait for the title change to sync.
161  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
162  ASSERT_TRUE(ModelMatchesVerifier(0));
163
164  ASSERT_EQ(tier1_a_url0->id(), top->GetChild(top->child_count() - 1)->id());
165  Remove(0, top, top->child_count() - 1);
166  Move(0, wired, tier1_b, 0);
167  Move(0, porsche, bar, 3);
168  const BookmarkNode* tier3_b = AddFolder(0, tier2_b, 1, L"tier3_b");
169  const BookmarkNode* leafs = AddURL(
170      0, tier1_a, 0, L"Toronto Maple Leafs", GURL("http://mapleleafs.nhl.com"));
171  const BookmarkNode* wynn = AddURL(0, bar, 1, L"Wynn",
172      GURL("http://www.wynnlasvegas.com"));
173
174  Move(0, wynn, tier3_b, 0);
175  Move(0, leafs, tier3_b, 0);
176
177  // Wait for newly added bookmarks to sync.
178  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
179  ASSERT_TRUE(ModelMatchesVerifier(0));
180
181  // Only verify FakeServer data if FakeServer is being used.
182  // TODO(pvalenzuela): Use this style of verification in more tests once it is
183  // proven stable.
184  if (GetFakeServer())
185    VerifyBookmarkModelMatchesFakeServer(0);
186}
187
188IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest, InjectedBookmark) {
189  std::string title = "Montreal Canadiens";
190  fake_server::EntityBuilderFactory entity_builder_factory;
191  scoped_ptr<fake_server::FakeServerEntity> entity =
192      entity_builder_factory.NewBookmarkEntityBuilder(
193          title, GURL("http://canadiens.nhl.com")).Build();
194  fake_server_->InjectEntity(entity.Pass());
195
196  DisableVerifier();
197  ASSERT_TRUE(SetupClients());
198  ASSERT_TRUE(SetupSync());
199
200  ASSERT_EQ(1, CountBookmarksWithTitlesMatching(0, base::UTF8ToWide(title)));
201}
202
203// Test that a client doesn't mutate the favicon data in the process
204// of storing the favicon data from sync to the database or in the process
205// of requesting data from the database for sync.
206IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest,
207                       SetFaviconHiDPIDifferentCodec) {
208  // Set the supported scale factors to 1x and 2x such that
209  // BookmarkModel::GetFavicon() requests both 1x and 2x.
210  // 1x -> for sync, 2x -> for the UI.
211  std::vector<ui::ScaleFactor> supported_scale_factors;
212  supported_scale_factors.push_back(ui::SCALE_FACTOR_100P);
213  supported_scale_factors.push_back(ui::SCALE_FACTOR_200P);
214  ui::SetSupportedScaleFactors(supported_scale_factors);
215
216  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
217  ASSERT_TRUE(ModelMatchesVerifier(0));
218
219  const GURL page_url("http://www.google.com");
220  const GURL icon_url("http://www.google.com/favicon.ico");
221  const BookmarkNode* bookmark = AddURL(0, L"title", page_url);
222
223  // Simulate receiving a favicon from sync encoded by a different PNG encoder
224  // than the one native to the OS. This tests the PNG data is not decoded to
225  // SkBitmap (or any other image format) then encoded back to PNG on the path
226  // between sync and the database.
227  gfx::Image original_favicon = Create1xFaviconFromPNGFile(
228      "favicon_cocoa_png_codec.png");
229  ASSERT_FALSE(original_favicon.IsEmpty());
230  SetFavicon(0, bookmark, icon_url, original_favicon,
231             bookmarks_helper::FROM_SYNC);
232
233  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
234  ASSERT_TRUE(ModelMatchesVerifier(0));
235
236  scoped_refptr<base::RefCountedMemory> original_favicon_bytes =
237      original_favicon.As1xPNGBytes();
238  gfx::Image final_favicon = GetBookmarkModel(0)->GetFavicon(bookmark);
239  scoped_refptr<base::RefCountedMemory> final_favicon_bytes =
240      final_favicon.As1xPNGBytes();
241
242  // Check that the data was not mutated from the original.
243  EXPECT_TRUE(original_favicon_bytes.get());
244  EXPECT_TRUE(original_favicon_bytes->Equals(final_favicon_bytes));
245}
246
247IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest,
248                       BookmarkAllNodesRemovedEvent) {
249  ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
250  // Starting state:
251  // other_node
252  //    -> folder0
253  //      -> tier1_a
254  //        -> http://mail.google.com
255  //        -> http://www.google.com
256  //      -> http://news.google.com
257  //      -> http://yahoo.com
258  //    -> http://www.cnn.com
259  // bookmark_bar
260  // -> empty_folder
261  // -> folder1
262  //    -> http://yahoo.com
263  // -> http://gmail.com
264
265  const BookmarkNode* folder0 = AddFolder(0, GetOtherNode(0), 0, L"folder0");
266  const BookmarkNode* tier1_a = AddFolder(0, folder0, 0, L"tier1_a");
267  ASSERT_TRUE(AddURL(0, folder0, 1, L"News", GURL("http://news.google.com")));
268  ASSERT_TRUE(AddURL(0, folder0, 2, L"Yahoo", GURL("http://www.yahoo.com")));
269  ASSERT_TRUE(AddURL(0, tier1_a, 0, L"Gmail", GURL("http://mail.google.com")));
270  ASSERT_TRUE(AddURL(0, tier1_a, 1, L"Google", GURL("http://www.google.com")));
271  ASSERT_TRUE(
272      AddURL(0, GetOtherNode(0), 1, L"CNN", GURL("http://www.cnn.com")));
273
274  ASSERT_TRUE(AddFolder(0, GetBookmarkBarNode(0), 0, L"empty_folder"));
275  const BookmarkNode* folder1 =
276      AddFolder(0, GetBookmarkBarNode(0), 1, L"folder1");
277  ASSERT_TRUE(AddURL(0, folder1, 0, L"Yahoo", GURL("http://www.yahoo.com")));
278  ASSERT_TRUE(
279      AddURL(0, GetBookmarkBarNode(0), 2, L"Gmail", GURL("http://gmail.com")));
280
281  // Set up sync, wait for its completion and verify that changes propagated.
282  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
283  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
284  ASSERT_TRUE(ModelMatchesVerifier(0));
285
286  // Remove all bookmarks and wait for sync completion.
287  RemoveAll(0);
288  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
289  // Verify other node has no children now.
290  EXPECT_EQ(0, GetOtherNode(0)->child_count());
291  EXPECT_EQ(0, GetBookmarkBarNode(0)->child_count());
292  // Verify model matches verifier.
293  ASSERT_TRUE(ModelMatchesVerifier(0));
294}
295