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/search_engines/template_url.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/common/chrome_paths.h"
20 #include "chrome/common/importer/imported_bookmark_entry.h"
21 #include "chrome/common/importer/imported_favicon_usage.h"
22 #include "chrome/common/importer/importer_data_types.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "components/autofill/core/common/password_form.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 wchar_t* username_element
;
42 const wchar_t* username
;
43 const wchar_t* password_element
;
44 const wchar_t* password
;
49 const wchar_t* keyword
;
53 const BookmarkInfo kFirefoxBookmarks
[] = {
54 {true, 1, {L
"Bookmarks Toolbar"},
59 "http://www.google.com/"},
62 const PasswordInfo kFirefoxPasswords
[] = {
63 {"http://localhost:8080/", "http://localhost:8080/", "http://localhost:8080/",
64 L
"loginuser", L
"abc", L
"loginpass", L
"123", false},
65 {"http://localhost:8080/", "", "http://localhost:8080/localhost",
66 L
"", L
"http", L
"", L
"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
), bookmark_count_(0), history_count_(0),
102 password_count_(0), keyword_count_(0), import_search_engines_(true) {
105 explicit FirefoxObserver(bool import_search_engines
)
106 : ProfileWriter(NULL
), bookmark_count_(0), history_count_(0),
107 password_count_(0), keyword_count_(0),
108 import_search_engines_(import_search_engines
) {
111 // importer::ImporterProgressObserver:
112 virtual void ImportStarted() OVERRIDE
{}
113 virtual void ImportItemStarted(importer::ImportItem item
) OVERRIDE
{}
114 virtual void ImportItemEnded(importer::ImportItem item
) OVERRIDE
{}
115 virtual void ImportEnded() OVERRIDE
{
116 base::MessageLoop::current()->Quit();
117 EXPECT_EQ(arraysize(kFirefoxBookmarks
), bookmark_count_
);
118 EXPECT_EQ(1U, history_count_
);
119 EXPECT_EQ(arraysize(kFirefoxPasswords
), password_count_
);
120 if (import_search_engines_
)
121 EXPECT_EQ(arraysize(kFirefoxKeywords
), keyword_count_
);
124 virtual bool BookmarkModelIsLoaded() const OVERRIDE
{
125 // Profile is ready for writing.
129 virtual bool TemplateURLServiceIsLoaded() const OVERRIDE
{
133 virtual void AddPasswordForm(const autofill::PasswordForm
& form
) OVERRIDE
{
134 PasswordInfo p
= kFirefoxPasswords
[password_count_
];
135 EXPECT_EQ(p
.origin
, form
.origin
.spec());
136 EXPECT_EQ(p
.realm
, form
.signon_realm
);
137 EXPECT_EQ(p
.action
, form
.action
.spec());
138 EXPECT_EQ(base::WideToUTF16(p
.username_element
), form
.username_element
);
139 EXPECT_EQ(base::WideToUTF16(p
.username
), form
.username_value
);
140 EXPECT_EQ(base::WideToUTF16(p
.password_element
), form
.password_element
);
141 EXPECT_EQ(base::WideToUTF16(p
.password
), form
.password_value
);
142 EXPECT_EQ(p
.blacklisted
, form
.blacklisted_by_user
);
146 virtual void AddHistoryPage(const history::URLRows
& page
,
147 history::VisitSource visit_source
) OVERRIDE
{
148 ASSERT_EQ(3U, page
.size());
149 EXPECT_EQ("http://www.google.com/", page
[0].url().spec());
150 EXPECT_EQ(base::ASCIIToUTF16("Google"), page
[0].title());
151 EXPECT_EQ("http://www.google.com/", page
[1].url().spec());
152 EXPECT_EQ(base::ASCIIToUTF16("Google"), page
[1].title());
153 EXPECT_EQ("http://www.cs.unc.edu/~jbs/resources/perl/perl-cgi/programs/"
154 "form1-POST.html", page
[2].url().spec());
155 EXPECT_EQ(base::ASCIIToUTF16("example form (POST)"), page
[2].title());
156 EXPECT_EQ(history::SOURCE_FIREFOX_IMPORTED
, visit_source
);
160 virtual void AddBookmarks(
161 const std::vector
<ImportedBookmarkEntry
>& bookmarks
,
162 const base::string16
& top_level_folder_name
) OVERRIDE
{
163 ASSERT_LE(bookmark_count_
+ bookmarks
.size(), arraysize(kFirefoxBookmarks
));
164 // Importer should import the FF favorites the same as the list, in the same
166 for (size_t i
= 0; i
< bookmarks
.size(); ++i
) {
167 EXPECT_NO_FATAL_FAILURE(
168 TestEqualBookmarkEntry(bookmarks
[i
],
169 kFirefoxBookmarks
[bookmark_count_
])) << i
;
174 virtual void AddKeywords(ScopedVector
<TemplateURL
> template_urls
,
175 bool unique_on_host_and_path
) OVERRIDE
{
176 for (size_t i
= 0; i
< template_urls
.size(); ++i
) {
177 // The order might not be deterministic, look in the expected list for
178 // that template URL.
180 base::string16 keyword
= template_urls
[i
]->keyword();
181 for (size_t j
= 0; j
< arraysize(kFirefoxKeywords
); ++j
) {
182 if (template_urls
[i
]->keyword() ==
183 base::WideToUTF16Hack(kFirefoxKeywords
[j
].keyword
)) {
184 EXPECT_EQ(kFirefoxKeywords
[j
].url
, template_urls
[i
]->url());
194 virtual void AddFavicons(
195 const std::vector
<ImportedFaviconUsage
>& favicons
) OVERRIDE
{
199 virtual ~FirefoxObserver() {}
201 size_t bookmark_count_
;
202 size_t history_count_
;
203 size_t password_count_
;
204 size_t keyword_count_
;
205 bool import_search_engines_
;
210 // These tests need to be browser tests in order to be able to run the OOP
211 // import (via ExternalProcessImporterHost) which launches a utility process on
212 // supported platforms.
213 class FirefoxProfileImporterBrowserTest
: public InProcessBrowserTest
{
215 virtual void SetUp() OVERRIDE
{
216 // Creates a new profile in a new subdirectory in the temp directory.
217 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
218 base::FilePath test_path
= temp_dir_
.path().AppendASCII("ImporterTest");
219 base::DeleteFile(test_path
, true);
220 base::CreateDirectory(test_path
);
221 profile_path_
= test_path
.AppendASCII("profile");
222 app_path_
= test_path
.AppendASCII("app");
223 base::CreateDirectory(app_path_
);
225 // This will launch the browser test and thus needs to happen last.
226 InProcessBrowserTest::SetUp();
229 void Firefox3xImporterBrowserTest(
230 std::string profile_dir
,
231 importer::ImporterProgressObserver
* observer
,
232 ProfileWriter
* writer
,
233 bool import_search_plugins
) {
234 base::FilePath data_path
;
235 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &data_path
));
236 data_path
= data_path
.AppendASCII(profile_dir
);
237 ASSERT_TRUE(base::CopyDirectory(data_path
, profile_path_
, true));
238 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &data_path
));
239 data_path
= data_path
.AppendASCII("firefox3_nss");
240 ASSERT_TRUE(base::CopyDirectory(data_path
, profile_path_
, false));
242 base::FilePath search_engine_path
= app_path_
;
243 search_engine_path
= search_engine_path
.AppendASCII("searchplugins");
244 base::CreateDirectory(search_engine_path
);
245 if (import_search_plugins
) {
246 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &data_path
));
247 data_path
= data_path
.AppendASCII("firefox3_searchplugins");
248 if (!base::PathExists(data_path
)) {
249 // TODO(maruel): Create search test data that we can open source!
250 LOG(ERROR
) << L
"Missing internal test data";
253 ASSERT_TRUE(base::CopyDirectory(data_path
, 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 if (import_search_plugins
)
264 items
= items
| importer::SEARCH_ENGINES
;
267 ExternalProcessImporterHost
* host
= new ExternalProcessImporterHost
;
268 host
->set_observer(observer
);
269 host
->StartImportSettings(source_profile
,
270 browser()->profile(),
272 make_scoped_refptr(writer
).get());
273 base::MessageLoop::current()->Run();
276 base::ScopedTempDir temp_dir_
;
277 base::FilePath profile_path_
;
278 base::FilePath app_path_
;
281 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest
,
282 MAYBE_IMPORTER(Firefox30Importer
)) {
283 scoped_refptr
<FirefoxObserver
> observer(new FirefoxObserver());
284 Firefox3xImporterBrowserTest("firefox3_profile", observer
.get(),
285 observer
.get(), true);
288 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest
,
289 MAYBE_IMPORTER(Firefox35Importer
)) {
290 bool import_search_engines
= false;
291 scoped_refptr
<FirefoxObserver
> observer(
292 new FirefoxObserver(import_search_engines
));
293 Firefox3xImporterBrowserTest("firefox35_profile", observer
.get(),
294 observer
.get(), import_search_engines
);