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"
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/downloader.h"
18 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
23 using ::i18n::addressinput::AddressData
;
24 using ::i18n::addressinput::AddressField
;
25 using ::i18n::addressinput::AddressNormalizer
;
26 using ::i18n::addressinput::BuildCallback
;
27 using ::i18n::addressinput::Downloader
;
28 using ::i18n::addressinput::FieldProblemMap
;
29 using ::i18n::addressinput::PreloadSupplier
;
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;
41 AddressValidator::AddressValidator(const std::string
& validation_data_url
,
42 scoped_ptr
<Downloader
> downloader
,
43 scoped_ptr
<Storage
> storage
,
44 LoadRulesListener
* load_rules_listener
)
45 : supplier_(new PreloadSupplier(validation_data_url
,
48 input_suggester_(new InputSuggester(supplier_
.get())),
49 normalizer_(new AddressNormalizer(supplier_
.get())),
50 validator_(new ::i18n::addressinput::AddressValidator(supplier_
.get())),
51 validated_(BuildCallback(this, &AddressValidator::Validated
)),
52 rules_loaded_(BuildCallback(this, &AddressValidator::RulesLoaded
)),
53 load_rules_listener_(load_rules_listener
),
54 weak_factory_(this) {}
56 AddressValidator::~AddressValidator() {}
58 void AddressValidator::LoadRules(const std::string
& region_code
) {
59 attempts_number_
[region_code
] = 0;
60 supplier_
->LoadRules(region_code
, *rules_loaded_
);
63 AddressValidator::Status
AddressValidator::ValidateAddress(
64 const AddressData
& address
,
65 const FieldProblemMap
* filter
,
66 FieldProblemMap
* problems
) const {
67 if (supplier_
->IsPending(address
.region_code
)) {
69 addressinput::ValidateRequiredFields(address
, filter
, problems
);
70 return RULES_NOT_READY
;
73 if (!supplier_
->IsLoaded(address
.region_code
)) {
75 addressinput::ValidateRequiredFields(address
, filter
, problems
);
76 return RULES_UNAVAILABLE
;
82 validator_
->Validate(address
,
83 true, // Allow postal office boxes.
84 true, // Require recipient name.
92 AddressValidator::Status
AddressValidator::GetSuggestions(
93 const AddressData
& user_input
,
94 AddressField focused_field
,
95 size_t suggestion_limit
,
96 std::vector
<AddressData
>* suggestions
) const {
97 if (supplier_
->IsPending(user_input
.region_code
))
98 return RULES_NOT_READY
;
100 if (!supplier_
->IsLoaded(user_input
.region_code
))
101 return RULES_UNAVAILABLE
;
106 suggestions
->clear();
108 if (focused_field
== POSTAL_CODE
||
109 (focused_field
>= ADMIN_AREA
&& focused_field
<= DEPENDENT_LOCALITY
)) {
110 input_suggester_
->GetSuggestions(
111 user_input
, focused_field
, suggestion_limit
, suggestions
);
117 bool AddressValidator::CanonicalizeAdministrativeArea(
118 AddressData
* address
) const {
119 if (!supplier_
->IsLoaded(address
->region_code
))
122 // TODO: It would probably be beneficial to use the full canonicalization.
123 AddressData
tmp(*address
);
124 normalizer_
->Normalize(&tmp
);
125 address
->administrative_area
= tmp
.administrative_area
;
130 AddressValidator::AddressValidator()
131 : load_rules_listener_(NULL
), weak_factory_(this) {}
133 base::TimeDelta
AddressValidator::GetBaseRetryPeriod() const {
134 return base::TimeDelta::FromSeconds(8);
137 void AddressValidator::Validated(bool success
,
139 const FieldProblemMap
&) {
143 void AddressValidator::RulesLoaded(bool success
,
144 const std::string
& region_code
,
146 if (load_rules_listener_
)
147 load_rules_listener_
->OnAddressValidationRulesLoaded(region_code
, success
);
149 // Count the first failed attempt to load rules as well.
150 if (success
|| attempts_number_
[region_code
] + 1 >= kMaxAttemptsNumber
)
153 base::MessageLoop::current()->PostDelayedTask(
155 base::Bind(&AddressValidator::RetryLoadRules
,
156 weak_factory_
.GetWeakPtr(),
158 GetBaseRetryPeriod() * pow(2, attempts_number_
[region_code
]++));
161 void AddressValidator::RetryLoadRules(const std::string
& region_code
) {
162 // Do not reset retry count.
163 supplier_
->LoadRules(region_code
, *rules_loaded_
);
166 } // namespace autofill