Run canExecute before executing delete command.
[chromium-blink-merge.git] / chrome / browser / importer / firefox_importer_browsertest.cc
blob536421e51b4e5f32977e3fb294cde2459d1a566f
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/files/file_path.h"
6 #include "base/files/file_util.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/importer_data_types.h"
21 #include "chrome/test/base/in_process_browser_test.h"
22 #include "components/autofill/core/browser/webdata/autofill_entry.h"
23 #include "components/autofill/core/common/password_form.h"
24 #include "components/favicon_base/favicon_usage_data.h"
25 #include "components/search_engines/template_url.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 // TODO(estade): some of these are disabled on mac. http://crbug.com/48007
29 // TODO(jschuh): Disabled on Win64 build. http://crbug.com/179688
30 #if defined(OS_MACOSX) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64))
31 #define MAYBE_IMPORTER(x) DISABLED_##x
32 #else
33 #define MAYBE_IMPORTER(x) x
34 #endif
36 namespace {
38 struct PasswordInfo {
39 const char* origin;
40 const char* action;
41 const char* realm;
42 const char* username_element;
43 const char* username;
44 const char* password_element;
45 const char* password;
46 bool blacklisted;
49 struct KeywordInfo {
50 const wchar_t* keyword_in_sqlite;
51 const wchar_t* keyword_in_json;
52 const char* url;
55 struct AutofillFormDataInfo {
56 const char* name;
57 const char* value;
60 const BookmarkInfo kFirefoxBookmarks[] = {
61 {true, 1, {"Bookmarks Toolbar"},
62 L"Toolbar",
63 "http://site/"},
64 {false, 0, {},
65 L"Title",
66 "http://www.google.com/"},
69 const PasswordInfo kFirefoxPasswords[] = {
70 {"http://blacklist.com/", "", "http://blacklist.com/",
71 "", "", "", "", true},
72 {"http://localhost:8080/", "http://localhost:8080/", "http://localhost:8080/",
73 "loginuser", "abc", "loginpass", "123", false},
74 {"http://localhost:8080/", "", "http://localhost:8080/localhost",
75 "", "http", "", "Http1+1abcdefg", false},
76 {"http://server.com:1234/", "", "http://server.com:1234/http_realm",
77 "loginuser", "user", "loginpass", "password", false},
78 {"http://server.com:4321/", "", "http://server.com:4321/http_realm",
79 "loginuser", "user", "loginpass", "", false},
80 {"http://server.com:4321/", "", "http://server.com:4321/http_realm",
81 "loginuser", "", "loginpass", "password", false},
84 const KeywordInfo kFirefoxKeywords[] = {
85 {L"amazon.com", L"amazon.com",
86 "http://www.amazon.com/exec/obidos/external-search/?field-keywords="
87 "{searchTerms}&mode=blended"},
88 {L"answers.com", L"answers.com",
89 "http://www.answers.com/main/ntquery?s={searchTerms}&gwp=13"},
90 {L"search.creativecommons.org", L"search.creativecommons.org",
91 "http://search.creativecommons.org/?q={searchTerms}"},
92 {L"search.ebay.com", L"search.ebay.com",
93 "http://search.ebay.com/search/search.dll?query={searchTerms}&"
94 "MfcISAPICommand=GetResult&ht=1&ebaytag1=ebayreg&srchdesc=n&"
95 "maxRecordsReturned=300&maxRecordsPerPage=50&SortProperty=MetaEndSort"},
96 {L"google.com", L"google.com",
97 "http://www.google.com/search?q={searchTerms}&ie=utf-8&oe=utf-8&aq=t"},
98 {L"en.wikipedia.org", L"wiki",
99 "http://en.wikipedia.org/wiki/Special:Search?search={searchTerms}"},
100 {L"search.yahoo.com", L"search.yahoo.com",
101 "http://search.yahoo.com/search?p={searchTerms}&ei=UTF-8"},
102 {L"flickr.com", L"flickr.com",
103 "http://www.flickr.com/photos/tags/?q={searchTerms}"},
104 {L"imdb.com", L"imdb.com", "http://www.imdb.com/find?q={searchTerms}"},
105 {L"webster.com", L"webster.com",
106 "http://www.webster.com/cgi-bin/dictionary?va={searchTerms}"},
107 // Search keywords.
108 {L"\x4E2D\x6587", L"\x4E2D\x6587", "http://www.google.com/"},
109 {L"keyword", L"keyword", "http://example.{searchTerms}.com/"},
110 // in_process_importer_bridge.cc:CreateTemplateURL() will return NULL for
111 // the following bookmark. Consequently, it won't be imported as a search
112 // engine.
113 {L"", L"", "http://%x.example.{searchTerms}.com/"},
116 const AutofillFormDataInfo kFirefoxAutofillEntries[] = {
117 {"name", "John"},
118 {"address", "#123 Cherry Ave"},
119 {"city", "Mountain View"},
120 {"zip", "94043"},
121 {"n300", "+1 (408) 871-4567"},
122 {"name", "john"},
123 {"name", "aguantó"},
124 {"address", "télévision@example.com"},
125 {"city", "&$%$$$ TESTO *&*&^&^& MOKO"},
126 {"zip", "WOHOOOO$$$$$$$$****"},
127 {"n300", "\xe0\xa4\x9f\xe2\x97\x8c\xe0\xa4\xbe\xe0\xa4\xaf\xe0\xa4\xb0"},
128 {"n300", "\xe4\xbb\xa5\xe7\x8e\xa9\xe4\xb8\xba\xe4\xb8\xbb"}
131 class FirefoxObserver : public ProfileWriter,
132 public importer::ImporterProgressObserver {
133 public:
134 explicit FirefoxObserver(bool use_keyword_in_json)
135 : ProfileWriter(NULL),
136 bookmark_count_(0),
137 history_count_(0),
138 password_count_(0),
139 keyword_count_(0),
140 use_keyword_in_json_(use_keyword_in_json) {}
142 // importer::ImporterProgressObserver:
143 void ImportStarted() override {}
144 void ImportItemStarted(importer::ImportItem item) override {}
145 void ImportItemEnded(importer::ImportItem item) override {}
146 void ImportEnded() override {
147 base::MessageLoop::current()->Quit();
148 EXPECT_EQ(arraysize(kFirefoxBookmarks), bookmark_count_);
149 EXPECT_EQ(1U, history_count_);
150 EXPECT_EQ(arraysize(kFirefoxPasswords), password_count_);
151 // The following test case from |kFirefoxKeywords| won't be imported:
152 // "http://%x.example.{searchTerms}.com/"}.
153 // Hence, value of |keyword_count_| should be lower than size of
154 // |kFirefoxKeywords| by 1.
155 EXPECT_EQ(arraysize(kFirefoxKeywords) - 1, keyword_count_);
158 bool BookmarkModelIsLoaded() const override {
159 // Profile is ready for writing.
160 return true;
163 bool TemplateURLServiceIsLoaded() const override { return true; }
165 void AddPasswordForm(const autofill::PasswordForm& form) override {
166 PasswordInfo p = kFirefoxPasswords[password_count_];
167 EXPECT_EQ(p.origin, form.origin.spec());
168 EXPECT_EQ(p.realm, form.signon_realm);
169 EXPECT_EQ(p.action, form.action.spec());
170 EXPECT_EQ(base::ASCIIToUTF16(p.username_element), form.username_element);
171 EXPECT_EQ(base::ASCIIToUTF16(p.username), form.username_value);
172 EXPECT_EQ(base::ASCIIToUTF16(p.password_element), form.password_element);
173 EXPECT_EQ(base::ASCIIToUTF16(p.password), form.password_value);
174 EXPECT_EQ(p.blacklisted, form.blacklisted_by_user);
175 ++password_count_;
178 void AddHistoryPage(const history::URLRows& page,
179 history::VisitSource visit_source) override {
180 ASSERT_EQ(3U, page.size());
181 EXPECT_EQ("http://www.google.com/", page[0].url().spec());
182 EXPECT_EQ(base::ASCIIToUTF16("Google"), page[0].title());
183 EXPECT_EQ("http://www.google.com/", page[1].url().spec());
184 EXPECT_EQ(base::ASCIIToUTF16("Google"), page[1].title());
185 EXPECT_EQ("http://www.cs.unc.edu/~jbs/resources/perl/perl-cgi/programs/"
186 "form1-POST.html", page[2].url().spec());
187 EXPECT_EQ(base::ASCIIToUTF16("example form (POST)"), page[2].title());
188 EXPECT_EQ(history::SOURCE_FIREFOX_IMPORTED, visit_source);
189 ++history_count_;
192 void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks,
193 const base::string16& top_level_folder_name) override {
194 ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kFirefoxBookmarks));
195 // Importer should import the FF favorites the same as the list, in the same
196 // order.
197 for (size_t i = 0; i < bookmarks.size(); ++i) {
198 EXPECT_NO_FATAL_FAILURE(
199 TestEqualBookmarkEntry(bookmarks[i],
200 kFirefoxBookmarks[bookmark_count_])) << i;
201 ++bookmark_count_;
205 void AddAutofillFormDataEntries(
206 const std::vector<autofill::AutofillEntry>& autofill_entries) override {
207 EXPECT_EQ(arraysize(kFirefoxAutofillEntries), autofill_entries.size());
208 for (size_t i = 0; i < arraysize(kFirefoxAutofillEntries); ++i) {
209 EXPECT_EQ(kFirefoxAutofillEntries[i].name,
210 base::UTF16ToUTF8(autofill_entries[i].key().name()));
211 EXPECT_EQ(kFirefoxAutofillEntries[i].value,
212 base::UTF16ToUTF8(autofill_entries[i].key().value()));
216 void AddKeywords(ScopedVector<TemplateURL> template_urls,
217 bool unique_on_host_and_path) override {
218 for (size_t i = 0; i < template_urls.size(); ++i) {
219 // The order might not be deterministic, look in the expected list for
220 // that template URL.
221 bool found = false;
222 const base::string16& imported_keyword = template_urls[i]->keyword();
223 for (size_t j = 0; j < arraysize(kFirefoxKeywords); ++j) {
224 const base::string16 expected_keyword = base::WideToUTF16(
225 use_keyword_in_json_ ?
226 kFirefoxKeywords[j].keyword_in_json :
227 kFirefoxKeywords[j].keyword_in_sqlite);
228 if (imported_keyword == expected_keyword) {
229 EXPECT_EQ(kFirefoxKeywords[j].url, template_urls[i]->url());
230 found = true;
231 break;
234 EXPECT_TRUE(found);
235 ++keyword_count_;
239 void AddFavicons(
240 const favicon_base::FaviconUsageDataList& favicons) override {}
242 private:
243 ~FirefoxObserver() override {}
245 size_t bookmark_count_;
246 size_t history_count_;
247 size_t password_count_;
248 size_t keyword_count_;
250 // Newer versions of Firefox can store custom keyword names in json, which
251 // override the sqlite values. To be able to test both older and newer
252 // versions, tests set this variable to indicate whether to expect the
253 // |keyword_in_sqlite| or |keyword_in_json| values from the reference data.
254 bool use_keyword_in_json_;
257 } // namespace
259 // These tests need to be browser tests in order to be able to run the OOP
260 // import (via ExternalProcessImporterHost) which launches a utility process on
261 // supported platforms.
262 class FirefoxProfileImporterBrowserTest : public InProcessBrowserTest {
263 protected:
264 void SetUp() override {
265 // Creates a new profile in a new subdirectory in the temp directory.
266 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
267 base::FilePath test_path = temp_dir_.path().AppendASCII("ImporterTest");
268 base::DeleteFile(test_path, true);
269 base::CreateDirectory(test_path);
270 profile_path_ = test_path.AppendASCII("profile");
271 app_path_ = test_path.AppendASCII("app");
272 base::CreateDirectory(app_path_);
274 // This will launch the browser test and thus needs to happen last.
275 InProcessBrowserTest::SetUp();
278 void FirefoxImporterBrowserTest(std::string profile_dir,
279 importer::ImporterProgressObserver* observer,
280 ProfileWriter* writer) {
281 base::FilePath data_path;
282 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
283 data_path = data_path.AppendASCII(profile_dir);
284 ASSERT_TRUE(base::CopyDirectory(data_path, profile_path_, true));
286 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
287 data_path = data_path.AppendASCII("firefox3_nss");
288 ASSERT_TRUE(base::CopyDirectory(data_path, profile_path_, false));
290 // Create a directory to house default search engines.
291 base::FilePath default_search_engine_path =
292 app_path_.AppendASCII("searchplugins");
293 base::CreateDirectory(default_search_engine_path);
295 // Create a directory to house custom/installed search engines.
296 base::FilePath custom_search_engine_path =
297 profile_path_.AppendASCII("searchplugins");
298 base::CreateDirectory(custom_search_engine_path);
300 // Copy over search engines.
301 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path));
302 data_path = data_path.AppendASCII("firefox_searchplugins");
303 base::FilePath default_search_engine_source_path =
304 data_path.AppendASCII("default");
305 base::FilePath custom_search_engine_source_path =
306 data_path.AppendASCII("custom");
307 ASSERT_TRUE(base::CopyDirectory(
308 default_search_engine_source_path, default_search_engine_path, false));
309 ASSERT_TRUE(base::CopyDirectory(
310 custom_search_engine_source_path, custom_search_engine_path, false));
312 importer::SourceProfile source_profile;
313 source_profile.importer_type = importer::TYPE_FIREFOX;
314 source_profile.app_path = app_path_;
315 source_profile.source_path = profile_path_;
316 source_profile.locale = "en-US";
318 int items = importer::HISTORY | importer::PASSWORDS | importer::FAVORITES |
319 importer::SEARCH_ENGINES | importer::AUTOFILL_FORM_DATA;
321 // Deletes itself.
322 ExternalProcessImporterHost* host = new ExternalProcessImporterHost;
323 host->set_observer(observer);
324 host->StartImportSettings(
325 source_profile, browser()->profile(), items, writer);
326 base::MessageLoop::current()->Run();
329 base::ScopedTempDir temp_dir_;
330 base::FilePath profile_path_;
331 base::FilePath app_path_;
334 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest,
335 MAYBE_IMPORTER(Firefox30Importer)) {
336 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver(false));
337 FirefoxImporterBrowserTest(
338 "firefox3_profile", observer.get(), observer.get());
341 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest,
342 MAYBE_IMPORTER(Firefox35Importer)) {
343 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver(false));
344 FirefoxImporterBrowserTest(
345 "firefox35_profile", observer.get(), observer.get());
348 IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest,
349 MAYBE_IMPORTER(FirefoxImporter)) {
350 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver(true));
351 FirefoxImporterBrowserTest("firefox_profile", observer.get(), observer.get());