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

Unified Diff: components/autofill/core/browser/webdata/autofill_table.cc

Issue 962673004: [Autofill/Autocomplete Feature] Substring matching instead of prefix matching. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporated Vaclav's review comments. Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
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() {
« no previous file with comments | « components/autofill/core/browser/suggestion.cc ('k') | components/autofill/core/browser/webdata/autofill_table_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698