OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #if defined(DLOPEN_GNOME_KEYRING) | |
8 #include <dlfcn.h> | |
9 #endif | |
10 | |
11 #include <map> | 7 #include <map> |
12 #include <string> | 8 #include <string> |
13 | 9 |
| 10 #include <dbus/dbus-glib.h> |
| 11 #include <dlfcn.h> |
| 12 |
14 #include "base/logging.h" | 13 #include "base/logging.h" |
15 #include "base/string_util.h" | 14 #include "base/string_util.h" |
16 #include "base/time.h" | 15 #include "base/time.h" |
17 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
18 #include "chrome/browser/chrome_thread.h" | 17 #include "chrome/browser/chrome_thread.h" |
19 | 18 |
20 using webkit_glue::PasswordForm; | 19 using webkit_glue::PasswordForm; |
21 | 20 |
| 21 namespace { |
| 22 |
22 /* Many of the gnome_keyring_* functions use variable arguments, which makes | 23 /* Many of the gnome_keyring_* functions use variable arguments, which makes |
23 * them difficult if not impossible to wrap in C. Therefore, we want the | 24 * them difficult if not impossible to wrap in C. Therefore, we want the |
24 * actual uses below to either call the functions directly (if we are linking | 25 * actual uses below to either call the functions directly (if we are linking |
25 * against libgnome-keyring), or call them via appropriately-typed function | 26 * against libgnome-keyring), or call them via appropriately-typed function |
26 * pointers (if we are dynamically loading libgnome-keyring). | 27 * pointers (if we are dynamically loading libgnome-keyring). |
27 * | 28 * |
28 * Thus, instead of making a wrapper class with two implementations, we use | 29 * Thus, instead of making a wrapper class with two implementations, we use |
29 * the preprocessor to rename the calls below in the dynamic load case, and | 30 * the preprocessor to rename the calls below in the dynamic load case, and |
30 * provide a function to initialize a set of function pointers that have the | 31 * provide a function to initialize a set of function pointers that have the |
31 * alternate names. We also make sure the types are correct, since otherwise | 32 * alternate names. We also make sure the types are correct, since otherwise |
32 * dynamic loading like this would leave us vulnerable to signature changes. */ | 33 * dynamic loading like this would leave us vulnerable to signature changes. */ |
33 | 34 |
34 #if defined(DLOPEN_GNOME_KEYRING) | 35 #if defined(DLOPEN_GNOME_KEYRING) |
35 | 36 |
36 namespace { | 37 // Call a given parameter with the name of each func we use from |
| 38 // gnome keyring. |
| 39 #define GNOME_KEYRING_FOR_EACH_FUNC(F) \ |
| 40 F(is_available) \ |
| 41 F(store_password_sync) \ |
| 42 F(delete_password_sync) \ |
| 43 F(find_itemsv_sync) \ |
| 44 F(result_to_message) \ |
| 45 F(found_list_free) \ |
| 46 F(list_item_ids_sync) \ |
| 47 F(item_get_attributes_sync) \ |
| 48 F(attribute_list_free) \ |
| 49 F(item_get_info_sync) \ |
| 50 F(item_info_get_secret) \ |
| 51 F(item_info_free) |
37 | 52 |
38 gboolean (*wrap_gnome_keyring_is_available)(); | 53 #define GNOME_KEYRING_DECLARE_TYPE(name) \ |
39 GnomeKeyringResult (*wrap_gnome_keyring_store_password_sync)( // NOLINT | 54 typeof(&gnome_keyring_##name) wrap_gnome_keyring_##name; |
40 const GnomeKeyringPasswordSchema* schema, const gchar* keyring, | 55 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_DECLARE_TYPE) |
41 const gchar* display_name, const gchar* password, ...); | 56 #undef GNOME_KEYRING_DECLARE_TYPE |
42 GnomeKeyringResult (*wrap_gnome_keyring_delete_password_sync)( // NOLINT | |
43 const GnomeKeyringPasswordSchema* schema, ...); | |
44 GnomeKeyringResult (*wrap_gnome_keyring_find_itemsv_sync)( // NOLINT | |
45 GnomeKeyringItemType type, GList** found, ...); | |
46 const gchar* (*wrap_gnome_keyring_result_to_message)(GnomeKeyringResult res); | |
47 void (*wrap_gnome_keyring_found_list_free)(GList* found_list); | |
48 | 57 |
49 /* Cause the compiler to complain if the types of the above function pointers | 58 // Make it easy to initialize the function pointers above with a loop below. |
50 * do not correspond to the types of the actual gnome_keyring_* functions. */ | |
51 #define GNOME_KEYRING_VERIFY_TYPE(name) \ | |
52 typeof(&gnome_keyring_##name) name = wrap_gnome_keyring_##name; name = name | |
53 | |
54 inline void VerifyGnomeKeyringTypes() { | |
55 GNOME_KEYRING_VERIFY_TYPE(is_available); | |
56 GNOME_KEYRING_VERIFY_TYPE(store_password_sync); | |
57 GNOME_KEYRING_VERIFY_TYPE(delete_password_sync); | |
58 GNOME_KEYRING_VERIFY_TYPE(find_itemsv_sync); | |
59 GNOME_KEYRING_VERIFY_TYPE(result_to_message); | |
60 GNOME_KEYRING_VERIFY_TYPE(found_list_free); | |
61 } | |
62 #undef GNOME_KEYRING_VERIFY_TYPE | |
63 | |
64 /* Make it easy to initialize the function pointers above with a loop below. */ | |
65 #define GNOME_KEYRING_FUNCTION(name) \ | 59 #define GNOME_KEYRING_FUNCTION(name) \ |
66 {#name, reinterpret_cast<void**>(&wrap_##name)} | 60 {"gnome_keyring_"#name, reinterpret_cast<void**>(&wrap_gnome_keyring_##name)}, |
67 const struct { | 61 const struct { |
68 const char* name; | 62 const char* name; |
69 void** pointer; | 63 void** pointer; |
70 } gnome_keyring_functions[] = { | 64 } gnome_keyring_functions[] = { |
71 GNOME_KEYRING_FUNCTION(gnome_keyring_is_available), | 65 GNOME_KEYRING_FOR_EACH_FUNC(GNOME_KEYRING_FUNCTION) |
72 GNOME_KEYRING_FUNCTION(gnome_keyring_store_password_sync), | 66 {NULL, NULL} |
73 GNOME_KEYRING_FUNCTION(gnome_keyring_delete_password_sync), | |
74 GNOME_KEYRING_FUNCTION(gnome_keyring_find_itemsv_sync), | |
75 GNOME_KEYRING_FUNCTION(gnome_keyring_result_to_message), | |
76 GNOME_KEYRING_FUNCTION(gnome_keyring_found_list_free), | |
77 {NULL, NULL} | |
78 }; | 67 }; |
79 #undef GNOME_KEYRING_FUNCTION | 68 #undef GNOME_KEYRING_FUNCTION |
80 | 69 |
81 /* Allow application code below to use the normal function names, but actually | 70 #undef GNOME_KEYRING_FOR_EACH_FUNC |
82 * end up using the function pointers above instead. */ | 71 |
| 72 // Allow application code below to use the normal function names, but actually |
| 73 // end up using the function pointers above instead. |
83 #define gnome_keyring_is_available \ | 74 #define gnome_keyring_is_available \ |
84 wrap_gnome_keyring_is_available | 75 wrap_gnome_keyring_is_available |
85 #define gnome_keyring_store_password_sync \ | 76 #define gnome_keyring_store_password_sync \ |
86 wrap_gnome_keyring_store_password_sync | 77 wrap_gnome_keyring_store_password_sync |
87 #define gnome_keyring_delete_password_sync \ | 78 #define gnome_keyring_delete_password_sync \ |
88 wrap_gnome_keyring_delete_password_sync | 79 wrap_gnome_keyring_delete_password_sync |
89 #define gnome_keyring_find_itemsv_sync \ | 80 #define gnome_keyring_find_itemsv_sync \ |
90 wrap_gnome_keyring_find_itemsv_sync | 81 wrap_gnome_keyring_find_itemsv_sync |
91 #define gnome_keyring_result_to_message \ | 82 #define gnome_keyring_result_to_message \ |
92 wrap_gnome_keyring_result_to_message | 83 wrap_gnome_keyring_result_to_message |
93 #define gnome_keyring_found_list_free \ | 84 #define gnome_keyring_found_list_free \ |
94 wrap_gnome_keyring_found_list_free | 85 wrap_gnome_keyring_found_list_free |
95 | 86 #define gnome_keyring_list_item_ids_sync \ |
96 // Older versions of GNOME Keyring have bugs that prevent them from working | 87 wrap_gnome_keyring_list_item_ids_sync |
97 // correctly with this code. (In particular, the non-pageable memory allocator | 88 #define gnome_keyring_item_get_attributes_sync \ |
98 // is rather busted.) There is no official way to check the version, but newer | 89 wrap_gnome_keyring_item_get_attributes_sync |
99 // versions provide several symbols that older versions did not. It would be | 90 #define gnome_keyring_attribute_list_free \ |
100 // best if we could check for a new official API, but the only new symbols are | 91 wrap_gnome_keyring_attribute_list_free |
101 // "private" symbols. Still, it is probable that they will not change, and it's | 92 #define gnome_keyring_item_get_info_sync \ |
102 // the best we can do for now. (And eventually we won't care about the older | 93 wrap_gnome_keyring_item_get_info_sync |
103 // versions anyway so we can remove this version check some day.) | 94 #define gnome_keyring_item_info_get_secret \ |
104 bool GnomeKeyringVersionOK(void* handle) { | 95 wrap_gnome_keyring_item_info_get_secret |
105 dlerror(); | 96 #define gnome_keyring_item_info_free \ |
106 dlsym(handle, "gnome_keyring_socket_connect_daemon"); | 97 wrap_gnome_keyring_item_info_free |
107 return !dlerror(); | |
108 } | |
109 | 98 |
110 /* Load the library and initialize the function pointers. */ | 99 /* Load the library and initialize the function pointers. */ |
111 bool LoadGnomeKeyring() { | 100 bool LoadGnomeKeyring() { |
112 void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL); | 101 void* handle = dlopen("libgnome-keyring.so.0", RTLD_NOW | RTLD_GLOBAL); |
113 if (!handle) { | 102 if (!handle) { |
114 // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because | 103 // We wanted to use GNOME Keyring, but we couldn't load it. Warn, because |
115 // either the user asked for this, or we autodetected it incorrectly. (Or | 104 // either the user asked for this, or we autodetected it incorrectly. (Or |
116 // the system has broken libraries, which is also good to warn about.) | 105 // the system has broken libraries, which is also good to warn about.) |
117 LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); | 106 LOG(WARNING) << "Could not load libgnome-keyring.so.0: " << dlerror(); |
118 return false; | 107 return false; |
119 } | 108 } |
120 if (!GnomeKeyringVersionOK(handle)) { | |
121 // GNOME Keyring is too old. Only info, not a warning, as this can happen | |
122 // on older systems without the user actually asking for it explicitly. | |
123 LOG(INFO) << "libgnome-keyring.so.0 is too old!"; | |
124 dlclose(handle); | |
125 return false; | |
126 } | |
127 for (size_t i = 0; gnome_keyring_functions[i].name; ++i) { | 109 for (size_t i = 0; gnome_keyring_functions[i].name; ++i) { |
128 dlerror(); | 110 dlerror(); |
129 *gnome_keyring_functions[i].pointer = | 111 *gnome_keyring_functions[i].pointer = |
130 dlsym(handle, gnome_keyring_functions[i].name); | 112 dlsym(handle, gnome_keyring_functions[i].name); |
131 const char* error = dlerror(); | 113 const char* error = dlerror(); |
132 if (error) { | 114 if (error) { |
133 LOG(ERROR) << "Unable to load symbol " << | 115 LOG(ERROR) << "Unable to load symbol " << |
134 gnome_keyring_functions[i].name << ": " << error; | 116 gnome_keyring_functions[i].name << ": " << error; |
135 dlclose(handle); | 117 dlclose(handle); |
136 return false; | 118 return false; |
137 } | 119 } |
138 } | 120 } |
139 // We leak the library handle. That's OK: this function is called only once. | 121 // We leak the library handle. That's OK: this function is called only once. |
140 return true; | 122 return true; |
141 } | 123 } |
142 | 124 |
143 } // namespace | 125 // Older versions of GNOME Keyring have bugs that prevent them from |
| 126 // working correctly with the find_itemsv API. (In particular, the |
| 127 // non-pageable memory allocator is rather busted.) There is no |
| 128 // official way to check the version, nor could we figure out any |
| 129 // reasonable unofficial way to do it. So we work around it by using |
| 130 // a much slower API. |
| 131 #define GNOME_KEYRING_WORKAROUND_MEMORY_CORRUPTION |
144 | 132 |
145 #else // !defined(DLOPEN_GNOME_KEYRING) | 133 #else // !defined(DLOPEN_GNOME_KEYRING) |
146 | 134 |
147 namespace { | |
148 | |
149 bool LoadGnomeKeyring() { | 135 bool LoadGnomeKeyring() { |
150 // We don't do the hacky version check here. When linking directly, we assume | 136 // We don't need to do anything here. When linking directly, we |
151 // that whoever is compiling this code has checked that the version is OK. | 137 // assume that whoever is compiling this code has checked that the |
| 138 // version is OK. |
152 return true; | 139 return true; |
153 } | 140 } |
154 | 141 |
155 } // namespace | |
156 | |
157 #endif // !defined(DLOPEN_GNOME_KEYRING) | 142 #endif // !defined(DLOPEN_GNOME_KEYRING) |
158 | 143 |
159 #define GNOME_KEYRING_APPLICATION_CHROME "chrome" | 144 #define GNOME_KEYRING_APPLICATION_CHROME "chrome" |
160 | 145 |
| 146 // Convert the attributes of a given keyring entry into a new |
| 147 // PasswordForm. Note: does *not* get the actual password, as that is |
| 148 // not a key attribute! Returns NULL if the attributes are for the |
| 149 // wrong application. |
| 150 PasswordForm* FormFromAttributes(GnomeKeyringAttributeList* attrs) { |
| 151 // Read the string and int attributes into the appropriate map. |
| 152 std::map<std::string, std::string> string_attr_map; |
| 153 std::map<std::string, uint32_t> uint_attr_map; |
| 154 for (guint i = 0; i < attrs->len; ++i) { |
| 155 GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index(attrs, i); |
| 156 if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { |
| 157 if (std::string(attr.name) == "application" && |
| 158 std::string(attr.value.string) != GNOME_KEYRING_APPLICATION_CHROME) { |
| 159 // This is not a password we care about. |
| 160 return NULL; |
| 161 } |
| 162 string_attr_map[attr.name] = attr.value.string; |
| 163 } else if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { |
| 164 uint_attr_map[attr.name] = attr.value.integer; |
| 165 } |
| 166 } |
| 167 |
| 168 PasswordForm* form = new PasswordForm(); |
| 169 form->origin = GURL(string_attr_map["origin_url"]); |
| 170 form->action = GURL(string_attr_map["action_url"]); |
| 171 form->username_element = UTF8ToUTF16(string_attr_map["username_element"]); |
| 172 form->username_value = UTF8ToUTF16(string_attr_map["username_value"]); |
| 173 form->password_element = UTF8ToUTF16(string_attr_map["password_element"]); |
| 174 form->submit_element = UTF8ToUTF16(string_attr_map["submit_element"]); |
| 175 form->signon_realm = string_attr_map["signon_realm"]; |
| 176 form->ssl_valid = uint_attr_map["ssl_valid"]; |
| 177 form->preferred = uint_attr_map["preferred"]; |
| 178 int64 date_created = 0; |
| 179 bool date_ok = StringToInt64(string_attr_map["date_created"], |
| 180 &date_created); |
| 181 DCHECK(date_ok); |
| 182 DCHECK_NE(date_created, 0); |
| 183 form->date_created = base::Time::FromTimeT(date_created); |
| 184 form->blacklisted_by_user = uint_attr_map["blacklisted_by_user"]; |
| 185 form->scheme = static_cast<PasswordForm::Scheme>(uint_attr_map["scheme"]); |
| 186 |
| 187 return form; |
| 188 } |
| 189 |
| 190 } // namespace |
| 191 |
161 // Schema is analagous to the fields in PasswordForm. | 192 // Schema is analagous to the fields in PasswordForm. |
162 const GnomeKeyringPasswordSchema NativeBackendGnome::kGnomeSchema = { | 193 const GnomeKeyringPasswordSchema NativeBackendGnome::kGnomeSchema = { |
163 GNOME_KEYRING_ITEM_GENERIC_SECRET, { | 194 GNOME_KEYRING_ITEM_GENERIC_SECRET, { |
164 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 195 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
165 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 196 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
166 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 197 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
167 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 198 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
168 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 199 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
169 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 200 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
170 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 201 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 return GetLoginsList(forms, true); | 398 return GetLoginsList(forms, true); |
368 } | 399 } |
369 | 400 |
370 bool NativeBackendGnome::GetBlacklistLogins(PasswordFormList* forms) { | 401 bool NativeBackendGnome::GetBlacklistLogins(PasswordFormList* forms) { |
371 return GetLoginsList(forms, false); | 402 return GetLoginsList(forms, false); |
372 } | 403 } |
373 | 404 |
374 bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, | 405 bool NativeBackendGnome::GetLoginsList(PasswordFormList* forms, |
375 bool autofillable) { | 406 bool autofillable) { |
376 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); | 407 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 408 |
| 409 uint32_t blacklisted_by_user = !autofillable; |
| 410 |
| 411 #if !defined(GNOME_KEYRING_WORKAROUND_MEMORY_CORRUPTION) |
377 GList* found = NULL; | 412 GList* found = NULL; |
378 uint32_t blacklisted_by_user = !autofillable; | |
379 // Search gnome keyring for matching passwords. | 413 // Search gnome keyring for matching passwords. |
380 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 414 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
381 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 415 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
382 &found, | 416 &found, |
383 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, | 417 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, |
384 blacklisted_by_user, | 418 blacklisted_by_user, |
385 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 419 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
386 GNOME_KEYRING_APPLICATION_CHROME, | 420 GNOME_KEYRING_APPLICATION_CHROME, |
387 NULL); | 421 NULL); |
388 if (result == GNOME_KEYRING_RESULT_NO_MATCH) | 422 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
389 return true; | 423 return true; |
390 if (result != GNOME_KEYRING_RESULT_OK) { | 424 if (result != GNOME_KEYRING_RESULT_OK) { |
391 LOG(ERROR) << "Keyring find failed: " | 425 LOG(ERROR) << "Keyring find failed: " |
392 << gnome_keyring_result_to_message(result); | 426 << gnome_keyring_result_to_message(result); |
393 return false; | 427 return false; |
394 } | 428 } |
395 ConvertFormList(found, forms); | 429 ConvertFormList(found, forms); |
396 return true; | 430 return true; |
| 431 #else |
| 432 PasswordFormList all_forms; |
| 433 if (!GetAllLogins(&all_forms)) |
| 434 return false; |
| 435 // Now manually filter the result for the values we care about. |
| 436 for (size_t i = 0; i < all_forms.size(); ++i) { |
| 437 if (all_forms[i]->blacklisted_by_user == blacklisted_by_user) |
| 438 forms->push_back(all_forms[i]); |
| 439 else |
| 440 delete all_forms[i]; |
| 441 } |
| 442 return true; |
| 443 #endif |
397 } | 444 } |
398 | 445 |
399 bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { | 446 bool NativeBackendGnome::GetAllLogins(PasswordFormList* forms) { |
| 447 // Older versions of GNOME Keyring have bugs that prevent them from |
| 448 // working correctly with the find_itemsv API. (In particular, the |
| 449 // non-pageable memory allocator is rather busted.) There is no |
| 450 // official way to check the version, nor could we figure out any |
| 451 // reasonable unofficial way to do it. So we work around it by |
| 452 // using a much slower API. |
| 453 |
| 454 #if !defined(GNOME_KEYRING_WORKAROUND_MEMORY_CORRUPTION) |
400 GList* found = NULL; | 455 GList* found = NULL; |
401 // We need to search for something, otherwise we get no results - so we search | 456 // We need to search for something, otherwise we get no results - so |
402 // for the fixed application string. | 457 // we search for the fixed application string. |
403 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 458 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
404 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 459 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
405 &found, | 460 &found, |
406 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 461 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
407 GNOME_KEYRING_APPLICATION_CHROME, | 462 GNOME_KEYRING_APPLICATION_CHROME, |
408 NULL); | 463 NULL); |
409 if (result == GNOME_KEYRING_RESULT_NO_MATCH) | 464 if (result == GNOME_KEYRING_RESULT_NO_MATCH) |
410 return true; | 465 return true; |
411 if (result != GNOME_KEYRING_RESULT_OK) { | 466 if (result != GNOME_KEYRING_RESULT_OK) { |
412 LOG(ERROR) << "Keyring find failed: " | 467 LOG(ERROR) << "Keyring find failed: " |
413 << gnome_keyring_result_to_message(result); | 468 << gnome_keyring_result_to_message(result); |
414 return false; | 469 return false; |
415 } | 470 } |
416 ConvertFormList(found, forms); | 471 ConvertFormList(found, forms); |
417 return true; | 472 return true; |
| 473 #else |
| 474 GList* ids = NULL; |
| 475 GnomeKeyringResult result = gnome_keyring_list_item_ids_sync(NULL, &ids); |
| 476 if (result != GNOME_KEYRING_RESULT_OK) { |
| 477 LOG(ERROR) << "Keyring itemid list failed: " |
| 478 << gnome_keyring_result_to_message(result); |
| 479 return false; |
| 480 } |
| 481 |
| 482 for (GList* i = ids; i; i = i->next) { |
| 483 int id = GPOINTER_TO_INT(i->data); |
| 484 GnomeKeyringAttributeList* attrs = NULL; |
| 485 result = gnome_keyring_item_get_attributes_sync(NULL, id, &attrs); |
| 486 if (result != GNOME_KEYRING_RESULT_OK) { |
| 487 LOG(ERROR) << "Keyring get item attributes failed:" |
| 488 << gnome_keyring_result_to_message(result); |
| 489 gnome_keyring_attribute_list_free(attrs); |
| 490 break; |
| 491 } |
| 492 |
| 493 PasswordForm* form = FormFromAttributes(attrs); |
| 494 gnome_keyring_attribute_list_free(attrs); |
| 495 |
| 496 if (form) { |
| 497 GnomeKeyringItemInfo* info = NULL; |
| 498 result = gnome_keyring_item_get_info_sync(NULL, id, &info); |
| 499 if (result != GNOME_KEYRING_RESULT_OK) { |
| 500 delete form; |
| 501 break; |
| 502 } |
| 503 form->password_value = UTF8ToUTF16( |
| 504 gnome_keyring_item_info_get_secret(info)); |
| 505 |
| 506 gnome_keyring_item_info_free(info); |
| 507 forms->push_back(form); |
| 508 } |
| 509 } |
| 510 g_list_free(ids); |
| 511 |
| 512 return result == GNOME_KEYRING_RESULT_OK; |
| 513 #endif |
418 } | 514 } |
419 | 515 |
420 void NativeBackendGnome::ConvertFormList(GList* found, | 516 void NativeBackendGnome::ConvertFormList(GList* found, |
421 PasswordFormList* forms) { | 517 PasswordFormList* forms) { |
422 GList* element = g_list_first(found); | 518 GList* element = g_list_first(found); |
423 while (element != NULL) { | 519 while (element != NULL) { |
424 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); | 520 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); |
| 521 GnomeKeyringAttributeList* attrs = data->attributes; |
425 | 522 |
426 GnomeKeyringAttributeList* attrs = data->attributes; | 523 PasswordForm* form = FormFromAttributes(attrs); |
427 // Read the string and int attributes into the appropriate map. | |
428 std::map<std::string, std::string> string_attr_map; | |
429 std::map<std::string, uint32_t> uint_attr_map; | |
430 for (guint i = 0; i < attrs->len; ++i) { | |
431 GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index(attrs, i); | |
432 if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { | |
433 string_attr_map[attr.name] = attr.value.string; | |
434 } else if (attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { | |
435 uint_attr_map[attr.name] = attr.value.integer; | |
436 } | |
437 } | |
438 | |
439 PasswordForm* form = new PasswordForm(); | |
440 form->origin = GURL(string_attr_map["origin_url"]); | |
441 form->action = GURL(string_attr_map["action_url"]); | |
442 form->username_element = UTF8ToUTF16(string_attr_map["username_element"]); | |
443 form->username_value = UTF8ToUTF16(string_attr_map["username_value"]); | |
444 form->password_element = UTF8ToUTF16(string_attr_map["password_element"]); | |
445 form->password_value = UTF8ToUTF16(data->secret); | 524 form->password_value = UTF8ToUTF16(data->secret); |
446 form->submit_element = UTF8ToUTF16(string_attr_map["submit_element"]); | |
447 form->signon_realm = string_attr_map["signon_realm"]; | |
448 form->ssl_valid = uint_attr_map["ssl_valid"]; | |
449 form->preferred = uint_attr_map["preferred"]; | |
450 int64 date_created = 0; | |
451 bool date_ok = StringToInt64(string_attr_map["date_created"], | |
452 &date_created); | |
453 DCHECK(date_ok); | |
454 DCHECK_NE(date_created, 0); | |
455 form->date_created = base::Time::FromTimeT(date_created); | |
456 form->blacklisted_by_user = uint_attr_map["blacklisted_by_user"]; | |
457 form->scheme = static_cast<PasswordForm::Scheme>(uint_attr_map["scheme"]); | |
458 | |
459 forms->push_back(form); | 525 forms->push_back(form); |
460 | 526 |
461 element = g_list_next(element); | 527 element = g_list_next(element); |
462 } | 528 } |
463 gnome_keyring_found_list_free(found); | 529 gnome_keyring_found_list_free(found); |
464 } | 530 } |
OLD | NEW |