blob: 342c81ed767c011539109a36ee4d71bd7ce3da40 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/autofill/core/browser/autofill_assistant.h"
#include <memory>
#include <utility>
#include "base/callback.h"
#include "base/feature_list.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using testing::_;
namespace autofill {
namespace {
class MockAutofillManager : public AutofillManager {
public:
MockAutofillManager(TestAutofillDriver* driver,
TestAutofillClient* client,
PersonalDataManager* pdm)
// Force to use the constructor designated for unit test.
: AutofillManager(driver, client, pdm) {}
virtual ~MockAutofillManager() {}
MOCK_METHOD5(FillCreditCardForm,
void(int query_id,
const FormData& form,
const FormFieldData& field,
const CreditCard& credit_card,
const base::string16& cvc));
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
};
} // namespace
class AutofillAssistantTest : public testing::Test {
protected:
AutofillAssistantTest()
: message_loop_(),
autofill_client_(),
autofill_driver_(),
pdm_(),
autofill_manager_(&autofill_driver_, &autofill_client_, &pdm_),
autofill_assistant_(&autofill_manager_) {}
void EnableAutofillCreditCardAssist() {
scoped_feature_list_.InitAndEnableFeature(kAutofillCreditCardAssist);
}
// Returns a valid credit card form.
FormData CreateValidCreditCardFormData() {
FormData form;
form.origin = GURL("https://myform.com");
form.action = GURL("https://myform.com/submit");
FormFieldData field;
field.form_control_type = "text";
field.label = base::ASCIIToUTF16("Name on Card");
field.name = base::ASCIIToUTF16("name_on_card");
form.fields.push_back(field);
field.label = base::ASCIIToUTF16("Card Number");
field.name = base::ASCIIToUTF16("card_number");
form.fields.push_back(field);
field.label = base::ASCIIToUTF16("Exp Month");
field.name = base::ASCIIToUTF16("ccmonth");
form.fields.push_back(field);
field.label = base::ASCIIToUTF16("Exp Year");
field.name = base::ASCIIToUTF16("ccyear");
form.fields.push_back(field);
field.label = base::ASCIIToUTF16("Verification");
field.name = base::ASCIIToUTF16("verification");
form.fields.push_back(field);
return form;
}
// Returns an initialized FormStructure with credit card form data. To be
// owned by the caller.
std::unique_ptr<FormStructure> CreateValidCreditCardForm() {
std::unique_ptr<FormStructure> form_structure;
form_structure.reset(new FormStructure(CreateValidCreditCardFormData()));
form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
/*source_id=*/0);
return form_structure;
}
base::MessageLoop message_loop_;
TestAutofillClient autofill_client_;
testing::NiceMock<TestAutofillDriver> autofill_driver_;
TestPersonalDataManager pdm_;
MockAutofillManager autofill_manager_;
AutofillAssistant autofill_assistant_;
base::test::ScopedFeatureList scoped_feature_list_;
};
MATCHER_P(CreditCardMatches, guid, "") {
return arg.guid() == guid;
}
// If the feature is turned off, CanShowCreditCardAssist() always returns
// false.
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOff) {
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
// Tests that with the feature enabled and proper input,
// CanShowCreditCardAssist() behaves as expected.
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn) {
EnableAutofillCreditCardAssist();
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
std::vector<std::unique_ptr<FormStructure>> form_structures;
EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
// With valid input, the function extracts the credit card form properly.
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
// Tests that with the feature enabled and proper input,
// CanShowCreditCardAssist() behaves as expected for secure contexts.
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Secure) {
EnableAutofillCreditCardAssist();
// Can be shown if the context is secure.
FormData form = CreateValidCreditCardFormData();
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
/*source_id=*/0);
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
// Tests that with the feature enabled and proper input,
// CanShowCreditCardAssist() behaves as expected for insecure contexts.
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_NotSecure) {
EnableAutofillCreditCardAssist();
// Cannot be shown if the context is not secure.
FormData form = CreateValidCreditCardFormData();
form.origin = GURL("http://myform.com");
form.action = GURL("http://myform.com/submit");
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
/*source_id=*/0);
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_FALSE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_Javascript) {
EnableAutofillCreditCardAssist();
// Can be shown if the context is secure and the form action is a javascript
// function (which is a valid url).
FormData form = CreateValidCreditCardFormData();
form.action = GURL("javascript:alert('hello');");
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
/*source_id=*/0);
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_WeirdJs) {
EnableAutofillCreditCardAssist();
// Can be shown if the context is secure and the form action is a javascript
// function that may or may not be valid.
FormData form = CreateValidCreditCardFormData();
form.action = GURL("javascript:myFunc");
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
/*source_id=*/0);
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
TEST_F(AutofillAssistantTest, CanShowCreditCardAssist_FeatureOn_EmptyAction) {
EnableAutofillCreditCardAssist();
// Can be shown if the context is secure and the form action is empty.
FormData form = CreateValidCreditCardFormData();
form.action = GURL();
std::unique_ptr<FormStructure> form_structure(new FormStructure(form));
form_structure->DetermineHeuristicTypes(/*ukm_service=*/nullptr,
/*source_id=*/0);
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
}
TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_CancelCvc) {
EnableAutofillCreditCardAssist();
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
// Will extract the credit card form data.
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
// Create a valid card for the assist.
CreditCard card;
test::SetCreditCardInfo(&card, "John Doe", "4111111111111111", "05", "2999",
"1");
// FillCreditCardForm should not be called if the user cancelled the CVC.
EXPECT_CALL(autofill_manager_, FillCreditCardForm(_, _, _, _, _)).Times(0);
autofill_assistant_.ShowAssistForCreditCard(card);
static_cast<CardUnmaskDelegate*>(
autofill_manager_.GetOrCreateFullCardRequest())
->OnUnmaskPromptClosed();
}
TEST_F(AutofillAssistantTest, ShowAssistForCreditCard_ValidCard_SubmitCvc) {
EnableAutofillCreditCardAssist();
std::unique_ptr<FormStructure> form_structure = CreateValidCreditCardForm();
// Will extract the credit card form data.
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::move(form_structure));
EXPECT_TRUE(autofill_assistant_.CanShowCreditCardAssist(form_structures));
// Create a valid card for the assist.
CreditCard card;
test::SetCreditCardInfo(&card, "John Doe", "4111111111111111", "05", "2999",
"1");
// FillCreditCardForm ends up being called after user has accepted the
// prompt.
EXPECT_CALL(
autofill_manager_,
FillCreditCardForm(kNoQueryId, _, _, CreditCardMatches(card.guid()),
base::ASCIIToUTF16("123")));
autofill_assistant_.ShowAssistForCreditCard(card);
CardUnmaskDelegate::UnmaskResponse unmask_response;
unmask_response.cvc = base::ASCIIToUTF16("123");
static_cast<CardUnmaskDelegate*>(
autofill_manager_.GetOrCreateFullCardRequest())
->OnUnmaskResponse(unmask_response);
}
} // namespace autofill