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 "chrome/utility/importer/safari_importer.h"
7 #include "base/basictypes.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/path_service.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/importer/imported_bookmark_entry.h"
18 #include "chrome/common/importer/importer_bridge.h"
19 #include "chrome/common/importer/safari_importer_utils.h"
20 #include "chrome/utility/importer/safari_importer.h"
21 #include "components/favicon_base/favicon_usage_data.h"
22 #include "sql/connection.h"
23 #include "testing/platform_test.h"
25 using base::ASCIIToUTF16;
27 // In order to test the Safari import functionality effectively, we store a
28 // simulated Library directory containing dummy data files in the same
29 // structure as ~/Library in the Chrome test data directory.
30 // This function returns the path to that directory.
31 base::FilePath GetTestSafariLibraryPath(const std::string& suffix) {
32 base::FilePath test_dir;
33 PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
35 // Our simulated ~/Library directory
37 test_dir.AppendASCII("import").AppendASCII("safari").AppendASCII(suffix);
40 class SafariImporterTest : public PlatformTest {
42 SafariImporter* GetSafariImporter() {
43 return GetSafariImporterWithPathSuffix("default");
46 SafariImporter* GetSafariImporterWithPathSuffix(const std::string& suffix) {
47 base::FilePath test_library_dir = GetTestSafariLibraryPath(suffix);
48 CHECK(base::PathExists(test_library_dir));
49 return new SafariImporter(test_library_dir);
53 TEST_F(SafariImporterTest, HistoryImport) {
54 scoped_refptr<SafariImporter> importer(GetSafariImporter());
56 std::vector<ImporterURLRow> history_items;
57 importer->ParseHistoryItems(&history_items);
59 // Should be 2 history items.
60 ASSERT_EQ(history_items.size(), 2U);
62 ImporterURLRow& it1 = history_items[0];
63 EXPECT_EQ(it1.url, GURL("http://www.firsthistoryitem.com/"));
64 EXPECT_EQ(it1.title, base::UTF8ToUTF16("First History Item Title"));
65 EXPECT_EQ(it1.visit_count, 1);
66 EXPECT_EQ(it1.hidden, 0);
67 EXPECT_EQ(it1.typed_count, 0);
68 EXPECT_EQ(it1.last_visit.ToDoubleT(),
69 importer->HistoryTimeToEpochTime(@"270598264.4"));
71 ImporterURLRow& it2 = history_items[1];
72 std::string second_item_title("http://www.secondhistoryitem.com/");
73 EXPECT_EQ(it2.url, GURL(second_item_title));
74 // The second item lacks a title so we expect the URL to be substituted.
75 EXPECT_EQ(base::UTF16ToUTF8(it2.title), second_item_title.c_str());
76 EXPECT_EQ(it2.visit_count, 55);
77 EXPECT_EQ(it2.hidden, 0);
78 EXPECT_EQ(it2.typed_count, 0);
79 EXPECT_EQ(it2.last_visit.ToDoubleT(),
80 importer->HistoryTimeToEpochTime(@"270598231.4"));
83 TEST_F(SafariImporterTest, BookmarkImport) {
88 // We store the path with levels of nesting delimited by forward slashes.
91 } kImportedBookmarksData[] = {
94 GURL("http://www.apple.com/"),
95 ASCIIToUTF16("Toolbar/"),
100 GURL("http://www.yahoo.com/"),
101 ASCIIToUTF16("Toolbar/"),
102 ASCIIToUTF16("Yahoo!")
106 GURL("http://www.cnn.com/"),
107 ASCIIToUTF16("Toolbar/News"),
112 GURL("http://www.nytimes.com/"),
113 ASCIIToUTF16("Toolbar/News"),
114 ASCIIToUTF16("The New York Times")
118 GURL("http://www.reddit.com/"),
120 ASCIIToUTF16("reddit.com: what's new online!")
126 ASCIIToUTF16("Empty Folder")
130 GURL("http://www.webkit.org/blog/"),
132 ASCIIToUTF16("Surfin' Safari - The WebKit Blog")
136 scoped_refptr<SafariImporter> importer(GetSafariImporter());
137 std::vector<ImportedBookmarkEntry> bookmarks;
138 importer->ParseBookmarks(ASCIIToUTF16("Toolbar"), &bookmarks);
139 size_t num_bookmarks = bookmarks.size();
140 ASSERT_EQ(arraysize(kImportedBookmarksData), num_bookmarks);
142 for (size_t i = 0; i < num_bookmarks; ++i) {
143 ImportedBookmarkEntry& entry = bookmarks[i];
144 EXPECT_EQ(kImportedBookmarksData[i].in_toolbar, entry.in_toolbar);
145 EXPECT_EQ(kImportedBookmarksData[i].url, entry.url);
147 std::vector<base::string16> path;
148 Tokenize(kImportedBookmarksData[i].path, ASCIIToUTF16("/"), &path);
149 ASSERT_EQ(path.size(), entry.path.size());
150 for (size_t j = 0; j < path.size(); ++j) {
151 EXPECT_EQ(path[j], entry.path[j]);
154 EXPECT_EQ(kImportedBookmarksData[i].title, entry.title);
158 TEST_F(SafariImporterTest, BookmarkImportWithEmptyBookmarksMenu) {
163 // We store the path with levels of nesting delimited by forward slashes.
165 base::string16 title;
166 } kImportedBookmarksData[] = {
169 GURL("http://www.apple.com/"),
170 ASCIIToUTF16("Toolbar/"),
171 ASCIIToUTF16("Apple")
175 GURL("http://www.yahoo.com/"),
176 ASCIIToUTF16("Toolbar/"),
177 ASCIIToUTF16("Yahoo!")
181 GURL("http://www.cnn.com/"),
182 ASCIIToUTF16("Toolbar/News"),
187 GURL("http://www.nytimes.com/"),
188 ASCIIToUTF16("Toolbar/News"),
189 ASCIIToUTF16("The New York Times")
193 GURL("http://www.webkit.org/blog/"),
195 ASCIIToUTF16("Surfin' Safari - The WebKit Blog")
199 scoped_refptr<SafariImporter> importer(
200 GetSafariImporterWithPathSuffix("empty_bookmarks_menu"));
201 std::vector<ImportedBookmarkEntry> bookmarks;
202 importer->ParseBookmarks(ASCIIToUTF16("Toolbar"), &bookmarks);
203 size_t num_bookmarks = bookmarks.size();
204 ASSERT_EQ(arraysize(kImportedBookmarksData), num_bookmarks);
206 for (size_t i = 0; i < num_bookmarks; ++i) {
207 ImportedBookmarkEntry& entry = bookmarks[i];
208 EXPECT_EQ(kImportedBookmarksData[i].in_toolbar, entry.in_toolbar);
209 EXPECT_EQ(kImportedBookmarksData[i].url, entry.url);
211 std::vector<base::string16> path;
212 Tokenize(kImportedBookmarksData[i].path, ASCIIToUTF16("/"), &path);
213 ASSERT_EQ(path.size(), entry.path.size());
214 for (size_t j = 0; j < path.size(); ++j) {
215 EXPECT_EQ(path[j], entry.path[j]);
218 EXPECT_EQ(kImportedBookmarksData[i].title, entry.title);
222 TEST_F(SafariImporterTest, FaviconImport) {
223 scoped_refptr<SafariImporter> importer(GetSafariImporter());
225 ASSERT_TRUE(importer->OpenDatabase(&db));
227 SafariImporter::FaviconMap favicon_map;
228 importer->ImportFaviconURLs(&db, &favicon_map);
230 favicon_base::FaviconUsageDataList favicons;
231 importer->LoadFaviconData(&db, favicon_map, &favicons);
233 size_t num_favicons = favicons.size();
234 ASSERT_EQ(num_favicons, 2U);
236 favicon_base::FaviconUsageData& fav0 = favicons[0];
237 EXPECT_EQ("http://s.ytimg.com/yt/favicon-vfl86270.ico",
238 fav0.favicon_url.spec());
239 EXPECT_GT(fav0.png_data.size(), 0U);
240 EXPECT_EQ(fav0.urls.size(), 1U);
241 EXPECT_TRUE(fav0.urls.find(GURL("http://www.youtube.com/"))
244 favicon_base::FaviconUsageData& fav1 = favicons[1];
245 EXPECT_EQ("http://www.opensearch.org/favicon.ico",
246 fav1.favicon_url.spec());
247 EXPECT_GT(fav1.png_data.size(), 0U);
248 EXPECT_EQ(fav1.urls.size(), 2U);
249 EXPECT_TRUE(fav1.urls.find(GURL("http://www.opensearch.org/Home"))
252 EXPECT_TRUE(fav1.urls.find(
253 GURL("http://www.opensearch.org/Special:Search?search=lalala&go=Search"))
257 TEST_F(SafariImporterTest, CanImport) {
258 uint16 items = importer::NONE;
259 EXPECT_TRUE(SafariImporterCanImport(
260 GetTestSafariLibraryPath("default"), &items));
261 EXPECT_EQ(items, importer::HISTORY | importer::FAVORITES);
262 EXPECT_EQ(items & importer::COOKIES, importer::NONE);
263 EXPECT_EQ(items & importer::PASSWORDS, importer::NONE);
264 EXPECT_EQ(items & importer::SEARCH_ENGINES, importer::NONE);
265 EXPECT_EQ(items & importer::HOME_PAGE, importer::NONE);
267 // Check that we don't import anything from a bogus library directory.
268 base::ScopedTempDir fake_library_dir;
269 ASSERT_TRUE(fake_library_dir.CreateUniqueTempDir());
270 EXPECT_FALSE(SafariImporterCanImport(fake_library_dir.path(), &items));