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 |