1 // Copyright (c) 2013 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/file_util.h"
6 #include "base/files/file_path.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/path_service.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/importer/external_process_importer_host.h"
15 #include "chrome/browser/importer/importer_progress_observer.h"
16 #include "chrome/browser/importer/importer_unittest_utils.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/common/chrome_paths.h"
19 #include "chrome/common/importer/imported_bookmark_entry.h"
20 #include "chrome/common/importer/imported_favicon_usage.h"
21 #include "chrome/common/importer/importer_data_types.h"
22 #include "chrome/test/base/in_process_browser_test.h"
23 #include "components/autofill/core/common/password_form.h"
24 #include "components/search_engines/template_url.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 // TODO(estade): some of these are disabled on mac. http://crbug.com/48007
28 // TODO(jschuh): Disabled on Win64 build. http://crbug.com/179688
29 #if defined(OS_MACOSX) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64))
30 #define MAYBE_IMPORTER(x) DISABLED_##x
32 #define MAYBE_IMPORTER(x) x
41 const char* username_element;
43 const char* password_element;
49 const wchar_t* keyword;
53 const BookmarkInfo kFirefoxBookmarks[] = {
54 {true, 1, {"Bookmarks Toolbar"},
59 "http://www.google.com/"},
62 const PasswordInfo kFirefoxPasswords[] = {
63 {"http://localhost:8080/", "http://localhost:8080/", "http://localhost:8080/",
64 "loginuser", "abc", "loginpass", "123", false},
65 {"http://localhost:8080/", "", "http://localhost:8080/localhost",
66 "", "http", "", "Http1+1abcdefg", false},
69 const KeywordInfo kFirefoxKeywords[] = {
71 "http://www.amazon.com/exec/obidos/external-search/?field-keywords="
72 "{searchTerms}&mode=blended" },
74 "http://www.answers.com/main/ntquery?s={searchTerms}&gwp=13" },
75 { L"search.creativecommons.org",
76 "http://search.creativecommons.org/?q={searchTerms}" },
78 "http://search.ebay.com/search/search.dll?query={searchTerms}&"
79 "MfcISAPICommand=GetResult&ht=1&ebaytag1=ebayreg&srchdesc=n&"
80 "maxRecordsReturned=300&maxRecordsPerPage=50&SortProperty=MetaEndSort" },
82 "http://www.google.com/search?q={searchTerms}&ie=utf-8&oe=utf-8&aq=t" },
83 { L"en.wikipedia.org",
84 "http://en.wikipedia.org/wiki/Special:Search?search={searchTerms}" },
85 { L"search.yahoo.com",
86 "http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8" },
88 "http://www.flickr.com/photos/tags/?q={searchTerms}" },
90 "http://www.imdb.com/find?q={searchTerms}" },
92 "http://www.webster.com/cgi-bin/dictionary?va={searchTerms}" },
94 { L"\x4E2D\x6587", "http://www.google.com/" },
97 class FirefoxObserver : public ProfileWriter,
98 public importer::ImporterProgressObserver {
101 : ProfileWriter(NULL),
107 // importer::ImporterProgressObserver:
108 virtual void ImportStarted() OVERRIDE {}
109 virtual void ImportItemStarted(importer::ImportItem item) OVERRIDE {}
110 virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE {}
111 virtual void ImportEnded() OVERRIDE {
112 base::MessageLoop::current()->Quit();
113 EXPECT_EQ(arraysize(kFirefoxBookmarks), bookmark_count_);
114 EXPECT_EQ(1U, history_count_);
115 EXPECT_EQ(arraysize(kFirefoxPasswords), password_count_);
116 EXPECT_EQ(arraysize(kFirefoxKeywords), keyword_count_);
119 virtual bool BookmarkModelIsLoaded() const OVERRIDE {
120 // Profile is ready for writing.
124 virtual bool TemplateURLServiceIsLoaded() const OVERRIDE {
128 virtual void AddPasswordForm(const autofill::PasswordForm& form) OVERRIDE {
129 PasswordInfo p = kFirefoxPasswords[password_count_];
130 EXPECT_EQ(p.origin, form.origin.spec());
131 EXPECT_EQ(p.realm, form.signon_realm);
132 EXPECT_EQ(p.action, form.action.spec());
133 EXPECT_EQ(base::ASCIIToUTF16(p.username_element), form.username_element);
134 EXPECT_EQ(base::ASCIIToUTF16(p.username), form.username_value);
135 EXPECT_EQ(base::ASCIIToUTF16(p.password_element), form.password_element);
136 EXPECT_EQ(base::ASCIIToUTF16(p.password), form.password_value);
137 EXPECT_EQ(p.blacklisted, form.blacklisted_by_user);
141 virtual void AddHistoryPage(const history::URLRows& page,
142 history::VisitSource visit_source) OVERRIDE {
143 ASSERT_EQ(3U, page.size());
144 EXPECT_EQ("http://www.google.com/", page[0].url().spec());
145 EXPECT_EQ(base::ASCIIToUTF16("Google"), page[0].title());
146 EXPECT_EQ("http://www.google.com/", page[1].url().spec());
147 EXPECT_EQ(base::ASCIIToUTF16("Google"), page[1].title());
148 EXPECT_EQ("http://www.cs.unc.edu/~jbs/resources/perl/perl-cgi/programs/"
149 "form1-POST.html", page[2].url().spec());
150 EXPECT_EQ(base::ASCIIToUTF16("example form (POST)"), page[2].title());
151 EXPECT_EQ(history::SOURCE_FIREFOX_IMPORTED, visit_source);
155 virtual void AddBookmarks(
156 const std::vector<ImportedBookmarkEntry>& bookmarks,
157 const base::string16& top_level_folder_name) OVERRIDE {
158 ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kFirefoxBookmarks));
159 // Importer should import the FF favorites the same as the list, in the same
161 for (size_t i = 0; i < bookmarks.size(); ++i) {
162 EXPECT_NO_FATAL_FAILURE(
163 TestEqualBookmarkEntry(bookmarks[i],
164 kFirefoxBookmarks[bookmark_count_])) << i;
169 virtual void AddKeywords(ScopedVector<TemplateURL> template_urls,
170 bool unique_on_host_and_path) OVERRIDE {
171 for (size_t i = 0; i < template_urls.size(); ++i) {
172 // The order might not be deterministic, look in the expected list for
173 // that template URL.
175 const base::string16& keyword = template_urls[i]->keyword();
176 for (size_t j = 0; j < arraysize(kFirefoxKeywords); ++j) {
177 if (keyword == base::WideToUTF16(kFirefoxKeywords[j].keyword)) {
178 EXPECT_EQ(kFirefoxKeywords[j].url, template_urls[i]->url());
188 virtual void AddFavicons(
189 const std::vector<ImportedFaviconUsage>& favicons) OVERRIDE {
193 virtual ~FirefoxObserver() {}
195 size_t bookmark_count_;
196 size_t history_count_;
197 size_t password_count_;
198 size_t keyword_count_;
203 // These tests need to be browser tests in order to be able to run the OOP
204 // import (via ExternalProcessImporterHost) which launches a utility process on
205 // supported platforms.
206 class FirefoxProfileImporterBrowserTest : public InProcessBrowserTest {
208 virtual void SetUp() OVERRIDE {
209 // Creates a new profile in a new subdirectory in the temp directory.
210 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
211 base::FilePath test_path = temp_dir_.path().AppendASCII("ImporterTest");
212 base::DeleteFile(test_path, true);
213 base::CreateDirectory(test_path);
214 profile_path_ = test_path.AppendASCII("profile");
215 app_path_ = test_path.AppendASCII("app");
216 base::CreateDirectory(app_path_);
218 // This will launch the browser test and thus needs to happen last.
219 InProcessBrowserTest::SetUp();
222 void FirefoxImporterBrowserTest(std::string profile_dir,
223 importer::ImporterProgressObserver* observer,
224 ProfileWriter* writer) {
225 base::FilePath data_path;
226 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
227 data_path = data_path.AppendASCII(profile_dir);
228 ASSERT_TRUE(base::CopyDirectory(data_path, profile_path_, true));
230 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
231 data_path = data_path.AppendASCII("firefox3_nss");
232 ASSERT_TRUE(base::CopyDirectory(data_path, profile_path_, false));
234 // Create a directory to house default search engines.
235 base::FilePath default_search_engine_path =
236 app_path_.AppendASCII("searchplugins");
237 base::CreateDirectory(default_search_engine_path);
239 // Create a directory to house custom/installed search engines.
240 base::FilePath custom_search_engine_path =
241 profile_path_.AppendASCII("searchplugins");
242 base::CreateDirectory(custom_search_engine_path);
244 // Copy over search engines.
245 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
246 data_path = data_path.AppendASCII("firefox_searchplugins");
247 base::FilePath default_search_engine_source_path =
248 data_path.AppendASCII("default");
249 base::FilePath custom_search_engine_source_path =
250 data_path.AppendASCII("custom");
251 ASSERT_TRUE(base::CopyDirectory(
252 default_search_engine_source_path, default_search_engine_path, false));
253 ASSERT_TRUE(base::CopyDirectory(
254 custom_search_engine_source_path, custom_search_engine_path, false));
256 importer::SourceProfile source_profile;
257 source_profile.importer_type = importer::TYPE_FIREFOX;
258 source_profile.app_path = app_path_;
259 source_profile.source_path = profile_path_;
260 source_profile.locale = "en-US";
262 int items = importer::HISTORY | importer::PASSWORDS | importer::FAVORITES |
263 importer::SEARCH_ENGINES;
266 ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
267 host->set_observer(observer);
268 host->StartImportSettings(
269 source_profile, browser()->profile(), items, writer);
270 base::MessageLoop::current()->Run();
273 base::ScopedTempDir temp_dir_;
274 base::FilePath profile_path_;
275 base::FilePath app_path_;
278 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest,
279 MAYBE_IMPORTER(Firefox30Importer)) {
280 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver());
281 FirefoxImporterBrowserTest(
282 "firefox3_profile", observer.get(), observer.get());
285 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest,
286 MAYBE_IMPORTER(Firefox35Importer)) {
287 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver());
288 FirefoxImporterBrowserTest(
289 "firefox35_profile", observer.get(), observer.get());
292 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest,
293 MAYBE_IMPORTER(FirefoxImporter)) {
294 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver());
295 FirefoxImporterBrowserTest("firefox_profile", observer.get(), observer.get());