diff options
-rw-r--r-- | base/string_util.cc | 54 | ||||
-rw-r--r-- | base/string_util.h | 15 | ||||
-rw-r--r-- | base/string_util_unittest.cc | 181 | ||||
-rw-r--r-- | chrome/browser/autofill/address_field.h | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/contact_info.cc | 357 | ||||
-rw-r--r-- | chrome/browser/autofill/contact_info.h | 105 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card_field.h | 4 | ||||
-rw-r--r-- | chrome/browser/autofill/form_group.h | 7 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 4 |
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', |