blob: de5b39b71ef64fa2275c50d8d0028059443ab05f [file] [log] [blame]
// 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 <stddef.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#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 Source;
class Storage;
struct AddressData;
namespace autofill {
class InputSuggester;
// The object to be notified when loading of address validation rules is
// finished.
class LoadRulesListener {
virtual ~LoadRulesListener() {}
// Called when the validation rules for the |region_code| have been loaded.
// The validation rules include the generic rules for the |region_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& region_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 {
// The status of address validation.
enum Status {
// Address validation completed successfully. Check |problems| to see if any
// problems were found.
// The validation rules are not available, because LoadRules() was not
// called or failed. Reload the rules.
// The validation rules are being loaded. Try again later.
// Takes ownership of |source| and |storage|.
AddressValidator(std::unique_ptr<::i18n::addressinput::Source> source,
std::unique_ptr<::i18n::addressinput::Storage> storage,
LoadRulesListener* load_rules_listener);
virtual ~AddressValidator();
// Loads the generic validation rules for |region_code| and specific rules
// 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.
// Example rule:
// If the rules are already in progress of being loaded, it does nothing.
// 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.
// 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 ValidateAddress(
const ::i18n::addressinput::AddressData& address,
const ::i18n::addressinput::FieldProblemMap* filter,
::i18n::addressinput::FieldProblemMap* problems) const;
// 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.
// If the |solutions| parameter is NULL, the checks whether the validation
// rules are available, but does not fill in suggestions.
// 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"}]
virtual Status GetSuggestions(
const ::i18n::addressinput::AddressData& user_input,
::i18n::addressinput::AddressField focused_field,
size_t suggestion_limit,
std::vector< ::i18n::addressinput::AddressData>* suggestions) const;
// Canonicalizes the administrative area in |address_data|. For example,
// "texas" changes to "TX". Returns true on success, otherwise leaves
// |address_data| alone and returns false.
virtual bool CanonicalizeAdministrativeArea(
::i18n::addressinput::AddressData* address) const;
// Constructor used only for MockAddressValidator.
// Returns the period of time to wait between the first attempt's failure and
// the second attempt's initiation to load rules. Exposed for testing.
virtual base::TimeDelta GetBaseRetryPeriod() const;
// 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& region_code, int);
// Retries loading rules without resetting the retry counter.
void RetryLoadRules(const std::string& region_code);
// Loads and stores aggregate rules at COUNTRY level.
const std::unique_ptr<::i18n::addressinput::PreloadSupplier> supplier_;
// Suggests addresses based on user input.
const std::unique_ptr<InputSuggester> input_suggester_;
// Normalizes addresses into a canonical form.
const std::unique_ptr<::i18n::addressinput::AddressNormalizer> normalizer_;
// Validates addresses.
const std::unique_ptr<const ::i18n::addressinput::AddressValidator>
// The callback that |validator_| invokes when it finished validating an
// address.
const std::unique_ptr<const ::i18n::addressinput::AddressValidator::Callback>
// The callback that |supplier_| invokes when it finished loading rules.
const std::unique_ptr<const ::i18n::addressinput::PreloadSupplier::Callback>
// Not owned delegate to invoke when |suppler_| finished loading rules. Can be
// NULL.
LoadRulesListener* const load_rules_listener_;
// A mapping of region codes to the number of attempts to retry loading rules.
std::map<std::string, int> attempts_number_;
// Member variables should appear before the WeakPtrFactory, to ensure that
// any WeakPtrs to AddressValidator are invalidated before its members
// variable's destructors are executed, rendering them invalid.
base::WeakPtrFactory<AddressValidator> weak_factory_;
} // namespace autofill