summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
authorrouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-11 23:18:33 +0000
committerrouslan@chromium.org <rouslan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-11 23:18:33 +0000
commitf91a9ccc1b2be06925899d48eb2d144e695a1d56 (patch)
tree71805fa02add0fca87f4a467b5174c80b8d430e2 /third_party
parent0a60abb713ad65f4d5cf202b91e2be79b2dce4c9 (diff)
downloadchromium_src-f91a9ccc1b2be06925899d48eb2d144e695a1d56.zip
chromium_src-f91a9ccc1b2be06925899d48eb2d144e695a1d56.tar.gz
chromium_src-f91a9ccc1b2be06925899d48eb2d144e695a1d56.tar.bz2
Reland "Use upstream libaddressinput in Chrome."
Remove static initializer and reland https://crrev.com/282408 which was reverted in https://crrev.com/282426. TBR=estade@chromium.org,thestig@chromium.org BUG=389918 Review URL: https://codereview.chromium.org/386873002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282726 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r--third_party/libaddressinput/BUILD.gn163
-rw-r--r--third_party/libaddressinput/README.chromium12
-rw-r--r--third_party/libaddressinput/chromium/addressinput_util.cc34
-rw-r--r--third_party/libaddressinput/chromium/addressinput_util.h8
-rw-r--r--third_party/libaddressinput/chromium/addressinput_util_unittest.cc2
-rw-r--r--third_party/libaddressinput/chromium/chrome_address_validator.cc154
-rw-r--r--third_party/libaddressinput/chromium/chrome_address_validator.h (renamed from third_party/libaddressinput/chromium/preload_address_validator.h)101
-rw-r--r--third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc (renamed from third_party/libaddressinput/chromium/preload_address_validator_unittest.cc)440
-rw-r--r--third_party/libaddressinput/chromium/chrome_downloader_impl.cc52
-rw-r--r--third_party/libaddressinput/chromium/chrome_downloader_impl.h11
-rw-r--r--third_party/libaddressinput/chromium/chrome_downloader_impl_unittest.cc28
-rw-r--r--third_party/libaddressinput/chromium/chrome_rule_test.cc2
-rw-r--r--third_party/libaddressinput/chromium/chrome_storage_impl.cc44
-rw-r--r--third_party/libaddressinput/chromium/chrome_storage_impl.h14
-rw-r--r--third_party/libaddressinput/chromium/chrome_storage_impl_unittest.cc6
-rw-r--r--third_party/libaddressinput/chromium/fallback_data_store.cc203
-rw-r--r--third_party/libaddressinput/chromium/fallback_data_store.h22
-rw-r--r--third_party/libaddressinput/chromium/fallback_data_store_unittest.cc40
-rw-r--r--third_party/libaddressinput/chromium/input_suggester.cc521
-rw-r--r--third_party/libaddressinput/chromium/input_suggester.h133
-rw-r--r--third_party/libaddressinput/chromium/json.cc172
-rw-r--r--third_party/libaddressinput/chromium/libaddressinput_util.cc72
-rw-r--r--third_party/libaddressinput/chromium/libaddressinput_util.h42
-rw-r--r--third_party/libaddressinput/chromium/libaddressinput_util_unittest.cc41
-rw-r--r--third_party/libaddressinput/chromium/override/basictypes_override.h10
-rw-r--r--third_party/libaddressinput/chromium/preload_address_validator.cc144
-rw-r--r--third_party/libaddressinput/chromium/storage_test_runner.cc88
-rw-r--r--third_party/libaddressinput/chromium/storage_test_runner.h47
-rw-r--r--third_party/libaddressinput/chromium/string_compare.cc69
-rw-r--r--third_party/libaddressinput/chromium/string_compare_unittest.cc26
-rw-r--r--third_party/libaddressinput/chromium/trie.cc81
-rw-r--r--third_party/libaddressinput/chromium/trie.h54
-rw-r--r--third_party/libaddressinput/chromium/trie_unittest.cc109
-rw-r--r--third_party/libaddressinput/libaddressinput.gyp265
34 files changed, 2435 insertions, 775 deletions
diff --git a/third_party/libaddressinput/BUILD.gn b/third_party/libaddressinput/BUILD.gn
index 291e549..a0e2341 100644
--- a/third_party/libaddressinput/BUILD.gn
+++ b/third_party/libaddressinput/BUILD.gn
@@ -4,70 +4,69 @@
import("//tools/grit/grit_rule.gni")
-# TODO(rouslan): Use the src/ directory. http://crbug.com/327046
-libaddressinput_dir = "chromium"
+# The list of files in libaddressinput.gypi.
+gypi_values = exec_script(
+ "//build/gypi_to_gn.py",
+ [ rebase_path("src/cpp/libaddressinput.gypi") ],
+ "scope",
+ [ "src/cpp/libaddressinput.gypi" ])
+
+libaddressinput_util_files = [
+ "src/cpp/src/address_data.cc",
+ "src/cpp/src/address_field.cc",
+ "src/cpp/src/address_field_util.cc",
+ "src/cpp/src/address_formatter.cc",
+ "src/cpp/src/address_metadata.cc",
+ "src/cpp/src/address_ui.cc",
+ "src/cpp/src/format_element.cc",
+ "src/cpp/src/language.cc",
+ "src/cpp/src/localization.cc",
+ "src/cpp/src/lookup_key.cc",
+ "src/cpp/src/region_data_constants.cc",
+ "src/cpp/src/rule.cc",
+ "src/cpp/src/util/cctype_tolower_equal.cc",
+ "src/cpp/src/util/json.cc",
+ "src/cpp/src/util/string_split.cc",
+ "src/cpp/src/util/string_util.cc",
+]
# GYP version: third_party/libaddressinput/libaddressinput.gyp:libaddressinput_strings
grit("strings") {
- source = "$libaddressinput_dir/cpp/res/libaddressinput_strings.grd"
-}
-
-# GYP version: third_party/libaddressinput/libaddressinput.gyp:libaddressinput_updated_strings
-grit("updated_strings") {
source = "//chrome/app/address_input_strings.grd"
}
config("libaddressinput_config") {
defines = [
- "CUSTOM_BASICTYPES=\"base/basictypes.h\"",
- "CUSTOM_SCOPED_PTR=\"base/memory/scoped_ptr.h\"",
+ "I18N_ADDRESSINPUT_USE_BASICTYPES_OVERRIDE=1",
+ "VALIDATION_DATA_URL=\"https://i18napis.appspot.com/ssl-aggregate-address/\"",
+ ]
+ include_dirs = [
+ "src/cpp/include",
+ "chromium/override",
]
- include_dirs = [ "$libaddressinput_dir/cpp/include" ]
}
# This target provides basic functionality which is cooked into the build.
# GYP version: third_party/libaddressinput/libaddressinput.gyp:libaddressinput_util
static_library("util") {
- sources = [
+ sources = libaddressinput_util_files
+ sources += [
"chromium/addressinput_util.cc",
- "chromium/addressinput_util.h",
- "chromium/canonicalize_string.cc",
"chromium/json.cc",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_data.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_field.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_formatter.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_metadata.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_problem.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/util/basictypes.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/util/internal/basictypes.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/util/internal/move.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/util/internal/scoped_ptr.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/util/internal/template_util.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/util/scoped_ptr.h",
- "$libaddressinput_dir/cpp/src/address_data.cc",
- "$libaddressinput_dir/cpp/src/address_field.cc",
- "$libaddressinput_dir/cpp/src/address_formatter.cc",
- "$libaddressinput_dir/cpp/src/address_metadata.cc",
- "$libaddressinput_dir/cpp/src/address_problem.cc",
- "$libaddressinput_dir/cpp/src/language.cc",
- "$libaddressinput_dir/cpp/src/language.h",
- "$libaddressinput_dir/cpp/src/region_data_constants.cc",
- "$libaddressinput_dir/cpp/src/region_data_constants.h",
- "$libaddressinput_dir/cpp/src/rule.cc",
- "$libaddressinput_dir/cpp/src/rule.h",
- "$libaddressinput_dir/cpp/src/util/canonicalize_string.h",
- "$libaddressinput_dir/cpp/src/util/cctype_tolower_equal.cc",
- "$libaddressinput_dir/cpp/src/util/cctype_tolower_equal.h",
- "$libaddressinput_dir/cpp/src/util/json.h",
- "$libaddressinput_dir/cpp/src/util/stl_util.h",
- "$libaddressinput_dir/cpp/src/util/string_util.cc",
- "$libaddressinput_dir/cpp/src/util/string_util.h",
+ ]
+ sources -= [
+ "src/cpp/src/util/json.cc",
]
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
+
direct_dependent_configs = [ ":libaddressinput_config" ]
- include_dirs = [ "$root_gen_dir/libaddressinput" ]
+
+ include_dirs = [ "$root_gen_dir/third_party/libaddressinput" ]
deps = [
+ ":strings",
"//base",
"//base:i18n",
"//third_party/icu",
@@ -79,41 +78,28 @@ static_library("util") {
# for validation rules.
# GYP version: third_party/libaddressinput/libaddressinput.gyp:libaddressinput
static_library("libaddressinput") {
- sources = [
+ sources = rebase_path(gypi_values.libaddressinput_files, ".", "src/cpp")
+ sources += [
+ "chromium/chrome_address_validator.cc",
"chromium/chrome_downloader_impl.cc",
- "chromium/chrome_downloader_impl.h",
"chromium/chrome_storage_impl.cc",
- "chromium/chrome_storage_impl.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_ui_component.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_ui.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/address_validator.h",
- "$libaddressinput_dir/cpp/include/libaddressinput/load_rules_delegate.h",
- "$libaddressinput_dir/cpp/src/address_ui.cc",
- "$libaddressinput_dir/cpp/src/address_validator.cc",
- "$libaddressinput_dir/cpp/src/country_rules_aggregator.cc",
- "$libaddressinput_dir/cpp/src/country_rules_aggregator.h",
- "$libaddressinput_dir/cpp/src/fallback_data_store.cc",
- "$libaddressinput_dir/cpp/src/fallback_data_store.h",
- "$libaddressinput_dir/cpp/src/grit.h",
- "$libaddressinput_dir/cpp/src/retriever.cc",
- "$libaddressinput_dir/cpp/src/retriever.h",
- "$libaddressinput_dir/cpp/src/ruleset.cc",
- "$libaddressinput_dir/cpp/src/ruleset.h",
- "$libaddressinput_dir/cpp/src/util/md5.cc",
- "$libaddressinput_dir/cpp/src/util/md5.h",
- "$libaddressinput_dir/cpp/src/util/trie.cc",
- "$libaddressinput_dir/cpp/src/util/trie.h",
+ "chromium/fallback_data_store.cc",
+ "chromium/input_suggester.cc",
+ "chromium/string_compare.cc",
+ "chromium/trie.cc",
+ ]
+ sources -= libaddressinput_util_files
+ sources -= [
+ "src/cpp/src/util/string_compare.cc",
]
- direct_dependent_configs = [ ":libaddressinput_config" ]
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
- defines = [
- "VALIDATION_DATA_URL=\"https://i18napis.appspot.com/ssl-aggregate-address/\"",
- ]
+ direct_dependent_configs = [ ":libaddressinput_config" ]
deps = [
":strings",
- ":updated_strings",
":util",
"//base",
"//base:i18n",
@@ -123,42 +109,27 @@ static_library("libaddressinput") {
}
test("libaddressinput_unittests") {
- sources = [
+ sources = rebase_path(gypi_values.libaddressinput_test_files, ".", "src/cpp")
+ sources += [
"chromium/addressinput_util_unittest.cc",
+ "chromium/chrome_address_validator_unittest.cc",
"chromium/chrome_downloader_impl_unittest.cc",
- "chromium/chrome_rule_test.cc",
"chromium/chrome_storage_impl_unittest.cc",
- "$libaddressinput_dir/cpp/test/address_data_test.cc",
- "$libaddressinput_dir/cpp/test/address_ui_test.cc",
- "$libaddressinput_dir/cpp/test/address_validator_test.cc",
- "$libaddressinput_dir/cpp/test/country_rules_aggregator_test.cc",
- "$libaddressinput_dir/cpp/test/countryinfo_example_addresses_test.cc",
- "$libaddressinput_dir/cpp/test/fake_downloader.cc",
- "$libaddressinput_dir/cpp/test/fake_downloader.h",
- "$libaddressinput_dir/cpp/test/fake_downloader_test.cc",
- "$libaddressinput_dir/cpp/test/fake_storage.cc",
- "$libaddressinput_dir/cpp/test/fake_storage.h",
- "$libaddressinput_dir/cpp/test/fake_storage_test.cc",
- "$libaddressinput_dir/cpp/test/fallback_data_store_test.cc",
- "$libaddressinput_dir/cpp/test/region_data_constants_test.cc",
- "$libaddressinput_dir/cpp/test/retriever_test.cc",
- "$libaddressinput_dir/cpp/test/rule_test.cc",
- "$libaddressinput_dir/cpp/test/storage_test_runner.cc",
- "$libaddressinput_dir/cpp/test/storage_test_runner.h",
- "$libaddressinput_dir/cpp/test/util/json_test.cc",
- "$libaddressinput_dir/cpp/test/util/md5_unittest.cc",
- "$libaddressinput_dir/cpp/test/util/scoped_ptr_unittest.cc",
- "$libaddressinput_dir/cpp/test/util/stl_util_unittest.cc",
- "$libaddressinput_dir/cpp/test/util/string_util_test.cc",
- "$libaddressinput_dir/cpp/test/util/trie_test.cc",
+ "chromium/fallback_data_store_unittest.cc",
+ "chromium/storage_test_runner.cc",
+ "chromium/string_compare_unittest.cc",
+ "chromium/trie_unittest.cc",
]
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
+
defines = [
"TEST_DATA_DIR=\"third_party/libaddressinput/src/testdata\"",
]
include_dirs = [
- "$libaddressinput_dir/cpp/src",
+ "src/cpp/src",
]
deps = [
diff --git a/third_party/libaddressinput/README.chromium b/third_party/libaddressinput/README.chromium
index 348c121..aa5496a 100644
--- a/third_party/libaddressinput/README.chromium
+++ b/third_party/libaddressinput/README.chromium
@@ -2,8 +2,8 @@ Name: The library to input, validate, and display addresses.
Short Name: libaddressinput
URL: https://code.google.com/p/libaddressinput/
Version: 0
-Date: 7 July 2014
-Revision: 300
+Date: 10 July 2014
+Revision: 304
License: Apache 2.0
License File: LICENSE
Security Critical: no
@@ -17,9 +17,5 @@ https://i18napis.appspot.com/ssl-aggregate-address. The library is used in
requestAutocomplete dialog and autofill.
Local Modifications:
-- The package is libaddressinput at revision 176 plus the Chrome-specific
- validation logic, which will be upstreamed back to libaddressinput
- (http://crbug.com/327046). The Chrome-specific version is in chromium/cpp/
- subdirectory. The original source code is in src/cpp/ subdirectory. Both
- versions use the original test data file src/testdata/countryinfo.txt.
-- Serbia and Montenegro (YU) was removed as a supported region.
+- Use Chrome's version of JSON reader in chromium/json.cc.
+- Use Chrome's version of loose string comparison in chromium/string_compare.cc.
diff --git a/third_party/libaddressinput/chromium/addressinput_util.cc b/third_party/libaddressinput/chromium/addressinput_util.cc
index 3af6137..d9e6725 100644
--- a/third_party/libaddressinput/chromium/addressinput_util.cc
+++ b/third_party/libaddressinput/chromium/addressinput_util.cc
@@ -8,8 +8,8 @@
#include "base/logging.h"
#include "base/macros.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_metadata.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h"
namespace autofill {
namespace addressinput {
@@ -21,32 +21,32 @@ using ::i18n::addressinput::AddressField;
using ::i18n::addressinput::AddressProblem;
using ::i18n::addressinput::IsFieldRequired;
+using ::i18n::addressinput::MISSING_REQUIRED_FIELD;
+
// Returns true if the |problem| should not be reported for the |field| because
// the |filter| excludes it.
-bool FilterExcludes(
- const std::multimap<AddressField, AddressProblem::Type>* filter,
- AddressField field,
- AddressProblem::Type problem) {
+bool FilterExcludes(const std::multimap<AddressField, AddressProblem>* filter,
+ AddressField field,
+ AddressProblem problem) {
return filter != NULL && !filter->empty() &&
- std::find(
- filter->begin(),
- filter->end(),
- std::multimap<AddressField, AddressProblem::Type>::value_type(
- field, problem)) == filter->end();
+ std::find(filter->begin(),
+ filter->end(),
+ std::multimap<AddressField, AddressProblem>::value_type(
+ field, problem)) == filter->end();
}
} // namespace
bool HasAllRequiredFields(const AddressData& address_to_check) {
- std::multimap<AddressField, AddressProblem::Type> problems;
+ std::multimap<AddressField, AddressProblem> problems;
ValidateRequiredFields(address_to_check, NULL, &problems);
return problems.empty();
}
void ValidateRequiredFields(
const AddressData& address_to_check,
- const std::multimap<AddressField, AddressProblem::Type>* filter,
- std::multimap<AddressField, AddressProblem::Type>* problems) {
+ const std::multimap<AddressField, AddressProblem>* filter,
+ std::multimap<AddressField, AddressProblem>* problems) {
DCHECK(problems);
static const AddressField kFields[] = {
@@ -63,10 +63,8 @@ void ValidateRequiredFields(
AddressField field = kFields[i];
if (address_to_check.IsFieldEmpty(field) &&
IsFieldRequired(field, address_to_check.region_code) &&
- !FilterExcludes(
- filter, field, AddressProblem::MISSING_REQUIRED_FIELD)) {
- problems->insert(
- std::make_pair(field, AddressProblem::MISSING_REQUIRED_FIELD));
+ !FilterExcludes(filter, field, MISSING_REQUIRED_FIELD)) {
+ problems->insert(std::make_pair(field, MISSING_REQUIRED_FIELD));
}
}
}
diff --git a/third_party/libaddressinput/chromium/addressinput_util.h b/third_party/libaddressinput/chromium/addressinput_util.h
index e3bdaa4..7c888a7 100644
--- a/third_party/libaddressinput/chromium/addressinput_util.h
+++ b/third_party/libaddressinput/chromium/addressinput_util.h
@@ -7,8 +7,8 @@
#include <map>
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_field.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_problem.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_problem.h"
namespace i18n {
namespace addressinput {
@@ -32,9 +32,9 @@ bool HasAllRequiredFields(
void ValidateRequiredFields(
const ::i18n::addressinput::AddressData& address_to_check,
const std::multimap< ::i18n::addressinput::AddressField,
- ::i18n::addressinput::AddressProblem::Type>* filter,
+ ::i18n::addressinput::AddressProblem>* filter,
std::multimap< ::i18n::addressinput::AddressField,
- ::i18n::addressinput::AddressProblem::Type>* problems);
+ ::i18n::addressinput::AddressProblem>* problems);
} // namespace addressinput
} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/addressinput_util_unittest.cc b/third_party/libaddressinput/chromium/addressinput_util_unittest.cc
index 846f3d4..b68ea81 100644
--- a/third_party/libaddressinput/chromium/addressinput_util_unittest.cc
+++ b/third_party/libaddressinput/chromium/addressinput_util_unittest.cc
@@ -5,7 +5,7 @@
#include "third_party/libaddressinput/chromium/addressinput_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
namespace autofill {
namespace addressinput {
diff --git a/third_party/libaddressinput/chromium/chrome_address_validator.cc b/third_party/libaddressinput/chromium/chrome_address_validator.cc
new file mode 100644
index 0000000..b54c74d
--- /dev/null
+++ b/third_party/libaddressinput/chromium/chrome_address_validator.cc
@@ -0,0 +1,154 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/chrome_address_validator.h"
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/libaddressinput/chromium/input_suggester.h"
+#include "third_party/libaddressinput/chromium/libaddressinput_util.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_normalizer.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/downloader.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+
+namespace autofill {
+
+using ::i18n::addressinput::AddressData;
+using ::i18n::addressinput::AddressField;
+using ::i18n::addressinput::AddressNormalizer;
+using ::i18n::addressinput::BuildCallback;
+using ::i18n::addressinput::Downloader;
+using ::i18n::addressinput::FieldProblemMap;
+using ::i18n::addressinput::PreloadSupplier;
+using ::i18n::addressinput::Storage;
+
+using ::i18n::addressinput::ADMIN_AREA;
+using ::i18n::addressinput::DEPENDENT_LOCALITY;
+using ::i18n::addressinput::POSTAL_CODE;
+
+AddressValidator::AddressValidator(const std::string& validation_data_url,
+ scoped_ptr<Downloader> downloader,
+ scoped_ptr<Storage> storage,
+ LoadRulesListener* load_rules_listener)
+ : supplier_(new PreloadSupplier(validation_data_url,
+ downloader.release(),
+ storage.release())),
+ input_suggester_(new InputSuggester(supplier_.get())),
+ normalizer_(new AddressNormalizer(supplier_.get())),
+ validator_(new ::i18n::addressinput::AddressValidator(supplier_.get())),
+ validated_(BuildCallback(this, &AddressValidator::Validated)),
+ rules_loaded_(BuildCallback(this, &AddressValidator::RulesLoaded)),
+ load_rules_listener_(load_rules_listener) {}
+
+AddressValidator::~AddressValidator() {}
+
+void AddressValidator::LoadRules(const std::string& region_code) {
+ DCHECK(supplier_);
+ supplier_->LoadRules(region_code, *rules_loaded_);
+}
+
+AddressValidator::Status AddressValidator::ValidateAddress(
+ const AddressData& address,
+ const FieldProblemMap* filter,
+ FieldProblemMap* problems) const {
+ DCHECK(supplier_);
+ DCHECK(validator_);
+
+ if (supplier_->IsPending(address.region_code)) {
+ if (problems)
+ addressinput::ValidateRequiredFields(address, filter, problems);
+ return RULES_NOT_READY;
+ }
+
+ if (!supplier_->IsLoaded(address.region_code)) {
+ if (problems)
+ addressinput::ValidateRequiredFields(address, filter, problems);
+ return RULES_UNAVAILABLE;
+ }
+
+ if (!problems)
+ return SUCCESS;
+
+ validator_->Validate(address,
+ true, // Allow postal office boxes.
+ true, // Require recipient name.
+ filter,
+ problems,
+ *validated_);
+
+ return SUCCESS;
+}
+
+AddressValidator::Status AddressValidator::GetSuggestions(
+ const AddressData& user_input,
+ AddressField focused_field,
+ size_t suggestion_limit,
+ std::vector<AddressData>* suggestions) const {
+ DCHECK(supplier_);
+ DCHECK(input_suggester_);
+
+ if (supplier_->IsPending(user_input.region_code))
+ return RULES_NOT_READY;
+
+ if (!supplier_->IsLoaded(user_input.region_code))
+ return RULES_UNAVAILABLE;
+
+ if (!suggestions)
+ return SUCCESS;
+
+ suggestions->clear();
+
+ if (focused_field == POSTAL_CODE ||
+ (focused_field >= ADMIN_AREA && focused_field <= DEPENDENT_LOCALITY)) {
+ input_suggester_->GetSuggestions(
+ user_input, focused_field, suggestion_limit, suggestions);
+ }
+
+ return SUCCESS;
+}
+
+bool AddressValidator::CanonicalizeAdministrativeArea(
+ AddressData* address) const {
+ DCHECK(address);
+ DCHECK(supplier_);
+ DCHECK(normalizer_);
+
+ if (!supplier_->IsLoaded(address->region_code))
+ return false;
+
+ // TODO: It would probably be beneficial to use the full canonicalization.
+ AddressData tmp(*address);
+ normalizer_->Normalize(&tmp);
+ address->administrative_area = tmp.administrative_area;
+
+ return true;
+}
+
+AddressValidator::AddressValidator() : load_rules_listener_(NULL) {}
+
+void AddressValidator::Validated(bool success,
+ const AddressData&,
+ const FieldProblemMap&) {
+ DCHECK(success);
+}
+
+void AddressValidator::RulesLoaded(bool success,
+ const std::string& country_code,
+ int) {
+ if (load_rules_listener_)
+ load_rules_listener_->OnAddressValidationRulesLoaded(country_code, success);
+}
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/preload_address_validator.h b/third_party/libaddressinput/chromium/chrome_address_validator.h
index 8b22040..49875c8 100644
--- a/third_party/libaddressinput/chromium/preload_address_validator.h
+++ b/third_party/libaddressinput/chromium/chrome_address_validator.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_PRELOAD_ADDRESS_VALIDATOR_H_
-#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_PRELOAD_ADDRESS_VALIDATOR_H_
+#ifndef THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_CHROME_ADDRESS_VALIDATOR_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_CHROME_ADDRESS_VALIDATOR_H_
#include <cstddef>
#include <string>
@@ -14,28 +14,49 @@
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h"
namespace i18n {
namespace addressinput {
-
+class AddressNormalizer;
class Downloader;
-class PreloadSupplier;
class Storage;
-class Synonyms;
struct AddressData;
-
-} // namespace addressinput
-} // namespace i18n
+}
+}
namespace autofill {
-class Suggestions;
+class InputSuggester;
-// Interface to the libaddressinput AddressValidator for Chromium Autofill.
-class PreloadAddressValidator {
+// The object to be notified when loading of address validation rules is
+// finished.
+class LoadRulesListener {
public:
- typedef ::i18n::addressinput::Callback<std::string, int> Callback;
+ virtual ~LoadRulesListener() {}
+
+ // Called when the validation rules for the |country_code| have been loaded.
+ // The validation rules include the generic rules for the |country_code| and
+ // specific rules for the country's administrative areas, localities, and
+ // dependent localities. If a country has language-specific validation rules,
+ // then these are also loaded.
+ //
+ // The |success| parameter is true when the rules were loaded successfully.
+ virtual void OnAddressValidationRulesLoaded(const std::string& country_code,
+ bool success) = 0;
+};
+// Interface to the libaddressinput AddressValidator for Chromium Autofill. The
+// class is named AddressValidator to simplify switching between libaddressinput
+// and this version.
+//
+// It's not possible to name this file address_validator.h because some
+// compilers do not handle multiple files with the same name (although in
+// different directories) gracefully. This class is a shim between upstream
+// libaddressinput API and the API that Chrome expects, hence the file name
+// chrome_address_validator.h.
+class AddressValidator {
+ public:
// The status of address validation.
enum Status {
// Address validation completed successfully. Check |problems| to see if any
@@ -51,15 +72,15 @@ class PreloadAddressValidator {
};
// Takes ownership of |downloader| and |storage|.
- PreloadAddressValidator(
- const std::string& validation_data_url,
- scoped_ptr< ::i18n::addressinput::Downloader> downloader,
- scoped_ptr< ::i18n::addressinput::Storage> storage);
+ AddressValidator(const std::string& validation_data_url,
+ scoped_ptr< ::i18n::addressinput::Downloader> downloader,
+ scoped_ptr< ::i18n::addressinput::Storage> storage,
+ LoadRulesListener* load_rules_listener);
- virtual ~PreloadAddressValidator();
+ virtual ~AddressValidator();
// Loads the generic validation rules for |region_code| and specific rules
- // for the regions's administrative areas, localities, and dependent
+ // for the region's administrative areas, localities, and dependent
// localities. A typical data size is 10KB. The largest is 250KB. If a region
// has language-specific validation rules, then these are also loaded.
//
@@ -67,9 +88,8 @@ class PreloadAddressValidator {
// https://i18napis.appspot.com/ssl-aggregate-address/data/US
//
// If the rules are already in progress of being loaded, it does nothing.
- // Calls |loaded| when the loading has finished.
- virtual void LoadRules(const std::string& region_code,
- const Callback& loaded);
+ // Invokes |load_rules_listener| when the loading has finished.
+ virtual void LoadRules(const std::string& region_code);
// Validates the |address| and populates |problems| with the validation
// problems, filtered according to the |filter| parameter.
@@ -77,7 +97,7 @@ class PreloadAddressValidator {
// If the |filter| is empty, then all discovered validation problems are
// returned. If the |filter| contains problem elements, then only the problems
// in the |filter| may be returned.
- virtual Status Validate(
+ virtual Status ValidateAddress(
const ::i18n::addressinput::AddressData& address,
const ::i18n::addressinput::FieldProblemMap* filter,
::i18n::addressinput::FieldProblemMap* problems) const;
@@ -119,23 +139,48 @@ class PreloadAddressValidator {
::i18n::addressinput::AddressData* address) const;
private:
+ friend class MockAddressValidator;
+
+ // Constructor used only for MockAddressValidator.
+ AddressValidator();
+
+ // Verifies that |validator_| succeeded. Invoked by |validated_| callback.
void Validated(bool success,
const ::i18n::addressinput::AddressData&,
const ::i18n::addressinput::FieldProblemMap&);
+ // Invokes the |load_rules_listener_|, if it's not NULL. Called by
+ // |rules_loaded_| callback.
+ void RulesLoaded(bool success, const std::string& country_code, int);
+
+ // Loads and stores aggregate rules at COUNTRY level.
const scoped_ptr< ::i18n::addressinput::PreloadSupplier> supplier_;
- const scoped_ptr<Suggestions> suggestions_;
- const scoped_ptr< ::i18n::addressinput::Synonyms> synonyms_;
+
+ // Suggests addresses based on user input.
+ const scoped_ptr<InputSuggester> input_suggester_;
+
+ // Normalizes addresses into a canonical form.
+ const scoped_ptr< ::i18n::addressinput::AddressNormalizer> normalizer_;
+
+ // Validates addresses.
const scoped_ptr<const ::i18n::addressinput::AddressValidator> validator_;
+
+ // The callback that |validator_| invokes when it finished validating an
+ // address.
const scoped_ptr<const ::i18n::addressinput::AddressValidator::Callback>
validated_;
- friend class MockAddressValidator;
- PreloadAddressValidator();
+ // The callback that |supplier_| invokes when it finished loading rules.
+ const scoped_ptr<const ::i18n::addressinput::PreloadSupplier::Callback>
+ rules_loaded_;
+
+ // Not owned delegate to invoke when |suppler_| finished loading rules. Can be
+ // NULL.
+ LoadRulesListener* const load_rules_listener_;
- DISALLOW_COPY_AND_ASSIGN(PreloadAddressValidator);
+ DISALLOW_COPY_AND_ASSIGN(AddressValidator);
};
} // namespace autofill
-#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_PRELOAD_ADDRESS_VALIDATOR_H_
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_CHROME_ADDRESS_VALIDATOR_H_
diff --git a/third_party/libaddressinput/chromium/preload_address_validator_unittest.cc b/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc
index 1cc7aaf..906d0a6 100644
--- a/third_party/libaddressinput/chromium/preload_address_validator_unittest.cc
+++ b/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "third_party/libaddressinput/chromium/chrome_address_validator.h"
+
#include <cstddef>
#include <string>
#include <vector>
@@ -10,31 +12,30 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-
-#define I18N_ADDRESSINPUT_UTIL_BASICTYPES_H_
-#include "third_party/libaddressinput/chromium/preload_address_validator.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_problem.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/downloader.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/null_storage.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
-#include "third_party/libaddressinput/src/cpp/src/region_data_constants.h"
#include "third_party/libaddressinput/src/cpp/test/fake_downloader.h"
namespace {
-using ::autofill::PreloadAddressValidator;
+using ::autofill::AddressValidator;
+using ::autofill::LoadRulesListener;
using ::i18n::addressinput::AddressData;
using ::i18n::addressinput::AddressField;
+using ::i18n::addressinput::AddressProblem;
using ::i18n::addressinput::BuildCallback;
using ::i18n::addressinput::Downloader;
using ::i18n::addressinput::FakeDownloader;
using ::i18n::addressinput::FieldProblemMap;
+using ::i18n::addressinput::GetRegionCodes;
using ::i18n::addressinput::NullStorage;
-using ::i18n::addressinput::RegionDataConstants;
using ::i18n::addressinput::Storage;
using ::i18n::addressinput::COUNTRY;
@@ -46,69 +47,113 @@ using ::i18n::addressinput::POSTAL_CODE;
using ::i18n::addressinput::STREET_ADDRESS;
using ::i18n::addressinput::RECIPIENT;
-using ::i18n::addressinput::UNKNOWN_VALUE;
using ::i18n::addressinput::INVALID_FORMAT;
using ::i18n::addressinput::MISMATCHING_VALUE;
+using ::i18n::addressinput::MISSING_REQUIRED_FIELD;
+using ::i18n::addressinput::UNEXPECTED_FIELD;
+using ::i18n::addressinput::UNKNOWN_VALUE;
+using ::i18n::addressinput::USES_P_O_BOX;
-class PreloadAddressValidatorTest : public testing::Test {
+class AddressValidatorTest : public testing::Test, LoadRulesListener {
protected:
- PreloadAddressValidatorTest()
+ AddressValidatorTest()
: validator_(
- new PreloadAddressValidator(
- FakeDownloader::kFakeAggregateDataUrl,
- scoped_ptr<Downloader>(new FakeDownloader),
- scoped_ptr<Storage>(new NullStorage))),
- loaded_(BuildCallback(this, &PreloadAddressValidatorTest::Loaded)) {
- validator_->LoadRules("US", *loaded_);
+ new AddressValidator(FakeDownloader::kFakeAggregateDataUrl,
+ scoped_ptr<Downloader>(new FakeDownloader),
+ scoped_ptr<Storage>(new NullStorage),
+ this)) {
+ validator_->LoadRules("US");
}
- virtual ~PreloadAddressValidatorTest() {}
+ virtual ~AddressValidatorTest() {}
- const scoped_ptr<PreloadAddressValidator> validator_;
- const scoped_ptr<PreloadAddressValidator::Callback> loaded_;
+ const scoped_ptr<AddressValidator> validator_;
private:
- void Loaded(bool success,
- const std::string& region_code,
- const int& rule_count) {
+ // LoadRulesListener implementation.
+ virtual void OnAddressValidationRulesLoaded(const std::string& country_code,
+ bool success) OVERRIDE {
AddressData address_data;
- address_data.region_code = region_code;
+ address_data.region_code = country_code;
FieldProblemMap dummy;
- PreloadAddressValidator::Status status =
- validator_->Validate(address_data, NULL, &dummy);
- ASSERT_EQ(success, status == PreloadAddressValidator::SUCCESS);
+ AddressValidator::Status status =
+ validator_->ValidateAddress(address_data, NULL, &dummy);
+ ASSERT_EQ(success, status == AddressValidator::SUCCESS);
}
- DISALLOW_COPY_AND_ASSIGN(PreloadAddressValidatorTest);
+ DISALLOW_COPY_AND_ASSIGN(AddressValidatorTest);
+};
+
+// Use this text fixture if you're going to use a region with a large set of
+// validation rules. All rules should be loaded in SetUpTestCase().
+class LargeAddressValidatorTest : public testing::Test {
+ protected:
+ LargeAddressValidatorTest() {}
+ virtual ~LargeAddressValidatorTest() {}
+
+ static void SetUpTestCase() {
+ validator_ =
+ new AddressValidator(FakeDownloader::kFakeAggregateDataUrl,
+ scoped_ptr<Downloader>(new FakeDownloader),
+ scoped_ptr<Storage>(new NullStorage),
+ NULL);
+ validator_->LoadRules("CN");
+ validator_->LoadRules("KR");
+ validator_->LoadRules("TW");
+ }
+
+ static void TearDownTestcase() {
+ delete validator_;
+ validator_ = NULL;
+ }
+
+ // Owned shared instance of validator with large sets validation rules.
+ static AddressValidator* validator_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LargeAddressValidatorTest);
};
-TEST_F(PreloadAddressValidatorTest, RegionHasRules) {
- const std::vector<std::string>& region_codes =
- RegionDataConstants::GetRegionCodes();
+AddressValidator* LargeAddressValidatorTest::validator_ = NULL;
+
+TEST_F(AddressValidatorTest, RegionHasRules) {
+ const std::vector<std::string>& region_codes = GetRegionCodes();
AddressData address;
for (size_t i = 0; i < region_codes.size(); ++i) {
SCOPED_TRACE("For region: " + region_codes[i]);
- validator_->LoadRules(region_codes[i], *loaded_);
+ validator_->LoadRules(region_codes[i]);
address.region_code = region_codes[i];
FieldProblemMap dummy;
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &dummy));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &dummy));
}
}
-TEST_F(PreloadAddressValidatorTest, EmptyAddressNoFatalFailure) {
+TEST_F(AddressValidatorTest, EmptyAddressNoFatalFailure) {
AddressData address;
address.region_code = "US";
FieldProblemMap dummy;
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &dummy));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &dummy));
}
-TEST_F(PreloadAddressValidatorTest, USZipCode) {
+TEST_F(AddressValidatorTest, UsStateNamesAreValidEntries) {
AddressData address;
+ address.region_code = "US";
+ address.administrative_area = "California";
+
+ FieldProblemMap filter;
+ filter.insert(std::make_pair(ADMIN_AREA, UNKNOWN_VALUE));
+ FieldProblemMap problems;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, &filter, &problems));
+ EXPECT_TRUE(problems.empty());
+}
+
+TEST_F(AddressValidatorTest, USZipCode) {
+ AddressData address;
+ address.recipient = "Mr. Smith";
address.address_line.push_back("340 Main St.");
address.locality = "Venice";
address.administrative_area = "CA";
@@ -117,27 +162,24 @@ TEST_F(PreloadAddressValidatorTest, USZipCode) {
// Valid Californian zip code.
address.postal_code = "90291";
FieldProblemMap problems;
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
problems.clear();
// An extended, valid Californian zip code.
address.postal_code = "90210-1234";
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
problems.clear();
// New York zip code (which is invalid for California).
address.postal_code = "12345";
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_EQ(1U, problems.size());
EXPECT_EQ(problems.begin()->first, POSTAL_CODE);
EXPECT_EQ(problems.begin()->second, MISMATCHING_VALUE);
@@ -146,9 +188,8 @@ TEST_F(PreloadAddressValidatorTest, USZipCode) {
// A zip code with a "90" in the middle.
address.postal_code = "12903";
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_EQ(1U, problems.size());
EXPECT_EQ(problems.begin()->first, POSTAL_CODE);
EXPECT_EQ(problems.begin()->second, MISMATCHING_VALUE);
@@ -157,9 +198,8 @@ TEST_F(PreloadAddressValidatorTest, USZipCode) {
// Invalid zip code (too many digits).
address.postal_code = "902911";
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_EQ(1U, problems.size());
EXPECT_EQ(problems.begin()->first, POSTAL_CODE);
EXPECT_EQ(problems.begin()->second, INVALID_FORMAT);
@@ -168,19 +208,16 @@ TEST_F(PreloadAddressValidatorTest, USZipCode) {
// Invalid zip code (too few digits).
address.postal_code = "9029";
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_EQ(1U, problems.size());
EXPECT_EQ(problems.begin()->first, POSTAL_CODE);
EXPECT_EQ(problems.begin()->second, INVALID_FORMAT);
}
-// Test case disabled because libaddressinput address validation doesn't do
-// those kinds of normalizations that this test case expects. TODO: Something.
-TEST_F(PreloadAddressValidatorTest, DISABLED_BasicValidation) {
+TEST_F(AddressValidatorTest, BasicValidation) {
// US rules should always be available, even though this load call fails.
- validator_->LoadRules("US", *loaded_);
+ validator_->LoadRules("US");
AddressData address;
address.region_code = "US";
address.language_code = "en";
@@ -188,48 +225,44 @@ TEST_F(PreloadAddressValidatorTest, DISABLED_BasicValidation) {
address.locality = "Paris";
address.postal_code = "75461";
address.address_line.push_back("123 Main St");
+ address.recipient = "Mr. Smith";
FieldProblemMap problems;
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
// The display name works as well as the key.
address.administrative_area = "Texas";
problems.clear();
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
// Ignore capitalization.
address.administrative_area = "tx";
problems.clear();
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
// Ignore capitalization.
address.administrative_area = "teXas";
problems.clear();
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
// Ignore diacriticals.
address.administrative_area = "T\u00E9xas";
problems.clear();
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
EXPECT_TRUE(problems.empty());
}
-TEST_F(PreloadAddressValidatorTest, BasicValidationFailure) {
+TEST_F(AddressValidatorTest, BasicValidationFailure) {
// US rules should always be available, even though this load call fails.
- validator_->LoadRules("US", *loaded_);
+ validator_->LoadRules("US");
AddressData address;
address.region_code = "US";
address.language_code = "en";
@@ -237,45 +270,45 @@ TEST_F(PreloadAddressValidatorTest, BasicValidationFailure) {
address.locality = "Paris";
address.postal_code = "75461";
address.address_line.push_back("123 Main St");
+ address.recipient = "Mr. Smith";
FieldProblemMap problems;
- EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
- validator_->Validate(address, NULL, &problems));
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(address, NULL, &problems));
ASSERT_EQ(1U, problems.size());
EXPECT_EQ(UNKNOWN_VALUE, problems.begin()->second);
EXPECT_EQ(ADMIN_AREA, problems.begin()->first);
}
-TEST_F(PreloadAddressValidatorTest, NoNullSuggestionsCrash) {
+TEST_F(AddressValidatorTest, NoNullSuggestionsCrash) {
AddressData address;
address.region_code = "US";
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, COUNTRY, 1, NULL));
}
-TEST_F(PreloadAddressValidatorTest, SuggestAdminAreaForPostalCode) {
+TEST_F(AddressValidatorTest, SuggestAdminAreaForPostalCode) {
AddressData address;
address.region_code = "US";
address.postal_code = "90291";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("CA", suggestions[0].administrative_area);
EXPECT_EQ("90291", suggestions[0].postal_code);
}
-TEST_F(PreloadAddressValidatorTest, SuggestLocalityForPostalCodeWithAdminArea) {
- validator_->LoadRules("TW", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestLocalityForPostalCodeWithAdminArea) {
AddressData address;
address.region_code = "TW";
address.postal_code = "515";
address.administrative_area = "Changhua";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("Dacun Township", suggestions[0].locality);
@@ -283,15 +316,15 @@ TEST_F(PreloadAddressValidatorTest, SuggestLocalityForPostalCodeWithAdminArea) {
EXPECT_EQ("515", suggestions[0].postal_code);
}
-TEST_F(PreloadAddressValidatorTest, SuggestAdminAreaForPostalCodeWithLocality) {
- validator_->LoadRules("TW", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestAdminAreaForPostalCodeWithLocality) {
AddressData address;
address.region_code = "TW";
address.postal_code = "515";
address.locality = "Dacun";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("Dacun Township", suggestions[0].locality);
@@ -299,149 +332,149 @@ TEST_F(PreloadAddressValidatorTest, SuggestAdminAreaForPostalCodeWithLocality) {
EXPECT_EQ("515", suggestions[0].postal_code);
}
-TEST_F(PreloadAddressValidatorTest, NoSuggestForPostalCodeWithWrongAdminArea) {
+TEST_F(AddressValidatorTest, NoSuggestForPostalCodeWithWrongAdminArea) {
AddressData address;
address.region_code = "US";
address.postal_code = "90066";
address.postal_code = "TX";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
EXPECT_TRUE(suggestions.empty());
}
-TEST_F(PreloadAddressValidatorTest, SuggestForLocality) {
- validator_->LoadRules("CN", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestForLocality) {
AddressData address;
address.region_code = "CN";
address.locality = "Anqin";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, LOCALITY, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("Anqing Shi", suggestions[0].locality);
- EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+ EXPECT_EQ("Anhui Sheng", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, SuggestForLocalityAndAdminArea) {
- validator_->LoadRules("CN", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestForLocalityAndAdminArea) {
AddressData address;
address.region_code = "CN";
address.locality = "Anqing";
address.administrative_area = "Anhui";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, LOCALITY, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_TRUE(suggestions[0].dependent_locality.empty());
EXPECT_EQ("Anqing Shi", suggestions[0].locality);
- EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+ EXPECT_EQ("Anhui Sheng", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, SuggestForAdminAreaAndLocality) {
- validator_->LoadRules("CN", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestForAdminAreaAndLocality) {
AddressData address;
address.region_code = "CN";
address.locality = "Anqing";
address.administrative_area = "Anhui";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_TRUE(suggestions[0].dependent_locality.empty());
EXPECT_TRUE(suggestions[0].locality.empty());
- EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+ EXPECT_EQ("Anhui Sheng", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, SuggestForDependentLocality) {
- validator_->LoadRules("CN", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestForDependentLocality) {
AddressData address;
address.region_code = "CN";
address.dependent_locality = "Zongyang";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(
address, DEPENDENT_LOCALITY, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("Zongyang Xian", suggestions[0].dependent_locality);
EXPECT_EQ("Anqing Shi", suggestions[0].locality);
- EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
+ EXPECT_EQ("Anhui Sheng", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest,
+TEST_F(LargeAddressValidatorTest,
NoSuggestForDependentLocalityWithWrongAdminArea) {
- validator_->LoadRules("CN", *loaded_);
AddressData address;
address.region_code = "CN";
address.dependent_locality = "Zongyang";
address.administrative_area = "Sichuan Sheng";
+ address.language_code = "zh-Latn";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(
address, DEPENDENT_LOCALITY, 10, &suggestions));
EXPECT_TRUE(suggestions.empty());
}
-TEST_F(PreloadAddressValidatorTest, EmptySuggestionsOverLimit) {
+TEST_F(AddressValidatorTest, EmptySuggestionsOverLimit) {
AddressData address;
address.region_code = "US";
address.administrative_area = "A";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
EXPECT_TRUE(suggestions.empty());
}
-TEST_F(PreloadAddressValidatorTest, PreferShortSuggestions) {
+TEST_F(AddressValidatorTest, PreferShortSuggestions) {
AddressData address;
address.region_code = "US";
address.administrative_area = "CA";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("CA", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, SuggestTheSingleMatchForFullMatchName) {
+TEST_F(AddressValidatorTest, SuggestTheSingleMatchForFullMatchName) {
AddressData address;
address.region_code = "US";
address.administrative_area = "Texas";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("Texas", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, SuggestAdminArea) {
+TEST_F(AddressValidatorTest, SuggestAdminArea) {
AddressData address;
address.region_code = "US";
address.administrative_area = "Cali";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("California", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, MultipleSuggestions) {
+TEST_F(AddressValidatorTest, MultipleSuggestions) {
AddressData address;
address.region_code = "US";
address.administrative_area = "MA";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
EXPECT_LT(1U, suggestions.size());
@@ -453,96 +486,104 @@ TEST_F(PreloadAddressValidatorTest, MultipleSuggestions) {
expected_suggestions.insert("Marshall Islands");
expected_suggestions.insert("Maryland");
for (std::vector<AddressData>::const_iterator it = suggestions.begin();
- it != suggestions.end(); ++it) {
+ it != suggestions.end();
+ ++it) {
expected_suggestions.erase(it->administrative_area);
}
EXPECT_TRUE(expected_suggestions.empty());
}
-TEST_F(PreloadAddressValidatorTest, SuggestNonLatinKeyWhenLanguageMatches) {
- validator_->LoadRules("KR", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestNonLatinKeyWhenLanguageMatches) {
AddressData address;
address.language_code = "ko";
address.region_code = "KR";
address.postal_code = "210-210";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("강원도", suggestions[0].administrative_area);
EXPECT_EQ("210-210", suggestions[0].postal_code);
}
-TEST_F(PreloadAddressValidatorTest, SuggestNonLatinKeyWhenUserInputIsNotLatin) {
- validator_->LoadRules("KR", *loaded_);
+TEST_F(LargeAddressValidatorTest, SuggestNonLatinKeyWhenUserInputIsNotLatin) {
AddressData address;
address.language_code = "en";
address.region_code = "KR";
address.administrative_area = "강원";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("강원도", suggestions[0].administrative_area);
}
-TEST_F(PreloadAddressValidatorTest,
+TEST_F(LargeAddressValidatorTest,
SuggestLatinNameWhenLanguageDiffersAndLatinNameAvailable) {
- validator_->LoadRules("KR", *loaded_);
AddressData address;
- address.language_code = "en";
+ address.language_code = "ko-Latn";
address.region_code = "KR";
address.postal_code = "210-210";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
EXPECT_EQ("Gangwon", suggestions[0].administrative_area);
EXPECT_EQ("210-210", suggestions[0].postal_code);
}
-TEST_F(PreloadAddressValidatorTest, SuggestLatinNameWhenUserInputIsLatin) {
- validator_->LoadRules("KR", *loaded_);
+TEST_F(AddressValidatorTest, NoSuggestionsForEmptyAddress) {
AddressData address;
- address.language_code = "ko";
- address.region_code = "KR";
- address.administrative_area = "Gang";
+ address.region_code = "US";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
- validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
+ EXPECT_EQ(
+ AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 999, &suggestions));
+ EXPECT_TRUE(suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, SuggestionIncludesCountry) {
+ AddressData address;
+ address.region_code = "US";
+ address.postal_code = "90291";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
ASSERT_EQ(1U, suggestions.size());
- EXPECT_EQ("Gangwon", suggestions[0].administrative_area);
+ EXPECT_EQ("US", suggestions[0].region_code);
}
-TEST_F(PreloadAddressValidatorTest, NoSuggestionsForEmptyAddress) {
+TEST_F(AddressValidatorTest, InvalidPostalCodeNoSuggestions) {
AddressData address;
address.region_code = "US";
+ address.postal_code = "0";
std::vector<AddressData> suggestions;
EXPECT_EQ(
- PreloadAddressValidator::SUCCESS,
+ AddressValidator::SUCCESS,
validator_->GetSuggestions(address, POSTAL_CODE, 999, &suggestions));
EXPECT_TRUE(suggestions.empty());
}
-TEST_F(PreloadAddressValidatorTest, SuggestionIncludesCountry) {
+TEST_F(AddressValidatorTest, MismatchedPostalCodeNoSuggestions) {
AddressData address;
address.region_code = "US";
+ address.administrative_area = "TX";
address.postal_code = "90291";
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
- validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
- ASSERT_EQ(1U, suggestions.size());
- EXPECT_EQ("US", suggestions[0].region_code);
+ EXPECT_EQ(
+ AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 999, &suggestions));
+ EXPECT_TRUE(suggestions.empty());
}
-TEST_F(PreloadAddressValidatorTest,
- SuggestOnlyForAdministrativeAreasAndPostalCode) {
+TEST_F(AddressValidatorTest, SuggestOnlyForAdministrativeAreasAndPostalCode) {
AddressData address;
address.region_code = "US";
address.administrative_area = "CA";
@@ -568,14 +609,24 @@ TEST_F(PreloadAddressValidatorTest,
for (size_t i = 0; i < kNumNoSuggestFields; ++i) {
std::vector<AddressData> suggestions;
- EXPECT_EQ(PreloadAddressValidator::SUCCESS,
+ EXPECT_EQ(AddressValidator::SUCCESS,
validator_->GetSuggestions(
address, kNoSugestFields[i], 999, &suggestions));
EXPECT_TRUE(suggestions.empty());
}
}
-TEST_F(PreloadAddressValidatorTest, CanonicalizeUsAdminAreaName) {
+TEST_F(AddressValidatorTest, SuggestionsAreCleared) {
+ AddressData address;
+ address.region_code = "US";
+
+ std::vector<AddressData> suggestions(1, address);
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+ EXPECT_TRUE(suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, CanonicalizeUsAdminAreaName) {
AddressData address;
address.region_code = "US";
address.administrative_area = "cALIFORNIa";
@@ -583,7 +634,7 @@ TEST_F(PreloadAddressValidatorTest, CanonicalizeUsAdminAreaName) {
EXPECT_EQ("CA", address.administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, CanonicalizeUsAdminAreaKey) {
+TEST_F(AddressValidatorTest, CanonicalizeUsAdminAreaKey) {
AddressData address;
address.region_code = "US";
address.administrative_area = "CA";
@@ -591,8 +642,8 @@ TEST_F(PreloadAddressValidatorTest, CanonicalizeUsAdminAreaKey) {
EXPECT_EQ("CA", address.administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, CanonicalizeJpAdminAreaKey) {
- validator_->LoadRules("JP", *loaded_);
+TEST_F(AddressValidatorTest, CanonicalizeJpAdminAreaKey) {
+ validator_->LoadRules("JP");
AddressData address;
address.region_code = "JP";
address.administrative_area = "東京都";
@@ -600,8 +651,8 @@ TEST_F(PreloadAddressValidatorTest, CanonicalizeJpAdminAreaKey) {
EXPECT_EQ("東京都", address.administrative_area);
}
-TEST_F(PreloadAddressValidatorTest, CanonicalizeJpAdminAreaLatinName) {
- validator_->LoadRules("JP", *loaded_);
+TEST_F(AddressValidatorTest, CanonicalizeJpAdminAreaLatinName) {
+ validator_->LoadRules("JP");
AddressData address;
address.region_code = "JP";
address.administrative_area = "tOKYo";
@@ -609,4 +660,81 @@ TEST_F(PreloadAddressValidatorTest, CanonicalizeJpAdminAreaLatinName) {
EXPECT_EQ("TOKYO", address.administrative_area);
}
+TEST_F(AddressValidatorTest, TokushimaSuggestionIsValid) {
+ validator_->LoadRules("JP");
+ AddressData address;
+ address.region_code = "JP";
+ address.administrative_area = "Toku";
+ address.language_code = "ja-Latn";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
+ ASSERT_EQ(1U, suggestions.size());
+ EXPECT_EQ("TOKUSHIMA", suggestions[0].administrative_area);
+
+ FieldProblemMap filter;
+ for (int i = UNEXPECTED_FIELD; i <= USES_P_O_BOX; ++i)
+ filter.insert(std::make_pair(ADMIN_AREA, static_cast<AddressProblem>(i)));
+
+ FieldProblemMap problems;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->ValidateAddress(suggestions[0], &filter, &problems));
+ EXPECT_TRUE(problems.empty());
+}
+
+TEST_F(AddressValidatorTest, ValidPostalCodeInSuggestion) {
+ validator_->LoadRules("US");
+ AddressData address;
+ address.region_code = "US";
+ address.administrative_area = "New";
+ address.postal_code = "13699";
+
+ std::vector<AddressData> suggestions;
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 999, &suggestions));
+ ASSERT_EQ(1U, suggestions.size());
+ EXPECT_EQ("New York", suggestions[0].administrative_area);
+
+ address.administrative_area = "New";
+ address.postal_code = "03755";
+
+ EXPECT_EQ(AddressValidator::SUCCESS,
+ validator_->GetSuggestions(address, ADMIN_AREA, 999, &suggestions));
+ ASSERT_EQ(1U, suggestions.size());
+ EXPECT_EQ("New Hampshire", suggestions[0].administrative_area);
+}
+
+TEST_F(AddressValidatorTest, ValidateRequiredFieldsWithoutRules) {
+ // Do not load the rules for JP.
+ AddressData address;
+ address.region_code = "JP";
+
+ FieldProblemMap problems;
+ EXPECT_EQ(AddressValidator::RULES_UNAVAILABLE,
+ validator_->ValidateAddress(address, NULL, &problems));
+ EXPECT_FALSE(problems.empty());
+
+ for (FieldProblemMap::const_iterator it = problems.begin();
+ it != problems.end();
+ ++it) {
+ EXPECT_EQ(MISSING_REQUIRED_FIELD, it->second);
+ }
+}
+
+TEST_F(AddressValidatorTest,
+ DoNotValidateRequiredFieldsWithoutRulesWhenErorrIsFiltered) {
+ // Do not load the rules for JP.
+ AddressData address;
+ address.region_code = "JP";
+
+ FieldProblemMap filter;
+ filter.insert(std::make_pair(COUNTRY, UNKNOWN_VALUE));
+
+ FieldProblemMap problems;
+ EXPECT_EQ(AddressValidator::RULES_UNAVAILABLE,
+ validator_->ValidateAddress(address, &filter, &problems));
+ EXPECT_TRUE(problems.empty());
+}
+
} // namespace
diff --git a/third_party/libaddressinput/chromium/chrome_downloader_impl.cc b/third_party/libaddressinput/chromium/chrome_downloader_impl.cc
index 507cc9e..950500e 100644
--- a/third_party/libaddressinput/chromium/chrome_downloader_impl.cc
+++ b/third_party/libaddressinput/chromium/chrome_downloader_impl.cc
@@ -55,27 +55,9 @@ ChromeDownloaderImpl::~ChromeDownloaderImpl() {
STLDeleteValues(&requests_);
}
-void ChromeDownloaderImpl::Download(
- const std::string& url,
- scoped_ptr<Callback> downloaded) {
- GURL resource(url);
- if (!resource.SchemeIsSecure()) {
- (*downloaded)(false, url, make_scoped_ptr(new std::string()));
- return;
- }
-
- scoped_ptr<net::URLFetcher> fetcher(
- net::URLFetcher::Create(resource, net::URLFetcher::GET, this));
- fetcher->SetLoadFlags(
- net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
- fetcher->SetRequestContext(getter_);
-
- Request* request = new Request(url, fetcher.Pass(), downloaded.Pass());
- request->fetcher->SaveResponseWithWriter(
- scoped_ptr<net::URLFetcherResponseWriter>(
- new UnownedStringWriter(&request->data)));
- requests_[request->fetcher.get()] = request;
- request->fetcher->Start();
+void ChromeDownloaderImpl::Download(const std::string& url,
+ const Callback& downloaded) const {
+ const_cast<ChromeDownloaderImpl*>(this)->DoDownload(url, downloaded);
}
void ChromeDownloaderImpl::OnURLFetchComplete(const net::URLFetcher* source) {
@@ -87,7 +69,7 @@ void ChromeDownloaderImpl::OnURLFetchComplete(const net::URLFetcher* source) {
scoped_ptr<std::string> data(new std::string());
if (ok)
data->swap(request->second->data);
- (*request->second->callback)(ok, request->second->url, data.Pass());
+ request->second->callback(ok, request->second->url, data.release());
delete request->second;
requests_.erase(request);
@@ -95,9 +77,31 @@ void ChromeDownloaderImpl::OnURLFetchComplete(const net::URLFetcher* source) {
ChromeDownloaderImpl::Request::Request(const std::string& url,
scoped_ptr<net::URLFetcher> fetcher,
- scoped_ptr<Callback> callback)
+ const Callback& callback)
: url(url),
fetcher(fetcher.Pass()),
- callback(callback.Pass()) {}
+ callback(callback) {}
+
+void ChromeDownloaderImpl::DoDownload(const std::string& url,
+ const Callback& downloaded) {
+ GURL resource(url);
+ if (!resource.SchemeIsSecure()) {
+ downloaded(false, url, NULL);
+ return;
+ }
+
+ scoped_ptr<net::URLFetcher> fetcher(
+ net::URLFetcher::Create(resource, net::URLFetcher::GET, this));
+ fetcher->SetLoadFlags(
+ net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES);
+ fetcher->SetRequestContext(getter_);
+
+ Request* request = new Request(url, fetcher.Pass(), downloaded);
+ request->fetcher->SaveResponseWithWriter(
+ scoped_ptr<net::URLFetcherResponseWriter>(
+ new UnownedStringWriter(&request->data)));
+ requests_[request->fetcher.get()] = request;
+ request->fetcher->Start();
+}
} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/chrome_downloader_impl.h b/third_party/libaddressinput/chromium/chrome_downloader_impl.h
index 2f0bf0d..ff9ff9f 100644
--- a/third_party/libaddressinput/chromium/chrome_downloader_impl.h
+++ b/third_party/libaddressinput/chromium/chrome_downloader_impl.h
@@ -10,7 +10,7 @@
#include "base/memory/scoped_vector.h"
#include "net/url_request/url_fetcher_delegate.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/downloader.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/downloader.h"
namespace net {
class URLFetcher;
@@ -29,7 +29,7 @@ class ChromeDownloaderImpl : public ::i18n::addressinput::Downloader,
// ::i18n::addressinput::Downloader:
virtual void Download(const std::string& url,
- scoped_ptr<Callback> downloaded) OVERRIDE;
+ const Callback& downloaded) const OVERRIDE;
// net::URLFetcherDelegate:
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
@@ -38,16 +38,19 @@ class ChromeDownloaderImpl : public ::i18n::addressinput::Downloader,
struct Request {
Request(const std::string& url,
scoped_ptr<net::URLFetcher> fetcher,
- scoped_ptr<Callback> callback);
+ const Callback& callback);
std::string url;
// The data that's received.
std::string data;
// The object that manages retrieving the data.
scoped_ptr<net::URLFetcher> fetcher;
- scoped_ptr<Callback> callback;
+ const Callback& callback;
};
+ // Non-const version of Download().
+ void DoDownload(const std::string& url, const Callback& downloaded);
+
net::URLRequestContextGetter* const getter_; // weak
// Maps from active url fetcher to request metadata. The value is owned.
diff --git a/third_party/libaddressinput/chromium/chrome_downloader_impl_unittest.cc b/third_party/libaddressinput/chromium/chrome_downloader_impl_unittest.cc
index 2bf1e01..5fee4d6 100644
--- a/third_party/libaddressinput/chromium/chrome_downloader_impl_unittest.cc
+++ b/third_party/libaddressinput/chromium/chrome_downloader_impl_unittest.cc
@@ -35,27 +35,31 @@ class ChromeDownloaderImplTest : public testing::Test {
scoped_refptr<net::TestURLRequestContextGetter> getter(
new net::TestURLRequestContextGetter(
base::MessageLoopProxy::current()));
- ChromeDownloaderImpl impl(getter);
- impl.Download(url_.spec(), BuildCallback());
+ ChromeDownloaderImpl impl(getter.get());
+ scoped_ptr< ::i18n::addressinput::Downloader::Callback> callback(
+ ::i18n::addressinput::BuildCallback(
+ this, &ChromeDownloaderImplTest::OnDownloaded));
+ impl.Download(url_.spec(), *callback);
base::MessageLoop::current()->RunUntilIdle();
}
void set_url(const GURL& url) { url_ = url; }
- const std::string& data() { return *data_; }
- bool success() { return success_; }
+ bool success() const { return success_; }
+ bool has_data() const { return !!data_; }
- private:
- scoped_ptr<ChromeDownloaderImpl::Callback> BuildCallback() {
- return ::i18n::addressinput::BuildScopedPtrCallback(
- this, &ChromeDownloaderImplTest::OnDownloaded);
+ const std::string& data() const {
+ DCHECK(data_);
+ return *data_;
}
+ private:
// Callback for when download is finished.
void OnDownloaded(bool success,
const std::string& url,
- scoped_ptr<std::string> data) {
+ std::string* data) {
+ ASSERT_FALSE(success && data == NULL);
success_ = success;
- data_ = data.Pass();
+ data_.reset(data);
}
base::MessageLoop loop_;
@@ -81,7 +85,7 @@ TEST_F(ChromeDownloaderImplTest, Failure) {
SetFakeResponse(kFakePayload, net::HTTP_INTERNAL_SERVER_ERROR);
Download();
EXPECT_FALSE(success());
- EXPECT_EQ(std::string(), data());
+ EXPECT_TRUE(!has_data() || data().empty());
}
TEST_F(ChromeDownloaderImplTest, RejectsInsecureScheme) {
@@ -90,7 +94,7 @@ TEST_F(ChromeDownloaderImplTest, RejectsInsecureScheme) {
SetFakeResponse(kFakePayload, net::HTTP_OK);
Download();
EXPECT_FALSE(success());
- EXPECT_EQ(std::string(), data());
+ EXPECT_TRUE(!has_data() || data().empty());
}
} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/chrome_rule_test.cc b/third_party/libaddressinput/chromium/chrome_rule_test.cc
index 064e7da..b1b6682 100644
--- a/third_party/libaddressinput/chromium/chrome_rule_test.cc
+++ b/third_party/libaddressinput/chromium/chrome_rule_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/libaddressinput/chromium/cpp/src/rule.h"
+#include "third_party/libaddressinput/src/cpp/src/rule.h"
#include <string>
diff --git a/third_party/libaddressinput/chromium/chrome_storage_impl.cc b/third_party/libaddressinput/chromium/chrome_storage_impl.cc
index b9d6d8b..6c559bb 100644
--- a/third_party/libaddressinput/chromium/chrome_storage_impl.cc
+++ b/third_party/libaddressinput/chromium/chrome_storage_impl.cc
@@ -4,8 +4,10 @@
#include "third_party/libaddressinput/chromium/chrome_storage_impl.h"
+#include "base/memory/scoped_ptr.h"
#include "base/prefs/writeable_pref_store.h"
#include "base/values.h"
+#include "third_party/libaddressinput/chromium/fallback_data_store.h"
namespace autofill {
@@ -17,55 +19,53 @@ ChromeStorageImpl::ChromeStorageImpl(WriteablePrefStore* store)
ChromeStorageImpl::~ChromeStorageImpl() {}
-void ChromeStorageImpl::Put(const std::string& key,
- scoped_ptr<std::string> data) {
+void ChromeStorageImpl::Put(const std::string& key, std::string* data) {
+ DCHECK(data);
+ scoped_ptr<std::string> owned_data(data);
scoped_ptr<base::StringValue> string_value(
new base::StringValue(std::string()));
- string_value->GetString()->swap(*data);
+ string_value->GetString()->swap(*owned_data);
backing_store_->SetValue(key, string_value.release());
}
-void ChromeStorageImpl::Get(
- const std::string& key,
- scoped_ptr<Storage::Callback> data_ready) const {
+void ChromeStorageImpl::Get(const std::string& key,
+ const Storage::Callback& data_ready) const {
// |Get()| should not be const, so this is just a thunk that fixes that.
- const_cast<ChromeStorageImpl*>(this)->DoGet(key, data_ready.Pass());
+ const_cast<ChromeStorageImpl*>(this)->DoGet(key, data_ready);
}
void ChromeStorageImpl::OnPrefValueChanged(const std::string& key) {}
void ChromeStorageImpl::OnInitializationCompleted(bool succeeded) {
- for (std::vector<Request*>::iterator iter =
- outstanding_requests_.begin();
+ for (std::vector<Request*>::iterator iter = outstanding_requests_.begin();
iter != outstanding_requests_.end(); ++iter) {
- DoGet((*iter)->key, (*iter)->callback.Pass());
+ DoGet((*iter)->key, (*iter)->callback);
}
outstanding_requests_.clear();
}
-void ChromeStorageImpl::DoGet(
- const std::string& key,
- scoped_ptr<Storage::Callback> data_ready) {
+void ChromeStorageImpl::DoGet(const std::string& key,
+ const Storage::Callback& data_ready) {
if (!backing_store_->IsInitializationComplete()) {
- outstanding_requests_.push_back(
- new Request(key, data_ready.Pass()));
+ outstanding_requests_.push_back(new Request(key, data_ready));
return;
}
const base::Value* value = NULL;
- const base::StringValue* string_value = NULL;
- if (backing_store_->GetValue(key, &value) &&
- value->GetAsString(&string_value)) {
- (*data_ready)(true, key, string_value->GetString());
+ scoped_ptr<std::string> data(new std::string);
+ if (backing_store_->GetValue(key, &value) && value->GetAsString(data.get())) {
+ data_ready(true, key, data.release());
+ } else if (FallbackDataStore::Get(key, data.get())) {
+ data_ready(true, key, data.release());
} else {
- (*data_ready)(false, key, std::string());
+ data_ready(false, key, NULL);
}
}
ChromeStorageImpl::Request::Request(const std::string& key,
- scoped_ptr<Storage::Callback> callback)
+ const Callback& callback)
: key(key),
- callback(callback.Pass()) {}
+ callback(callback) {}
} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/chrome_storage_impl.h b/third_party/libaddressinput/chromium/chrome_storage_impl.h
index 5ee657b..b68c72b 100644
--- a/third_party/libaddressinput/chromium/chrome_storage_impl.h
+++ b/third_party/libaddressinput/chromium/chrome_storage_impl.h
@@ -11,8 +11,7 @@
#include "base/memory/scoped_vector.h"
#include "base/prefs/pref_store.h"
#include "base/scoped_observer.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/storage.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/util/scoped_ptr.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
class WriteablePrefStore;
@@ -28,9 +27,8 @@ class ChromeStorageImpl : public ::i18n::addressinput::Storage,
virtual ~ChromeStorageImpl();
// ::i18n::addressinput::Storage implementation.
- virtual void Put(const std::string& key, scoped_ptr<std::string> data)
- OVERRIDE;
- virtual void Get(const std::string& key, scoped_ptr<Callback> data_ready)
+ virtual void Put(const std::string& key, std::string* data) OVERRIDE;
+ virtual void Get(const std::string& key, const Callback& data_ready)
const OVERRIDE;
// PrefStore::Observer implementation.
@@ -39,14 +37,14 @@ class ChromeStorageImpl : public ::i18n::addressinput::Storage,
private:
struct Request {
- Request(const std::string& key, scoped_ptr<Callback> callback);
+ Request(const std::string& key, const Callback& callback);
std::string key;
- scoped_ptr<Callback> callback;
+ const Callback& callback;
};
// Non-const version of Get().
- void DoGet(const std::string& key, scoped_ptr<Callback> data_ready);
+ void DoGet(const std::string& key, const Callback& data_ready);
WriteablePrefStore* backing_store_; // weak
diff --git a/third_party/libaddressinput/chromium/chrome_storage_impl_unittest.cc b/third_party/libaddressinput/chromium/chrome_storage_impl_unittest.cc
index 4bbdbd0..277bfb9 100644
--- a/third_party/libaddressinput/chromium/chrome_storage_impl_unittest.cc
+++ b/third_party/libaddressinput/chromium/chrome_storage_impl_unittest.cc
@@ -7,9 +7,9 @@
#include <string>
#include "base/prefs/value_map_pref_store.h"
-#include "cpp/test/storage_test_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/callback.h"
+#include "third_party/libaddressinput/chromium/storage_test_runner.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
namespace autofill {
@@ -25,7 +25,7 @@ class ChromeStorageImplTest : public testing::Test {
scoped_refptr<ValueMapPrefStore> store_;
ChromeStorageImpl storage_;
- i18n::addressinput::StorageTestRunner runner_;
+ StorageTestRunner runner_;
};
TEST_F(ChromeStorageImplTest, StandardStorageTests) {
diff --git a/third_party/libaddressinput/chromium/fallback_data_store.cc b/third_party/libaddressinput/chromium/fallback_data_store.cc
new file mode 100644
index 0000000..4c20aa1
--- /dev/null
+++ b/third_party/libaddressinput/chromium/fallback_data_store.cc
@@ -0,0 +1,203 @@
+// Copyright 2014 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 "fallback_data_store.h"
+
+#include <string>
+
+namespace autofill {
+
+bool FallbackDataStore::Get(const std::string& key, std::string* data) {
+ if (key != "data/US")
+ return false;
+
+ // Available at https://i18napis.appspot.com/ssl-aggregate-address/data/US.
+ // The appended checksum is valid, but the timestamp is old.
+ data->assign(
+ "timestamp=0\n"
+ "checksum=38d4bcdadfe494ffe062a7ad668d66d6\n"
+ "{\"data/US/LA\": {\"lang\": \"en\", \"zipex\": \"70000,71599\", \"nam"
+ "e\": \"Louisiana\", \"zip\": \"70|71[0-5]\", \"key\": \"LA\", \"id\":"
+ " \"data/US/LA\"}, \"data/US/VT\": {\"lang\": \"en\", \"zipex\": \"0500"
+ "0,05999\", \"name\": \"Vermont\", \"zip\": \"05\", \"key\": \"VT\", \""
+ "id\": \"data/US/VT\"}, \"data/US/NM\": {\"lang\": \"en\", \"zipex\": \""
+ "87000,88499\", \"name\": \"New Mexico\", \"zip\": \"87|88[0-4]\", \"k"
+ "ey\": \"NM\", \"id\": \"data/US/NM\"}, \"data/US/NJ\": {\"lang\": \"e"
+ "n\", \"zipex\": \"07000,08999\", \"name\": \"New Jersey\", \"zip\": \""
+ "0[78]\", \"key\": \"NJ\", \"id\": \"data/US/NJ\"}, \"data/US/NH\": {\""
+ "lang\": \"en\", \"zipex\": \"03000,03899\", \"name\": \"New Hampshire\""
+ ", \"zip\": \"03[0-8]\", \"key\": \"NH\", \"id\": \"data/US/NH\"}, \"d"
+ "ata/US/ND\": {\"lang\": \"en\", \"zipex\": \"58000,58999\", \"name\":"
+ " \"North Dakota\", \"zip\": \"58\", \"key\": \"ND\", \"id\": \"data/US"
+ "/ND\"}, \"data/US/NE\": {\"lang\": \"en\", \"zipex\": \"68000,69999\","
+ " \"name\": \"Nebraska\", \"zip\": \"6[89]\", \"key\": \"NE\", \"id\":"
+ " \"data/US/NE\"}, \"data/US/NC\": {\"lang\": \"en\", \"zipex\": \"2700"
+ "0,28999\", \"name\": \"North Carolina\", \"zip\": \"2[78]\", \"key\":"
+ " \"NC\", \"id\": \"data/US/NC\"}, \"data/US/PR\": {\"lang\": \"en\", \""
+ "zipex\": \"00600,00799:00900,00999\", \"name\": \"Puerto Rico\", \"zi"
+ "p\": \"00[679]\", \"key\": \"PR\", \"id\": \"data/US/PR\"}, \"data/US/"
+ "RI\": {\"lang\": \"en\", \"zipex\": \"02800,02999\", \"name\": \"Rhode"
+ " Island\", \"zip\": \"02[89]\", \"key\": \"RI\", \"id\": \"data/US/RI\""
+ "}, \"data/US/NY\": {\"lang\": \"en\", \"zipex\": \"10000,14999:06390:"
+ "00501:00544\", \"name\": \"New York\", \"zip\": \"1[0-4]|06390|00501|0"
+ "0544\", \"key\": \"NY\", \"id\": \"data/US/NY\"}, \"data/US/NV\": {\"l"
+ "ang\": \"en\", \"zipex\": \"88900,89999\", \"name\": \"Nevada\", \"zi"
+ "p\": \"889|89\", \"key\": \"NV\", \"id\": \"data/US/NV\"}, \"data/US/K"
+ "Y\": {\"lang\": \"en\", \"zipex\": \"40000,42799\", \"name\": \"Kentuc"
+ "ky\", \"zip\": \"4[01]|42[0-7]\", \"key\": \"KY\", \"id\": \"data/US/K"
+ "Y\"}, \"data/US/PA\": {\"lang\": \"en\", \"zipex\": \"15000,19699\", \""
+ "name\": \"Pennsylvania\", \"zip\": \"1[5-8]|19[0-6]\", \"key\": \"PA\""
+ ", \"id\": \"data/US/PA\"}, \"data/US/OH\": {\"lang\": \"en\", \"zipe"
+ "x\": \"43000,45999\", \"name\": \"Ohio\", \"zip\": \"4[3-5]\", \"key\""
+ ": \"OH\", \"id\": \"data/US/OH\"}, \"data/US/AS\": {\"lang\": \"en\","
+ " \"zipex\": \"96799\", \"name\": \"American Samoa\", \"zip\": \"96799\""
+ ", \"key\": \"AS\", \"id\": \"data/US/AS\"}, \"data/US/AA\": {\"lang\""
+ ": \"en\", \"zipex\": \"34000,34099\", \"name\": \"Armed Forces (AA)\","
+ " \"zip\": \"340\", \"key\": \"AA\", \"id\": \"data/US/AA\"}, \"data/US"
+ "/GA\": {\"lang\": \"en\", \"zipex\": \"30000,31999:39800,39899:39901\""
+ ", \"name\": \"Georgia\", \"zip\": \"3[01]|398|39901\", \"key\": \"GA\""
+ ", \"id\": \"data/US/GA\"}, \"data/US/OK\": {\"lang\": \"en\", \"zipex\""
+ ": \"73000,74999\", \"name\": \"Oklahoma\", \"zip\": \"7[34]\", \"key\""
+ ": \"OK\", \"id\": \"data/US/OK\"}, \"data/US/CO\": {\"lang\": \"en\","
+ " \"zipex\": \"80000,81999\", \"name\": \"Colorado\", \"zip\": \"8[01]\""
+ ", \"key\": \"CO\", \"id\": \"data/US/CO\"}, \"data/US/AK\": {\"lang\""
+ ": \"en\", \"zipex\": \"99500,99999\", \"name\": \"Alaska\", \"zip\": \""
+ "99[5-9]\", \"key\": \"AK\", \"id\": \"data/US/AK\"}, \"data/US/WV\": "
+ "{\"lang\": \"en\", \"zipex\": \"24700,26999\", \"name\": \"West Virgin"
+ "ia\", \"zip\": \"24[7-9]|2[56]\", \"key\": \"WV\", \"id\": \"data/US/W"
+ "V\"}, \"data/US/AL\": {\"lang\": \"en\", \"zipex\": \"35000,36999\", \""
+ "name\": \"Alabama\", \"zip\": \"3[56]\", \"key\": \"AL\", \"id\": \"d"
+ "ata/US/AL\"}, \"data/US/GU\": {\"lang\": \"en\", \"zipex\": \"96910,96"
+ "932\", \"name\": \"Guam\", \"zip\": \"969([1-2]\\\\d|3[12])\", \"key\":"
+ " \"GU\", \"id\": \"data/US/GU\"}, \"data/US/AR\": {\"lang\": \"en\", \""
+ "zipex\": \"71600,72999\", \"name\": \"Arkansas\", \"zip\": \"71[6-9]|"
+ "72\", \"key\": \"AR\", \"id\": \"data/US/AR\"}, \"data/US/AP\": {\"lan"
+ "g\": \"en\", \"zipex\": \"96200,96699\", \"name\": \"Armed Forces (AP"
+ ")\", \"zip\": \"96[2-6]\", \"key\": \"AP\", \"id\": \"data/US/AP\"}, \""
+ "data/US/AZ\": {\"lang\": \"en\", \"zipex\": \"85000,86999\", \"name\""
+ ": \"Arizona\", \"zip\": \"8[56]\", \"key\": \"AZ\", \"id\": \"data/US/"
+ "AZ\"}, \"data/US/VI\": {\"lang\": \"en\", \"zipex\": \"00800,00899\","
+ " \"name\": \"Virgin Islands\", \"zip\": \"008\", \"key\": \"VI\", \"i"
+ "d\": \"data/US/VI\"}, \"data/US/CT\": {\"lang\": \"en\", \"zipex\": \""
+ "06000,06999\", \"name\": \"Connecticut\", \"zip\": \"06\", \"key\": \""
+ "CT\", \"id\": \"data/US/CT\"}, \"data/US/ME\": {\"lang\": \"en\", \"zi"
+ "pex\": \"03900,04999\", \"name\": \"Maine\", \"zip\": \"039|04\", \"ke"
+ "y\": \"ME\", \"id\": \"data/US/ME\"}, \"data/US/MD\": {\"lang\": \"en\""
+ ", \"zipex\": \"20600,21999\", \"name\": \"Maryland\", \"zip\": \"20[6"
+ "-9]|21\", \"key\": \"MD\", \"id\": \"data/US/MD\"}, \"data/US/IN\": {\""
+ "lang\": \"en\", \"zipex\": \"46000,47999\", \"name\": \"Indiana\", \""
+ "zip\": \"4[67]\", \"key\": \"IN\", \"id\": \"data/US/IN\"}, \"data/US/"
+ "MA\": {\"lang\": \"en\", \"zipex\": \"01000,02799:05501:05544\", \"nam"
+ "e\": \"Massachusetts\", \"zip\": \"01|02[0-7]|05501|05544\", \"key\":"
+ " \"MA\", \"id\": \"data/US/MA\"}, \"data/US/IL\": {\"lang\": \"en\", \""
+ "zipex\": \"60000,62999\", \"name\": \"Illinois\", \"zip\": \"6[0-2]\""
+ ", \"key\": \"IL\", \"id\": \"data/US/IL\"}, \"data/US/MO\": {\"lang\":"
+ " \"en\", \"zipex\": \"63000,65999\", \"name\": \"Missouri\", \"zip\":"
+ " \"6[3-5]\", \"key\": \"MO\", \"id\": \"data/US/MO\"}, \"data/US/MN\":"
+ " {\"lang\": \"en\", \"zipex\": \"55000,56799\", \"name\": \"Minnesota\""
+ ", \"zip\": \"55|56[0-7]\", \"key\": \"MN\", \"id\": \"data/US/MN\"},"
+ " \"data/US/IA\": {\"lang\": \"en\", \"zipex\": \"50000,52999\", \"nam"
+ "e\": \"Iowa\", \"zip\": \"5[0-2]\", \"key\": \"IA\", \"id\": \"data/US"
+ "/IA\"}, \"data/US/TN\": {\"lang\": \"en\", \"zipex\": \"37000,38599\","
+ " \"name\": \"Tennessee\", \"zip\": \"37|38[0-5]\", \"key\": \"TN\", \""
+ "id\": \"data/US/TN\"}, \"data/US/WY\": {\"lang\": \"en\", \"zipex\": \""
+ "82000,83199:83414\", \"name\": \"Wyoming\", \"zip\": \"82|83[01]|8341"
+ "4\", \"key\": \"WY\", \"id\": \"data/US/WY\"}, \"data/US/KS\": {\"lan"
+ "g\": \"en\", \"zipex\": \"66000,67999\", \"name\": \"Kansas\", \"zip\""
+ ": \"6[67]\", \"key\": \"KS\", \"id\": \"data/US/KS\"}, \"data/US/MI\":"
+ " {\"lang\": \"en\", \"zipex\": \"48000,49999\", \"name\": \"Michigan\""
+ ", \"zip\": \"4[89]\", \"key\": \"MI\", \"id\": \"data/US/MI\"}, \"data"
+ "/US/ID\": {\"lang\": \"en\", \"zipex\": \"83200,83999\", \"name\": \"I"
+ "daho\", \"zip\": \"83[2-9]\", \"key\": \"ID\", \"id\": \"data/US/ID\"}"
+ ", \"data/US/MT\": {\"lang\": \"en\", \"zipex\": \"59000,59999\", \"nam"
+ "e\": \"Montana\", \"zip\": \"59\", \"key\": \"MT\", \"id\": \"data/US/"
+ "MT\"}, \"data/US/MS\": {\"lang\": \"en\", \"zipex\": \"38600,39799\","
+ " \"name\": \"Mississippi\", \"zip\": \"38[6-9]|39[0-7]\", \"key\": \"M"
+ "S\", \"id\": \"data/US/MS\"}, \"data/US/MP\": {\"lang\": \"en\", \"zip"
+ "ex\": \"96950,96952\", \"name\": \"Northern Mariana Islands\", \"zip\""
+ ": \"9695[0-2]\", \"key\": \"MP\", \"id\": \"data/US/MP\"}, \"data/US/P"
+ "W\": {\"lang\": \"en\", \"zipex\": \"96940\", \"name\": \"Palau\", \"z"
+ "ip\": \"969(39|40)\", \"key\": \"PW\", \"id\": \"data/US/PW\"}, \"data"
+ "/US/SC\": {\"lang\": \"en\", \"zipex\": \"29000,29999\", \"name\": \"S"
+ "outh Carolina\", \"zip\": \"29\", \"key\": \"SC\", \"id\": \"data/US/S"
+ "C\"}, \"data/US/MH\": {\"lang\": \"en\", \"zipex\": \"96960,96979\", \""
+ "name\": \"Marshall Islands\", \"zip\": \"969[67]\", \"key\": \"MH\","
+ " \"id\": \"data/US/MH\"}, \"data/US/WI\": {\"lang\": \"en\", \"zipex\""
+ ": \"53000,54999\", \"name\": \"Wisconsin\", \"zip\": \"5[34]\", \"key\""
+ ": \"WI\", \"id\": \"data/US/WI\"}, \"data/US/SD\": {\"lang\": \"en\","
+ " \"zipex\": \"57000,57999\", \"name\": \"South Dakota\", \"zip\": \"5"
+ "7\", \"key\": \"SD\", \"id\": \"data/US/SD\"}, \"data/US/OR\": {\"lan"
+ "g\": \"en\", \"zipex\": \"97000,97999\", \"name\": \"Oregon\", \"zip\""
+ ": \"97\", \"key\": \"OR\", \"id\": \"data/US/OR\"}, \"data/US/UT\": {\""
+ "lang\": \"en\", \"zipex\": \"84000,84999\", \"name\": \"Utah\", \"zi"
+ "p\": \"84\", \"key\": \"UT\", \"id\": \"data/US/UT\"}, \"data/US/VA\":"
+ " {\"lang\": \"en\", \"zipex\": \"20100,20199:22000,24699\", \"name\":"
+ " \"Virginia\", \"zip\": \"201|2[23]|24[0-6]\", \"key\": \"VA\", \"id\""
+ ": \"data/US/VA\"}, \"data/US/AE\": {\"lang\": \"en\", \"zipex\": \"090"
+ "00,09999\", \"name\": \"Armed Forces (AE)\", \"zip\": \"09\", \"key\":"
+ " \"AE\", \"id\": \"data/US/AE\"}, \"data/US/FL\": {\"lang\": \"en\", \""
+ "zipex\": \"32000,33999:34100,34999\", \"name\": \"Florida\", \"zip\":"
+ " \"3[23]|34[1-9]\", \"key\": \"FL\", \"id\": \"data/US/FL\"}, \"data/U"
+ "S/FM\": {\"lang\": \"en\", \"zipex\": \"96941,96944\", \"name\": \"Mic"
+ "ronesia\", \"zip\": \"9694[1-4]\", \"key\": \"FM\", \"id\": \"data/US/"
+ "FM\"}, \"data/US/DE\": {\"lang\": \"en\", \"zipex\": \"19700,19999\","
+ " \"name\": \"Delaware\", \"zip\": \"19[7-9]\", \"key\": \"DE\", \"id\""
+ ": \"data/US/DE\"}, \"data/US/CA\": {\"lang\": \"en\", \"zipex\": \"900"
+ "00,96199\", \"name\": \"California\", \"zip\": \"9[0-5]|96[01]\", \"ke"
+ "y\": \"CA\", \"id\": \"data/US/CA\"}, \"data/US\": {\"lang\": \"en\","
+ " \"upper\": \"CS\", \"sub_zipexs\": \"35000,36999~99500,99999~96799~85"
+ "000,86999~71600,72999~34000,34099~09000,09999~96200,96699~90000,96199~"
+ "80000,81999~06000,06999~19700,19999~20000,20099:20200,20599:56900,5699"
+ "9~32000,33999:34100,34999~30000,31999:39800,39899:39901~96910,96932~96"
+ "700,96798:96800,96899~83200,83999~60000,62999~46000,47999~50000,52999~"
+ "66000,67999~40000,42799~70000,71599~03900,04999~96960,96979~20600,2199"
+ "9~01000,02799:05501:05544~48000,49999~96941,96944~55000,56799~38600,39"
+ "799~63000,65999~59000,59999~68000,69999~88900,89999~03000,03899~07000,"
+ "08999~87000,88499~10000,14999:06390:00501:00544~27000,28999~58000,5899"
+ "9~96950,96952~43000,45999~73000,74999~97000,97999~96940~15000,19699~00"
+ "600,00799:00900,00999~02800,02999~29000,29999~57000,57999~37000,38599~"
+ "75000,79999:88500,88599:73301:73344~84000,84999~05000,05999~00800,0089"
+ "9~20100,20199:22000,24699~98000,99499~24700,26999~53000,54999~82000,83"
+ "199:83414\", \"zipex\": \"95014,22162-1010\", \"name\": \"UNITED STATE"
+ "S\", \"zip\": \"\\\\d{5}([ \\\\-]\\\\d{4})?\", \"zip_name_type\": \"zi"
+ "p\", \"fmt\": \"%N%n%O%n%A%n%C %S %Z\", \"state_name_type\": \"state\""
+ ", \"languages\": \"en\", \"sub_keys\": \"AL~AK~AS~AZ~AR~AA~AE~AP~CA~CO"
+ "~CT~DE~DC~FL~GA~GU~HI~ID~IL~IN~IA~KS~KY~LA~ME~MH~MD~MA~MI~FM~MN~MS~MO~"
+ "MT~NE~NV~NH~NJ~NM~NY~NC~ND~MP~OH~OK~OR~PW~PA~PR~RI~SC~SD~TN~TX~UT~VT~V"
+ "I~VA~WA~WV~WI~WY\","
+ " \"key\": \"US\", \"require\": \"ACSZ\", \"posturl\": \"https://tools."
+ "usps.com/go/ZipLookupAction!input.action\", \"id\": \"dat"
+ "a/US\", \"sub_names\": \"Alabama~Alaska~American Samoa~Arizona~Arkansa"
+ "s~Armed Forces (AA)~Armed Forces (AE)~Armed Forces (AP)~California~Col"
+ "orado~Connecticut~Delaware~District of Columbia~Florida~Georgia~Guam~H"
+ "awaii~Idaho~Illinois~Indiana~Iowa~Kansas~Kentucky~Louisiana~Maine~Mars"
+ "hall Islands~Maryland~Massachusetts~Michigan~Micronesia~Minnesota~Miss"
+ "issippi~Missouri~Montana~Nebraska~Nevada~New Hampshire~New Jersey~New "
+ "Mexico~New York~North Carolina~North Dakota~Northern Mariana Islands~O"
+ "hio~Oklahoma~Oregon~Palau~Pennsylvania~Puerto Rico~Rhode Island~South "
+ "Carolina~South Dakota~Tennessee~Texas~Utah~Vermont~Virgin Islands~Virg"
+ "inia~Washington~West Virginia~Wisconsin~Wyoming\", \"sub_zips\": \"3[5"
+ "6]~99[5-9]~96799~8[56]~71[6-9]|72~340~09~96[2-6]~9[0-5]|96[01]~8[01]~0"
+ "6~19[7-9]~20[02-5]|569~3[23]|34[1-9]~3[01]|398|39901~969([1-2]\\\\d|3[12"
+ "])~967[0-8]|9679[0-8]|968~83[2-9]~6[0-2]~4[67]~5[0-2]~6[67]~4[01]|42[0"
+ "-7]~70|71[0-5]~039|04~969[67]~20[6-9]|21~01|02[0-7]|05501|05544~4[89]~"
+ "9694[1-4]~55|56[0-7]~38[6-9]|39[0-7]~6[3-5]~59~6[89]~889|89~03[0-8]~0["
+ "78]~87|88[0-4]~1[0-4]|06390|00501|00544~2[78]~58~9695[0-2]~4[3-5]~7[34"
+ "]~97~969(39|40)~1[5-8]|19[0-6]~00[679]~02[89]~29~57~37|38[0-5]~7[5-9]|"
+ "885|73301|73344~84~05~008~201|2[23]|24[0-6]~98|99[0-4]~24[7-9]|2[56]~5"
+ "[34]~82|83[01]|83414\"}, \"data/US/TX\": {\"lang\": \"en\", \"zipex\":"
+ " \"75000,79999:88500,88599:73301:73344\", \"name\": \"Texas\", \"zip\""
+ ": \"7[5-9]|885|73301|73344\", \"key\": \"TX\", \"id\": \"data/US/TX\"}"
+ ", \"data/US/WA\": {\"lang\": \"en\", \"zipex\": \"98000,99499\", \"nam"
+ "e\": \"Washington\", \"zip\": \"98|99[0-4]\", \"key\": \"WA\", \"id\":"
+ " \"data/US/WA\"}, \"data/US/DC\": {\"lang\": \"en\", \"zipex\": \"2000"
+ "0,20099:20200,20599:56900,56999\", \"name\": \"District of Columbia\","
+ " \"zip\": \"20[02-5]|569\", \"key\": \"DC\", \"id\": \"data/US/DC\"},"
+ " \"data/US/HI\": {\"lang\": \"en\", \"zipex\": \"96700,96798:96800,968"
+ "99\", \"name\": \"Hawaii\", \"zip\": \"967[0-8]|9679[0-8]|968\", \"key"
+ "\": \"HI\", \"id\": \"data/US/HI\"}}");
+ return true;
+}
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/fallback_data_store.h b/third_party/libaddressinput/chromium/fallback_data_store.h
new file mode 100644
index 0000000..fd8d680
--- /dev/null
+++ b/third_party/libaddressinput/chromium/fallback_data_store.h
@@ -0,0 +1,22 @@
+// Copyright 2014 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 THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_FALLBACK_DATA_STORE_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_FALLBACK_DATA_STORE_H_
+
+#include <string>
+
+namespace autofill {
+
+class FallbackDataStore {
+ public:
+ // Gets stale, but valid static data for |key|. Should only be used as a last
+ // resort after attempts to check the local cache or the webserver have
+ // failed.
+ static bool Get(const std::string& key, std::string* data);
+};
+
+} // namespace autofill
+
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_FALLBACK_DATA_STORE_H_
diff --git a/third_party/libaddressinput/chromium/fallback_data_store_unittest.cc b/third_party/libaddressinput/chromium/fallback_data_store_unittest.cc
new file mode 100644
index 0000000..31f32b1
--- /dev/null
+++ b/third_party/libaddressinput/chromium/fallback_data_store_unittest.cc
@@ -0,0 +1,40 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/fallback_data_store.h"
+
+#include <cstddef>
+#include <ctime>
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/src/util/json.h"
+#include "third_party/libaddressinput/src/cpp/src/validating_util.h"
+
+namespace autofill {
+
+using i18n::addressinput::Json;
+using i18n::addressinput::ValidatingUtil;
+
+TEST(FallbackDataStore, Parsability) {
+ std::string data;
+ ASSERT_TRUE(FallbackDataStore::Get("data/US", &data));
+
+ // Should be stale.
+ EXPECT_FALSE(ValidatingUtil::UnwrapTimestamp(&data, time(NULL)));
+
+ // Should be uncorrupted.
+ EXPECT_TRUE(ValidatingUtil::UnwrapChecksum(&data));
+
+ // Should be valid JSON.
+ Json json;
+ ASSERT_TRUE(json.ParseObject(data));
+
+ // Should have a dictionary for "data/US", as this is aggregate data.
+ std::string not_checked;
+ EXPECT_FALSE(json.GetStringValueForKey("data/US", &not_checked));
+ EXPECT_TRUE(json.HasDictionaryValueForKey("data/US"));
+}
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/input_suggester.cc b/third_party/libaddressinput/chromium/input_suggester.cc
new file mode 100644
index 0000000..5e6c7e7
--- /dev/null
+++ b/third_party/libaddressinput/chromium/input_suggester.cc
@@ -0,0 +1,521 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/input_suggester.h"
+
+#include <cstddef>
+#include <set>
+#include <utility>
+
+#include "base/logging.h"
+#include "third_party/libaddressinput/chromium/trie.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/region_data.h"
+
+namespace autofill {
+
+using ::i18n::addressinput::AddressData;
+using ::i18n::addressinput::AddressField;
+using ::i18n::addressinput::BuildCallback;
+using ::i18n::addressinput::FieldProblemMap;
+using ::i18n::addressinput::PreloadSupplier;
+using ::i18n::addressinput::RegionData;
+using ::i18n::addressinput::RegionDataBuilder;
+
+using ::i18n::addressinput::ADMIN_AREA;
+using ::i18n::addressinput::COUNTRY;
+using ::i18n::addressinput::DEPENDENT_LOCALITY;
+using ::i18n::addressinput::LOCALITY;
+using ::i18n::addressinput::POSTAL_CODE;
+
+using ::i18n::addressinput::INVALID_FORMAT;
+using ::i18n::addressinput::MISMATCHING_VALUE;
+
+namespace {
+
+// Initial size for the buffer used in the canonicalizer.
+static const size_t kInitialBufferSize = 32;
+
+// A region and its metadata useful for constructing a suggestion.
+struct Suggestion {
+ public:
+ // Builds a suggestion of |region_to_suggest|. Does not take ownership of
+ // |region_to_suggest|, which should not be NULL.
+ Suggestion(const RegionData* region_to_suggest,
+ AddressField matching_address_field,
+ bool region_key_matches)
+ : region_to_suggest(region_to_suggest),
+ matching_address_field(matching_address_field),
+ region_key_matches(region_key_matches) {
+ DCHECK(region_to_suggest);
+ }
+
+ ~Suggestion() {}
+
+ // The region that should be suggested. For example, if the region is ("CA",
+ // "California"), then either "CA" or "California" should be suggested.
+ const RegionData* region_to_suggest;
+
+ // The field in the address for which the suggestion should be made. For
+ // example, ADMIN_AREA in US means the suggestion should be made for the field
+ // labeled "State".
+ AddressField matching_address_field;
+
+ // True if the key of the region matches user input (the name may or may not
+ // match). "CA" should be suggested for a ("CA", "California") region.
+ //
+ // False if only the name of the region matches user input (the key does not
+ // match). "California" should be suggested for a ("CA", "California") region.
+ bool region_key_matches;
+};
+
+// Suggestions for an address. Contains lists of suggestions for administrative
+// area, locality, and dependent locality fields of an address.
+class AddressSuggestions {
+ public:
+ AddressSuggestions() {}
+ ~AddressSuggestions() {}
+
+ // Marks all regions at |address_field| level as matching user input.
+ void AllRegionsMatchForField(AddressField address_field) {
+ all_regions_match_input_.insert(address_field);
+ }
+
+ // Marks given regions at |address_field| level as matching user input. The
+ // |regions_match_key| parameter contains the regions that match user input by
+ // their keys. The |regions_match_name| parameter contains the regions that
+ // match user input by their names.
+ //
+ // The |address_field| parameter should be either ADMIN_AREA, LOCALITY, or
+ // DEPENDENT_LOCALITY.
+ bool AddRegions(AddressField address_field,
+ const std::set<const RegionData*>& regions_match_key,
+ const std::set<const RegionData*>& regions_match_name) {
+ DCHECK(address_field >= ADMIN_AREA);
+ DCHECK(address_field <= DEPENDENT_LOCALITY);
+
+ AddressField parent_address_field =
+ static_cast<AddressField>(address_field - 1);
+
+ bool all_parents_match =
+ parent_address_field == COUNTRY ||
+ all_regions_match_input_.find(parent_address_field) !=
+ all_regions_match_input_.end();
+
+ // Cannot build |address_field| level suggestions if there are no matches in
+ // |parent_address_field| level regions.
+ const RegionsMatchInput* parents = NULL;
+ if (address_field > ADMIN_AREA && !all_parents_match) {
+ parents = &regions_match_input_[parent_address_field];
+ if (parents->keys.empty() && parents->names.empty())
+ return false;
+ }
+
+ RegionsMatchInput* regions = NULL;
+ if (address_field < DEPENDENT_LOCALITY)
+ regions = &regions_match_input_[address_field];
+
+ std::vector<Suggestion>* suggestions = &suggestions_[address_field];
+ bool added_suggestions = false;
+
+ // Iterate over both |regions_match_key| and |regions_match_name| and build
+ // Suggestion objects based on the given RegionData objects. Advance either
+ // one iterator at a time (if they point to different data) or both
+ // iterators at once (if they point to the same data).
+ for (std::set<const RegionData*>::const_iterator
+ key_it = regions_match_key.begin(),
+ name_it = regions_match_name.begin();
+ key_it != regions_match_key.end() ||
+ name_it != regions_match_name.end();) {
+ const RegionData* key_region =
+ key_it != regions_match_key.end() ? *key_it : NULL;
+ const RegionData* name_region =
+ name_it != regions_match_name.end() ? *name_it : NULL;
+
+ // Regions that do not have a parent that also matches input will not
+ // become suggestions.
+ bool key_region_has_parent =
+ all_parents_match ||
+ (parents && !parents->keys.empty() && key_region &&
+ parents->keys.find(&key_region->parent()) != parents->keys.end());
+ bool name_region_has_parent =
+ all_parents_match ||
+ (parents && !parents->names.empty() && name_region &&
+ parents->names.find(&name_region->parent()) != parents->names.end());
+
+ if (name_region && (!key_region || name_region < key_region)) {
+ if (name_region_has_parent) {
+ suggestions->push_back(Suggestion(name_region, address_field, false));
+ added_suggestions = true;
+ if (regions)
+ regions->names.insert(name_region);
+ }
+
+ ++name_it;
+ } else if (key_region && (!name_region || key_region < name_region)) {
+ if (key_region_has_parent) {
+ suggestions->push_back(Suggestion(key_region, address_field, true));
+ added_suggestions = true;
+ if (regions)
+ regions->keys.insert(key_region);
+ }
+
+ ++key_it;
+ } else {
+ if (key_region_has_parent) {
+ suggestions->push_back(Suggestion(key_region, address_field, true));
+ added_suggestions = true;
+ if (regions) {
+ regions->keys.insert(key_region);
+ regions->names.insert(name_region);
+ }
+ }
+
+ ++key_it;
+ ++name_it;
+ }
+ }
+
+ return added_suggestions;
+ }
+
+ // Swaps the suggestions for the smallest sub-region into |suggestions|.
+ // |this| is not usable after this call due to using the swap() operation.
+ //
+ // The |suggestions| parameter should not be NULL.
+ void SwapSmallestSubRegionSuggestions(std::vector<Suggestion>* suggestions) {
+ DCHECK(suggestions);
+ for (int i = DEPENDENT_LOCALITY; i >= ADMIN_AREA; --i) {
+ std::vector<Suggestion>* result =
+ &suggestions_[static_cast<AddressField>(i)];
+ if (!result->empty()) {
+ suggestions->swap(*result);
+ return;
+ }
+ }
+ }
+
+ private:
+ // The sets of non-owned regions used for looking up regions that match user
+ // input by keys and names.
+ struct RegionsMatchInput {
+ std::set<const RegionData*> keys;
+ std::set<const RegionData*> names;
+ };
+
+ // The regions that match user input at ADMIN_AREA and LOCALITY levels.
+ std::map<AddressField, RegionsMatchInput> regions_match_input_;
+
+ // The set of fields for which all regions match user input. Used to avoid
+ // storing a long list in |regions_match_input_| and later looking it up
+ // there.
+ std::set<AddressField> all_regions_match_input_;
+
+ // Suggestions at ADMIN_AREA, LOCALITY, and DEPENDENT_LOCALITY levels.
+ std::map<AddressField, std::vector<Suggestion> > suggestions_;
+
+ DISALLOW_COPY_AND_ASSIGN(AddressSuggestions);
+};
+
+} // namespace
+
+InputSuggester::StringCanonicalizer::StringCanonicalizer()
+ : buffer_(kInitialBufferSize, 0) {
+ UErrorCode error_code = U_ZERO_ERROR;
+ collator_.reset(
+ icu::Collator::createInstance(icu::Locale::getRoot(), error_code));
+ DCHECK(U_SUCCESS(error_code));
+ collator_->setStrength(icu::Collator::PRIMARY);
+}
+
+InputSuggester::StringCanonicalizer::~StringCanonicalizer() {}
+
+const std::vector<uint8_t>& InputSuggester::StringCanonicalizer::Canonicalize(
+ const std::string& original) const {
+ DCHECK(!original.empty());
+
+ icu::UnicodeString icu_str(original.c_str(),
+ static_cast<int32_t>(original.length()));
+ int32_t sort_key_size =
+ collator_->getSortKey(icu_str, &buffer_[0], buffer_size());
+ DCHECK_LT(0, sort_key_size);
+
+ if (sort_key_size > buffer_size()) {
+ buffer_.resize(sort_key_size * 2, 0);
+ sort_key_size = collator_->getSortKey(icu_str, &buffer_[0], buffer_size());
+ DCHECK_LT(0, sort_key_size);
+ DCHECK_GT(buffer_size(), sort_key_size);
+ }
+
+ return buffer_;
+}
+
+int32_t InputSuggester::StringCanonicalizer::buffer_size() const {
+ return static_cast<int32_t>(buffer_.size());
+}
+
+// All sub-regions of a COUNTRY level region, organized into tries for lookup by
+// region name or key.
+class InputSuggester::SubRegionData {
+ public:
+ SubRegionData()
+ : initialized_(false),
+ smallest_region_size_(COUNTRY),
+ canonicalizer_(NULL) {}
+
+ ~SubRegionData() {}
+
+ bool is_initialized() const { return initialized_; }
+
+ // Adds the sub-regions of |country_region| into tries. Uses
+ // |shared_canonicalizer| for case and diacritic insensitive lookup of the
+ // sub-regions. Should be called at most once.
+ void Initialize(const RegionData& country_region,
+ const StringCanonicalizer& shared_canonicalizer) {
+ DCHECK(!initialized_);
+ DCHECK(!country_region.has_parent());
+
+ initialized_ = true;
+ canonicalizer_ = &shared_canonicalizer;
+
+ if (!country_region.sub_regions().empty())
+ AddSubRegionsOf(country_region, COUNTRY);
+ }
+
+ // Adds the suggestions for |user_input| into |suggestions| when user is
+ // typing in |focused_field|.
+ void BuildSuggestions(const AddressData& user_input,
+ AddressField focused_field,
+ std::vector<Suggestion>* suggestions) {
+ DCHECK(initialized_);
+
+ // Do not suggest anything if there's no suggestion data for the focused
+ // field.
+ if (focused_field != POSTAL_CODE && smallest_region_size_ < focused_field)
+ return;
+
+ // Non-owned regions that match a field value by region key.
+ std::set<const RegionData*> regions_match_key;
+
+ // Non-owned regions that match a field value by region name.
+ std::set<const RegionData*> regions_match_name;
+
+ AddressSuggestions address_suggestions;
+ for (int i = ADMIN_AREA; i <= focused_field && i <= DEPENDENT_LOCALITY;
+ ++i) {
+ AddressField address_field = static_cast<AddressField>(i);
+ AddressField parent_address_field = static_cast<AddressField>(i - 1);
+
+ const std::string& field_value = user_input.GetFieldValue(address_field);
+ const std::string& parent_field_value =
+ user_input.GetFieldValue(parent_address_field);
+
+ if (field_value.empty() &&
+ (address_field == ADMIN_AREA || parent_field_value.empty())) {
+ address_suggestions.AllRegionsMatchForField(address_field);
+ continue;
+ }
+
+ if (field_value.empty()) {
+ DCHECK_NE(address_field, focused_field);
+ continue;
+ }
+
+ regions_match_key.clear();
+ regions_match_name.clear();
+
+ const FieldTries& field_tries = field_tries_[address_field];
+
+ const std::vector<uint8_t>& canonicalized_value =
+ canonicalizer_->Canonicalize(field_value);
+
+ field_tries.keys.FindDataForKeyPrefix(canonicalized_value,
+ &regions_match_key);
+ field_tries.names.FindDataForKeyPrefix(canonicalized_value,
+ &regions_match_name);
+
+ bool added_suggestions = address_suggestions.AddRegions(
+ address_field, regions_match_key, regions_match_name);
+
+ // Do not suggest anything if the focused field does not have suggestions.
+ if (address_field == focused_field && !added_suggestions)
+ return;
+ }
+
+ address_suggestions.SwapSmallestSubRegionSuggestions(suggestions);
+ }
+
+ private:
+ // The tries to lookup regions for a specific field by keys and names. For
+ // example, the FieldTries for ADMIN_AREA in US will have keys for "AL", "AK",
+ // "AS", etc and names for "Alabama", "Alaska", "American Samoa", etc. The
+ // struct is uncopyable due to Trie objects being uncopyable.
+ struct FieldTries {
+ Trie<const RegionData*> keys;
+ Trie<const RegionData*> names;
+ };
+
+ // Adds the sub-regions of |parent_region| into tries.
+ void AddSubRegionsOf(const RegionData& parent_region,
+ AddressField parent_field) {
+ DCHECK(!parent_region.sub_regions().empty());
+
+ AddressField address_field = static_cast<AddressField>(parent_field + 1);
+ DCHECK(address_field >= ADMIN_AREA);
+ DCHECK(address_field <= DEPENDENT_LOCALITY);
+
+ FieldTries* field_tries = &field_tries_[address_field];
+ for (std::vector<const RegionData*>::const_iterator it =
+ parent_region.sub_regions().begin();
+ it != parent_region.sub_regions().end();
+ ++it) {
+ const RegionData* region = *it;
+ DCHECK(region);
+ DCHECK(!region->key().empty());
+ DCHECK(!region->name().empty());
+
+ field_tries->keys.AddDataForKey(
+ canonicalizer_->Canonicalize(region->key()), region);
+
+ field_tries->names.AddDataForKey(
+ canonicalizer_->Canonicalize(region->name()), region);
+
+ if (smallest_region_size_ < address_field)
+ smallest_region_size_ = address_field;
+
+ if (!region->sub_regions().empty())
+ AddSubRegionsOf(*region, address_field);
+ }
+ }
+
+ // True after Initialize() has been called.
+ bool initialized_;
+
+ // The tries to lookup regions for ADMIN_AREA, LOCALITY, and
+ // DEPENDENT_LOCALITY.
+ std::map<AddressField, FieldTries> field_tries_;
+
+ // The smallest size of a sub-region that has data. For example, this is
+ // ADMIN_AREA in US, but DEPENDENT_LOCALITY in CN.
+ AddressField smallest_region_size_;
+
+ // A shared instance of string canonicalizer for case and diacritic comparison
+ // of region keys and names.
+ const StringCanonicalizer* canonicalizer_;
+};
+
+InputSuggester::InputSuggester(PreloadSupplier* supplier)
+ : region_data_builder_(supplier),
+ input_helper_(supplier),
+ validator_(supplier),
+ validated_(BuildCallback(this, &InputSuggester::Validated)) {}
+
+InputSuggester::~InputSuggester() {}
+
+void InputSuggester::GetSuggestions(const AddressData& user_input,
+ AddressField focused_field,
+ size_t suggestions_limit,
+ std::vector<AddressData>* suggestions) {
+ DCHECK(suggestions);
+ DCHECK(focused_field == POSTAL_CODE ||
+ (focused_field >= ADMIN_AREA && focused_field <= DEPENDENT_LOCALITY));
+
+ AddressData address_copy = user_input;
+
+ // Do not suggest anything if the user input is empty.
+ if (address_copy.IsFieldEmpty(focused_field))
+ return;
+
+ if (focused_field == POSTAL_CODE) {
+ // Do not suggest anything if the user is typing an invalid postal code.
+ FieldProblemMap problems;
+ FieldProblemMap filter;
+ filter.insert(std::make_pair(POSTAL_CODE, INVALID_FORMAT));
+ validator_.Validate(address_copy,
+ true, // Allow postal office boxes.
+ false, // Do not require recipient name.
+ &filter,
+ &problems,
+ *validated_);
+ if (!problems.empty())
+ return;
+
+ // Fill in the sub-regions based on the postal code.
+ input_helper_.FillAddress(&address_copy);
+ }
+
+ // Lazily initialize the mapping from COUNTRY level regions to all of their
+ // sub-regions with metadata for generating suggestions.
+ std::string unused_best_language;
+ const RegionData& region_data =
+ region_data_builder_.Build(address_copy.region_code,
+ address_copy.language_code,
+ &unused_best_language);
+ SubRegionData* sub_region_data = &sub_regions_[&region_data];
+ if (!sub_region_data->is_initialized())
+ sub_region_data->Initialize(region_data, canonicalizer_);
+
+ // Build the list of regions that match |address_copy| when the user is typing
+ // in the |focused_field|.
+ std::vector<Suggestion> suggested_regions;
+ sub_region_data->BuildSuggestions(
+ address_copy, focused_field, &suggested_regions);
+
+ FieldProblemMap problems;
+ FieldProblemMap filter;
+ filter.insert(std::make_pair(POSTAL_CODE, MISMATCHING_VALUE));
+
+ // Generate suggestions based on the regions.
+ for (std::vector<Suggestion>::const_iterator suggested_region_it =
+ suggested_regions.begin();
+ suggested_region_it != suggested_regions.end();
+ ++suggested_region_it) {
+ AddressData address;
+ address.region_code = address_copy.region_code;
+ address.postal_code = address_copy.postal_code;
+
+ // Traverse the tree of regions from the smallest |region_to_suggest| to the
+ // country-wide "root" of the tree. Use the region names or keys found at
+ // each of the levels of the tree to build the |address| to suggest.
+ AddressField address_field = suggested_region_it->matching_address_field;
+ for (const RegionData* region = suggested_region_it->region_to_suggest;
+ region->has_parent();
+ region = &region->parent()) {
+ address.SetFieldValue(address_field,
+ suggested_region_it->region_key_matches
+ ? region->key()
+ : region->name());
+ address_field = static_cast<AddressField>(address_field - 1);
+ }
+
+ // Do not suggest an address with a mismatching postal code.
+ problems.clear();
+ validator_.Validate(address,
+ true, // Allow postal office boxes.
+ false, // Do not require recipient name.
+ &filter,
+ &problems,
+ *validated_);
+ if (!problems.empty())
+ continue;
+
+ // Do not add more suggestions than |suggestions_limit|.
+ if (suggestions->size() >= suggestions_limit) {
+ suggestions->clear();
+ return;
+ }
+
+ suggestions->push_back(address);
+ }
+}
+
+void InputSuggester::Validated(bool success,
+ const AddressData&,
+ const FieldProblemMap&) {
+ DCHECK(success);
+}
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/input_suggester.h b/third_party/libaddressinput/chromium/input_suggester.h
new file mode 100644
index 0000000..b361057
--- /dev/null
+++ b/third_party/libaddressinput/chromium/input_suggester.h
@@ -0,0 +1,133 @@
+// Copyright 2014 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 THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_INPUT_SUGGESTER_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_INPUT_SUGGESTER_H_
+
+#include <stdint.h>
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/icu/source/i18n/unicode/coll.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_input_helper.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/region_data_builder.h"
+
+namespace i18n {
+namespace addressinput {
+class PreloadSupplier;
+class RegionData;
+struct AddressData;
+}
+}
+
+namespace autofill {
+
+// Suggests address completions for a partially entered address from the user.
+class InputSuggester {
+ public:
+ // Does not take ownership of |supplier|, which should not be NULL.
+ explicit InputSuggester(::i18n::addressinput::PreloadSupplier* supplier);
+ ~InputSuggester();
+
+ // Fills in |suggestions| for the partially typed in |user_input|, assuming
+ // the user is typing in the |focused_field|. If the number of |suggestions|
+ // is over the |suggestion_limit|, then returns no |suggestions| at all.
+ //
+ // Sample user input 1:
+ // country code = "US"
+ // postal code = "90066"
+ // focused field = POSTAL_CODE
+ // suggestions limit = 1
+ // Suggestion:
+ // [{administrative_area: "CA"}]
+ //
+ // Sample user input 2:
+ // country code = "CN"
+ // dependent locality = "Zongyang"
+ // focused field = DEPENDENT_LOCALITY
+ // suggestions limit = 10
+ // Suggestion:
+ // [{dependent_locality: "Zongyang Xian",
+ // locality: "Anqing Shi",
+ // administrative_area: "Anhui Sheng"}]
+ //
+ // Builds the index for generating suggestions lazily.
+ //
+ // The |suggestions| parameter should not be NULL. The |focused_field|
+ // parameter should be either POSTAL_CODE or between ADMIN_AREA and
+ // DEPENDENT_LOCALITY inclusively.
+ void GetSuggestions(
+ const ::i18n::addressinput::AddressData& user_input,
+ ::i18n::addressinput::AddressField focused_field,
+ size_t suggestion_limit,
+ std::vector< ::i18n::addressinput::AddressData>* suggestions);
+
+ private:
+ class SubRegionData;
+
+ // Canonicalizes strings for case and diacritic insensitive comparison.
+ class StringCanonicalizer {
+ public:
+ // Initializes the canonicalizer. This is slow, so avoid calling it more
+ // often than necessary.
+ StringCanonicalizer();
+ ~StringCanonicalizer();
+
+ // Returns a 0-terminated canonical version of the string that can be used
+ // for comparing strings regardless of diacritics and capitalization.
+ // Canonicalize("Texas") == Canonicalize("T\u00E9xas");
+ // Canonicalize("Texas") == Canonicalize("teXas");
+ // Canonicalize("Texas") != Canonicalize("California");
+ //
+ // The output is not human-readable.
+ // Canonicalize("Texas") != "Texas";
+ //
+ // The |original| parameter should not be empty.
+ const std::vector<uint8_t>& Canonicalize(const std::string& original) const;
+
+ private:
+ int32_t buffer_size() const;
+
+ mutable std::vector<uint8_t> buffer_;
+ scoped_ptr<icu::Collator> collator_;
+
+ DISALLOW_COPY_AND_ASSIGN(StringCanonicalizer);
+ };
+
+ // The method to be invoked by |validated_| callback.
+ void Validated(bool success,
+ const ::i18n::addressinput::AddressData&,
+ const ::i18n::addressinput::FieldProblemMap&);
+
+ // Data source for region data.
+ ::i18n::addressinput::RegionDataBuilder region_data_builder_;
+
+ // Suggests sub-regions based on postal code.
+ const ::i18n::addressinput::AddressInputHelper input_helper_;
+
+ // Verifies that suggested sub-regions match the postal code.
+ ::i18n::addressinput::AddressValidator validator_;
+
+ // The callback for |validator_| to invoke when validation finishes.
+ const scoped_ptr<const ::i18n::addressinput::AddressValidator::Callback>
+ validated_;
+
+ // A mapping from a COUNTRY level region to a collection of all of its
+ // sub-regions along with metadata used to construct suggestions.
+ std::map<const ::i18n::addressinput::RegionData*, SubRegionData> sub_regions_;
+
+ // Canonicalizes strings for case and diacritic insensitive search of
+ // sub-region names.
+ StringCanonicalizer canonicalizer_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputSuggester);
+};
+
+} // namespace autofill
+
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_INPUT_SUGGESTER_H_
diff --git a/third_party/libaddressinput/chromium/json.cc b/third_party/libaddressinput/chromium/json.cc
index 5437e1e..7e1a66a 100644
--- a/third_party/libaddressinput/chromium/json.cc
+++ b/third_party/libaddressinput/chromium/json.cc
@@ -2,12 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "cpp/src/util/json.h"
+#include "third_party/libaddressinput/src/cpp/src/util/json.h"
+
+#include <map>
+#include <utility>
#include "base/basictypes.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
#include "base/values.h"
namespace i18n {
@@ -15,108 +19,128 @@ namespace addressinput {
namespace {
-// A base class for Chrome Json objects. JSON gets parsed into a
-// base::DictionaryValue and data is accessed via the Json interface.
-class ChromeJson : public Json {
- public:
- virtual bool GetStringValueForKey(const std::string& key, std::string* value)
- const OVERRIDE;
- virtual bool GetJsonValueForKey(const std::string& key,
- scoped_ptr<Json>* value) const OVERRIDE;
- protected:
- ChromeJson() {}
- virtual ~ChromeJson() {}
+// Returns |json| parsed into a JSON dictionary. Sets |parser_error| to true if
+// parsing failed.
+::scoped_ptr<const base::DictionaryValue> Parse(const std::string& json,
+ bool* parser_error) {
+ DCHECK(parser_error);
+ ::scoped_ptr<const base::DictionaryValue> result;
- virtual const base::DictionaryValue* GetDict() const = 0;
+ // |json| is converted to a |c_str()| here because rapidjson and other parts
+ // of the standalone library use char* rather than std::string.
+ ::scoped_ptr<const base::Value> parsed(base::JSONReader::Read(json.c_str()));
+ *parser_error = !parsed || !parsed->IsType(base::Value::TYPE_DICTIONARY);
- DISALLOW_COPY_AND_ASSIGN(ChromeJson);
-};
+ if (*parser_error)
+ result.reset(new base::DictionaryValue);
+ else
+ result.reset(static_cast<const base::DictionaryValue*>(parsed.release()));
-// A Json object that will parse a string and own the parsed data.
-class JsonDataOwner : public ChromeJson {
- public:
- JsonDataOwner() {}
- virtual ~JsonDataOwner() {}
+ return result.Pass();
+}
- virtual bool ParseObject(const std::string& json) OVERRIDE {
- dict_.reset();
+// Returns the list of keys in |dict|.
+std::vector<std::string> GetKeysFromDictionary(
+ const base::DictionaryValue& dict) {
+ std::vector<std::string> keys;
+ for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance())
+ keys.push_back(it.key());
+ return keys;
+}
- // |json| is converted to a |c_str()| here because rapidjson and other parts
- // of the standalone library use char* rather than std::string.
- scoped_ptr<base::Value> parsed(base::JSONReader::Read(json.c_str()));
- if (parsed && parsed->IsType(base::Value::TYPE_DICTIONARY))
- dict_.reset(static_cast<base::DictionaryValue*>(parsed.release()));
+} // namespace
- return !!dict_;
- }
+// Implementation of JSON parser for libaddressinput using JSON parser in
+// Chrome.
+class Json::JsonImpl {
+ public:
+ explicit JsonImpl(const std::string& json)
+ : owned_(Parse(json, &parser_error_)),
+ dict_(*owned_),
+ keys_(GetKeysFromDictionary(dict_)) {}
- protected:
- virtual const base::DictionaryValue* GetDict() const OVERRIDE {
- return dict_.get();
- }
+ ~JsonImpl() { STLDeleteValues(&sub_dicts_); }
- private:
- scoped_ptr<base::DictionaryValue> dict_;
+ bool parser_error() const { return parser_error_; }
- DISALLOW_COPY_AND_ASSIGN(JsonDataOwner);
-};
+ const std::vector<std::string>& keys() const { return keys_; }
-// A Json object which will point to data that's been parsed by a different
-// ChromeJson. It does not own its data and is only valid as long as its parent
-// ChromeJson is valid.
-class JsonDataCopy : public ChromeJson {
- public:
- explicit JsonDataCopy(const base::DictionaryValue* dict) :
- dict_(dict) {}
- virtual ~JsonDataCopy() {}
+ bool GetStringValueForKey(const std::string& key, std::string* value) const {
+ return dict_.GetStringWithoutPathExpansion(key, value);
+ }
- virtual bool ParseObject(const std::string& json) OVERRIDE {
- NOTREACHED();
- return false;
+ bool HasDictionaryValueForKey(const std::string& key) {
+ return !!FindDictionary(key);
}
- protected:
- virtual const base::DictionaryValue* GetDict() const OVERRIDE {
- return dict_;
+ const Json& GetDictionaryValueForKey(const std::string& key) {
+ const Json* result = FindDictionary(key);
+ DCHECK(result);
+ return *result;
}
private:
- const base::DictionaryValue* dict_; // weak reference.
+ explicit JsonImpl(const base::DictionaryValue& dict)
+ : parser_error_(false), dict_(dict), keys_(GetKeysFromDictionary(dict)) {}
- DISALLOW_COPY_AND_ASSIGN(JsonDataCopy);
-};
+ // The caller does not own the returned value, which can be NULL if there's no
+ // dictionary for |key|.
+ const Json* FindDictionary(const std::string& key) {
+ std::map<std::string, Json*>::const_iterator it = sub_dicts_.find(key);
+ if (it != sub_dicts_.end())
+ return it->second;
-// ChromeJson ------------------------------------------------------------------
+ const base::DictionaryValue* sub_dict = NULL;
+ if (!dict_.GetDictionaryWithoutPathExpansion(key, &sub_dict) || !sub_dict)
+ return NULL;
-bool ChromeJson::GetStringValueForKey(const std::string& key,
- std::string* value) const {
- return GetDict()->GetStringWithoutPathExpansion(key, value);
-}
+ std::pair<std::map<std::string, Json*>::iterator, bool> result =
+ sub_dicts_.insert(std::make_pair(key, new Json));
+ DCHECK(result.second);
+
+ Json* sub_json = result.first->second;
+ sub_json->impl_.reset(new JsonImpl(*sub_dict));
-bool ChromeJson::GetJsonValueForKey(const std::string& key,
- scoped_ptr<Json>* value) const {
- const base::DictionaryValue* sub_dict = NULL;
- if (!GetDict()->GetDictionaryWithoutPathExpansion(key, &sub_dict) ||
- !sub_dict) {
- return false;
+ return sub_json;
}
- if (value)
- value->reset(new JsonDataCopy(sub_dict));
+ const ::scoped_ptr<const base::DictionaryValue> owned_;
+ bool parser_error_;
+ const base::DictionaryValue& dict_;
+ const std::vector<std::string> keys_;
+ std::map<std::string, Json*> sub_dicts_;
- return true;
-}
+ DISALLOW_COPY_AND_ASSIGN(JsonImpl);
+};
-} // namespace
+Json::Json() {}
Json::~Json() {}
-// static
-scoped_ptr<Json> Json::Build() {
- return scoped_ptr<Json>(new JsonDataOwner);
+bool Json::ParseObject(const std::string& json) {
+ DCHECK(!impl_);
+ impl_.reset(new JsonImpl(json));
+ if (impl_->parser_error())
+ impl_.reset();
+ return !!impl_;
}
-Json::Json() {}
+const std::vector<std::string>& Json::GetKeys() const {
+ return impl_->keys();
+}
+
+bool Json::GetStringValueForKey(const std::string& key,
+ std::string* value) const {
+ return impl_->GetStringValueForKey(key, value);
+}
+
+bool Json::HasDictionaryValueForKey(const std::string& key) const {
+ return impl_->HasDictionaryValueForKey(key);
+}
+
+const Json& Json::GetDictionaryValueForKey(const std::string& key) const {
+ return impl_->GetDictionaryValueForKey(key);
+}
} // namespace addressinput
} // namespace i18n
diff --git a/third_party/libaddressinput/chromium/libaddressinput_util.cc b/third_party/libaddressinput/chromium/libaddressinput_util.cc
new file mode 100644
index 0000000..11f675f
--- /dev/null
+++ b/third_party/libaddressinput/chromium/libaddressinput_util.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/libaddressinput_util.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h"
+
+namespace autofill {
+namespace addressinput {
+
+namespace {
+
+using ::i18n::addressinput::AddressData;
+using ::i18n::addressinput::AddressField;
+using ::i18n::addressinput::AddressProblem;
+using ::i18n::addressinput::IsFieldRequired;
+
+using ::i18n::addressinput::MISSING_REQUIRED_FIELD;
+
+// Based on ::i18n::addressinput::ValidationTask::ShouldReport().
+bool ShouldReport(const std::multimap<AddressField, AddressProblem>* filter,
+ AddressField field,
+ AddressProblem problem) {
+ return filter == NULL || filter->empty() ||
+ std::find(filter->begin(),
+ filter->end(),
+ std::multimap<AddressField, AddressProblem>::value_type(
+ field, problem)) != filter->end();
+}
+
+} // namespace
+
+bool HasAllRequiredFields(const AddressData& address_to_check) {
+ std::multimap<AddressField, AddressProblem> problems;
+ ValidateRequiredFields(address_to_check, NULL, &problems);
+ return problems.empty();
+}
+
+void ValidateRequiredFields(
+ const AddressData& address_to_check,
+ const std::multimap<AddressField, AddressProblem>* filter,
+ std::multimap<AddressField, AddressProblem>* problems) {
+ DCHECK(problems);
+
+ static const AddressField kFields[] = {
+ ::i18n::addressinput::COUNTRY,
+ ::i18n::addressinput::ADMIN_AREA,
+ ::i18n::addressinput::LOCALITY,
+ ::i18n::addressinput::DEPENDENT_LOCALITY,
+ ::i18n::addressinput::SORTING_CODE,
+ ::i18n::addressinput::POSTAL_CODE,
+ ::i18n::addressinput::STREET_ADDRESS,
+ ::i18n::addressinput::RECIPIENT};
+
+ for (size_t i = 0; i < arraysize(kFields); ++i) {
+ AddressField field = kFields[i];
+ if (address_to_check.IsFieldEmpty(field) &&
+ IsFieldRequired(field, address_to_check.region_code) &&
+ ShouldReport(filter, field, MISSING_REQUIRED_FIELD)) {
+ problems->insert(std::make_pair(field, MISSING_REQUIRED_FIELD));
+ }
+ }
+}
+
+} // namespace addressinput
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/libaddressinput_util.h b/third_party/libaddressinput/chromium/libaddressinput_util.h
new file mode 100644
index 0000000..f03528d
--- /dev/null
+++ b/third_party/libaddressinput/chromium/libaddressinput_util.h
@@ -0,0 +1,42 @@
+// Copyright 2014 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 THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_LIBADDRESSINPUT_UTIL_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_LIBADDRESSINPUT_UTIL_H_
+
+#include <map>
+
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_problem.h"
+
+namespace i18n {
+namespace addressinput {
+struct AddressData;
+}
+}
+
+namespace autofill {
+namespace addressinput {
+
+// Returns true if |address_to_check| has all of its required fields.
+bool HasAllRequiredFields(
+ const ::i18n::addressinput::AddressData& address_to_check);
+
+// Validates required fields in |address_to_check| without loading rules from
+// the server. The |problems| parameter cannot be NULL. Does not take ownership
+// of its parameters.
+//
+// See documentation of ::i18n::addressinput::AddressValidator::Validate() for
+// description of |filter| and |problems|.
+void ValidateRequiredFields(
+ const ::i18n::addressinput::AddressData& address_to_check,
+ const std::multimap< ::i18n::addressinput::AddressField,
+ ::i18n::addressinput::AddressProblem>* filter,
+ std::multimap< ::i18n::addressinput::AddressField,
+ ::i18n::addressinput::AddressProblem>* problems);
+
+} // namespace addressinput
+} // namespace autofill
+
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_LIBADDRESSINPUT_UTIL_H_
diff --git a/third_party/libaddressinput/chromium/libaddressinput_util_unittest.cc b/third_party/libaddressinput/chromium/libaddressinput_util_unittest.cc
new file mode 100644
index 0000000..23b0b93
--- /dev/null
+++ b/third_party/libaddressinput/chromium/libaddressinput_util_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/libaddressinput_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
+
+namespace autofill {
+namespace addressinput {
+
+using ::i18n::addressinput::AddressData;
+
+TEST(RequiredFieldsTest, AddressRequiresRegionCode) {
+ AddressData address;
+ EXPECT_FALSE(HasAllRequiredFields(address));
+}
+
+TEST(RequiredFieldsTest, UsRequiresState) {
+ AddressData address;
+ address.region_code = "US";
+ address.postal_code = "90291";
+ // Leave state empty.
+ address.locality = "Los Angeles";
+ address.address_line.push_back("340 Main St.");
+ EXPECT_FALSE(HasAllRequiredFields(address));
+}
+
+TEST(RequiredFieldsTest, CompleteAddressReturnsTrue) {
+ AddressData address;
+ address.region_code = "US";
+ address.postal_code = "90291";
+ address.administrative_area = "CA";
+ address.locality = "Los Angeles";
+ address.address_line.push_back("340 Main St.");
+ EXPECT_TRUE(HasAllRequiredFields(address));
+}
+
+} // namespace addressinput
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/override/basictypes_override.h b/third_party/libaddressinput/chromium/override/basictypes_override.h
new file mode 100644
index 0000000..699bc0f
--- /dev/null
+++ b/third_party/libaddressinput/chromium/override/basictypes_override.h
@@ -0,0 +1,10 @@
+// Copyright 2014 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 THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_BASICTYPES_OVERRIDE_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_BASICTYPES_OVERRIDE_H_
+
+#include "base/basictypes.h"
+
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_BASICTYPES_OVERRIDE_H_
diff --git a/third_party/libaddressinput/chromium/preload_address_validator.cc b/third_party/libaddressinput/chromium/preload_address_validator.cc
deleted file mode 100644
index 816e3a5..0000000
--- a/third_party/libaddressinput/chromium/preload_address_validator.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 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 <cstddef>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-
-#define I18N_ADDRESSINPUT_UTIL_BASICTYPES_H_
-#include "third_party/libaddressinput/chromium/preload_address_validator.h"
-#include "third_party/libaddressinput/chromium/suggestions.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_validator.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/downloader.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/preload_supplier.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
-#include "third_party/libaddressinput/src/cpp/include/libaddressinput/synonyms.h"
-
-namespace autofill {
-
-using ::i18n::addressinput::AddressData;
-using ::i18n::addressinput::AddressField;
-using ::i18n::addressinput::AddressValidator;
-using ::i18n::addressinput::BuildCallback;
-using ::i18n::addressinput::Downloader;
-using ::i18n::addressinput::FieldProblemMap;
-using ::i18n::addressinput::PreloadSupplier;
-using ::i18n::addressinput::Storage;
-using ::i18n::addressinput::Synonyms;
-
-PreloadAddressValidator::PreloadAddressValidator(
- const std::string& validation_data_url,
- scoped_ptr<Downloader> downloader,
- scoped_ptr<Storage> storage)
- : supplier_(
- new PreloadSupplier(
- validation_data_url,
- downloader.release(),
- storage.release())),
- suggestions_(
- new Suggestions(
- supplier_.get())),
- synonyms_(
- new Synonyms(
- supplier_.get())),
- validator_(
- new AddressValidator(
- supplier_.get())),
- validated_(BuildCallback(this, &PreloadAddressValidator::Validated)) {
-}
-
-PreloadAddressValidator::~PreloadAddressValidator() {
-}
-
-void PreloadAddressValidator::LoadRules(const std::string& region_code,
- const Callback& loaded) {
- assert(supplier_ != NULL);
- supplier_->LoadRules(region_code, loaded);
-}
-
-PreloadAddressValidator::Status PreloadAddressValidator::Validate(
- const AddressData& address,
- const FieldProblemMap* filter,
- FieldProblemMap* problems) const {
- assert(supplier_ != NULL);
- assert(validator_ != NULL);
-
- if (supplier_->IsPending(address.region_code)) {
- return RULES_NOT_READY;
- }
-
- if (!supplier_->IsLoaded(address.region_code)) {
- return RULES_UNAVAILABLE;
- }
-
- validator_->Validate(
- address,
- /*allow_postal*/ false,
- /*require_name*/ false,
- filter,
- problems,
- *validated_);
-
- return SUCCESS;
-}
-
-PreloadAddressValidator::Status PreloadAddressValidator::GetSuggestions(
- const AddressData& user_input,
- AddressField focused_field,
- size_t suggestion_limit,
- std::vector<AddressData>* suggestions) const {
- assert(suggestions_ != NULL);
- assert(supplier_ != NULL);
-
- if (supplier_->IsPending(user_input.region_code)) {
- return RULES_NOT_READY;
- }
-
- if (!supplier_->IsLoaded(user_input.region_code)) {
- return RULES_UNAVAILABLE;
- }
-
- suggestions_->GetSuggestions(
- user_input,
- focused_field,
- suggestion_limit,
- suggestions);
-
- return SUCCESS;
-}
-
-bool PreloadAddressValidator::CanonicalizeAdministrativeArea(
- AddressData* address) const {
- assert(address != NULL);
- assert(supplier_ != NULL);
- assert(synonyms_ != NULL);
-
- if (!supplier_->IsLoaded(address->region_code)) {
- return false;
- }
-
- // TODO: It would probably be beneficial to use the full canonicalization.
- AddressData tmp(*address);
- synonyms_->NormalizeForDisplay(&tmp);
- address->administrative_area = tmp.administrative_area;
-
- return true;
-}
-
-void PreloadAddressValidator::Validated(bool success,
- const AddressData&,
- const FieldProblemMap&) {
- assert(success);
-}
-
-// Stub constructor for use by MockAddressValidator.
-PreloadAddressValidator::PreloadAddressValidator() {
-}
-
-} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/storage_test_runner.cc b/third_party/libaddressinput/chromium/storage_test_runner.cc
new file mode 100644
index 0000000..453f0f2
--- /dev/null
+++ b/third_party/libaddressinput/chromium/storage_test_runner.cc
@@ -0,0 +1,88 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/storage_test_runner.h"
+
+#include <cassert>
+#include <cstddef>
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h"
+
+namespace autofill {
+
+using ::i18n::addressinput::Storage;
+
+StorageTestRunner::StorageTestRunner(Storage* storage)
+ : storage_(storage),
+ success_(false),
+ key_(),
+ data_() {}
+
+StorageTestRunner::~StorageTestRunner() {}
+
+void StorageTestRunner::RunAllTests() {
+ EXPECT_NO_FATAL_FAILURE(GetWithoutPutReturnsEmptyData());
+ EXPECT_NO_FATAL_FAILURE(GetReturnsWhatWasPut());
+ EXPECT_NO_FATAL_FAILURE(SecondPutOverwritesData());
+}
+
+void StorageTestRunner::ClearValues() {
+ success_ = false;
+ key_.clear();
+ data_.clear();
+}
+
+scoped_ptr<Storage::Callback> StorageTestRunner::BuildCallback() {
+ return scoped_ptr<Storage::Callback>(::i18n::addressinput::BuildCallback(
+ this, &StorageTestRunner::OnDataReady));
+}
+
+void StorageTestRunner::OnDataReady(bool success,
+ const std::string& key,
+ std::string* data) {
+ assert(!success || data != NULL);
+ success_ = success;
+ key_ = key;
+ if (data != NULL) {
+ data_ = *data;
+ delete data;
+ }
+}
+
+void StorageTestRunner::GetWithoutPutReturnsEmptyData() {
+ ClearValues();
+ scoped_ptr<Storage::Callback> callback(BuildCallback());
+ storage_->Get("key", *callback);
+
+ EXPECT_FALSE(success_);
+ EXPECT_EQ("key", key_);
+ EXPECT_TRUE(data_.empty());
+}
+
+void StorageTestRunner::GetReturnsWhatWasPut() {
+ ClearValues();
+ storage_->Put("key", new std::string("value"));
+ scoped_ptr<Storage::Callback> callback(BuildCallback());
+ storage_->Get("key", *callback);
+
+ EXPECT_TRUE(success_);
+ EXPECT_EQ("key", key_);
+ EXPECT_EQ("value", data_);
+}
+
+void StorageTestRunner::SecondPutOverwritesData() {
+ ClearValues();
+ storage_->Put("key", new std::string("bad-value"));
+ storage_->Put("key", new std::string("good-value"));
+ scoped_ptr<Storage::Callback> callback(BuildCallback());
+ storage_->Get("key", *callback);
+
+ EXPECT_TRUE(success_);
+ EXPECT_EQ("key", key_);
+ EXPECT_EQ("good-value", data_);
+}
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/storage_test_runner.h b/third_party/libaddressinput/chromium/storage_test_runner.h
new file mode 100644
index 0000000..113587d
--- /dev/null
+++ b/third_party/libaddressinput/chromium/storage_test_runner.h
@@ -0,0 +1,47 @@
+// Copyright 2014 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 THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_STORAGE_TEST_RUNNER_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_STORAGE_TEST_RUNNER_H_
+
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace autofill {
+
+// A test sutie for ::i18n::addressinput::Storage.
+class StorageTestRunner {
+ public:
+ // Does not take ownership of |storage|.
+ explicit StorageTestRunner(::i18n::addressinput::Storage* storage);
+ ~StorageTestRunner();
+
+ // Runs all the tests from the standard test suite.
+ void RunAllTests();
+
+ private:
+ void ClearValues();
+ scoped_ptr< ::i18n::addressinput::Storage::Callback> BuildCallback();
+ void OnDataReady(bool success, const std::string& key, std::string* data);
+
+ // Test suite.
+ void GetWithoutPutReturnsEmptyData();
+ void GetReturnsWhatWasPut();
+ void SecondPutOverwritesData();
+
+ ::i18n::addressinput::Storage* storage_; // weak
+ bool success_;
+ std::string key_;
+ std::string data_;
+
+ DISALLOW_COPY_AND_ASSIGN(StorageTestRunner);
+};
+
+} // namespace autofill
+
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_STORAGE_TEST_RUNNER_H_
diff --git a/third_party/libaddressinput/chromium/string_compare.cc b/third_party/libaddressinput/chromium/string_compare.cc
new file mode 100644
index 0000000..9d247eb
--- /dev/null
+++ b/third_party/libaddressinput/chromium/string_compare.cc
@@ -0,0 +1,69 @@
+// Copyright 2014 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 "third_party/libaddressinput/src/cpp/src/util/string_compare.h"
+
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/icu/source/i18n/unicode/coll.h"
+
+namespace i18n {
+namespace addressinput {
+
+namespace {
+
+class IcuStringComparer {
+ public:
+ IcuStringComparer() {
+ UErrorCode error_code = U_ZERO_ERROR;
+ collator_.reset(
+ icu::Collator::createInstance(icu::Locale::getRoot(), error_code));
+ DCHECK(U_SUCCESS(error_code));
+ collator_->setStrength(icu::Collator::PRIMARY);
+ }
+
+ ~IcuStringComparer() {}
+
+ int Compare(const std::string& a, const std::string& b) const {
+ UErrorCode error_code = U_ZERO_ERROR;
+ int result = collator_->compareUTF8(a, b, error_code);
+ DCHECK(U_SUCCESS(error_code));
+ return result;
+ }
+
+ private:
+ // ::scoped_ptr is from "base/memory/scoped_ptr.h", which does not interfere
+ // with ::i18n::addressinput::scoped_ptr from
+ // <libaddressinput/util/scoped_ptr.h>.
+ ::scoped_ptr<icu::Collator> collator_;
+
+ DISALLOW_COPY_AND_ASSIGN(IcuStringComparer);
+};
+
+static base::LazyInstance<IcuStringComparer> g_comparer =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+// Dummy required for scoped_ptr<Impl>.
+class StringCompare::Impl {};
+
+StringCompare::StringCompare() {}
+
+StringCompare::~StringCompare() {}
+
+bool StringCompare::NaturalEquals(const std::string& a,
+ const std::string& b) const {
+ return g_comparer.Get().Compare(a, b) == 0;
+}
+
+bool StringCompare::NaturalLess(const std::string& a,
+ const std::string& b) const {
+ return g_comparer.Get().Compare(a, b) < 0;
+}
+
+} // namespace addressinput
+} // namespace i18n
diff --git a/third_party/libaddressinput/chromium/string_compare_unittest.cc b/third_party/libaddressinput/chromium/string_compare_unittest.cc
new file mode 100644
index 0000000..0f9d9c7
--- /dev/null
+++ b/third_party/libaddressinput/chromium/string_compare_unittest.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 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 "third_party/libaddressinput/src/cpp/src/util/string_compare.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+TEST(ChromeStringCompareTest, IgnoreDiacritics) {
+ i18n::addressinput::StringCompare sc;
+ EXPECT_TRUE(sc.NaturalEquals("Texas", "T\u00E9xas"));
+}
+
+TEST(ChromeStringCompareTest, IgnoreCapitalization) {
+ i18n::addressinput::StringCompare sc;
+ EXPECT_TRUE(sc.NaturalEquals("Texas", "teXas"));
+}
+
+TEST(ChromeStringCompareTest, DifferentStringAreDifferent) {
+ i18n::addressinput::StringCompare sc;
+ EXPECT_FALSE(sc.NaturalEquals("Texas", "California"));
+}
+
+} // namespace
diff --git a/third_party/libaddressinput/chromium/trie.cc b/third_party/libaddressinput/chromium/trie.cc
new file mode 100644
index 0000000..e9289af
--- /dev/null
+++ b/third_party/libaddressinput/chromium/trie.cc
@@ -0,0 +1,81 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/trie.h"
+
+#include <queue>
+#include <string>
+
+#include "base/logging.h"
+
+// Separating template definitions and declarations requires defining all
+// possible template parameters to avoid linking errors.
+namespace i18n {
+namespace addressinput {
+class RegionData;
+}
+}
+
+namespace autofill {
+
+template <typename T>
+Trie<T>::Trie() {}
+
+template <typename T>
+Trie<T>::~Trie() {}
+
+template <typename T>
+void Trie<T>::AddDataForKey(const std::vector<uint8_t>& key,
+ const T& data_item) {
+ Trie<T>* current_node = this;
+ for (std::vector<uint8_t>::size_type i = 0; i < key.size(); ++i) {
+ if (!key[i])
+ break;
+ current_node = &current_node->sub_nodes_[key[i]];
+ }
+ current_node->data_list_.insert(data_item);
+}
+
+template <typename T>
+void Trie<T>::FindDataForKeyPrefix(const std::vector<uint8_t>& key_prefix,
+ std::set<T>* results) const {
+ DCHECK(results);
+
+ // Find the sub-trie for the key prefix.
+ const Trie<T>* current_node = this;
+ for (std::vector<uint8_t>::size_type i = 0; i < key_prefix.size(); ++i) {
+ if (!key_prefix[i])
+ break;
+
+ typename std::map<uint8_t, Trie<T> >::const_iterator sub_node_it =
+ current_node->sub_nodes_.find(key_prefix[i]);
+ if (sub_node_it == current_node->sub_nodes_.end())
+ return;
+
+ current_node = &sub_node_it->second;
+ }
+
+ // Collect data from all sub-tries.
+ std::queue<const Trie<T>*> node_queue;
+ node_queue.push(current_node);
+ while (!node_queue.empty()) {
+ const Trie<T>* queue_front = node_queue.front();
+ node_queue.pop();
+
+ results->insert(queue_front->data_list_.begin(),
+ queue_front->data_list_.end());
+
+ for (typename std::map<uint8_t, Trie<T> >::const_iterator sub_node_it =
+ queue_front->sub_nodes_.begin();
+ sub_node_it != queue_front->sub_nodes_.end();
+ ++sub_node_it) {
+ node_queue.push(&sub_node_it->second);
+ }
+ }
+}
+
+template class Trie<const ::i18n::addressinput::RegionData*>;
+template class Trie<std::string>;
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/chromium/trie.h b/third_party/libaddressinput/chromium/trie.h
new file mode 100644
index 0000000..914897e
--- /dev/null
+++ b/third_party/libaddressinput/chromium/trie.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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 THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_TRIE_H_
+#define THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_TRIE_H_
+
+#include <stdint.h>
+#include <map>
+#include <set>
+#include <vector>
+
+namespace autofill {
+
+// A prefix search tree. Can return all objects whose keys start with a prefix
+// byte sequence.
+//
+// Maps keys to multiple objects. This property is useful when mapping region
+// names to region objects. For example, there's a "St. Petersburg" in Florida,
+// and there's a "St. Petersburg" in Russia. A lookup for "St. Petersburg" key
+// should return two distinct objects.
+template <typename T>
+class Trie {
+ public:
+ Trie();
+ ~Trie();
+
+ // Returns true if no data was added in AddDataForKey().
+ bool empty() const { return data_list_.empty() && sub_nodes_.empty(); }
+
+ // Adds a mapping from the 0 terminated |key| to |data_item|. Can be called
+ // with the same |key| multiple times.
+ void AddDataForKey(const std::vector<uint8_t>& key, const T& data_item);
+
+ // Adds all objects whose keys start with the 0 terminated |key_prefix| to the
+ // |results| parameter. The |results| parameter should not be NULL.
+ void FindDataForKeyPrefix(const std::vector<uint8_t>& key_prefix,
+ std::set<T>* results) const;
+
+ private:
+ // All objects for this node in the Trie. This field is a collection to enable
+ // mapping the same key to multiple objects.
+ std::set<T> data_list_;
+
+ // Trie sub nodes. The root Trie stores the objects for the empty key. The
+ // children of the root Trie store the objects for the one-byte keys. The
+ // grand-children of the root Trie store the objects for the two-byte keys,
+ // and so on.
+ std::map<uint8_t, Trie<T> > sub_nodes_;
+};
+
+} // namespace autofill
+
+#endif // THIRD_PARTY_LIBADDRESSINPUT_CHROMIUM_TRIE_H_
diff --git a/third_party/libaddressinput/chromium/trie_unittest.cc b/third_party/libaddressinput/chromium/trie_unittest.cc
new file mode 100644
index 0000000..32b0bb1
--- /dev/null
+++ b/third_party/libaddressinput/chromium/trie_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright 2014 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 "third_party/libaddressinput/chromium/trie.h"
+
+#include <stdint.h>
+#include <set>
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+namespace {
+
+std::vector<uint8_t> ToByteArray(const std::string& text) {
+ std::vector<uint8_t> result(text.length() + 1, 0);
+ result.assign(text.begin(), text.end());
+ return result;
+}
+
+} // namespace
+
+TEST(TrieTest, EmptyTrieHasNoData) {
+ Trie<std::string> trie;
+ std::set<std::string> result;
+ trie.FindDataForKeyPrefix(ToByteArray("key"), &result);
+ EXPECT_TRUE(result.empty());
+}
+
+TEST(TrieTest, CanGetDataByExactKey) {
+ Trie<std::string> trie;
+ trie.AddDataForKey(ToByteArray("hello"), "world");
+ std::set<std::string> result;
+ trie.FindDataForKeyPrefix(ToByteArray("hello"), &result);
+ std::set<std::string> expected;
+ expected.insert("world");
+ EXPECT_EQ(expected, result);
+}
+
+TEST(TrieTest, CanGetDataByPrefix) {
+ Trie<std::string> trie;
+ trie.AddDataForKey(ToByteArray("hello"), "world");
+ std::set<std::string> result;
+ trie.FindDataForKeyPrefix(ToByteArray("he"), &result);
+ std::set<std::string> expected;
+ expected.insert("world");
+ EXPECT_EQ(expected, result);
+}
+
+TEST(TrieTest, KeyTooLongNoData) {
+ Trie<std::string> trie;
+ trie.AddDataForKey(ToByteArray("hello"), "world");
+ std::set<std::string> result;
+ trie.FindDataForKeyPrefix(ToByteArray("helloo"), &result);
+ EXPECT_TRUE(result.empty());
+}
+
+TEST(TrieTest, CommonPrefixFindsMultipleData) {
+ Trie<std::string> trie;
+ trie.AddDataForKey(ToByteArray("hello"), "world");
+ trie.AddDataForKey(ToByteArray("howdy"), "buddy");
+ trie.AddDataForKey(ToByteArray("foo"), "bar");
+ std::set<std::string> results;
+ trie.FindDataForKeyPrefix(ToByteArray("h"), &results);
+ std::set<std::string> expected;
+ expected.insert("world");
+ expected.insert("buddy");
+ EXPECT_EQ(expected, results);
+}
+
+TEST(TrieTest, KeyCanBePrefixOfOtherKey) {
+ Trie<std::string> trie;
+ trie.AddDataForKey(ToByteArray("hello"), "world");
+ trie.AddDataForKey(ToByteArray("helloo"), "woorld");
+ trie.AddDataForKey(ToByteArray("hella"), "warld");
+ std::set<std::string> results;
+ trie.FindDataForKeyPrefix(ToByteArray("hello"), &results);
+ std::set<std::string> expected;
+ expected.insert("world");
+ expected.insert("woorld");
+ EXPECT_EQ(expected, results);
+}
+
+TEST(TrieTest, AllowMutlipleKeys) {
+ Trie<std::string> trie;
+ trie.AddDataForKey(ToByteArray("hello"), "world");
+ trie.AddDataForKey(ToByteArray("hello"), "woorld");
+ std::set<std::string> results;
+ trie.FindDataForKeyPrefix(ToByteArray("hello"), &results);
+ std::set<std::string> expected;
+ expected.insert("world");
+ expected.insert("woorld");
+ EXPECT_EQ(expected, results);
+}
+
+TEST(TrieTest, CanFindVeryLongKey) {
+ Trie<std::string> trie;
+ static const char kVeryLongKey[] = "1234567890qwertyuioasdfghj";
+ trie.AddDataForKey(ToByteArray(kVeryLongKey), "world");
+ std::set<std::string> result;
+ trie.FindDataForKeyPrefix(ToByteArray(kVeryLongKey), &result);
+ std::set<std::string> expected;
+ expected.insert("world");
+ EXPECT_EQ(expected, result);
+}
+
+} // namespace autofill
diff --git a/third_party/libaddressinput/libaddressinput.gyp b/third_party/libaddressinput/libaddressinput.gyp
index e9d1852..e0aa83b 100644
--- a/third_party/libaddressinput/libaddressinput.gyp
+++ b/third_party/libaddressinput/libaddressinput.gyp
@@ -2,239 +2,160 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
+ 'includes': ['src/cpp/libaddressinput.gypi'],
'variables': {
- # TODO(rouslan): Use the src/ directory. http://crbug.com/327046
- 'libaddressinput_dir': 'chromium',
- },
- 'target_defaults': {
- 'conditions': [
- ['OS=="mac" or OS=="ios"', {
- 'xcode_settings': {
- 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'NO',
- },
- }],
- ],
- 'defines': [
- 'CUSTOM_BASICTYPES="base/basictypes.h"',
- 'CUSTOM_SCOPED_PTR="base/memory/scoped_ptr.h"',
+ 'libaddressinput_util_files': [
+ 'src/cpp/src/address_data.cc',
+ 'src/cpp/src/address_field.cc',
+ 'src/cpp/src/address_field_util.cc',
+ 'src/cpp/src/address_formatter.cc',
+ 'src/cpp/src/address_metadata.cc',
+ 'src/cpp/src/address_ui.cc',
+ 'src/cpp/src/format_element.cc',
+ 'src/cpp/src/language.cc',
+ 'src/cpp/src/localization.cc',
+ 'src/cpp/src/lookup_key.cc',
+ 'src/cpp/src/region_data_constants.cc',
+ 'src/cpp/src/rule.cc',
+ 'src/cpp/src/util/cctype_tolower_equal.cc',
+ 'src/cpp/src/util/json.cc',
+ 'src/cpp/src/util/string_split.cc',
+ 'src/cpp/src/util/string_util.cc',
],
},
'targets': [
{
- # GN version: //third_party/libaddressinput:strings
'target_name': 'libaddressinput_strings',
'type': 'none',
'variables': {
'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/third_party/libaddressinput/',
+ 'grit_grd_file': '../../chrome/app/address_input_strings.grd',
},
'actions': [
{
'action_name': 'libaddressinput_strings',
'variables': {
- 'grit_grd_file': '<(libaddressinput_dir)/cpp/res/libaddressinput_strings.grd',
},
'includes': [
'../../build/grit_action.gypi',
],
},
],
- 'includes': [
- '../../build/grit_target.gypi',
- ],
- },
- {
- # GN version: //third_party/libaddressinput:updated_strings
- 'target_name': 'libaddressinput_updated_strings',
- 'type': 'none',
- 'variables': {
- 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/grit/libaddressinput/',
+ 'direct_dependent_settings': {
+ # Files in libaddressinput include the grit-generated en_messages.cc
+ # without knowing its path.
+ 'include_dirs': [
+ '<(grit_out_dir)',
+ ],
},
- 'actions': [
- {
- 'action_name': 'libaddressinput_updated_strings',
- 'variables': {
- 'grit_grd_file': '../../chrome/app/address_input_strings.grd',
- },
- 'includes': [
- '../../build/grit_action.gypi',
- ],
- },
- ],
- 'includes': [
- '../../build/grit_target.gypi',
- ],
},
- # This target provides basic functionality which is cooked into the build.
{
- # GN version: //third_party/libaddressinput:util
'target_name': 'libaddressinput_util',
'type': 'static_library',
- 'include_dirs': [
- '<(libaddressinput_dir)/cpp/include/',
- '<(SHARED_INTERMEDIATE_DIR)/libaddressinput/',
- ],
'sources': [
+ '<@(libaddressinput_util_files)',
'chromium/addressinput_util.cc',
- 'chromium/addressinput_util.h',
- 'chromium/canonicalize_string.cc',
'chromium/json.cc',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_data.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_field.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_formatter.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_metadata.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_problem.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/util/basictypes.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/util/internal/basictypes.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/util/internal/move.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/util/internal/scoped_ptr.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/util/internal/template_util.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/util/scoped_ptr.h',
- '<(libaddressinput_dir)/cpp/src/address_data.cc',
- '<(libaddressinput_dir)/cpp/src/address_field.cc',
- '<(libaddressinput_dir)/cpp/src/address_formatter.cc',
- '<(libaddressinput_dir)/cpp/src/address_metadata.cc',
- '<(libaddressinput_dir)/cpp/src/address_problem.cc',
- '<(libaddressinput_dir)/cpp/src/language.cc',
- '<(libaddressinput_dir)/cpp/src/language.h',
- '<(libaddressinput_dir)/cpp/src/region_data_constants.cc',
- '<(libaddressinput_dir)/cpp/src/region_data_constants.h',
- '<(libaddressinput_dir)/cpp/src/rule.cc',
- '<(libaddressinput_dir)/cpp/src/rule.h',
- '<(libaddressinput_dir)/cpp/src/util/canonicalize_string.h',
- '<(libaddressinput_dir)/cpp/src/util/cctype_tolower_equal.cc',
- '<(libaddressinput_dir)/cpp/src/util/cctype_tolower_equal.h',
- '<(libaddressinput_dir)/cpp/src/util/json.h',
- '<(libaddressinput_dir)/cpp/src/util/stl_util.h',
- '<(libaddressinput_dir)/cpp/src/util/string_util.cc',
- '<(libaddressinput_dir)/cpp/src/util/string_util.h',
],
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/base/base.gyp:base_i18n',
- '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
- '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
- '<(DEPTH)/third_party/re2/re2.gyp:re2',
+ 'sources!': [
+ 'src/cpp/src/util/json.cc',
+ ],
+ 'conditions': [
+ ['OS=="mac" or OS=="ios"', {
+ # localization.cc in libaddressinput_util_files includes
+ # grit-generated en_messages.cc, which does not have a newline.
+ 'xcode_settings': {
+ 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'NO',
+ },
+ }],
+ ],
+ 'include_dirs': [
+ 'chromium/override/',
+ 'src/cpp/include/',
+ ],
+ 'defines': [
+ 'I18N_ADDRESSINPUT_USE_BASICTYPES_OVERRIDE=1',
],
'direct_dependent_settings': {
- 'defines': [
- 'CUSTOM_BASICTYPES="base/basictypes.h"',
- 'CUSTOM_SCOPED_PTR="base/memory/scoped_ptr.h"',
- ],
'include_dirs': [
- '<(libaddressinput_dir)/cpp/include/',
+ 'chromium/override/',
+ 'src/cpp/include/',
+ ],
+ 'defines': [
+ 'I18N_ADDRESSINPUT_USE_BASICTYPES_OVERRIDE=1',
],
},
+ 'dependencies': [
+ '../re2/re2.gyp:re2',
+ 'libaddressinput_strings',
+ ],
+ 'export_dependent_settings': [
+ 'libaddressinput_strings',
+ ],
},
- # This target provides more complicated functionality like pinging servers
- # for validation rules.
{
- # GN version: //third_party/libaddressinput
'target_name': 'libaddressinput',
'type': 'static_library',
- 'include_dirs': [
- '<(libaddressinput_dir)/cpp/include/',
- '<(SHARED_INTERMEDIATE_DIR)/libaddressinput/',
- ],
'sources': [
+ '<@(libaddressinput_files)',
+ 'chromium/chrome_address_validator.cc',
'chromium/chrome_downloader_impl.cc',
- 'chromium/chrome_downloader_impl.h',
'chromium/chrome_storage_impl.cc',
- 'chromium/chrome_storage_impl.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_ui_component.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_ui.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/address_validator.h',
- '<(libaddressinput_dir)/cpp/include/libaddressinput/load_rules_delegate.h',
- '<(libaddressinput_dir)/cpp/src/address_ui.cc',
- '<(libaddressinput_dir)/cpp/src/address_validator.cc',
- '<(libaddressinput_dir)/cpp/src/country_rules_aggregator.cc',
- '<(libaddressinput_dir)/cpp/src/country_rules_aggregator.h',
- '<(libaddressinput_dir)/cpp/src/fallback_data_store.cc',
- '<(libaddressinput_dir)/cpp/src/fallback_data_store.h',
- '<(libaddressinput_dir)/cpp/src/grit.h',
- '<(libaddressinput_dir)/cpp/src/retriever.cc',
- '<(libaddressinput_dir)/cpp/src/retriever.h',
- '<(libaddressinput_dir)/cpp/src/ruleset.cc',
- '<(libaddressinput_dir)/cpp/src/ruleset.h',
- '<(libaddressinput_dir)/cpp/src/util/md5.cc',
- '<(libaddressinput_dir)/cpp/src/util/md5.h',
- '<(libaddressinput_dir)/cpp/src/util/trie.cc',
- '<(libaddressinput_dir)/cpp/src/util/trie.h',
+ 'chromium/fallback_data_store.cc',
+ 'chromium/input_suggester.cc',
+ 'chromium/string_compare.cc',
+ 'chromium/trie.cc',
],
- 'defines': [
- 'VALIDATION_DATA_URL="https://i18napis.appspot.com/ssl-aggregate-address/"',
- ],
- 'dependencies': [
- 'libaddressinput_strings',
- 'libaddressinput_updated_strings',
- 'libaddressinput_util',
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/base/base.gyp:base_i18n',
- '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
- '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
- '<(DEPTH)/third_party/re2/re2.gyp:re2',
+ 'sources!': [
+ '<@(libaddressinput_util_files)',
+ 'src/cpp/src/util/string_compare.cc',
],
'direct_dependent_settings': {
'defines': [
- 'CUSTOM_BASICTYPES="base/basictypes.h"',
- 'CUSTOM_SCOPED_PTR="base/memory/scoped_ptr.h"',
- ],
- 'include_dirs': [
- '<(libaddressinput_dir)/cpp/include/',
+ 'I18N_ADDRESS_VALIDATION_DATA_URL="https://i18napis.appspot.com/ssl-aggregate-address/"',
],
},
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../base/base.gyp:base_prefs',
+ '../../net/net.gyp:net',
+ '../icu/icu.gyp:icui18n',
+ '../icu/icu.gyp:icuuc',
+ '../re2/re2.gyp:re2',
+ 'libaddressinput_util',
+ ],
+ 'export_dependent_settings': [
+ 'libaddressinput_util',
+ ],
},
{
- # GN version: //third_party/libaddressinput:libaddressinput_unittests
'target_name': 'libaddressinput_unittests',
'type': '<(gtest_target_type)',
- 'include_dirs': [
- '<(DEPTH)',
- '<(libaddressinput_dir)/cpp/src/',
- '<(DEPTH)/testing/gtest/include/',
- '<(SHARED_INTERMEDIATE_DIR)/libaddressinput/',
- ],
'sources': [
+ '<@(libaddressinput_test_files)',
'chromium/addressinput_util_unittest.cc',
+ 'chromium/chrome_address_validator_unittest.cc',
'chromium/chrome_downloader_impl_unittest.cc',
- 'chromium/chrome_rule_test.cc',
'chromium/chrome_storage_impl_unittest.cc',
- '<(libaddressinput_dir)/cpp/test/address_data_test.cc',
- '<(libaddressinput_dir)/cpp/test/address_formatter_test.cc',
- '<(libaddressinput_dir)/cpp/test/address_metadata_test.cc',
- '<(libaddressinput_dir)/cpp/test/address_ui_test.cc',
- '<(libaddressinput_dir)/cpp/test/address_validator_test.cc',
- '<(libaddressinput_dir)/cpp/test/country_rules_aggregator_test.cc',
- '<(libaddressinput_dir)/cpp/test/countryinfo_example_addresses_test.cc',
- '<(libaddressinput_dir)/cpp/test/fake_downloader.cc',
- '<(libaddressinput_dir)/cpp/test/fake_downloader.h',
- '<(libaddressinput_dir)/cpp/test/fake_downloader_test.cc',
- '<(libaddressinput_dir)/cpp/test/fake_storage.cc',
- '<(libaddressinput_dir)/cpp/test/fake_storage.h',
- '<(libaddressinput_dir)/cpp/test/fake_storage_test.cc',
- '<(libaddressinput_dir)/cpp/test/fallback_data_store_test.cc',
- '<(libaddressinput_dir)/cpp/test/language_test.cc',
- '<(libaddressinput_dir)/cpp/test/region_data_constants_test.cc',
- '<(libaddressinput_dir)/cpp/test/retriever_test.cc',
- '<(libaddressinput_dir)/cpp/test/rule_test.cc',
- '<(libaddressinput_dir)/cpp/test/storage_test_runner.cc',
- '<(libaddressinput_dir)/cpp/test/storage_test_runner.h',
- '<(libaddressinput_dir)/cpp/test/util/json_test.cc',
- '<(libaddressinput_dir)/cpp/test/util/md5_unittest.cc',
- '<(libaddressinput_dir)/cpp/test/util/scoped_ptr_unittest.cc',
- '<(libaddressinput_dir)/cpp/test/util/stl_util_unittest.cc',
- '<(libaddressinput_dir)/cpp/test/util/string_util_test.cc',
- '<(libaddressinput_dir)/cpp/test/util/trie_test.cc',
+ 'chromium/fallback_data_store_unittest.cc',
+ 'chromium/storage_test_runner.cc',
+ 'chromium/string_compare_unittest.cc',
+ 'chromium/trie_unittest.cc',
],
'defines': [
'TEST_DATA_DIR="third_party/libaddressinput/src/testdata"',
],
+ 'include_dirs': [
+ '../../',
+ 'src/cpp/src/',
+ ],
'dependencies': [
+ '../../base/base.gyp:base_prefs',
+ '../../base/base.gyp:run_all_unittests',
+ '../../net/net.gyp:net_test_support',
+ '../../testing/gtest.gyp:gtest',
'libaddressinput',
- 'libaddressinput_strings',
- '<(DEPTH)/base/base.gyp:base_prefs',
- '<(DEPTH)/base/base.gyp:run_all_unittests',
- '<(DEPTH)/net/net.gyp:net_test_support',
- '<(DEPTH)/testing/gtest.gyp:gtest',
+ 'libaddressinput_util',
],
},
],