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

Side by Side Diff: chrome/browser/password_manager/password_store_mac.cc

Issue 23477015: [sync] Significantly speed up password model association on mac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback Created 7 years, 3 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
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>
11 #include <utility>
11 #include <vector> 12 #include <vector>
12 13
13 #include "base/callback.h" 14 #include "base/callback.h"
14 #include "base/debug/crash_logging.h" 15 #include "base/debug/crash_logging.h"
15 #include "base/debug/stack_trace.h" 16 #include "base/debug/stack_trace.h"
16 #include "base/logging.h" 17 #include "base/logging.h"
17 #include "base/mac/mac_logging.h" 18 #include "base/mac/mac_logging.h"
18 #include "base/mac/mac_util.h" 19 #include "base/mac/mac_util.h"
19 #include "base/message_loop/message_loop.h" 20 #include "base/message_loop/message_loop.h"
20 #include "base/stl_util.h" 21 #include "base/stl_util.h"
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 switch (auth_type) { 230 switch (auth_type) {
230 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML; 231 case kSecAuthenticationTypeHTMLForm: return PasswordForm::SCHEME_HTML;
231 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC; 232 case kSecAuthenticationTypeHTTPBasic: return PasswordForm::SCHEME_BASIC;
232 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST; 233 case kSecAuthenticationTypeHTTPDigest: return PasswordForm::SCHEME_DIGEST;
233 default: return PasswordForm::SCHEME_OTHER; 234 default: return PasswordForm::SCHEME_OTHER;
234 } 235 }
235 } 236 }
236 237
237 bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, 238 bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain,
238 const SecKeychainItemRef& keychain_item, 239 const SecKeychainItemRef& keychain_item,
239 PasswordForm* form) { 240 PasswordForm* form,
241 bool extract_password_data) {
240 DCHECK(form); 242 DCHECK(form);
241 243
242 SecKeychainAttributeInfo attrInfo; 244 SecKeychainAttributeInfo attrInfo;
243 UInt32 tags[] = { kSecAccountItemAttr, 245 UInt32 tags[] = { kSecAccountItemAttr,
244 kSecServerItemAttr, 246 kSecServerItemAttr,
245 kSecPortItemAttr, 247 kSecPortItemAttr,
246 kSecPathItemAttr, 248 kSecPathItemAttr,
247 kSecProtocolItemAttr, 249 kSecProtocolItemAttr,
248 kSecAuthenticationTypeItemAttr, 250 kSecAuthenticationTypeItemAttr,
249 kSecSecurityDomainItemAttr, 251 kSecSecurityDomainItemAttr,
250 kSecCreationDateItemAttr, 252 kSecCreationDateItemAttr,
251 kSecNegativeItemAttr }; 253 kSecNegativeItemAttr };
252 attrInfo.count = arraysize(tags); 254 attrInfo.count = arraysize(tags);
253 attrInfo.tag = tags; 255 attrInfo.tag = tags;
254 attrInfo.format = NULL; 256 attrInfo.format = NULL;
255 257
256 SecKeychainAttributeList *attrList; 258 SecKeychainAttributeList *attrList;
257 UInt32 password_length; 259 UInt32 password_length;
258 void* password_data; 260
261 // If |extract_password_data| is false, do not pass in a reference to
262 // |password_data|. ItemCopyAttributesAndData will then extract only the
263 // attributes of |keychain_item| (doesn't require OS authorization), and not
264 // attempt to extract its password data (requires OS authorization).
265 void* password_data = NULL;
266 void** password_data_ref = extract_password_data ? &password_data : NULL;
267
259 OSStatus result = keychain.ItemCopyAttributesAndData(keychain_item, &attrInfo, 268 OSStatus result = keychain.ItemCopyAttributesAndData(keychain_item, &attrInfo,
260 NULL, &attrList, 269 NULL, &attrList,
261 &password_length, 270 &password_length,
262 &password_data); 271 password_data_ref);
263 272
264 if (result != noErr) { 273 if (result != noErr) {
265 // We don't log errSecAuthFailed because that just means that the user 274 // We don't log errSecAuthFailed because that just means that the user
266 // chose not to allow us access to the item. 275 // chose not to allow us access to the item.
267 if (result != errSecAuthFailed) { 276 if (result != errSecAuthFailed) {
268 OSSTATUS_LOG(ERROR, result) << "Keychain data load failed"; 277 OSSTATUS_LOG(ERROR, result) << "Keychain data load failed";
269 } 278 }
270 return false; 279 return false;
271 } 280 }
272 281
273 UTF8ToUTF16(static_cast<const char *>(password_data), password_length, 282 if (extract_password_data) {
274 &(form->password_value)); 283 UTF8ToUTF16(static_cast<const char *>(password_data), password_length,
284 &(form->password_value));
285 }
275 286
276 int port = kAnyPort; 287 int port = kAnyPort;
277 std::string server; 288 std::string server;
278 std::string security_domain; 289 std::string security_domain;
279 std::string path; 290 std::string path;
280 for (unsigned int i = 0; i < attrList->count; i++) { 291 for (unsigned int i = 0; i < attrList->count; i++) {
281 SecKeychainAttribute attr = attrList->attr[i]; 292 SecKeychainAttribute attr = attrList->attr[i];
282 if (!attr.data) { 293 if (!attr.data) {
283 continue; 294 continue;
284 } 295 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 form->blacklisted_by_user = true; 337 form->blacklisted_by_user = true;
327 } 338 }
328 break; 339 break;
329 } 340 }
330 } 341 }
331 keychain.ItemFreeAttributesAndData(attrList, password_data); 342 keychain.ItemFreeAttributesAndData(attrList, password_data);
332 343
333 // kSecNegativeItemAttr doesn't seem to actually be in widespread use. In 344 // kSecNegativeItemAttr doesn't seem to actually be in widespread use. In
334 // practice, other browsers seem to use a "" or " " password (and a special 345 // practice, other browsers seem to use a "" or " " password (and a special
335 // user name) to indicated blacklist entries. 346 // user name) to indicated blacklist entries.
336 if (form->password_value.empty() || EqualsASCII(form->password_value, " ")) { 347 if (extract_password_data && (form->password_value.empty() ||
348 EqualsASCII(form->password_value, " "))) {
337 form->blacklisted_by_user = true; 349 form->blacklisted_by_user = true;
338 } 350 }
339 351
340 form->origin = URLFromComponents(form->ssl_valid, server, port, path); 352 form->origin = URLFromComponents(form->ssl_valid, server, port, path);
341 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm 353 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm
342 // format. 354 // format.
343 form->signon_realm = form->origin.GetOrigin().spec(); 355 form->signon_realm = form->origin.GetOrigin().spec();
344 if (form->scheme != PasswordForm::SCHEME_HTML) { 356 if (form->scheme != PasswordForm::SCHEME_HTML) {
345 form->signon_realm.append(security_domain); 357 form->signon_realm.append(security_domain);
346 } 358 }
347 return true; 359 return true;
348 } 360 }
349 361
350 bool FormsMatchForMerge(const PasswordForm& form_a, 362 bool FormsMatchForMerge(const PasswordForm& form_a,
351 const PasswordForm& form_b) { 363 const PasswordForm& form_b) {
352 // We never merge blacklist entries between our store and the keychain. 364 // We never merge blacklist entries between our store and the keychain.
353 if (form_a.blacklisted_by_user || form_b.blacklisted_by_user) { 365 if (form_a.blacklisted_by_user || form_b.blacklisted_by_user) {
stuartmorgan 2013/09/30 22:39:12 As far as I can tell, you are pulling a bunch of p
Raghu Simha 2013/10/02 02:09:50 There is a filtering step for blacklisted password
354 return false; 366 return false;
355 } 367 }
356 return form_a.scheme == form_b.scheme && 368 return form_a.scheme == form_b.scheme &&
357 form_a.signon_realm == form_b.signon_realm && 369 form_a.signon_realm == form_b.signon_realm &&
358 form_a.username_value == form_b.username_value; 370 form_a.username_value == form_b.username_value;
359 } 371 }
360 372
361 // Returns an the best match for |form| from |keychain_forms|, or NULL if there 373 // Returns an the best match for |form| from |keychain_forms|, or NULL if there
362 // is no suitable match. 374 // is no suitable match.
363 PasswordForm* BestKeychainFormForForm( 375 PasswordForm* BestKeychainFormForForm(
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 451
440 // Add in the blacklist entries from the database. 452 // Add in the blacklist entries from the database.
441 merged_forms->insert(merged_forms->end(), 453 merged_forms->insert(merged_forms->end(),
442 database_blacklist_forms.begin(), 454 database_blacklist_forms.begin(),
443 database_blacklist_forms.end()); 455 database_blacklist_forms.end());
444 456
445 // Clear out all the Keychain entries we used. 457 // Clear out all the Keychain entries we used.
446 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms); 458 DeleteVectorElementsInSet(keychain_forms, used_keychain_forms);
447 } 459 }
448 460
461 std::vector<MacKeychainPasswordFormAdapter::ItemFormPair>
462 GetAllKeychainItemAttributesAsPasswordForms(
463 std::vector<SecKeychainItemRef>* keychain_items,
464 const AppleKeychain& keychain) {
465 DCHECK(keychain_items);
466 MacKeychainPasswordFormAdapter keychain_adapter(&keychain);
467 *keychain_items = keychain_adapter.GetAllPasswordFormKeychainItems();
468 std::vector<MacKeychainPasswordFormAdapter::ItemFormPair> item_form_pairs;
469 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items->begin();
470 i != keychain_items->end(); ++i) {
471 PasswordForm* form_without_password = new PasswordForm();
472 internal_keychain_helpers::FillPasswordFormFromKeychainItem(
473 keychain,
474 *i,
475 form_without_password,
476 false); // Load password attributes, but not password data.
477 item_form_pairs.push_back(std::make_pair(&(*i), form_without_password));
478 }
479 return item_form_pairs;
480 }
481
449 std::vector<PasswordForm*> GetPasswordsForForms( 482 std::vector<PasswordForm*> GetPasswordsForForms(
450 const AppleKeychain& keychain, 483 const AppleKeychain& keychain,
451 std::vector<PasswordForm*>* database_forms) { 484 std::vector<PasswordForm*>* database_forms) {
485 // First load the attributes of all items in the keychain without loading
486 // their password data, and then match items in |database_forms| against them.
487 // This avoids individually searching through the keychain for passwords
488 // matching each form in |database_forms|, and results in a significant
489 // performance gain, replacing O(N) keychain search operations with a single
490 // operation that loads all keychain items, and then selective reads of only
491 // the relevant passwords. See crbug.com/263685.
492 std::vector<SecKeychainItemRef> keychain_items;
493 std::vector<MacKeychainPasswordFormAdapter::ItemFormPair> item_form_pairs =
494 GetAllKeychainItemAttributesAsPasswordForms(&keychain_items, keychain);
495
496 // Next, compare the attributes of the PasswordForms in |database_forms|
497 // against those in |item_form_pairs|, and extract password data for each
498 // matching PasswordForm using its corresponding SecKeychainItemRef.
452 MacKeychainPasswordFormAdapter keychain_adapter(&keychain); 499 MacKeychainPasswordFormAdapter keychain_adapter(&keychain);
453
454 std::vector<PasswordForm*> merged_forms; 500 std::vector<PasswordForm*> merged_forms;
455 for (std::vector<PasswordForm*>::iterator i = database_forms->begin(); 501 for (std::vector<PasswordForm*>::iterator i = database_forms->begin();
456 i != database_forms->end();) { 502 i != database_forms->end();) {
457 std::vector<PasswordForm*> db_form_container(1, *i); 503 std::vector<PasswordForm*> db_form_container(1, *i);
458 std::vector<PasswordForm*> keychain_matches = 504 std::vector<PasswordForm*> keychain_matches =
459 keychain_adapter.PasswordsMergeableWithForm(**i); 505 keychain_adapter.ExtractPasswordsMergeableWithForm(item_form_pairs,
506 **i);
460 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms); 507 MergePasswordForms(&keychain_matches, &db_form_container, &merged_forms);
461 if (db_form_container.empty()) { 508 if (db_form_container.empty()) {
462 i = database_forms->erase(i); 509 i = database_forms->erase(i);
463 } else { 510 } else {
464 ++i; 511 ++i;
465 } 512 }
466 STLDeleteElements(&keychain_matches); 513 STLDeleteElements(&keychain_matches);
467 } 514 }
515
516 // Clean up temporary PasswordForms and SecKeychainItemRefs.
517 STLDeleteContainerPairSecondPointers(item_form_pairs.begin(),
518 item_form_pairs.end());
519 for (std::vector<SecKeychainItemRef>::iterator i = keychain_items.begin();
520 i != keychain_items.end(); ++i) {
521 keychain.Free(*i);
522 }
468 return merged_forms; 523 return merged_forms;
469 } 524 }
470 525
471 class Thread : public base::Thread { 526 class Thread : public base::Thread {
472 public: 527 public:
473 Thread(const char* name) : base::Thread(name) {} 528 Thread(const char* name) : base::Thread(name) {}
474 virtual ~Thread() { 529 virtual ~Thread() {
475 base::debug::SetCrashKeyToStackTrace( 530 base::debug::SetCrashKeyToStackTrace(
476 crash_keys::mac::kPasswordThreadDtorTrace, base::debug::StackTrace()); 531 crash_keys::mac::kPasswordThreadDtorTrace, base::debug::StackTrace());
477 } 532 }
(...skipping 11 matching lines...) Expand all
489 std::vector<PasswordForm*> 544 std::vector<PasswordForm*>
490 MacKeychainPasswordFormAdapter::PasswordsFillingForm( 545 MacKeychainPasswordFormAdapter::PasswordsFillingForm(
491 const PasswordForm& query_form) { 546 const PasswordForm& query_form) {
492 std::vector<SecKeychainItemRef> keychain_items = 547 std::vector<SecKeychainItemRef> keychain_items =
493 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, 548 MatchingKeychainItems(query_form.signon_realm, query_form.scheme,
494 NULL, NULL); 549 NULL, NULL);
495 550
496 return ConvertKeychainItemsToForms(&keychain_items); 551 return ConvertKeychainItemsToForms(&keychain_items);
497 } 552 }
498 553
554 bool MacKeychainPasswordFormAdapter::FormIsValidAndMatchesOtherForm(
555 const PasswordForm& query_form,
556 const PasswordForm& other_form) {
557 std::string server;
558 std::string security_domain;
559 int port;
560 bool is_secure;
561 if (!ExtractSignonRealmComponents(query_form.signon_realm, &server, &port,
562 &is_secure, &security_domain)) {
563 return false;
564 }
565 return internal_keychain_helpers::FormsMatchForMerge(query_form, other_form);
566 }
567
499 std::vector<PasswordForm*> 568 std::vector<PasswordForm*>
500 MacKeychainPasswordFormAdapter::PasswordsMergeableWithForm( 569 MacKeychainPasswordFormAdapter::ExtractPasswordsMergeableWithForm(
stuartmorgan 2013/09/30 22:39:12 AFAICT this no longer operates on the keychain in
Raghu Simha 2013/10/02 02:09:50 We reference the keychain in line 580, while calli
570 const std::vector<ItemFormPair>& item_form_pairs,
501 const PasswordForm& query_form) { 571 const PasswordForm& query_form) {
502 std::string username = UTF16ToUTF8(query_form.username_value); 572 std::vector<PasswordForm*> matches;
503 std::vector<SecKeychainItemRef> keychain_items = 573 for (std::vector<ItemFormPair>::const_iterator i = item_form_pairs.begin();
504 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, 574 i != item_form_pairs.end(); ++i) {
505 NULL, username.c_str()); 575 if (FormIsValidAndMatchesOtherForm(query_form, *(i->second))) {
506 576 // Create a new object, since the caller is responsible for deleting the
507 return ConvertKeychainItemsToForms(&keychain_items); 577 // returned forms.
stuartmorgan 2013/09/30 22:39:12 Feel free to use ScopedVector anywhere it makes li
Raghu Simha 2013/10/02 02:09:50 I did consider using a ScopedVector here, but ende
578 PasswordForm* form_with_password = new PasswordForm();
579 internal_keychain_helpers::FillPasswordFormFromKeychainItem(
580 *keychain_,
581 *(i->first),
582 form_with_password,
583 true); // Load password attributes and data.
584 matches.push_back(form_with_password);
585 }
586 }
587 return matches;
508 } 588 }
509 589
510 PasswordForm* MacKeychainPasswordFormAdapter::PasswordExactlyMatchingForm( 590 PasswordForm* MacKeychainPasswordFormAdapter::PasswordExactlyMatchingForm(
511 const PasswordForm& query_form) { 591 const PasswordForm& query_form) {
512 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form); 592 SecKeychainItemRef keychain_item = KeychainItemForForm(query_form);
513 if (keychain_item) { 593 if (keychain_item) {
514 PasswordForm* form = new PasswordForm(); 594 PasswordForm* form = new PasswordForm();
515 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, 595 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_,
516 keychain_item, 596 keychain_item,
517 form); 597 form,
598 true);
518 keychain_->Free(keychain_item); 599 keychain_->Free(keychain_item);
519 return form; 600 return form;
520 } 601 }
521 return NULL; 602 return NULL;
522 } 603 }
523 604
524 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm( 605 bool MacKeychainPasswordFormAdapter::HasPasswordsMergeableWithForm(
525 const PasswordForm& query_form) { 606 const PasswordForm& query_form) {
526 std::string username = UTF16ToUTF8(query_form.username_value); 607 std::string username = UTF16ToUTF8(query_form.username_value);
527 std::vector<SecKeychainItemRef> matches = 608 std::vector<SecKeychainItemRef> matches =
528 MatchingKeychainItems(query_form.signon_realm, query_form.scheme, 609 MatchingKeychainItems(query_form.signon_realm, query_form.scheme,
529 NULL, username.c_str()); 610 NULL, username.c_str());
530 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin(); 611 for (std::vector<SecKeychainItemRef>::iterator i = matches.begin();
531 i != matches.end(); ++i) { 612 i != matches.end(); ++i) {
532 keychain_->Free(*i); 613 keychain_->Free(*i);
533 } 614 }
534 615
535 return !matches.empty(); 616 return !matches.empty();
536 } 617 }
537 618
538 std::vector<PasswordForm*> 619 std::vector<SecKeychainItemRef>
539 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() { 620 MacKeychainPasswordFormAdapter::GetAllPasswordFormKeychainItems() {
540 SecAuthenticationType supported_auth_types[] = { 621 SecAuthenticationType supported_auth_types[] = {
541 kSecAuthenticationTypeHTMLForm, 622 kSecAuthenticationTypeHTMLForm,
542 kSecAuthenticationTypeHTTPBasic, 623 kSecAuthenticationTypeHTTPBasic,
543 kSecAuthenticationTypeHTTPDigest, 624 kSecAuthenticationTypeHTTPDigest,
544 }; 625 };
545 626
546 std::vector<SecKeychainItemRef> matches; 627 std::vector<SecKeychainItemRef> matches;
547 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) { 628 for (unsigned int i = 0; i < arraysize(supported_auth_types); ++i) {
548 KeychainSearch keychain_search(*keychain_); 629 KeychainSearch keychain_search(*keychain_);
549 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i], 630 keychain_search.Init(NULL, 0, kSecProtocolTypeAny, supported_auth_types[i],
550 NULL, NULL, NULL, CreatorCodeForSearch()); 631 NULL, NULL, NULL, CreatorCodeForSearch());
551 keychain_search.FindMatchingItems(&matches); 632 keychain_search.FindMatchingItems(&matches);
552 } 633 }
634 return matches;
635 }
553 636
554 return ConvertKeychainItemsToForms(&matches); 637 std::vector<PasswordForm*>
638 MacKeychainPasswordFormAdapter::GetAllPasswordFormPasswords() {
639 std::vector<SecKeychainItemRef> items = GetAllPasswordFormKeychainItems();
640 return ConvertKeychainItemsToForms(&items);
555 } 641 }
556 642
557 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { 643 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) {
558 // We should never be trying to store a blacklist in the keychain. 644 // We should never be trying to store a blacklist in the keychain.
559 DCHECK(!form.blacklisted_by_user); 645 DCHECK(!form.blacklisted_by_user);
560 646
561 std::string server; 647 std::string server;
562 std::string security_domain; 648 std::string security_domain;
563 int port; 649 int port;
564 bool is_secure; 650 bool is_secure;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 finds_only_owned_ = finds_only_owned; 698 finds_only_owned_ = finds_only_owned;
613 } 699 }
614 700
615 std::vector<PasswordForm*> 701 std::vector<PasswordForm*>
616 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms( 702 MacKeychainPasswordFormAdapter::ConvertKeychainItemsToForms(
617 std::vector<SecKeychainItemRef>* items) { 703 std::vector<SecKeychainItemRef>* items) {
618 std::vector<PasswordForm*> keychain_forms; 704 std::vector<PasswordForm*> keychain_forms;
619 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin(); 705 for (std::vector<SecKeychainItemRef>::const_iterator i = items->begin();
620 i != items->end(); ++i) { 706 i != items->end(); ++i) {
621 PasswordForm* form = new PasswordForm(); 707 PasswordForm* form = new PasswordForm();
622 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, 708 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(
623 *i, form)) { 709 *keychain_, *i, form, true)) {
624 keychain_forms.push_back(form); 710 keychain_forms.push_back(form);
625 } 711 }
626 keychain_->Free(*i); 712 keychain_->Free(*i);
627 } 713 }
628 items->clear(); 714 items->clear();
629 return keychain_forms; 715 return keychain_forms;
630 } 716 }
631 717
632 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm( 718 SecKeychainItemRef MacKeychainPasswordFormAdapter::KeychainItemForForm(
633 const PasswordForm& form) { 719 const PasswordForm& form) {
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); 1117 owned_keychain_adapter.SetFindsOnlyOwnedItems(true);
1032 for (std::vector<PasswordForm*>::const_iterator i = forms.begin(); 1118 for (std::vector<PasswordForm*>::const_iterator i = forms.begin();
1033 i != forms.end(); ++i) { 1119 i != forms.end(); ++i) {
1034 owned_keychain_adapter.RemovePassword(**i); 1120 owned_keychain_adapter.RemovePassword(**i);
1035 } 1121 }
1036 } 1122 }
1037 1123
1038 void PasswordStoreMac::CreateNotificationService() { 1124 void PasswordStoreMac::CreateNotificationService() {
1039 notification_service_.reset(content::NotificationService::Create()); 1125 notification_service_.reset(content::NotificationService::Create());
1040 } 1126 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698