OLD | NEW |
| (Empty) |
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 "chrome/browser/bookmarks/bookmark_html_writer.h" | |
6 | |
7 #include "base/files/scoped_temp_dir.h" | |
8 #include "base/i18n/time_formatting.h" | |
9 #include "base/path_service.h" | |
10 #include "base/run_loop.h" | |
11 #include "base/strings/string16.h" | |
12 #include "base/strings/string_util.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "base/time/time.h" | |
15 #include "chrome/browser/bookmarks/bookmark_model.h" | |
16 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | |
17 #include "chrome/browser/favicon/favicon_service.h" | |
18 #include "chrome/browser/favicon/favicon_service_factory.h" | |
19 #include "chrome/browser/history/history_service.h" | |
20 #include "chrome/browser/history/history_service_factory.h" | |
21 #include "chrome/browser/importer/bookmark_html_reader.h" | |
22 #include "chrome/common/importer/imported_bookmark_entry.h" | |
23 #include "chrome/common/importer/imported_favicon_usage.h" | |
24 #include "chrome/test/base/testing_profile.h" | |
25 #include "chrome/test/base/ui_test_utils.h" | |
26 #include "content/public/test/test_browser_thread_bundle.h" | |
27 #include "grit/generated_resources.h" | |
28 #include "testing/gtest/include/gtest/gtest.h" | |
29 #include "third_party/skia/include/core/SkBitmap.h" | |
30 #include "ui/base/l10n/l10n_util.h" | |
31 #include "ui/gfx/codec/png_codec.h" | |
32 | |
33 using content::BrowserThread; | |
34 | |
35 namespace { | |
36 | |
37 const int kIconWidth = 16; | |
38 const int kIconHeight = 16; | |
39 | |
40 void MakeTestSkBitmap(int w, int h, SkBitmap* bmp) { | |
41 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h); | |
42 bmp->allocPixels(); | |
43 | |
44 uint32_t* src_data = bmp->getAddr32(0, 0); | |
45 for (int i = 0; i < w * h; i++) { | |
46 src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240); | |
47 } | |
48 } | |
49 | |
50 } // namespace | |
51 | |
52 class BookmarkHTMLWriterTest : public testing::Test { | |
53 protected: | |
54 virtual void SetUp() { | |
55 testing::Test::SetUp(); | |
56 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
57 path_ = temp_dir_.path().AppendASCII("bookmarks.html"); | |
58 } | |
59 | |
60 // Converts an ImportedBookmarkEntry to a string suitable for assertion | |
61 // testing. | |
62 string16 BookmarkEntryToString(const ImportedBookmarkEntry& entry) { | |
63 string16 result; | |
64 result.append(ASCIIToUTF16("on_toolbar=")); | |
65 if (entry.in_toolbar) | |
66 result.append(ASCIIToUTF16("true")); | |
67 else | |
68 result.append(ASCIIToUTF16("false")); | |
69 | |
70 result.append(ASCIIToUTF16(" url=") + UTF8ToUTF16(entry.url.spec())); | |
71 | |
72 result.append(ASCIIToUTF16(" path=")); | |
73 for (size_t i = 0; i < entry.path.size(); ++i) { | |
74 if (i != 0) | |
75 result.append(ASCIIToUTF16("/")); | |
76 result.append(entry.path[i]); | |
77 } | |
78 | |
79 result.append(ASCIIToUTF16(" title=")); | |
80 result.append(entry.title); | |
81 | |
82 result.append(ASCIIToUTF16(" time=")); | |
83 result.append(base::TimeFormatFriendlyDateAndTime(entry.creation_time)); | |
84 return result; | |
85 } | |
86 | |
87 // Creates a set of bookmark values to a string for assertion testing. | |
88 string16 BookmarkValuesToString(bool on_toolbar, | |
89 const GURL& url, | |
90 const string16& title, | |
91 base::Time creation_time, | |
92 const string16& f1, | |
93 const string16& f2, | |
94 const string16& f3) { | |
95 ImportedBookmarkEntry entry; | |
96 entry.in_toolbar = on_toolbar; | |
97 entry.url = url; | |
98 if (!f1.empty()) { | |
99 entry.path.push_back(f1); | |
100 if (!f2.empty()) { | |
101 entry.path.push_back(f2); | |
102 if (!f3.empty()) | |
103 entry.path.push_back(f3); | |
104 } | |
105 } | |
106 entry.title = title; | |
107 entry.creation_time = creation_time; | |
108 return BookmarkEntryToString(entry); | |
109 } | |
110 | |
111 void AssertBookmarkEntryEquals(const ImportedBookmarkEntry& entry, | |
112 bool on_toolbar, | |
113 const GURL& url, | |
114 const string16& title, | |
115 base::Time creation_time, | |
116 const string16& f1, | |
117 const string16& f2, | |
118 const string16& f3) { | |
119 EXPECT_EQ(BookmarkValuesToString(on_toolbar, url, title, creation_time, | |
120 f1, f2, f3), | |
121 BookmarkEntryToString(entry)); | |
122 } | |
123 | |
124 base::ScopedTempDir temp_dir_; | |
125 base::FilePath path_; | |
126 }; | |
127 | |
128 // Class that will notify message loop when file is written. | |
129 class BookmarksObserver : public BookmarksExportObserver { | |
130 public: | |
131 explicit BookmarksObserver(base::RunLoop* loop) : loop_(loop) { | |
132 DCHECK(loop); | |
133 } | |
134 | |
135 virtual void OnExportFinished() OVERRIDE { | |
136 loop_->Quit(); | |
137 } | |
138 | |
139 private: | |
140 base::RunLoop* loop_; | |
141 | |
142 DISALLOW_COPY_AND_ASSIGN(BookmarksObserver); | |
143 }; | |
144 | |
145 // Tests bookmark_html_writer by populating a BookmarkModel, writing it out by | |
146 // way of bookmark_html_writer, then using the importer to read it back in. | |
147 TEST_F(BookmarkHTMLWriterTest, Test) { | |
148 content::TestBrowserThreadBundle thread_bundle; | |
149 | |
150 TestingProfile profile; | |
151 profile.CreateHistoryService(true, false); | |
152 profile.BlockUntilHistoryProcessesPendingRequests(); | |
153 profile.CreateFaviconService(); | |
154 profile.CreateBookmarkModel(true); | |
155 | |
156 BookmarkModel* model = BookmarkModelFactory::GetForProfile(&profile); | |
157 ui_test_utils::WaitForBookmarkModelToLoad(model); | |
158 | |
159 // Create test PNG representing favicon for url1. | |
160 SkBitmap bitmap; | |
161 MakeTestSkBitmap(kIconWidth, kIconHeight, &bitmap); | |
162 std::vector<unsigned char> icon_data; | |
163 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &icon_data); | |
164 | |
165 // Populate the BookmarkModel. This creates the following bookmark structure: | |
166 // Bookmarks bar | |
167 // F1 | |
168 // url1 | |
169 // F2 | |
170 // url2 | |
171 // url3 | |
172 // url4 | |
173 // Other | |
174 // url1 | |
175 // url2 | |
176 // F3 | |
177 // F4 | |
178 // url1 | |
179 // Mobile | |
180 // url1 | |
181 // <bookmark without a title.> | |
182 string16 f1_title = ASCIIToUTF16("F\"&;<1\""); | |
183 string16 f2_title = ASCIIToUTF16("F2"); | |
184 string16 f3_title = ASCIIToUTF16("F 3"); | |
185 string16 f4_title = ASCIIToUTF16("F4"); | |
186 string16 url1_title = ASCIIToUTF16("url 1"); | |
187 string16 url2_title = ASCIIToUTF16("url&2"); | |
188 string16 url3_title = ASCIIToUTF16("url\"3"); | |
189 string16 url4_title = ASCIIToUTF16("url\"&;"); | |
190 string16 unnamed_bookmark_title = ASCIIToUTF16(""); | |
191 GURL url1("http://url1"); | |
192 GURL url1_favicon("http://url1/icon.ico"); | |
193 GURL url2("http://url2"); | |
194 GURL url3("http://url3"); | |
195 GURL url4("javascript:alert(\"Hello!\");"); | |
196 GURL unnamed_bookmark_url("about:blank"); | |
197 base::Time t1(base::Time::Now()); | |
198 base::Time t2(t1 + base::TimeDelta::FromHours(1)); | |
199 base::Time t3(t1 + base::TimeDelta::FromHours(1)); | |
200 base::Time t4(t1 + base::TimeDelta::FromHours(1)); | |
201 const BookmarkNode* f1 = model->AddFolder( | |
202 model->bookmark_bar_node(), 0, f1_title); | |
203 model->AddURLWithCreationTime(f1, 0, url1_title, url1, t1); | |
204 HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)-> | |
205 AddPage(url1, base::Time::Now(), history::SOURCE_BROWSED); | |
206 FaviconServiceFactory::GetForProfile( | |
207 &profile, Profile::EXPLICIT_ACCESS)->SetFavicons( | |
208 url1, url1_favicon, chrome::FAVICON, | |
209 gfx::Image::CreateFrom1xBitmap(bitmap)); | |
210 const BookmarkNode* f2 = model->AddFolder(f1, 1, f2_title); | |
211 model->AddURLWithCreationTime(f2, 0, url2_title, url2, t2); | |
212 model->AddURLWithCreationTime(model->bookmark_bar_node(), | |
213 1, url3_title, url3, t3); | |
214 | |
215 model->AddURLWithCreationTime(model->other_node(), 0, url1_title, url1, t1); | |
216 model->AddURLWithCreationTime(model->other_node(), 1, url2_title, url2, t2); | |
217 const BookmarkNode* f3 = model->AddFolder(model->other_node(), 2, f3_title); | |
218 const BookmarkNode* f4 = model->AddFolder(f3, 0, f4_title); | |
219 model->AddURLWithCreationTime(f4, 0, url1_title, url1, t1); | |
220 model->AddURLWithCreationTime(model->bookmark_bar_node(), 2, url4_title, | |
221 url4, t4); | |
222 model->AddURLWithCreationTime(model->mobile_node(), 0, url1_title, url1, t1); | |
223 model->AddURLWithCreationTime(model->mobile_node(), 1, unnamed_bookmark_title, | |
224 unnamed_bookmark_url, t2); | |
225 | |
226 base::RunLoop run_loop; | |
227 | |
228 // Write to a temp file. | |
229 BookmarksObserver observer(&run_loop); | |
230 bookmark_html_writer::WriteBookmarks(&profile, path_, &observer); | |
231 run_loop.Run(); | |
232 | |
233 // Clear favicon so that it would be read from file. | |
234 FaviconServiceFactory::GetForProfile( | |
235 &profile, Profile::EXPLICIT_ACCESS)->SetFavicons( | |
236 url1, url1_favicon, chrome::FAVICON, gfx::Image()); | |
237 | |
238 // Read the bookmarks back in. | |
239 std::vector<ImportedBookmarkEntry> parsed_bookmarks; | |
240 std::vector<ImportedFaviconUsage> favicons; | |
241 bookmark_html_reader::ImportBookmarksFile(base::Callback<bool(void)>(), | |
242 base::Callback<bool(const GURL&)>(), | |
243 path_, | |
244 &parsed_bookmarks, | |
245 &favicons); | |
246 | |
247 // Check loaded favicon (url1 is represented by 4 separate bookmarks). | |
248 EXPECT_EQ(4U, favicons.size()); | |
249 for (size_t i = 0; i < favicons.size(); i++) { | |
250 if (url1_favicon == favicons[i].favicon_url) { | |
251 EXPECT_EQ(1U, favicons[i].urls.size()); | |
252 std::set<GURL>::const_iterator iter = favicons[i].urls.find(url1); | |
253 ASSERT_TRUE(iter != favicons[i].urls.end()); | |
254 ASSERT_TRUE(*iter == url1); | |
255 ASSERT_TRUE(favicons[i].png_data == icon_data); | |
256 } | |
257 } | |
258 | |
259 // Verify we got back what we wrote. | |
260 ASSERT_EQ(9U, parsed_bookmarks.size()); | |
261 // Windows and ChromeOS builds use Sentence case. | |
262 string16 bookmark_folder_name = | |
263 l10n_util::GetStringUTF16(IDS_BOOKMARK_BAR_FOLDER_NAME); | |
264 AssertBookmarkEntryEquals(parsed_bookmarks[0], true, url1, url1_title, t1, | |
265 bookmark_folder_name, f1_title, string16()); | |
266 AssertBookmarkEntryEquals(parsed_bookmarks[1], true, url2, url2_title, t2, | |
267 bookmark_folder_name, f1_title, f2_title); | |
268 AssertBookmarkEntryEquals(parsed_bookmarks[2], true, url3, url3_title, t3, | |
269 bookmark_folder_name, string16(), string16()); | |
270 AssertBookmarkEntryEquals(parsed_bookmarks[3], true, url4, url4_title, t4, | |
271 bookmark_folder_name, string16(), string16()); | |
272 AssertBookmarkEntryEquals(parsed_bookmarks[4], false, url1, url1_title, t1, | |
273 string16(), string16(), string16()); | |
274 AssertBookmarkEntryEquals(parsed_bookmarks[5], false, url2, url2_title, t2, | |
275 string16(), string16(), string16()); | |
276 AssertBookmarkEntryEquals(parsed_bookmarks[6], false, url1, url1_title, t1, | |
277 f3_title, f4_title, string16()); | |
278 AssertBookmarkEntryEquals(parsed_bookmarks[7], false, url1, url1_title, t1, | |
279 string16(), string16(), string16()); | |
280 AssertBookmarkEntryEquals(parsed_bookmarks[8], false, unnamed_bookmark_url, | |
281 unnamed_bookmark_title, t2, | |
282 string16(), string16(), string16()); | |
283 } | |
OLD | NEW |