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