| Index: chrome/browser/password_manager/password_store_gnome.cc
|
| ===================================================================
|
| --- chrome/browser/password_manager/password_store_gnome.cc (revision 48988)
|
| +++ chrome/browser/password_manager/password_store_gnome.cc (working copy)
|
| @@ -4,6 +4,11 @@
|
|
|
| #include "chrome/browser/password_manager/password_store_gnome.h"
|
|
|
| +#if defined(DLOPEN_GNOME_KEYRING)
|
| +#include <dlfcn.h>
|
| +#endif
|
| +
|
| +#include <map>
|
| #include <string>
|
|
|
| #include "base/logging.h"
|
| @@ -17,6 +22,117 @@
|
| using std::vector;
|
| using webkit_glue::PasswordForm;
|
|
|
| +/* Many of the gnome_keyring_* functions use variable arguments, which makes
|
| + * them difficult if not impossible to wrap in C. Therefore, we want the
|
| + * actual uses below to either call the functions directly (if we are linking
|
| + * against libgnome-keyring), or call them via appropriately-typed function
|
| + * pointers (if we are dynamically loading libgnome-keyring).
|
| + *
|
| + * Thus, instead of making a wrapper class with two implementations, we use
|
| + * the preprocessor to rename the calls below in the dynamic load case, and
|
| + * provide a function to initialize a set of function pointers that have the
|
| + * alternate names. We also make sure the types are correct, since otherwise
|
| + * dynamic loading like this would leave us vulnerable to signature changes. */
|
| +
|
| +#if defined(DLOPEN_GNOME_KEYRING)
|
| +
|
| +namespace {
|
| +
|
| +gboolean (*wrap_gnome_keyring_is_available)();
|
| +GnomeKeyringResult (*wrap_gnome_keyring_store_password_sync)( // NOLINT
|
| + const GnomeKeyringPasswordSchema* schema, const gchar* keyring,
|
| + const gchar* display_name, const gchar* password, ...);
|
| +GnomeKeyringResult (*wrap_gnome_keyring_delete_password_sync)( // NOLINT
|
| + const GnomeKeyringPasswordSchema* schema, ...);
|
| +GnomeKeyringResult (*wrap_gnome_keyring_find_itemsv_sync)( // NOLINT
|
| + GnomeKeyringItemType type, GList** found, ...);
|
| +const gchar* (*wrap_gnome_keyring_result_to_message)(GnomeKeyringResult res);
|
| +void (*wrap_gnome_keyring_found_list_free)(GList* found_list);
|
| +
|
| +/* Cause the compiler to complain if the types of the above function pointers
|
| + * do not correspond to the types of the actual gnome_keyring_* functions. */
|
| +#define GNOME_KEYRING_VERIFY_TYPE(name) \
|
| + typeof(&gnome_keyring_##name) name = wrap_gnome_keyring_##name; name = name
|
| +
|
| +inline void VerifyGnomeKeyringTypes() {
|
| + GNOME_KEYRING_VERIFY_TYPE(is_available);
|
| + GNOME_KEYRING_VERIFY_TYPE(store_password_sync);
|
| + GNOME_KEYRING_VERIFY_TYPE(delete_password_sync);
|
| + GNOME_KEYRING_VERIFY_TYPE(find_itemsv_sync);
|
| + GNOME_KEYRING_VERIFY_TYPE(result_to_message);
|
| + GNOME_KEYRING_VERIFY_TYPE(found_list_free);
|
| +}
|
| +#undef GNOME_KEYRING_VERIFY_TYPE
|
| +
|
| +/* Make it easy to initialize the function pointers above with a loop below. */
|
| +#define GNOME_KEYRING_FUNCTION(name) \
|
| + {#name, reinterpret_cast<void**>(&wrap_##name)}
|
| +const struct {
|
| + const char* name;
|
| + void** pointer;
|
| +} gnome_keyring_functions[] = {
|
| + GNOME_KEYRING_FUNCTION(gnome_keyring_is_available),
|
| + GNOME_KEYRING_FUNCTION(gnome_keyring_store_password_sync),
|
| + GNOME_KEYRING_FUNCTION(gnome_keyring_delete_password_sync),
|
| + GNOME_KEYRING_FUNCTION(gnome_keyring_find_itemsv_sync),
|
| + GNOME_KEYRING_FUNCTION(gnome_keyring_result_to_message),
|
| + GNOME_KEYRING_FUNCTION(gnome_keyring_found_list_free),
|
| + {NULL, NULL}
|
| +};
|
| +#undef GNOME_KEYRING_FUNCTION
|
| +
|
| +/* Allow application code below to use the normal function names, but actually
|
| + * end up using the function pointers above instead. */
|
| +#define gnome_keyring_is_available \
|
| + wrap_gnome_keyring_is_available
|
| +#define gnome_keyring_store_password_sync \
|
| + wrap_gnome_keyring_store_password_sync
|
| +#define gnome_keyring_delete_password_sync \
|
| + wrap_gnome_keyring_delete_password_sync
|
| +#define gnome_keyring_find_itemsv_sync \
|
| + wrap_gnome_keyring_find_itemsv_sync
|
| +#define gnome_keyring_result_to_message \
|
| + wrap_gnome_keyring_result_to_message
|
| +#define gnome_keyring_found_list_free \
|
| + wrap_gnome_keyring_found_list_free
|
| +
|
| +/* Load the library and initialize the function pointers. */
|
| +bool LoadGnomeKeyring() {
|
| + void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL);
|
| + if (!handle) {
|
| + LOG(INFO) << "Could not find libgnome-keyring.so.0";
|
| + return false;
|
| + }
|
| + for (size_t i = 0; gnome_keyring_functions[i].name; ++i) {
|
| + dlerror();
|
| + *gnome_keyring_functions[i].pointer =
|
| + dlsym(handle, gnome_keyring_functions[i].name);
|
| + const char* error = dlerror();
|
| + if (error) {
|
| + LOG(ERROR) << "Unable to load symbol " <<
|
| + gnome_keyring_functions[i].name << ": " << error;
|
| + dlclose(handle);
|
| + return false;
|
| + }
|
| + }
|
| + // We leak the library handle. That's OK: this function is called only once.
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +#else // DLOPEN_GNOME_KEYRING
|
| +
|
| +namespace {
|
| +
|
| +bool LoadGnomeKeyring() {
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +#endif // DLOPEN_GNOME_KEYRING
|
| +
|
| #define GNOME_KEYRING_APPLICATION_CHROME "chrome"
|
|
|
| // Schema is analagous to the fields in PasswordForm.
|
| @@ -49,7 +165,9 @@
|
| }
|
|
|
| bool PasswordStoreGnome::Init() {
|
| - return PasswordStore::Init() && gnome_keyring_is_available();
|
| + return PasswordStore::Init() &&
|
| + LoadGnomeKeyring() &&
|
| + gnome_keyring_is_available();
|
| }
|
|
|
| void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) {
|
| @@ -301,7 +419,7 @@
|
| int64 date_created = 0;
|
| bool date_ok = StringToInt64(date, &date_created);
|
| DCHECK(date_ok);
|
| - DCHECK(date_created != 0);
|
| + DCHECK_NE(date_created, 0);
|
| form->date_created = base::Time::FromTimeT(date_created);
|
| form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"];
|
| form->scheme = static_cast<PasswordForm::Scheme>(
|
|
|