Index: chrome/browser/password_manager/native_backend_gnome_x.cc |
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc |
index 6fa8f6c9c98d83a257ca688bc5538171785a6082..9097587179fd0d92db893683c304613429e965b2 100644 |
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc |
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc |
@@ -4,9 +4,6 @@ |
#include "chrome/browser/password_manager/native_backend_gnome_x.h" |
-#include <dlfcn.h> |
-#include <gnome-keyring.h> |
- |
#include <map> |
#include <string> |
#include <vector> |
@@ -17,6 +14,7 @@ |
#include "base/string_util.h" |
#include "base/stringprintf.h" |
#include "base/synchronization/waitable_event.h" |
+#include "base/threading/thread_restrictions.h" |
#include "base/time.h" |
#include "base/utf_string_conversions.h" |
#include "content/public/browser/browser_thread.h" |
@@ -24,69 +22,6 @@ |
using content::BrowserThread; |
using content::PasswordForm; |
-#define GNOME_KEYRING_DEFINE_POINTER(name) \ |
- typeof(&::gnome_keyring_##name) GnomeKeyringLoader::gnome_keyring_##name; |
-GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_POINTER) |
-#undef GNOME_KEYRING_DEFINE_POINTER |
- |
-bool GnomeKeyringLoader::keyring_loaded = false; |
- |
-#if defined(DLOPEN_GNOME_KEYRING) |
- |
-#define GNOME_KEYRING_FUNCTION_INFO(name) \ |
- {"gnome_keyring_"#name, reinterpret_cast<void**>(&gnome_keyring_##name)}, |
-const GnomeKeyringLoader::FunctionInfo GnomeKeyringLoader::functions[] = { |
- GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION_INFO) |
- {NULL, NULL} |
-}; |
-#undef GNOME_KEYRING_FUNCTION_INFO |
- |
-/* Load the library and initialize the function pointers. */ |
-bool GnomeKeyringLoader::LoadGnomeKeyring() { |
- if (keyring_loaded) |
- return true; |
- |
- void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL); |
- if (!handle) { |
- // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because |
- // either the user asked for this, or we autodetected it incorrectly. (Or |
- // the system has broken libraries, which is also good to warn about.) |
- LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); |
- return false; |
- } |
- |
- for (size_t i = 0; functions[i].name; ++i) { |
- dlerror(); |
- *functions[i].pointer = dlsym(handle, functions[i].name); |
- const char* error = dlerror(); |
- if (error) { |
- LOG(ERROR) << "Unable to load symbol " |
- << functions[i].name << ": " << error; |
- dlclose(handle); |
- return false; |
- } |
- } |
- |
- keyring_loaded = true; |
- // We leak the library handle. That's OK: this function is called only once. |
- return true; |
-} |
- |
-#else // defined(DLOPEN_GNOME_KEYRING) |
- |
-bool GnomeKeyringLoader::LoadGnomeKeyring() { |
- if (keyring_loaded) |
- return true; |
-#define GNOME_KEYRING_ASSIGN_POINTER(name) \ |
- gnome_keyring_##name = &::gnome_keyring_##name; |
- GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_ASSIGN_POINTER) |
-#undef GNOME_KEYRING_ASSIGN_POINTER |
- keyring_loaded = true; |
- return true; |
-} |
- |
-#endif // defined(DLOPEN_GNOME_KEYRING) |
- |
namespace { |
const char kGnomeKeyringAppString[] = "chrome"; |
@@ -99,6 +34,8 @@ PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
std::map<std::string, std::string> string_attr_map; |
std::map<std::string, uint32_t> uint_attr_map; |
for (guint i = 0; i < attrs->len; ++i) { |
+ // Note: gnome_keyring_attribute_list_index below is a macro |
+ // and not a function call. |
GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index(attrs, i); |
if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) |
string_attr_map[attr.name] = attr.value.string; |
@@ -194,11 +131,15 @@ const GnomeKeyringPasswordSchema kGnomeSchema = { |
// a WaitResult() method should be called to wait for the result. Each instance |
// supports only one outstanding method at a time, though multiple instances may |
// be used in parallel. |
-class GKRMethod : public GnomeKeyringLoader { |
+class GKRMethod { |
public: |
typedef NativeBackendGnome::PasswordFormList PasswordFormList; |
- GKRMethod() : event_(false, false), result_(GNOME_KEYRING_RESULT_CANCELLED) {} |
+ explicit GKRMethod(const LibGnomeKeyringLoader* loader) |
+ : loader_(loader), |
+ event_(false, false), |
+ result_(GNOME_KEYRING_RESULT_CANCELLED) { |
+ } |
// Action methods. These call gnome_keyring_* functions. Call from UI thread. |
// See GetProfileSpecificAppString() for more information on the app string. |
@@ -224,6 +165,8 @@ class GKRMethod : public GnomeKeyringLoader { |
static void OnOperationGetList(GnomeKeyringResult result, GList* list, |
gpointer data); |
+ const LibGnomeKeyringLoader* loader_; |
+ |
base::WaitableEvent event_; |
GnomeKeyringResult result_; |
NativeBackendGnome::PasswordFormList forms_; |
@@ -236,7 +179,7 @@ void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { |
// We don't want to actually save passwords as though on January 1, 1970. |
if (!date_created) |
date_created = time(NULL); |
- gnome_keyring_store_password( |
+ loader_->gnome_keyring_store_password( |
&kGnomeSchema, |
NULL, // Default keyring. |
form.origin.spec().c_str(), // Display name. |
@@ -264,7 +207,7 @@ void GKRMethod::AddLoginSearch(const PasswordForm& form, |
const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// Search GNOME Keyring for matching passwords to update. |
- gnome_keyring_find_itemsv( |
+ loader_->gnome_keyring_find_itemsv( |
GNOME_KEYRING_ITEM_GENERIC_SECRET, |
OnOperationGetList, |
this, // data |
@@ -290,7 +233,7 @@ void GKRMethod::UpdateLoginSearch(const PasswordForm& form, |
const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// Search GNOME Keyring for matching passwords to update. |
- gnome_keyring_find_itemsv( |
+ loader_->gnome_keyring_find_itemsv( |
GNOME_KEYRING_ITEM_GENERIC_SECRET, |
OnOperationGetList, |
this, // data |
@@ -313,7 +256,7 @@ void GKRMethod::UpdateLoginSearch(const PasswordForm& form, |
void GKRMethod::RemoveLogin(const PasswordForm& form, const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// We find forms using the same fields as LoginDatabase::RemoveLogin(). |
- gnome_keyring_delete_password( |
+ loader_->gnome_keyring_delete_password( |
&kGnomeSchema, |
OnOperationDone, |
this, // data |
@@ -332,7 +275,7 @@ void GKRMethod::RemoveLogin(const PasswordForm& form, const char* app_string) { |
void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// Search GNOME Keyring for matching passwords. |
- gnome_keyring_find_itemsv( |
+ loader_->gnome_keyring_find_itemsv( |
GNOME_KEYRING_ITEM_GENERIC_SECRET, |
OnOperationGetList, |
this, // data |
@@ -348,7 +291,7 @@ void GKRMethod::GetLoginsList(uint32_t blacklisted_by_user, |
const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// Search GNOME Keyring for matching passwords. |
- gnome_keyring_find_itemsv( |
+ loader_->gnome_keyring_find_itemsv( |
GNOME_KEYRING_ITEM_GENERIC_SECRET, |
OnOperationGetList, |
this, // data |
@@ -364,7 +307,7 @@ void GKRMethod::GetAllLogins(const char* app_string) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
// We need to search for something, otherwise we get no results - so |
// we search for the fixed application string. |
- gnome_keyring_find_itemsv( |
+ loader_->gnome_keyring_find_itemsv( |
GNOME_KEYRING_ITEM_GENERIC_SECRET, |
OnOperationGetList, |
this, // data |
@@ -433,12 +376,15 @@ NativeBackendGnome::~NativeBackendGnome() { |
} |
bool NativeBackendGnome::Init() { |
- return LoadGnomeKeyring() && gnome_keyring_is_available(); |
+ // TODO(phajdan.jr): Redesign the code to load library on different thread. |
+ base::ThreadRestrictions::ScopedAllowIO allow_io; |
+ return libgnome_keyring_loader_.Load("libgnome-keyring.so.0") && |
+ libgnome_keyring_loader_.gnome_keyring_is_available(); |
} |
bool NativeBackendGnome::RawAddLogin(const PasswordForm& form) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::AddLogin, |
base::Unretained(&method), |
@@ -446,7 +392,8 @@ bool NativeBackendGnome::RawAddLogin(const PasswordForm& form) { |
GnomeKeyringResult result = method.WaitResult(); |
if (result != GNOME_KEYRING_RESULT_OK) { |
LOG(ERROR) << "Keyring save failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
// Successful write. Try migration if necessary. |
@@ -462,7 +409,7 @@ bool NativeBackendGnome::AddLogin(const PasswordForm& form) { |
// We'd add the new one first, and then delete the original, but then the |
// delete might actually delete the newly-added entry! |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::AddLoginSearch, |
base::Unretained(&method), |
@@ -472,7 +419,8 @@ bool NativeBackendGnome::AddLogin(const PasswordForm& form) { |
if (result != GNOME_KEYRING_RESULT_OK && |
result != GNOME_KEYRING_RESULT_NO_MATCH) { |
LOG(ERROR) << "Keyring find failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
if (forms.size() > 0) { |
@@ -502,7 +450,7 @@ bool NativeBackendGnome::UpdateLogin(const PasswordForm& form) { |
// the new one first, and then delete the original, but then the delete might |
// actually delete the newly-added entry! |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::UpdateLoginSearch, |
base::Unretained(&method), |
@@ -511,7 +459,8 @@ bool NativeBackendGnome::UpdateLogin(const PasswordForm& form) { |
GnomeKeyringResult result = method.WaitResult(&forms); |
if (result != GNOME_KEYRING_RESULT_OK) { |
LOG(ERROR) << "Keyring find failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
@@ -548,7 +497,7 @@ bool NativeBackendGnome::UpdateLogin(const PasswordForm& form) { |
bool NativeBackendGnome::RemoveLogin(const PasswordForm& form) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::RemoveLogin, |
base::Unretained(&method), |
@@ -558,7 +507,8 @@ bool NativeBackendGnome::RemoveLogin(const PasswordForm& form) { |
// Warning, not error, because this can sometimes happen due to the user |
// racing with the daemon to delete the password a second time. |
LOG(WARNING) << "Keyring delete failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
// Successful write. Try migration if necessary. Note that presumably if we've |
@@ -595,7 +545,7 @@ bool NativeBackendGnome::RemoveLoginsCreatedBetween( |
bool NativeBackendGnome::GetLogins(const PasswordForm& form, |
PasswordFormList* forms) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::GetLogins, |
base::Unretained(&method), |
@@ -605,7 +555,8 @@ bool NativeBackendGnome::GetLogins(const PasswordForm& form, |
return true; |
if (result != GNOME_KEYRING_RESULT_OK) { |
LOG(ERROR) << "Keyring find failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
// Successful read of actual data. Try migration if necessary. |
@@ -652,7 +603,7 @@ bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, |
uint32_t blacklisted_by_user = !autofillable; |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::GetLoginsList, |
base::Unretained(&method), |
@@ -662,7 +613,8 @@ bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, |
return true; |
if (result != GNOME_KEYRING_RESULT_OK) { |
LOG(ERROR) << "Keyring find failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
// Successful read of actual data. Try migration if necessary. |
@@ -672,7 +624,7 @@ bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, |
} |
bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { |
- GKRMethod method; |
+ GKRMethod method(&libgnome_keyring_loader_); |
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
base::Bind(&GKRMethod::GetAllLogins, |
base::Unretained(&method), |
@@ -682,7 +634,8 @@ bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { |
return true; |
if (result != GNOME_KEYRING_RESULT_OK) { |
LOG(ERROR) << "Keyring find failed: " |
- << gnome_keyring_result_to_message(result); |
+ << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
+ result); |
return false; |
} |
// Successful read of actual data. Try migration if necessary. |