Commit 76b6bc93 authored by Matthias Körber's avatar Matthias Körber Committed by Commit Bot

[Autofill] Relax interpretation of autocomplete attribute 'country'.

With this change, a field with the 'country' autocomplete attribute must
not strictly contain an ISO 3166-1-alpha-2 country code as specified,
but may also contain a localized full text name.

The wrong usage of the autocomplete attribute prevents users from
importing address profiles from filled forms.

Change-Id: I1fa954530abdcebab6dc4be69a092ad0d9b7cee6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2162774
Commit-Queue: Matthias Körber <koerber@google.com>
Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/master@{#764210}
parent 538816ae
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include "base/check_op.h" #include "base/check_op.h"
#include "base/feature_list.h"
#include "base/i18n/case_conversion.h" #include "base/i18n/case_conversion.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "base/stl_util.h" #include "base/stl_util.h"
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
#include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/geo/autofill_country.h"
#include "components/autofill/core/browser/geo/country_names.h" #include "components/autofill/core/browser/geo/country_names.h"
#include "components/autofill/core/browser/geo/state_names.h" #include "components/autofill/core/browser/geo/state_names.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_l10n_util.h" #include "components/autofill/core/common/autofill_l10n_util.h"
namespace autofill { namespace autofill {
...@@ -222,10 +224,21 @@ bool Address::SetInfoImpl(const AutofillType& type, ...@@ -222,10 +224,21 @@ bool Address::SetInfoImpl(const AutofillType& type,
const std::string& app_locale) { const std::string& app_locale) {
if (type.html_type() == HTML_TYPE_COUNTRY_CODE) { if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
if (!data_util::IsValidCountryCode(base::i18n::ToUpper(value))) { if (!data_util::IsValidCountryCode(base::i18n::ToUpper(value))) {
country_code_ = std::string(); // Some popular websites use the HTML_TYPE_COUNTRY_CODE attribute for
return false; // full text names (e.g. alliedelec.com). Try to convert the value to a
// country code as a fallback.
if (base::FeatureList::IsEnabled(
features::kAutofillAllowHtmlTypeCountryCodesWithFullNames)) {
CountryNames* country_names =
!value.empty() ? CountryNames::GetInstance() : nullptr;
country_code_ = country_names ? country_names->GetCountryCode(value)
: std::string();
return !country_code_.empty();
} else {
country_code_ = std::string();
return false;
}
} }
country_code_ = base::ToUpperASCII(base::UTF16ToASCII(value)); country_code_ = base::ToUpperASCII(base::UTF16ToASCII(value));
return true; return true;
} }
......
...@@ -9,9 +9,11 @@ ...@@ -9,9 +9,11 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_model/address.h" #include "components/autofill/core/browser/data_model/address.h"
#include "components/autofill/core/browser/geo/country_names.h" #include "components/autofill/core/browser/geo/country_names.h"
#include "components/autofill/core/common/autofill_features.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16; using base::ASCIIToUTF16;
...@@ -56,6 +58,73 @@ TEST_F(AddressTest, GetCountry) { ...@@ -56,6 +58,73 @@ TEST_F(AddressTest, GetCountry) {
EXPECT_EQ(ASCIIToUTF16("CA"), country); EXPECT_EQ(ASCIIToUTF16("CA"), country);
} }
// Test that country data can be properly returned as either a country code or a
// full country name that can even be localized.
TEST_F(AddressTest, SetHtmlCountryCodeTypeWithFullCountryName) {
Address address;
EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
// Enable the feature that allows for full country names although the
// field type explicitly set to HTML_TYPE_COUNTRY_CODE.
base::test::ScopedFeatureList feature;
feature.InitAndEnableFeature(
features::kAutofillAllowHtmlTypeCountryCodesWithFullNames);
// Create an autofill type from HTML_TYPE_COUNTRY_CODE.
AutofillType autofill_type(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
// Test that the country value can be set and retrieved if it is not
// a country code but a full country name.
address.SetInfo(autofill_type, ASCIIToUTF16("Germany"), "en-US");
base::string16 actual_country =
address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
base::string16 actual_country_code = address.GetInfo(
AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
EXPECT_EQ(ASCIIToUTF16("Germany"), actual_country);
EXPECT_EQ(ASCIIToUTF16("DE"), actual_country_code);
// Reset the country and verify that the reset works as expected.
address.SetInfo(autofill_type, ASCIIToUTF16(""), "en-US");
actual_country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
actual_country_code = address.GetInfo(
AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
EXPECT_EQ(ASCIIToUTF16(""), actual_country);
EXPECT_EQ(ASCIIToUTF16(""), actual_country_code);
// Test that the country value can be set and retrieved if it is not
// a country code but a full country name with a non-standard locale.
address.SetInfo(autofill_type, ASCIIToUTF16("deutschland"), "de");
actual_country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
actual_country_code = address.GetInfo(
AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
EXPECT_EQ(ASCIIToUTF16("Germany"), actual_country);
EXPECT_EQ(ASCIIToUTF16("DE"), actual_country_code);
// Reset the country.
address.SetInfo(autofill_type, ASCIIToUTF16(""), "en-US");
// Test that the country is still stored correctly with a supplied
// country code.
address.SetInfo(autofill_type, ASCIIToUTF16("DE"), "en-US");
actual_country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
actual_country_code = address.GetInfo(
AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
EXPECT_EQ(ASCIIToUTF16("DE"), actual_country_code);
EXPECT_EQ(ASCIIToUTF16("Germany"), actual_country);
// By disabling the feature, test that the country name deduction actually
// uses the path for HTML_TYPE_COUNTRY_CODE.
feature.Reset();
feature.InitAndDisableFeature(
features::kAutofillAllowHtmlTypeCountryCodesWithFullNames);
address.SetInfo(autofill_type, ASCIIToUTF16("Germany"), "en-US");
actual_country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
actual_country_code = address.GetInfo(
AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
EXPECT_EQ(ASCIIToUTF16(""), actual_country);
EXPECT_EQ(ASCIIToUTF16(""), actual_country_code);
}
// Test that we properly detect country codes appropriate for each country. // Test that we properly detect country codes appropriate for each country.
TEST_F(AddressTest, SetCountry) { TEST_F(AddressTest, SetCountry) {
Address address; Address address;
......
...@@ -25,6 +25,13 @@ namespace features { ...@@ -25,6 +25,13 @@ namespace features {
const base::Feature kAutofillAddressNormalizer{ const base::Feature kAutofillAddressNormalizer{
"AutofillAddressNormalizer", base::FEATURE_ENABLED_BY_DEFAULT}; "AutofillAddressNormalizer", base::FEATURE_ENABLED_BY_DEFAULT};
// Controls if a full country name instead of a country code in a field with a
// type derived from HTML_TYPE_COUNTRY_CODE can be used to set the profile
// country.
const base::Feature kAutofillAllowHtmlTypeCountryCodesWithFullNames{
"AutofillAllowHtmlTypeCountryCodesWithFullNames",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether autofill activates on non-HTTP(S) pages. Useful for // Controls whether autofill activates on non-HTTP(S) pages. Useful for
// automated with data URLS in cases where it's too difficult to use the // automated with data URLS in cases where it's too difficult to use the
// embedded test server. Generally avoid using. // embedded test server. Generally avoid using.
......
...@@ -22,6 +22,7 @@ namespace features { ...@@ -22,6 +22,7 @@ namespace features {
// All features in alphabetical order. // All features in alphabetical order.
extern const base::Feature kAutofillAddressNormalizer; extern const base::Feature kAutofillAddressNormalizer;
extern const base::Feature kAutofillAllowHtmlTypeCountryCodesWithFullNames;
extern const base::Feature kAutofillAllowNonHttpActivation; extern const base::Feature kAutofillAllowNonHttpActivation;
extern const base::Feature kAutofillAlwaysFillAddresses; extern const base::Feature kAutofillAlwaysFillAddresses;
extern const base::Feature kAutofillCacheQueryResponses; extern const base::Feature kAutofillCacheQueryResponses;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment