firefox_importer_browsertest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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. 4 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" 26 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 31#else 32#define MAYBE_IMPORTER(x) x 33#endif 34 35namespace { 36 37struct PasswordInfo { 38 const char* origin; 39 const char* action; 40 const char* realm; 41 const char* username_element; 42 const char* username; 43 const char* password_element; 44 const char* password; 45 bool blacklisted; 46}; 47 48struct KeywordInfo { 49 const wchar_t* keyword; 50 const char* url; 51}; 52 53const BookmarkInfo kFirefoxBookmarks[] = { 54 {true, 1, {"Bookmarks Toolbar"}, 55 L"Toolbar", 56 "http://site/"}, 57 {false, 0, {}, 58 L"Title", 59 "http://www.google.com/"}, 60}; 61 62const 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}, 67}; 68 69const KeywordInfo kFirefoxKeywords[] = { 70 { L"amazon.com", 71 "http://www.amazon.com/exec/obidos/external-search/?field-keywords=" 72 "{searchTerms}&mode=blended" }, 73 { L"answers.com", 74 "http://www.answers.com/main/ntquery?s={searchTerms}&gwp=13" }, 75 { L"search.creativecommons.org", 76 "http://search.creativecommons.org/?q={searchTerms}" }, 77 { L"search.ebay.com", 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" }, 81 { L"google.com", 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" }, 87 { L"flickr.com", 88 "http://www.flickr.com/photos/tags/?q={searchTerms}" }, 89 { L"imdb.com", 90 "http://www.imdb.com/find?q={searchTerms}" }, 91 { L"webster.com", 92 "http://www.webster.com/cgi-bin/dictionary?va={searchTerms}" }, 93 // Search keywords. 94 { L"\x4E2D\x6587", "http://www.google.com/" }, 95}; 96 97class FirefoxObserver : public ProfileWriter, 98 public importer::ImporterProgressObserver { 99 public: 100 FirefoxObserver() 101 : ProfileWriter(NULL), 102 bookmark_count_(0), 103 history_count_(0), 104 password_count_(0), 105 keyword_count_(0) {} 106 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_); 117 } 118 119 virtual bool BookmarkModelIsLoaded() const OVERRIDE { 120 // Profile is ready for writing. 121 return true; 122 } 123 124 virtual bool TemplateURLServiceIsLoaded() const OVERRIDE { 125 return true; 126 } 127 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); 138 ++password_count_; 139 } 140 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); 152 ++history_count_; 153 } 154 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 160 // order. 161 for (size_t i = 0; i < bookmarks.size(); ++i) { 162 EXPECT_NO_FATAL_FAILURE( 163 TestEqualBookmarkEntry(bookmarks[i], 164 kFirefoxBookmarks[bookmark_count_])) << i; 165 ++bookmark_count_; 166 } 167 } 168 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. 174 bool found = false; 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()); 179 found = true; 180 break; 181 } 182 } 183 EXPECT_TRUE(found); 184 ++keyword_count_; 185 } 186 } 187 188 virtual void AddFavicons( 189 const std::vector<ImportedFaviconUsage>& favicons) OVERRIDE { 190 } 191 192 private: 193 virtual ~FirefoxObserver() {} 194 195 size_t bookmark_count_; 196 size_t history_count_; 197 size_t password_count_; 198 size_t keyword_count_; 199}; 200 201} // namespace 202 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. 206class FirefoxProfileImporterBrowserTest : public InProcessBrowserTest { 207 protected: 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_); 217 218 // This will launch the browser test and thus needs to happen last. 219 InProcessBrowserTest::SetUp(); 220 } 221 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)); 229 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)); 233 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); 238 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); 243 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)); 255 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"; 261 262 int items = importer::HISTORY | importer::PASSWORDS | importer::FAVORITES | 263 importer::SEARCH_ENGINES; 264 265 // Deletes itself. 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(); 271 } 272 273 base::ScopedTempDir temp_dir_; 274 base::FilePath profile_path_; 275 base::FilePath app_path_; 276}; 277 278IN_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()); 283} 284 285IN_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()); 290} 291 292IN_PROC_BROWSER_TEST_F(FirefoxProfileImporterBrowserTest, 293 MAYBE_IMPORTER(FirefoxImporter)) { 294 scoped_refptr<FirefoxObserver> observer(new FirefoxObserver()); 295 FirefoxImporterBrowserTest("firefox_profile", observer.get(), observer.get()); 296} 297