diff options
Diffstat (limited to 'chrome/browser/autofill')
-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 |
5 files changed, 471 insertions, 6 deletions
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_ |