diff options
author | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-15 00:27:20 +0000 |
---|---|---|
committer | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-15 00:27:20 +0000 |
commit | 1851d3b3a7a499157ec236df20bd8d3aa61a1265 (patch) | |
tree | 6ea5b5057ac19b8d77f0b18c6e76dccb7c6d4994 /chrome | |
parent | 9fe5c5244c7df4682ab9c09a769c897253ba7a43 (diff) | |
download | chromium_src-1851d3b3a7a499157ec236df20bd8d3aa61a1265.zip chromium_src-1851d3b3a7a499157ec236df20bd8d3aa61a1265.tar.gz chromium_src-1851d3b3a7a499157ec236df20bd8d3aa61a1265.tar.bz2 |
Import passwords from Firefox 3.1 and above.
BUG=9103
Review URL: http://codereview.chromium.org/165352
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23503 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/importer/firefox3_importer.cc | 26 | ||||
-rw-r--r-- | chrome/browser/importer/importer_unittest.cc | 109 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor.cc | 69 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_linux.h | 8 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_mac.h | 6 | ||||
-rw-r--r-- | chrome/browser/importer/nss_decryptor_win.h | 6 | ||||
-rw-r--r-- | chrome/test/data/firefox35_profile/cert8.db | bin | 0 -> 65536 bytes | |||
-rw-r--r-- | chrome/test/data/firefox35_profile/cookies.sqlite | bin | 0 -> 2048 bytes | |||
-rw-r--r-- | chrome/test/data/firefox35_profile/key3.db | bin | 0 -> 16384 bytes | |||
-rw-r--r-- | chrome/test/data/firefox35_profile/places.sqlite | bin | 0 -> 131072 bytes | |||
-rw-r--r-- | chrome/test/data/firefox35_profile/prefs.js | 32 | ||||
-rw-r--r-- | chrome/test/data/firefox35_profile/search.sqlite | bin | 0 -> 2048 bytes | |||
-rw-r--r-- | chrome/test/data/firefox35_profile/secmod.db | bin | 0 -> 16384 bytes | |||
-rw-r--r-- | chrome/test/data/firefox35_profile/signons.sqlite | bin | 0 -> 11264 bytes |
14 files changed, 201 insertions, 55 deletions
diff --git a/chrome/browser/importer/firefox3_importer.cc b/chrome/browser/importer/firefox3_importer.cc index 8ee342c..0a951ad 100644 --- a/chrome/browser/importer/firefox3_importer.cc +++ b/chrome/browser/importer/firefox3_importer.cc @@ -265,18 +265,22 @@ void Firefox3Importer::ImportPasswords() { !decryptor.Init(app_path_, source_path_)) return; - // Firefox 3 uses signons3.txt to store the passwords. - std::wstring file = source_path_; - file_util::AppendToPath(&file, L"signons3.txt"); - if (!file_util::PathExists(file)) { - file = source_path_; - file_util::AppendToPath(&file, L"signons2.txt"); - } - - std::string content; - file_util::ReadFileToString(file, &content); std::vector<PasswordForm> forms; - decryptor.ParseSignons(content, &forms); + FilePath source_path = FilePath::FromWStringHack(source_path_); + FilePath file = source_path.AppendASCII("signons.sqlite"); + if (file_util::PathExists(file)) { + // Since Firefox 3.1, passwords are in signons.sqlite db. + decryptor.ReadAndParseSignons(file, &forms); + } else { + // Firefox 3.0 uses signons3.txt to store the passwords. + file = source_path.AppendASCII("signons3.txt"); + if (!file_util::PathExists(file)) + file = source_path.AppendASCII("signons2.txt"); + + std::string content; + file_util::ReadFileToString(file, &content); + decryptor.ParseSignons(content, &forms); + } if (!cancelled()) { for (size_t i = 0; i < forms.size(); ++i) { diff --git a/chrome/browser/importer/importer_unittest.cc b/chrome/browser/importer/importer_unittest.cc index 6a348ec..729c2a1 100644 --- a/chrome/browser/importer/importer_unittest.cc +++ b/chrome/browser/importer/importer_unittest.cc @@ -51,6 +51,46 @@ class ImporterTest : public testing::Test { ASSERT_FALSE(file_util::PathExists(test_path_)); } + void Firefox3xImporterTest(std::wstring profile_dir, + ImporterHost::Observer* observer, + ProfileWriter* writer, + bool import_search_plugins) { + std::wstring data_path; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); + file_util::AppendToPath(&data_path, profile_dir + L"\\*"); + ASSERT_TRUE(file_util::CopyDirectory(data_path, profile_path_, true)); + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); + file_util::AppendToPath(&data_path, L"firefox3_nss"); + ASSERT_TRUE(file_util::CopyDirectory(data_path, profile_path_, false)); + + std::wstring search_engine_path = app_path_; + file_util::AppendToPath(&search_engine_path, L"searchplugins"); + CreateDirectory(search_engine_path.c_str(), NULL); + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); + file_util::AppendToPath(&data_path, L"firefox3_searchplugins"); + if (!file_util::PathExists(data_path)) { + // TODO(maruel): Create test data that we can open source! + LOG(ERROR) << L"Missing internal test data"; + return; + } + ASSERT_TRUE(file_util::CopyDirectory(data_path, search_engine_path, false)); + + MessageLoop* loop = MessageLoop::current(); + ProfileInfo profile_info; + profile_info.browser_type = FIREFOX3; + profile_info.app_path = app_path_; + profile_info.source_path = profile_path_; + scoped_refptr<ImporterHost> host = new ImporterHost(loop); + host->SetObserver(observer); + int items = HISTORY | PASSWORDS | FAVORITES; + if (import_search_plugins) + items = items | SEARCH_ENGINES; + loop->PostTask(FROM_HERE, NewRunnableMethod(host.get(), + &ImporterHost::StartImportSettings, profile_info, + static_cast<Profile*>(NULL), items, writer, true)); + loop->Run(); + } + MessageLoopForUI message_loop_; std::wstring test_path_; std::wstring profile_path_; @@ -675,11 +715,15 @@ static const int kDefaultFirefox3KeywordIndex = 8; class Firefox3Observer : public ProfileWriter, public ImporterHost::Observer { public: - Firefox3Observer() : ProfileWriter(NULL) { - bookmark_count_ = 0; - history_count_ = 0; - password_count_ = 0; - keyword_count_ = 0; + Firefox3Observer() + : ProfileWriter(NULL), bookmark_count_(0), history_count_(0), + password_count_(0), keyword_count_(0), import_search_engines_(true) { + } + + Firefox3Observer(bool import_search_engines) + : ProfileWriter(NULL), bookmark_count_(0), history_count_(0), + password_count_(0), keyword_count_(0), + import_search_engines_(import_search_engines) { } virtual void ImportItemStarted(ImportItem item) {} @@ -690,11 +734,13 @@ class Firefox3Observer : public ProfileWriter, EXPECT_EQ(arraysize(kFirefox3Bookmarks), bookmark_count_); EXPECT_EQ(1, history_count_); EXPECT_EQ(arraysize(kFirefox3Passwords), password_count_); - EXPECT_EQ(arraysize(kFirefox3Keywords), keyword_count_); - EXPECT_EQ(kFirefox3Keywords[kDefaultFirefox3KeywordIndex].keyword, - default_keyword_); - EXPECT_EQ(kFirefox3Keywords[kDefaultFirefox3KeywordIndex].url, - default_keyword_url_); + if (import_search_engines_) { + EXPECT_EQ(arraysize(kFirefox3Keywords), keyword_count_); + EXPECT_EQ(kFirefox3Keywords[kDefaultFirefox3KeywordIndex].keyword, + default_keyword_); + EXPECT_EQ(kFirefox3Keywords[kDefaultFirefox3KeywordIndex].url, + default_keyword_url_); + } } virtual bool BookmarkModelIsLoaded() const { @@ -780,42 +826,19 @@ class Firefox3Observer : public ProfileWriter, int history_count_; int password_count_; int keyword_count_; + bool import_search_engines_; std::wstring default_keyword_; std::wstring default_keyword_url_; }; -TEST_F(ImporterTest, Firefox3Importer) { - std::wstring data_path; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); - file_util::AppendToPath(&data_path, L"firefox3_profile\\*"); - ASSERT_TRUE(file_util::CopyDirectory(data_path, profile_path_, true)); - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); - file_util::AppendToPath(&data_path, L"firefox3_nss"); - ASSERT_TRUE(file_util::CopyDirectory(data_path, profile_path_, false)); - - std::wstring search_engine_path = app_path_; - file_util::AppendToPath(&search_engine_path, L"searchplugins"); - CreateDirectory(search_engine_path.c_str(), NULL); - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); - file_util::AppendToPath(&data_path, L"firefox3_searchplugins"); - if (!file_util::PathExists(data_path)) { - // TODO(maruel): Create test data that we can open source! - LOG(ERROR) << L"Missing internal test data"; - return; - } - ASSERT_TRUE(file_util::CopyDirectory(data_path, search_engine_path, false)); - - MessageLoop* loop = MessageLoop::current(); - ProfileInfo profile_info; - profile_info.browser_type = FIREFOX3; - profile_info.app_path = app_path_; - profile_info.source_path = profile_path_; - scoped_refptr<ImporterHost> host = new ImporterHost(loop); +TEST_F(ImporterTest, Firefox30Importer) { Firefox3Observer* observer = new Firefox3Observer(); - host->SetObserver(observer); - loop->PostTask(FROM_HERE, NewRunnableMethod(host.get(), - &ImporterHost::StartImportSettings, profile_info, - static_cast<Profile*>(NULL), - HISTORY | PASSWORDS | FAVORITES | SEARCH_ENGINES, observer, true)); - loop->Run(); + Firefox3xImporterTest(L"firefox3_profile", observer, observer, true); +} + +TEST_F(ImporterTest, Firefox35Importer) { + bool import_search_engines = false; + Firefox3Observer* observer = new Firefox3Observer(import_search_engines); + Firefox3xImporterTest(L"firefox35_profile", observer, observer, + import_search_engines); } diff --git a/chrome/browser/importer/nss_decryptor.cc b/chrome/browser/importer/nss_decryptor.cc index ccdd3ce..13bb14b 100644 --- a/chrome/browser/importer/nss_decryptor.cc +++ b/chrome/browser/importer/nss_decryptor.cc @@ -4,7 +4,9 @@ #include "chrome/browser/importer/nss_decryptor.h" +#include "base/scoped_ptr.h" #include "build/build_config.h" +#include "chrome/common/sqlite_utils.h" #if defined(OS_LINUX) #include <pk11pub.h> @@ -226,3 +228,70 @@ void NSSDecryptor::ParseSignons(const std::string& content, } } } + +bool NSSDecryptor::ReadAndParseSignons(const FilePath& sqlite_file, + std::vector<webkit_glue::PasswordForm>* forms) { + sqlite3* sqlite; + if (OpenSqliteDb(sqlite_file, &sqlite) != SQLITE_OK) + return false; + sqlite_utils::scoped_sqlite_db_ptr db(sqlite); + + SQLStatement s; + const char* stmt = "SELECT hostname FROM moz_disabledHosts"; + if (s.prepare(db.get(), stmt) != SQLITE_OK) + return false; + + GURL::Replacements rep; + rep.ClearQuery(); + rep.ClearRef(); + rep.ClearUsername(); + rep.ClearPassword(); + // Read domains for which passwords are never saved. + while (s.step() == SQLITE_ROW) { + PasswordForm form; + form.origin = GURL(s.column_string(0)).ReplaceComponents(rep); + form.signon_realm = form.origin.GetOrigin().spec(); + form.blacklisted_by_user = true; + forms->push_back(form); + } + + SQLStatement s2; + const char* stmt2 = "SELECT hostname, httpRealm, formSubmitURL, " + "usernameField, passwordField, encryptedUsername, " + "encryptedPassword FROM moz_logins"; + + if (s2.prepare(db.get(), stmt2) != SQLITE_OK) + return false; + + while (s2.step() == SQLITE_ROW) { + GURL url; + std::string realm(s2.column_string(1)); + if (!realm.empty()) { + // In this case, the scheme may not exsit. Assume HTTP. + std::string host(s2.column_string(0)); + if (host.find("://") == std::string::npos) + host = "http://" + host; + url = GURL(host); + } else { + url = GURL(s2.column_string(0)); + } + // Skip this row if the URL is not valid. + if (!url.is_valid()) + continue; + + PasswordForm form; + form.origin = url.ReplaceComponents(rep); + form.signon_realm = form.origin.GetOrigin().spec(); + if (!realm.empty()) + form.signon_realm += realm; + form.ssl_valid = form.origin.SchemeIsSecure(); + // The user name, password and action. + form.username_element = UTF8ToWide(s2.column_string(3)); + form.username_value = Decrypt(s2.column_string(5)); + form.password_element = UTF8ToWide(s2.column_string(4)); + form.password_value = Decrypt(s2.column_string(6)); + form.action = GURL(s2.column_string(2)).ReplaceComponents(rep); + forms->push_back(form); + } + return true; +} diff --git a/chrome/browser/importer/nss_decryptor_linux.h b/chrome/browser/importer/nss_decryptor_linux.h index 508b30a..d73c733 100644 --- a/chrome/browser/importer/nss_decryptor_linux.h +++ b/chrome/browser/importer/nss_decryptor_linux.h @@ -10,6 +10,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/file_path.h" namespace webkit_glue { struct PasswordForm; @@ -35,7 +36,12 @@ class NSSDecryptor { void ParseSignons(const std::string& content, std::vector<webkit_glue::PasswordForm>* forms); - private: + // Reads and parses the Firefox password sqlite db, decrypts the + // username/password and reads other related information. + // The result will be stored in |forms|. + bool ReadAndParseSignons(const FilePath& sqlite_file, + std::vector<webkit_glue::PasswordForm>* forms); +private: // Does not actually free the slot, since we'll free it when NSSDecryptor is // destroyed. void FreeSlot(PK11SlotInfo* slot) const {}; diff --git a/chrome/browser/importer/nss_decryptor_mac.h b/chrome/browser/importer/nss_decryptor_mac.h index 46933cc..1eaf109 100644 --- a/chrome/browser/importer/nss_decryptor_mac.h +++ b/chrome/browser/importer/nss_decryptor_mac.h @@ -9,6 +9,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/file_path.h" #include "base/logging.h" // The following declarations of functions and types are from Firefox @@ -131,6 +132,11 @@ class NSSDecryptor { void ParseSignons(const std::string& content, std::vector<webkit_glue::PasswordForm>* forms); + // Reads and parses the Firefox password sqlite db, decrypts the + // username/password and reads other related information. + // The result will be stored in |forms|. + bool ReadAndParseSignons(const FilePath& sqlite_file, + std::vector<webkit_glue::PasswordForm>* forms); private: PK11SlotInfo* GetKeySlotForDB() const { return PK11_GetInternalKeySlot(); } void FreeSlot(PK11SlotInfo* slot) const { PK11_FreeSlot(slot); } diff --git a/chrome/browser/importer/nss_decryptor_win.h b/chrome/browser/importer/nss_decryptor_win.h index b191206..f0b2345 100644 --- a/chrome/browser/importer/nss_decryptor_win.h +++ b/chrome/browser/importer/nss_decryptor_win.h @@ -131,6 +131,12 @@ class NSSDecryptor { void ParseSignons(const std::string& content, std::vector<webkit_glue::PasswordForm>* forms); + // Reads and parses the Firefox password sqlite db, decrypts the + // username/password and reads other related information. + // The result will be stored in |forms|. + bool ReadAndParseSignons(const FilePath& sqlite_file, + std::vector<webkit_glue::PasswordForm>* forms); + private: // Performs tasks common across all platforms to initialize NSS. bool InitNSS(const std::wstring& db_path, diff --git a/chrome/test/data/firefox35_profile/cert8.db b/chrome/test/data/firefox35_profile/cert8.db Binary files differnew file mode 100644 index 0000000..ac40a33 --- /dev/null +++ b/chrome/test/data/firefox35_profile/cert8.db diff --git a/chrome/test/data/firefox35_profile/cookies.sqlite b/chrome/test/data/firefox35_profile/cookies.sqlite Binary files differnew file mode 100644 index 0000000..f9ec2f5 --- /dev/null +++ b/chrome/test/data/firefox35_profile/cookies.sqlite diff --git a/chrome/test/data/firefox35_profile/key3.db b/chrome/test/data/firefox35_profile/key3.db Binary files differnew file mode 100644 index 0000000..6788cae --- /dev/null +++ b/chrome/test/data/firefox35_profile/key3.db diff --git a/chrome/test/data/firefox35_profile/places.sqlite b/chrome/test/data/firefox35_profile/places.sqlite Binary files differnew file mode 100644 index 0000000..9540a3e --- /dev/null +++ b/chrome/test/data/firefox35_profile/places.sqlite diff --git a/chrome/test/data/firefox35_profile/prefs.js b/chrome/test/data/firefox35_profile/prefs.js new file mode 100644 index 0000000..c65a9be2 --- /dev/null +++ b/chrome/test/data/firefox35_profile/prefs.js @@ -0,0 +1,32 @@ +# Mozilla User Preferences + +/* Do not edit this file. + * + * If you make changes to this file while the application is running, + * the changes will be overwritten when the application exits. + * + * To make a manual change to preferences, you can visit the URL about:config + * For more information, see http://www.mozilla.org/unix/customizing.html#prefs + */ + +user_pref("app.update.lastUpdateTime.addon-background-update-timer", 1211306768); +user_pref("app.update.lastUpdateTime.background-update-timer", 1211306767); +user_pref("app.update.lastUpdateTime.blocklist-background-update-timer", 1211306767); +user_pref("app.update.lastUpdateTime.microsummary-generator-update-timer", 1211306768); +user_pref("app.update.lastUpdateTime.search-engine-update-timer", 1211306768); +user_pref("browser.migration.version", 1); +user_pref("browser.places.importBookmarksHTML", false); +user_pref("browser.places.importDefaults", false); +user_pref("browser.places.leftPaneFolderId", -1); +user_pref("browser.places.migratePostDataAnnotations", false); +user_pref("browser.places.smartBookmarksVersion", 1); +user_pref("browser.places.updateRecentTagsUri", false); +user_pref("browser.search.selectedEngine", "IMDB"); +user_pref("browser.search.useDBForOrder", true); +user_pref("browser.sessionstore.resume_session_once", true); +user_pref("browser.startup.homepage_override.mstone", "rv:1.9"); +user_pref("extensions.enabledItems", "{972ce4c6-7e08-4474-a285-3208198ce6fd}:3.0"); +user_pref("extensions.lastAppVersion", "3.0"); +user_pref("intl.charsetmenu.browser.cache", "UTF-8"); +user_pref("network.cookie.prefsMigrated", true); +user_pref("urlclassifier.keyupdatetime.https://sb-ssl.google.com/safebrowsing/newkey", 1213898771); diff --git a/chrome/test/data/firefox35_profile/search.sqlite b/chrome/test/data/firefox35_profile/search.sqlite Binary files differnew file mode 100644 index 0000000..55d45cb --- /dev/null +++ b/chrome/test/data/firefox35_profile/search.sqlite diff --git a/chrome/test/data/firefox35_profile/secmod.db b/chrome/test/data/firefox35_profile/secmod.db Binary files differnew file mode 100644 index 0000000..cb8cc20 --- /dev/null +++ b/chrome/test/data/firefox35_profile/secmod.db diff --git a/chrome/test/data/firefox35_profile/signons.sqlite b/chrome/test/data/firefox35_profile/signons.sqlite Binary files differnew file mode 100644 index 0000000..b3e0aa0 --- /dev/null +++ b/chrome/test/data/firefox35_profile/signons.sqlite |