OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/password_manager/core/browser/login_database.h" | 5 #include "components/password_manager/core/browser/login_database.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 // You *must* change LoginTableColumns if this query changes. | 570 // You *must* change LoginTableColumns if this query changes. |
571 const std::string sql_query = "SELECT origin_url, action_url, " | 571 const std::string sql_query = "SELECT origin_url, action_url, " |
572 "username_element, username_value, " | 572 "username_element, username_value, " |
573 "password_element, password_value, submit_element, " | 573 "password_element, password_value, submit_element, " |
574 "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " | 574 "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " |
575 "scheme, password_type, possible_usernames, times_used, form_data, " | 575 "scheme, password_type, possible_usernames, times_used, form_data, " |
576 "use_additional_auth, date_synced, display_name, avatar_url, " | 576 "use_additional_auth, date_synced, display_name, avatar_url, " |
577 "federation_url, is_zero_click FROM logins WHERE signon_realm == ? "; | 577 "federation_url, is_zero_click FROM logins WHERE signon_realm == ? "; |
578 sql::Statement s; | 578 sql::Statement s; |
579 const GURL signon_realm(form.signon_realm); | 579 const GURL signon_realm(form.signon_realm); |
580 std::string registered_domain = | 580 std::string registered_domain = GetRegistryControlledDomain(signon_realm); |
581 PSLMatchingHelper::GetRegistryControlledDomain(signon_realm); | 581 PSLDomainMatchMetric psl_domain_match_metric = PSL_DOMAIN_MATCH_NONE; |
582 PSLMatchingHelper::PSLDomainMatchMetric psl_domain_match_metric = | 582 const bool should_PSL_matching_apply = |
583 PSLMatchingHelper::PSL_DOMAIN_MATCH_NONE; | 583 ShouldPSLDomainMatchingApply(registered_domain); |
584 // PSL matching only applies to HTML forms. | 584 // PSL matching only applies to HTML forms. |
585 if (form.scheme == PasswordForm::SCHEME_HTML && | 585 if (form.scheme == PasswordForm::SCHEME_HTML && should_PSL_matching_apply) { |
586 psl_helper_.ShouldPSLDomainMatchingApply(registered_domain)) { | |
587 // We are extending the original SQL query with one that includes more | 586 // We are extending the original SQL query with one that includes more |
588 // possible matches based on public suffix domain matching. Using a regexp | 587 // possible matches based on public suffix domain matching. Using a regexp |
589 // here is just an optimization to not have to parse all the stored entries | 588 // here is just an optimization to not have to parse all the stored entries |
590 // in the |logins| table. The result (scheme, domain and port) is verified | 589 // in the |logins| table. The result (scheme, domain and port) is verified |
591 // further down using GURL. See the functions SchemeMatches, | 590 // further down using GURL. See the functions SchemeMatches, |
592 // RegistryControlledDomainMatches and PortMatches. | 591 // RegistryControlledDomainMatches and PortMatches. |
593 const std::string extended_sql_query = | 592 const std::string extended_sql_query = |
594 sql_query + "OR signon_realm REGEXP ? "; | 593 sql_query + "OR signon_realm REGEXP ? "; |
595 // TODO(nyquist) Re-enable usage of GetCachedStatement when | 594 // TODO(nyquist) Re-enable usage of GetCachedStatement when |
596 // http://crbug.com/248608 is fixed. | 595 // http://crbug.com/248608 is fixed. |
597 s.Assign(db_.GetUniqueStatement(extended_sql_query.c_str())); | 596 s.Assign(db_.GetUniqueStatement(extended_sql_query.c_str())); |
598 // We need to escape . in the domain. Since the domain has already been | 597 // We need to escape . in the domain. Since the domain has already been |
599 // sanitized using GURL, we do not need to escape any other characters. | 598 // sanitized using GURL, we do not need to escape any other characters. |
600 base::ReplaceChars(registered_domain, ".", "\\.", ®istered_domain); | 599 base::ReplaceChars(registered_domain, ".", "\\.", ®istered_domain); |
601 std::string scheme = signon_realm.scheme(); | 600 std::string scheme = signon_realm.scheme(); |
602 // We need to escape . in the scheme. Since the scheme has already been | 601 // We need to escape . in the scheme. Since the scheme has already been |
603 // sanitized using GURL, we do not need to escape any other characters. | 602 // sanitized using GURL, we do not need to escape any other characters. |
604 // The scheme soap.beep is an example with '.'. | 603 // The scheme soap.beep is an example with '.'. |
605 base::ReplaceChars(scheme, ".", "\\.", &scheme); | 604 base::ReplaceChars(scheme, ".", "\\.", &scheme); |
606 const std::string port = signon_realm.port(); | 605 const std::string port = signon_realm.port(); |
607 // For a signon realm such as http://foo.bar/, this regexp will match | 606 // For a signon realm such as http://foo.bar/, this regexp will match |
608 // domains on the form http://foo.bar/, http://www.foo.bar/, | 607 // domains on the form http://foo.bar/, http://www.foo.bar/, |
609 // http://www.mobile.foo.bar/. It will not match http://notfoo.bar/. | 608 // http://www.mobile.foo.bar/. It will not match http://notfoo.bar/. |
610 // The scheme and port has to be the same as the observed form. | 609 // The scheme and port has to be the same as the observed form. |
611 std::string regexp = "^(" + scheme + ":\\/\\/)([\\w-]+\\.)*" + | 610 std::string regexp = "^(" + scheme + ":\\/\\/)([\\w-]+\\.)*" + |
612 registered_domain + "(:" + port + ")?\\/$"; | 611 registered_domain + "(:" + port + ")?\\/$"; |
613 s.BindString(0, form.signon_realm); | 612 s.BindString(0, form.signon_realm); |
614 s.BindString(1, regexp); | 613 s.BindString(1, regexp); |
615 } else { | 614 } else { |
616 psl_domain_match_metric = PSLMatchingHelper::PSL_DOMAIN_MATCH_DISABLED; | 615 psl_domain_match_metric = PSL_DOMAIN_MATCH_NOT_USED; |
617 s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, sql_query.c_str())); | 616 s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, sql_query.c_str())); |
618 s.BindString(0, form.signon_realm); | 617 s.BindString(0, form.signon_realm); |
619 } | 618 } |
620 | 619 |
621 while (s.Step()) { | 620 while (s.Step()) { |
622 scoped_ptr<PasswordForm> new_form(new PasswordForm()); | 621 scoped_ptr<PasswordForm> new_form(new PasswordForm()); |
623 EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s); | 622 EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s); |
624 if (result == ENCRYPTION_RESULT_SERVICE_FAILURE) | 623 if (result == ENCRYPTION_RESULT_SERVICE_FAILURE) |
625 return false; | 624 return false; |
626 if (result == ENCRYPTION_RESULT_ITEM_FAILURE) | 625 if (result == ENCRYPTION_RESULT_ITEM_FAILURE) |
627 continue; | 626 continue; |
628 DCHECK(result == ENCRYPTION_RESULT_SUCCESS); | 627 DCHECK(result == ENCRYPTION_RESULT_SUCCESS); |
629 if (psl_helper_.IsMatchingEnabled()) { | 628 if (should_PSL_matching_apply) { |
630 if (!PSLMatchingHelper::IsPublicSuffixDomainMatch(new_form->signon_realm, | 629 if (!IsPublicSuffixDomainMatch(new_form->signon_realm, |
631 form.signon_realm)) { | 630 form.signon_realm)) { |
632 // The database returned results that should not match. Skipping result. | 631 // The database returned results that should not match. Skipping result. |
633 continue; | 632 continue; |
634 } | 633 } |
635 if (form.signon_realm != new_form->signon_realm) { | 634 if (form.signon_realm != new_form->signon_realm) { |
636 // Ignore non-HTML matches. | 635 // Ignore non-HTML matches. |
637 if (new_form->scheme != PasswordForm::SCHEME_HTML) | 636 if (new_form->scheme != PasswordForm::SCHEME_HTML) |
638 continue; | 637 continue; |
639 | 638 |
640 psl_domain_match_metric = PSLMatchingHelper::PSL_DOMAIN_MATCH_FOUND; | 639 psl_domain_match_metric = PSL_DOMAIN_MATCH_FOUND; |
641 // This is not a perfect match, so we need to create a new valid result. | 640 // This is not a perfect match, so we need to create a new valid result. |
642 // We do this by copying over origin, signon realm and action from the | 641 // We do this by copying over origin, signon realm and action from the |
643 // observed form and setting the original signon realm to what we found | 642 // observed form and setting the original signon realm to what we found |
644 // in the database. We use the fact that |original_signon_realm| is | 643 // in the database. We use the fact that |original_signon_realm| is |
645 // non-empty to communicate that this match was found using public | 644 // non-empty to communicate that this match was found using public |
646 // suffix matching. | 645 // suffix matching. |
647 new_form->original_signon_realm = new_form->signon_realm; | 646 new_form->original_signon_realm = new_form->signon_realm; |
648 new_form->origin = form.origin; | 647 new_form->origin = form.origin; |
649 new_form->signon_realm = form.signon_realm; | 648 new_form->signon_realm = form.signon_realm; |
650 new_form->action = form.action; | 649 new_form->action = form.action; |
651 } | 650 } |
652 } | 651 } |
653 forms->push_back(new_form.release()); | 652 forms->push_back(new_form.release()); |
654 } | 653 } |
655 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", | 654 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PslDomainMatchTriggering", |
656 psl_domain_match_metric, | 655 psl_domain_match_metric, |
657 PSLMatchingHelper::PSL_DOMAIN_MATCH_COUNT); | 656 PSL_DOMAIN_MATCH_COUNT); |
658 return s.Succeeded(); | 657 return s.Succeeded(); |
659 } | 658 } |
660 | 659 |
661 bool LoginDatabase::GetLoginsCreatedBetween( | 660 bool LoginDatabase::GetLoginsCreatedBetween( |
662 const base::Time begin, | 661 const base::Time begin, |
663 const base::Time end, | 662 const base::Time end, |
664 std::vector<autofill::PasswordForm*>* forms) const { | 663 std::vector<autofill::PasswordForm*>* forms) const { |
665 DCHECK(forms); | 664 DCHECK(forms); |
666 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, | 665 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, |
667 "SELECT origin_url, action_url, " | 666 "SELECT origin_url, action_url, " |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 | 762 |
764 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { | 763 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { |
765 DCHECK(db_.is_open()); | 764 DCHECK(db_.is_open()); |
766 meta_table_.Reset(); | 765 meta_table_.Reset(); |
767 db_.Close(); | 766 db_.Close(); |
768 sql::Connection::Delete(db_path_); | 767 sql::Connection::Delete(db_path_); |
769 return Init(db_path_); | 768 return Init(db_path_); |
770 } | 769 } |
771 | 770 |
772 } // namespace password_manager | 771 } // namespace password_manager |
OLD | NEW |