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

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

Issue 1375883002: Support Android username-only credentials. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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) 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/password_store_mac.h" 5 #include "chrome/browser/password_manager/password_store_mac.h"
6 #include "chrome/browser/password_manager/password_store_mac_internal.h" 6 #include "chrome/browser/password_manager/password_store_mac_internal.h"
7 7
8 #include <CoreServices/CoreServices.h> 8 #include <CoreServices/CoreServices.h>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 mover(scoped_ptr<autofill::PasswordForm>(form_ptr)); 231 mover(scoped_ptr<autofill::PasswordForm>(form_ptr));
232 } 232 }
233 // We moved the ownership of every form out of |forms|. For performance 233 // We moved the ownership of every form out of |forms|. For performance
234 // reasons, we can just weak_clear it, instead of nullptr-ing the respective 234 // reasons, we can just weak_clear it, instead of nullptr-ing the respective
235 // elements and letting the vector's destructor to go through the list once 235 // elements and letting the vector's destructor to go through the list once
236 // more. This was tested on a benchmark, and seemed to make a difference on 236 // more. This was tested on a benchmark, and seemed to make a difference on
237 // Mac. 237 // Mac.
238 forms->weak_clear(); 238 forms->weak_clear();
239 } 239 }
240 240
241 // True if the form has no password to be stored in Keychain.
242 bool IsDBOnlyForm(const autofill::PasswordForm& form) {
engedy 2015/10/08 17:31:00 nit: IsLoginDatabaseOnlyForm
vasilii 2015/10/12 15:12:48 Done.
243 return form.blacklisted_by_user || !form.federation_url.is_empty() ||
244 form.scheme == autofill::PasswordForm::SCHEME_USERNAME_ONLY;
245 }
246
241 } // namespace 247 } // namespace
242 248
243 #pragma mark - 249 #pragma mark -
244 250
245 // TODO(stuartmorgan): Convert most of this to private helpers in 251 // TODO(stuartmorgan): Convert most of this to private helpers in
246 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public 252 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public
247 // methods to provide test coverage. 253 // methods to provide test coverage.
248 namespace internal_keychain_helpers { 254 namespace internal_keychain_helpers {
249 255
250 // Returns a URL built from the given components. To create a URL without a 256 // Returns a URL built from the given components. To create a URL without a
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 break; 469 break;
464 } 470 }
465 } 471 }
466 keychain.ItemFreeAttributesAndData(attr_list, nullptr); 472 keychain.ItemFreeAttributesAndData(attr_list, nullptr);
467 return creator_code && creator_code == base::mac::CreatorCodeForApplication(); 473 return creator_code && creator_code == base::mac::CreatorCodeForApplication();
468 } 474 }
469 475
470 bool FormsMatchForMerge(const PasswordForm& form_a, 476 bool FormsMatchForMerge(const PasswordForm& form_a,
471 const PasswordForm& form_b, 477 const PasswordForm& form_b,
472 FormMatchStrictness strictness) { 478 FormMatchStrictness strictness) {
473 // We never merge blacklist entries between our store and the Keychain, 479 // We never merge blacklist entries between our store and the Keychain,
vabr (Chromium) 2015/10/09 07:53:09 nit: This comment is slightly out of date. And giv
vasilii 2015/10/12 15:12:48 Done.
474 // and federated logins should not be stored in the Keychain at all. 480 // and federated logins should not be stored in the Keychain at all.
475 if (form_a.blacklisted_by_user || form_b.blacklisted_by_user || 481 if (IsDBOnlyForm(form_a) || IsDBOnlyForm(form_b))
476 !form_a.federation_url.is_empty() || !form_b.federation_url.is_empty()) {
477 return false; 482 return false;
478 } 483
479 bool equal_realm = form_a.signon_realm == form_b.signon_realm; 484 bool equal_realm = form_a.signon_realm == form_b.signon_realm;
480 if (strictness == FUZZY_FORM_MATCH) { 485 if (strictness == FUZZY_FORM_MATCH) {
481 equal_realm |= (!form_a.original_signon_realm.empty()) && 486 equal_realm |= (!form_a.original_signon_realm.empty()) &&
482 form_a.original_signon_realm == form_b.signon_realm; 487 form_a.original_signon_realm == form_b.signon_realm;
483 } 488 }
484 return form_a.scheme == form_b.scheme && equal_realm && 489 return form_a.scheme == form_b.scheme && equal_realm &&
485 form_a.username_value == form_b.username_value; 490 form_a.username_value == form_b.username_value;
486 } 491 }
487 492
488 // Moves entries from |forms| that represent either blacklisted or federated 493 // Moves entries from |forms| that represent either blacklisted or federated
489 // logins into |extracted|. These two types are stored only in the LoginDatabase 494 // logins into |extracted|. These two types are stored only in the LoginDatabase
490 // and do not have corresponding Keychain entries. 495 // and do not have corresponding Keychain entries.
491 void ExtractNonKeychainForms(ScopedVector<autofill::PasswordForm>* forms, 496 void ExtractNonKeychainForms(ScopedVector<autofill::PasswordForm>* forms,
492 ScopedVector<autofill::PasswordForm>* extracted) { 497 ScopedVector<autofill::PasswordForm>* extracted) {
493 extracted->reserve(extracted->size() + forms->size()); 498 extracted->reserve(extracted->size() + forms->size());
494 ScopedVector<autofill::PasswordForm> remaining; 499 ScopedVector<autofill::PasswordForm> remaining;
495 MoveAllFormsOut( 500 MoveAllFormsOut(
496 forms, [&remaining, extracted](scoped_ptr<autofill::PasswordForm> form) { 501 forms, [&remaining, extracted](scoped_ptr<autofill::PasswordForm> form) {
497 if (form->blacklisted_by_user || !form->federation_url.is_empty()) 502 if (IsDBOnlyForm(*form))
498 extracted->push_back(form.Pass()); 503 extracted->push_back(form.Pass());
499 else 504 else
500 remaining.push_back(form.Pass()); 505 remaining.push_back(form.Pass());
501 }); 506 });
502 forms->swap(remaining); 507 forms->swap(remaining);
503 } 508 }
504 509
505 // Takes |keychain_forms| and |database_forms| and moves the following 2 types 510 // Takes |keychain_forms| and |database_forms| and moves the following 2 types
506 // of forms to |merged_forms|: 511 // of forms to |merged_forms|:
507 // (1) |database_forms| that by principle never have a corresponding Keychain 512 // (1) |database_forms| that by principle never have a corresponding Keychain
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); 720 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form);
716 if (keychain_item) { 721 if (keychain_item) {
717 keychain_->Free(keychain_item); 722 keychain_->Free(keychain_item);
718 return true; 723 return true;
719 } 724 }
720 return false; 725 return false;
721 } 726 }
722 727
723 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( 728 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm(
724 const PasswordForm& query_form) { 729 const PasswordForm& query_form) {
725 if (!query_form.federation_url.is_empty()) 730 if (IsDBOnlyForm(query_form))
726 return false; 731 return false;
727 std::string username = base::UTF16ToUTF8(query_form.username_value); 732 std::string username = base::UTF16ToUTF8(query_form.username_value);
728 std::vector<SecKeychainItemRef> matches = 733 std::vector<SecKeychainItemRef> matches =
729 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, 734 MatchingKeychainItems(query_form.signon_realm, query_form.scheme,
730 NULL, username.c_str()); 735 NULL, username.c_str());
731 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); 736 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin();
732 i != matches.end(); ++i) { 737 i != matches.end(); ++i) {
733 keychain_->Free(*i); 738 keychain_->Free(*i);
734 } 739 }
735 740
(...skipping 26 matching lines...) Expand all
762 } 767 }
763 768
764 ScopedVector<autofill::PasswordForm> 769 ScopedVector<autofill::PasswordForm>
765 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { 770 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() {
766 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); 771 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems();
767 return ConvertKeychainItemsToForms(&items); 772 return ConvertKeychainItemsToForms(&items);
768 } 773 }
769 774
770 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { 775 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) {
771 // We should never be trying to store a blacklist in the keychain. 776 // We should never be trying to store a blacklist in the keychain.
772 DCHECK(!form.blacklisted_by_user); 777 DCHECK(!IsDBOnlyForm(form));
773 778
774 std::string server; 779 std::string server;
775 std::string security_domain; 780 std::string security_domain;
776 UInt32 port; 781 UInt32 port;
777 bool is_secure; 782 bool is_secure;
778 if (!internal_keychain_helpers::ExtractSignonRealmComponents( 783 if (!internal_keychain_helpers::ExtractSignonRealmComponents(
779 form.signon_realm, &server, &port, &is_secure, &security_domain)) { 784 form.signon_realm, &server, &port, &is_secure, &security_domain)) {
780 return false; 785 return false;
781 } 786 }
782 std::string path; 787 std::string path;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 } 847 }
843 items->clear(); 848 items->clear();
844 return forms.Pass(); 849 return forms.Pass();
845 } 850 }
846 851
847 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( 852 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm(
848 const PasswordForm& form) { 853 const PasswordForm& form) {
849 // We don't store blacklist entries in the keychain, so the answer to "what 854 // We don't store blacklist entries in the keychain, so the answer to "what
850 // Keychain item goes with this form" is always "nothing" for blacklists. 855 // Keychain item goes with this form" is always "nothing" for blacklists.
851 // Same goes for federated logins. 856 // Same goes for federated logins.
852 if (form.blacklisted_by_user || !form.federation_url.is_empty()) { 857 if (IsDBOnlyForm(form))
853 return NULL; 858 return NULL;
854 }
855 859
856 std::string path; 860 std::string path;
857 // Path doesn't make sense for Android app credentials. 861 // Path doesn't make sense for Android app credentials.
858 if (!password_manager::IsValidAndroidFacetURI(form.signon_realm)) 862 if (!password_manager::IsValidAndroidFacetURI(form.signon_realm))
859 path = form.origin.path(); 863 path = form.origin.path();
860 std::string username = base::UTF16ToUTF8(form.username_value); 864 std::string username = base::UTF16ToUTF8(form.username_value);
861 std::vector<SecKeychainItemRef> matches = MatchingKeychainItems( 865 std::vector<SecKeychainItemRef> matches = MatchingKeychainItems(
862 form.signon_realm, form.scheme, path.c_str(), username.c_str()); 866 form.signon_realm, form.scheme, path.c_str(), username.c_str());
863 867
864 if (matches.empty()) { 868 if (matches.empty()) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 } 914 }
911 915
912 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|. 916 // Returns the Keychain SecAuthenticationType type corresponding to |scheme|.
913 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme( 917 SecAuthenticationType MacKeychainPasswordFormAdapter::AuthTypeForScheme(
914 PasswordForm::Scheme scheme) { 918 PasswordForm::Scheme scheme) {
915 switch (scheme) { 919 switch (scheme) {
916 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm; 920 case PasswordForm::SCHEME_HTML: return kSecAuthenticationTypeHTMLForm;
917 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic; 921 case PasswordForm::SCHEME_BASIC: return kSecAuthenticationTypeHTTPBasic;
918 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest; 922 case PasswordForm::SCHEME_DIGEST: return kSecAuthenticationTypeHTTPDigest;
919 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault; 923 case PasswordForm::SCHEME_OTHER: return kSecAuthenticationTypeDefault;
924 case PasswordForm::SCHEME_USERNAME_ONLY:
925 NOTREACHED();
926 break;
920 } 927 }
921 NOTREACHED(); 928 NOTREACHED();
922 return kSecAuthenticationTypeDefault; 929 return kSecAuthenticationTypeDefault;
923 } 930 }
924 931
925 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword( 932 bool MacKeychainPasswordFormAdapter::SetKeychainItemPassword(
926 const SecKeychainItemRef& keychain_item, const std::string& password) { 933 const SecKeychainItemRef& keychain_item, const std::string& password) {
927 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL, 934 OSStatus result = keychain_->ItemModifyAttributesAndData(keychain_item, NULL,
928 password.size(), 935 password.size(),
929 password.c_str()); 936 password.c_str());
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 1263
1257 scoped_ptr<password_manager::InteractionsStats> 1264 scoped_ptr<password_manager::InteractionsStats>
1258 PasswordStoreMac::GetSiteStatsImpl(const GURL& origin_domain) { 1265 PasswordStoreMac::GetSiteStatsImpl(const GURL& origin_domain) {
1259 DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); 1266 DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
1260 return login_metadata_db_ 1267 return login_metadata_db_
1261 ? login_metadata_db_->stats_table().GetRow(origin_domain) 1268 ? login_metadata_db_->stats_table().GetRow(origin_domain)
1262 : scoped_ptr<password_manager::InteractionsStats>(); 1269 : scoped_ptr<password_manager::InteractionsStats>();
1263 } 1270 }
1264 1271
1265 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { 1272 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) {
1266 if (form.blacklisted_by_user || !form.federation_url.is_empty()) 1273 if (IsDBOnlyForm(form))
1267 return true; 1274 return true;
1268 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); 1275 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get());
1269 return keychainAdapter.AddPassword(form); 1276 return keychainAdapter.AddPassword(form);
1270 } 1277 }
1271 1278
1272 bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm( 1279 bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm(
1273 const autofill::PasswordForm& form) { 1280 const autofill::PasswordForm& form) {
1274 DCHECK(login_metadata_db_); 1281 DCHECK(login_metadata_db_);
1275 bool has_match = false; 1282 bool has_match = false;
1276 ScopedVector<autofill::PasswordForm> database_forms; 1283 ScopedVector<autofill::PasswordForm> database_forms;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 ScopedVector<PasswordForm> forms_with_keychain_entry; 1332 ScopedVector<PasswordForm> forms_with_keychain_entry;
1326 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, 1333 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms,
1327 &forms_with_keychain_entry); 1334 &forms_with_keychain_entry);
1328 1335
1329 // Clean up any orphaned database entries. 1336 // Clean up any orphaned database entries.
1330 RemoveDatabaseForms(&database_forms); 1337 RemoveDatabaseForms(&database_forms);
1331 1338
1332 // Move the orphaned DB forms to the output parameter. 1339 // Move the orphaned DB forms to the output parameter.
1333 AppendSecondToFirst(orphaned_forms, &database_forms); 1340 AppendSecondToFirst(orphaned_forms, &database_forms);
1334 } 1341 }
OLDNEW
« no previous file with comments | « no previous file | components/autofill/core/common/password_form.h » ('j') | components/autofill/core/common/password_form.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698