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