| Index: components/autofill/core/browser/webdata/autofill_table.cc
|
| diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
|
| index c337f60223f165cecc20a75e0ae7808ddaf7f800..2ee8455b1ad28d875ce0756145de7afd5be54dd8 100644
|
| --- a/components/autofill/core/browser/webdata/autofill_table.cc
|
| +++ b/components/autofill/core/browser/webdata/autofill_table.cc
|
| @@ -18,6 +18,7 @@
|
| #include "base/logging.h"
|
| #include "base/numerics/safe_conversions.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/time/time.h"
|
| #include "components/autofill/core/browser/autofill_country.h"
|
| @@ -28,6 +29,7 @@
|
| #include "components/autofill/core/browser/webdata/autofill_change.h"
|
| #include "components/autofill/core/browser/webdata/autofill_entry.h"
|
| #include "components/autofill/core/common/autofill_switches.h"
|
| +#include "components/autofill/core/common/autofill_util.h"
|
| #include "components/autofill/core/common/form_field_data.h"
|
| #include "components/os_crypt/os_crypt.h"
|
| #include "components/webdata/common/web_database.h"
|
| @@ -368,6 +370,28 @@ CreditCard::ServerStatus ServerStatusStringToEnum(const std::string& status) {
|
| return CreditCard::OK;
|
| }
|
|
|
| +// Returns |s| with |escaper| in front of each of occurrence of a character from
|
| +// |special_chars|. Any occurrence of |escaper| in |s| is doubled. For example,
|
| +// Substitute("hello_world!", "_%", '!'') returns "hello!_world!!".
|
| +base::string16 Substitute(const base::string16& s,
|
| + const base::string16& special_chars,
|
| + const base::char16& escaper) {
|
| + // Prepend |escaper| to the list of |special_chars|.
|
| + base::string16 escape_wildcards(special_chars);
|
| + escape_wildcards.insert(escape_wildcards.begin(), escaper);
|
| +
|
| + // Prepend the |escaper| just before |special_chars| in |s|.
|
| + base::string16 result(s);
|
| + for (base::char16 c : escape_wildcards) {
|
| + for (size_t pos = 0; (pos = result.find(c, pos)) != base::string16::npos;
|
| + pos += 2) {
|
| + result.insert(result.begin() + pos, escaper);
|
| + }
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| } // namespace
|
|
|
| // The maximum length allowed for form data.
|
| @@ -456,9 +480,10 @@ bool AutofillTable::GetFormValuesForElementName(
|
| std::vector<base::string16>* values,
|
| int limit) {
|
| DCHECK(values);
|
| - sql::Statement s;
|
| + bool succeeded = false;
|
|
|
| if (prefix.empty()) {
|
| + sql::Statement s;
|
| s.Assign(db_->GetUniqueStatement(
|
| "SELECT value FROM autofill "
|
| "WHERE name = ? "
|
| @@ -466,28 +491,62 @@ bool AutofillTable::GetFormValuesForElementName(
|
| "LIMIT ?"));
|
| s.BindString16(0, name);
|
| s.BindInt(1, limit);
|
| +
|
| + values->clear();
|
| + while (s.Step())
|
| + values->push_back(s.ColumnString16(0));
|
| +
|
| + succeeded = s.Succeeded();
|
| } else {
|
| base::string16 prefix_lower = base::i18n::ToLower(prefix);
|
| base::string16 next_prefix = prefix_lower;
|
| next_prefix[next_prefix.length() - 1]++;
|
|
|
| - s.Assign(db_->GetUniqueStatement(
|
| + sql::Statement s1;
|
| + s1.Assign(db_->GetUniqueStatement(
|
| "SELECT value FROM autofill "
|
| "WHERE name = ? AND "
|
| "value_lower >= ? AND "
|
| "value_lower < ? "
|
| "ORDER BY count DESC "
|
| "LIMIT ?"));
|
| - s.BindString16(0, name);
|
| - s.BindString16(1, prefix_lower);
|
| - s.BindString16(2, next_prefix);
|
| - s.BindInt(3, limit);
|
| + s1.BindString16(0, name);
|
| + s1.BindString16(1, prefix_lower);
|
| + s1.BindString16(2, next_prefix);
|
| + s1.BindInt(3, limit);
|
| +
|
| + values->clear();
|
| + while (s1.Step())
|
| + values->push_back(s1.ColumnString16(0));
|
| +
|
| + succeeded = s1.Succeeded();
|
| +
|
| + if (IsFeatureSubstringMatchEnabled()) {
|
| + sql::Statement s2;
|
| + s2.Assign(db_->GetUniqueStatement(
|
| + "SELECT value FROM autofill "
|
| + "WHERE name = ? AND ("
|
| + " value LIKE '% ' || :prefix || '%' ESCAPE '!' OR "
|
| + " value LIKE '%.' || :prefix || '%' ESCAPE '!' OR "
|
| + " value LIKE '%,' || :prefix || '%' ESCAPE '!' OR "
|
| + " value LIKE '%-' || :prefix || '%' ESCAPE '!' OR "
|
| + " value LIKE '%@' || :prefix || '%' ESCAPE '!' OR "
|
| + " value LIKE '%!_' || :prefix || '%' ESCAPE '!' ) "
|
| + "ORDER BY count DESC "
|
| + "LIMIT ?"));
|
| +
|
| + s2.BindString16(0, name);
|
| + // escaper as L'!' -> 0x21.
|
| + s2.BindString16(1, Substitute(prefix_lower, ASCIIToUTF16("_%"), 0x21));
|
| + s2.BindInt(2, limit);
|
| + while (s2.Step())
|
| + values->push_back(s2.ColumnString16(0));
|
| +
|
| + succeeded &= s2.Succeeded();
|
| + }
|
| }
|
|
|
| - values->clear();
|
| - while (s.Step())
|
| - values->push_back(s.ColumnString16(0));
|
| - return s.Succeeded();
|
| + return succeeded;
|
| }
|
|
|
| bool AutofillTable::HasFormElements() {
|
|
|