| 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. | 
|  |