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/source.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::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;
41 AddressValidator::AddressValidator(scoped_ptr
<Source
> source
,
42 scoped_ptr
<Storage
> storage
,
43 LoadRulesListener
* load_rules_listener
)
44 : supplier_(new PreloadSupplier(source
.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
)) {
67 addressinput::ValidateRequiredFields(address
, filter
, problems
);
68 return RULES_NOT_READY
;
71 if (!supplier_
->IsLoaded(address
.region_code
)) {
73 addressinput::ValidateRequiredFields(address
, filter
, problems
);
74 return RULES_UNAVAILABLE
;
80 validator_
->Validate(address
,
81 true, // Allow postal office boxes.
82 true, // Require recipient name.
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
;
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
);
115 bool AddressValidator::CanonicalizeAdministrativeArea(
116 AddressData
* address
) const {
117 if (!supplier_
->IsLoaded(address
->region_code
))
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
;
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
,
137 const FieldProblemMap
&) {
141 void AddressValidator::RulesLoaded(bool success
,
142 const std::string
& region_code
,
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
)
151 base::MessageLoop::current()->PostDelayedTask(
153 base::Bind(&AddressValidator::RetryLoadRules
,
154 weak_factory_
.GetWeakPtr(),
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