summaryrefslogtreecommitdiffstats
path: root/components/autofill/core/browser/phone_number.cc
diff options
context:
space:
mode:
Diffstat (limited to 'components/autofill/core/browser/phone_number.cc')
-rw-r--r--components/autofill/core/browser/phone_number.cc246
1 files changed, 246 insertions, 0 deletions
diff --git a/components/autofill/core/browser/phone_number.cc b/components/autofill/core/browser/phone_number.cc
new file mode 100644
index 0000000..9dc1b34
--- /dev/null
+++ b/components/autofill/core/browser/phone_number.cc
@@ -0,0 +1,246 @@
+// Copyright 2013 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 "components/autofill/core/browser/phone_number.h"
+
+#include "base/basictypes.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/phone_number_i18n.h"
+
+namespace autofill {
+namespace {
+
+const char16 kPhoneNumberSeparators[] = { ' ', '.', '(', ')', '-', 0 };
+
+// The number of digits in a phone number.
+const size_t kPhoneNumberLength = 7;
+
+// The number of digits in an area code.
+const size_t kPhoneCityCodeLength = 3;
+
+void StripPunctuation(base::string16* number) {
+ RemoveChars(*number, kPhoneNumberSeparators, number);
+}
+
+// Returns the region code for this phone number, which is an ISO 3166 2-letter
+// country code. The returned value is based on the |profile|; if the |profile|
+// does not have a country code associated with it, falls back to the country
+// code corresponding to the |app_locale|.
+std::string GetRegion(const AutofillProfile& profile,
+ const std::string& app_locale) {
+ base::string16 country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
+ if (!country_code.empty())
+ return UTF16ToASCII(country_code);
+
+ return AutofillCountry::CountryCodeForLocale(app_locale);
+}
+
+} // namespace
+
+PhoneNumber::PhoneNumber(AutofillProfile* profile)
+ : profile_(profile) {
+}
+
+PhoneNumber::PhoneNumber(const PhoneNumber& number)
+ : profile_(NULL) {
+ *this = number;
+}
+
+PhoneNumber::~PhoneNumber() {}
+
+PhoneNumber& PhoneNumber::operator=(const PhoneNumber& number) {
+ if (this == &number)
+ return *this;
+
+ number_ = number.number_;
+ profile_ = number.profile_;
+ cached_parsed_phone_ = number.cached_parsed_phone_;
+ return *this;
+}
+
+void PhoneNumber::GetSupportedTypes(FieldTypeSet* supported_types) const {
+ supported_types->insert(PHONE_HOME_WHOLE_NUMBER);
+ supported_types->insert(PHONE_HOME_NUMBER);
+ supported_types->insert(PHONE_HOME_CITY_CODE);
+ supported_types->insert(PHONE_HOME_CITY_AND_NUMBER);
+ supported_types->insert(PHONE_HOME_COUNTRY_CODE);
+}
+
+base::string16 PhoneNumber::GetRawInfo(AutofillFieldType type) const {
+ type = AutofillType::GetEquivalentFieldType(type);
+ if (type == PHONE_HOME_WHOLE_NUMBER)
+ return number_;
+
+ // Only the whole number is available as raw data. All of the other types are
+ // parsed from this raw info, and parsing requires knowledge of the phone
+ // number's region, which is only available via GetInfo().
+ return base::string16();
+}
+
+void PhoneNumber::SetRawInfo(AutofillFieldType type,
+ const base::string16& value) {
+ type = AutofillType::GetEquivalentFieldType(type);
+ if (type != PHONE_HOME_CITY_AND_NUMBER &&
+ type != PHONE_HOME_WHOLE_NUMBER) {
+ // Only full phone numbers should be set directly. The remaining field
+ // field types are read-only.
+ return;
+ }
+
+ number_ = value;
+
+ // Invalidate the cached number.
+ cached_parsed_phone_ = i18n::PhoneObject();
+}
+
+// Normalize phones if |type| is a whole number:
+// (650)2345678 -> 6502345678
+// 1-800-FLOWERS -> 18003569377
+// If the phone cannot be normalized, returns the stored value verbatim.
+base::string16 PhoneNumber::GetInfo(AutofillFieldType type,
+ const std::string& app_locale) const {
+ type = AutofillType::GetEquivalentFieldType(type);
+ UpdateCacheIfNeeded(app_locale);
+
+ // Queries for whole numbers will return the non-normalized number if
+ // normalization for the number fails. All other field types require
+ // normalization.
+ if (type != PHONE_HOME_WHOLE_NUMBER && !cached_parsed_phone_.IsValidNumber())
+ return base::string16();
+
+ switch (type) {
+ case PHONE_HOME_WHOLE_NUMBER:
+ return cached_parsed_phone_.GetWholeNumber();
+
+ case PHONE_HOME_NUMBER:
+ return cached_parsed_phone_.number();
+
+ case PHONE_HOME_CITY_CODE:
+ return cached_parsed_phone_.city_code();
+
+ case PHONE_HOME_COUNTRY_CODE:
+ return cached_parsed_phone_.country_code();
+
+ case PHONE_HOME_CITY_AND_NUMBER:
+ return
+ cached_parsed_phone_.city_code() + cached_parsed_phone_.number();
+
+ default:
+ NOTREACHED();
+ return base::string16();
+ }
+}
+
+bool PhoneNumber::SetInfo(AutofillFieldType type,
+ const base::string16& value,
+ const std::string& app_locale) {
+ type = AutofillType::GetEquivalentFieldType(type);
+ SetRawInfo(type, value);
+
+ if (number_.empty())
+ return true;
+
+ // Store a formatted (i.e., pretty printed) version of the number.
+ UpdateCacheIfNeeded(app_locale);
+ number_ = cached_parsed_phone_.GetFormattedNumber();
+ return !number_.empty();
+}
+
+void PhoneNumber::GetMatchingTypes(const base::string16& text,
+ const std::string& app_locale,
+ FieldTypeSet* matching_types) const {
+ base::string16 stripped_text = text;
+ StripPunctuation(&stripped_text);
+ FormGroup::GetMatchingTypes(stripped_text, app_locale, matching_types);
+
+ // For US numbers, also compare to the three-digit prefix and the four-digit
+ // suffix, since web sites often split numbers into these two fields.
+ base::string16 number = GetInfo(PHONE_HOME_NUMBER, app_locale);
+ if (GetRegion(*profile_, app_locale) == "US" &&
+ number.size() == (kPrefixLength + kSuffixLength)) {
+ base::string16 prefix = number.substr(kPrefixOffset, kPrefixLength);
+ base::string16 suffix = number.substr(kSuffixOffset, kSuffixLength);
+ if (text == prefix || text == suffix)
+ matching_types->insert(PHONE_HOME_NUMBER);
+ }
+
+ base::string16 whole_number = GetInfo(PHONE_HOME_WHOLE_NUMBER, app_locale);
+ if (!whole_number.empty()) {
+ base::string16 normalized_number =
+ i18n::NormalizePhoneNumber(text, GetRegion(*profile_, app_locale));
+ if (normalized_number == whole_number)
+ matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
+ }
+}
+
+void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
+ std::string region = GetRegion(*profile_, app_locale);
+ if (!number_.empty() && cached_parsed_phone_.region() != region)
+ cached_parsed_phone_ = i18n::PhoneObject(number_, region);
+}
+
+PhoneNumber::PhoneCombineHelper::PhoneCombineHelper() {
+}
+
+PhoneNumber::PhoneCombineHelper::~PhoneCombineHelper() {
+}
+
+bool PhoneNumber::PhoneCombineHelper::SetInfo(AutofillFieldType field_type,
+ const base::string16& value) {
+ field_type = AutofillType::GetEquivalentFieldType(field_type);
+ if (field_type == PHONE_HOME_COUNTRY_CODE) {
+ country_ = value;
+ return true;
+ }
+
+ if (field_type == PHONE_HOME_CITY_CODE) {
+ city_ = value;
+ return true;
+ }
+
+ if (field_type == PHONE_HOME_CITY_AND_NUMBER) {
+ phone_ = value;
+ return true;
+ }
+
+ if (field_type == PHONE_HOME_WHOLE_NUMBER) {
+ whole_number_ = value;
+ return true;
+ }
+
+ if (field_type == PHONE_HOME_NUMBER) {
+ phone_.append(value);
+ return true;
+ }
+
+ return false;
+}
+
+bool PhoneNumber::PhoneCombineHelper::ParseNumber(
+ const AutofillProfile& profile,
+ const std::string& app_locale,
+ base::string16* value) {
+ if (IsEmpty())
+ return false;
+
+ if (!whole_number_.empty()) {
+ *value = whole_number_;
+ return true;
+ }
+
+ return i18n::ConstructPhoneNumber(
+ country_, city_, phone_, GetRegion(profile, app_locale), value);
+}
+
+bool PhoneNumber::PhoneCombineHelper::IsEmpty() const {
+ return phone_.empty() && whole_number_.empty();
+}
+
+} // namespace autofill