Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / libaddressinput / chromium / chrome_address_validator.cc
blobc55ab49ca47e60d75491ed729216f9c3dd1ba988
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "third_party/libaddressinput/chromium/chrome_address_validator.h"
7 #include <cmath>
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "third_party/libaddressinput/chromium/addressinput_util.h"
14 #include "third_party/libaddressinput/chromium/input_suggester.h"
15 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h"
16 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_normalizer.h"
17 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
18 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
20 namespace autofill {
21 namespace {
23 using ::i18n::addressinput::AddressData;
24 using ::i18n::addressinput::AddressField;
25 using ::i18n::addressinput::AddressNormalizer;
26 using ::i18n::addressinput::BuildCallback;
27 using ::i18n::addressinput::FieldProblemMap;
28 using ::i18n::addressinput::PreloadSupplier;
29 using ::i18n::addressinput::Source;
30 using ::i18n::addressinput::Storage;
32 using ::i18n::addressinput::ADMIN_AREA;
33 using ::i18n::addressinput::DEPENDENT_LOCALITY;
34 using ::i18n::addressinput::POSTAL_CODE;
36 // The maximum number attempts to load rules.
37 static const int kMaxAttemptsNumber = 8;
39 } // namespace
41 AddressValidator::AddressValidator(scoped_ptr<Source> source,
42 scoped_ptr<Storage> storage,
43 LoadRulesListener* load_rules_listener)
44 : supplier_(new PreloadSupplier(source.release(),
45 storage.release())),
46 input_suggester_(new InputSuggester(supplier_.get())),
47 normalizer_(new AddressNormalizer(supplier_.get())),
48 validator_(new ::i18n::addressinput::AddressValidator(supplier_.get())),
49 validated_(BuildCallback(this, &AddressValidator::Validated)),
50 rules_loaded_(BuildCallback(this, &AddressValidator::RulesLoaded)),
51 load_rules_listener_(load_rules_listener),
52 weak_factory_(this) {}
54 AddressValidator::~AddressValidator() {}
56 void AddressValidator::LoadRules(const std::string& region_code) {
57 attempts_number_[region_code] = 0;
58 supplier_->LoadRules(region_code, *rules_loaded_);
61 AddressValidator::Status AddressValidator::ValidateAddress(
62 const AddressData& address,
63 const FieldProblemMap* filter,
64 FieldProblemMap* problems) const {
65 if (supplier_->IsPending(address.region_code)) {
66 if (problems)
67 addressinput::ValidateRequiredFields(address, filter, problems);
68 return RULES_NOT_READY;
71 if (!supplier_->IsLoaded(address.region_code)) {
72 if (problems)
73 addressinput::ValidateRequiredFields(address, filter, problems);
74 return RULES_UNAVAILABLE;
77 if (!problems)
78 return SUCCESS;
80 validator_->Validate(address,
81 true, // Allow postal office boxes.
82 true, // Require recipient name.
83 filter,
84 problems,
85 *validated_);
87 return SUCCESS;
90 AddressValidator::Status AddressValidator::GetSuggestions(
91 const AddressData& user_input,
92 AddressField focused_field,
93 size_t suggestion_limit,
94 std::vector<AddressData>* suggestions) const {
95 if (supplier_->IsPending(user_input.region_code))
96 return RULES_NOT_READY;
98 if (!supplier_->IsLoaded(user_input.region_code))
99 return RULES_UNAVAILABLE;
101 if (!suggestions)
102 return SUCCESS;
104 suggestions->clear();
106 if (focused_field == POSTAL_CODE ||
107 (focused_field >= ADMIN_AREA && focused_field <= DEPENDENT_LOCALITY)) {
108 input_suggester_->GetSuggestions(
109 user_input, focused_field, suggestion_limit, suggestions);
112 return SUCCESS;
115 bool AddressValidator::CanonicalizeAdministrativeArea(
116 AddressData* address) const {
117 if (!supplier_->IsLoaded(address->region_code))
118 return false;
120 // TODO: It would probably be beneficial to use the full canonicalization.
121 AddressData tmp(*address);
122 normalizer_->Normalize(&tmp);
123 address->administrative_area = tmp.administrative_area;
125 return true;
128 AddressValidator::AddressValidator()
129 : load_rules_listener_(NULL), weak_factory_(this) {}
131 base::TimeDelta AddressValidator::GetBaseRetryPeriod() const {
132 return base::TimeDelta::FromSeconds(8);
135 void AddressValidator::Validated(bool success,
136 const AddressData&,
137 const FieldProblemMap&) {
138 DCHECK(success);
141 void AddressValidator::RulesLoaded(bool success,
142 const std::string& region_code,
143 int) {
144 if (load_rules_listener_)
145 load_rules_listener_->OnAddressValidationRulesLoaded(region_code, success);
147 // Count the first failed attempt to load rules as well.
148 if (success || attempts_number_[region_code] + 1 >= kMaxAttemptsNumber)
149 return;
151 base::MessageLoop::current()->PostDelayedTask(
152 FROM_HERE,
153 base::Bind(&AddressValidator::RetryLoadRules,
154 weak_factory_.GetWeakPtr(),
155 region_code),
156 GetBaseRetryPeriod() * pow(2, attempts_number_[region_code]++));
159 void AddressValidator::RetryLoadRules(const std::string& region_code) {
160 // Do not reset retry count.
161 supplier_->LoadRules(region_code, *rules_loaded_);
164 } // namespace autofill