Index: chrome/browser/password_manager/native_backend_gnome_x.cc |
=================================================================== |
--- chrome/browser/password_manager/native_backend_gnome_x.cc (revision 93060) |
+++ chrome/browser/password_manager/native_backend_gnome_x.cc (working copy) |
@@ -23,66 +23,28 @@ |
using webkit_glue::PasswordForm; |
-namespace { |
+#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 |
-// 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). |
+bool GnomeKeyringLoader::keyring_loaded = false; |
-// 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) |
-// Call a given parameter with the name of each function we use from GNOME |
-// Keyring. |
-#define GNOME_KEYRING_FOR_EACH_FUNC(F) \ |
- F(is_available) \ |
- F(store_password) \ |
- F(delete_password) \ |
- F(find_itemsv) \ |
- F(result_to_message) |
- |
-// Define the actual function pointers that we'll use in application code. |
-#define GNOME_KEYRING_DEFINE_WRAPPER(name) \ |
- typeof(&gnome_keyring_##name) wrap_gnome_keyring_##name; |
-GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_WRAPPER) |
-#undef GNOME_KEYRING_DEFINE_WRAPPER |
- |
-// Make it easy to initialize the function pointers above with a loop below. |
-#define GNOME_KEYRING_FUNCTION(name) \ |
- {"gnome_keyring_"#name, reinterpret_cast<void**>(&wrap_gnome_keyring_##name)}, |
-const struct { |
- const char* name; |
- void** pointer; |
-} gnome_keyring_functions[] = { |
- GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION) |
+#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 |
+#undef GNOME_KEYRING_FUNCTION_INFO |
-#undef GNOME_KEYRING_FOR_EACH_FUNC |
- |
-// 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 \ |
- wrap_gnome_keyring_store_password |
-#define gnome_keyring_delete_password \ |
- wrap_gnome_keyring_delete_password |
-#define gnome_keyring_find_itemsv \ |
- wrap_gnome_keyring_find_itemsv |
-#define gnome_keyring_result_to_message \ |
- wrap_gnome_keyring_result_to_message |
- |
/* Load the library and initialize the function pointers. */ |
-bool LoadGnomeKeyring() { |
+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 |
@@ -91,31 +53,41 @@ |
LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); |
return false; |
} |
- for (size_t i = 0; gnome_keyring_functions[i].name; ++i) { |
+ |
+ for (size_t i = 0; functions[i].name; ++i) { |
dlerror(); |
- *gnome_keyring_functions[i].pointer = |
- dlsym(handle, gnome_keyring_functions[i].name); |
+ *functions[i].pointer = dlsym(handle, functions[i].name); |
const char* error = dlerror(); |
if (error) { |
LOG(ERROR) << "Unable to load symbol " |
- << gnome_keyring_functions[i].name << ": " << error; |
+ << 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) |
+#else // defined(DLOPEN_GNOME_KEYRING) |
-bool LoadGnomeKeyring() { |
- // We don't need to do anything here. |
+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) |
+#endif // defined(DLOPEN_GNOME_KEYRING) |
+namespace { |
+ |
const char kGnomeKeyringAppString[] = "chrome"; |
// Convert the attributes of a given keyring entry into a new PasswordForm. |
@@ -221,7 +193,7 @@ |
// 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 { |
+class GKRMethod : public GnomeKeyringLoader { |
public: |
typedef NativeBackendGnome::PasswordFormList PasswordFormList; |