Index: chrome/browser/password_manager/password_store_mac.cc |
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc |
index bb50c7425f1a6208bdb54b9f42369294e273602c..e056c462c1f3f206504d2dea253422548bd1db56 100644 |
--- a/chrome/browser/password_manager/password_store_mac.cc |
+++ b/chrome/browser/password_manager/password_store_mac.cc |
@@ -15,7 +15,6 @@ |
#include "base/logging.h" |
#include "base/mac/foundation_util.h" |
#include "base/mac/mac_logging.h" |
-#include "base/memory/scoped_vector.h" |
#include "base/message_loop/message_loop.h" |
#include "base/stl_util.h" |
#include "base/strings/string_util.h" |
@@ -189,6 +188,13 @@ PasswordStoreChangeList FormsToRemoveChangeList( |
return changes; |
} |
+// Moves the content of |second| to the end of |first|. |
+void AppendSecondToFirst(ScopedVector<autofill::PasswordForm>* first, |
+ ScopedVector<autofill::PasswordForm>* second) { |
+ first->insert(first->end(), second->begin(), second->end()); |
+ second->weak_clear(); |
+} |
+ |
} // namespace |
#pragma mark - |
@@ -418,70 +424,62 @@ PasswordForm* BestKeychainFormForForm( |
return partial_match; |
} |
-// Returns entries from |forms| that are blacklist entries, after removing |
-// them from |forms|. |
-std::vector<PasswordForm*> ExtractBlacklistForms( |
- std::vector<PasswordForm*>* forms) { |
- std::vector<PasswordForm*> blacklist_forms; |
- for (std::vector<PasswordForm*>::iterator i = forms->begin(); |
- i != forms->end();) { |
- PasswordForm* form = *i; |
- if (form->blacklisted_by_user) { |
- blacklist_forms.push_back(form); |
- i = forms->erase(i); |
- } else { |
- ++i; |
- } |
- } |
- return blacklist_forms; |
-} |
- |
-// Deletes and removes from v any element that exists in s. |
-template <class T> |
-void DeleteVectorElementsInSet(std::vector<T*>* v, const std::set<T*>& s) { |
- for (typename std::vector<T*>::iterator i = v->begin(); i != v->end();) { |
- T* element = *i; |
- if (s.find(element) != s.end()) { |
- delete element; |
- i = v->erase(i); |
- } else { |
- ++i; |
- } |
+// Moves entries from |forms| that are blacklist entries into |blacklist|. |
+void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms, |
+ ScopedVector<autofill::PasswordForm>* blacklist) { |
+ blacklist->reserve(blacklist->size() + forms->size()); |
+ ScopedVector<autofill::PasswordForm> non_blacklist; |
+ for (auto& form : *forms) { |
+ if (form->blacklisted_by_user) |
+ blacklist->push_back(form); |
+ else |
+ non_blacklist.push_back(form); |
+ form = nullptr; |
} |
+ forms->swap(non_blacklist); |
} |
-void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms, |
- std::vector<PasswordForm*>* database_forms, |
- std::vector<PasswordForm*>* merged_forms) { |
+// Takes |keychain_forms| and |database_forms| and moves the following 2 types |
+// of forms to |merged_forms|: (1) blacklisted |database_forms|, (2) |
+// |database_forms| which have a corresponding entry in |keychain_forms|. The |
+// database forms of type (2) have their password value updated from the |
+// corresponding keychain form, and all the keychain forms corresponding to some |
+// database form are removed from |keychain_forms| and deleted. |
+void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms, |
+ ScopedVector<autofill::PasswordForm>* database_forms, |
+ ScopedVector<autofill::PasswordForm>* merged_forms) { |
// Pull out the database blacklist items, since they are used as-is rather |
// than being merged with keychain forms. |
- std::vector<PasswordForm*> database_blacklist_forms = |
- ExtractBlacklistForms(database_forms); |
+ ExtractBlacklistForms(database_forms, merged_forms); |
// Merge the normal entries. |
- std::set<PasswordForm*> used_keychain_forms; |
- for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); |
- i != database_forms->end();) { |
- PasswordForm* db_form = *i; |
- PasswordForm* best_match = BestKeychainFormForForm(*db_form, |
- keychain_forms); |
+ ScopedVector<autofill::PasswordForm> unused_database_forms; |
+ unused_database_forms.reserve(database_forms->size()); |
+ std::set<autofill::PasswordForm*> used_keychain_forms; |
+ for (auto& db_form : *database_forms) { |
+ PasswordForm* best_match = |
+ BestKeychainFormForForm(*db_form, &keychain_forms->get()); |
if (best_match) { |
used_keychain_forms.insert(best_match); |
db_form->password_value = best_match->password_value; |
merged_forms->push_back(db_form); |
- i = database_forms->erase(i); |
} else { |
- ++i; |
+ unused_database_forms.push_back(db_form); |
} |
+ db_form = nullptr; |
} |
- |
- // Add in the blacklist entries from the database. |
- merged_forms->insert(merged_forms->end(), |
- database_blacklist_forms.begin(), |
- database_blacklist_forms.end()); |
+ database_forms->swap(unused_database_forms); |
// Clear out all the Keychain entries we used. |
- DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); |
+ ScopedVector<autofill::PasswordForm> unused_keychain_forms; |
+ unused_keychain_forms.reserve(keychain_forms->size()); |
+ for (auto& keychain_form : *keychain_forms) { |
+ if (!ContainsKey(used_keychain_forms, keychain_form)) { |
+ unused_keychain_forms.push_back(keychain_form); |
+ keychain_form = nullptr; |
+ } |
+ } |
+ keychain_forms->swap(unused_keychain_forms); |
} |
std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( |
@@ -504,9 +502,9 @@ std::vector<ItemFormPair> ExtractAllKeychainItemAttributesIntoPasswordForms( |
return item_form_pairs; |
} |
-std::vector<PasswordForm*> GetPasswordsForForms( |
- const AppleKeychain& keychain, |
- std::vector<PasswordForm*>* database_forms) { |
+void GetPasswordsForForms(const AppleKeychain& keychain, |
+ ScopedVector<autofill::PasswordForm>* database_forms, |
+ ScopedVector<autofill::PasswordForm>* passwords) { |
// First load the attributes of all items in the keychain without loading |
// their password data, and then match items in |database_forms| against them. |
// This avoids individually searching through the keychain for passwords |
@@ -522,29 +520,27 @@ std::vector<PasswordForm*> GetPasswordsForForms( |
// Next, compare the attributes of the PasswordForms in |database_forms| |
// against those in |item_form_pairs|, and extract password data for each |
// matching PasswordForm using its corresponding SecKeychainItemRef. |
- std::vector<PasswordForm*> merged_forms; |
- for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); |
- i != database_forms->end();) { |
- std::vector<PasswordForm*> db_form_container(1, *i); |
- std::vector<PasswordForm*> keychain_matches = |
- ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, **i); |
- MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); |
- if (db_form_container.empty()) { |
- i = database_forms->erase(i); |
- } else { |
- ++i; |
- } |
- STLDeleteElements(&keychain_matches); |
+ ScopedVector<autofill::PasswordForm> unused_db_forms; |
+ unused_db_forms.reserve(database_forms->size()); |
+ for (auto& db_form : *database_forms) { |
+ ScopedVector<autofill::PasswordForm> keychain_matches( |
vasilii
2015/01/28 15:09:03
nit: ScopedVector<autofill::PasswordForm> keychain
vabr (Chromium)
2015/01/28 16:36:27
Done.
You are right: Both the r-value constructor
vasilii
2015/01/28 17:27:22
There is no operator= here. "MyObject o = somethin
|
+ ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *db_form)); |
+ |
+ ScopedVector<autofill::PasswordForm> db_form_container; |
+ db_form_container.push_back(db_form); |
+ db_form = nullptr; |
+ MergePasswordForms(&keychain_matches, &db_form_container, passwords); |
+ unused_db_forms.insert(unused_db_forms.end(), db_form_container.begin(), |
+ db_form_container.end()); |
+ db_form_container.weak_clear(); |
} |
+ database_forms->swap(unused_db_forms); |
- // Clean up temporary PasswordForms and SecKeychainItemRefs. |
STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), |
item_form_pairs.end()); |
- for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin(); |
- i != keychain_items.end(); ++i) { |
- keychain.Free(*i); |
+ for (SecKeychainItemRef item : keychain_items) { |
+ keychain.Free(item); |
} |
- return merged_forms; |
} |
// TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
@@ -590,11 +586,11 @@ bool FormIsValidAndMatchesOtherForm(const PasswordForm& query_form, |
query_form, other_form, STRICT_FORM_MATCH); |
} |
-std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm( |
+ScopedVector<autofill::PasswordForm> ExtractPasswordsMergeableWithForm( |
const AppleKeychain& keychain, |
const std::vector<ItemFormPair>& item_form_pairs, |
const PasswordForm& query_form) { |
- std::vector<PasswordForm*> matches; |
+ ScopedVector<autofill::PasswordForm> matches; |
for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); |
i != item_form_pairs.end(); ++i) { |
if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { |
@@ -602,16 +598,14 @@ std::vector<PasswordForm*> ExtractPasswordsMergeableWithForm( |
// returned forms. |
scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); |
internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
- keychain, |
- *(i->first), |
- form_with_password.get(), |
+ keychain, *(i->first), form_with_password.get(), |
true); // Load password attributes and data. |
// Do not include blacklisted items found in the keychain. |
if (!form_with_password->blacklisted_by_user) |
matches.push_back(form_with_password.release()); |
} |
} |
- return matches; |
+ return matches.Pass(); |
} |
} // namespace internal_keychain_helpers |
@@ -623,12 +617,12 @@ MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
: keychain_(keychain), finds_only_owned_(false) { |
} |
-std::vector<PasswordForm*> MacKeychainPasswordFormAdapter::PasswordsFillingForm( |
+ScopedVector<autofill::PasswordForm> |
+MacKeychainPasswordFormAdapter::PasswordsFillingForm( |
const std::string& signon_realm, |
PasswordForm::Scheme scheme) { |
std::vector<SecKeychainItemRef> keychain_items = |
MatchingKeychainItems(signon_realm, scheme, NULL, NULL); |
- |
return ConvertKeychainItemsToForms(&keychain_items); |
} |
@@ -681,8 +675,8 @@ std::vector<SecKeychainItemRef> |
return matches; |
} |
-std::vector<PasswordForm*> |
- MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { |
+ScopedVector<autofill::PasswordForm> |
+MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { |
std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems(); |
return ConvertKeychainItemsToForms(&items); |
} |
@@ -745,21 +739,20 @@ void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems( |
finds_only_owned_ = finds_only_owned; |
} |
-std::vector<PasswordForm*> |
- MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( |
- std::vector<SecKeychainItemRef>* items) { |
- std::vector<PasswordForm*> keychain_forms; |
- for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); |
- i != items->end(); ++i) { |
- PasswordForm* form = new PasswordForm(); |
+ScopedVector<autofill::PasswordForm> |
+MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( |
+ std::vector<SecKeychainItemRef>* items) { |
+ ScopedVector<autofill::PasswordForm> forms; |
+ for (SecKeychainItemRef item : *items) { |
+ scoped_ptr<PasswordForm> form(new PasswordForm()); |
if (internal_keychain_helpers::FillPasswordFormFromKeychainItem( |
- *keychain_, *i, form, true)) { |
- keychain_forms.push_back(form); |
+ *keychain_, item, form.get(), true)) { |
+ forms.push_back(form.release()); |
} |
- keychain_->Free(*i); |
+ keychain_->Free(item); |
} |
items->clear(); |
- return keychain_forms; |
+ return forms.Pass(); |
} |
SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( |
@@ -983,15 +976,15 @@ PasswordStoreChangeList PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( |
base::Time delete_begin, |
base::Time delete_end) { |
PasswordStoreChangeList changes; |
- ScopedVector<PasswordForm> forms; |
+ ScopedVector<PasswordForm> forms_to_remove; |
if (login_metadata_db_ && |
login_metadata_db_->GetLoginsCreatedBetween(delete_begin, delete_end, |
- &forms.get()) && |
+ &forms_to_remove) && |
login_metadata_db_->RemoveLoginsCreatedBetween(delete_begin, |
delete_end)) { |
- RemoveKeychainForms(forms.get()); |
- CleanOrphanedForms(&forms.get()); |
- changes = FormsToRemoveChangeList(forms.get()); |
+ RemoveKeychainForms(forms_to_remove.get()); |
+ CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms. |
+ changes = FormsToRemoveChangeList(forms_to_remove.get()); |
LogStatsForBulkDeletion(changes.size()); |
} |
return changes; |
@@ -1001,14 +994,14 @@ PasswordStoreChangeList PasswordStoreMac::RemoveLoginsSyncedBetweenImpl( |
base::Time delete_begin, |
base::Time delete_end) { |
PasswordStoreChangeList changes; |
- ScopedVector<PasswordForm> forms; |
+ ScopedVector<PasswordForm> forms_to_remove; |
if (login_metadata_db_ && |
login_metadata_db_->GetLoginsSyncedBetween(delete_begin, delete_end, |
- &forms.get()) && |
+ &forms_to_remove) && |
login_metadata_db_->RemoveLoginsSyncedBetween(delete_begin, delete_end)) { |
- RemoveKeychainForms(forms.get()); |
- CleanOrphanedForms(&forms.get()); |
- changes = FormsToRemoveChangeList(forms.get()); |
+ RemoveKeychainForms(forms_to_remove.get()); |
+ CleanOrphanedForms(&forms_to_remove); // Add the orphaned forms_to_remove. |
+ changes = FormsToRemoveChangeList(forms_to_remove.get()); |
LogStatsForBulkDeletionDuringRollback(changes.size()); |
} |
return changes; |
@@ -1022,97 +1015,92 @@ void PasswordStoreMac::GetLoginsImpl( |
prompt_policy == ALLOW_PROMPT); |
if (!login_metadata_db_) { |
- callback_runner.Run(std::vector<PasswordForm*>()); |
+ callback_runner.Run(ScopedVector<autofill::PasswordForm>()); |
return; |
} |
ScopedVector<PasswordForm> database_forms; |
- login_metadata_db_->GetLogins(form, &database_forms.get()); |
+ login_metadata_db_->GetLogins(form, &database_forms); |
// Let's gather all signon realms we want to match with keychain entries. |
std::set<std::string> realm_set; |
realm_set.insert(form.signon_realm); |
- for (std::vector<PasswordForm*>::const_iterator db_form = |
- database_forms.begin(); |
- db_form != database_forms.end(); |
- ++db_form) { |
+ for (const autofill::PasswordForm* db_form : database_forms) { |
// TODO(vabr): We should not be getting different schemes here. |
// http://crbug.com/340112 |
- if (form.scheme != (*db_form)->scheme) |
+ if (form.scheme != db_form->scheme) |
continue; // Forms with different schemes never match. |
- const std::string& original_singon_realm((*db_form)->original_signon_realm); |
+ const std::string& original_singon_realm(db_form->original_signon_realm); |
if (!original_singon_realm.empty()) |
realm_set.insert(original_singon_realm); |
} |
- std::vector<PasswordForm*> keychain_forms; |
+ ScopedVector<autofill::PasswordForm> keychain_forms; |
for (std::set<std::string>::const_iterator realm = realm_set.begin(); |
- realm != realm_set.end(); |
- ++realm) { |
+ realm != realm_set.end(); ++realm) { |
MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get()); |
- std::vector<PasswordForm*> temp_keychain_forms = |
- keychain_adapter.PasswordsFillingForm(*realm, form.scheme); |
- keychain_forms.insert(keychain_forms.end(), |
- temp_keychain_forms.begin(), |
- temp_keychain_forms.end()); |
+ ScopedVector<autofill::PasswordForm> temp_keychain_forms( |
+ keychain_adapter.PasswordsFillingForm(*realm, form.scheme)); |
+ AppendSecondToFirst(&keychain_forms, &temp_keychain_forms); |
} |
- std::vector<PasswordForm*> matched_forms; |
- internal_keychain_helpers::MergePasswordForms(&keychain_forms, |
- &database_forms.get(), |
- &matched_forms); |
+ ScopedVector<autofill::PasswordForm> matched_forms; |
+ internal_keychain_helpers::MergePasswordForms( |
+ &keychain_forms, &database_forms, &matched_forms); |
// Strip any blacklist entries out of the unused Keychain array, then take |
// all the entries that are left (which we can use as imported passwords). |
ScopedVector<PasswordForm> keychain_blacklist_forms; |
- internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms).swap( |
- keychain_blacklist_forms.get()); |
+ internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms, |
+ &keychain_blacklist_forms); |
matched_forms.insert(matched_forms.end(), |
keychain_forms.begin(), |
keychain_forms.end()); |
- keychain_forms.clear(); |
+ keychain_forms.weak_clear(); |
if (!database_forms.empty()) { |
RemoveDatabaseForms(database_forms.get()); |
NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); |
} |
- callback_runner.Run(matched_forms); |
+ callback_runner.Run(matched_forms.Pass()); |
} |
void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { |
- FillBlacklistLogins(request->result()); |
+ ScopedVector<autofill::PasswordForm> obtained_forms; |
+ FillBlacklistLogins(&obtained_forms); |
+ request->result()->swap(obtained_forms.get()); |
ForwardLoginsResult(request); |
} |
void PasswordStoreMac::GetAutofillableLoginsImpl(GetLoginsRequest* request) { |
- FillAutofillableLogins(request->result()); |
+ ScopedVector<autofill::PasswordForm> obtained_forms; |
+ FillAutofillableLogins(&obtained_forms); |
+ request->result()->swap(obtained_forms.get()); |
ForwardLoginsResult(request); |
} |
bool PasswordStoreMac::FillAutofillableLogins( |
- std::vector<PasswordForm*>* forms) { |
+ ScopedVector<autofill::PasswordForm>* forms) { |
DCHECK(thread_->message_loop() == base::MessageLoop::current()); |
ScopedVector<PasswordForm> database_forms; |
if (!login_metadata_db_ || |
- !login_metadata_db_->GetAutofillableLogins(&database_forms.get())) |
+ !login_metadata_db_->GetAutofillableLogins(&database_forms)) |
return false; |
- std::vector<PasswordForm*> merged_forms = |
- internal_keychain_helpers::GetPasswordsForForms(*keychain_, |
- &database_forms.get()); |
+ internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, |
+ forms); |
if (!database_forms.empty()) { |
RemoveDatabaseForms(database_forms.get()); |
NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); |
} |
- forms->insert(forms->end(), merged_forms.begin(), merged_forms.end()); |
return true; |
} |
bool PasswordStoreMac::FillBlacklistLogins( |
- std::vector<PasswordForm*>* forms) { |
+ ScopedVector<autofill::PasswordForm>* forms) { |
DCHECK(thread_->message_loop() == base::MessageLoop::current()); |
return login_metadata_db_ && login_metadata_db_->GetBlacklistLogins(forms); |
} |
@@ -1129,21 +1117,19 @@ bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm( |
const autofill::PasswordForm& form) { |
DCHECK(login_metadata_db_); |
bool has_match = false; |
- std::vector<PasswordForm*> database_forms; |
+ ScopedVector<autofill::PasswordForm> database_forms; |
login_metadata_db_->GetLogins(form, &database_forms); |
- for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); |
- i != database_forms.end(); ++i) { |
+ for (const autofill::PasswordForm* db_form : database_forms) { |
// Below we filter out forms with non-empty original_signon_realm, because |
// those signal fuzzy matches, and we are only interested in exact ones. |
- if ((*i)->original_signon_realm.empty() && |
+ if (db_form->original_signon_realm.empty() && |
internal_keychain_helpers::FormsMatchForMerge( |
- form, **i, internal_keychain_helpers::STRICT_FORM_MATCH) && |
- (*i)->origin == form.origin) { |
+ form, *db_form, internal_keychain_helpers::STRICT_FORM_MATCH) && |
+ db_form->origin == form.origin) { |
has_match = true; |
break; |
} |
} |
- STLDeleteElements(&database_forms); |
return has_match; |
} |
@@ -1166,19 +1152,24 @@ void PasswordStoreMac::RemoveKeychainForms( |
} |
} |
-void PasswordStoreMac::CleanOrphanedForms(std::vector<PasswordForm*>* forms) { |
- DCHECK(forms); |
+void PasswordStoreMac::CleanOrphanedForms( |
+ ScopedVector<autofill::PasswordForm>* orphaned_forms) { |
+ DCHECK(orphaned_forms); |
DCHECK(login_metadata_db_); |
- std::vector<PasswordForm*> database_forms; |
+ ScopedVector<autofill::PasswordForm> database_forms; |
login_metadata_db_->GetAutofillableLogins(&database_forms); |
- ScopedVector<PasswordForm> merged_forms; |
- merged_forms.get() = internal_keychain_helpers::GetPasswordsForForms( |
- *keychain_, &database_forms); |
+ // Filter forms with corresponding Keychain entry out of |database_forms|. |
+ ScopedVector<PasswordForm> forms_with_keychain_entry; |
+ internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, |
+ &forms_with_keychain_entry); |
// Clean up any orphaned database entries. |
- RemoveDatabaseForms(database_forms); |
+ RemoveDatabaseForms(database_forms.get()); |
- forms->insert(forms->end(), database_forms.begin(), database_forms.end()); |
+ // Move the orphaned DB forms to the output parameter. |
+ orphaned_forms->insert(orphaned_forms->end(), database_forms.begin(), |
+ database_forms.end()); |
+ database_forms.weak_clear(); |
} |