1 // Copyright (c) 2015 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 "chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/histogram_tester.h"
11 #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h"
12 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
13 #include "components/autofill/core/browser/autofill_client.h"
14 #include "components/autofill/core/browser/autofill_metrics.h"
15 #include "components/autofill/core/browser/autofill_test_utils.h"
16 #include "components/autofill/core/common/autofill_pref_names.h"
17 #include "components/user_prefs/user_prefs.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/test/test_utils.h"
23 using base::ASCIIToUTF16
;
25 class TestCardUnmaskDelegate
: public CardUnmaskDelegate
{
27 TestCardUnmaskDelegate() : weak_factory_(this) {}
29 virtual ~TestCardUnmaskDelegate() {}
31 // CardUnmaskDelegate implementation.
32 void OnUnmaskResponse(const UnmaskResponse
& response
) override
{
35 void OnUnmaskPromptClosed() override
{}
37 const UnmaskResponse
& response() { return response_
; }
39 base::WeakPtr
<TestCardUnmaskDelegate
> GetWeakPtr() {
40 return weak_factory_
.GetWeakPtr();
44 UnmaskResponse response_
;
45 base::WeakPtrFactory
<TestCardUnmaskDelegate
> weak_factory_
;
47 DISALLOW_COPY_AND_ASSIGN(TestCardUnmaskDelegate
);
50 class TestCardUnmaskPromptView
: public CardUnmaskPromptView
{
52 void ControllerGone() override
{}
53 void DisableAndWaitForVerification() override
{}
54 void GotVerificationResult(const base::string16
& error_message
,
55 bool allow_retry
) override
{}
58 class TestCardUnmaskPromptController
: public CardUnmaskPromptControllerImpl
{
60 TestCardUnmaskPromptController(
61 content::WebContents
* contents
,
62 TestCardUnmaskPromptView
* test_unmask_prompt_view
,
63 scoped_refptr
<content::MessageLoopRunner
> runner
)
64 : CardUnmaskPromptControllerImpl(contents
),
65 test_unmask_prompt_view_(test_unmask_prompt_view
),
66 can_store_locally_(true),
68 weak_factory_(this) {}
70 CardUnmaskPromptView
* CreateAndShowView() override
{
71 return test_unmask_prompt_view_
;
73 void LoadRiskFingerprint() override
{
74 OnDidLoadRiskFingerprint("risk aversion");
76 bool CanStoreLocally() const override
{ return can_store_locally_
; }
78 void set_can_store_locally(bool can
) { can_store_locally_
= can
; }
80 base::WeakPtr
<TestCardUnmaskPromptController
> GetWeakPtr() {
81 return weak_factory_
.GetWeakPtr();
85 TestCardUnmaskPromptView
* test_unmask_prompt_view_
;
86 bool can_store_locally_
;
87 scoped_refptr
<content::MessageLoopRunner
> runner_
;
88 base::WeakPtrFactory
<TestCardUnmaskPromptController
> weak_factory_
;
90 DISALLOW_COPY_AND_ASSIGN(TestCardUnmaskPromptController
);
93 class CardUnmaskPromptControllerImplTest
94 : public ChromeRenderViewHostTestHarness
{
96 CardUnmaskPromptControllerImplTest() {}
97 ~CardUnmaskPromptControllerImplTest() override
{}
99 void SetUp() override
{
100 ChromeRenderViewHostTestHarness::SetUp();
101 test_unmask_prompt_view_
.reset(new TestCardUnmaskPromptView());
102 controller_
.reset(new TestCardUnmaskPromptController(
103 web_contents(), test_unmask_prompt_view_
.get(), runner_
));
104 delegate_
.reset(new TestCardUnmaskDelegate());
105 SetImportCheckboxState(false);
108 void TearDown() override
{
109 ChromeRenderViewHostTestHarness::TearDown();
113 controller_
->ShowPrompt(test::GetMaskedServerCard(),
114 delegate_
->GetWeakPtr());
117 void ShowPromptAmex() {
118 controller_
->ShowPrompt(test::GetMaskedServerCardAmex(),
119 delegate_
->GetWeakPtr());
122 void ShowPromptAndSimulateResponse(bool should_store_pan
) {
124 controller_
->OnUnmaskResponse(ASCIIToUTF16("444"),
126 ASCIIToUTF16("2015"),
130 user_prefs::UserPrefs::Get(web_contents()->GetBrowserContext())
131 ->GetBoolean(prefs::kAutofillWalletImportStorageCheckboxState
));
135 void SetImportCheckboxState(bool value
) {
136 user_prefs::UserPrefs::Get(web_contents()->GetBrowserContext())
137 ->SetBoolean(prefs::kAutofillWalletImportStorageCheckboxState
, value
);
140 // This member must outlive the controller.
141 scoped_refptr
<content::MessageLoopRunner
> runner_
;
143 scoped_ptr
<TestCardUnmaskPromptView
> test_unmask_prompt_view_
;
144 scoped_ptr
<TestCardUnmaskPromptController
> controller_
;
145 scoped_ptr
<TestCardUnmaskDelegate
> delegate_
;
148 DISALLOW_COPY_AND_ASSIGN(CardUnmaskPromptControllerImplTest
);
151 TEST_F(CardUnmaskPromptControllerImplTest
, LogShown
) {
152 base::HistogramTester histogram_tester
;
155 histogram_tester
.ExpectUniqueSample(
156 "Autofill.UnmaskPrompt.Events",
157 AutofillMetrics::UNMASK_PROMPT_SHOWN
, 1);
160 TEST_F(CardUnmaskPromptControllerImplTest
, LogClosedNoAttempts
) {
162 base::HistogramTester histogram_tester
;
163 controller_
->OnUnmaskDialogClosed();
165 histogram_tester
.ExpectBucketCount(
166 "Autofill.UnmaskPrompt.Events",
167 AutofillMetrics::UNMASK_PROMPT_CLOSED_NO_ATTEMPTS
, 1);
170 TEST_F(CardUnmaskPromptControllerImplTest
, LogClosedAbandonUnmasking
) {
171 ShowPromptAndSimulateResponse(false);
172 base::HistogramTester histogram_tester
;
174 controller_
->OnUnmaskDialogClosed();
176 histogram_tester
.ExpectBucketCount(
177 "Autofill.UnmaskPrompt.Events",
178 AutofillMetrics::UNMASK_PROMPT_CLOSED_ABANDON_UNMASKING
, 1);
181 TEST_F(CardUnmaskPromptControllerImplTest
, LogClosedFailedToUnmaskRetriable
) {
182 ShowPromptAndSimulateResponse(false);
183 controller_
->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE
);
184 base::HistogramTester histogram_tester
;
186 controller_
->OnUnmaskDialogClosed();
188 histogram_tester
.ExpectBucketCount(
189 "Autofill.UnmaskPrompt.Events",
191 ::UNMASK_PROMPT_CLOSED_FAILED_TO_UNMASK_RETRIABLE_FAILURE
,
195 TEST_F(CardUnmaskPromptControllerImplTest
, LogClosedFailedToUnmaskNonRetriable
)
197 ShowPromptAndSimulateResponse(false);
198 controller_
->OnVerificationResult(AutofillClient::PERMANENT_FAILURE
);
199 base::HistogramTester histogram_tester
;
201 controller_
->OnUnmaskDialogClosed();
203 histogram_tester
.ExpectBucketCount(
204 "Autofill.UnmaskPrompt.Events",
206 ::UNMASK_PROMPT_CLOSED_FAILED_TO_UNMASK_NON_RETRIABLE_FAILURE
,
210 TEST_F(CardUnmaskPromptControllerImplTest
, LogUnmaskedCardFirstAttempt
) {
211 ShowPromptAndSimulateResponse(false);
212 base::HistogramTester histogram_tester
;
214 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
215 controller_
->OnUnmaskDialogClosed();
217 histogram_tester
.ExpectBucketCount(
218 "Autofill.UnmaskPrompt.Events",
219 AutofillMetrics::UNMASK_PROMPT_UNMASKED_CARD_FIRST_ATTEMPT
, 1);
222 TEST_F(CardUnmaskPromptControllerImplTest
, LogUnmaskedCardAfterFailure
) {
223 ShowPromptAndSimulateResponse(false);
224 controller_
->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE
);
225 controller_
->OnUnmaskResponse(ASCIIToUTF16("444"),
227 ASCIIToUTF16("2015"),
228 false /* should_store_pan */);
229 base::HistogramTester histogram_tester
;
231 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
232 controller_
->OnUnmaskDialogClosed();
234 histogram_tester
.ExpectBucketCount(
235 "Autofill.UnmaskPrompt.Events",
236 AutofillMetrics::UNMASK_PROMPT_UNMASKED_CARD_AFTER_FAILED_ATTEMPTS
, 1);
239 TEST_F(CardUnmaskPromptControllerImplTest
, LogSavedCardLocally
) {
240 ShowPromptAndSimulateResponse(true);
241 base::HistogramTester histogram_tester
;
243 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
244 controller_
->OnUnmaskDialogClosed();
246 histogram_tester
.ExpectBucketCount(
247 "Autofill.UnmaskPrompt.Events",
248 AutofillMetrics::UNMASK_PROMPT_SAVED_CARD_LOCALLY
, 1);
251 TEST_F(CardUnmaskPromptControllerImplTest
, LogDidOptIn
) {
252 SetImportCheckboxState(false);
253 ShowPromptAndSimulateResponse(true);
254 base::HistogramTester histogram_tester
;
255 controller_
->OnUnmaskDialogClosed();
257 histogram_tester
.ExpectBucketCount(
258 "Autofill.UnmaskPrompt.Events",
259 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_OPT_IN
, 1);
262 TEST_F(CardUnmaskPromptControllerImplTest
, LogDidNotOptIn
) {
263 SetImportCheckboxState(false);
264 ShowPromptAndSimulateResponse(false);
265 base::HistogramTester histogram_tester
;
266 controller_
->OnUnmaskDialogClosed();
268 histogram_tester
.ExpectBucketCount(
269 "Autofill.UnmaskPrompt.Events",
270 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_IN
, 1);
273 TEST_F(CardUnmaskPromptControllerImplTest
, LogDidOptOut
) {
274 SetImportCheckboxState(true);
275 ShowPromptAndSimulateResponse(false);
276 base::HistogramTester histogram_tester
;
277 controller_
->OnUnmaskDialogClosed();
279 histogram_tester
.ExpectBucketCount(
280 "Autofill.UnmaskPrompt.Events",
281 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_OPT_OUT
, 1);
284 TEST_F(CardUnmaskPromptControllerImplTest
, LogDidNotOptOut
) {
285 SetImportCheckboxState(true);
286 ShowPromptAndSimulateResponse(true);
287 base::HistogramTester histogram_tester
;
288 controller_
->OnUnmaskDialogClosed();
290 histogram_tester
.ExpectBucketCount(
291 "Autofill.UnmaskPrompt.Events",
292 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_OUT
, 1);
295 TEST_F(CardUnmaskPromptControllerImplTest
, DontLogForHiddenCheckbox
) {
296 controller_
->set_can_store_locally(false);
297 ShowPromptAndSimulateResponse(false);
298 base::HistogramTester histogram_tester
;
299 controller_
->OnUnmaskDialogClosed();
301 histogram_tester
.ExpectBucketCount(
302 "Autofill.UnmaskPrompt.Events",
303 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_OPT_IN
, 0);
304 histogram_tester
.ExpectBucketCount(
305 "Autofill.UnmaskPrompt.Events",
306 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_IN
, 0);
307 histogram_tester
.ExpectBucketCount(
308 "Autofill.UnmaskPrompt.Events",
309 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_OPT_OUT
, 0);
310 histogram_tester
.ExpectBucketCount(
311 "Autofill.UnmaskPrompt.Events",
312 AutofillMetrics::UNMASK_PROMPT_LOCAL_SAVE_DID_NOT_OPT_OUT
, 0);
315 TEST_F(CardUnmaskPromptControllerImplTest
, LogDurationNoAttempts
) {
317 base::HistogramTester histogram_tester
;
319 controller_
->OnUnmaskDialogClosed();
321 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration", 1);
322 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration.NoAttempts",
326 TEST_F(CardUnmaskPromptControllerImplTest
, LogDurationAbandonUnmasking
) {
327 ShowPromptAndSimulateResponse(false);
328 base::HistogramTester histogram_tester
;
330 controller_
->OnUnmaskDialogClosed();
332 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration", 1);
333 histogram_tester
.ExpectTotalCount(
334 "Autofill.UnmaskPrompt.Duration.AbandonUnmasking", 1);
337 TEST_F(CardUnmaskPromptControllerImplTest
, LogDurationFailedToUnmaskRetriable
) {
338 ShowPromptAndSimulateResponse(false);
339 controller_
->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE
);
340 base::HistogramTester histogram_tester
;
342 controller_
->OnUnmaskDialogClosed();
344 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration", 1);
345 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration.Failure",
349 TEST_F(CardUnmaskPromptControllerImplTest
,
350 LogDurationFailedToUnmaskNonRetriable
) {
351 ShowPromptAndSimulateResponse(false);
352 controller_
->OnVerificationResult(AutofillClient::PERMANENT_FAILURE
);
353 base::HistogramTester histogram_tester
;
355 controller_
->OnUnmaskDialogClosed();
357 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration", 1);
358 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration.Failure",
362 TEST_F(CardUnmaskPromptControllerImplTest
, LogDurationCardFirstAttempt
) {
363 ShowPromptAndSimulateResponse(false);
364 base::HistogramTester histogram_tester
;
366 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
367 controller_
->OnUnmaskDialogClosed();
369 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration", 1);
370 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration.Success",
374 TEST_F(CardUnmaskPromptControllerImplTest
,
375 LogDurationUnmaskedCardAfterFailure
) {
376 ShowPromptAndSimulateResponse(false);
377 controller_
->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE
);
378 controller_
->OnUnmaskResponse(
379 base::ASCIIToUTF16("444"), base::ASCIIToUTF16("01"),
380 base::ASCIIToUTF16("2015"), false /* should_store_pan */);
381 base::HistogramTester histogram_tester
;
383 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
384 controller_
->OnUnmaskDialogClosed();
386 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration", 1);
387 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.Duration.Success",
391 TEST_F(CardUnmaskPromptControllerImplTest
, LogTimeBeforeAbandonUnmasking
) {
392 ShowPromptAndSimulateResponse(false);
393 base::HistogramTester histogram_tester
;
395 controller_
->OnUnmaskDialogClosed();
397 histogram_tester
.ExpectTotalCount(
398 "Autofill.UnmaskPrompt.TimeBeforeAbandonUnmasking", 1);
401 TEST_F(CardUnmaskPromptControllerImplTest
, LogRealPanResultSuccess
) {
402 ShowPromptAndSimulateResponse(false);
403 base::HistogramTester histogram_tester
;
404 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
406 histogram_tester
.ExpectBucketCount(
407 "Autofill.UnmaskPrompt.GetRealPanResult",
408 AutofillMetrics::GET_REAL_PAN_RESULT_SUCCESS
, 1);
411 TEST_F(CardUnmaskPromptControllerImplTest
, LogRealPanTryAgainFailure
) {
412 ShowPromptAndSimulateResponse(false);
413 base::HistogramTester histogram_tester
;
415 controller_
->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE
);
417 histogram_tester
.ExpectBucketCount(
418 "Autofill.UnmaskPrompt.GetRealPanResult",
419 AutofillMetrics::GET_REAL_PAN_RESULT_TRY_AGAIN_FAILURE
, 1);
422 TEST_F(CardUnmaskPromptControllerImplTest
, LogUnmaskingDurationResultSuccess
) {
423 ShowPromptAndSimulateResponse(false);
424 base::HistogramTester histogram_tester
;
426 controller_
->OnVerificationResult(AutofillClient::SUCCESS
);
428 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.UnmaskingDuration",
430 histogram_tester
.ExpectTotalCount(
431 "Autofill.UnmaskPrompt.UnmaskingDuration.Success", 1);
434 TEST_F(CardUnmaskPromptControllerImplTest
,
435 LogUnmaskingDurationTryAgainFailure
) {
436 ShowPromptAndSimulateResponse(false);
437 base::HistogramTester histogram_tester
;
439 controller_
->OnVerificationResult(AutofillClient::TRY_AGAIN_FAILURE
);
441 histogram_tester
.ExpectTotalCount("Autofill.UnmaskPrompt.UnmaskingDuration",
443 histogram_tester
.ExpectTotalCount(
444 "Autofill.UnmaskPrompt.UnmaskingDuration.Failure", 1);
447 TEST_F(CardUnmaskPromptControllerImplTest
, CvcInputValidation
) {
451 // null when |valid| is false.
452 const char* canonicalized_input
;
454 CvcCase cvc_cases
[] = {
455 { "123", true, "123" },
456 { "123 ", true, "123" },
463 for (size_t i
= 0; i
< arraysize(cvc_cases
); ++i
) {
464 EXPECT_EQ(cvc_cases
[i
].valid
,
465 controller_
->InputCvcIsValid(ASCIIToUTF16(cvc_cases
[i
].input
)));
466 if (!cvc_cases
[i
].valid
)
469 controller_
->OnUnmaskResponse(ASCIIToUTF16(cvc_cases
[i
].input
),
470 base::string16(), base::string16(), false);
471 EXPECT_EQ(ASCIIToUTF16(cvc_cases
[i
].canonicalized_input
),
472 delegate_
->response().cvc
);
475 CvcCase cvc_cases_amex
[] = {
478 { "1234", true, "1234" },
479 { "\t1234 ", true, "1234" },
480 { " 1234", true, "1234" },
486 for (size_t i
= 0; i
< arraysize(cvc_cases_amex
); ++i
) {
488 cvc_cases_amex
[i
].valid
,
489 controller_
->InputCvcIsValid(ASCIIToUTF16(cvc_cases_amex
[i
].input
)));
490 if (!cvc_cases_amex
[i
].valid
)
493 controller_
->OnUnmaskResponse(ASCIIToUTF16(cvc_cases_amex
[i
].input
),
494 base::string16(), base::string16(), false);
495 EXPECT_EQ(ASCIIToUTF16(cvc_cases_amex
[i
].canonicalized_input
),
496 delegate_
->response().cvc
);
500 TEST_F(CardUnmaskPromptControllerImplTest
, ExpirationDateValidation
) {
502 const char* input_month
;
503 const char* input_year
;
506 {"01", "2040", true},
510 {"01", "1940", false},
511 {"13", "2040", false},
516 for (size_t i
= 0; i
< arraysize(exp_cases
); ++i
) {
517 EXPECT_EQ(exp_cases
[i
].valid
, controller_
->InputExpirationIsValid(
518 ASCIIToUTF16(exp_cases
[i
].input_month
),
519 ASCIIToUTF16(exp_cases
[i
].input_year
)));
523 } // namespace autofill