OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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> | |
8 #include <gnome-keyring.h> | |
9 | |
10 #include <map> | 7 #include <map> |
11 #include <string> | 8 #include <string> |
12 #include <vector> | 9 #include <vector> |
13 | 10 |
14 #include "base/logging.h" | 11 #include "base/logging.h" |
15 #include "base/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
16 #include "base/string_piece.h" | 13 #include "base/string_piece.h" |
17 #include "base/string_util.h" | 14 #include "base/string_util.h" |
18 #include "base/stringprintf.h" | 15 #include "base/stringprintf.h" |
19 #include "base/synchronization/waitable_event.h" | 16 #include "base/synchronization/waitable_event.h" |
| 17 #include "base/threading/thread_restrictions.h" |
20 #include "base/time.h" | 18 #include "base/time.h" |
21 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
22 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
23 | 21 |
24 using content::BrowserThread; | 22 using content::BrowserThread; |
25 using content::PasswordForm; | 23 using content::PasswordForm; |
26 | 24 |
27 #define GNOME_KEYRING_DEFINE_POINTER(name) \ | |
28 typeof(&::gnome_keyring_##name) GnomeKeyringLoader::gnome_keyring_##name; | |
29 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DEFINE_POINTER) | |
30 #undef GNOME_KEYRING_DEFINE_POINTER | |
31 | |
32 bool GnomeKeyringLoader::keyring_loaded = false; | |
33 | |
34 #if defined(DLOPEN_GNOME_KEYRING) | |
35 | |
36 #define GNOME_KEYRING_FUNCTION_INFO(name) \ | |
37 {"gnome_keyring_"#name, reinterpret_cast<void**>(&gnome_keyring_##name)}, | |
38 const GnomeKeyringLoader::FunctionInfo GnomeKeyringLoader::functions[] = { | |
39 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION_INFO) | |
40 {NULL, NULL} | |
41 }; | |
42 #undef GNOME_KEYRING_FUNCTION_INFO | |
43 | |
44 /* Load the library and initialize the function pointers. */ | |
45 bool GnomeKeyringLoader::LoadGnomeKeyring() { | |
46 if (keyring_loaded) | |
47 return true; | |
48 | |
49 void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL); | |
50 if (!handle) { | |
51 // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because | |
52 // either the user asked for this, or we autodetected it incorrectly. (Or | |
53 // the system has broken libraries, which is also good to warn about.) | |
54 LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); | |
55 return false; | |
56 } | |
57 | |
58 for (size_t i = 0; functions[i].name; ++i) { | |
59 dlerror(); | |
60 *functions[i].pointer = dlsym(handle, functions[i].name); | |
61 const char* error = dlerror(); | |
62 if (error) { | |
63 LOG(ERROR) << "Unable to load symbol " | |
64 << functions[i].name << ": " << error; | |
65 dlclose(handle); | |
66 return false; | |
67 } | |
68 } | |
69 | |
70 keyring_loaded = true; | |
71 // We leak the library handle. That's OK: this function is called only once. | |
72 return true; | |
73 } | |
74 | |
75 #else // defined(DLOPEN_GNOME_KEYRING) | |
76 | |
77 bool GnomeKeyringLoader::LoadGnomeKeyring() { | |
78 if (keyring_loaded) | |
79 return true; | |
80 #define GNOME_KEYRING_ASSIGN_POINTER(name) \ | |
81 gnome_keyring_##name = &::gnome_keyring_##name; | |
82 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_ASSIGN_POINTER) | |
83 #undef GNOME_KEYRING_ASSIGN_POINTER | |
84 keyring_loaded = true; | |
85 return true; | |
86 } | |
87 | |
88 #endif // defined(DLOPEN_GNOME_KEYRING) | |
89 | |
90 namespace { | 25 namespace { |
91 | 26 |
92 const char kGnomeKeyringAppString[] = "chrome"; | 27 const char kGnomeKeyringAppString[] = "chrome"; |
93 | 28 |
94 // Convert the attributes of a given keyring entry into a new PasswordForm. | 29 // Convert the attributes of a given keyring entry into a new PasswordForm. |
95 // Note: does *not* get the actual password, as that is not a key attribute! | 30 // Note: does *not* get the actual password, as that is not a key attribute! |
96 // Returns NULL if the attributes are for the wrong application. | 31 // Returns NULL if the attributes are for the wrong application. |
97 PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { | 32 PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
98 // Read the string and int attributes into the appropriate map. | 33 // Read the string and int attributes into the appropriate map. |
99 std::map<std::string, std::string> string_attr_map; | 34 std::map<std::string, std::string> string_attr_map; |
100 std::map<std::string, uint32_t> uint_attr_map; | 35 std::map<std::string, uint32_t> uint_attr_map; |
101 for (guint i = 0; i < attrs->len; ++i) { | 36 for (guint i = 0; i < attrs->len; ++i) { |
| 37 // Note: gnome_keyring_attribute_list_index below is a macro |
| 38 // and not a function call. |
102 GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index(attrs, i); | 39 GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index(attrs, i); |
103 if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) | 40 if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) |
104 string_attr_map[attr.name] = attr.value.string; | 41 string_attr_map[attr.name] = attr.value.string; |
105 else if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) | 42 else if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) |
106 uint_attr_map[attr.name] = attr.value.integer; | 43 uint_attr_map[attr.name] = attr.value.integer; |
107 } | 44 } |
108 // Check to make sure this is a password we care about. | 45 // Check to make sure this is a password we care about. |
109 const std::string& app_value = string_attr_map["application"]; | 46 const std::string& app_value = string_attr_map["application"]; |
110 if (!base::StringPiece(app_value).starts_with(kGnomeKeyringAppString)) | 47 if (!base::StringPiece(app_value).starts_with(kGnomeKeyringAppString)) |
111 return NULL; | 48 return NULL; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 // caller, e.g. in the password management UI), and *block* the DB thread | 124 // caller, e.g. in the password management UI), and *block* the DB thread |
188 // waiting for a response from the UI thread to provide the synchronous API | 125 // waiting for a response from the UI thread to provide the synchronous API |
189 // PasswordStore expects of us. (It will then in turn switch back to the | 126 // PasswordStore expects of us. (It will then in turn switch back to the |
190 // original caller to send the asynchronous reply to the original request.) | 127 // original caller to send the asynchronous reply to the original request.) |
191 | 128 |
192 // This class represents a call to a GNOME Keyring method. A RunnableMethod | 129 // This class represents a call to a GNOME Keyring method. A RunnableMethod |
193 // should be posted to the UI thread to call one of its action methods, and then | 130 // should be posted to the UI thread to call one of its action methods, and then |
194 // a WaitResult() method should be called to wait for the result. Each instance | 131 // a WaitResult() method should be called to wait for the result. Each instance |
195 // supports only one outstanding method at a time, though multiple instances may | 132 // supports only one outstanding method at a time, though multiple instances may |
196 // be used in parallel. | 133 // be used in parallel. |
197 class GKRMethod : public GnomeKeyringLoader { | 134 class GKRMethod { |
198 public: | 135 public: |
199 typedef NativeBackendGnome::PasswordFormList PasswordFormList; | 136 typedef NativeBackendGnome::PasswordFormList PasswordFormList; |
200 | 137 |
201 GKRMethod() : event_(false, false), result_(GNOME_KEYRING_RESULT_CANCELLED) {} | 138 explicit GKRMethod(const LibGnomeKeyringLoader* loader) |
| 139 : loader_(loader), |
| 140 event_(false, false), |
| 141 result_(GNOME_KEYRING_RESULT_CANCELLED) { |
| 142 } |
202 | 143 |
203 // Action methods. These call gnome_keyring_* functions. Call from UI thread. | 144 // Action methods. These call gnome_keyring_* functions. Call from UI thread. |
204 // See GetProfileSpecificAppString() for more information on the app string. | 145 // See GetProfileSpecificAppString() for more information on the app string. |
205 void AddLogin(const PasswordForm& form, const char* app_string); | 146 void AddLogin(const PasswordForm& form, const char* app_string); |
206 void AddLoginSearch(const PasswordForm& form, const char* app_string); | 147 void AddLoginSearch(const PasswordForm& form, const char* app_string); |
207 void UpdateLoginSearch(const PasswordForm& form, const char* app_string); | 148 void UpdateLoginSearch(const PasswordForm& form, const char* app_string); |
208 void RemoveLogin(const PasswordForm& form, const char* app_string); | 149 void RemoveLogin(const PasswordForm& form, const char* app_string); |
209 void GetLogins(const PasswordForm& form, const char* app_string); | 150 void GetLogins(const PasswordForm& form, const char* app_string); |
210 void GetLoginsList(uint32_t blacklisted_by_user, const char* app_string); | 151 void GetLoginsList(uint32_t blacklisted_by_user, const char* app_string); |
211 void GetAllLogins(const char* app_string); | 152 void GetAllLogins(const char* app_string); |
212 | 153 |
213 // Use after AddLogin, RemoveLogin. | 154 // Use after AddLogin, RemoveLogin. |
214 GnomeKeyringResult WaitResult(); | 155 GnomeKeyringResult WaitResult(); |
215 | 156 |
216 // Use after AddLoginSearch, UpdateLoginSearch, GetLogins, GetLoginsList, | 157 // Use after AddLoginSearch, UpdateLoginSearch, GetLogins, GetLoginsList, |
217 // GetAllLogins. | 158 // GetAllLogins. |
218 GnomeKeyringResult WaitResult(PasswordFormList* forms); | 159 GnomeKeyringResult WaitResult(PasswordFormList* forms); |
219 | 160 |
220 private: | 161 private: |
221 // All these callbacks are called on UI thread. | 162 // All these callbacks are called on UI thread. |
222 static void OnOperationDone(GnomeKeyringResult result, gpointer data); | 163 static void OnOperationDone(GnomeKeyringResult result, gpointer data); |
223 | 164 |
224 static void OnOperationGetList(GnomeKeyringResult result, GList* list, | 165 static void OnOperationGetList(GnomeKeyringResult result, GList* list, |
225 gpointer data); | 166 gpointer data); |
226 | 167 |
| 168 const LibGnomeKeyringLoader* loader_; |
| 169 |
227 base::WaitableEvent event_; | 170 base::WaitableEvent event_; |
228 GnomeKeyringResult result_; | 171 GnomeKeyringResult result_; |
229 NativeBackendGnome::PasswordFormList forms_; | 172 NativeBackendGnome::PasswordFormList forms_; |
230 }; | 173 }; |
231 | 174 |
232 void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { | 175 void GKRMethod::AddLogin(const PasswordForm& form, const char* app_string) { |
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
234 time_t date_created = form.date_created.ToTimeT(); | 177 time_t date_created = form.date_created.ToTimeT(); |
235 // If we are asked to save a password with 0 date, use the current time. | 178 // If we are asked to save a password with 0 date, use the current time. |
236 // We don't want to actually save passwords as though on January 1, 1970. | 179 // We don't want to actually save passwords as though on January 1, 1970. |
237 if (!date_created) | 180 if (!date_created) |
238 date_created = time(NULL); | 181 date_created = time(NULL); |
239 gnome_keyring_store_password( | 182 loader_->gnome_keyring_store_password( |
240 &kGnomeSchema, | 183 &kGnomeSchema, |
241 NULL, // Default keyring. | 184 NULL, // Default keyring. |
242 form.origin.spec().c_str(), // Display name. | 185 form.origin.spec().c_str(), // Display name. |
243 UTF16ToUTF8(form.password_value).c_str(), | 186 UTF16ToUTF8(form.password_value).c_str(), |
244 OnOperationDone, | 187 OnOperationDone, |
245 this, // data | 188 this, // data |
246 NULL, // destroy_data | 189 NULL, // destroy_data |
247 "origin_url", form.origin.spec().c_str(), | 190 "origin_url", form.origin.spec().c_str(), |
248 "action_url", form.action.spec().c_str(), | 191 "action_url", form.action.spec().c_str(), |
249 "username_element", UTF16ToUTF8(form.username_element).c_str(), | 192 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
250 "username_value", UTF16ToUTF8(form.username_value).c_str(), | 193 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
251 "password_element", UTF16ToUTF8(form.password_element).c_str(), | 194 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
252 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), | 195 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
253 "signon_realm", form.signon_realm.c_str(), | 196 "signon_realm", form.signon_realm.c_str(), |
254 "ssl_valid", form.ssl_valid, | 197 "ssl_valid", form.ssl_valid, |
255 "preferred", form.preferred, | 198 "preferred", form.preferred, |
256 "date_created", base::Int64ToString(date_created).c_str(), | 199 "date_created", base::Int64ToString(date_created).c_str(), |
257 "blacklisted_by_user", form.blacklisted_by_user, | 200 "blacklisted_by_user", form.blacklisted_by_user, |
258 "scheme", form.scheme, | 201 "scheme", form.scheme, |
259 "application", app_string, | 202 "application", app_string, |
260 NULL); | 203 NULL); |
261 } | 204 } |
262 | 205 |
263 void GKRMethod::AddLoginSearch(const PasswordForm& form, | 206 void GKRMethod::AddLoginSearch(const PasswordForm& form, |
264 const char* app_string) { | 207 const char* app_string) { |
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
266 // Search GNOME Keyring for matching passwords to update. | 209 // Search GNOME Keyring for matching passwords to update. |
267 gnome_keyring_find_itemsv( | 210 loader_->gnome_keyring_find_itemsv( |
268 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 211 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
269 OnOperationGetList, | 212 OnOperationGetList, |
270 this, // data | 213 this, // data |
271 NULL, // destroy_data | 214 NULL, // destroy_data |
272 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 215 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
273 form.origin.spec().c_str(), | 216 form.origin.spec().c_str(), |
274 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 217 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
275 UTF16ToUTF8(form.username_element).c_str(), | 218 UTF16ToUTF8(form.username_element).c_str(), |
276 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 219 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
277 UTF16ToUTF8(form.username_value).c_str(), | 220 UTF16ToUTF8(form.username_value).c_str(), |
278 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 221 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
279 UTF16ToUTF8(form.password_element).c_str(), | 222 UTF16ToUTF8(form.password_element).c_str(), |
280 "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 223 "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
281 UTF16ToUTF8(form.submit_element).c_str(), | 224 UTF16ToUTF8(form.submit_element).c_str(), |
282 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 225 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
283 form.signon_realm.c_str(), | 226 form.signon_realm.c_str(), |
284 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 227 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
285 app_string, | 228 app_string, |
286 NULL); | 229 NULL); |
287 } | 230 } |
288 | 231 |
289 void GKRMethod::UpdateLoginSearch(const PasswordForm& form, | 232 void GKRMethod::UpdateLoginSearch(const PasswordForm& form, |
290 const char* app_string) { | 233 const char* app_string) { |
291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
292 // Search GNOME Keyring for matching passwords to update. | 235 // Search GNOME Keyring for matching passwords to update. |
293 gnome_keyring_find_itemsv( | 236 loader_->gnome_keyring_find_itemsv( |
294 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 237 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
295 OnOperationGetList, | 238 OnOperationGetList, |
296 this, // data | 239 this, // data |
297 NULL, // destroy_data | 240 NULL, // destroy_data |
298 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 241 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
299 form.origin.spec().c_str(), | 242 form.origin.spec().c_str(), |
300 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 243 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
301 UTF16ToUTF8(form.username_element).c_str(), | 244 UTF16ToUTF8(form.username_element).c_str(), |
302 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 245 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
303 UTF16ToUTF8(form.username_value).c_str(), | 246 UTF16ToUTF8(form.username_value).c_str(), |
304 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 247 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
305 UTF16ToUTF8(form.password_element).c_str(), | 248 UTF16ToUTF8(form.password_element).c_str(), |
306 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 249 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
307 form.signon_realm.c_str(), | 250 form.signon_realm.c_str(), |
308 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 251 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
309 app_string, | 252 app_string, |
310 NULL); | 253 NULL); |
311 } | 254 } |
312 | 255 |
313 void GKRMethod::RemoveLogin(const PasswordForm& form, const char* app_string) { | 256 void GKRMethod::RemoveLogin(const PasswordForm& form, const char* app_string) { |
314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
315 // We find forms using the same fields as LoginDatabase::RemoveLogin(). | 258 // We find forms using the same fields as LoginDatabase::RemoveLogin(). |
316 gnome_keyring_delete_password( | 259 loader_->gnome_keyring_delete_password( |
317 &kGnomeSchema, | 260 &kGnomeSchema, |
318 OnOperationDone, | 261 OnOperationDone, |
319 this, // data | 262 this, // data |
320 NULL, // destroy_data | 263 NULL, // destroy_data |
321 "origin_url", form.origin.spec().c_str(), | 264 "origin_url", form.origin.spec().c_str(), |
322 "action_url", form.action.spec().c_str(), | 265 "action_url", form.action.spec().c_str(), |
323 "username_element", UTF16ToUTF8(form.username_element).c_str(), | 266 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
324 "username_value", UTF16ToUTF8(form.username_value).c_str(), | 267 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
325 "password_element", UTF16ToUTF8(form.password_element).c_str(), | 268 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
326 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), | 269 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
327 "signon_realm", form.signon_realm.c_str(), | 270 "signon_realm", form.signon_realm.c_str(), |
328 "application", app_string, | 271 "application", app_string, |
329 NULL); | 272 NULL); |
330 } | 273 } |
331 | 274 |
332 void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { | 275 void GKRMethod::GetLogins(const PasswordForm& form, const char* app_string) { |
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
334 // Search GNOME Keyring for matching passwords. | 277 // Search GNOME Keyring for matching passwords. |
335 gnome_keyring_find_itemsv( | 278 loader_->gnome_keyring_find_itemsv( |
336 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 279 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
337 OnOperationGetList, | 280 OnOperationGetList, |
338 this, // data | 281 this, // data |
339 NULL, // destroy_data | 282 NULL, // destroy_data |
340 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 283 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
341 form.signon_realm.c_str(), | 284 form.signon_realm.c_str(), |
342 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 285 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
343 app_string, | 286 app_string, |
344 NULL); | 287 NULL); |
345 } | 288 } |
346 | 289 |
347 void GKRMethod::GetLoginsList(uint32_t blacklisted_by_user, | 290 void GKRMethod::GetLoginsList(uint32_t blacklisted_by_user, |
348 const char* app_string) { | 291 const char* app_string) { |
349 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
350 // Search GNOME Keyring for matching passwords. | 293 // Search GNOME Keyring for matching passwords. |
351 gnome_keyring_find_itemsv( | 294 loader_->gnome_keyring_find_itemsv( |
352 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 295 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
353 OnOperationGetList, | 296 OnOperationGetList, |
354 this, // data | 297 this, // data |
355 NULL, // destroy_data | 298 NULL, // destroy_data |
356 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, | 299 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, |
357 blacklisted_by_user, | 300 blacklisted_by_user, |
358 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 301 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
359 app_string, | 302 app_string, |
360 NULL); | 303 NULL); |
361 } | 304 } |
362 | 305 |
363 void GKRMethod::GetAllLogins(const char* app_string) { | 306 void GKRMethod::GetAllLogins(const char* app_string) { |
364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
365 // We need to search for something, otherwise we get no results - so | 308 // We need to search for something, otherwise we get no results - so |
366 // we search for the fixed application string. | 309 // we search for the fixed application string. |
367 gnome_keyring_find_itemsv( | 310 loader_->gnome_keyring_find_itemsv( |
368 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 311 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
369 OnOperationGetList, | 312 OnOperationGetList, |
370 this, // data | 313 this, // data |
371 NULL, // destroy_data | 314 NULL, // destroy_data |
372 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 315 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
373 app_string, | 316 app_string, |
374 NULL); | 317 NULL); |
375 } | 318 } |
376 | 319 |
377 GnomeKeyringResult GKRMethod::WaitResult() { | 320 GnomeKeyringResult GKRMethod::WaitResult() { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } else { | 369 } else { |
427 app_string_ = kGnomeKeyringAppString; | 370 app_string_ = kGnomeKeyringAppString; |
428 migrate_tried_ = false; | 371 migrate_tried_ = false; |
429 } | 372 } |
430 } | 373 } |
431 | 374 |
432 NativeBackendGnome::~NativeBackendGnome() { | 375 NativeBackendGnome::~NativeBackendGnome() { |
433 } | 376 } |
434 | 377 |
435 bool NativeBackendGnome::Init() { | 378 bool NativeBackendGnome::Init() { |
436 return LoadGnomeKeyring() && gnome_keyring_is_available(); | 379 // TODO(phajdan.jr): Redesign the code to load library on different thread. |
| 380 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 381 return libgnome_keyring_loader_.Load("libgnome-keyring.so.0") && |
| 382 libgnome_keyring_loader_.gnome_keyring_is_available(); |
437 } | 383 } |
438 | 384 |
439 bool NativeBackendGnome::RawAddLogin(const PasswordForm& form) { | 385 bool NativeBackendGnome::RawAddLogin(const PasswordForm& form) { |
440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
441 GKRMethod method; | 387 GKRMethod method(&libgnome_keyring_loader_); |
442 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 388 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
443 base::Bind(&GKRMethod::AddLogin, | 389 base::Bind(&GKRMethod::AddLogin, |
444 base::Unretained(&method), | 390 base::Unretained(&method), |
445 form, app_string_.c_str())); | 391 form, app_string_.c_str())); |
446 GnomeKeyringResult result = method.WaitResult(); | 392 GnomeKeyringResult result = method.WaitResult(); |
447 if (result != GNOME_KEYRING_RESULT_OK) { | 393 if (result != GNOME_KEYRING_RESULT_OK) { |
448 LOG(ERROR) << "Keyring save failed: " | 394 LOG(ERROR) << "Keyring save failed: " |
449 << gnome_keyring_result_to_message(result); | 395 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 396 result); |
450 return false; | 397 return false; |
451 } | 398 } |
452 // Successful write. Try migration if necessary. | 399 // Successful write. Try migration if necessary. |
453 if (!migrate_tried_) | 400 if (!migrate_tried_) |
454 MigrateToProfileSpecificLogins(); | 401 MigrateToProfileSpecificLogins(); |
455 return true; | 402 return true; |
456 } | 403 } |
457 | 404 |
458 bool NativeBackendGnome::AddLogin(const PasswordForm& form) { | 405 bool NativeBackendGnome::AddLogin(const PasswordForm& form) { |
459 // Based on LoginDatabase::AddLogin(), we search for an existing match based | 406 // Based on LoginDatabase::AddLogin(), we search for an existing match based |
460 // on origin_url, username_element, username_value, password_element, submit | 407 // on origin_url, username_element, username_value, password_element, submit |
461 // element, and signon_realm first, remove that, and then add the new entry. | 408 // element, and signon_realm first, remove that, and then add the new entry. |
462 // We'd add the new one first, and then delete the original, but then the | 409 // We'd add the new one first, and then delete the original, but then the |
463 // delete might actually delete the newly-added entry! | 410 // delete might actually delete the newly-added entry! |
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
465 GKRMethod method; | 412 GKRMethod method(&libgnome_keyring_loader_); |
466 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 413 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
467 base::Bind(&GKRMethod::AddLoginSearch, | 414 base::Bind(&GKRMethod::AddLoginSearch, |
468 base::Unretained(&method), | 415 base::Unretained(&method), |
469 form, app_string_.c_str())); | 416 form, app_string_.c_str())); |
470 PasswordFormList forms; | 417 PasswordFormList forms; |
471 GnomeKeyringResult result = method.WaitResult(&forms); | 418 GnomeKeyringResult result = method.WaitResult(&forms); |
472 if (result != GNOME_KEYRING_RESULT_OK && | 419 if (result != GNOME_KEYRING_RESULT_OK && |
473 result != GNOME_KEYRING_RESULT_NO_MATCH) { | 420 result != GNOME_KEYRING_RESULT_NO_MATCH) { |
474 LOG(ERROR) << "Keyring find failed: " | 421 LOG(ERROR) << "Keyring find failed: " |
475 << gnome_keyring_result_to_message(result); | 422 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 423 result); |
476 return false; | 424 return false; |
477 } | 425 } |
478 if (forms.size() > 0) { | 426 if (forms.size() > 0) { |
479 if (forms.size() > 1) { | 427 if (forms.size() > 1) { |
480 LOG(WARNING) << "Adding login when there are " << forms.size() | 428 LOG(WARNING) << "Adding login when there are " << forms.size() |
481 << " matching logins already! Will replace only the first."; | 429 << " matching logins already! Will replace only the first."; |
482 } | 430 } |
483 | 431 |
484 // We try migration before updating the existing logins, since otherwise | 432 // We try migration before updating the existing logins, since otherwise |
485 // we'd do it after making some but not all of the changes below. | 433 // we'd do it after making some but not all of the changes below. |
486 if (forms.size() > 0 && !migrate_tried_) | 434 if (forms.size() > 0 && !migrate_tried_) |
487 MigrateToProfileSpecificLogins(); | 435 MigrateToProfileSpecificLogins(); |
488 | 436 |
489 RemoveLogin(*forms[0]); | 437 RemoveLogin(*forms[0]); |
490 for (size_t i = 0; i < forms.size(); ++i) | 438 for (size_t i = 0; i < forms.size(); ++i) |
491 delete forms[i]; | 439 delete forms[i]; |
492 } | 440 } |
493 return RawAddLogin(form); | 441 return RawAddLogin(form); |
494 } | 442 } |
495 | 443 |
496 bool NativeBackendGnome::UpdateLogin(const PasswordForm& form) { | 444 bool NativeBackendGnome::UpdateLogin(const PasswordForm& form) { |
497 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by | 445 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by |
498 // origin_url, username_element, username_value, password_element, and | 446 // origin_url, username_element, username_value, password_element, and |
499 // signon_realm. We then compare the result to the updated form. If they | 447 // signon_realm. We then compare the result to the updated form. If they |
500 // differ in any of the action, password_value, ssl_valid, or preferred | 448 // differ in any of the action, password_value, ssl_valid, or preferred |
501 // fields, then we remove the original, and then add the new entry. We'd add | 449 // fields, then we remove the original, and then add the new entry. We'd add |
502 // the new one first, and then delete the original, but then the delete might | 450 // the new one first, and then delete the original, but then the delete might |
503 // actually delete the newly-added entry! | 451 // actually delete the newly-added entry! |
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
505 GKRMethod method; | 453 GKRMethod method(&libgnome_keyring_loader_); |
506 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 454 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
507 base::Bind(&GKRMethod::UpdateLoginSearch, | 455 base::Bind(&GKRMethod::UpdateLoginSearch, |
508 base::Unretained(&method), | 456 base::Unretained(&method), |
509 form, app_string_.c_str())); | 457 form, app_string_.c_str())); |
510 PasswordFormList forms; | 458 PasswordFormList forms; |
511 GnomeKeyringResult result = method.WaitResult(&forms); | 459 GnomeKeyringResult result = method.WaitResult(&forms); |
512 if (result != GNOME_KEYRING_RESULT_OK) { | 460 if (result != GNOME_KEYRING_RESULT_OK) { |
513 LOG(ERROR) << "Keyring find failed: " | 461 LOG(ERROR) << "Keyring find failed: " |
514 << gnome_keyring_result_to_message(result); | 462 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 463 result); |
515 return false; | 464 return false; |
516 } | 465 } |
517 | 466 |
518 // We try migration before updating the existing logins, since otherwise | 467 // We try migration before updating the existing logins, since otherwise |
519 // we'd do it after making some but not all of the changes below. | 468 // we'd do it after making some but not all of the changes below. |
520 if (forms.size() > 0 && !migrate_tried_) | 469 if (forms.size() > 0 && !migrate_tried_) |
521 MigrateToProfileSpecificLogins(); | 470 MigrateToProfileSpecificLogins(); |
522 | 471 |
523 bool ok = true; | 472 bool ok = true; |
524 for (size_t i = 0; i < forms.size(); ++i) { | 473 for (size_t i = 0; i < forms.size(); ++i) { |
(...skipping 16 matching lines...) Expand all Loading... |
541 if (!RawAddLogin(*forms[i])) | 490 if (!RawAddLogin(*forms[i])) |
542 ok = false; | 491 ok = false; |
543 } | 492 } |
544 delete forms[i]; | 493 delete forms[i]; |
545 } | 494 } |
546 return ok; | 495 return ok; |
547 } | 496 } |
548 | 497 |
549 bool NativeBackendGnome::RemoveLogin(const PasswordForm& form) { | 498 bool NativeBackendGnome::RemoveLogin(const PasswordForm& form) { |
550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
551 GKRMethod method; | 500 GKRMethod method(&libgnome_keyring_loader_); |
552 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 501 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
553 base::Bind(&GKRMethod::RemoveLogin, | 502 base::Bind(&GKRMethod::RemoveLogin, |
554 base::Unretained(&method), | 503 base::Unretained(&method), |
555 form, app_string_.c_str())); | 504 form, app_string_.c_str())); |
556 GnomeKeyringResult result = method.WaitResult(); | 505 GnomeKeyringResult result = method.WaitResult(); |
557 if (result != GNOME_KEYRING_RESULT_OK) { | 506 if (result != GNOME_KEYRING_RESULT_OK) { |
558 // Warning, not error, because this can sometimes happen due to the user | 507 // Warning, not error, because this can sometimes happen due to the user |
559 // racing with the daemon to delete the password a second time. | 508 // racing with the daemon to delete the password a second time. |
560 LOG(WARNING) << "Keyring delete failed: " | 509 LOG(WARNING) << "Keyring delete failed: " |
561 << gnome_keyring_result_to_message(result); | 510 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 511 result); |
562 return false; | 512 return false; |
563 } | 513 } |
564 // Successful write. Try migration if necessary. Note that presumably if we've | 514 // Successful write. Try migration if necessary. Note that presumably if we've |
565 // been asked to delete a login, it's because we returned it previously; thus, | 515 // been asked to delete a login, it's because we returned it previously; thus, |
566 // this will probably never happen since we'd have already tried migration. | 516 // this will probably never happen since we'd have already tried migration. |
567 if (!migrate_tried_) | 517 if (!migrate_tried_) |
568 MigrateToProfileSpecificLogins(); | 518 MigrateToProfileSpecificLogins(); |
569 return true; | 519 return true; |
570 } | 520 } |
571 | 521 |
(...skipping 16 matching lines...) Expand all Loading... |
588 ok = false; | 538 ok = false; |
589 } | 539 } |
590 delete forms[i]; | 540 delete forms[i]; |
591 } | 541 } |
592 return ok; | 542 return ok; |
593 } | 543 } |
594 | 544 |
595 bool NativeBackendGnome::GetLogins(const PasswordForm& form, | 545 bool NativeBackendGnome::GetLogins(const PasswordForm& form, |
596 PasswordFormList* forms) { | 546 PasswordFormList* forms) { |
597 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 547 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
598 GKRMethod method; | 548 GKRMethod method(&libgnome_keyring_loader_); |
599 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 549 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
600 base::Bind(&GKRMethod::GetLogins, | 550 base::Bind(&GKRMethod::GetLogins, |
601 base::Unretained(&method), | 551 base::Unretained(&method), |
602 form, app_string_.c_str())); | 552 form, app_string_.c_str())); |
603 GnomeKeyringResult result = method.WaitResult(forms); | 553 GnomeKeyringResult result = method.WaitResult(forms); |
604 if (result == GNOME_KEYRING_RESULT_NO_MATCH) | 554 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
605 return true; | 555 return true; |
606 if (result != GNOME_KEYRING_RESULT_OK) { | 556 if (result != GNOME_KEYRING_RESULT_OK) { |
607 LOG(ERROR) << "Keyring find failed: " | 557 LOG(ERROR) << "Keyring find failed: " |
608 << gnome_keyring_result_to_message(result); | 558 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 559 result); |
609 return false; | 560 return false; |
610 } | 561 } |
611 // Successful read of actual data. Try migration if necessary. | 562 // Successful read of actual data. Try migration if necessary. |
612 if (!migrate_tried_) | 563 if (!migrate_tried_) |
613 MigrateToProfileSpecificLogins(); | 564 MigrateToProfileSpecificLogins(); |
614 return true; | 565 return true; |
615 } | 566 } |
616 | 567 |
617 bool NativeBackendGnome::GetLoginsCreatedBetween(const base::Time& get_begin, | 568 bool NativeBackendGnome::GetLoginsCreatedBetween(const base::Time& get_begin, |
618 const base::Time& get_end, | 569 const base::Time& get_end, |
(...skipping 26 matching lines...) Expand all Loading... |
645 bool NativeBackendGnome::GetBlacklistLogins(PasswordFormList* forms) { | 596 bool NativeBackendGnome::GetBlacklistLogins(PasswordFormList* forms) { |
646 return GetLoginsList(forms, false); | 597 return GetLoginsList(forms, false); |
647 } | 598 } |
648 | 599 |
649 bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, | 600 bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, |
650 bool autofillable) { | 601 bool autofillable) { |
651 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); | 602 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
652 | 603 |
653 uint32_t blacklisted_by_user = !autofillable; | 604 uint32_t blacklisted_by_user = !autofillable; |
654 | 605 |
655 GKRMethod method; | 606 GKRMethod method(&libgnome_keyring_loader_); |
656 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 607 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
657 base::Bind(&GKRMethod::GetLoginsList, | 608 base::Bind(&GKRMethod::GetLoginsList, |
658 base::Unretained(&method), | 609 base::Unretained(&method), |
659 blacklisted_by_user, app_string_.c_str())); | 610 blacklisted_by_user, app_string_.c_str())); |
660 GnomeKeyringResult result = method.WaitResult(forms); | 611 GnomeKeyringResult result = method.WaitResult(forms); |
661 if (result == GNOME_KEYRING_RESULT_NO_MATCH) | 612 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
662 return true; | 613 return true; |
663 if (result != GNOME_KEYRING_RESULT_OK) { | 614 if (result != GNOME_KEYRING_RESULT_OK) { |
664 LOG(ERROR) << "Keyring find failed: " | 615 LOG(ERROR) << "Keyring find failed: " |
665 << gnome_keyring_result_to_message(result); | 616 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 617 result); |
666 return false; | 618 return false; |
667 } | 619 } |
668 // Successful read of actual data. Try migration if necessary. | 620 // Successful read of actual data. Try migration if necessary. |
669 if (!migrate_tried_) | 621 if (!migrate_tried_) |
670 MigrateToProfileSpecificLogins(); | 622 MigrateToProfileSpecificLogins(); |
671 return true; | 623 return true; |
672 } | 624 } |
673 | 625 |
674 bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { | 626 bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { |
675 GKRMethod method; | 627 GKRMethod method(&libgnome_keyring_loader_); |
676 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 628 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
677 base::Bind(&GKRMethod::GetAllLogins, | 629 base::Bind(&GKRMethod::GetAllLogins, |
678 base::Unretained(&method), | 630 base::Unretained(&method), |
679 app_string_.c_str())); | 631 app_string_.c_str())); |
680 GnomeKeyringResult result = method.WaitResult(forms); | 632 GnomeKeyringResult result = method.WaitResult(forms); |
681 if (result == GNOME_KEYRING_RESULT_NO_MATCH) | 633 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
682 return true; | 634 return true; |
683 if (result != GNOME_KEYRING_RESULT_OK) { | 635 if (result != GNOME_KEYRING_RESULT_OK) { |
684 LOG(ERROR) << "Keyring find failed: " | 636 LOG(ERROR) << "Keyring find failed: " |
685 << gnome_keyring_result_to_message(result); | 637 << libgnome_keyring_loader_.gnome_keyring_result_to_message( |
| 638 result); |
686 return false; | 639 return false; |
687 } | 640 } |
688 // Successful read of actual data. Try migration if necessary. | 641 // Successful read of actual data. Try migration if necessary. |
689 if (!migrate_tried_) | 642 if (!migrate_tried_) |
690 MigrateToProfileSpecificLogins(); | 643 MigrateToProfileSpecificLogins(); |
691 return true; | 644 return true; |
692 } | 645 } |
693 | 646 |
694 std::string NativeBackendGnome::GetProfileSpecificAppString() const { | 647 std::string NativeBackendGnome::GetProfileSpecificAppString() const { |
695 // Originally, the application string was always just "chrome" and used only | 648 // Originally, the application string was always just "chrome" and used only |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 // Each other profile must be able to migrate the shared data as well, | 684 // Each other profile must be able to migrate the shared data as well, |
732 // so we must leave it alone. After a few releases, we'll add code to | 685 // so we must leave it alone. After a few releases, we'll add code to |
733 // delete them, and eventually remove this migration code. | 686 // delete them, and eventually remove this migration code. |
734 // TODO(mdm): follow through with the plan above. | 687 // TODO(mdm): follow through with the plan above. |
735 PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_); | 688 PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_); |
736 } else { | 689 } else { |
737 // We failed to migrate for some reason. Use the old app string. | 690 // We failed to migrate for some reason. Use the old app string. |
738 app_string_ = kGnomeKeyringAppString; | 691 app_string_ = kGnomeKeyringAppString; |
739 } | 692 } |
740 } | 693 } |
OLD | NEW |