summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autofill/contact_info.cc
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-04 20:27:25 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-04 20:27:25 +0000
commit6c17851db5843c959c073b606f474434cddf5c19 (patch)
treeca18cefae8e06d37b648dd36a28e3dd2ecddfc5a /chrome/browser/autofill/contact_info.cc
parent5ed7c01ee895b37c12252bc63d769af26f9093ec (diff)
downloadchromium_src-6c17851db5843c959c073b606f474434cddf5c19.zip
chromium_src-6c17851db5843c959c073b606f474434cddf5c19.tar.gz
chromium_src-6c17851db5843c959c073b606f474434cddf5c19.tar.bz2
Implement ContactInfo, the FormGroup that stores contact information.
BUG=none TEST=StringUtilTest.Tokenizer Review URL: http://codereview.chromium.org/502103 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35475 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autofill/contact_info.cc')
-rw-r--r--chrome/browser/autofill/contact_info.cc357
1 files changed, 357 insertions, 0 deletions
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);
+}