| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/password_manager/native_backend_gnome_x.h" | 5 #include "chrome/browser/password_manager/native_backend_gnome_x.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <gnome-keyring.h> | 8 #include <gnome-keyring.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 16 #include "base/string_piece.h" | 16 #include "base/string_piece.h" |
| 17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/stringprintf.h" | 18 #include "base/stringprintf.h" |
| 19 #include "base/time.h" | 19 #include "base/time.h" |
| 20 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
| 21 #include "base/synchronization/waitable_event.h" | 21 #include "base/synchronization/waitable_event.h" |
| 22 #include "content/browser/browser_thread.h" | 22 #include "content/browser/browser_thread.h" |
| 23 | 23 |
| 24 using webkit_glue::PasswordForm; | 24 using webkit_glue::PasswordForm; |
| 25 | 25 |
| 26 namespace { | 26 #define GNOME_KEYRING_DEFINE_POINTER(name) \ |
| 27 typeof(&::gnome_keyring_##name) GnomeKeyringLoader::gnome_keyring_##name; |
| 28 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_POINTER) |
| 29 #undef GNOME_KEYRING_DEFINE_POINTER |
| 27 | 30 |
| 28 // Many of the gnome_keyring_* functions use variable arguments, which makes | 31 bool GnomeKeyringLoader::keyring_loaded = false; |
| 29 // them difficult if not impossible to wrap in C. Therefore, we want the | |
| 30 // actual uses below to either call the functions directly (if we are linking | |
| 31 // against libgnome-keyring), or call them via appropriately-typed function | |
| 32 // pointers (if we are dynamically loading libgnome-keyring). | |
| 33 | |
| 34 // Thus, instead of making a wrapper class with two implementations, we use | |
| 35 // the preprocessor to rename the calls below in the dynamic load case, and | |
| 36 // provide a function to initialize a set of function pointers that have the | |
| 37 // alternate names. We also make sure the types are correct, since otherwise | |
| 38 // dynamic loading like this would leave us vulnerable to signature changes. | |
| 39 | 32 |
| 40 #if defined(DLOPEN_GNOME_KEYRING) | 33 #if defined(DLOPEN_GNOME_KEYRING) |
| 41 | 34 |
| 42 // Call a given parameter with the name of each function we use from GNOME | 35 #define GNOME_KEYRING_FUNCTION_INFO(name) \ |
| 43 // Keyring. | 36 {"gnome_keyring_"#name, reinterpret_cast<void**>(&gnome_keyring_##name)}, |
| 44 #define GNOME_KEYRING_FOR_EACH_FUNC(F) \ | 37 const GnomeKeyringLoader::FunctionInfo GnomeKeyringLoader::functions[] = { |
| 45 F(is_available) \ | 38 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION_INFO) |
| 46 F(store_password) \ | |
| 47 F(delete_password) \ | |
| 48 F(find_itemsv) \ | |
| 49 F(result_to_message) | |
| 50 | |
| 51 // Define the actual function pointers that we'll use in application code. | |
| 52 #define GNOME_KEYRING_DEFINE_WRAPPER(name) \ | |
| 53 typeof(&gnome_keyring_##name) wrap_gnome_keyring_##name; | |
| 54 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_WRAPPER) | |
| 55 #undef GNOME_KEYRING_DEFINE_WRAPPER | |
| 56 | |
| 57 // Make it easy to initialize the function pointers above with a loop below. | |
| 58 #define GNOME_KEYRING_FUNCTION(name) \ | |
| 59 {"gnome_keyring_"#name, reinterpret_cast<void**>(&wrap_gnome_keyring_##name)}, | |
| 60 const struct { | |
| 61 const char* name; | |
| 62 void** pointer; | |
| 63 } gnome_keyring_functions[] = { | |
| 64 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION) | |
| 65 {NULL, NULL} | 39 {NULL, NULL} |
| 66 }; | 40 }; |
| 67 #undef GNOME_KEYRING_FUNCTION | 41 #undef GNOME_KEYRING_FUNCTION_INFO |
| 68 | |
| 69 #undef GNOME_KEYRING_FOR_EACH_FUNC | |
| 70 | |
| 71 // Allow application code below to use the normal function names, but actually | |
| 72 // end up using the function pointers above instead. | |
| 73 #define gnome_keyring_is_available \ | |
| 74 wrap_gnome_keyring_is_available | |
| 75 #define gnome_keyring_store_password \ | |
| 76 wrap_gnome_keyring_store_password | |
| 77 #define gnome_keyring_delete_password \ | |
| 78 wrap_gnome_keyring_delete_password | |
| 79 #define gnome_keyring_find_itemsv \ | |
| 80 wrap_gnome_keyring_find_itemsv | |
| 81 #define gnome_keyring_result_to_message \ | |
| 82 wrap_gnome_keyring_result_to_message | |
| 83 | 42 |
| 84 /* Load the library and initialize the function pointers. */ | 43 /* Load the library and initialize the function pointers. */ |
| 85 bool LoadGnomeKeyring() { | 44 bool GnomeKeyringLoader::LoadGnomeKeyring() { |
| 45 if (keyring_loaded) |
| 46 return true; |
| 47 |
| 86 void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL); | 48 void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL); |
| 87 if (!handle) { | 49 if (!handle) { |
| 88 // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because | 50 // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because |
| 89 // either the user asked for this, or we autodetected it incorrectly. (Or | 51 // either the user asked for this, or we autodetected it incorrectly. (Or |
| 90 // the system has broken libraries, which is also good to warn about.) | 52 // the system has broken libraries, which is also good to warn about.) |
| 91 LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); | 53 LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); |
| 92 return false; | 54 return false; |
| 93 } | 55 } |
| 94 for (size_t i = 0; gnome_keyring_functions[i].name; ++i) { | 56 |
| 57 for (size_t i = 0; functions[i].name; ++i) { |
| 95 dlerror(); | 58 dlerror(); |
| 96 *gnome_keyring_functions[i].pointer = | 59 *functions[i].pointer = dlsym(handle, functions[i].name); |
| 97 dlsym(handle, gnome_keyring_functions[i].name); | |
| 98 const char* error = dlerror(); | 60 const char* error = dlerror(); |
| 99 if (error) { | 61 if (error) { |
| 100 LOG(ERROR) << "Unable to load symbol " | 62 LOG(ERROR) << "Unable to load symbol " |
| 101 << gnome_keyring_functions[i].name << ": " << error; | 63 << functions[i].name << ": " << error; |
| 102 dlclose(handle); | 64 dlclose(handle); |
| 103 return false; | 65 return false; |
| 104 } | 66 } |
| 105 } | 67 } |
| 68 |
| 69 keyring_loaded = true; |
| 106 // We leak the library handle. That's OK: this function is called only once. | 70 // We leak the library handle. That's OK: this function is called only once. |
| 107 return true; | 71 return true; |
| 108 } | 72 } |
| 109 | 73 |
| 110 #else // !defined(DLOPEN_GNOME_KEYRING) | 74 #else // defined(DLOPEN_GNOME_KEYRING) |
| 111 | 75 |
| 112 bool LoadGnomeKeyring() { | 76 bool GnomeKeyringLoader::LoadGnomeKeyring() { |
| 113 // We don't need to do anything here. | 77 if (keyring_loaded) |
| 78 return true; |
| 79 #define GNOME_KEYRING_ASSIGN_POINTER(name) \ |
| 80 gnome_keyring_##name = &::gnome_keyring_##name; |
| 81 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_ASSIGN_POINTER) |
| 82 #undef GNOME_KEYRING_ASSIGN_POINTER |
| 83 keyring_loaded = true; |
| 114 return true; | 84 return true; |
| 115 } | 85 } |
| 116 | 86 |
| 117 #endif // !defined(DLOPEN_GNOME_KEYRING) | 87 #endif // defined(DLOPEN_GNOME_KEYRING) |
| 88 |
| 89 namespace { |
| 118 | 90 |
| 119 const char kGnomeKeyringAppString[] = "chrome"; | 91 const char kGnomeKeyringAppString[] = "chrome"; |
| 120 | 92 |
| 121 // Convert the attributes of a given keyring entry into a new PasswordForm. | 93 // Convert the attributes of a given keyring entry into a new PasswordForm. |
| 122 // Note: does *not* get the actual password, as that is not a key attribute! | 94 // Note: does *not* get the actual password, as that is not a key attribute! |
| 123 // Returns NULL if the attributes are for the wrong application. | 95 // Returns NULL if the attributes are for the wrong application. |
| 124 PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { | 96 PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
| 125 // Read the string and int attributes into the appropriate map. | 97 // Read the string and int attributes into the appropriate map. |
| 126 std::map<std::string, std::string> string_attr_map; | 98 std::map<std::string, std::string> string_attr_map; |
| 127 std::map<std::string, uint32_t> uint_attr_map; | 99 std::map<std::string, uint32_t> uint_attr_map; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 // caller, e.g. in the password management UI), and *block* the DB thread | 186 // caller, e.g. in the password management UI), and *block* the DB thread |
| 215 // waiting for a response from the UI thread to provide the synchronous API | 187 // waiting for a response from the UI thread to provide the synchronous API |
| 216 // PasswordStore expects of us. (It will then in turn switch back to the | 188 // PasswordStore expects of us. (It will then in turn switch back to the |
| 217 // original caller to send the asynchronous reply to the original request.) | 189 // original caller to send the asynchronous reply to the original request.) |
| 218 | 190 |
| 219 // This class represents a call to a GNOME Keyring method. A RunnableMethod | 191 // This class represents a call to a GNOME Keyring method. A RunnableMethod |
| 220 // should be posted to the UI thread to call one of its action methods, and then | 192 // should be posted to the UI thread to call one of its action methods, and then |
| 221 // a WaitResult() method should be called to wait for the result. Each instance | 193 // a WaitResult() method should be called to wait for the result. Each instance |
| 222 // supports only one outstanding method at a time, though multiple instances may | 194 // supports only one outstanding method at a time, though multiple instances may |
| 223 // be used in parallel. | 195 // be used in parallel. |
| 224 class GKRMethod { | 196 class GKRMethod : public GnomeKeyringLoader { |
| 225 public: | 197 public: |
| 226 typedef NativeBackendGnome::PasswordFormList PasswordFormList; | 198 typedef NativeBackendGnome::PasswordFormList PasswordFormList; |
| 227 | 199 |
| 228 GKRMethod() : event_(false, false), result_(GNOME_KEYRING_RESULT_CANCELLED) {} | 200 GKRMethod() : event_(false, false), result_(GNOME_KEYRING_RESULT_CANCELLED) {} |
| 229 | 201 |
| 230 // Action methods. These call gnome_keyring_* functions. Call from UI thread. | 202 // Action methods. These call gnome_keyring_* functions. Call from UI thread. |
| 231 // See GetProfileSpecificAppString() for more information on the app string. | 203 // See GetProfileSpecificAppString() for more information on the app string. |
| 232 void AddLogin(const PasswordForm& form, const char* app_string); | 204 void AddLogin(const PasswordForm& form, const char* app_string); |
| 233 void AddLoginSearch(const PasswordForm& form, const char* app_string); | 205 void AddLoginSearch(const PasswordForm& form, const char* app_string); |
| 234 void UpdateLoginSearch(const PasswordForm& form, const char* app_string); | 206 void UpdateLoginSearch(const PasswordForm& form, const char* app_string); |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 // Each other profile must be able to migrate the shared data as well, | 726 // Each other profile must be able to migrate the shared data as well, |
| 755 // so we must leave it alone. After a few releases, we'll add code to | 727 // so we must leave it alone. After a few releases, we'll add code to |
| 756 // delete them, and eventually remove this migration code. | 728 // delete them, and eventually remove this migration code. |
| 757 // TODO(mdm): follow through with the plan above. | 729 // TODO(mdm): follow through with the plan above. |
| 758 PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_); | 730 PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_); |
| 759 } else { | 731 } else { |
| 760 // We failed to migrate for some reason. Use the old app string. | 732 // We failed to migrate for some reason. Use the old app string. |
| 761 app_string_ = kGnomeKeyringAppString; | 733 app_string_ = kGnomeKeyringAppString; |
| 762 } | 734 } |
| 763 } | 735 } |
| OLD | NEW |