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

Side by Side 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: Lambdas + scoped_ptr Created 5 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 return changes; 188 return changes;
189 } 189 }
190 190
191 // Moves the content of |second| to the end of |first|. 191 // Moves the content of |second| to the end of |first|.
192 void AppendSecondToFirst(ScopedVector<autofill::PasswordForm>* first, 192 void AppendSecondToFirst(ScopedVector<autofill::PasswordForm>* first,
193 ScopedVector<autofill::PasswordForm>* second) { 193 ScopedVector<autofill::PasswordForm>* second) {
194 first->insert(first->end(), second->begin(), second->end()); 194 first->insert(first->end(), second->begin(), second->end());
195 second->weak_clear(); 195 second->weak_clear();
196 } 196 }
197 197
198 // Returns the best match for |base_form| from |keychain_forms|, or nullptr if
199 // there is no suitable match.
200 const PasswordForm* BestKeychainFormForForm(
201 const PasswordForm& base_form,
202 const std::vector<PasswordForm*>& keychain_forms) {
203 const PasswordForm* partial_match = nullptr;
204 for (const auto* keychain_form : keychain_forms) {
205 // TODO(stuartmorgan): We should really be scoring path matches and picking
206 // the best, rather than just checking exact-or-not (although in practice
207 // keychain items with paths probably came from us).
208 if (internal_keychain_helpers::FormsMatchForMerge(
209 base_form, *keychain_form,
210 internal_keychain_helpers::FUZZY_FORM_MATCH)) {
211 if (base_form.origin == keychain_form->origin) {
212 return keychain_form;
213 } else if (!partial_match) {
214 partial_match = keychain_form;
215 }
216 }
217 }
218 return partial_match;
219 }
220
221 // Iterates over all elements in |forms|, passes the pointed to objects to
222 // |move_form|, and clears |forms| efficiently.
vasilii 2015/01/30 14:43:34 Expand the comment saying something about FormMove
vabr (Chromium) 2015/01/30 14:49:51 Done.
223 template <typename FormMover>
224 inline void MoveAllFormsOut(ScopedVector<autofill::PasswordForm>* forms,
225 FormMover mover) {
226 for (autofill::PasswordForm* form_ptr : *forms) {
227 scoped_ptr<autofill::PasswordForm> form(form_ptr);
228 mover(form.Pass());
vasilii 2015/01/30 14:43:34 mover(scoped_ptr<autofill::PasswordForm>(form_ptr)
vabr (Chromium) 2015/01/30 14:49:51 Done.
vasilii 2015/01/30 15:29:08 Just copy-paste my comment :-)
vabr (Chromium) 2015/01/30 16:47:51 Hopefully done this time. :)
229 }
230 // We moved the ownership of every form out of |forms|. For performance
231 // reasons, we can just weak_clear it, instead of nullptr-ing the respective
232 // elements and letting the vector's destructor to go through the list once
233 // more. This was tested on a banchmark, and seemed to make a difference on
vasilii 2015/01/30 14:43:34 bEnchmark
vabr (Chromium) 2015/01/30 14:49:51 Done.
234 // Mac.
235 forms->weak_clear();
236 }
237
198 } // namespace 238 } // namespace
199 239
200 #pragma mark - 240 #pragma mark -
201 241
202 // TODO(stuartmorgan): Convert most of this to private helpers in 242 // TODO(stuartmorgan): Convert most of this to private helpers in
203 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public 243 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public
204 // methods to provide test coverage. 244 // methods to provide test coverage.
205 namespace internal_keychain_helpers { 245 namespace internal_keychain_helpers {
206 246
207 // Returns a URL built from the given components. To create a URL without a 247 // Returns a URL built from the given components. To create a URL without a
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 } 435 }
396 bool equal_realm = form_a.signon_realm == form_b.signon_realm; 436 bool equal_realm = form_a.signon_realm == form_b.signon_realm;
397 if (strictness == FUZZY_FORM_MATCH) { 437 if (strictness == FUZZY_FORM_MATCH) {
398 equal_realm |= (!form_a.original_signon_realm.empty()) && 438 equal_realm |= (!form_a.original_signon_realm.empty()) &&
399 form_a.original_signon_realm == form_b.signon_realm; 439 form_a.original_signon_realm == form_b.signon_realm;
400 } 440 }
401 return form_a.scheme == form_b.scheme && equal_realm && 441 return form_a.scheme == form_b.scheme && equal_realm &&
402 form_a.username_value == form_b.username_value; 442 form_a.username_value == form_b.username_value;
403 } 443 }
404 444
405 // Returns an the best match for |base_form| from |keychain_forms|, or NULL if
406 // there is no suitable match.
407 PasswordForm* BestKeychainFormForForm(
408 const PasswordForm& base_form,
409 const std::vector<PasswordForm*>* keychain_forms) {
410 PasswordForm* partial_match = NULL;
411 for (std::vector<PasswordForm*>::const_iterator i = keychain_forms->begin();
412 i != keychain_forms->end(); ++i) {
413 // TODO(stuartmorgan): We should really be scoring path matches and picking
414 // the best, rather than just checking exact-or-not (although in practice
415 // keychain items with paths probably came from us).
416 if (FormsMatchForMerge(base_form, *(*i), FUZZY_FORM_MATCH)) {
417 if (base_form.origin == (*i)->origin) {
418 return *i;
419 } else if (!partial_match) {
420 partial_match = *i;
421 }
422 }
423 }
424 return partial_match;
425 }
426
427 // Moves entries from |forms| that are blacklist entries into |blacklist|. 445 // Moves entries from |forms| that are blacklist entries into |blacklist|.
428 void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms, 446 void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms,
429 ScopedVector<autofill::PasswordForm>* blacklist) { 447 ScopedVector<autofill::PasswordForm>* blacklist) {
430 blacklist->reserve(blacklist->size() + forms->size()); 448 blacklist->reserve(blacklist->size() + forms->size());
431 ScopedVector<autofill::PasswordForm> non_blacklist; 449 ScopedVector<autofill::PasswordForm> non_blacklist;
432 for (auto& form : *forms) { 450 // Move forms in either |non_blacklist| or |blacklist|, depending on whether
451 // they are blacklisted by the user.
452 MoveAllFormsOut(forms, [&non_blacklist, blacklist](
453 scoped_ptr<autofill::PasswordForm> form) {
433 if (form->blacklisted_by_user) 454 if (form->blacklisted_by_user)
434 blacklist->push_back(form); 455 blacklist->push_back(form.release());
435 else 456 else
436 non_blacklist.push_back(form); 457 non_blacklist.push_back(form.release());
437 form = nullptr; 458 });
438 }
439 forms->swap(non_blacklist); 459 forms->swap(non_blacklist);
440 } 460 }
441 461
442 // Takes |keychain_forms| and |database_forms| and moves the following 2 types 462 // Takes |keychain_forms| and |database_forms| and moves the following 2 types
443 // of forms to |merged_forms|: (1) blacklisted |database_forms|, (2) 463 // of forms to |merged_forms|: (1) blacklisted |database_forms|, (2)
444 // |database_forms| which have a corresponding entry in |keychain_forms|. The 464 // |database_forms| which have a corresponding entry in |keychain_forms|. The
445 // database forms of type (2) have their password value updated from the 465 // database forms of type (2) have their password value updated from the
446 // corresponding keychain form, and all the keychain forms corresponding to some 466 // corresponding keychain form, and all the keychain forms corresponding to some
447 // database form are removed from |keychain_forms| and deleted. 467 // database form are removed from |keychain_forms| and deleted.
448 void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms, 468 void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms,
449 ScopedVector<autofill::PasswordForm>* database_forms, 469 ScopedVector<autofill::PasswordForm>* database_forms,
450 ScopedVector<autofill::PasswordForm>* merged_forms) { 470 ScopedVector<autofill::PasswordForm>* merged_forms) {
451 // Pull out the database blacklist items, since they are used as-is rather 471 // Pull out the database blacklist items, since they are used as-is rather
452 // than being merged with keychain forms. 472 // than being merged with keychain forms.
453 ExtractBlacklistForms(database_forms, merged_forms); 473 ExtractBlacklistForms(database_forms, merged_forms);
454 474
455 // Merge the normal entries. 475 // Merge the normal entries.
456 ScopedVector<autofill::PasswordForm> unused_database_forms; 476 ScopedVector<autofill::PasswordForm> unused_database_forms;
457 unused_database_forms.reserve(database_forms->size()); 477 unused_database_forms.reserve(database_forms->size());
458 std::set<autofill::PasswordForm*> used_keychain_forms; 478 std::set<const autofill::PasswordForm*> used_keychain_forms;
459 for (auto& db_form : *database_forms) { 479 // Move all database forms to either |merged_forms| or
460 PasswordForm* best_match = 480 // |unused_database_forms|, based on whether they have a match in the keychain
461 BestKeychainFormForForm(*db_form, &keychain_forms->get()); 481 // forms or not. If there is a match, add its password to the DB form and
482 // mark the keychain form as used.
483 MoveAllFormsOut(database_forms, [keychain_forms, &used_keychain_forms,
484 merged_forms, &unused_database_forms](
485 scoped_ptr<autofill::PasswordForm> form) {
486 const PasswordForm* best_match =
487 BestKeychainFormForForm(*form, keychain_forms->get());
462 if (best_match) { 488 if (best_match) {
463 used_keychain_forms.insert(best_match); 489 used_keychain_forms.insert(best_match);
464 db_form->password_value = best_match->password_value; 490 form->password_value = best_match->password_value;
465 merged_forms->push_back(db_form); 491 merged_forms->push_back(form.release());
466 } else { 492 } else {
467 unused_database_forms.push_back(db_form); 493 unused_database_forms.push_back(form.release());
468 } 494 }
469 db_form = nullptr; 495 });
470 }
471 database_forms->swap(unused_database_forms); 496 database_forms->swap(unused_database_forms);
472 497
473 // Clear out all the Keychain entries we used. 498 // Clear out all the Keychain entries we used.
474 ScopedVector<autofill::PasswordForm> unused_keychain_forms; 499 ScopedVector<autofill::PasswordForm> unused_keychain_forms;
475 unused_keychain_forms.reserve(keychain_forms->size()); 500 unused_keychain_forms.reserve(keychain_forms->size());
476 for (auto& keychain_form : *keychain_forms) { 501 for (auto& keychain_form : *keychain_forms) {
477 if (!ContainsKey(used_keychain_forms, keychain_form)) { 502 if (!ContainsKey(used_keychain_forms, keychain_form)) {
478 unused_keychain_forms.push_back(keychain_form); 503 unused_keychain_forms.push_back(keychain_form);
479 keychain_form = nullptr; 504 keychain_form = nullptr;
480 } 505 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 std::vector<SecKeychainItemRef> keychain_items; 540 std::vector<SecKeychainItemRef> keychain_items;
516 std::vector<ItemFormPair> item_form_pairs = 541 std::vector<ItemFormPair> item_form_pairs =
517 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, 542 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items,
518 keychain); 543 keychain);
519 544
520 // Next, compare the attributes of the PasswordForms in |database_forms| 545 // Next, compare the attributes of the PasswordForms in |database_forms|
521 // against those in |item_form_pairs|, and extract password data for each 546 // against those in |item_form_pairs|, and extract password data for each
522 // matching PasswordForm using its corresponding SecKeychainItemRef. 547 // matching PasswordForm using its corresponding SecKeychainItemRef.
523 ScopedVector<autofill::PasswordForm> unused_db_forms; 548 ScopedVector<autofill::PasswordForm> unused_db_forms;
524 unused_db_forms.reserve(database_forms->size()); 549 unused_db_forms.reserve(database_forms->size());
525 for (auto& db_form : *database_forms) { 550 // Move database forms with a password stored in |keychain| to |passwords|,
551 // including the password. The rest is moved to |unused_db_forms|.
552 MoveAllFormsOut(database_forms,
553 [&keychain, &item_form_pairs, passwords, &unused_db_forms](
554 scoped_ptr<autofill::PasswordForm> form) {
526 ScopedVector<autofill::PasswordForm> keychain_matches = 555 ScopedVector<autofill::PasswordForm> keychain_matches =
527 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *db_form); 556 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *form);
528 557
529 ScopedVector<autofill::PasswordForm> db_form_container; 558 ScopedVector<autofill::PasswordForm> db_form_container;
530 db_form_container.push_back(db_form); 559 db_form_container.push_back(form.release());
531 db_form = nullptr;
532 MergePasswordForms(&keychain_matches, &db_form_container, passwords); 560 MergePasswordForms(&keychain_matches, &db_form_container, passwords);
533 unused_db_forms.insert(unused_db_forms.end(), db_form_container.begin(), 561 AppendSecondToFirst(&unused_db_forms, &db_form_container);
534 db_form_container.end()); 562 });
535 db_form_container.weak_clear();
536 }
537 database_forms->swap(unused_db_forms); 563 database_forms->swap(unused_db_forms);
538 564
539 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), 565 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(),
540 item_form_pairs.end()); 566 item_form_pairs.end());
541 for (SecKeychainItemRef item : keychain_items) { 567 for (SecKeychainItemRef item : keychain_items) {
542 keychain.Free(item); 568 keychain.Free(item);
543 } 569 }
544 } 570 }
545 571
546 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. 572 // TODO(stuartmorgan): signon_realm for proxies is not yet supported.
(...skipping 28 matching lines...) Expand all
575 bool FormIsValidAndMatchesOtherForm(const PasswordForm& query_form, 601 bool FormIsValidAndMatchesOtherForm(const PasswordForm& query_form,
576 const PasswordForm& other_form) { 602 const PasswordForm& other_form) {
577 std::string server; 603 std::string server;
578 std::string security_domain; 604 std::string security_domain;
579 UInt32 port; 605 UInt32 port;
580 bool is_secure; 606 bool is_secure;
581 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port, 607 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port,
582 &is_secure, &security_domain)) { 608 &is_secure, &security_domain)) {
583 return false; 609 return false;
584 } 610 }
585 return internal_keychain_helpers::FormsMatchForMerge( 611 return FormsMatchForMerge(query_form, other_form, STRICT_FORM_MATCH);
586 query_form, other_form, STRICT_FORM_MATCH);
587 } 612 }
588 613
589 ScopedVector<autofill::PasswordForm> ExtractPasswordsMergeableWithForm( 614 ScopedVector<autofill::PasswordForm> ExtractPasswordsMergeableWithForm(
590 const AppleKeychain& keychain, 615 const AppleKeychain& keychain,
591 const std::vector<ItemFormPair>& item_form_pairs, 616 const std::vector<ItemFormPair>& item_form_pairs,
592 const PasswordForm& query_form) { 617 const PasswordForm& query_form) {
593 ScopedVector<autofill::PasswordForm> matches; 618 ScopedVector<autofill::PasswordForm> matches;
594 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin(); 619 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin();
595 i != item_form_pairs.end(); ++i) { 620 i != item_form_pairs.end(); ++i) {
596 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) { 621 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) {
597 // Create a new object, since the caller is responsible for deleting the 622 // Create a new object, since the caller is responsible for deleting the
598 // returned forms. 623 // returned forms.
599 scoped_ptr<PasswordForm> form_with_password(new PasswordForm()); 624 scoped_ptr<PasswordForm> form_with_password(new PasswordForm());
600 internal_keychain_helpers::FillPasswordFormFromKeychainItem( 625 FillPasswordFormFromKeychainItem(
601 keychain, *(i->first), form_with_password.get(), 626 keychain, *(i->first), form_with_password.get(),
602 true); // Load password attributes and data. 627 true); // Load password attributes and data.
603 // Do not include blacklisted items found in the keychain. 628 // Do not include blacklisted items found in the keychain.
604 if (!form_with_password->blacklisted_by_user) 629 if (!form_with_password->blacklisted_by_user)
605 matches.push_back(form_with_password.release()); 630 matches.push_back(form_with_password.release());
606 } 631 }
607 } 632 }
608 return matches.Pass(); 633 return matches.Pass();
609 } 634 }
610 635
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 1070
1046 ScopedVector<autofill::PasswordForm> matched_forms; 1071 ScopedVector<autofill::PasswordForm> matched_forms;
1047 internal_keychain_helpers::MergePasswordForms( 1072 internal_keychain_helpers::MergePasswordForms(
1048 &keychain_forms, &database_forms, &matched_forms); 1073 &keychain_forms, &database_forms, &matched_forms);
1049 1074
1050 // Strip any blacklist entries out of the unused Keychain array, then take 1075 // Strip any blacklist entries out of the unused Keychain array, then take
1051 // all the entries that are left (which we can use as imported passwords). 1076 // all the entries that are left (which we can use as imported passwords).
1052 ScopedVector<PasswordForm> keychain_blacklist_forms; 1077 ScopedVector<PasswordForm> keychain_blacklist_forms;
1053 internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms, 1078 internal_keychain_helpers::ExtractBlacklistForms(&keychain_forms,
1054 &keychain_blacklist_forms); 1079 &keychain_blacklist_forms);
1055 matched_forms.insert(matched_forms.end(), 1080 AppendSecondToFirst(&matched_forms, &keychain_forms);
1056 keychain_forms.begin(),
1057 keychain_forms.end());
1058 keychain_forms.weak_clear();
1059 1081
1060 if (!database_forms.empty()) { 1082 if (!database_forms.empty()) {
1061 RemoveDatabaseForms(database_forms.get()); 1083 RemoveDatabaseForms(database_forms.get());
1062 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get())); 1084 NotifyLoginsChanged(FormsToRemoveChangeList(database_forms.get()));
1063 } 1085 }
1064 1086
1065 callback_runner.Run(matched_forms.Pass()); 1087 callback_runner.Run(matched_forms.Pass());
1066 } 1088 }
1067 1089
1068 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) { 1090 void PasswordStoreMac::GetBlacklistLoginsImpl(GetLoginsRequest* request) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 1184
1163 // Filter forms with corresponding Keychain entry out of |database_forms|. 1185 // Filter forms with corresponding Keychain entry out of |database_forms|.
1164 ScopedVector<PasswordForm> forms_with_keychain_entry; 1186 ScopedVector<PasswordForm> forms_with_keychain_entry;
1165 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms, 1187 internal_keychain_helpers::GetPasswordsForForms(*keychain_, &database_forms,
1166 &forms_with_keychain_entry); 1188 &forms_with_keychain_entry);
1167 1189
1168 // Clean up any orphaned database entries. 1190 // Clean up any orphaned database entries.
1169 RemoveDatabaseForms(database_forms.get()); 1191 RemoveDatabaseForms(database_forms.get());
1170 1192
1171 // Move the orphaned DB forms to the output parameter. 1193 // Move the orphaned DB forms to the output parameter.
1172 orphaned_forms->insert(orphaned_forms->end(), database_forms.begin(), 1194 AppendSecondToFirst(orphaned_forms, &database_forms);
1173 database_forms.end());
1174 database_forms.weak_clear();
1175 } 1195 }
OLDNEW
« 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