1 // Copyright 2016 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/autofill/core/browser/autofill_assistant.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/callback.h"
11 #include "base/feature_list.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/test/scoped_feature_list.h"
14 #include "base/test/task_environment.h"
15 #include "components/autofill/core/browser/autofill_driver.h"
16 #include "components/autofill/core/browser/autofill_manager.h"
17 #include "components/autofill/core/browser/autofill_test_utils.h"
18 #include "components/autofill/core/browser/data_model/credit_card.h"
19 #include "components/autofill/core/browser/form_structure.h"
20 #include "components/autofill/core/browser/mock_autocomplete_history_manager.h"
21 #include "components/autofill/core/browser/payments/test_credit_card_save_manager.h"
22 #include "components/autofill/core/browser/test_autofill_client.h"
23 #include "components/autofill/core/browser/test_autofill_driver.h"
24 #include "components/autofill/core/browser/test_personal_data_manager.h"
25 #include "components/autofill/core/common/autofill_constants.h"
26 #include "components/autofill/core/common/autofill_features.h"
27 #include "services/network/public/cpp/shared_url_loader_factory.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/gurl.h"
31
32 using testing::_;
33
34 namespace autofill {
35 namespace {
36
37 class MockAutofillManager : public AutofillManager {
38 public:
MockAutofillManager(TestAutofillDriver * driver,TestAutofillClient * client,PersonalDataManager * pdm,AutocompleteHistoryManager * ahm)39 MockAutofillManager(TestAutofillDriver* driver,
40 TestAutofillClient* client,
41 PersonalDataManager* pdm,
42 AutocompleteHistoryManager* ahm)
43 // Force to use the constructor designated for unit test.
44 : AutofillManager(driver, client, pdm, ahm) {}
~MockAutofillManager()45 virtual ~MockAutofillManager() {}
46
47 MOCK_METHOD5(FillCreditCardForm,
48 void(int query_id,
49 const FormData& form,
50 const FormFieldData& field,
51 const CreditCard& credit_card,
52 const base::string16& cvc));
53
54 using AutofillManager::mutable_form_structures;
55
56 private:
57 DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
58 };
59
60 } // namespace
61
62 class AutofillAssistantTest : public testing::Test {
63 protected:
AutofillAssistantTest()64 AutofillAssistantTest()
65 : task_environment_(),
66 autofill_client_(),
67 autofill_driver_(),
68 pdm_(),
69 ahm_() {}
70
SetUp()71 void SetUp() {
72 payments::TestPaymentsClient* payments_client =
73 new payments::TestPaymentsClient(autofill_driver_.GetURLLoaderFactory(),
74 autofill_client_.GetIdentityManager(),
75 &pdm_);
76 autofill_client_.set_test_payments_client(
77 std::unique_ptr<payments::TestPaymentsClient>(payments_client));
78 TestCreditCardSaveManager* credit_card_save_manager =
79 new TestCreditCardSaveManager(&autofill_driver_, &autofill_client_,
80 payments_client, &pdm_);
81 autofill::TestFormDataImporter* test_form_data_importer =
82 new TestFormDataImporter(
83 &autofill_client_, payments_client,
84 std::unique_ptr<CreditCardSaveManager>(credit_card_save_manager),
85 &pdm_, "en-US");
86 autofill_client_.set_test_form_data_importer(
87 std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
88
89 autofill_manager_ = std::make_unique<MockAutofillManager>(
90 &autofill_driver_, &autofill_client_, &pdm_, &ahm_);
91
92 autofill_assistant_ =
93 std::make_unique<AutofillAssistant>(autofill_manager_.get());
94 }
95
EnableAutofillCreditCardAssist()96 void EnableAutofillCreditCardAssist() {
97 scoped_feature_list_.InitAndEnableFeature(
98 features::kAutofillCreditCardAssist);
99 }
100
101 // Returns a valid credit card form.
CreateValidCreditCardFormData()102 FormData CreateValidCreditCardFormData() {
103 FormData form;
104 form.url = GURL("https://myform.com");
105 form.action = GURL("https://myform.com/submit");
106
107 FormFieldData field;
108 field.form_control_type = "text";
109
110 field.label = base::ASCIIToUTF16("Name on Card");
111 field.name = base::ASCIIToUTF16("name_on_card");
112 form.fields.push_back(field);
113
114 field.label = base::ASCIIToUTF16("Card Number");
115 field.name = base::ASCIIToUTF16("card_number");
116 form.fields.push_back(field);
117
118 field.label = base::ASCIIToUTF16("Exp Month");
119 field.name = base::ASCIIToUTF16("ccmonth");
120 form.fields.push_back(field);
121
122 field.label = base::ASCIIToUTF16("Exp Year");
123 field.name = base::ASCIIToUTF16("ccyear");
124 form.fields.push_back(field);
125
126 field.label = base::ASCIIToUTF16("Verification");
127 field.name = base::ASCIIToUTF16("verification");
128 form.fields.push_back(field);
129
130 return form;
131 }
132
133 // Returns an initialized FormStructure with credit card form data. To be
134 // owned by the caller.
CreateValidCreditCardForm()135 std::unique_ptr<FormStructure> CreateValidCreditCardForm() {
136 std::unique_ptr<FormStructure> form_structure;
137 form_structure.reset(new FormStructure(CreateValidCreditCardFormData()));
138 form_structure->DetermineHeuristicTypes();
139 return form_structure;
140 }
141
142 // Convenience method to cast the FullCardRequest into a CardUnmaskDelegate.
full_card_unmask_delegate()143 CardUnmaskDelegate* full_card_unmask_delegate() {
144 payments::FullCardRequest* full_card_request =
145 autofill_manager_->credit_card_access_manager_->cvc_authenticator_
146 ->full_card_request_.get();
147 DCHECK(full_card_request);
148 return static_cast<CardUnmaskDelegate*>(full_card_request);
149 }
150
151 base::test::SingleThreadTaskEnvironment task_environment_;
152 TestAutofillClient autofill_client_;
153 testing::NiceMock<TestAutofillDriver> autofill_driver_;
154 TestPersonalDataManager pdm_;
155 MockAutocompleteHistoryManager ahm_;
156 std::unique_ptr<MockAutofillManager> autofill_manager_;
157 std::unique_ptr<AutofillAssistant> autofill_assistant_;
158 base::test::ScopedFeatureList scoped_feature_list_;
159 };
160
161 MATCHER_P(CreditCardMatches, guid, "") {
162 return arg.guid() == guid;
163 }
164
165 // If the feature is turned off, CanShowCreditCardAssist() always returns
166 // false.
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOff)167 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOff) {
168 std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
169
170 auto& form_structures = *autofill_manager_->mutable_form_structures();
171 auto signature = form_structure->form_signature();
172 form_structures[signature] = std::move(form_structure);
173 EXPECT_FALSE(autofill_assistant_->CanShowCreditCardAssist());
174 }
175
176 // Tests that with the feature enabled and proper input,
177 // CanShowCreditCardAssist() behaves as expected.
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOn)178 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn) {
179 EnableAutofillCreditCardAssist();
180
181 EXPECT_FALSE(autofill_assistant_->CanShowCreditCardAssist());
182
183 // With valid input, the function extracts the credit card form properly.
184 std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
185 auto& form_structures = *autofill_manager_->mutable_form_structures();
186 auto signature = form_structure->form_signature();
187 form_structures[signature] = std::move(form_structure);
188 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
189 }
190
191 // Tests that with the feature enabled and proper input,
192 // CanShowCreditCardAssist() behaves as expected for secure contexts.
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOn_Secure)193 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Secure) {
194 EnableAutofillCreditCardAssist();
195
196 // Can be shown if the context is secure.
197 FormData form = CreateValidCreditCardFormData();
198 auto form_structure = std::make_unique<FormStructure>(form);
199 form_structure->DetermineHeuristicTypes();
200
201 auto& form_structures = *autofill_manager_->mutable_form_structures();
202 auto signature = form_structure->form_signature();
203 form_structures[signature] = std::move(form_structure);
204 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
205 }
206
207 // Tests that with the feature enabled and proper input,
208 // CanShowCreditCardAssist() behaves as expected for insecure contexts.
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOn_NotSecure)209 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_NotSecure) {
210 EnableAutofillCreditCardAssist();
211
212 // Cannot be shown if the context is not secure.
213 FormData form = CreateValidCreditCardFormData();
214 form.url = GURL("http://myform.com");
215 form.action = GURL("http://myform.com/submit");
216 auto form_structure = std::make_unique<FormStructure>(form);
217 form_structure->DetermineHeuristicTypes();
218
219 auto& form_structures = *autofill_manager_->mutable_form_structures();
220 auto signature = form_structure->form_signature();
221 form_structures[signature] = std::move(form_structure);
222 EXPECT_FALSE(autofill_assistant_->CanShowCreditCardAssist());
223 }
224
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOn_Javascript)225 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Javascript) {
226 EnableAutofillCreditCardAssist();
227
228 // Can be shown if the context is secure and the form action is a javascript
229 // function (which is a valid url).
230 FormData form = CreateValidCreditCardFormData();
231 form.action = GURL("javascript:alert('hello');");
232 auto form_structure = std::make_unique<FormStructure>(form);
233 form_structure->DetermineHeuristicTypes();
234
235 auto& form_structures = *autofill_manager_->mutable_form_structures();
236 auto signature = form_structure->form_signature();
237 form_structures[signature] = std::move(form_structure);
238 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
239 }
240
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOn_WeirdJs)241 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_WeirdJs) {
242 EnableAutofillCreditCardAssist();
243
244 // Can be shown if the context is secure and the form action is a javascript
245 // function that may or may not be valid.
246 FormData form = CreateValidCreditCardFormData();
247 form.action = GURL("javascript:myFunc");
248 auto form_structure = std::make_unique<FormStructure>(form);
249 form_structure->DetermineHeuristicTypes();
250
251 auto& form_structures = *autofill_manager_->mutable_form_structures();
252 auto signature = form_structure->form_signature();
253 form_structures[signature] = std::move(form_structure);
254 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
255 }
256
TEST_F(AutofillAssistantTest,CanShowCreditCardAssist_FeatureOn_EmptyAction)257 TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_EmptyAction) {
258 EnableAutofillCreditCardAssist();
259
260 // Can be shown if the context is secure and the form action is empty.
261 FormData form = CreateValidCreditCardFormData();
262 form.action = GURL();
263 auto form_structure = std::make_unique<FormStructure>(form);
264 form_structure->DetermineHeuristicTypes();
265
266 auto& form_structures = *autofill_manager_->mutable_form_structures();
267 auto signature = form_structure->form_signature();
268 form_structures[signature] = std::move(form_structure);
269 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
270 }
271
TEST_F(AutofillAssistantTest,ShowAssistForCreditCard_ValidCard_CancelCvc)272 TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_CancelCvc) {
273 EnableAutofillCreditCardAssist();
274 std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
275
276 // Will extract the credit card form data.
277 auto& form_structures = *autofill_manager_->mutable_form_structures();
278 auto signature = form_structure->form_signature();
279 form_structures[signature] = std::move(form_structure);
280 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
281
282 // Create a valid card for the assist.
283 CreditCard card;
284 test::SetCreditCardInfo(&card, "John Doe", "4111111111111111", "05", "2999",
285 "1");
286
287 // FillCreditCardForm should not be called if the user cancelled the CVC.
288 EXPECT_CALL(*autofill_manager_, FillCreditCardForm(_, _, _, _, _)).Times(0);
289
290 autofill_assistant_->ShowAssistForCreditCard(card);
291 full_card_unmask_delegate()->OnUnmaskPromptClosed();
292 }
293
TEST_F(AutofillAssistantTest,ShowAssistForCreditCard_ValidCard_SubmitCvc)294 TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_SubmitCvc) {
295 EnableAutofillCreditCardAssist();
296 std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
297
298 // Will extract the credit card form data.
299 auto& form_structures = *autofill_manager_->mutable_form_structures();
300 auto signature = form_structure->form_signature();
301 form_structures[signature] = std::move(form_structure);
302 EXPECT_TRUE(autofill_assistant_->CanShowCreditCardAssist());
303
304 // Create a valid card for the assist.
305 CreditCard card;
306 test::SetCreditCardInfo(&card, "John Doe", "4111111111111111", "05", "2999",
307 "1");
308
309 // FillCreditCardForm ends up being called after user has accepted the
310 // prompt.
311 EXPECT_CALL(
312 *autofill_manager_,
313 FillCreditCardForm(kNoQueryId, _, _, CreditCardMatches(card.guid()),
314 base::ASCIIToUTF16("123")));
315
316 autofill_assistant_->ShowAssistForCreditCard(card);
317
318 CardUnmaskDelegate::UserProvidedUnmaskDetails unmask_details;
319 unmask_details.cvc = base::ASCIIToUTF16("123");
320 full_card_unmask_delegate()->OnUnmaskPromptAccepted(unmask_details);
321 }
322
323 } // namespace autofill
324