Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1535)

Side by Side Diff: chrome/browser/password_manager/native_backend_libsecret.cc

Issue 906973007: PasswordStore: Clean up expectations about rewriting vectors of forms (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix FillMatchingLogins + a typo Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 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_libsecret.h" 5 #include "chrome/browser/password_manager/native_backend_libsecret.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #include <list> 8 #include <list>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 name_values_.push_back(value); 232 name_values_.push_back(value);
233 gpointer value_str = 233 gpointer value_str =
234 static_cast<gpointer>(const_cast<char*>(name_values_.back().c_str())); 234 static_cast<gpointer>(const_cast<char*>(name_values_.back().c_str()));
235 g_hash_table_insert(attrs_, name_str, value_str); 235 g_hash_table_insert(attrs_, name_str, value_str);
236 } 236 }
237 237
238 void LibsecretAttributesBuilder::Append(const std::string& name, int64 value) { 238 void LibsecretAttributesBuilder::Append(const std::string& name, int64 value) {
239 Append(name, base::Int64ToString(value)); 239 Append(name, base::Int64ToString(value));
240 } 240 }
241 241
242 // Generates a profile-specific app string based on profile_id_.
243 std::string GetProfileSpecificAppString(LocalProfileId id) {
244 // Originally, the application string was always just "chrome" and used only
245 // so that we had *something* to search for since GNOME Keyring won't search
246 // for nothing. Now we use it to distinguish passwords for different profiles.
247 return base::StringPrintf("%s-%d", kLibsecretAppString, id);
248 }
249
242 } // namespace 250 } // namespace
243 251
244 bool LibsecretLoader::LibsecretIsAvailable() { 252 bool LibsecretLoader::LibsecretIsAvailable() {
245 if (!libsecret_loaded) 253 if (!libsecret_loaded)
246 return false; 254 return false;
247 // A dummy query is made to check for availability, because libsecret doesn't 255 // A dummy query is made to check for availability, because libsecret doesn't
248 // have a dedicated availability function. For performance reasons, the query 256 // have a dedicated availability function. For performance reasons, the query
249 // is meant to return an empty result. 257 // is meant to return an empty result.
250 LibsecretAttributesBuilder attrs; 258 LibsecretAttributesBuilder attrs;
251 attrs.Append("application", "chrome-string_to_get_empty_result"); 259 attrs.Append("application", "chrome-string_to_get_empty_result");
(...skipping 24 matching lines...) Expand all
276 return LoadLibsecret() && LibsecretIsAvailable(); 284 return LoadLibsecret() && LibsecretIsAvailable();
277 } 285 }
278 286
279 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin( 287 password_manager::PasswordStoreChangeList NativeBackendLibsecret::AddLogin(
280 const PasswordForm& form) { 288 const PasswordForm& form) {
281 // Based on LoginDatabase::AddLogin(), we search for an existing match based 289 // Based on LoginDatabase::AddLogin(), we search for an existing match based
282 // on origin_url, username_element, username_value, password_element, submit 290 // on origin_url, username_element, username_value, password_element, submit
283 // element, and signon_realm first, remove that, and then add the new entry. 291 // element, and signon_realm first, remove that, and then add the new entry.
284 // We'd add the new one first, and then delete the original, but then the 292 // We'd add the new one first, and then delete the original, but then the
285 // delete might actually delete the newly-added entry! 293 // delete might actually delete the newly-added entry!
286 ScopedVector<autofill::PasswordForm> forms; 294 ScopedVector<autofill::PasswordForm> forms =
287 AddUpdateLoginSearch(form, SEARCH_USE_SUBMIT, &forms); 295 AddUpdateLoginSearch(form, SEARCH_USE_SUBMIT);
288 password_manager::PasswordStoreChangeList changes; 296 password_manager::PasswordStoreChangeList changes;
289 if (forms.size() > 0) { 297 if (forms.size() > 0) {
290 if (forms.size() > 1) { 298 if (forms.size() > 1) {
291 VLOG(1) << "Adding login when there are " << forms.size() 299 VLOG(1) << "Adding login when there are " << forms.size()
292 << " matching logins already! Will replace only the first."; 300 << " matching logins already! Will replace only the first.";
293 } 301 }
294 302
295 if (RemoveLogin(*forms[0])) { 303 if (RemoveLogin(*forms[0])) {
296 changes.push_back(password_manager::PasswordStoreChange( 304 changes.push_back(password_manager::PasswordStoreChange(
297 password_manager::PasswordStoreChange::REMOVE, *forms[0])); 305 password_manager::PasswordStoreChange::REMOVE, *forms[0]));
(...skipping 11 matching lines...) Expand all
309 password_manager::PasswordStoreChangeList* changes) { 317 password_manager::PasswordStoreChangeList* changes) {
310 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by 318 // Based on LoginDatabase::UpdateLogin(), we search for forms to update by
311 // origin_url, username_element, username_value, password_element, and 319 // origin_url, username_element, username_value, password_element, and
312 // signon_realm. We then compare the result to the updated form. If they 320 // signon_realm. We then compare the result to the updated form. If they
313 // differ in any of the mutable fields, then we remove the original, and 321 // differ in any of the mutable fields, then we remove the original, and
314 // then add the new entry. We'd add the new one first, and then delete the 322 // then add the new entry. We'd add the new one first, and then delete the
315 // original, but then the delete might actually delete the newly-added entry! 323 // original, but then the delete might actually delete the newly-added entry!
316 DCHECK(changes); 324 DCHECK(changes);
317 changes->clear(); 325 changes->clear();
318 326
319 ScopedVector<autofill::PasswordForm> forms; 327 ScopedVector<autofill::PasswordForm> forms =
320 AddUpdateLoginSearch(form, SEARCH_IGNORE_SUBMIT, &forms); 328 AddUpdateLoginSearch(form, SEARCH_IGNORE_SUBMIT);
321 329
322 bool removed = false; 330 bool removed = false;
323 for (size_t i = 0; i < forms.size(); ++i) { 331 for (size_t i = 0; i < forms.size(); ++i) {
324 if (*forms[i] != form) { 332 if (*forms[i] != form) {
325 RemoveLogin(*forms[i]); 333 RemoveLogin(*forms[i]);
326 removed = true; 334 removed = true;
327 } 335 }
328 } 336 }
329 if (!removed) 337 if (!removed)
330 return true; 338 return true;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 password_manager::PasswordStoreChangeList* changes) { 379 password_manager::PasswordStoreChangeList* changes) {
372 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); 380 return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes);
373 } 381 }
374 382
375 bool NativeBackendLibsecret::GetLogins( 383 bool NativeBackendLibsecret::GetLogins(
376 const PasswordForm& form, 384 const PasswordForm& form,
377 ScopedVector<autofill::PasswordForm>* forms) { 385 ScopedVector<autofill::PasswordForm>* forms) {
378 return GetLoginsList(&form, ALL_LOGINS, forms); 386 return GetLoginsList(&form, ALL_LOGINS, forms);
379 } 387 }
380 388
381 void NativeBackendLibsecret::AddUpdateLoginSearch( 389 ScopedVector<autofill::PasswordForm>
390 NativeBackendLibsecret::AddUpdateLoginSearch(
382 const autofill::PasswordForm& lookup_form, 391 const autofill::PasswordForm& lookup_form,
383 AddUpdateLoginSearchOptions options, 392 AddUpdateLoginSearchOptions options) {
384 ScopedVector<autofill::PasswordForm>* forms) {
385 LibsecretAttributesBuilder attrs; 393 LibsecretAttributesBuilder attrs;
386 attrs.Append("origin_url", lookup_form.origin.spec()); 394 attrs.Append("origin_url", lookup_form.origin.spec());
387 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element)); 395 attrs.Append("username_element", UTF16ToUTF8(lookup_form.username_element));
388 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value)); 396 attrs.Append("username_value", UTF16ToUTF8(lookup_form.username_value));
389 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element)); 397 attrs.Append("password_element", UTF16ToUTF8(lookup_form.password_element));
390 if (options == SEARCH_USE_SUBMIT) 398 if (options == SEARCH_USE_SUBMIT)
391 attrs.Append("submit_element", UTF16ToUTF8(lookup_form.submit_element)); 399 attrs.Append("submit_element", UTF16ToUTF8(lookup_form.submit_element));
392 attrs.Append("signon_realm", lookup_form.signon_realm); 400 attrs.Append("signon_realm", lookup_form.signon_realm);
393 attrs.Append("application", app_string_); 401 attrs.Append("application", app_string_);
394 402
395 GError* error = nullptr; 403 GError* error = nullptr;
396 GList* found = secret_service_search_sync(nullptr, // default secret service 404 GList* found = secret_service_search_sync(nullptr, // default secret service
397 &kLibsecretSchema, attrs.Get(), 405 &kLibsecretSchema, attrs.Get(),
398 SECRET_SEARCH_ALL, 406 SECRET_SEARCH_ALL,
399 nullptr, // no cancellable ojbect 407 nullptr, // no cancellable ojbect
400 &error); 408 &error);
401 if (error) { 409 if (error) {
402 VLOG(1) << "Unable to get logins " << error->message; 410 VLOG(1) << "Unable to get logins " << error->message;
403 g_error_free(error); 411 g_error_free(error);
404 if (found) 412 if (found)
405 g_list_free(found); 413 g_list_free(found);
406 return; 414 return ScopedVector<autofill::PasswordForm>();
407 } 415 }
408 416
409 ConvertFormList(found, &lookup_form, forms); 417 return ConvertFormList(found, &lookup_form);
410 } 418 }
411 419
412 bool NativeBackendLibsecret::RawAddLogin(const PasswordForm& form) { 420 bool NativeBackendLibsecret::RawAddLogin(const PasswordForm& form) {
413 int64 date_created = form.date_created.ToInternalValue(); 421 int64 date_created = form.date_created.ToInternalValue();
414 // If we are asked to save a password with 0 date, use the current time. 422 // If we are asked to save a password with 0 date, use the current time.
415 // We don't want to actually save passwords as though on January 1, 1601. 423 // We don't want to actually save passwords as though on January 1, 1601.
416 if (!date_created) 424 if (!date_created)
417 date_created = base::Time::Now().ToInternalValue(); 425 date_created = base::Time::Now().ToInternalValue();
418 int64 date_synced = form.date_synced.ToInternalValue(); 426 int64 date_synced = form.date_synced.ToInternalValue();
419 GError* error = nullptr; 427 GError* error = nullptr;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 469
462 bool NativeBackendLibsecret::GetBlacklistLogins( 470 bool NativeBackendLibsecret::GetBlacklistLogins(
463 ScopedVector<autofill::PasswordForm>* forms) { 471 ScopedVector<autofill::PasswordForm>* forms) {
464 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms); 472 return GetLoginsList(nullptr, BLACKLISTED_LOGINS, forms);
465 } 473 }
466 474
467 bool NativeBackendLibsecret::GetLoginsList( 475 bool NativeBackendLibsecret::GetLoginsList(
468 const PasswordForm* lookup_form, 476 const PasswordForm* lookup_form,
469 GetLoginsListOptions options, 477 GetLoginsListOptions options,
470 ScopedVector<autofill::PasswordForm>* forms) { 478 ScopedVector<autofill::PasswordForm>* forms) {
479 forms->clear();
471 LibsecretAttributesBuilder attrs; 480 LibsecretAttributesBuilder attrs;
472 attrs.Append("application", app_string_); 481 attrs.Append("application", app_string_);
473 if (options != ALL_LOGINS) 482 if (options != ALL_LOGINS)
474 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS); 483 attrs.Append("blacklisted_by_user", options == BLACKLISTED_LOGINS);
475 if (lookup_form && 484 if (lookup_form &&
476 !password_manager::ShouldPSLDomainMatchingApply( 485 !password_manager::ShouldPSLDomainMatchingApply(
477 password_manager::GetRegistryControlledDomain( 486 password_manager::GetRegistryControlledDomain(
478 GURL(lookup_form->signon_realm)))) 487 GURL(lookup_form->signon_realm))))
479 attrs.Append("signon_realm", lookup_form->signon_realm); 488 attrs.Append("signon_realm", lookup_form->signon_realm);
480 489
481 GError* error = nullptr; 490 GError* error = nullptr;
482 GList* found = secret_service_search_sync(nullptr, // default secret service 491 GList* found = secret_service_search_sync(nullptr, // default secret service
483 &kLibsecretSchema, attrs.Get(), 492 &kLibsecretSchema, attrs.Get(),
484 SECRET_SEARCH_ALL, 493 SECRET_SEARCH_ALL,
485 nullptr, // no cancellable ojbect 494 nullptr, // no cancellable ojbect
486 &error); 495 &error);
487 if (error) { 496 if (error) {
488 VLOG(1) << "Unable to get logins " << error->message; 497 VLOG(1) << "Unable to get logins " << error->message;
489 g_error_free(error); 498 g_error_free(error);
490 if (found) 499 if (found)
491 g_list_free(found); 500 g_list_free(found);
492 return false; 501 return false;
493 } 502 }
494 503
495 return ConvertFormList(found, lookup_form, forms); 504 *forms = ConvertFormList(found, lookup_form);
496 } 505 return true;
497
498 bool NativeBackendLibsecret::GetAllLogins(
499 ScopedVector<autofill::PasswordForm>* forms) {
500 return GetLoginsList(nullptr, ALL_LOGINS, forms);
501 } 506 }
502 507
503 bool NativeBackendLibsecret::GetLoginsBetween( 508 bool NativeBackendLibsecret::GetLoginsBetween(
504 base::Time get_begin, 509 base::Time get_begin,
505 base::Time get_end, 510 base::Time get_end,
506 TimestampToCompare date_to_compare, 511 TimestampToCompare date_to_compare,
507 ScopedVector<autofill::PasswordForm>* forms) { 512 ScopedVector<autofill::PasswordForm>* forms) {
513 forms->clear();
508 ScopedVector<autofill::PasswordForm> all_forms; 514 ScopedVector<autofill::PasswordForm> all_forms;
509 if (!GetAllLogins(&all_forms)) 515 if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms))
510 return false; 516 return false;
511 517
512 base::Time autofill::PasswordForm::*date_member = 518 base::Time autofill::PasswordForm::*date_member =
513 date_to_compare == CREATION_TIMESTAMP 519 date_to_compare == CREATION_TIMESTAMP
514 ? &autofill::PasswordForm::date_created 520 ? &autofill::PasswordForm::date_created
515 : &autofill::PasswordForm::date_synced; 521 : &autofill::PasswordForm::date_synced;
516 for (auto& saved_form : all_forms) { 522 for (auto& saved_form : all_forms) {
517 if (get_begin <= saved_form->*date_member && 523 if (get_begin <= saved_form->*date_member &&
518 (get_end.is_null() || saved_form->*date_member < get_end)) { 524 (get_end.is_null() || saved_form->*date_member < get_end)) {
519 forms->push_back(saved_form); 525 forms->push_back(saved_form);
(...skipping 20 matching lines...) Expand all
540 if (RemoveLogin(*forms[i])) { 546 if (RemoveLogin(*forms[i])) {
541 changes->push_back(password_manager::PasswordStoreChange( 547 changes->push_back(password_manager::PasswordStoreChange(
542 password_manager::PasswordStoreChange::REMOVE, *forms[i])); 548 password_manager::PasswordStoreChange::REMOVE, *forms[i]));
543 } else { 549 } else {
544 ok = false; 550 ok = false;
545 } 551 }
546 } 552 }
547 return ok; 553 return ok;
548 } 554 }
549 555
550 bool NativeBackendLibsecret::ConvertFormList( 556 ScopedVector<autofill::PasswordForm> NativeBackendLibsecret::ConvertFormList(
551 GList* found, 557 GList* found,
552 const PasswordForm* lookup_form, 558 const PasswordForm* lookup_form) {
553 ScopedVector<autofill::PasswordForm>* forms) { 559 ScopedVector<autofill::PasswordForm> forms;
554 password_manager::PSLDomainMatchMetric psl_domain_match_metric = 560 password_manager::PSLDomainMatchMetric psl_domain_match_metric =
555 password_manager::PSL_DOMAIN_MATCH_NONE; 561 password_manager::PSL_DOMAIN_MATCH_NONE;
556 GError* error = nullptr; 562 GError* error = nullptr;
557 for (GList* element = g_list_first(found); element != nullptr; 563 for (GList* element = g_list_first(found); element != nullptr;
558 element = g_list_next(element)) { 564 element = g_list_next(element)) {
559 SecretItem* secretItem = static_cast<SecretItem*>(element->data); 565 SecretItem* secretItem = static_cast<SecretItem*>(element->data);
560 LibsecretLoader::secret_item_load_secret_sync(secretItem, nullptr, &error); 566 LibsecretLoader::secret_item_load_secret_sync(secretItem, nullptr, &error);
561 if (error) { 567 if (error) {
562 VLOG(1) << "Unable to load secret item" << error->message; 568 VLOG(1) << "Unable to load secret item" << error->message;
563 g_error_free(error); 569 g_error_free(error);
(...skipping 17 matching lines...) Expand all
581 form->signon_realm = lookup_form->signon_realm; 587 form->signon_realm = lookup_form->signon_realm;
582 form->origin = lookup_form->origin; 588 form->origin = lookup_form->origin;
583 } 589 }
584 SecretValue* secretValue = secret_item_get_secret(secretItem); 590 SecretValue* secretValue = secret_item_get_secret(secretItem);
585 if (secretValue) { 591 if (secretValue) {
586 form->password_value = UTF8ToUTF16(secret_value_get_text(secretValue)); 592 form->password_value = UTF8ToUTF16(secret_value_get_text(secretValue));
587 secret_value_unref(secretValue); 593 secret_value_unref(secretValue);
588 } else { 594 } else {
589 VLOG(1) << "Unable to access password from list element!"; 595 VLOG(1) << "Unable to access password from list element!";
590 } 596 }
591 forms->push_back(form.release()); 597 forms.push_back(form.release());
592 } else { 598 } else {
593 VLOG(1) << "Could not initialize PasswordForm from attributes!"; 599 VLOG(1) << "Could not initialize PasswordForm from attributes!";
594 } 600 }
595 } 601 }
596 602
597 if (lookup_form) { 603 if (lookup_form) {
598 const GURL signon_realm(lookup_form->signon_realm); 604 const GURL signon_realm(lookup_form->signon_realm);
599 std::string registered_domain = 605 std::string registered_domain =
600 password_manager::GetRegistryControlledDomain(signon_realm); 606 password_manager::GetRegistryControlledDomain(signon_realm);
601 UMA_HISTOGRAM_ENUMERATION( 607 UMA_HISTOGRAM_ENUMERATION(
602 "PasswordManager.PslDomainMatchTriggering", 608 "PasswordManager.PslDomainMatchTriggering",
603 password_manager::ShouldPSLDomainMatchingApply(registered_domain) 609 password_manager::ShouldPSLDomainMatchingApply(registered_domain)
604 ? psl_domain_match_metric 610 ? psl_domain_match_metric
605 : password_manager::PSL_DOMAIN_MATCH_NOT_USED, 611 : password_manager::PSL_DOMAIN_MATCH_NOT_USED,
606 password_manager::PSL_DOMAIN_MATCH_COUNT); 612 password_manager::PSL_DOMAIN_MATCH_COUNT);
607 } 613 }
608 g_list_free(found); 614 g_list_free(found);
609 return true; 615 return forms.Pass();
610 } 616 }
611
612 std::string NativeBackendLibsecret::GetProfileSpecificAppString(
613 LocalProfileId id) {
614 // Originally, the application string was always just "chrome" and used only
615 // so that we had *something* to search for since GNOME Keyring won't search
616 // for nothing. Now we use it to distinguish passwords for different profiles.
617 return base::StringPrintf("%s-%d", kLibsecretAppString, id);
618 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698