Chromium Code Reviews| 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..88d845eba1bf025474d78ef159bccc0dcffacec4 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,30 @@ 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::string16::const_iterator it = escape_wildcards.begin(); |
|
please use gerrit instead
2015/07/06 20:15:17
Please use a c++11 loop, like this:
for (base::ch
Pritam Nikam
2015/07/07 16:18:31
Done.
|
| + it != escape_wildcards.end(); ++it) { |
| + size_t pos = 0; |
| + while ((pos = result.find(*it, pos)) != base::string16::npos) { |
| + result.insert(result.begin() + pos, escaper); |
| + pos += 2; |
| + } |
|
please use gerrit instead
2015/07/06 20:15:17
Lines 387-391 are a for loop in disguise. Let's us
Pritam Nikam
2015/07/07 16:18:31
Done.
|
| + } |
| + |
| + return result; |
| +} |
| + |
| } // namespace |
| // The maximum length allowed for form data. |
| @@ -456,9 +482,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 +493,63 @@ 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 '!' ) " |
|
please use gerrit instead
2015/07/06 20:15:17
Please add a space between '%' and ESCAPE.
Pritam Nikam
2015/07/07 16:18:31
Done.
|
| + "ORDER BY count DESC " |
| + "LIMIT ?")); |
| + |
| + s2.BindString16(0, name); |
| + s2.BindString16(1, Substitute(prefix_lower, ASCIIToUTF16("_%"), L'!')); |
|
please use gerrit instead
2015/07/06 20:15:17
Please use 0x21, which is a base::char16, instead
Pritam Nikam
2015/07/07 16:18:31
Done.
|
| + s2.BindInt(2, limit); |
| + |
| + // Append substring matched suggestions. |
|
please use gerrit instead
2015/07/06 20:15:17
It's clear what's going on without this comment.
Pritam Nikam
2015/07/07 16:18:31
Done.
|
| + 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() { |