| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 ~KeychainSearch(); | 27 ~KeychainSearch(); |
| 28 | 28 |
| 29 // Sets up a keycahin search based on an non "null" (NULL for char*, | 29 // Sets up a keycahin search based on an non "null" (NULL for char*, |
| 30 // The appropriate "Any" entry for other types) arguments. | 30 // The appropriate "Any" entry for other types) arguments. |
| 31 // | 31 // |
| 32 // IMPORTANT: Any paramaters passed in *must* remain valid for as long as the | 32 // IMPORTANT: Any paramaters passed in *must* remain valid for as long as the |
| 33 // KeychainSearch object, since the search uses them by reference. | 33 // KeychainSearch object, since the search uses them by reference. |
| 34 void Init(const char* server, const UInt32& port, | 34 void Init(const char* server, const UInt32& port, |
| 35 const SecProtocolType& protocol, | 35 const SecProtocolType& protocol, |
| 36 const SecAuthenticationType& auth_type, const char* security_domain, | 36 const SecAuthenticationType& auth_type, const char* security_domain, |
| 37 const char* path, const char* username); | 37 const char* path, const char* username, OSType creator); |
| 38 | 38 |
| 39 // Fills |items| with all Keychain items that match the Init'd search. | 39 // Fills |items| with all Keychain items that match the Init'd search. |
| 40 // If the search fails for any reason, |items| will be unchanged. | 40 // If the search fails for any reason, |items| will be unchanged. |
| 41 void FindMatchingItems(std::vector<SecKeychainItemRef>* matches); | 41 void FindMatchingItems(std::vector<SecKeychainItemRef>* matches); |
| 42 | 42 |
| 43 private: | 43 private: |
| 44 const MacKeychain* keychain_; | 44 const MacKeychain* keychain_; |
| 45 SecKeychainAttributeList search_attributes_; | 45 SecKeychainAttributeList search_attributes_; |
| 46 SecKeychainSearchRef search_ref_; | 46 SecKeychainSearchRef search_ref_; |
| 47 }; | 47 }; |
| 48 | 48 |
| 49 KeychainSearch::KeychainSearch(const MacKeychain& keychain) | 49 KeychainSearch::KeychainSearch(const MacKeychain& keychain) |
| 50 : keychain_(&keychain), search_ref_(NULL) { | 50 : keychain_(&keychain), search_ref_(NULL) { |
| 51 search_attributes_.count = 0; | 51 search_attributes_.count = 0; |
| 52 search_attributes_.attr = NULL; | 52 search_attributes_.attr = NULL; |
| 53 } | 53 } |
| 54 | 54 |
| 55 KeychainSearch::~KeychainSearch() { | 55 KeychainSearch::~KeychainSearch() { |
| 56 if (search_attributes_.attr) { | 56 if (search_attributes_.attr) { |
| 57 free(search_attributes_.attr); | 57 free(search_attributes_.attr); |
| 58 } | 58 } |
| 59 } | 59 } |
| 60 | 60 |
| 61 void KeychainSearch::Init(const char* server, const UInt32& port, | 61 void KeychainSearch::Init(const char* server, const UInt32& port, |
| 62 const SecProtocolType& protocol, | 62 const SecProtocolType& protocol, |
| 63 const SecAuthenticationType& auth_type, | 63 const SecAuthenticationType& auth_type, |
| 64 const char* security_domain, const char* path, | 64 const char* security_domain, const char* path, |
| 65 const char* username) { | 65 const char* username, OSType creator) { |
| 66 // Allocate enough to hold everything we might use. | 66 // Allocate enough to hold everything we might use. |
| 67 const unsigned int kMaxEntryCount = 7; | 67 const unsigned int kMaxEntryCount = 8; |
| 68 search_attributes_.attr = | 68 search_attributes_.attr = |
| 69 static_cast<SecKeychainAttribute*>(calloc(kMaxEntryCount, | 69 static_cast<SecKeychainAttribute*>(calloc(kMaxEntryCount, |
| 70 sizeof(SecKeychainAttribute))); | 70 sizeof(SecKeychainAttribute))); |
| 71 unsigned int entries = 0; | 71 unsigned int entries = 0; |
| 72 // We only use search_attributes_ with SearchCreateFromAttributes, which takes | 72 // We only use search_attributes_ with SearchCreateFromAttributes, which takes |
| 73 // a "const SecKeychainAttributeList *", so we trust that they won't try | 73 // a "const SecKeychainAttributeList *", so we trust that they won't try |
| 74 // to modify the list, and that casting away const-ness is thus safe. | 74 // to modify the list, and that casting away const-ness is thus safe. |
| 75 if (server != NULL) { | 75 if (server != NULL) { |
| 76 DCHECK(entries < kMaxEntryCount); | 76 DCHECK(entries < kMaxEntryCount); |
| 77 search_attributes_.attr[entries].tag = kSecServerItemAttr; | 77 search_attributes_.attr[entries].tag = kSecServerItemAttr; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 ++entries; | 121 ++entries; |
| 122 } | 122 } |
| 123 if (username != NULL) { | 123 if (username != NULL) { |
| 124 DCHECK(entries <= kMaxEntryCount); | 124 DCHECK(entries <= kMaxEntryCount); |
| 125 search_attributes_.attr[entries].tag = kSecAccountItemAttr; | 125 search_attributes_.attr[entries].tag = kSecAccountItemAttr; |
| 126 search_attributes_.attr[entries].length = strlen(username); | 126 search_attributes_.attr[entries].length = strlen(username); |
| 127 search_attributes_.attr[entries].data = | 127 search_attributes_.attr[entries].data = |
| 128 const_cast<void*>(reinterpret_cast<const void*>(username)); | 128 const_cast<void*>(reinterpret_cast<const void*>(username)); |
| 129 ++entries; | 129 ++entries; |
| 130 } | 130 } |
| 131 if (creator != 0) { |
| 132 DCHECK(entries <= kMaxEntryCount); |
| 133 search_attributes_.attr[entries].tag = kSecCreatorItemAttr; |
| 134 search_attributes_.attr[entries].length = sizeof(creator); |
| 135 search_attributes_.attr[entries].data = |
| 136 const_cast<void*>(reinterpret_cast<const void*>(&creator)); |
| 137 ++entries; |
| 138 } |
| 131 search_attributes_.count = entries; | 139 search_attributes_.count = entries; |
| 132 } | 140 } |
| 133 | 141 |
| 134 void KeychainSearch::FindMatchingItems(std::vector<SecKeychainItemRef>* items) { | 142 void KeychainSearch::FindMatchingItems(std::vector<SecKeychainItemRef>* items) { |
| 135 OSStatus result = keychain_->SearchCreateFromAttributes( | 143 OSStatus result = keychain_->SearchCreateFromAttributes( |
| 136 NULL, kSecInternetPasswordItemClass, &search_attributes_, &search_ref_); | 144 NULL, kSecInternetPasswordItemClass, &search_attributes_, &search_ref_); |
| 137 | 145 |
| 138 if (result != noErr) { | 146 if (result != noErr) { |
| 139 LOG(ERROR) << "Keychain lookup failed with error " << result; | 147 LOG(ERROR) << "Keychain lookup failed with error " << result; |
| 140 return; | 148 return; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 form->origin = URLFromComponents(form->ssl_valid, server, port, path); | 329 form->origin = URLFromComponents(form->ssl_valid, server, port, path); |
| 322 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm | 330 // TODO(stuartmorgan): Handle proxies, which need a different signon_realm |
| 323 // format. | 331 // format. |
| 324 form->signon_realm = form->origin.GetOrigin().spec(); | 332 form->signon_realm = form->origin.GetOrigin().spec(); |
| 325 if (form->scheme != PasswordForm::SCHEME_HTML) { | 333 if (form->scheme != PasswordForm::SCHEME_HTML) { |
| 326 form->signon_realm.append(security_domain); | 334 form->signon_realm.append(security_domain); |
| 327 } | 335 } |
| 328 return true; | 336 return true; |
| 329 } | 337 } |
| 330 | 338 |
| 331 bool FormsMatchForMerge(const PasswordForm& form_a, const PasswordForm& form_b, | 339 bool FormsMatchForMerge(const PasswordForm& form_a, |
| 332 bool* path_matches) { | 340 const PasswordForm& form_b) { |
| 333 // We never merge blacklist entries between our store and the keychain. | 341 // We never merge blacklist entries between our store and the keychain. |
| 334 if (form_a.blacklisted_by_user || form_b.blacklisted_by_user) { | 342 if (form_a.blacklisted_by_user || form_b.blacklisted_by_user) { |
| 335 return false; | 343 return false; |
| 336 } | 344 } |
| 337 bool matches = form_a.scheme == form_b.scheme && | 345 return form_a.scheme == form_b.scheme && |
| 338 form_a.signon_realm == form_b.signon_realm && | 346 form_a.signon_realm == form_b.signon_realm && |
| 339 form_a.username_value == form_b.username_value; | 347 form_a.username_value == form_b.username_value; |
| 340 if (matches && path_matches) { | |
| 341 *path_matches = (form_a.origin == form_b.origin); | |
| 342 } | |
| 343 return matches; | |
| 344 } | 348 } |
| 345 | 349 |
| 346 // Returns an the best match for |form| from |keychain_forms|, or NULL if there | 350 // Returns an the best match for |form| from |keychain_forms|, or NULL if there |
| 347 // is no suitable match. | 351 // is no suitable match. |
| 348 PasswordForm* BestKeychainFormForForm( | 352 PasswordForm* BestKeychainFormForForm( |
| 349 const PasswordForm& base_form, | 353 const PasswordForm& base_form, |
| 350 const std::vector<PasswordForm*>* keychain_forms) { | 354 const std::vector<PasswordForm*>* keychain_forms) { |
| 351 PasswordForm* partial_match = NULL; | 355 PasswordForm* partial_match = NULL; |
| 352 for (std::vector<PasswordForm*>::const_iterator i = keychain_forms->begin(); | 356 for (std::vector<PasswordForm*>::const_iterator i = keychain_forms->begin(); |
| 353 i != keychain_forms->end(); ++i) { | 357 i != keychain_forms->end(); ++i) { |
| 354 // TODO(stuartmorgan): We should really be scoring path matches and picking | 358 // TODO(stuartmorgan): We should really be scoring path matches and picking |
| 355 // the best, rather than just checking exact-or-not (although in practice | 359 // the best, rather than just checking exact-or-not (although in practice |
| 356 // keychain items with paths probably came from us). | 360 // keychain items with paths probably came from us). |
| 357 bool path_matches = false; | 361 if (FormsMatchForMerge(base_form, *(*i))) { |
| 358 if (FormsMatchForMerge(base_form, *(*i), &path_matches)) { | 362 if (base_form.origin == (*i)->origin) { |
| 359 if (path_matches) { | |
| 360 return *i; | 363 return *i; |
| 361 } else if (!partial_match) { | 364 } else if (!partial_match) { |
| 362 partial_match = *i; | 365 partial_match = *i; |
| 363 } | 366 } |
| 364 } | 367 } |
| 365 } | 368 } |
| 366 return partial_match; | 369 return partial_match; |
| 367 } | 370 } |
| 368 | 371 |
| 369 void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms, | 372 void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 i = keychain_forms->erase(i); | 412 i = keychain_forms->erase(i); |
| 410 } | 413 } |
| 411 } | 414 } |
| 412 } | 415 } |
| 413 | 416 |
| 414 } // namespace internal_keychain_helpers | 417 } // namespace internal_keychain_helpers |
| 415 | 418 |
| 416 #pragma mark - | 419 #pragma mark - |
| 417 | 420 |
| 418 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( | 421 MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( |
| 419 MacKeychain* keychain) : keychain_(keychain) { | 422 MacKeychain* keychain) : keychain_(keychain), finds_only_owned_(false) { |
| 420 } | 423 } |
| 421 | 424 |
| 422 std::vector<PasswordForm*> | 425 std::vector<PasswordForm*> |
| 423 MacKeychainPasswordFormAdapter::PasswordsMatchingForm( | 426 MacKeychainPasswordFormAdapter::PasswordsMatchingForm( |
| 424 const PasswordForm& query_form) { | 427 const PasswordForm& query_form) { |
| 425 std::vector<SecKeychainItemRef> keychain_items = | 428 std::vector<SecKeychainItemRef> keychain_items = |
| 426 KeychainItemsForFillingForm(query_form); | 429 KeychainItemsForFillingForm(query_form); |
| 427 | 430 |
| 428 std::vector<PasswordForm*> keychain_forms = | 431 std::vector<PasswordForm*> keychain_forms = |
| 429 CreateFormsFromKeychainItems(keychain_items); | 432 CreateFormsFromKeychainItems(keychain_items); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 441 PasswordForm* form = new PasswordForm(); | 444 PasswordForm* form = new PasswordForm(); |
| 442 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 445 internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
| 443 keychain_item, | 446 keychain_item, |
| 444 form); | 447 form); |
| 445 keychain_->Free(keychain_item); | 448 keychain_->Free(keychain_item); |
| 446 return form; | 449 return form; |
| 447 } | 450 } |
| 448 return NULL; | 451 return NULL; |
| 449 } | 452 } |
| 450 | 453 |
| 451 bool MacKeychainPasswordFormAdapter::AddLogin(const PasswordForm& form) { | 454 bool MacKeychainPasswordFormAdapter::AddPassword(const PasswordForm& form) { |
| 452 // We should never be trying to store a blacklist in the keychain. | 455 // We should never be trying to store a blacklist in the keychain. |
| 453 DCHECK(!form.blacklisted_by_user); | 456 DCHECK(!form.blacklisted_by_user); |
| 454 | 457 |
| 455 std::string server; | 458 std::string server; |
| 456 std::string security_domain; | 459 std::string security_domain; |
| 457 int port; | 460 int port; |
| 458 bool is_secure; | 461 bool is_secure; |
| 459 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port, | 462 if (!ExtractSignonRealmComponents(form.signon_realm, &server, &port, |
| 460 &is_secure, &security_domain)) { | 463 &is_secure, &security_domain)) { |
| 461 return false; | 464 return false; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 484 return false; | 487 return false; |
| 485 } | 488 } |
| 486 bool changed = SetKeychainItemPassword(existing_item, password); | 489 bool changed = SetKeychainItemPassword(existing_item, password); |
| 487 keychain_->Free(existing_item); | 490 keychain_->Free(existing_item); |
| 488 return changed; | 491 return changed; |
| 489 } | 492 } |
| 490 | 493 |
| 491 return result == noErr; | 494 return result == noErr; |
| 492 } | 495 } |
| 493 | 496 |
| 497 bool MacKeychainPasswordFormAdapter::RemovePassword(const PasswordForm& form) { |
| 498 SecKeychainItemRef keychain_item = KeychainItemForForm(form); |
| 499 if (keychain_item == NULL) |
| 500 return false; |
| 501 OSStatus result = keychain_->ItemDelete(keychain_item); |
| 502 keychain_->Free(keychain_item); |
| 503 return result == noErr; |
| 504 } |
| 505 |
| 506 void MacKeychainPasswordFormAdapter::SetFindsOnlyOwnedItems( |
| 507 bool finds_only_owned) { |
| 508 finds_only_owned_ = finds_only_owned; |
| 509 } |
| 510 |
| 494 std::vector<PasswordForm*> | 511 std::vector<PasswordForm*> |
| 495 MacKeychainPasswordFormAdapter::CreateFormsFromKeychainItems( | 512 MacKeychainPasswordFormAdapter::CreateFormsFromKeychainItems( |
| 496 const std::vector<SecKeychainItemRef>& items) { | 513 const std::vector<SecKeychainItemRef>& items) { |
| 497 std::vector<PasswordForm*> keychain_forms; | 514 std::vector<PasswordForm*> keychain_forms; |
| 498 for (std::vector<SecKeychainItemRef>::const_iterator i = items.begin(); | 515 for (std::vector<SecKeychainItemRef>::const_iterator i = items.begin(); |
| 499 i != items.end(); ++i) { | 516 i != items.end(); ++i) { |
| 500 PasswordForm* form = new PasswordForm(); | 517 PasswordForm* form = new PasswordForm(); |
| 501 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, | 518 if (internal_keychain_helpers::FillPasswordFormFromKeychainItem(*keychain_, |
| 502 *i, form)) { | 519 *i, form)) { |
| 503 keychain_forms.push_back(form); | 520 keychain_forms.push_back(form); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 // TODO(stuartmorgan): Proxies will currently fail here, since their | 569 // TODO(stuartmorgan): Proxies will currently fail here, since their |
| 553 // signon_realm is not a URL. We need to detect the proxy case and handle | 570 // signon_realm is not a URL. We need to detect the proxy case and handle |
| 554 // it specially. | 571 // it specially. |
| 555 return matches; | 572 return matches; |
| 556 } | 573 } |
| 557 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS | 574 SecProtocolType protocol = is_secure ? kSecProtocolTypeHTTPS |
| 558 : kSecProtocolTypeHTTP; | 575 : kSecProtocolTypeHTTP; |
| 559 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); | 576 SecAuthenticationType auth_type = AuthTypeForScheme(scheme); |
| 560 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? | 577 const char* auth_domain = (scheme == PasswordForm::SCHEME_HTML) ? |
| 561 NULL : security_domain.c_str(); | 578 NULL : security_domain.c_str(); |
| 579 OSType creator = finds_only_owned_ ? kChromeKeychainCreatorCode : 0; |
| 562 | 580 |
| 563 KeychainSearch keychain_search(*keychain_); | 581 KeychainSearch keychain_search(*keychain_); |
| 564 keychain_search.Init(server.c_str(), port, protocol, auth_type, | 582 keychain_search.Init(server.c_str(), port, protocol, auth_type, |
| 565 auth_domain, path, username); | 583 auth_domain, path, username, creator); |
| 566 keychain_search.FindMatchingItems(&matches); | 584 keychain_search.FindMatchingItems(&matches); |
| 567 return matches; | 585 return matches; |
| 568 } | 586 } |
| 569 | 587 |
| 570 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. | 588 // TODO(stuartmorgan): signon_realm for proxies is not yet supported. |
| 571 bool MacKeychainPasswordFormAdapter::ExtractSignonRealmComponents( | 589 bool MacKeychainPasswordFormAdapter::ExtractSignonRealmComponents( |
| 572 const std::string& signon_realm, std::string* server, int* port, | 590 const std::string& signon_realm, std::string* server, int* port, |
| 573 bool* is_secure, std::string* security_domain) { | 591 bool* is_secure, std::string* security_domain) { |
| 574 // The signon_realm will be the Origin portion of a URL for an HTML form, | 592 // The signon_realm will be the Origin portion of a URL for an HTML form, |
| 575 // and the same but with the security domain as a path for HTTP auth. | 593 // and the same but with the security domain as a path for HTTP auth. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 | 651 |
| 634 PasswordStoreMac::~PasswordStoreMac() {} | 652 PasswordStoreMac::~PasswordStoreMac() {} |
| 635 | 653 |
| 636 void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) { | 654 void PasswordStoreMac::AddLoginImpl(const PasswordForm& form) { |
| 637 if (AddToKeychainIfNecessary(form)) { | 655 if (AddToKeychainIfNecessary(form)) { |
| 638 login_metadata_db_->AddLogin(form); | 656 login_metadata_db_->AddLogin(form); |
| 639 } | 657 } |
| 640 } | 658 } |
| 641 | 659 |
| 642 void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) { | 660 void PasswordStoreMac::UpdateLoginImpl(const PasswordForm& form) { |
| 643 // The keychain AddLogin will update if there is a collision and add if there | 661 // The keychain add will update if there is a collision and add if there |
| 644 // isn't, which is the behavior we want, so there's no separate UpdateLogin. | 662 // isn't, which is the behavior we want, so there's no separate update call. |
| 645 if (AddToKeychainIfNecessary(form)) { | 663 if (AddToKeychainIfNecessary(form)) { |
| 646 int update_count = 0; | 664 int update_count = 0; |
| 647 login_metadata_db_->UpdateLogin(form, &update_count); | 665 login_metadata_db_->UpdateLogin(form, &update_count); |
| 648 // Update will catch any database entries that we already had, but we could | 666 // Update will catch any database entries that we already had, but we could |
| 649 // also be updating a keychain-only form, in which case we need to add. | 667 // also be updating a keychain-only form, in which case we need to add. |
| 650 if (update_count == 0) { | 668 if (update_count == 0) { |
| 651 login_metadata_db_->AddLogin(form); | 669 login_metadata_db_->AddLogin(form); |
| 652 } | 670 } |
| 653 } | 671 } |
| 654 } | 672 } |
| 655 | 673 |
| 656 void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) { | 674 void PasswordStoreMac::RemoveLoginImpl(const PasswordForm& form) { |
| 657 NOTIMPLEMENTED(); | 675 login_metadata_db_->RemoveLogin(form); |
| 676 |
| 677 // See if we own a Keychain item associated with this item. We can do an exact |
| 678 // search rather than messing around with trying to do fuzzy matching because |
| 679 // passwords that we created will always have an exact-match database entry. |
| 680 // (If a user does lose their profile but not their keychain we'll treat the |
| 681 // entries we find like other imported entries anyway, so it's reasonable to |
| 682 // handle deletes on them the way we would for an imported item.) |
| 683 MacKeychainPasswordFormAdapter owned_keychain_adapter(keychain_.get()); |
| 684 owned_keychain_adapter.SetFindsOnlyOwnedItems(true); |
| 685 PasswordForm* owned_password_form = |
| 686 owned_keychain_adapter.PasswordExactlyMatchingForm(form); |
| 687 if (owned_password_form) { |
| 688 // If we don't have other forms using it (i.e., a form differing only by |
| 689 // the names of the form elements), delete the keychain entry. |
| 690 if (!DatabaseHasFormMatchingKeychainForm(form)) { |
| 691 owned_keychain_adapter.RemovePassword(form); |
| 692 } |
| 693 } |
| 658 } | 694 } |
| 659 | 695 |
| 660 void PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( | 696 void PasswordStoreMac::RemoveLoginsCreatedBetweenImpl( |
| 661 const base::Time& delete_begin, const base::Time& delete_end) { | 697 const base::Time& delete_begin, const base::Time& delete_end) { |
| 662 NOTIMPLEMENTED(); | 698 NOTIMPLEMENTED(); |
| 663 } | 699 } |
| 664 | 700 |
| 665 void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request, | 701 void PasswordStoreMac::GetLoginsImpl(GetLoginsRequest* request, |
| 666 const webkit_glue::PasswordForm& form) { | 702 const webkit_glue::PasswordForm& form) { |
| 667 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); | 703 MacKeychainPasswordFormAdapter keychain_adapter(keychain_.get()); |
| 668 std::vector<PasswordForm*> keychain_forms = | 704 std::vector<PasswordForm*> keychain_forms = |
| 669 keychainAdapter.PasswordsMatchingForm(form); | 705 keychain_adapter.PasswordsMatchingForm(form); |
| 670 | 706 |
| 671 std::vector<PasswordForm*> database_forms; | 707 std::vector<PasswordForm*> database_forms; |
| 672 login_metadata_db_->GetLogins(form, &database_forms); | 708 login_metadata_db_->GetLogins(form, &database_forms); |
| 673 | 709 |
| 674 std::vector<PasswordForm*> merged_forms; | 710 std::vector<PasswordForm*> merged_forms; |
| 675 internal_keychain_helpers::MergePasswordForms(&keychain_forms, | 711 internal_keychain_helpers::MergePasswordForms(&keychain_forms, |
| 676 &database_forms, | 712 &database_forms, |
| 677 &merged_forms); | 713 &merged_forms); |
| 678 | 714 |
| 679 // Clean up any orphaned database entries. | 715 // Clean up any orphaned database entries. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 694 | 730 |
| 695 void PasswordStoreMac::GetAllAutofillableLoginsImpl(GetLoginsRequest* request) { | 731 void PasswordStoreMac::GetAllAutofillableLoginsImpl(GetLoginsRequest* request) { |
| 696 NOTIMPLEMENTED(); | 732 NOTIMPLEMENTED(); |
| 697 } | 733 } |
| 698 | 734 |
| 699 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { | 735 bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { |
| 700 if (form.blacklisted_by_user) { | 736 if (form.blacklisted_by_user) { |
| 701 return true; | 737 return true; |
| 702 } | 738 } |
| 703 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); | 739 MacKeychainPasswordFormAdapter keychainAdapter(keychain_.get()); |
| 704 return keychainAdapter.AddLogin(form); | 740 return keychainAdapter.AddPassword(form); |
| 705 } | 741 } |
| 742 |
| 743 bool PasswordStoreMac::DatabaseHasFormMatchingKeychainForm( |
| 744 const webkit_glue::PasswordForm& form) { |
| 745 bool has_match = false; |
| 746 std::vector<PasswordForm*> database_forms; |
| 747 login_metadata_db_->GetLogins(form, &database_forms); |
| 748 for (std::vector<PasswordForm*>::iterator i = database_forms.begin(); |
| 749 i != database_forms.end(); ++i) { |
| 750 if (internal_keychain_helpers::FormsMatchForMerge(form, **i) && |
| 751 (*i)->origin == form.origin) { |
| 752 has_match = true; |
| 753 break; |
| 754 } |
| 755 } |
| 756 STLDeleteElements(&database_forms); |
| 757 return has_match; |
| 758 } |
| OLD | NEW |