OLD | NEW |
1 // Copyright (c) 2006-2009 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/password_store_gnome.h" | 5 #include "chrome/browser/password_manager/password_store_gnome.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/task.h" | 11 #include "base/task.h" |
12 #include "base/time.h" | 12 #include "base/time.h" |
| 13 #include "base/utf_string_conversions.h" |
13 | 14 |
14 using std::map; | 15 using std::map; |
15 using std::string; | 16 using std::string; |
16 using std::vector; | 17 using std::vector; |
| 18 using webkit_glue::PasswordForm; |
| 19 |
| 20 #define GNOME_KEYRING_APPLICATION_CHROME "chrome" |
17 | 21 |
18 // Schema is analagous to the fields in PasswordForm. | 22 // Schema is analagous to the fields in PasswordForm. |
19 const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = { | 23 const GnomeKeyringPasswordSchema PasswordStoreGnome::kGnomeSchema = { |
20 GNOME_KEYRING_ITEM_GENERIC_SECRET, { | 24 GNOME_KEYRING_ITEM_GENERIC_SECRET, { |
21 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 25 { "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
22 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 26 { "action_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
23 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 27 { "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
24 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 28 { "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
25 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 29 { "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
26 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 30 { "submit_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
27 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 31 { "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
28 { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 32 { "ssl_valid", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
29 { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 33 { "preferred", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
30 { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, | 34 { "date_created", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
31 { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 35 { "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
32 { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, | 36 { "scheme", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32 }, |
| 37 // This field is always "chrome" so that we can search for it. |
| 38 { "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, |
33 { NULL } | 39 { NULL } |
34 } | 40 } |
35 }; | 41 }; |
36 | 42 |
37 PasswordStoreGnome::PasswordStoreGnome() { | 43 PasswordStoreGnome::PasswordStoreGnome(LoginDatabase* login_db, |
| 44 Profile* profile, |
| 45 WebDataService* web_data_service) { |
38 } | 46 } |
39 | 47 |
40 PasswordStoreGnome::~PasswordStoreGnome() { | 48 PasswordStoreGnome::~PasswordStoreGnome() { |
41 } | 49 } |
42 | 50 |
43 bool PasswordStoreGnome::Init() { | 51 bool PasswordStoreGnome::Init() { |
44 return PasswordStore::Init() && gnome_keyring_is_available(); | 52 return PasswordStore::Init() && gnome_keyring_is_available(); |
45 } | 53 } |
46 | 54 |
47 void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) { | 55 void PasswordStoreGnome::AddLoginImpl(const PasswordForm& form) { |
48 AutoLock l(gnome_keyring_lock_); | 56 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
49 GnomeKeyringResult result = gnome_keyring_store_password_sync( | 57 AddLoginHelper(form, base::Time::Now()); |
50 &kGnomeSchema, | |
51 NULL, // Default keyring. | |
52 // TODO(johnmaguire@google.com): Localise this. | |
53 "Form password stored by Chrome", | |
54 WideToASCII(form.password_value).c_str(), | |
55 "origin_url", form.origin.spec().c_str(), | |
56 "action_url", form.action.spec().c_str(), | |
57 "username_element", form.username_element.c_str(), | |
58 "username_value", form.username_value.c_str(), | |
59 "password_element", form.password_element.c_str(), | |
60 "submit_element", form.submit_element.c_str(), | |
61 "signon_realm", form.signon_realm.c_str(), | |
62 "ssl_valid", form.ssl_valid, | |
63 "preferred", form.preferred, | |
64 "date_created", Int64ToString(base::Time::Now().ToTimeT()).c_str(), | |
65 "blacklisted_by_user", form.blacklisted_by_user, | |
66 "scheme", form.scheme, | |
67 NULL); | |
68 | |
69 if (result != GNOME_KEYRING_RESULT_OK) { | |
70 LOG(ERROR) << "Keyring save failed: " | |
71 << gnome_keyring_result_to_message(result); | |
72 } | |
73 } | 58 } |
74 | 59 |
75 void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) { | 60 void PasswordStoreGnome::UpdateLoginImpl(const PasswordForm& form) { |
76 AddLoginImpl(form); // Add & Update are the same in gnome keyring. | 61 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by |
| 62 // origin_url, username_element, username_value, password_element, and |
| 63 // signon_realm. We then compare the result to the updated form. If they |
| 64 // differ in any of the action, password_value, ssl_valid, or preferred |
| 65 // fields, then we add a new login with those fields updated and only delete |
| 66 // the original on success. |
| 67 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 68 GList* found = NULL; |
| 69 // Search gnome keyring for matching passwords. |
| 70 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 71 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 72 &found, |
| 73 "origin_url", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 74 form.origin.spec().c_str(), |
| 75 "username_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 76 UTF16ToUTF8(form.username_element).c_str(), |
| 77 "username_value", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 78 UTF16ToUTF8(form.username_value).c_str(), |
| 79 "password_element", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 80 UTF16ToUTF8(form.password_element).c_str(), |
| 81 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 82 form.signon_realm.c_str(), |
| 83 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 84 GNOME_KEYRING_APPLICATION_CHROME, |
| 85 NULL); |
| 86 vector<PasswordForm*> forms; |
| 87 if (result == GNOME_KEYRING_RESULT_OK) { |
| 88 FillFormVector(found, &forms); |
| 89 for (size_t i = 0; i < forms.size(); ++i) { |
| 90 if (forms[i]->action != form.action || |
| 91 forms[i]->password_value != form.password_value || |
| 92 forms[i]->ssl_valid != form.ssl_valid || |
| 93 forms[i]->preferred != form.preferred) { |
| 94 PasswordForm updated = *forms[i]; |
| 95 updated.action = form.action; |
| 96 updated.password_value = form.password_value; |
| 97 updated.ssl_valid = form.ssl_valid; |
| 98 updated.preferred = form.preferred; |
| 99 if (AddLoginHelper(updated, updated.date_created)) |
| 100 RemoveLoginImpl(*forms[i]); |
| 101 } |
| 102 delete forms[i]; |
| 103 } |
| 104 } else { |
| 105 LOG(ERROR) << "Keyring find failed: " |
| 106 << gnome_keyring_result_to_message(result); |
| 107 } |
77 } | 108 } |
78 | 109 |
79 void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) { | 110 void PasswordStoreGnome::RemoveLoginImpl(const PasswordForm& form) { |
80 AutoLock l(gnome_keyring_lock_); | 111 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 112 // We find forms using the same fields as LoginDatabase::RemoveLogin(). |
81 GnomeKeyringResult result = gnome_keyring_delete_password_sync( | 113 GnomeKeyringResult result = gnome_keyring_delete_password_sync( |
82 &kGnomeSchema, | 114 &kGnomeSchema, |
83 "origin_url", form.origin.spec().c_str(), | 115 "origin_url", form.origin.spec().c_str(), |
84 "action_url", form.action.spec().c_str(), | 116 "action_url", form.action.spec().c_str(), |
85 "username_element", form.username_element.c_str(), | 117 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
86 "username_value", form.username_value.c_str(), | 118 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
87 "password_element", form.password_element.c_str(), | 119 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
88 "submit_element", form.submit_element.c_str(), | 120 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
| 121 "signon_realm", form.signon_realm.c_str(), |
| 122 NULL); |
| 123 if (result != GNOME_KEYRING_RESULT_OK) { |
| 124 LOG(ERROR) << "Keyring delete failed: " |
| 125 << gnome_keyring_result_to_message(result); |
| 126 } |
| 127 } |
| 128 |
| 129 void PasswordStoreGnome::RemoveLoginsCreatedBetweenImpl( |
| 130 const base::Time& delete_begin, |
| 131 const base::Time& delete_end) { |
| 132 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 133 GList* found = NULL; |
| 134 // Search GNOME keyring for all passwords, then delete the ones in the range. |
| 135 // We need to search for something, otherwise we get no results - so we search |
| 136 // for the fixed application string. |
| 137 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 138 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 139 &found, |
| 140 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 141 GNOME_KEYRING_APPLICATION_CHROME, |
| 142 NULL); |
| 143 if (result == GNOME_KEYRING_RESULT_OK) { |
| 144 // We could walk the list and delete items as we find them, but it is much |
| 145 // easier to build the vector and use RemoveLoginImpl() to delete them. |
| 146 vector<PasswordForm*> forms; |
| 147 FillFormVector(found, &forms); |
| 148 for (size_t i = 0; i < forms.size(); ++i) { |
| 149 if (delete_begin <= forms[i]->date_created && |
| 150 (delete_end.is_null() || forms[i]->date_created < delete_end)) { |
| 151 RemoveLoginImpl(*forms[i]); |
| 152 } |
| 153 delete forms[i]; |
| 154 } |
| 155 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) { |
| 156 LOG(ERROR) << "Keyring find failed: " |
| 157 << gnome_keyring_result_to_message(result); |
| 158 } |
| 159 } |
| 160 |
| 161 void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request, |
| 162 const PasswordForm& form) { |
| 163 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 164 GList* found = NULL; |
| 165 // Search gnome keyring for matching passwords. |
| 166 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
| 167 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
| 168 &found, |
| 169 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 170 form.signon_realm.c_str(), |
| 171 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
| 172 GNOME_KEYRING_APPLICATION_CHROME, |
| 173 NULL); |
| 174 vector<PasswordForm*> forms; |
| 175 if (result == GNOME_KEYRING_RESULT_OK) { |
| 176 FillFormVector(found, &forms); |
| 177 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) { |
| 178 LOG(ERROR) << "Keyring find failed: " |
| 179 << gnome_keyring_result_to_message(result); |
| 180 } |
| 181 NotifyConsumer(request, forms); |
| 182 } |
| 183 |
| 184 void PasswordStoreGnome::GetAutofillableLoginsImpl( |
| 185 GetLoginsRequest* request) { |
| 186 std::vector<PasswordForm*> forms; |
| 187 FillAutofillableLogins(&forms); |
| 188 NotifyConsumer(request, forms); |
| 189 } |
| 190 |
| 191 void PasswordStoreGnome::GetBlacklistLoginsImpl( |
| 192 GetLoginsRequest* request) { |
| 193 std::vector<PasswordForm*> forms; |
| 194 FillBlacklistLogins(&forms); |
| 195 NotifyConsumer(request, forms); |
| 196 } |
| 197 |
| 198 bool PasswordStoreGnome::FillAutofillableLogins( |
| 199 std::vector<PasswordForm*>* forms) { |
| 200 return FillSomeLogins(true, forms); |
| 201 } |
| 202 |
| 203 bool PasswordStoreGnome::FillBlacklistLogins( |
| 204 std::vector<PasswordForm*>* forms) { |
| 205 return FillSomeLogins(false, forms); |
| 206 } |
| 207 |
| 208 bool PasswordStoreGnome::AddLoginHelper(const PasswordForm& form, |
| 209 const base::Time& date_created) { |
| 210 GnomeKeyringResult result = gnome_keyring_store_password_sync( |
| 211 &kGnomeSchema, |
| 212 NULL, // Default keyring. |
| 213 form.origin.spec().c_str(), // Display name. |
| 214 UTF16ToUTF8(form.password_value).c_str(), |
| 215 "origin_url", form.origin.spec().c_str(), |
| 216 "action_url", form.action.spec().c_str(), |
| 217 "username_element", UTF16ToUTF8(form.username_element).c_str(), |
| 218 "username_value", UTF16ToUTF8(form.username_value).c_str(), |
| 219 "password_element", UTF16ToUTF8(form.password_element).c_str(), |
| 220 "submit_element", UTF16ToUTF8(form.submit_element).c_str(), |
89 "signon_realm", form.signon_realm.c_str(), | 221 "signon_realm", form.signon_realm.c_str(), |
90 "ssl_valid", form.ssl_valid, | 222 "ssl_valid", form.ssl_valid, |
91 "preferred", form.preferred, | 223 "preferred", form.preferred, |
92 "date_created", Int64ToString(form.date_created.ToTimeT()).c_str(), | 224 "date_created", Int64ToString(date_created.ToTimeT()).c_str(), |
93 "blacklisted_by_user", form.blacklisted_by_user, | 225 "blacklisted_by_user", form.blacklisted_by_user, |
94 "scheme", form.scheme, | 226 "scheme", form.scheme, |
95 NULL); | 227 "application", GNOME_KEYRING_APPLICATION_CHROME, |
| 228 NULL); |
| 229 |
96 if (result != GNOME_KEYRING_RESULT_OK) { | 230 if (result != GNOME_KEYRING_RESULT_OK) { |
97 LOG(ERROR) << "Keyring delete failed: " | 231 LOG(ERROR) << "Keyring save failed: " |
98 << gnome_keyring_result_to_message(result); | 232 << gnome_keyring_result_to_message(result); |
99 } | 233 return false; |
100 } | 234 } |
101 | 235 return true; |
102 void PasswordStoreGnome::GetLoginsImpl(GetLoginsRequest* request) { | 236 } |
103 AutoLock l(gnome_keyring_lock_); | 237 |
104 GList* found = NULL; | 238 bool PasswordStoreGnome::FillSomeLogins( |
| 239 bool autofillable, |
| 240 std::vector<PasswordForm*>* forms) { |
| 241 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB)); |
| 242 GList* found = NULL; |
| 243 uint32_t blacklisted_by_user = !autofillable; |
105 // Search gnome keyring for matching passwords. | 244 // Search gnome keyring for matching passwords. |
106 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( | 245 GnomeKeyringResult result = gnome_keyring_find_itemsv_sync( |
107 GNOME_KEYRING_ITEM_GENERIC_SECRET, | 246 GNOME_KEYRING_ITEM_GENERIC_SECRET, |
108 &found, | 247 &found, |
109 "signon_realm", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, | 248 "blacklisted_by_user", GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32, |
110 request->form.signon_realm.c_str(), | 249 blacklisted_by_user, |
111 NULL); | 250 "application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, |
112 vector<PasswordForm*> forms; | 251 GNOME_KEYRING_APPLICATION_CHROME, |
113 if (result == GNOME_KEYRING_RESULT_NO_MATCH) { | 252 NULL); |
114 NotifyConsumer(request, forms); | 253 if (result == GNOME_KEYRING_RESULT_OK) { |
115 return; | 254 FillFormVector(found, forms); |
116 } else if (result != GNOME_KEYRING_RESULT_OK) { | 255 } else if (result != GNOME_KEYRING_RESULT_NO_MATCH) { |
117 LOG(ERROR) << "Keyring find failed: " | 256 LOG(ERROR) << "Keyring find failed: " |
118 << gnome_keyring_result_to_message(result); | 257 << gnome_keyring_result_to_message(result); |
119 NotifyConsumer(request, forms); | 258 return false; |
120 return; | 259 } |
121 } | 260 return true; |
122 | 261 } |
123 // Parse all the results from the returned GList into a | 262 |
124 // vector<PasswordForm*>. PasswordForms are allocated on the heap. These | 263 void PasswordStoreGnome::FillFormVector(GList* found, |
125 // will be deleted by the consumer. | 264 std::vector<PasswordForm*>* forms) { |
126 GList* element = g_list_first(found); | 265 GList* element = g_list_first(found); |
127 while (element != NULL) { | 266 while (element != NULL) { |
128 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); | 267 GnomeKeyringFound* data = static_cast<GnomeKeyringFound*>(element->data); |
129 char* password = data->secret; | 268 char* password = data->secret; |
130 | 269 |
131 GnomeKeyringAttributeList* attributes = data->attributes; | 270 GnomeKeyringAttributeList* attributes = data->attributes; |
132 // Read the string & int attributes into the appropriate map. | 271 // Read the string and int attributes into the appropriate map. |
133 map<string, string> string_attribute_map; | 272 map<string, string> string_attribute_map; |
134 map<string, uint32> uint_attribute_map; | 273 map<string, uint32> uint_attribute_map; |
135 for (unsigned int i = 0; i < attributes->len; ++i) { | 274 for (unsigned int i = 0; i < attributes->len; ++i) { |
136 GnomeKeyringAttribute attribute = | 275 GnomeKeyringAttribute attribute = |
137 gnome_keyring_attribute_list_index(attributes, i); | 276 gnome_keyring_attribute_list_index(attributes, i); |
138 if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { | 277 if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING) { |
139 string_attribute_map[string(attribute.name)] = | 278 string_attribute_map[string(attribute.name)] = |
140 string(attribute.value.string); | 279 string(attribute.value.string); |
141 } else if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { | 280 } else if (attribute.type == GNOME_KEYRING_ATTRIBUTE_TYPE_UINT32) { |
142 uint_attribute_map[string(attribute.name)] = attribute.value.integer; | 281 uint_attribute_map[string(attribute.name)] = attribute.value.integer; |
143 } | 282 } |
144 } | 283 } |
145 | 284 |
146 PasswordForm* form = new PasswordForm(); | 285 PasswordForm* form = new PasswordForm(); |
147 form->origin = GURL(string_attribute_map["origin_url"]); | 286 form->origin = GURL(string_attribute_map["origin_url"]); |
148 form->action = GURL(string_attribute_map["action_url"]); | 287 form->action = GURL(string_attribute_map["action_url"]); |
149 form->username_element = | 288 form->username_element = |
150 ASCIIToWide(string(string_attribute_map["username_element"])); | 289 UTF8ToUTF16(string(string_attribute_map["username_element"])); |
151 form->username_value = | 290 form->username_value = |
152 ASCIIToWide(string(string_attribute_map["username_value"])); | 291 UTF8ToUTF16(string(string_attribute_map["username_value"])); |
153 form->password_element = | 292 form->password_element = |
154 ASCIIToWide(string(string_attribute_map["password_element"])); | 293 UTF8ToUTF16(string(string_attribute_map["password_element"])); |
155 form->password_value = ASCIIToWide(string(password)); | 294 form->password_value = UTF8ToUTF16(string(password)); |
156 form->submit_element = | 295 form->submit_element = |
157 ASCIIToWide(string(string_attribute_map["submit_element"])); | 296 UTF8ToUTF16(string(string_attribute_map["submit_element"])); |
158 form->signon_realm = uint_attribute_map["signon_realm"]; | 297 form->signon_realm = string_attribute_map["signon_realm"]; |
159 form->ssl_valid = uint_attribute_map["ssl_valid"]; | 298 form->ssl_valid = uint_attribute_map["ssl_valid"]; |
160 form->preferred = uint_attribute_map["preferred"]; | 299 form->preferred = uint_attribute_map["preferred"]; |
161 string date = string_attribute_map["date_created"]; | 300 string date = string_attribute_map["date_created"]; |
162 int64 date_created = 0; | 301 int64 date_created = 0; |
163 DCHECK(StringToInt64(date, &date_created) && date_created != 0); | 302 bool date_ok = StringToInt64(date, &date_created); |
| 303 DCHECK(date_ok); |
| 304 DCHECK(date_created != 0); |
164 form->date_created = base::Time::FromTimeT(date_created); | 305 form->date_created = base::Time::FromTimeT(date_created); |
165 form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"]; | 306 form->blacklisted_by_user = uint_attribute_map["blacklisted_by_user"]; |
166 form->scheme = | 307 form->scheme = static_cast<PasswordForm::Scheme>( |
167 static_cast<PasswordForm::Scheme>(uint_attribute_map["scheme"]); | 308 uint_attribute_map["scheme"]); |
168 | 309 |
169 forms.push_back(form); | 310 forms->push_back(form); |
170 | 311 |
171 element = g_list_next(element); | 312 element = g_list_next(element); |
172 } | 313 } |
173 gnome_keyring_found_list_free(found); | 314 gnome_keyring_found_list_free(found); |
174 found = NULL; | |
175 | |
176 NotifyConsumer(request, forms); | |
177 } | 315 } |
OLD | NEW |