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

Unified Diff: chrome/browser/password_manager/password_store_mac.cc

Issue 885033002: PasswordStoreMac: Use ScopedVector::weak_erase to improve performance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 96518ffb46c3524bb441264a80799338b5a8df07..d53806d3bda3d02f217867d2fa938f3e95d0fc85 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -195,6 +195,103 @@ void AppendSecondToFirst(ScopedVector<autofill::PasswordForm>* first,
second->weak_clear();
}
+// Returns an the best match for |base_form| from |keychain_forms|, or NULL if
+// there is no suitable match.
+PasswordForm* BestKeychainFormForForm(
vabr (Chromium) 2015/01/29 15:41:11 This is a plain move out of the internal_keychain_
vasilii 2015/01/29 16:41:12 Acknowledged.
+ const PasswordForm& base_form,
+ const std::vector<PasswordForm*>* keychain_forms) {
vasilii 2015/01/29 16:41:13 const std::vector<PasswordForm*>&
vabr (Chromium) 2015/01/30 12:57:09 Done. (Originally I did not intend to modify this
+ PasswordForm* partial_match = NULL;
+ for (std::vector<PasswordForm*>::const_iterator i = keychain_forms->begin();
+ i != keychain_forms->end(); ++i) {
+ // TODO(stuartmorgan): We should really be scoring path matches and picking
+ // the best, rather than just checking exact-or-not (although in practice
+ // keychain items with paths probably came from us).
+ if (internal_keychain_helpers::FormsMatchForMerge(
+ base_form, *(*i), internal_keychain_helpers::FUZZY_FORM_MATCH)) {
vasilii 2015/01/29 16:41:13 **i
vabr (Chromium) 2015/01/30 12:57:09 Done.
+ if (base_form.origin == (*i)->origin) {
+ return *i;
+ } else if (!partial_match) {
+ partial_match = *i;
+ }
+ }
+ }
+ return partial_match;
+}
+
+typedef base::Callback<void(scoped_ptr<autofill::PasswordForm>)>
+ TakeFormCallback;
vasilii 2015/01/29 16:41:13 The typedef should go to the beginning of the file
vabr (Chromium) 2015/01/30 12:57:09 Agreed, but I'll remove the typedef anyway.
+
+// Stores |form| in either |non_blacklist| or |blacklist|, depending on whether
+// |form| is blacklisted by the user.
+void ExtractBlacklistFormsCallback(
vabr (Chromium) 2015/01/29 15:41:11 The three callbacks correspond to the three places
+ ScopedVector<autofill::PasswordForm>* non_blacklist,
+ ScopedVector<autofill::PasswordForm>* blacklist,
+ scoped_ptr<autofill::PasswordForm> form) {
+ if (form->blacklisted_by_user)
+ blacklist->push_back(form.release());
+ else
+ non_blacklist->push_back(form.release());
+}
+
+// If |db_form|, coming from the login DB, has a match in |keychain_forms|, the
+// password of the match is copied into |db_form|, which is moved to
+// |merged_forms|. The used keychain form is also marked in
+// |used_keychain_forms|. Otherwise, |db_form| is moved to
+// |unused_database_forms|.
+void MergePasswordFormsCallback(
+ const std::vector<autofill::PasswordForm*>* keychain_forms,
vasilii 2015/01/29 16:41:13 const std::vector<autofill::PasswordForm*>&
vabr (Chromium) 2015/01/30 12:57:09 Done.
+ std::set<autofill::PasswordForm*>* used_keychain_forms,
+ ScopedVector<autofill::PasswordForm>* unused_database_forms,
+ ScopedVector<autofill::PasswordForm>* merged_forms,
+ scoped_ptr<autofill::PasswordForm> db_form) {
+ PasswordForm* best_match = BestKeychainFormForForm(*db_form, keychain_forms);
+ if (best_match) {
+ used_keychain_forms->insert(best_match);
+ db_form->password_value = best_match->password_value;
+ merged_forms->push_back(db_form.release());
+ } else {
+ unused_database_forms->push_back(db_form.release());
+ }
+}
+
+// If there is a password stored in |keychain| for |db_form|, adds it to
+// |db_form| and moves |db_form| to |passwords|. Otherwise moves |db_form| to
+// |unused_db_forms|.
+void GetPasswordsForFormsCallback(
+ const AppleKeychain* keychain,
+ const std::vector<internal_keychain_helpers::ItemFormPair>& item_form_pairs,
+ ScopedVector<autofill::PasswordForm>* passwords,
+ ScopedVector<autofill::PasswordForm>* unused_db_forms,
+ scoped_ptr<autofill::PasswordForm> db_form) {
+ ScopedVector<autofill::PasswordForm> keychain_matches =
+ internal_keychain_helpers::ExtractPasswordsMergeableWithForm(
+ *keychain, item_form_pairs, *db_form);
+
+ ScopedVector<autofill::PasswordForm> db_form_container;
+ db_form_container.push_back(db_form.release());
+ internal_keychain_helpers::MergePasswordForms(&keychain_matches,
+ &db_form_container, passwords);
+ unused_db_forms->insert(unused_db_forms->end(), db_form_container.begin(),
vasilii 2015/01/29 16:41:13 Do you want to reuse AppendSecondToFirst?
vabr (Chromium) 2015/01/30 12:57:09 Indeed! Thanks, it felt like I forgot something.
+ db_form_container.end());
+ db_form_container.weak_clear();
+}
+
+// Iterates over all elements in |forms|, passes the pointed to objects to
+// |move_form|, and clears |forms| efficiently.
+void MoveAllFormsOut(ScopedVector<autofill::PasswordForm>* forms,
vabr (Chromium) 2015/01/29 15:41:11 This is the only function which gets to use weak_e
+ TakeFormCallback move_form) {
+ for (auto* form_ptr : *forms) {
vasilii 2015/01/29 16:41:13 autofill::PasswordForm*
vabr (Chromium) 2015/01/30 12:57:09 Done.
+ scoped_ptr<autofill::PasswordForm> form(form_ptr);
+ move_form.Run(form.Pass());
+ }
+ // We moved the ownership of every form out of |forms|. For performance
+ // reasons, we can just weak_clear it, instead of nullptr-ing the respective
+ // elements and letting the vector's destructor to go through the list once
+ // more. This was tested on a banchmark, and seemed to make a difference on
+ // Mac.
+ forms->weak_clear();
+}
+
} // namespace
#pragma mark -
@@ -402,40 +499,15 @@ bool FormsMatchForMerge(const PasswordForm& form_a,
form_a.username_value == form_b.username_value;
}
-// Returns an the best match for |base_form| from |keychain_forms|, or NULL if
-// there is no suitable match.
-PasswordForm* BestKeychainFormForForm(
- const PasswordForm& base_form,
- const std::vector<PasswordForm*>* keychain_forms) {
- PasswordForm* partial_match = NULL;
- for (std::vector<PasswordForm*>::const_iterator i = keychain_forms->begin();
- i != keychain_forms->end(); ++i) {
- // TODO(stuartmorgan): We should really be scoring path matches and picking
- // the best, rather than just checking exact-or-not (although in practice
- // keychain items with paths probably came from us).
- if (FormsMatchForMerge(base_form, *(*i), FUZZY_FORM_MATCH)) {
- if (base_form.origin == (*i)->origin) {
- return *i;
- } else if (!partial_match) {
- partial_match = *i;
- }
- }
- }
- return partial_match;
-}
-
// 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;
- }
+ // Move forms in either |non_blacklist| or |blacklist|, depending on whether
+ // they are blacklisted by the user.
+ MoveAllFormsOut(forms, base::Bind(&ExtractBlacklistFormsCallback,
+ &non_blacklist, blacklist));
forms->swap(non_blacklist);
}
@@ -456,18 +528,14 @@ void MergePasswordForms(ScopedVector<autofill::PasswordForm>* 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);
- } else {
- unused_database_forms.push_back(db_form);
- }
- db_form = nullptr;
- }
+ // Move all database forms to either |merged_forms| or
+ // |unused_database_forms|, based on whether they have a match in the keychain
+ // forms or not. If there is a match, add its password to the DB form and
+ // mark the keychain form as used.
+ MoveAllFormsOut(
+ database_forms,
+ base::Bind(&MergePasswordFormsCallback, &keychain_forms->get(),
+ &used_keychain_forms, &unused_database_forms, merged_forms));
database_forms->swap(unused_database_forms);
// Clear out all the Keychain entries we used.
@@ -522,18 +590,11 @@ void GetPasswordsForForms(const AppleKeychain& keychain,
// matching PasswordForm using its corresponding SecKeychainItemRef.
ScopedVector<autofill::PasswordForm> unused_db_forms;
unused_db_forms.reserve(database_forms->size());
- for (auto& db_form : *database_forms) {
- ScopedVector<autofill::PasswordForm> keychain_matches =
- 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();
- }
+ // Move database forms with a password stored in |keychain| to |passwords|,
+ // including the password. The rest is moved to |unused_db_forms|.
+ MoveAllFormsOut(database_forms,
+ base::Bind(&GetPasswordsForFormsCallback, &keychain,
+ item_form_pairs, passwords, &unused_db_forms));
database_forms->swap(unused_db_forms);
STLDeleteContainerPairSecondPointers(item_form_pairs.begin(),
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698