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

Side by Side Diff: chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.cc

Issue 1138653003: Move card unmask interfaces and controller into the autofill component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Edit factory function comment Created 5 years, 7 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 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.
4
5 #include "chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.h"
6
7 #include "base/bind.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h"
14 #include "chrome/grit/generated_resources.h"
15 #include "components/autofill/core/browser/autofill_experiments.h"
16 #include "components/autofill/core/browser/autofill_metrics.h"
17 #include "components/autofill/core/common/autofill_pref_names.h"
18 #include "grit/theme_resources.h"
19 #include "ui/base/l10n/l10n_util.h"
20
21 namespace autofill {
22
23 CardUnmaskPromptControllerImpl::CardUnmaskPromptControllerImpl(
24 content::WebContents* web_contents,
25 const RiskDataCallback& risk_data_callback,
26 PrefService* pref_service,
27 bool is_off_the_record)
28 : web_contents_(web_contents),
29 risk_data_callback_(risk_data_callback),
30 pref_service_(pref_service),
31 is_off_the_record_(is_off_the_record),
32 card_unmask_view_(nullptr),
33 unmasking_result_(AutofillClient::NONE),
34 unmasking_initial_should_store_pan_(false),
35 unmasking_number_of_attempts_(0),
36 weak_pointer_factory_(this) {
37 }
38
39 CardUnmaskPromptControllerImpl::~CardUnmaskPromptControllerImpl() {
40 if (card_unmask_view_)
41 card_unmask_view_->ControllerGone();
42 }
43
44 void CardUnmaskPromptControllerImpl::ShowPrompt(
45 const CreditCard& card,
46 base::WeakPtr<CardUnmaskDelegate> delegate) {
47 if (card_unmask_view_)
48 card_unmask_view_->ControllerGone();
49
50 shown_timestamp_ = base::Time::Now();
51 pending_response_ = CardUnmaskDelegate::UnmaskResponse();
52 LoadRiskFingerprint();
53 card_ = card;
54 delegate_ = delegate;
55 card_unmask_view_ = CreateAndShowView();
56 unmasking_result_ = AutofillClient::NONE;
57 unmasking_number_of_attempts_ = 0;
58 unmasking_initial_should_store_pan_ = GetStoreLocallyStartState();
59 AutofillMetrics::LogUnmaskPromptEvent(AutofillMetrics::UNMASK_PROMPT_SHOWN);
60 }
61
62 bool CardUnmaskPromptControllerImpl::AllowsRetry(
63 AutofillClient::GetRealPanResult result) {
64 if (result == AutofillClient::NETWORK_ERROR ||
65 result == AutofillClient::PERMANENT_FAILURE) {
66 return false;
67 }
68 return true;
69 }
70
71 void CardUnmaskPromptControllerImpl::OnVerificationResult(
72 AutofillClient::GetRealPanResult result) {
73 if (!card_unmask_view_)
74 return;
75
76 base::string16 error_message;
77 switch (result) {
78 case AutofillClient::SUCCESS:
79 break;
80
81 case AutofillClient::TRY_AGAIN_FAILURE: {
82 error_message = l10n_util::GetStringUTF16(
83 IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_TRY_AGAIN);
84 break;
85 }
86
87 case AutofillClient::PERMANENT_FAILURE: {
88 error_message = l10n_util::GetStringUTF16(
89 IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_PERMANENT);
90 break;
91 }
92
93 case AutofillClient::NETWORK_ERROR: {
94 error_message = l10n_util::GetStringUTF16(
95 IDS_AUTOFILL_CARD_UNMASK_PROMPT_ERROR_NETWORK);
96 break;
97 }
98
99 case AutofillClient::NONE:
100 NOTREACHED();
101 return;
102 }
103
104 unmasking_result_ = result;
105 AutofillMetrics::LogRealPanResult(result);
106 AutofillMetrics::LogUnmaskingDuration(base::Time::Now() - verify_timestamp_,
107 result);
108 card_unmask_view_->GotVerificationResult(error_message,
109 AllowsRetry(result));
110 }
111
112 void CardUnmaskPromptControllerImpl::OnUnmaskDialogClosed() {
113 card_unmask_view_ = nullptr;
114 LogOnCloseEvents();
115 if (delegate_.get())
116 delegate_->OnUnmaskPromptClosed();
117 }
118
119 void CardUnmaskPromptControllerImpl::LogOnCloseEvents() {
120 AutofillMetrics::UnmaskPromptEvent close_reason_event = GetCloseReasonEvent();
121 AutofillMetrics::LogUnmaskPromptEvent(close_reason_event);
122 AutofillMetrics::LogUnmaskPromptEventDuration(
123 base::Time::Now() - shown_timestamp_, close_reason_event);
124
125 if (close_reason_event == AutofillMetrics::UNMASK_PROMPT_CLOSED_NO_ATTEMPTS)
126 return;
127
128 if (close_reason_event ==
129 AutofillMetrics::UNMASK_PROMPT_CLOSED_ABANDON_UNMASKING) {
130 AutofillMetrics::LogTimeBeforeAbandonUnmasking(base::Time::Now() -
131 verify_timestamp_);
132 }
133
134 bool final_should_store_pan = pending_response_.should_store_pan;
135 if (unmasking_result_ == AutofillClient::SUCCESS && final_should_store_pan) {
136 AutofillMetrics::LogUnmaskPromptEvent(
137 AutofillMetrics::UNMASK_PROMPT_SAVED_CARD_LOCALLY);
138 }
139
140 if (CanStoreLocally()) {
141 // Tracking changes in local save preference.
142 AutofillMetrics::UnmaskPromptEvent event;
143 if (unmasking_initial_should_store_pan_ && final_should_store_pan) {
144 event = AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_OUT;
145 } else if (!unmasking_initial_should_store_pan_ &&
146 !final_should_store_pan) {
147 event = AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_IN;
148 } else if (unmasking_initial_should_store_pan_ && !final_should_store_pan) {
149 event = AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_OPT_OUT;
150 } else {
151 event = AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_OPT_IN;
152 }
153 AutofillMetrics::LogUnmaskPromptEvent(event);
154 }
155 }
156
157 AutofillMetrics::UnmaskPromptEvent
158 CardUnmaskPromptControllerImpl::GetCloseReasonEvent() {
159 if (unmasking_number_of_attempts_ == 0)
160 return AutofillMetrics::UNMASK_PROMPT_CLOSED_NO_ATTEMPTS;
161
162 // If NONE and we have a pending request, we have a pending GetRealPan
163 // request.
164 if (unmasking_result_ == AutofillClient::NONE)
165 return AutofillMetrics::UNMASK_PROMPT_CLOSED_ABANDON_UNMASKING;
166
167 if (unmasking_result_ == AutofillClient::SUCCESS) {
168 return unmasking_number_of_attempts_ == 1
169 ? AutofillMetrics::UNMASK_PROMPT_UNMASKED_CARD_FIRST_ATTEMPT
170 : AutofillMetrics::
171 UNMASK_PROMPT_UNMASKED_CARD_AFTER_FAILED_ATTEMPTS;
172 } else {
173 return AllowsRetry(unmasking_result_)
174 ? AutofillMetrics::
175 UNMASK_PROMPT_CLOSED_FAILED_TO_UNMASK_RETRIABLE_FAILURE
176 : AutofillMetrics::
177 UNMASK_PROMPT_CLOSED_FAILED_TO_UNMASK_NON_RETRIABLE_FAILURE ;
178 }
179 }
180
181 void CardUnmaskPromptControllerImpl::OnUnmaskResponse(
182 const base::string16& cvc,
183 const base::string16& exp_month,
184 const base::string16& exp_year,
185 bool should_store_pan) {
186 verify_timestamp_ = base::Time::Now();
187 unmasking_number_of_attempts_++;
188 unmasking_result_ = AutofillClient::NONE;
189 card_unmask_view_->DisableAndWaitForVerification();
190
191 DCHECK(InputCvcIsValid(cvc));
192 base::TrimWhitespace(cvc, base::TRIM_ALL, &pending_response_.cvc);
193 if (ShouldRequestExpirationDate()) {
194 DCHECK(InputExpirationIsValid(exp_month, exp_year));
195 pending_response_.exp_month = exp_month;
196 pending_response_.exp_year = exp_year;
197 }
198 if (CanStoreLocally()) {
199 pending_response_.should_store_pan = should_store_pan;
200 // Remember the last choice the user made (on this device).
201 pref_service_->SetBoolean(
202 prefs::kAutofillWalletImportStorageCheckboxState, should_store_pan);
203 } else {
204 DCHECK(!should_store_pan);
205 pending_response_.should_store_pan = false;
206 }
207
208 if (!pending_response_.risk_data.empty())
209 delegate_->OnUnmaskResponse(pending_response_);
210 }
211
212 content::WebContents* CardUnmaskPromptControllerImpl::GetWebContents() {
213 return web_contents_;
214 }
215
216 base::string16 CardUnmaskPromptControllerImpl::GetWindowTitle() const {
217 int ids = ShouldRequestExpirationDate()
218 ? IDS_AUTOFILL_CARD_UNMASK_PROMPT_UPDATE_TITLE
219 : IDS_AUTOFILL_CARD_UNMASK_PROMPT_TITLE;
220 return l10n_util::GetStringFUTF16(ids, card_.TypeAndLastFourDigits());
221 }
222
223 base::string16 CardUnmaskPromptControllerImpl::GetInstructionsMessage() const {
224 if (ShouldRequestExpirationDate()) {
225 return l10n_util::GetStringUTF16(
226 card_.type() == kAmericanExpressCard
227 ? IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED_AMEX
228 : IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED);
229 }
230
231 return l10n_util::GetStringUTF16(
232 card_.type() == kAmericanExpressCard
233 ? IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_AMEX
234 : IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS);
235 }
236
237 int CardUnmaskPromptControllerImpl::GetCvcImageRid() const {
238 return card_.type() == kAmericanExpressCard ? IDR_CREDIT_CARD_CVC_HINT_AMEX
239 : IDR_CREDIT_CARD_CVC_HINT;
240 }
241
242 bool CardUnmaskPromptControllerImpl::ShouldRequestExpirationDate() const {
243 return card_.GetServerStatus() == CreditCard::EXPIRED;
244 }
245
246 bool CardUnmaskPromptControllerImpl::CanStoreLocally() const {
247 // Never offer to save for incognito.
248 if (is_off_the_record_)
249 return false;
250 return autofill::OfferStoreUnmaskedCards();
251 }
252
253 bool CardUnmaskPromptControllerImpl::GetStoreLocallyStartState() const {
254 return pref_service_->GetBoolean(
255 prefs::kAutofillWalletImportStorageCheckboxState);
256 }
257
258 bool CardUnmaskPromptControllerImpl::InputCvcIsValid(
259 const base::string16& input_text) const {
260 base::string16 trimmed_text;
261 base::TrimWhitespace(input_text, base::TRIM_ALL, &trimmed_text);
262 size_t input_size = card_.type() == kAmericanExpressCard ? 4 : 3;
263 return trimmed_text.size() == input_size &&
264 base::ContainsOnlyChars(trimmed_text,
265 base::ASCIIToUTF16("0123456789"));
266 }
267
268 bool CardUnmaskPromptControllerImpl::InputExpirationIsValid(
269 const base::string16& month,
270 const base::string16& year) const {
271 if ((month.size() != 2U && month.size() != 1U) ||
272 (year.size() != 4U && year.size() != 2U)) {
273 return false;
274 }
275
276 int month_value = 0, year_value = 0;
277 if (!base::StringToInt(month, &month_value) ||
278 !base::StringToInt(year, &year_value)) {
279 return false;
280 }
281
282 if (month_value < 1 || month_value > 12)
283 return false;
284
285 base::Time::Exploded now;
286 base::Time::Now().LocalExplode(&now);
287
288 // Convert 2 digit year to 4 digit year.
289 if (year_value < 100)
290 year_value += (now.year / 100) * 100;
291
292 if (year_value < now.year)
293 return false;
294
295 if (year_value > now.year)
296 return true;
297
298 return month_value >= now.month;
299 }
300
301 base::TimeDelta CardUnmaskPromptControllerImpl::GetSuccessMessageDuration()
302 const {
303 return base::TimeDelta::FromMilliseconds(500);
304 }
305
306 CardUnmaskPromptView* CardUnmaskPromptControllerImpl::CreateAndShowView() {
307 return CardUnmaskPromptView::CreateAndShow(this);
308 }
309
310 void CardUnmaskPromptControllerImpl::LoadRiskFingerprint() {
311 risk_data_callback_.Run(
312 base::Bind(&CardUnmaskPromptControllerImpl::OnDidLoadRiskFingerprint,
313 weak_pointer_factory_.GetWeakPtr()));
314 }
315
316 void CardUnmaskPromptControllerImpl::OnDidLoadRiskFingerprint(
317 const std::string& risk_data) {
318 pending_response_.risk_data = risk_data;
319 if (!pending_response_.cvc.empty())
320 delegate_->OnUnmaskResponse(pending_response_);
321 }
322
323 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698