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

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: 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 an the best match for |base_form| from |keychain_forms|, or NULL if
199 // there is no suitable match.
200 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.
201 const PasswordForm& base_form,
202 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
203 PasswordForm* partial_match = NULL;
204 for (std::vector<PasswordForm*>::const_iterator i = keychain_forms->begin();
205 i != keychain_forms->end(); ++i) {
206 // TODO(stuartmorgan): We should really be scoring path matches and picking
207 // the best, rather than just checking exact-or-not (although in practice
208 // keychain items with paths probably came from us).
209 if (internal_keychain_helpers::FormsMatchForMerge(
210 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.
211 if (base_form.origin == (*i)->origin) {
212 return *i;
213 } else if (!partial_match) {
214 partial_match = *i;
215 }
216 }
217 }
218 return partial_match;
219 }
220
221 typedef base::Callback<void(scoped_ptr<autofill::PasswordForm>)>
222 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.
223
224 // Stores |form| in either |non_blacklist| or |blacklist|, depending on whether
225 // |form| is blacklisted by the user.
226 void ExtractBlacklistFormsCallback(
vabr (Chromium) 2015/01/29 15:41:11 The three callbacks correspond to the three places
227 ScopedVector<autofill::PasswordForm>* non_blacklist,
228 ScopedVector<autofill::PasswordForm>* blacklist,
229 scoped_ptr<autofill::PasswordForm> form) {
230 if (form->blacklisted_by_user)
231 blacklist->push_back(form.release());
232 else
233 non_blacklist->push_back(form.release());
234 }
235
236 // If |db_form|, coming from the login DB, has a match in |keychain_forms|, the
237 // password of the match is copied into |db_form|, which is moved to
238 // |merged_forms|. The used keychain form is also marked in
239 // |used_keychain_forms|. Otherwise, |db_form| is moved to
240 // |unused_database_forms|.
241 void MergePasswordFormsCallback(
242 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.
243 std::set<autofill::PasswordForm*>* used_keychain_forms,
244 ScopedVector<autofill::PasswordForm>* unused_database_forms,
245 ScopedVector<autofill::PasswordForm>* merged_forms,
246 scoped_ptr<autofill::PasswordForm> db_form) {
247 PasswordForm* best_match = BestKeychainFormForForm(*db_form, keychain_forms);
248 if (best_match) {
249 used_keychain_forms->insert(best_match);
250 db_form->password_value = best_match->password_value;
251 merged_forms->push_back(db_form.release());
252 } else {
253 unused_database_forms->push_back(db_form.release());
254 }
255 }
256
257 // If there is a password stored in |keychain| for |db_form|, adds it to
258 // |db_form| and moves |db_form| to |passwords|. Otherwise moves |db_form| to
259 // |unused_db_forms|.
260 void GetPasswordsForFormsCallback(
261 const AppleKeychain* keychain,
262 const std::vector<internal_keychain_helpers::ItemFormPair>& item_form_pairs,
263 ScopedVector<autofill::PasswordForm>* passwords,
264 ScopedVector<autofill::PasswordForm>* unused_db_forms,
265 scoped_ptr<autofill::PasswordForm> db_form) {
266 ScopedVector<autofill::PasswordForm> keychain_matches =
267 internal_keychain_helpers::ExtractPasswordsMergeableWithForm(
268 *keychain, item_form_pairs, *db_form);
269
270 ScopedVector<autofill::PasswordForm> db_form_container;
271 db_form_container.push_back(db_form.release());
272 internal_keychain_helpers::MergePasswordForms(&keychain_matches,
273 &db_form_container, passwords);
274 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.
275 db_form_container.end());
276 db_form_container.weak_clear();
277 }
278
279 // Iterates over all elements in |forms|, passes the pointed to objects to
280 // |move_form|, and clears |forms| efficiently.
281 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
282 TakeFormCallback move_form) {
283 for (auto* form_ptr : *forms) {
vasilii 2015/01/29 16:41:13 autofill::PasswordForm*
vabr (Chromium) 2015/01/30 12:57:09 Done.
284 scoped_ptr<autofill::PasswordForm> form(form_ptr);
285 move_form.Run(form.Pass());
286 }
287 // We moved the ownership of every form out of |forms|. For performance
288 // reasons, we can just weak_clear it, instead of nullptr-ing the respective
289 // elements and letting the vector's destructor to go through the list once
290 // more. This was tested on a banchmark, and seemed to make a difference on
291 // Mac.
292 forms->weak_clear();
293 }
294
198 } // namespace 295 } // namespace
199 296
200 #pragma mark - 297 #pragma mark -
201 298
202 // TODO(stuartmorgan): Convert most of this to private helpers in 299 // TODO(stuartmorgan): Convert most of this to private helpers in
203 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public 300 // MacKeychainPasswordFormAdapter once it has sufficient higher-level public
204 // methods to provide test coverage. 301 // methods to provide test coverage.
205 namespace internal_keychain_helpers { 302 namespace internal_keychain_helpers {
206 303
207 // Returns a URL built from the given components. To create a URL without a 304 // 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 } 492 }
396 bool equal_realm = form_a.signon_realm == form_b.signon_realm; 493 bool equal_realm = form_a.signon_realm == form_b.signon_realm;
397 if (strictness == FUZZY_FORM_MATCH) { 494 if (strictness == FUZZY_FORM_MATCH) {
398 equal_realm |= (!form_a.original_signon_realm.empty()) && 495 equal_realm |= (!form_a.original_signon_realm.empty()) &&
399 form_a.original_signon_realm == form_b.signon_realm; 496 form_a.original_signon_realm == form_b.signon_realm;
400 } 497 }
401 return form_a.scheme == form_b.scheme && equal_realm && 498 return form_a.scheme == form_b.scheme && equal_realm &&
402 form_a.username_value == form_b.username_value; 499 form_a.username_value == form_b.username_value;
403 } 500 }
404 501
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|. 502 // Moves entries from |forms| that are blacklist entries into |blacklist|.
428 void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms, 503 void ExtractBlacklistForms(ScopedVector<autofill::PasswordForm>* forms,
429 ScopedVector<autofill::PasswordForm>* blacklist) { 504 ScopedVector<autofill::PasswordForm>* blacklist) {
430 blacklist->reserve(blacklist->size() + forms->size()); 505 blacklist->reserve(blacklist->size() + forms->size());
431 ScopedVector<autofill::PasswordForm> non_blacklist; 506 ScopedVector<autofill::PasswordForm> non_blacklist;
432 for (auto& form : *forms) { 507 // Move forms in either |non_blacklist| or |blacklist|, depending on whether
433 if (form->blacklisted_by_user) 508 // they are blacklisted by the user.
434 blacklist->push_back(form); 509 MoveAllFormsOut(forms, base::Bind(&ExtractBlacklistFormsCallback,
435 else 510 &non_blacklist, blacklist));
436 non_blacklist.push_back(form);
437 form = nullptr;
438 }
439 forms->swap(non_blacklist); 511 forms->swap(non_blacklist);
440 } 512 }
441 513
442 // Takes |keychain_forms| and |database_forms| and moves the following 2 types 514 // Takes |keychain_forms| and |database_forms| and moves the following 2 types
443 // of forms to |merged_forms|: (1) blacklisted |database_forms|, (2) 515 // of forms to |merged_forms|: (1) blacklisted |database_forms|, (2)
444 // |database_forms| which have a corresponding entry in |keychain_forms|. The 516 // |database_forms| which have a corresponding entry in |keychain_forms|. The
445 // database forms of type (2) have their password value updated from the 517 // database forms of type (2) have their password value updated from the
446 // corresponding keychain form, and all the keychain forms corresponding to some 518 // corresponding keychain form, and all the keychain forms corresponding to some
447 // database form are removed from |keychain_forms| and deleted. 519 // database form are removed from |keychain_forms| and deleted.
448 void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms, 520 void MergePasswordForms(ScopedVector<autofill::PasswordForm>* keychain_forms,
449 ScopedVector<autofill::PasswordForm>* database_forms, 521 ScopedVector<autofill::PasswordForm>* database_forms,
450 ScopedVector<autofill::PasswordForm>* merged_forms) { 522 ScopedVector<autofill::PasswordForm>* merged_forms) {
451 // Pull out the database blacklist items, since they are used as-is rather 523 // Pull out the database blacklist items, since they are used as-is rather
452 // than being merged with keychain forms. 524 // than being merged with keychain forms.
453 ExtractBlacklistForms(database_forms, merged_forms); 525 ExtractBlacklistForms(database_forms, merged_forms);
454 526
455 // Merge the normal entries. 527 // Merge the normal entries.
456 ScopedVector<autofill::PasswordForm> unused_database_forms; 528 ScopedVector<autofill::PasswordForm> unused_database_forms;
457 unused_database_forms.reserve(database_forms->size()); 529 unused_database_forms.reserve(database_forms->size());
458 std::set<autofill::PasswordForm*> used_keychain_forms; 530 std::set<autofill::PasswordForm*> used_keychain_forms;
459 for (auto& db_form : *database_forms) { 531 // Move all database forms to either |merged_forms| or
460 PasswordForm* best_match = 532 // |unused_database_forms|, based on whether they have a match in the keychain
461 BestKeychainFormForForm(*db_form, &keychain_forms->get()); 533 // forms or not. If there is a match, add its password to the DB form and
462 if (best_match) { 534 // mark the keychain form as used.
463 used_keychain_forms.insert(best_match); 535 MoveAllFormsOut(
464 db_form->password_value = best_match->password_value; 536 database_forms,
465 merged_forms->push_back(db_form); 537 base::Bind(&MergePasswordFormsCallback, &keychain_forms->get(),
466 } else { 538 &used_keychain_forms, &unused_database_forms, merged_forms));
467 unused_database_forms.push_back(db_form);
468 }
469 db_form = nullptr;
470 }
471 database_forms->swap(unused_database_forms); 539 database_forms->swap(unused_database_forms);
472 540
473 // Clear out all the Keychain entries we used. 541 // Clear out all the Keychain entries we used.
474 ScopedVector<autofill::PasswordForm> unused_keychain_forms; 542 ScopedVector<autofill::PasswordForm> unused_keychain_forms;
475 unused_keychain_forms.reserve(keychain_forms->size()); 543 unused_keychain_forms.reserve(keychain_forms->size());
476 for (auto& keychain_form : *keychain_forms) { 544 for (auto& keychain_form : *keychain_forms) {
477 if (!ContainsKey(used_keychain_forms, keychain_form)) { 545 if (!ContainsKey(used_keychain_forms, keychain_form)) {
478 unused_keychain_forms.push_back(keychain_form); 546 unused_keychain_forms.push_back(keychain_form);
479 keychain_form = nullptr; 547 keychain_form = nullptr;
480 } 548 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 std::vector<SecKeychainItemRef> keychain_items; 583 std::vector<SecKeychainItemRef> keychain_items;
516 std::vector<ItemFormPair> item_form_pairs = 584 std::vector<ItemFormPair> item_form_pairs =
517 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items, 585 ExtractAllKeychainItemAttributesIntoPasswordForms(&keychain_items,
518 keychain); 586 keychain);
519 587
520 // Next, compare the attributes of the PasswordForms in |database_forms| 588 // Next, compare the attributes of the PasswordForms in |database_forms|
521 // against those in |item_form_pairs|, and extract password data for each 589 // against those in |item_form_pairs|, and extract password data for each
522 // matching PasswordForm using its corresponding SecKeychainItemRef. 590 // matching PasswordForm using its corresponding SecKeychainItemRef.
523 ScopedVector<autofill::PasswordForm> unused_db_forms; 591 ScopedVector<autofill::PasswordForm> unused_db_forms;
524 unused_db_forms.reserve(database_forms->size()); 592 unused_db_forms.reserve(database_forms->size());
525 for (auto& db_form : *database_forms) { 593 // Move database forms with a password stored in |keychain| to |passwords|,
526 ScopedVector<autofill::PasswordForm> keychain_matches = 594 // including the password. The rest is moved to |unused_db_forms|.
527 ExtractPasswordsMergeableWithForm(keychain, item_form_pairs, *db_form); 595 MoveAllFormsOut(database_forms,
528 596 base::Bind(&GetPasswordsForFormsCallback, &keychain,
529 ScopedVector<autofill::PasswordForm> db_form_container; 597 item_form_pairs, passwords, &unused_db_forms));
530 db_form_container.push_back(db_form);
531 db_form = nullptr;
532 MergePasswordForms(&keychain_matches, &db_form_container, passwords);
533 unused_db_forms.insert(unused_db_forms.end(), db_form_container.begin(),
534 db_form_container.end());
535 db_form_container.weak_clear();
536 }
537 database_forms->swap(unused_db_forms); 598 database_forms->swap(unused_db_forms);
538 599
539 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(), 600 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(),
540 item_form_pairs.end()); 601 item_form_pairs.end());
541 for (SecKeychainItemRef item : keychain_items) { 602 for (SecKeychainItemRef item : keychain_items) {
542 keychain.Free(item); 603 keychain.Free(item);
543 } 604 }
544 } 605 }
545 606
546 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. 607 // TODO(stuartmorgan): signon_realm for proxies is not yet supported.
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 &forms_with_keychain_entry); 1227 &forms_with_keychain_entry);
1167 1228
1168 // Clean up any orphaned database entries. 1229 // Clean up any orphaned database entries.
1169 RemoveDatabaseForms(database_forms.get()); 1230 RemoveDatabaseForms(database_forms.get());
1170 1231
1171 // Move the orphaned DB forms to the output parameter. 1232 // Move the orphaned DB forms to the output parameter.
1172 orphaned_forms->insert(orphaned_forms->end(), database_forms.begin(), 1233 orphaned_forms->insert(orphaned_forms->end(), database_forms.begin(),
1173 database_forms.end()); 1234 database_forms.end());
1174 database_forms.weak_clear(); 1235 database_forms.weak_clear();
1175 } 1236 }
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