Chromium Code Reviews| 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(), |