diff options
author | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-26 17:58:24 +0000 |
---|---|---|
committer | kuchhal@chromium.org <kuchhal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-26 17:58:24 +0000 |
commit | 4a63ae1381005ba988ca6f49a6c9256ab634db12 (patch) | |
tree | a6724dec3bc9c24646e2e296d9cda8f4977b5358 /chrome | |
parent | b6e97b66c5777bbd1c5fef47a77247f6a3fb319e (diff) | |
download | chromium_src-4a63ae1381005ba988ca6f49a6c9256ab634db12.zip chromium_src-4a63ae1381005ba988ca6f49a6c9256ab634db12.tar.gz chromium_src-4a63ae1381005ba988ca6f49a6c9256ab634db12.tar.bz2 |
Enable Firefox import on OS X. No UI yet.
Review URL: http://codereview.chromium.org/143001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19381 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils.cc | 191 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils.h | 7 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils_linux.cc | 39 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils_mac.cc | 37 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_importer_utils_win.cc | 155 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_profile_lock.cc | 11 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_profile_lock.h | 13 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_profile_lock_posix.cc | 51 | ||||
-rw-r--r-- | chrome/browser/importer/firefox_profile_lock_unittest.cc | 41 | ||||
-rw-r--r-- | chrome/browser/importer/importer.cc | 4 | ||||
-rw-r--r-- | chrome/chrome.gyp | 4 |
11 files changed, 352 insertions, 201 deletions
diff --git a/chrome/browser/importer/firefox_importer_utils.cc b/chrome/browser/importer/firefox_importer_utils.cc index 47816c8..df0e5aa 100644 --- a/chrome/browser/importer/firefox_importer_utils.cc +++ b/chrome/browser/importer/firefox_importer_utils.cc @@ -6,12 +6,6 @@ #include <algorithm> -#if defined(OS_WIN) -#include <shlobj.h> - -#include "app/win_util.h" -#include "base/registry.h" -#endif #include "base/logging.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" @@ -46,82 +40,8 @@ class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter { private: DISALLOW_EVIL_CONSTRUCTORS(FirefoxURLParameterFilter); }; - -#if defined(OS_WIN) -typedef BOOL (WINAPI* SetDllDirectoryFunc)(LPCTSTR lpPathName); - -// A helper class whose destructor calls SetDllDirectory(NULL) to undo the -// effects of a previous SetDllDirectory call. -class SetDllDirectoryCaller { - public: - explicit SetDllDirectoryCaller() : func_(NULL) { } - - ~SetDllDirectoryCaller() { - if (func_) - func_(NULL); - } - - // Sets the SetDllDirectory function pointer to activates this object. - void set_func(SetDllDirectoryFunc func) { func_ = func; } - - private: - SetDllDirectoryFunc func_; -}; -#endif - } // namespace -#if defined(OS_WIN) -// NOTE: Keep these in order since we need test all those paths according -// to priority. For example. One machine has multiple users. One non-admin -// user installs Firefox 2, which causes there is a Firefox2 entry under HKCU. -// One admin user installs Firefox 3, which causes there is a Firefox 3 entry -// under HKLM. So when the non-admin user log in, we should deal with Firefox 2 -// related data instead of Firefox 3. -static const HKEY kFireFoxRegistryPaths[] = { - HKEY_CURRENT_USER, - HKEY_LOCAL_MACHINE -}; - -int GetCurrentFirefoxMajorVersionFromRegistry() { - TCHAR ver_buffer[128]; - DWORD ver_buffer_length = sizeof(ver_buffer); - int highest_version = 0; - // When installing Firefox with admin account, the product keys will be - // written under HKLM\Mozilla. Otherwise it the keys will be written under - // HKCU\Mozilla. - for (int i = 0; i < arraysize(kFireFoxRegistryPaths); ++i) { - bool result = ReadFromRegistry(kFireFoxRegistryPaths[i], - L"Software\\Mozilla\\Mozilla Firefox", - L"CurrentVersion", ver_buffer, &ver_buffer_length); - if (!result) - continue; - highest_version = std::max(highest_version, _wtoi(ver_buffer)); - } - return highest_version; -} - -std::wstring GetFirefoxInstallPathFromRegistry() { - // Detects the path that Firefox is installed in. - std::wstring registry_path = L"Software\\Mozilla\\Mozilla Firefox"; - TCHAR buffer[MAX_PATH]; - DWORD buffer_length = sizeof(buffer); - bool result; - result = ReadFromRegistry(HKEY_LOCAL_MACHINE, registry_path.c_str(), - L"CurrentVersion", buffer, &buffer_length); - if (!result) - return std::wstring(); - registry_path += L"\\" + std::wstring(buffer) + L"\\Main"; - buffer_length = sizeof(buffer); - result = ReadFromRegistry(HKEY_LOCAL_MACHINE, registry_path.c_str(), - L"Install Directory", buffer, &buffer_length); - if (!result) - return std::wstring(); - return buffer; -} -#endif - -#if defined(OS_WIN) || defined(OS_LINUX) bool GetFirefoxVersionAndPathFromProfile(const std::wstring& profile_path, int* version, std::wstring* app_path) { @@ -152,32 +72,6 @@ bool GetFirefoxVersionAndPathFromProfile(const std::wstring& profile_path, return ret; } - -FilePath GetProfilesINI() { - FilePath ini_file; -#if defined(OS_WIN) - // The default location of the profile folder containing user data is - // under the "Application Data" folder in Windows XP. - wchar_t buffer[MAX_PATH] = {0}; - if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, - SHGFP_TYPE_CURRENT, buffer))) { - ini_file = FilePath(buffer).Append(L"Mozilla\\Firefox\\profiles.ini"); - } - -#else - // The default location of the profile folder containing user data is - // under user HOME directory in .mozilla/firefox folder on Linux. - const char *home = getenv("HOME"); - if (home && home[0]) { - ini_file = FilePath(home).Append(".mozilla/firefox/profiles.ini"); - } -#endif - if (file_util::PathExists(ini_file)) - return ini_file; - - return FilePath(); -} - void ParseProfileINI(std::wstring file, DictionaryValue* root) { // Reads the whole INI file. std::string content; @@ -221,7 +115,6 @@ void ParseProfileINI(std::wstring file, DictionaryValue* root) { } } } -#endif bool CanImportURL(const GURL& url) { const char* kInvalidSchemes[] = {"wyciwyg", "place", "about", "chrome"}; @@ -442,12 +335,6 @@ bool IsDefaultHomepage(const GURL& homepage, // class NSSDecryptor. -// static -const wchar_t NSSDecryptor::kNSS3Library[] = L"nss3.dll"; -const wchar_t NSSDecryptor::kSoftokn3Library[] = L"softokn3.dll"; -const wchar_t NSSDecryptor::kPLDS4Library[] = L"plds4.dll"; -const wchar_t NSSDecryptor::kNSPR4Library[] = L"nspr4.dll"; - NSSDecryptor::NSSDecryptor() : NSS_Init(NULL), NSS_Shutdown(NULL), PK11_GetInternalKeySlot(NULL), PK11_CheckUserPassword(NULL), PK11_FreeSlot(NULL), @@ -461,73 +348,9 @@ NSSDecryptor::~NSSDecryptor() { Free(); } -bool NSSDecryptor::Init(const std::wstring& dll_path, - const std::wstring& db_path) { -#if defined(OS_WIN) - // We call SetDllDirectory to work around a Purify bug (GetModuleHandle - // fails inside Purify under certain conditions). SetDllDirectory only - // exists on Windows XP SP1 or later, so we look up its address at run time. - HMODULE kernel32_dll = GetModuleHandle(L"kernel32.dll"); - if (kernel32_dll == NULL) - return false; - SetDllDirectoryFunc set_dll_directory = - (SetDllDirectoryFunc)GetProcAddress(kernel32_dll, "SetDllDirectoryW"); - SetDllDirectoryCaller caller; - - if (set_dll_directory != NULL) { - if (!set_dll_directory(dll_path.c_str())) - return false; - caller.set_func(set_dll_directory); - nss3_dll_ = LoadLibrary(kNSS3Library); - if (nss3_dll_ == NULL) - return false; - } else { - // Fall back on LoadLibraryEx if SetDllDirectory isn't available. We - // actually prefer this method because it doesn't change the DLL search - // path, which is a process-wide property. - std::wstring path = dll_path; - file_util::AppendToPath(&path, kNSS3Library); - nss3_dll_ = LoadLibraryEx(path.c_str(), NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); - if (nss3_dll_ == NULL) - return false; - - // Firefox 2 uses NSS 3.11. Firefox 3 uses NSS 3.12. NSS 3.12 has two - // changes in its DLLs: - // 1. nss3.dll is not linked with softokn3.dll at build time, but rather - // loads softokn3.dll using LoadLibrary in NSS_Init. - // 2. softokn3.dll has a new dependency sqlite3.dll. - // NSS_Init's LoadLibrary call has trouble finding sqlite3.dll. To help - // it out, we preload softokn3.dll using LoadLibraryEx with the - // LOAD_WITH_ALTERED_SEARCH_PATH flag. This helps because LoadLibrary - // doesn't load a DLL again if it's already loaded. This workaround is - // harmless for NSS 3.11. - path = dll_path; - file_util::AppendToPath(&path, kSoftokn3Library); - softokn3_dll_ = LoadLibraryEx(path.c_str(), NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); - if (softokn3_dll_ == NULL) { - Free(); - return false; - } - } - HMODULE plds4_dll = GetModuleHandle(kPLDS4Library); - HMODULE nspr4_dll = GetModuleHandle(kNSPR4Library); -#elif defined(OS_LINUX) - nss3_dll_ = base::LoadNativeLibrary(FilePath("libnss3.so")); - if (nss3_dll_ == NULL) - return false; - base::NativeLibrary plds4_dll = base::LoadNativeLibrary( - FilePath("libplds4.so")); - base::NativeLibrary nspr4_dll = base::LoadNativeLibrary( - FilePath("libnspr4.so")); -#else - // TODO(port): Check on MAC - base::NativeLibrary plds4_dll, nspr4_dll; - NOTIMPLEMENTED(); - return false; -#endif - +bool NSSDecryptor::InitNSS(const std::wstring& db_path, + base::NativeLibrary plds4_dll, + base::NativeLibrary nspr4_dll) { // NSPR DLLs are already loaded now. if (plds4_dll == NULL || nspr4_dll == NULL) { Free(); @@ -581,12 +404,10 @@ void NSSDecryptor::Free() { PR_Cleanup(); is_nss_initialized_ = false; } -#if defined(OS_WIN) || defined(OS_LINUX) if (softokn3_dll_ != NULL) base::UnloadNativeLibrary(softokn3_dll_); if (nss3_dll_ != NULL) base::UnloadNativeLibrary(nss3_dll_); -#endif NSS_Init = NULL; NSS_Shutdown = NULL; PK11_GetInternalKeySlot = NULL; @@ -641,12 +462,6 @@ void NSSDecryptor::Free() { * ***** END LICENSE BLOCK ***** */ std::wstring NSSDecryptor::Decrypt(const std::string& crypt) const { -#if !defined(OS_WIN) && !defined(OS_LINUX) - // TODO(port): Load nss3. - NOTIMPLEMENTED(); - return std::wstring(); -#endif - // Do nothing if NSS is not loaded. if (!nss3_dll_) return std::wstring(); diff --git a/chrome/browser/importer/firefox_importer_utils.h b/chrome/browser/importer/firefox_importer_utils.h index cb44b1c..47deecf 100644 --- a/chrome/browser/importer/firefox_importer_utils.h +++ b/chrome/browser/importer/firefox_importer_utils.h @@ -27,7 +27,6 @@ int GetCurrentFirefoxMajorVersionFromRegistry(); std::wstring GetFirefoxInstallPathFromRegistry(); #endif -#if defined(OS_WIN) || defined(OS_LINUX) // Detects version of Firefox and installation path from given Firefox profile bool GetFirefoxVersionAndPathFromProfile(const std::wstring& profile_path, int* version, @@ -51,7 +50,6 @@ FilePath GetProfilesINI(); // We set "[value]" in path "<Section>.<Key>". For example, the path // "Genenral.StartWithLastProfile" has the value "1". void ParseProfileINI(std::wstring file, DictionaryValue* root); -#endif // Returns true if we want to add the URL to the history. We filter // out the URL with a unsupported scheme. @@ -193,6 +191,11 @@ class NSSDecryptor { std::vector<webkit_glue::PasswordForm>* forms); private: + // Performs tasks common across all platforms to initialize NSS. + bool InitNSS(const std::wstring& db_path, + base::NativeLibrary plds4_dll, + base::NativeLibrary nspr4_dll); + // Methods in Firefox security components. NSSInitFunc NSS_Init; NSSShutdownFunc NSS_Shutdown; diff --git a/chrome/browser/importer/firefox_importer_utils_linux.cc b/chrome/browser/importer/firefox_importer_utils_linux.cc new file mode 100644 index 0000000..66f39a1 --- /dev/null +++ b/chrome/browser/importer/firefox_importer_utils_linux.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/importer/firefox_importer_utils.h" + +FilePath GetProfilesINI() { + FilePath ini_file; + // The default location of the profile folder containing user data is + // under user HOME directory in .mozilla/firefox folder on Linux. + const char *home = getenv("HOME"); + if (home && home[0]) { + ini_file = FilePath(home).Append(".mozilla/firefox/profiles.ini"); + } + if (file_util::PathExists(ini_file)) + return ini_file; + + return FilePath(); +} + +// static +const wchar_t NSSDecryptor::kNSS3Library[] = L"libnss3.so"; +const wchar_t NSSDecryptor::kSoftokn3Library[] = L"libsoftokn3.so"; +const wchar_t NSSDecryptor::kPLDS4Library[] = L"libplds4.so"; +const wchar_t NSSDecryptor::kNSPR4Library[] = L"libnspr4.so"; + +bool NSSDecryptor::Init(const std::wstring& dll_path, + const std::wstring& db_path) { + nss3_dll_ = base::LoadNativeLibrary( + FilePath::FromWStringHack(kNSS3Library)); + if (nss3_dll_ == NULL) + return false; + base::NativeLibrary plds4_lib = base::LoadNativeLibrary( + FilePath::FromWStringHack(kPLDS4Library)); + base::NativeLibrary nspr4_lib = base::LoadNativeLibrary( + FilePath::FromWStringHack(kNSPR4Library)); + + return InitNSS(db_path, plds4_lib, nspr4_lib); +} diff --git a/chrome/browser/importer/firefox_importer_utils_mac.cc b/chrome/browser/importer/firefox_importer_utils_mac.cc new file mode 100644 index 0000000..9fb3cf5 --- /dev/null +++ b/chrome/browser/importer/firefox_importer_utils_mac.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/importer/firefox_importer_utils.h" + +#include "base/logging.h" + +FilePath GetProfilesINI() { + FilePath ini_file; + // ~/Library/Application Support/Firefox on OS X. + // This should be changed to NSSearchPathForDirectoriesInDomains(). + // See bug http://code.google.com/p/chromium/issues/detail?id=15455 + const char *home = getenv("HOME"); + if (home && home[0]) { + ini_file = FilePath(home).Append( + "Library/Application Support/Firefox/profiles.ini"); + } + if (file_util::PathExists(ini_file)) + return ini_file; + + return FilePath(); +} + +// static +const wchar_t NSSDecryptor::kNSS3Library[] = L"libnss3.dylib"; +const wchar_t NSSDecryptor::kSoftokn3Library[] = L"libsoftokn3.dylib"; +const wchar_t NSSDecryptor::kPLDS4Library[] = L"libplds4.dylib"; +const wchar_t NSSDecryptor::kNSPR4Library[] = L"libnspr4.dylib"; + +bool NSSDecryptor::Init(const std::wstring& dll_path, + const std::wstring& db_path) { + // TODO(port): Load the NSS libraries and call InitNSS() + // http://code.google.com/p/chromium/issues/detail?id=15455 + NOTIMPLEMENTED(); + return false; +} diff --git a/chrome/browser/importer/firefox_importer_utils_win.cc b/chrome/browser/importer/firefox_importer_utils_win.cc new file mode 100644 index 0000000..3a531e3 --- /dev/null +++ b/chrome/browser/importer/firefox_importer_utils_win.cc @@ -0,0 +1,155 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/importer/firefox_importer_utils.h" + +#include "base/registry.h" + +namespace { + +typedef BOOL (WINAPI* SetDllDirectoryFunc)(LPCTSTR lpPathName); + +// A helper class whose destructor calls SetDllDirectory(NULL) to undo the +// effects of a previous SetDllDirectory call. +class SetDllDirectoryCaller { + public: + explicit SetDllDirectoryCaller() : func_(NULL) { } + + ~SetDllDirectoryCaller() { + if (func_) + func_(NULL); + } + + // Sets the SetDllDirectory function pointer to activates this object. + void set_func(SetDllDirectoryFunc func) { func_ = func; } + + private: + SetDllDirectoryFunc func_; +}; + +} // namespace + +// NOTE: Keep these in order since we need test all those paths according +// to priority. For example. One machine has multiple users. One non-admin +// user installs Firefox 2, which causes there is a Firefox2 entry under HKCU. +// One admin user installs Firefox 3, which causes there is a Firefox 3 entry +// under HKLM. So when the non-admin user log in, we should deal with Firefox 2 +// related data instead of Firefox 3. +static const HKEY kFireFoxRegistryPaths[] = { + HKEY_CURRENT_USER, + HKEY_LOCAL_MACHINE +}; + +int GetCurrentFirefoxMajorVersionFromRegistry() { + TCHAR ver_buffer[128]; + DWORD ver_buffer_length = sizeof(ver_buffer); + int highest_version = 0; + // When installing Firefox with admin account, the product keys will be + // written under HKLM\Mozilla. Otherwise it the keys will be written under + // HKCU\Mozilla. + for (int i = 0; i < arraysize(kFireFoxRegistryPaths); ++i) { + bool result = ReadFromRegistry(kFireFoxRegistryPaths[i], + L"Software\\Mozilla\\Mozilla Firefox", + L"CurrentVersion", ver_buffer, &ver_buffer_length); + if (!result) + continue; + highest_version = std::max(highest_version, _wtoi(ver_buffer)); + } + return highest_version; +} + +std::wstring GetFirefoxInstallPathFromRegistry() { + // Detects the path that Firefox is installed in. + std::wstring registry_path = L"Software\\Mozilla\\Mozilla Firefox"; + TCHAR buffer[MAX_PATH]; + DWORD buffer_length = sizeof(buffer); + bool result; + result = ReadFromRegistry(HKEY_LOCAL_MACHINE, registry_path.c_str(), + L"CurrentVersion", buffer, &buffer_length); + if (!result) + return std::wstring(); + registry_path += L"\\" + std::wstring(buffer) + L"\\Main"; + buffer_length = sizeof(buffer); + result = ReadFromRegistry(HKEY_LOCAL_MACHINE, registry_path.c_str(), + L"Install Directory", buffer, &buffer_length); + if (!result) + return std::wstring(); + return buffer; +} + +FilePath GetProfilesINI() { + FilePath ini_file; + // The default location of the profile folder containing user data is + // under the "Application Data" folder in Windows XP. + wchar_t buffer[MAX_PATH] = {0}; + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, + SHGFP_TYPE_CURRENT, buffer))) { + ini_file = FilePath(buffer).Append(L"Mozilla\\Firefox\\profiles.ini"); + } + if (file_util::PathExists(ini_file)) + return ini_file; + + return FilePath(); +} + +// static +const wchar_t NSSDecryptor::kNSS3Library[] = L"nss3.dll"; +const wchar_t NSSDecryptor::kSoftokn3Library[] = L"softokn3.dll"; +const wchar_t NSSDecryptor::kPLDS4Library[] = L"plds4.dll"; +const wchar_t NSSDecryptor::kNSPR4Library[] = L"nspr4.dll"; + +bool NSSDecryptor::Init(const std::wstring& dll_path, + const std::wstring& db_path) { + // We call SetDllDirectory to work around a Purify bug (GetModuleHandle + // fails inside Purify under certain conditions). SetDllDirectory only + // exists on Windows XP SP1 or later, so we look up its address at run time. + HMODULE kernel32_dll = GetModuleHandle(L"kernel32.dll"); + if (kernel32_dll == NULL) + return false; + SetDllDirectoryFunc set_dll_directory = + (SetDllDirectoryFunc)GetProcAddress(kernel32_dll, "SetDllDirectoryW"); + SetDllDirectoryCaller caller; + + if (set_dll_directory != NULL) { + if (!set_dll_directory(dll_path.c_str())) + return false; + caller.set_func(set_dll_directory); + nss3_dll_ = LoadLibrary(kNSS3Library); + if (nss3_dll_ == NULL) + return false; + } else { + // Fall back on LoadLibraryEx if SetDllDirectory isn't available. We + // actually prefer this method because it doesn't change the DLL search + // path, which is a process-wide property. + std::wstring path = dll_path; + file_util::AppendToPath(&path, kNSS3Library); + nss3_dll_ = LoadLibraryEx(path.c_str(), NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); + if (nss3_dll_ == NULL) + return false; + + // Firefox 2 uses NSS 3.11. Firefox 3 uses NSS 3.12. NSS 3.12 has two + // changes in its DLLs: + // 1. nss3.dll is not linked with softokn3.dll at build time, but rather + // loads softokn3.dll using LoadLibrary in NSS_Init. + // 2. softokn3.dll has a new dependency sqlite3.dll. + // NSS_Init's LoadLibrary call has trouble finding sqlite3.dll. To help + // it out, we preload softokn3.dll using LoadLibraryEx with the + // LOAD_WITH_ALTERED_SEARCH_PATH flag. This helps because LoadLibrary + // doesn't load a DLL again if it's already loaded. This workaround is + // harmless for NSS 3.11. + path = dll_path; + file_util::AppendToPath(&path, kSoftokn3Library); + softokn3_dll_ = LoadLibraryEx(path.c_str(), NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); + if (softokn3_dll_ == NULL) { + Free(); + return false; + } + } + HMODULE plds4_dll = GetModuleHandle(kPLDS4Library); + HMODULE nspr4_dll = GetModuleHandle(kNSPR4Library); + + return InitNSS(db_path, plds4_dll, nspr4_dll); +} diff --git a/chrome/browser/importer/firefox_profile_lock.cc b/chrome/browser/importer/firefox_profile_lock.cc index f51a9f9..4503d64 100644 --- a/chrome/browser/importer/firefox_profile_lock.cc +++ b/chrome/browser/importer/firefox_profile_lock.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -53,11 +53,16 @@ // static #if defined(OS_LINUX) -// TODO(rahulk): Even though this is called OLD_LOCK_FILE_NAME in Firefox code // http://www.google.com/codesearch/p?hl=en#e_ObwTAVPyo/profile/dirserviceprovider/src/nsProfileLock.cpp&l=433 -// this seems to work with Firefox 3.0. const FilePath::CharType* FirefoxProfileLock::kLockFileName = + FILE_PATH_LITERAL(".parentlock"); +const FilePath::CharType* FirefoxProfileLock::kOldLockFileName = FILE_PATH_LITERAL("lock"); +#elif defined(OS_MACOSX) +const FilePath::CharType* FirefoxProfileLock::kLockFileName = + FILE_PATH_LITERAL(".parentlock"); +const FilePath::CharType* FirefoxProfileLock::kOldLockFileName = + FILE_PATH_LITERAL("parent.lock"); #else const FilePath::CharType* FirefoxProfileLock::kLockFileName = FILE_PATH_LITERAL("parent.lock"); diff --git a/chrome/browser/importer/firefox_profile_lock.h b/chrome/browser/importer/firefox_profile_lock.h index 1474869..1c1c7ee 100644 --- a/chrome/browser/importer/firefox_profile_lock.h +++ b/chrome/browser/importer/firefox_profile_lock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -84,6 +84,7 @@ class FirefoxProfileLock { FRIEND_TEST(FirefoxImporterTest, ProfileLockOrphaned); static const FilePath::CharType* kLockFileName; + static const FilePath::CharType* kOldLockFileName; void Init(); @@ -95,6 +96,16 @@ class FirefoxProfileLock { HANDLE lock_handle_; #elif defined(OS_POSIX) int lock_fd_; + + // On Posix systems Firefox apparently first tries to put a fcntl lock + // on a file and if that fails, it does a regular exculsive open on another + // file. This variable contains the location of this other file. + FilePath old_lock_file_; + + // Method that tries to put a fcntl lock on file specified by |lock_file_|. + // Returns false if lock is already help by another process. true in all + // other cases. + bool LockWithFcntl(); #endif DISALLOW_COPY_AND_ASSIGN(FirefoxProfileLock); diff --git a/chrome/browser/importer/firefox_profile_lock_posix.cc b/chrome/browser/importer/firefox_profile_lock_posix.cc index b32dd54..919b04a 100644 --- a/chrome/browser/importer/firefox_profile_lock_posix.cc +++ b/chrome/browser/importer/firefox_profile_lock_posix.cc @@ -1,9 +1,10 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/importer/firefox_profile_lock.h" +#include <errno.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> @@ -62,7 +63,14 @@ void FirefoxProfileLock::Init() { void FirefoxProfileLock::Lock() { if (HasAcquired()) return; - lock_fd_ = open(lock_file_.value().c_str(), O_CREAT | O_EXCL, 0644); + + bool fcntl_lock = LockWithFcntl(); + if (!fcntl_lock) { + return; + } else if (!HasAcquired()) { + old_lock_file_ = lock_file_.DirName().Append(kOldLockFileName); + lock_fd_ = open(old_lock_file_.value().c_str(), O_CREAT | O_EXCL, 0644); + } } void FirefoxProfileLock::Unlock() { @@ -70,9 +78,46 @@ void FirefoxProfileLock::Unlock() { return; close(lock_fd_); lock_fd_ = -1; - file_util::Delete(lock_file_, false); + file_util::Delete(old_lock_file_, false); } bool FirefoxProfileLock::HasAcquired() { return (lock_fd_ >= 0); } + +// This function tries to lock Firefox profile using fcntl(). The return +// value of this function together with HasAcquired() tells the current status +// of lock. +// if return == false: Another process has lock to the profile. +// if return == true && HasAcquired() == true: successfully acquired the lock. +// if return == false && HasAcquired() == false: Failed to acquire lock due +// to some error (so that we can try alternate method of profile lock). +bool FirefoxProfileLock::LockWithFcntl() { + lock_fd_ = open(lock_file_.value().c_str(), O_WRONLY | O_CREAT | O_TRUNC, + 0666); + if (lock_fd_ == -1) + return true; + + struct flock lock; + lock.l_start = 0; + lock.l_len = 0; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + + struct flock testlock = lock; + if (fcntl(lock_fd_, F_GETLK, &testlock) == -1) { + close(lock_fd_); + lock_fd_ = -1; + return true; + } else if (fcntl(lock_fd_, F_SETLK, &lock) == -1) { + close(lock_fd_); + lock_fd_ = -1; + if (errno == EAGAIN || errno == EACCES) + return false; + else + return true; + } else { + // We have the lock. + return true; + } +} diff --git a/chrome/browser/importer/firefox_profile_lock_unittest.cc b/chrome/browser/importer/firefox_profile_lock_unittest.cc new file mode 100644 index 0000000..4345048 --- /dev/null +++ b/chrome/browser/importer/firefox_profile_lock_unittest.cc @@ -0,0 +1,41 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" + +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/process_util.h" +#include "base/string_util.h" +#include "chrome/browser/importer/firefox_profile_lock.h" +#include "chrome/common/chrome_paths.h" + +class FirefoxProfileLockTest : public testing::Test { + public: + protected: + virtual void SetUp() { + ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_path_)); + std::wstring dir_name(L"FirefoxProfileLockTest"); + dir_name.append(StringPrintf(L"-%d", base::GetCurrentProcId())); + test_path_ = test_path_.Append(FilePath::FromWStringHack(dir_name)); + file_util::Delete(test_path_, true); + file_util::CreateDirectory(test_path_); + } + + virtual void TearDown() { + ASSERT_TRUE(file_util::Delete(test_path_, true)); + ASSERT_FALSE(file_util::PathExists(test_path_)); + } + + FilePath test_path_; +}; + +TEST_F(FirefoxProfileLockTest, LockTest) { + FirefoxProfileLock lock1(test_path_.ToWStringHack()); + ASSERT_TRUE(lock1.HasAcquired()); + lock1.Unlock(); + ASSERT_FALSE(lock1.HasAcquired()); + lock1.Lock(); + ASSERT_TRUE(lock1.HasAcquired()); +} diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc index a4987f2..74d2694 100644 --- a/chrome/browser/importer/importer.cc +++ b/chrome/browser/importer/importer.cc @@ -679,9 +679,6 @@ void ImporterHost::DetectIEProfiles() { #endif void ImporterHost::DetectFirefoxProfiles() { -#if defined(OS_MACOSX) - NOTIMPLEMENTED(); -#else DictionaryValue root; std::wstring ini_file = GetProfilesINI().ToWStringHack(); ParseProfileINI(ini_file, &root); @@ -761,7 +758,6 @@ void ImporterHost::DetectFirefoxProfiles() { SEARCH_ENGINES; source_profiles_.push_back(firefox); } -#endif } void ImporterHost::DetectGoogleToolbarProfiles() { diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index d7ea225..ddd2c9b 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1114,6 +1114,9 @@ 'browser/importer/firefox3_importer.cc', 'browser/importer/firefox3_importer.h', 'browser/importer/firefox_importer_utils.cc', + 'browser/importer/firefox_importer_utils_linux.cc', + 'browser/importer/firefox_importer_utils_mac.cc', + 'browser/importer/firefox_importer_utils_win.cc', 'browser/importer/firefox_importer_utils.h', 'browser/importer/firefox_profile_lock.cc', 'browser/importer/firefox_profile_lock.h', @@ -3443,6 +3446,7 @@ 'browser/importer/firefox_importer_unittest.cc', 'browser/importer/importer_unittest.cc', 'browser/importer/toolbar_importer_unittest.cc', + 'browser/importer/firefox_profile_lock_unittest.cc', 'browser/keychain_mock_mac.cc', 'browser/keychain_mock_mac.h', 'browser/login_prompt_unittest.cc', |