This source file includes following definitions.
- SanitizeRegion
- IsValidPhoneNumber
- FormatValidatedNumber
- ParsePhoneNumber
- NormalizePhoneNumber
- ConstructPhoneNumber
- PhoneNumbersMatch
- GetFormattedNumber
- GetNationallyFormattedNumber
- GetWholeNumber
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "third_party/libphonenumber/src/phonenumber_api.h"
using i18n::phonenumbers::PhoneNumber;
using i18n::phonenumbers::PhoneNumberUtil;
namespace autofill {
namespace {
std::string SanitizeRegion(const std::string& region,
const std::string& app_locale) {
if (region.length() == 2)
return region;
return AutofillCountry::CountryCodeForLocale(app_locale);
}
bool IsValidPhoneNumber(const PhoneNumber& phone_number) {
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
if (!phone_util->IsPossibleNumber(phone_number))
return false;
if (!phone_util->IsValidNumber(phone_number))
return false;
return true;
}
void FormatValidatedNumber(const PhoneNumber& number,
const base::string16& country_code,
base::string16* formatted_number,
base::string16* normalized_number) {
PhoneNumberUtil::PhoneNumberFormat format =
country_code.empty() ?
PhoneNumberUtil::NATIONAL :
PhoneNumberUtil::INTERNATIONAL;
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
std::string processed_number;
phone_util->Format(number, format, &processed_number);
if (formatted_number)
*formatted_number = base::UTF8ToUTF16(processed_number);
if (normalized_number) {
phone_util->NormalizeDigitsOnly(&processed_number);
*normalized_number = base::UTF8ToUTF16(processed_number);
}
}
}
namespace i18n {
bool ParsePhoneNumber(const base::string16& value,
const std::string& default_region,
base::string16* country_code,
base::string16* city_code,
base::string16* number,
std::string* inferred_region,
PhoneNumber* i18n_number) {
country_code->clear();
city_code->clear();
number->clear();
*i18n_number = PhoneNumber();
std::string number_text(base::UTF16ToUTF8(value));
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
DCHECK_EQ(2U, default_region.size());
if (phone_util->Parse(number_text, default_region, i18n_number) !=
PhoneNumberUtil::NO_PARSING_ERROR) {
return false;
}
if (!IsValidPhoneNumber(*i18n_number))
return false;
std::string national_significant_number;
phone_util->GetNationalSignificantNumber(*i18n_number,
&national_significant_number);
int area_length = phone_util->GetLengthOfGeographicalAreaCode(*i18n_number);
int destination_length =
phone_util->GetLengthOfNationalDestinationCode(*i18n_number);
if (destination_length > area_length)
area_length = destination_length;
std::string area_code;
std::string subscriber_number;
if (area_length > 0) {
area_code = national_significant_number.substr(0, area_length);
subscriber_number = national_significant_number.substr(area_length);
} else {
subscriber_number = national_significant_number;
}
*number = base::UTF8ToUTF16(subscriber_number);
*city_code = base::UTF8ToUTF16(area_code);
*country_code = base::string16();
phone_util->NormalizeDigitsOnly(&number_text);
base::string16 normalized_number(base::UTF8ToUTF16(number_text));
if (i18n_number->has_country_code()) {
*country_code = base::UTF8ToUTF16(
base::StringPrintf("%d", i18n_number->country_code()));
if (normalized_number.length() <= national_significant_number.length() &&
!StartsWith(normalized_number, *country_code,
true )) {
country_code->clear();
}
}
phone_util->GetRegionCodeForNumber(*i18n_number, inferred_region);
return true;
}
base::string16 NormalizePhoneNumber(const base::string16& value,
const std::string& region) {
DCHECK_EQ(2u, region.size());
base::string16 country_code, unused_city_code, unused_number;
std::string unused_region;
PhoneNumber phone_number;
if (!ParsePhoneNumber(value, region, &country_code, &unused_city_code,
&unused_number, &unused_region, &phone_number)) {
return base::string16();
}
base::string16 normalized_number;
FormatValidatedNumber(phone_number, country_code, NULL, &normalized_number);
return normalized_number;
}
bool ConstructPhoneNumber(const base::string16& country_code,
const base::string16& city_code,
const base::string16& number,
const std::string& region,
base::string16* whole_number) {
DCHECK_EQ(2u, region.size());
whole_number->clear();
base::string16 unused_country_code, unused_city_code, unused_number;
std::string unused_region;
PhoneNumber phone_number;
if (!ParsePhoneNumber(country_code + city_code + number, region,
&unused_country_code, &unused_city_code, &unused_number,
&unused_region, &phone_number)) {
return false;
}
FormatValidatedNumber(phone_number, country_code, whole_number, NULL);
return true;
}
bool PhoneNumbersMatch(const base::string16& number_a,
const base::string16& number_b,
const std::string& raw_region,
const std::string& app_locale) {
const std::string region = SanitizeRegion(raw_region, app_locale);
PhoneNumberUtil* phone_util = PhoneNumberUtil::GetInstance();
PhoneNumber i18n_number1;
if (phone_util->Parse(
base::UTF16ToUTF8(number_a), region.c_str(), &i18n_number1) !=
PhoneNumberUtil::NO_PARSING_ERROR) {
return false;
}
PhoneNumber i18n_number2;
if (phone_util->Parse(
base::UTF16ToUTF8(number_b), region.c_str(), &i18n_number2) !=
PhoneNumberUtil::NO_PARSING_ERROR) {
return false;
}
switch (phone_util->IsNumberMatch(i18n_number1, i18n_number2)) {
case PhoneNumberUtil::INVALID_NUMBER:
case PhoneNumberUtil::NO_MATCH:
return false;
case PhoneNumberUtil::SHORT_NSN_MATCH:
return false;
case PhoneNumberUtil::NSN_MATCH:
case PhoneNumberUtil::EXACT_MATCH:
return true;
}
NOTREACHED();
return false;
}
PhoneObject::PhoneObject(const base::string16& number,
const std::string& region) {
DCHECK_EQ(2u, region.size());
scoped_ptr<PhoneNumber> i18n_number(new PhoneNumber);
if (ParsePhoneNumber(number, region, &country_code_, &city_code_, &number_,
®ion_, i18n_number.get())) {
i18n_number_ = i18n_number.Pass();
} else {
whole_number_ = number;
}
}
PhoneObject::PhoneObject(const PhoneObject& other) { *this = other; }
PhoneObject::PhoneObject() {}
PhoneObject::~PhoneObject() {}
const base::string16& PhoneObject::GetFormattedNumber() const {
if (i18n_number_ && formatted_number_.empty()) {
FormatValidatedNumber(*i18n_number_, country_code_, &formatted_number_,
&whole_number_);
}
return formatted_number_;
}
base::string16 PhoneObject::GetNationallyFormattedNumber() const {
base::string16 formatted = whole_number_;
if (i18n_number_)
FormatValidatedNumber(*i18n_number_, base::string16(), &formatted, NULL);
return formatted;
}
const base::string16& PhoneObject::GetWholeNumber() const {
if (i18n_number_ && whole_number_.empty()) {
FormatValidatedNumber(*i18n_number_, country_code_, &formatted_number_,
&whole_number_);
}
return whole_number_;
}
PhoneObject& PhoneObject::operator=(const PhoneObject& other) {
if (this == &other)
return *this;
region_ = other.region_;
if (other.i18n_number_.get())
i18n_number_.reset(new PhoneNumber(*other.i18n_number_));
else
i18n_number_.reset();
country_code_ = other.country_code_;
city_code_ = other.city_code_;
number_ = other.number_;
formatted_number_ = other.formatted_number_;
whole_number_ = other.whole_number_;
return *this;
}
}
}