summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/string_util.cc54
-rw-r--r--base/string_util.h15
-rw-r--r--base/string_util_unittest.cc181
-rw-r--r--chrome/browser/autofill/address_field.h4
-rw-r--r--chrome/browser/autofill/contact_info.cc357
-rw-r--r--chrome/browser/autofill/contact_info.h105
-rw-r--r--chrome/browser/autofill/credit_card_field.h4
-rw-r--r--chrome/browser/autofill/form_group.h7
-rwxr-xr-xchrome/chrome_browser.gypi4
9 files changed, 671 insertions, 60 deletions
diff --git a/base/string_util.cc b/base/string_util.cc
index b38e182..abbfd57 100644
--- a/base/string_util.cc
+++ b/base/string_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -293,7 +293,6 @@ namespace base {
bool IsWprintfFormatPortable(const wchar_t* format) {
for (const wchar_t* position = format; *position != '\0'; ++position) {
-
if (*position == '%') {
bool in_specification = true;
bool modifier_l = false;
@@ -322,7 +321,6 @@ bool IsWprintfFormatPortable(const wchar_t* format) {
}
}
}
-
}
return true;
@@ -816,9 +814,9 @@ bool StartsWithASCII(const std::string& str,
template <typename STR>
bool StartsWithT(const STR& str, const STR& search, bool case_sensitive) {
- if (case_sensitive)
+ if (case_sensitive) {
return str.compare(0, search.length(), search) == 0;
- else {
+ } else {
if (search.size() > str.size())
return false;
return std::equal(search.begin(), search.end(), str.begin(),
@@ -1105,7 +1103,6 @@ namespace {
template <typename STR, typename INT, typename UINT, bool NEG>
struct IntToStringT {
-
// This is to avoid a compiler warning about unary minus on unsigned type.
// For example, say you had the following code:
// template <typename INT>
@@ -1349,6 +1346,47 @@ void SplitStringDontTrim(const std::string& str,
}
template<typename STR>
+static size_t TokenizeT(const STR& str,
+ const STR& delimiters,
+ std::vector<STR>* tokens) {
+ tokens->clear();
+
+ typename STR::size_type start = str.find_first_not_of(delimiters);
+ while (start != STR::npos) {
+ typename STR::size_type end = str.find_first_of(delimiters, start + 1);
+ if (end == STR::npos) {
+ tokens->push_back(str.substr(start));
+ break;
+ } else {
+ tokens->push_back(str.substr(start, end - start));
+ start = str.find_first_not_of(delimiters, end + 1);
+ }
+ }
+
+ return tokens->size();
+}
+
+size_t Tokenize(const std::wstring& str,
+ const std::wstring& delimiters,
+ std::vector<std::wstring>* tokens) {
+ return TokenizeT(str, delimiters, tokens);
+}
+
+#if !defined(WCHAR_T_IS_UTF16)
+size_t Tokenize(const string16& str,
+ const string16& delimiters,
+ std::vector<string16>* tokens) {
+ return TokenizeT(str, delimiters, tokens);
+}
+#endif
+
+size_t Tokenize(const std::string& str,
+ const std::string& delimiters,
+ std::vector<std::string>* tokens) {
+ return TokenizeT(str, delimiters, tokens);
+}
+
+template<typename STR>
static STR JoinStringT(const std::vector<STR>& parts,
typename STR::value_type sep) {
if (parts.size() == 0) return STR();
@@ -1388,7 +1426,7 @@ void SplitStringAlongWhitespaceT(const STR& str, std::vector<STR>* result) {
bool last_was_ws = false;
size_t last_non_ws_start = 0;
for (size_t i = 0; i < length; ++i) {
- switch(str[i]) {
+ switch (str[i]) {
// HTML 5 defines whitespace as: space, tab, LF, line tab, FF, or CR.
case L' ':
case L'\t':
@@ -1559,7 +1597,7 @@ static void EatSameChars(const CHAR** pattern, const CHAR** string) {
template <class CHAR>
static void EatWildcard(const CHAR** pattern) {
- while(**pattern) {
+ while (**pattern) {
if (!IsWildcard(**pattern))
return;
(*pattern)++;
diff --git a/base/string_util.h b/base/string_util.h
index 723242e..f0fa6da 100644
--- a/base/string_util.h
+++ b/base/string_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -547,6 +547,19 @@ void SplitStringDontTrim(const std::string& str,
char s,
std::vector<std::string>* r);
+// Splits a string into its fields delimited by any of the characters in
+// |delimiters|. Each field is added to the |tokens| vector. Returns the
+// number of tokens found.
+size_t Tokenize(const std::wstring& str,
+ const std::wstring& delimiters,
+ std::vector<std::wstring>* tokens);
+size_t Tokenize(const string16& str,
+ const string16& delimiters,
+ std::vector<string16>* tokens);
+size_t Tokenize(const std::string& str,
+ const std::string& delimiters,
+ std::vector<std::string>* tokens);
+
// Does the opposite of SplitString().
std::wstring JoinString(const std::vector<std::wstring>& parts, wchar_t s);
string16 JoinString(const std::vector<string16>& parts, char16 s);
diff --git a/base/string_util_unittest.cc b/base/string_util_unittest.cc
index 76dafa3..7e3062a 100644
--- a/base/string_util_unittest.cc
+++ b/base/string_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -172,7 +172,7 @@ TEST(StringUtilTest, IsStringUTF8) {
EXPECT_TRUE(IsStringUTF8("\xe1\x80\xbf"));
EXPECT_TRUE(IsStringUTF8("\xf1\x80\xa0\xbf"));
EXPECT_TRUE(IsStringUTF8("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"));
- EXPECT_TRUE(IsStringUTF8("\xef\xbb\xbf" "abc")); // UTF-8 BOM
+ EXPECT_TRUE(IsStringUTF8("\xef\xbb\xbf" "abc")); // UTF-8 BOM
// surrogate code points
EXPECT_FALSE(IsStringUTF8("\xed\xa0\x80\xed\xbf\xbf"));
@@ -180,22 +180,22 @@ TEST(StringUtilTest, IsStringUTF8) {
EXPECT_FALSE(IsStringUTF8("\xed\xbf\xbf"));
// overlong sequences
- EXPECT_FALSE(IsStringUTF8("\xc0\x80")); // U+0000
- EXPECT_FALSE(IsStringUTF8("\xc1\x80\xc1\x81")); // "AB"
- EXPECT_FALSE(IsStringUTF8("\xe0\x80\x80")); // U+0000
- EXPECT_FALSE(IsStringUTF8("\xe0\x82\x80")); // U+0080
- EXPECT_FALSE(IsStringUTF8("\xe0\x9f\xbf")); // U+07ff
- EXPECT_FALSE(IsStringUTF8("\xf0\x80\x80\x8D")); // U+000D
- EXPECT_FALSE(IsStringUTF8("\xf0\x80\x82\x91")); // U+0091
- EXPECT_FALSE(IsStringUTF8("\xf0\x80\xa0\x80")); // U+0800
- EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbb\xbf")); // U+FEFF (BOM)
- EXPECT_FALSE(IsStringUTF8("\xf8\x80\x80\x80\xbf")); // U+003F
- EXPECT_FALSE(IsStringUTF8("\xfc\x80\x80\x80\xa0\xa5")); // U+00A5
+ EXPECT_FALSE(IsStringUTF8("\xc0\x80")); // U+0000
+ EXPECT_FALSE(IsStringUTF8("\xc1\x80\xc1\x81")); // "AB"
+ EXPECT_FALSE(IsStringUTF8("\xe0\x80\x80")); // U+0000
+ EXPECT_FALSE(IsStringUTF8("\xe0\x82\x80")); // U+0080
+ EXPECT_FALSE(IsStringUTF8("\xe0\x9f\xbf")); // U+07ff
+ EXPECT_FALSE(IsStringUTF8("\xf0\x80\x80\x8D")); // U+000D
+ EXPECT_FALSE(IsStringUTF8("\xf0\x80\x82\x91")); // U+0091
+ EXPECT_FALSE(IsStringUTF8("\xf0\x80\xa0\x80")); // U+0800
+ EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbb\xbf")); // U+FEFF (BOM)
+ EXPECT_FALSE(IsStringUTF8("\xf8\x80\x80\x80\xbf")); // U+003F
+ EXPECT_FALSE(IsStringUTF8("\xfc\x80\x80\x80\xa0\xa5")); // U+00A5
// Beyond U+10FFFF (the upper limit of Unicode codespace)
- EXPECT_FALSE(IsStringUTF8("\xf4\x90\x80\x80")); // U+110000
- EXPECT_FALSE(IsStringUTF8("\xf8\xa0\xbf\x80\xbf")); // 5 bytes
- EXPECT_FALSE(IsStringUTF8("\xfc\x9c\xbf\x80\xbf\x80")); // 6 bytes
+ EXPECT_FALSE(IsStringUTF8("\xf4\x90\x80\x80")); // U+110000
+ EXPECT_FALSE(IsStringUTF8("\xf8\xa0\xbf\x80\xbf")); // 5 bytes
+ EXPECT_FALSE(IsStringUTF8("\xfc\x9c\xbf\x80\xbf\x80")); // 6 bytes
// BOMs in UTF-16(BE|LE) and UTF-32(BE|LE)
EXPECT_FALSE(IsStringUTF8("\xfe\xff"));
@@ -204,23 +204,23 @@ TEST(StringUtilTest, IsStringUTF8) {
EXPECT_FALSE(IsStringUTF8("\xff\xfe\x00\x00"));
// Non-characters : U+xxFFF[EF] where xx is 0x00 through 0x10 and <FDD0,FDEF>
- EXPECT_FALSE(IsStringUTF8("\xef\xbf\xbe")); // U+FFFE)
- EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbf\xbe")); // U+1FFFE
- EXPECT_FALSE(IsStringUTF8("\xf3\xbf\xbf\xbf")); // U+10FFFF
+ EXPECT_FALSE(IsStringUTF8("\xef\xbf\xbe")); // U+FFFE)
+ EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbf\xbe")); // U+1FFFE
+ EXPECT_FALSE(IsStringUTF8("\xf3\xbf\xbf\xbf")); // U+10FFFF
// This should also be false, but currently we pass them through.
// Disable them for now.
#if 0
- EXPECT_FALSE(IsStringUTF8("\xef\xb7\x90")); // U+FDD0
- EXPECT_FALSE(IsStringUTF8("\xef\xb7\xaf")); // U+FDEF
+ EXPECT_FALSE(IsStringUTF8("\xef\xb7\x90")); // U+FDD0
+ EXPECT_FALSE(IsStringUTF8("\xef\xb7\xaf")); // U+FDEF
#endif
// Strings in legacy encodings. We can certainly make up strings
// in a legacy encoding that are valid in UTF-8, but in real data,
// most of them are invalid as UTF-8.
- EXPECT_FALSE(IsStringUTF8("caf\xe9")); // cafe with U+00E9 in ISO-8859-1
- EXPECT_FALSE(IsStringUTF8("\xb0\xa1\xb0\xa2")); // U+AC00, U+AC001 in EUC-KR
- EXPECT_FALSE(IsStringUTF8("\xa7\x41\xa6\x6e")); // U+4F60 U+597D in Big5
+ EXPECT_FALSE(IsStringUTF8("caf\xe9")); // cafe with U+00E9 in ISO-8859-1
+ EXPECT_FALSE(IsStringUTF8("\xb0\xa1\xb0\xa2")); // U+AC00, U+AC001 in EUC-KR
+ EXPECT_FALSE(IsStringUTF8("\xa7\x41\xa6\x6e")); // U+4F60 U+597D in Big5
// "abc" with U+201[CD] in windows-125[0-8]
EXPECT_FALSE(IsStringUTF8("\x93" "abc\x94"));
// U+0639 U+064E U+0644 U+064E in ISO-8859-6
@@ -446,7 +446,6 @@ struct IntToStringTest {
}
TEST(StringUtilTest, IntToString) {
-
static const IntToStringTest<int> int_tests[] = {
{ 0, "0", "0" },
{ -1, "-1", "4294967295" },
@@ -869,22 +868,22 @@ TEST(StringUtilTest, StringAppendfInt) {
// Make sure that lengths exactly around the initial buffer size are handled
// correctly.
TEST(StringUtilTest, StringPrintfBounds) {
- const int src_len = 1026;
- char src[src_len];
+ const int kSrcLen = 1026;
+ char src[kSrcLen];
for (size_t i = 0; i < arraysize(src); i++)
src[i] = 'A';
- wchar_t srcw[src_len];
+ wchar_t srcw[kSrcLen];
for (size_t i = 0; i < arraysize(srcw); i++)
srcw[i] = 'A';
for (int i = 1; i < 3; i++) {
- src[src_len - i] = 0;
+ src[kSrcLen - i] = 0;
std::string out;
SStringPrintf(&out, "%s", src);
EXPECT_STREQ(src, out.c_str());
- srcw[src_len - i] = 0;
+ srcw[kSrcLen - i] = 0;
std::wstring outw;
SStringPrintf(&outw, L"%ls", srcw);
EXPECT_STREQ(srcw, outw.c_str());
@@ -903,11 +902,12 @@ TEST(StringUtilTest, Grow) {
std::string out;
SStringPrintf(&out, fmt, src, src, src, src, src, src, src);
- char* ref = new char[320000];
+ const int kRefSize = 320000;
+ char* ref = new char[kRefSize];
#if defined(OS_WIN)
- sprintf_s(ref, 320000, fmt, src, src, src, src, src, src, src);
+ sprintf_s(ref, kRefSize, fmt, src, src, src, src, src, src, src);
#elif defined(OS_POSIX)
- snprintf(ref, 320000, fmt, src, src, src, src, src, src, src);
+ snprintf(ref, kRefSize, fmt, src, src, src, src, src, src, src);
#endif
EXPECT_STREQ(ref, out.c_str());
@@ -971,50 +971,50 @@ TEST(StringUtilTest, SplitString) {
std::vector<std::wstring> r;
SplitString(L"a,b,c", L',', &r);
- EXPECT_EQ(3U, r.size());
+ ASSERT_EQ(3U, r.size());
EXPECT_EQ(r[0], L"a");
EXPECT_EQ(r[1], L"b");
EXPECT_EQ(r[2], L"c");
r.clear();
SplitString(L"a, b, c", L',', &r);
- EXPECT_EQ(3U, r.size());
+ ASSERT_EQ(3U, r.size());
EXPECT_EQ(r[0], L"a");
EXPECT_EQ(r[1], L"b");
EXPECT_EQ(r[2], L"c");
r.clear();
SplitString(L"a,,c", L',', &r);
- EXPECT_EQ(3U, r.size());
+ ASSERT_EQ(3U, r.size());
EXPECT_EQ(r[0], L"a");
EXPECT_EQ(r[1], L"");
EXPECT_EQ(r[2], L"c");
r.clear();
SplitString(L"", L'*', &r);
- EXPECT_EQ(1U, r.size());
+ ASSERT_EQ(1U, r.size());
EXPECT_EQ(r[0], L"");
r.clear();
SplitString(L"foo", L'*', &r);
- EXPECT_EQ(1U, r.size());
+ ASSERT_EQ(1U, r.size());
EXPECT_EQ(r[0], L"foo");
r.clear();
SplitString(L"foo ,", L',', &r);
- EXPECT_EQ(2U, r.size());
+ ASSERT_EQ(2U, r.size());
EXPECT_EQ(r[0], L"foo");
EXPECT_EQ(r[1], L"");
r.clear();
SplitString(L",", L',', &r);
- EXPECT_EQ(2U, r.size());
+ ASSERT_EQ(2U, r.size());
EXPECT_EQ(r[0], L"");
EXPECT_EQ(r[1], L"");
r.clear();
SplitString(L"\t\ta\t", L'\t', &r);
- EXPECT_EQ(4U, r.size());
+ ASSERT_EQ(4U, r.size());
EXPECT_EQ(r[0], L"");
EXPECT_EQ(r[1], L"");
EXPECT_EQ(r[2], L"a");
@@ -1022,7 +1022,7 @@ TEST(StringUtilTest, SplitString) {
r.clear();
SplitStringDontTrim(L"\t\ta\t", L'\t', &r);
- EXPECT_EQ(4U, r.size());
+ ASSERT_EQ(4U, r.size());
EXPECT_EQ(r[0], L"");
EXPECT_EQ(r[1], L"");
EXPECT_EQ(r[2], L"a");
@@ -1030,18 +1030,111 @@ TEST(StringUtilTest, SplitString) {
r.clear();
SplitString(L"\ta\t\nb\tcc", L'\n', &r);
- EXPECT_EQ(2U, r.size());
+ ASSERT_EQ(2U, r.size());
EXPECT_EQ(r[0], L"a");
EXPECT_EQ(r[1], L"b\tcc");
r.clear();
SplitStringDontTrim(L"\ta\t\nb\tcc", L'\n', &r);
- EXPECT_EQ(2U, r.size());
+ ASSERT_EQ(2U, r.size());
EXPECT_EQ(r[0], L"\ta\t");
EXPECT_EQ(r[1], L"b\tcc");
r.clear();
}
+// Test for Tokenize
+TEST(StringUtilTest, Tokenize) {
+ std::vector<std::string> r;
+ size_t size;
+
+ size = Tokenize("This is a string", " ", &r);
+ EXPECT_EQ(4U, size);
+ ASSERT_EQ(4U, r.size());
+ EXPECT_EQ(r[0], "This");
+ EXPECT_EQ(r[1], "is");
+ EXPECT_EQ(r[2], "a");
+ EXPECT_EQ(r[3], "string");
+ r.clear();
+
+ size = Tokenize("one,two,three", ",", &r);
+ EXPECT_EQ(3U, size);
+ ASSERT_EQ(3U, r.size());
+ EXPECT_EQ(r[0], "one");
+ EXPECT_EQ(r[1], "two");
+ EXPECT_EQ(r[2], "three");
+ r.clear();
+
+ size = Tokenize("one,two:three;four", ",:", &r);
+ EXPECT_EQ(3U, size);
+ ASSERT_EQ(3U, r.size());
+ EXPECT_EQ(r[0], "one");
+ EXPECT_EQ(r[1], "two");
+ EXPECT_EQ(r[2], "three;four");
+ r.clear();
+
+ size = Tokenize("one,two:three;four", ";,:", &r);
+ EXPECT_EQ(4U, size);
+ ASSERT_EQ(4U, r.size());
+ EXPECT_EQ(r[0], "one");
+ EXPECT_EQ(r[1], "two");
+ EXPECT_EQ(r[2], "three");
+ EXPECT_EQ(r[3], "four");
+ r.clear();
+
+ size = Tokenize("one, two, three", ",", &r);
+ EXPECT_EQ(3U, size);
+ ASSERT_EQ(3U, r.size());
+ EXPECT_EQ(r[0], "one");
+ EXPECT_EQ(r[1], " two");
+ EXPECT_EQ(r[2], " three");
+ r.clear();
+
+ size = Tokenize("one, two, three, ", ",", &r);
+ EXPECT_EQ(4U, size);
+ ASSERT_EQ(4U, r.size());
+ EXPECT_EQ(r[0], "one");
+ EXPECT_EQ(r[1], " two");
+ EXPECT_EQ(r[2], " three");
+ EXPECT_EQ(r[3], " ");
+ r.clear();
+
+ size = Tokenize("one, two, three,", ",", &r);
+ EXPECT_EQ(3U, size);
+ ASSERT_EQ(3U, r.size());
+ EXPECT_EQ(r[0], "one");
+ EXPECT_EQ(r[1], " two");
+ EXPECT_EQ(r[2], " three");
+ r.clear();
+
+ size = Tokenize("", ",", &r);
+ EXPECT_EQ(0U, size);
+ ASSERT_EQ(0U, r.size());
+ r.clear();
+
+ size = Tokenize(",", ",", &r);
+ EXPECT_EQ(0U, size);
+ ASSERT_EQ(0U, r.size());
+ r.clear();
+
+ size = Tokenize(",;:.", ".:;,", &r);
+ EXPECT_EQ(0U, size);
+ ASSERT_EQ(0U, r.size());
+ r.clear();
+
+ size = Tokenize("\t\ta\t", "\t", &r);
+ EXPECT_EQ(1U, size);
+ ASSERT_EQ(1U, r.size());
+ EXPECT_EQ(r[0], "a");
+ r.clear();
+
+ size = Tokenize("\ta\t\nb\tcc", "\n", &r);
+ EXPECT_EQ(2U, size);
+ ASSERT_EQ(2U, r.size());
+ EXPECT_EQ(r[0], "\ta\t");
+ EXPECT_EQ(r[1], "b\tcc");
+ r.clear();
+}
+
// Test for JoinString
TEST(StringUtilTest, JoinString) {
std::vector<std::string> in;
diff --git a/chrome/browser/autofill/address_field.h b/chrome/browser/autofill/address_field.h
index 58ea0de..bd568d8 100644
--- a/chrome/browser/autofill/address_field.h
+++ b/chrome/browser/autofill/address_field.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,7 +15,7 @@ class AutoFillField;
class AddressField : public FormField {
public:
virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const;
- virtual FormFieldType GetFormFieldType() { return kAddressType; }
+ virtual FormFieldType GetFormFieldType() const { return kAddressType; }
virtual int priority() const { return 3; }
static AddressField* Parse(std::vector<AutoFillField*>::const_iterator* iter,
diff --git a/chrome/browser/autofill/contact_info.cc b/chrome/browser/autofill/contact_info.cc
new file mode 100644
index 0000000..9e31b18
--- /dev/null
+++ b/chrome/browser/autofill/contact_info.cc
@@ -0,0 +1,357 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/autofill/contact_info.h"
+
+#include "base/basictypes.h"
+#include "base/string_util.h"
+#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/field_types.h"
+
+static const string16 kNameSplitChars = ASCIIToUTF16("-'. ");
+
+static const AutoFillFieldType kAutoFillContactInfoTypes[] = {
+ NAME_FIRST,
+ NAME_MIDDLE,
+ NAME_LAST,
+ EMAIL_ADDRESS,
+ COMPANY_NAME,
+};
+
+static const size_t kAutoFillContactInfoLength =
+ arraysize(kAutoFillContactInfoTypes);
+
+FormGroup* ContactInfo::Clone() const {
+ return new ContactInfo(*this);
+}
+
+void ContactInfo::GetPossibleFieldTypes(const string16& text,
+ FieldTypeSet* possible_types) const {
+ if (IsFirstName(text))
+ possible_types->insert(NAME_FIRST);
+
+ if (IsMiddleName(text))
+ possible_types->insert(NAME_MIDDLE);
+
+ if (IsLastName(text))
+ possible_types->insert(NAME_LAST);
+
+ if (IsMiddleInitial(text))
+ possible_types->insert(NAME_MIDDLE_INITIAL);
+
+ if (IsSuffix(text))
+ possible_types->insert(NAME_SUFFIX);
+
+ if (IsFullName(text))
+ possible_types->insert(NAME_FULL);
+
+ if (email_ == text)
+ possible_types->insert(EMAIL_ADDRESS);
+
+ if (company_name_ == text)
+ possible_types->insert(COMPANY_NAME);
+}
+
+void ContactInfo::FindInfoMatches(const AutoFillType& type,
+ const string16& info,
+ std::vector<string16>* matched_text) const {
+ if (matched_text == NULL) {
+ DLOG(ERROR) << "NULL matched vector passed in";
+ return;
+ }
+
+ string16 match;
+ if (type.field_type() == UNKNOWN_TYPE) {
+ for (size_t i = 0; i < kAutoFillContactInfoLength; i++) {
+ if (FindInfoMatchesHelper(kAutoFillContactInfoTypes[i], info, &match))
+ matched_text->push_back(match);
+ }
+ } else if (FindInfoMatchesHelper(type.field_type(), info, &match)) {
+ matched_text->push_back(match);
+ }
+}
+
+string16 ContactInfo::GetFieldText(const AutoFillType& type) const {
+ AutoFillFieldType field_type = type.field_type();
+ if (field_type == NAME_FIRST)
+ return first();
+
+ if (field_type == NAME_MIDDLE)
+ return middle();
+
+ if (field_type == NAME_LAST)
+ return last();
+
+ if (field_type == NAME_MIDDLE_INITIAL)
+ MiddleInitial();
+
+ if (field_type == NAME_FULL)
+ return FullName();
+
+ if (field_type == NAME_SUFFIX)
+ return suffix();
+
+ if (field_type == EMAIL_ADDRESS)
+ return email();
+
+ if (field_type == COMPANY_NAME)
+ return company_name();
+
+ return EmptyString16();
+}
+
+void ContactInfo::SetInfo(const AutoFillType& type, const string16& value) {
+ AutoFillFieldType field_type = type.field_type();
+ DCHECK(type.group() == AutoFillType::CONTACT_INFO);
+ if (field_type == NAME_FIRST)
+ SetFirst(value);
+ else if (field_type == NAME_MIDDLE)
+ SetMiddle(value);
+ else if (field_type == NAME_LAST)
+ SetLast(value);
+ else if (field_type == NAME_SUFFIX)
+ set_suffix(value);
+ else if (field_type == EMAIL_ADDRESS)
+ email_ = value;
+ else if (field_type == COMPANY_NAME)
+ company_name_ = value;
+ else
+ NOTREACHED();
+}
+
+string16 ContactInfo::FullName() const {
+ if (first_.empty())
+ return EmptyString16();
+
+ std::vector<string16> full_name;
+ full_name.push_back(first_);
+
+ if (!middle_.empty())
+ full_name.push_back(middle_);
+
+ if (!last_.empty())
+ full_name.push_back(last_);
+
+ if (!suffix_.empty())
+ full_name.push_back(suffix_);
+
+ return JoinString(full_name, ' ');
+}
+
+string16 ContactInfo::MiddleInitial() const {
+ if (middle_.empty())
+ return EmptyString16();
+
+ string16 middle_name(middle());
+ string16 initial;
+ initial.push_back(middle_name[0]);
+ return initial;
+}
+
+ContactInfo::ContactInfo(const ContactInfo& contact_info)
+ : first_tokens_(contact_info.first_tokens_),
+ middle_tokens_(contact_info.middle_tokens_),
+ last_tokens_(contact_info.last_tokens_),
+ first_(contact_info.first_),
+ middle_(contact_info.middle_),
+ last_(contact_info.last_),
+ suffix_(contact_info.suffix_),
+ email_(contact_info.email_),
+ company_name_(contact_info.company_name_) {
+}
+
+bool ContactInfo::FindInfoMatchesHelper(const AutoFillFieldType& field_type,
+ const string16& info,
+ string16* match) const {
+ if (match == NULL) {
+ DLOG(ERROR) << "NULL match string passed in";
+ return false;
+ }
+
+ match->clear();
+ if (field_type == NAME_FIRST &&
+ StartsWith(first(), info, false)) {
+ *match = first();
+ } else if (field_type == NAME_MIDDLE &&
+ StartsWith(middle(), info, false)) {
+ *match = middle();
+ } else if (field_type == NAME_LAST &&
+ StartsWith(last(), info, false)) {
+ *match = last();
+ } else if (field_type == NAME_SUFFIX &&
+ StartsWith(suffix(), info, false)) {
+ *match = suffix();
+ } else if (field_type == NAME_MIDDLE_INITIAL && IsMiddleInitial(info)) {
+ *match = MiddleInitial();
+ } else if (field_type == NAME_FULL &&
+ StartsWith(FullName(), info, false)) {
+ *match = FullName();
+ } else if (field_type == EMAIL_ADDRESS &&
+ StartsWith(email(), info, false)) {
+ *match = email();
+ } else if (field_type == COMPANY_NAME &&
+ StartsWith(company_name(), info, false)) {
+ *match = company_name();
+ }
+
+ return !match->empty();
+}
+
+// If each of the 'words' contained in the text are also present in the first
+// name then we will consider the text to be of type kFirstName. This means
+// that people with multiple first names will be able to enter any one of
+// their first names and have it correctly recognized.
+bool ContactInfo::IsFirstName(const string16& text) const {
+ return IsNameMatch(text, first_tokens_);
+}
+
+// If each of the 'words' contained in the text are also present in the middle
+// name then we will consider the text to be of type kMiddleName.
+bool ContactInfo::IsMiddleName(const string16& text) const {
+ return IsNameMatch(text, middle_tokens_);
+}
+
+// If each of the 'words' contained in the text are also present in the last
+// name then we will consider the text to be of type kLastName.
+bool ContactInfo::IsLastName(const string16& text) const {
+ return IsNameMatch(text, last_tokens_);
+}
+
+bool ContactInfo::IsSuffix(const string16& text) const {
+ string16 lower_suffix = StringToLowerASCII(suffix_);
+ return (lower_suffix == text);
+}
+
+bool ContactInfo::IsMiddleInitial(const string16& text) const {
+ if (text.length() != 1)
+ return false;
+
+ string16 lower_case = StringToLowerASCII(text);
+ // If the text entered was a single character and it matches the first letter
+ // of any of the given middle names then we consider it to be a middle
+ // initial field.
+ size_t middle_tokens_size = middle_tokens_.size();
+ for (size_t i = 0; i < middle_tokens_size; ++i) {
+ if (middle_tokens_[i][0] == lower_case[0])
+ return true;
+ }
+
+ return false;
+}
+
+// A field will be considered to be of type NAME_FULL if:
+// 1) it contains at least one word from the first name.
+// 2) it contains at least one word from the last name.
+// 3) all of the words in the field match a word in either the first,
+// middle, or last name.
+bool ContactInfo::IsFullName(const string16& text) const {
+ size_t first_tokens_size = first_tokens_.size();
+ if (first_tokens_size == 0)
+ return false;
+
+ size_t middle_tokens_size = middle_tokens_.size();
+
+ size_t last_tokens_size = last_tokens_.size();
+ if (last_tokens_size == 0)
+ return false;
+
+ NameTokens text_tokens;
+ Tokenize(text, kNameSplitChars, &text_tokens);
+ size_t text_tokens_size = text_tokens.size();
+ if (text_tokens_size == 0 || text_tokens_size < 2)
+ return false;
+
+ size_t name_tokens_size =
+ first_tokens_size + middle_tokens_size + last_tokens_size;
+ if (text_tokens_size > name_tokens_size)
+ return false;
+
+ bool first_name_match = false;
+ bool last_name_match = false;
+ NameTokens::iterator iter;
+ for (iter = text_tokens.begin(); iter != text_tokens.end(); ++iter) {
+ bool match = false;
+ if (IsWordInName(*iter, first_tokens_)) {
+ match = true;
+ first_name_match = true;
+ }
+
+ if (IsWordInName(*iter, last_tokens_)) {
+ match = true;
+ last_name_match = true;
+ }
+
+ if (IsWordInName(*iter, middle_tokens_))
+ match = true;
+
+ if (!match)
+ return false;
+ }
+
+ return (first_name_match && last_name_match);
+}
+
+bool ContactInfo::IsNameMatch(const string16& text,
+ const NameTokens& name_tokens) const {
+ size_t name_tokens_size = name_tokens.size();
+ if (name_tokens_size == 0)
+ return false;
+
+ NameTokens text_tokens;
+ Tokenize(text, kNameSplitChars, &text_tokens);
+ size_t text_tokens_size = text_tokens.size();
+ if (text_tokens_size == 0)
+ return false;
+
+ if (text_tokens_size > name_tokens_size)
+ return false;
+
+ // If each of the 'words' contained in the text are also present in the name,
+ // then we will consider the text to match the name.
+ NameTokens::iterator iter;
+ for (iter = text_tokens.begin(); iter != text_tokens.end(); ++iter) {
+ if (!IsWordInName(*iter, name_tokens))
+ return false;
+ }
+
+ return true;
+}
+
+bool ContactInfo::IsWordInName(const string16& word,
+ const NameTokens& name_tokens) const {
+ NameTokens::const_iterator iter;
+ for (iter = name_tokens.begin(); iter != name_tokens.end(); ++iter) {
+ if (word == *iter)
+ return true;
+ }
+
+ return false;
+}
+
+void ContactInfo::SetFirst(const string16& first) {
+ first_ = first;
+ first_tokens_.clear();
+ Tokenize(first, kNameSplitChars, &first_tokens_);
+ NameTokens::iterator iter;
+ for (iter = first_tokens_.begin(); iter != first_tokens_.end(); ++iter)
+ *iter = StringToLowerASCII(*iter);
+}
+
+void ContactInfo::SetMiddle(const string16& middle) {
+ middle_ = middle;
+ middle_tokens_.clear();
+ Tokenize(middle, kNameSplitChars, &middle_tokens_);
+ NameTokens::iterator iter;
+ for (iter = middle_tokens_.begin(); iter != middle_tokens_.end(); ++iter)
+ *iter = StringToLowerASCII(*iter);
+}
+
+void ContactInfo::SetLast(const string16& last) {
+ last_ = last;
+ last_tokens_.clear();
+ Tokenize(last, kNameSplitChars, &last_tokens_);
+ NameTokens::iterator iter;
+ for (iter = last_tokens_.begin(); iter != last_tokens_.end(); ++iter)
+ *iter = StringToLowerASCII(*iter);
+}
diff --git a/chrome/browser/autofill/contact_info.h b/chrome/browser/autofill/contact_info.h
new file mode 100644
index 0000000..957e55e
--- /dev/null
+++ b/chrome/browser/autofill/contact_info.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_AUTOFILL_CONTACT_INFO_H_
+#define CHROME_BROWSER_AUTOFILL_CONTACT_INFO_H_
+
+#include <vector>
+
+#include "base/string16.h"
+#include "chrome/browser/autofill/form_group.h"
+
+typedef std::vector<string16> NameTokens;
+
+// A form group that stores contact information.
+class ContactInfo : public FormGroup {
+ public:
+ ContactInfo() {}
+
+ // FormGroup implementation:
+ virtual FormGroup* Clone() const;
+ virtual void GetPossibleFieldTypes(const string16& text,
+ FieldTypeSet* possible_types) const;
+ virtual void FindInfoMatches(const AutoFillType& type,
+ const string16& info,
+ std::vector<string16>* matched_text) const;
+ virtual string16 GetFieldText(const AutoFillType& type) const;
+ virtual void SetInfo(const AutoFillType& type, const string16& value);
+
+ // Returns the full name, which can include up to the first, middle, middle
+ // initial, last name, and suffix.
+ string16 FullName() const;
+
+ string16 first() const { return first_; }
+ string16 middle() const { return middle_; }
+ string16 last() const { return last_; }
+ string16 MiddleInitial() const;
+ string16 suffix() const { return suffix_; }
+ string16 email() const { return email_; }
+ string16 company_name() const { return company_name_; }
+
+ private:
+ explicit ContactInfo(const ContactInfo& contact_info);
+ void operator=(const ContactInfo& info);
+
+ // A helper function for FindInfoMatches that only handles matching the info
+ // with the requested field type.
+ bool FindInfoMatchesHelper(const AutoFillFieldType& field_type,
+ const string16& info,
+ string16* matched_text) const;
+
+ // Returns true if |text| is the first name.
+ bool IsFirstName(const string16& text) const;
+
+ // Returns true if |text| is the middle name.
+ bool IsMiddleName(const string16& text) const;
+
+ // Returns true if |text| is the last name.
+ bool IsLastName(const string16& text) const;
+
+ // Returns true if |text| is the suffix.
+ bool IsSuffix(const string16& text) const;
+
+ // Returns true if |text| is the middle initial.
+ bool IsMiddleInitial(const string16& text) const;
+
+ // Returns true if |text| is the last name.
+ bool IsFullName(const string16& text) const;
+
+ // Returns true if all of the tokens in |text| match the tokens in
+ // |name_tokens|.
+ bool IsNameMatch(const string16& text, const NameTokens& name_tokens) const;
+
+ // Returns true if |word| is one of the tokens in |name_tokens|.
+ bool IsWordInName(const string16& word, const NameTokens& name_tokens) const;
+
+ // Sets |first_| to |first| and |first_tokens_| to the set of tokens in
+ // |first|, made lowercase.
+ void SetFirst(const string16& first);
+
+ // Sets |middle_| to |middle| and |middle_tokens_| to the set of tokens in
+ // |middle|, made lowercase.
+ void SetMiddle(const string16& middle);
+
+ // Sets |last_| to |last| and |last_tokens_| to the set of tokens in |last|,
+ // made lowercase.
+ void SetLast(const string16& last);
+
+ void set_suffix(const string16& suffix) { suffix_ = suffix; }
+
+ // List of tokens in each part of the name.
+ NameTokens first_tokens_;
+ NameTokens middle_tokens_;
+ NameTokens last_tokens_;
+
+ // Contact information data.
+ string16 first_;
+ string16 middle_;
+ string16 last_;
+ string16 suffix_;
+ string16 email_;
+ string16 company_name_;
+};
+
+#endif // CHROME_BROWSER_AUTOFILL_CONTACT_INFO_H_
diff --git a/chrome/browser/autofill/credit_card_field.h b/chrome/browser/autofill/credit_card_field.h
index 4fed417..d870db7 100644
--- a/chrome/browser/autofill/credit_card_field.h
+++ b/chrome/browser/autofill/credit_card_field.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,7 +15,7 @@ class CreditCardField : public FormField {
public:
// FormField implementation:
virtual bool GetFieldInfo(FieldTypeMap* field_type_map) const;
- virtual FormFieldType GetFormFieldType() { return kCreditCardType; }
+ virtual FormFieldType GetFormFieldType() const { return kCreditCardType; }
virtual int priority() const { return 4; }
static CreditCardField* Parse(
diff --git a/chrome/browser/autofill/form_group.h b/chrome/browser/autofill/form_group.h
index 60250da..042ae0d 100644
--- a/chrome/browser/autofill/form_group.h
+++ b/chrome/browser/autofill/form_group.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -8,6 +8,9 @@
#include <vector>
#include "base/string16.h"
+#include "base/string_util.h"
+#include "chrome/browser/autofill/autofill_type.h"
+#include "chrome/browser/autofill/field_types.h"
// This class is an interface for collections of form fields, grouped by type.
// The information in objects of this class is managed by the
@@ -46,7 +49,7 @@ class FormGroup {
// Returns the label for this FormGroup item. This should be overridden for
// form group items that implement a label.
- virtual string16 Label() const { return EmptyString(); }
+ virtual string16 Label() const { return EmptyString16(); }
};
#endif // CHROME_BROWSER_AUTOFILL_FORM_GROUP_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 926d6e20..8af16a2 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1,4 +1,4 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -90,6 +90,8 @@
'browser/autofill/autofill_manager.h',
'browser/autofill/autofill_type.cc',
'browser/autofill/autofill_type.h',
+ 'browser/autofill/contact_info.cc',
+ 'browser/autofill/contact_info.h',
'browser/autofill/credit_card_field.cc',
'browser/autofill/credit_card_field.h',
'browser/autofill/field_types.h',