Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: components/payments/core/address_normalizer.cc

Issue 2829903004: Reland: Normalize shipping address for merchant on Desktop. (Closed)
Patch Set: Make android code use the new impl Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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.
4
5 #include "components/payments/core/address_normalizer.h"
6
7 #include <stddef.h>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/cancelable_callback.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/sequenced_task_runner_handle.h"
18 #include "base/time/time.h"
19 #include "components/autofill/core/browser/address_i18n.h"
20 #include "components/autofill/core/browser/autofill_profile.h"
21 #include "components/payments/core/payment_request_data_util.h"
22 #include "third_party/libaddressinput/chromium/chrome_address_validator.h"
23 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_da ta.h"
24 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/source.h"
25 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
26
27 namespace payments {
28 namespace {
29
30 using ::autofill::AutofillProfile;
31 using ::i18n::addressinput::Source;
32 using ::i18n::addressinput::Storage;
33
34 class AddressNormalizationRequest : public AddressNormalizer::Request {
35 public:
36 // The |delegate| and |address_validator| need to outlive this Request.
37 AddressNormalizationRequest(const AutofillProfile& profile,
38 const std::string& region_code,
39 int timeout_seconds,
40 AddressNormalizer::Delegate* delegate,
41 autofill::AddressValidator* address_validator)
42 : profile_(profile),
43 region_code_(region_code),
44 delegate_(delegate),
45 address_validator_(address_validator),
46 has_responded_(false),
47 on_timeout_(
48 base::Bind(&::payments::AddressNormalizationRequest::OnRulesLoaded,
49 base::Unretained(this),
50 false)) {
51 base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
52 FROM_HERE, on_timeout_.callback(),
53 base::TimeDelta::FromSeconds(timeout_seconds));
54 }
55
56 ~AddressNormalizationRequest() override {}
57
58 void OnRulesLoaded(bool success) override {
59 on_timeout_.Cancel();
60
61 // Check if the timeout happened before the rules were loaded.
62 if (has_responded_)
63 return;
64 has_responded_ = true;
65
66 // In either case, format the phone number.
67 FormatPhoneNumberForResponse();
68
69 if (!success) {
70 delegate_->OnCouldNotNormalize(profile_);
71 return;
72 }
73
74 // The rules should be loaded.
75 DCHECK(address_validator_->AreRulesLoadedForRegion(region_code_));
76
77 // Create the AddressData from the profile.
78 ::i18n::addressinput::AddressData address_data =
79 *autofill::i18n::CreateAddressDataFromAutofillProfile(profile_,
80 region_code_);
81
82 // Normalize the address.
83 if (address_validator_ &&
84 address_validator_->NormalizeAddress(&address_data)) {
85 profile_.SetRawInfo(autofill::ADDRESS_HOME_STATE,
86 base::UTF8ToUTF16(address_data.administrative_area));
87 profile_.SetRawInfo(autofill::ADDRESS_HOME_CITY,
88 base::UTF8ToUTF16(address_data.locality));
89 profile_.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY,
90 base::UTF8ToUTF16(address_data.dependent_locality));
91 }
92
93 delegate_->OnAddressNormalized(profile_);
94 }
95
96 private:
97 // Tries to format the phone number to the E.164 format to send in the Payment
98 // Response, as defined in the Payment Request spec. Keeps the original
99 // if it cannot be formatted. More info at:
100 // https://w3c.github.io/browser-payment-api/#paymentrequest-updated-algorithm
101 void FormatPhoneNumberForResponse() {
102 const std::string original_number = base::UTF16ToUTF8(profile_.GetInfo(
103 autofill::AutofillType(autofill::PHONE_HOME_WHOLE_NUMBER),
104 region_code_));
105
106 std::string formatted_number =
107 data_util::FormatPhoneForResponse(original_number, region_code_);
108
109 profile_.SetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER,
110 base::UTF8ToUTF16(formatted_number));
111 }
112
113 AutofillProfile profile_;
114 std::string region_code_;
115 AddressNormalizer::Delegate* delegate_;
116 autofill::AddressValidator* address_validator_;
117
118 bool has_responded_;
119 base::CancelableCallback<void()> on_timeout_;
120
121 DISALLOW_COPY_AND_ASSIGN(AddressNormalizationRequest);
122 };
123
124 } // namespace
125
126 AddressNormalizer::AddressNormalizer(std::unique_ptr<Source> source,
127 std::unique_ptr<Storage> storage)
128 : address_validator_(std::move(source), std::move(storage), this) {}
129
130 AddressNormalizer::~AddressNormalizer() {}
131
132 void AddressNormalizer::LoadRulesForRegion(const std::string& region_code) {
133 address_validator_.LoadRules(region_code);
134 }
135
136 bool AddressNormalizer::AreRulesLoadedForRegion(
137 const std::string& region_code) {
138 return address_validator_.AreRulesLoadedForRegion(region_code);
139 }
140
141 void AddressNormalizer::StartAddressNormalization(
142 const AutofillProfile& profile,
143 const std::string& region_code,
144 int timeout_seconds,
145 AddressNormalizer::Delegate* requester) {
146 DCHECK(timeout_seconds >= 0);
147
148 std::unique_ptr<AddressNormalizationRequest> request(
149 base::MakeUnique<AddressNormalizationRequest>(profile, region_code,
150 timeout_seconds, requester,
151 &address_validator_));
152
153 // Check if the rules are already loaded.
154 if (AreRulesLoadedForRegion(region_code)) {
155 request->OnRulesLoaded(true);
156 } else {
157 // Setup the variables so the profile gets normalized when the rules have
158 // finished loading.
159 auto it = pending_normalization_.find(region_code);
160 if (it == pending_normalization_.end()) {
161 // If no entry exists yet, create the entry and assign it to |it|.
162 it = pending_normalization_
163 .insert(std::make_pair(region_code,
164 std::vector<std::unique_ptr<Request>>()))
165 .first;
166 }
167
168 it->second.push_back(std::move(request));
169
170 // Start loading the rules for that region. If the rules were already in the
171 // process of being loaded, this call will do nothing.
172 LoadRulesForRegion(region_code);
173 }
174 }
175
176 void AddressNormalizer::OnAddressValidationRulesLoaded(
177 const std::string& region_code,
178 bool success) {
179 // Check if an address normalization is pending.
180 auto it = pending_normalization_.find(region_code);
181 if (it != pending_normalization_.end()) {
182 for (size_t i = 0; i < it->second.size(); ++i) {
183 it->second[i]->OnRulesLoaded(success);
184 }
185 pending_normalization_.erase(it);
186 }
187 }
188
189 } // namespace payments
OLDNEW
« no previous file with comments | « components/payments/core/address_normalizer.h ('k') | components/payments/core/address_normalizer_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698