blob: bc5ed88828a93cfd37866c14577c3d8c671a893b [file] [log] [blame]
// Copyright 2013 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_manager.h"
#include <stddef.h>
#include <algorithm>
#include <memory>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_download_manager.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/popup_item_ids.h"
#include "components/autofill/core/browser/suggestion.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_download_manager.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_autofill_external_delegate.h"
#include "components/autofill/core/browser/test_autofill_manager.h"
#include "components/autofill/core/browser/test_form_structure.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/prefs/pref_service.h"
#include "components/security_state/core/security_state.h"
#include "components/strings/grit/components_strings.h"
#include "components/variations/variations_associated_data.h"
#include "components/variations/variations_params_manager.h"
#include "net/base/url_util.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics;
using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery;
using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload;
using autofill::features::kAutofillRestrictUnownedFieldsToFormlessCheckout;
using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
using testing::_;
using testing::AtLeast;
using testing::Return;
using testing::SaveArg;
using testing::UnorderedElementsAre;
namespace autofill {
namespace {
const int kDefaultPageID = 137;
class MockAutofillClient : public TestAutofillClient {
public:
MockAutofillClient() {}
~MockAutofillClient() override {}
MOCK_METHOD0(ShouldShowSigninPromo, bool());
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
class MockAutofillDownloadManager : public TestAutofillDownloadManager {
public:
MockAutofillDownloadManager(AutofillDriver* driver,
AutofillDownloadManager::Observer* observer)
: TestAutofillDownloadManager(driver, observer) {}
MOCK_METHOD5(StartUploadRequest,
bool(const FormStructure&,
bool,
const ServerFieldTypeSet&,
const std::string&,
bool));
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillDownloadManager);
};
void ExpectFilledField(const char* expected_label,
const char* expected_name,
const char* expected_value,
const char* expected_form_control_type,
const FormFieldData& field) {
SCOPED_TRACE(expected_label);
EXPECT_EQ(UTF8ToUTF16(expected_label), field.label);
EXPECT_EQ(UTF8ToUTF16(expected_name), field.name);
EXPECT_EQ(UTF8ToUTF16(expected_value), field.value);
EXPECT_EQ(expected_form_control_type, field.form_control_type);
}
// Verifies that the |filled_form| has been filled with the given data.
// Verifies address fields if |has_address_fields| is true, and verifies
// credit card fields if |has_credit_card_fields| is true. Verifies both if both
// are true. |use_month_type| is used for credit card input month type.
void ExpectFilledForm(int page_id,
const FormData& filled_form,
int expected_page_id,
const char* first,
const char* middle,
const char* last,
const char* address1,
const char* address2,
const char* city,
const char* state,
const char* postal_code,
const char* country,
const char* phone,
const char* email,
const char* name_on_card,
const char* card_number,
const char* expiration_month,
const char* expiration_year,
bool has_address_fields,
bool has_credit_card_fields,
bool use_month_type) {
// The number of fields in the address and credit card forms created above.
const size_t kAddressFormSize = 11;
const size_t kCreditCardFormSize = use_month_type ? 4 : 5;
EXPECT_EQ(expected_page_id, page_id);
EXPECT_EQ(ASCIIToUTF16("MyForm"), filled_form.name);
if (has_credit_card_fields) {
EXPECT_EQ(GURL("https://myform.com/form.html"), filled_form.origin);
EXPECT_EQ(GURL("https://myform.com/submit.html"), filled_form.action);
} else {
EXPECT_EQ(GURL("http://myform.com/form.html"), filled_form.origin);
EXPECT_EQ(GURL("http://myform.com/submit.html"), filled_form.action);
}
size_t form_size = 0;
if (has_address_fields)
form_size += kAddressFormSize;
if (has_credit_card_fields)
form_size += kCreditCardFormSize;
ASSERT_EQ(form_size, filled_form.fields.size());
if (has_address_fields) {
ExpectFilledField("First Name", "firstname", first, "text",
filled_form.fields[0]);
ExpectFilledField("Middle Name", "middlename", middle, "text",
filled_form.fields[1]);
ExpectFilledField("Last Name", "lastname", last, "text",
filled_form.fields[2]);
ExpectFilledField("Address Line 1", "addr1", address1, "text",
filled_form.fields[3]);
ExpectFilledField("Address Line 2", "addr2", address2, "text",
filled_form.fields[4]);
ExpectFilledField("City", "city", city, "text", filled_form.fields[5]);
ExpectFilledField("State", "state", state, "text", filled_form.fields[6]);
ExpectFilledField("Postal Code", "zipcode", postal_code, "text",
filled_form.fields[7]);
ExpectFilledField("Country", "country", country, "text",
filled_form.fields[8]);
ExpectFilledField("Phone Number", "phonenumber", phone, "tel",
filled_form.fields[9]);
ExpectFilledField("Email", "email", email, "email", filled_form.fields[10]);
}
if (has_credit_card_fields) {
size_t offset = has_address_fields ? kAddressFormSize : 0;
ExpectFilledField("Name on Card", "nameoncard", name_on_card, "text",
filled_form.fields[offset + 0]);
ExpectFilledField("Card Number", "cardnumber", card_number, "text",
filled_form.fields[offset + 1]);
if (use_month_type) {
std::string exp_year = expiration_year;
std::string exp_month = expiration_month;
std::string date;
if (!exp_year.empty() && !exp_month.empty())
date = exp_year + "-" + exp_month;
ExpectFilledField("Expiration Date", "ccmonth", date.c_str(), "month",
filled_form.fields[offset + 2]);
} else {
ExpectFilledField("Expiration Date", "ccmonth", expiration_month, "text",
filled_form.fields[offset + 2]);
ExpectFilledField("", "ccyear", expiration_year, "text",
filled_form.fields[offset + 3]);
}
}
}
void ExpectFilledAddressFormElvis(int page_id,
const FormData& filled_form,
int expected_page_id,
bool has_credit_card_fields) {
ExpectFilledForm(page_id, filled_form, expected_page_id, "Elvis", "Aaron",
"Presley", "3734 Elvis Presley Blvd.", "Apt. 10", "Memphis",
"Tennessee", "38116", "United States", "12345678901",
"theking@gmail.com", "", "", "", "", true,
has_credit_card_fields, false);
}
void ExpectFilledCreditCardFormElvis(int page_id,
const FormData& filled_form,
int expected_page_id,
bool has_address_fields) {
ExpectFilledForm(page_id, filled_form, expected_page_id, "", "", "", "", "",
"", "", "", "", "", "", "Elvis Presley", "4234567890123456",
"04", "2999", has_address_fields, true, false);
}
void ExpectFilledCreditCardYearMonthWithYearMonth(int page_id,
const FormData& filled_form,
int expected_page_id,
bool has_address_fields,
const char* year,
const char* month) {
ExpectFilledForm(page_id, filled_form, expected_page_id, "", "", "", "", "",
"", "", "", "", "", "", "Miku Hatsune", "4234567890654321",
month, year, has_address_fields, true, true);
}
class MockAutocompleteHistoryManager : public AutocompleteHistoryManager {
public:
MockAutocompleteHistoryManager(AutofillDriver* driver, AutofillClient* client)
: AutocompleteHistoryManager(driver, client) {}
MOCK_METHOD4(OnGetAutocompleteSuggestions,
void(int query_id,
const base::string16& name,
const base::string16& prefix,
const std::string& form_control_type));
MOCK_METHOD1(OnWillSubmitForm, void(const FormData& form));
private:
DISALLOW_COPY_AND_ASSIGN(MockAutocompleteHistoryManager);
};
class MockAutofillDriver : public TestAutofillDriver {
public:
MockAutofillDriver() {}
// Mock methods to enable testability.
MOCK_METHOD3(SendFormDataToRenderer,
void(int query_id,
RendererFormDataAction action,
const FormData& data));
MOCK_METHOD1(SendAutofillTypePredictionsToRenderer,
void(const std::vector<FormStructure*>& forms));
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
};
} // namespace
class AutofillManagerTest : public testing::Test {
public:
AutofillManagerTest() {}
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
personal_data_.set_database(autofill_client_.GetDatabase());
personal_data_.SetPrefService(autofill_client_.GetPrefs());
autofill_driver_ =
std::make_unique<testing::NiceMock<MockAutofillDriver>>();
request_context_ = new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get());
autofill_driver_->SetURLRequestContext(request_context_.get());
autofill_manager_ = std::make_unique<TestAutofillManager>(
autofill_driver_.get(), &autofill_client_, &personal_data_);
download_manager_ = new MockAutofillDownloadManager(
autofill_driver_.get(), autofill_manager_.get());
// AutofillManager takes ownership of |download_manager_|.
autofill_manager_->set_download_manager(download_manager_);
external_delegate_ = std::make_unique<TestAutofillExternalDelegate>(
autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
variation_params_.ClearAllVariationParams();
// Initialize the TestPersonalDataManager with some default data.
CreateTestAutofillProfiles();
CreateTestCreditCards();
}
void CreateTestServerCreditCards() {
personal_data_.ClearCreditCards();
CreditCard masked_server_card;
test::SetCreditCardInfo(&masked_server_card, "Elvis Presley",
"4234567890123456", // Visa
"04", "2999", "1");
masked_server_card.set_guid("00000000-0000-0000-0000-000000000007");
masked_server_card.set_record_type(CreditCard::MASKED_SERVER_CARD);
personal_data_.AddServerCreditCard(masked_server_card);
CreditCard full_server_card;
test::SetCreditCardInfo(&full_server_card, "Buddy Holly",
"5187654321098765", // Mastercard
"10", "2998", "1");
full_server_card.set_guid("00000000-0000-0000-0000-000000000008");
full_server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
personal_data_.AddServerCreditCard(full_server_card);
}
void CreateTestServerAndLocalCreditCards() {
personal_data_.ClearCreditCards();
CreditCard masked_server_card;
test::SetCreditCardInfo(&masked_server_card, "Elvis Presley",
"4234567890123456", // Visa
"04", "2999", "1");
masked_server_card.set_guid("00000000-0000-0000-0000-000000000007");
masked_server_card.set_record_type(CreditCard::MASKED_SERVER_CARD);
personal_data_.AddServerCreditCard(masked_server_card);
CreditCard full_server_card;
test::SetCreditCardInfo(&full_server_card, "Buddy Holly",
"5187654321098765", // Mastercard
"10", "2998", "1");
full_server_card.set_guid("00000000-0000-0000-0000-000000000008");
full_server_card.set_record_type(CreditCard::FULL_SERVER_CARD);
personal_data_.AddServerCreditCard(full_server_card);
CreditCard local_card;
test::SetCreditCardInfo(&local_card, "Elvis Presley",
"4234567890123456", // Visa
"04", "2999", "1");
local_card.set_guid("00000000-0000-0000-0000-000000000009");
local_card.set_record_type(CreditCard::LOCAL_CARD);
personal_data_.AddCreditCard(local_card);
}
void TearDown() override {
// Order of destruction is important as AutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
autofill_manager_.reset();
autofill_driver_.reset();
// Remove the AutofillWebDataService so TestPersonalDataManager does not
// need to care about removing self as an observer in destruction.
personal_data_.set_database(scoped_refptr<AutofillWebDataService>(nullptr));
personal_data_.SetPrefService(nullptr);
personal_data_.ClearCreditCards();
request_context_ = nullptr;
}
void GetAutofillSuggestions(int query_id,
const FormData& form,
const FormFieldData& field) {
autofill_manager_->OnQueryFormFieldAutofill(
query_id, form, field, gfx::RectF(),
/*autoselect_first_suggestion=*/false);
}
void GetAutofillSuggestions(const FormData& form,
const FormFieldData& field) {
GetAutofillSuggestions(kDefaultPageID, form, field);
}
void AutocompleteSuggestionsReturned(
const std::vector<base::string16>& result) {
autofill_manager_->autocomplete_history_manager_->SendSuggestions(&result);
}
void FormsSeen(const std::vector<FormData>& forms) {
autofill_manager_->OnFormsSeen(forms, base::TimeTicks());
}
void FormSubmitted(const FormData& form) {
autofill_manager_->OnFormSubmitted(
form, false, SubmissionSource::FORM_SUBMISSION, base::TimeTicks::Now());
}
void FillAutofillFormData(int query_id,
const FormData& form,
const FormFieldData& field,
int unique_id) {
autofill_manager_->FillOrPreviewForm(AutofillDriver::FORM_DATA_ACTION_FILL,
query_id, form, field, unique_id);
}
// Calls |autofill_manager_->OnFillAutofillFormData()| with the specified
// input parameters after setting up the expectation that the mock driver's
// |SendFormDataToRenderer()| method will be called and saving the parameters
// of that call into the |response_query_id| and |response_data| output
// parameters.
void FillAutofillFormDataAndSaveResults(int input_query_id,
const FormData& input_form,
const FormFieldData& input_field,
int unique_id,
int* response_query_id,
FormData* response_data) {
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _))
.WillOnce((DoAll(testing::SaveArg<0>(response_query_id),
testing::SaveArg<2>(response_data))));
FillAutofillFormData(input_query_id, input_form, input_field, unique_id);
}
int MakeFrontendID(const std::string& cc_sid,
const std::string& profile_sid) const {
return autofill_manager_->MakeFrontendID(cc_sid, profile_sid);
}
bool WillFillCreditCardNumber(const FormData& form,
const FormFieldData& field) {
return autofill_manager_->WillFillCreditCardNumber(form, field);
}
// Populates |form| with data corresponding to a simple credit card form.
// Note that this actually appends fields to the form data, which can be
// useful for building up more complex test forms.
void CreateTestCreditCardFormData(FormData* form,
bool is_https,
bool use_month_type) {
form->name = ASCIIToUTF16("MyForm");
if (is_https) {
form->origin = GURL("https://myform.com/form.html");
form->action = GURL("https://myform.com/submit.html");
} else {
form->origin = GURL("http://myform.com/form.html");
form->action = GURL("http://myform.com/submit.html");
}
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
form->fields.push_back(field);
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
form->fields.push_back(field);
if (use_month_type) {
test::CreateTestFormField("Expiration Date", "ccmonth", "", "month",
&field);
form->fields.push_back(field);
} else {
test::CreateTestFormField("Expiration Date", "ccmonth", "", "text",
&field);
form->fields.push_back(field);
test::CreateTestFormField("", "ccyear", "", "text", &field);
form->fields.push_back(field);
}
test::CreateTestFormField("CVC", "cvc", "", "text", &field);
form->fields.push_back(field);
}
void PrepareForRealPanResponse(FormData* form, CreditCard* card) {
// This line silences the warning from PaymentsClient about matching sync
// and Payments server types.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
"sync-url", "https://google.com");
CreateTestCreditCardFormData(form, true, false);
FormsSeen(std::vector<FormData>(1, *form));
*card = CreditCard(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(card, "John Dillinger", "1881" /* Visa */, "01",
"2017", "1");
card->SetNetworkForMaskedCard(kVisaCard);
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _))
.Times(AtLeast(1));
autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form,
form->fields[0], *card);
}
// Convenience method for using and retrieving a mock autocomplete history
// manager.
MockAutocompleteHistoryManager* RecreateMockAutocompleteHistoryManager() {
MockAutocompleteHistoryManager* manager =
new MockAutocompleteHistoryManager(autofill_driver_.get(),
autofill_manager_->client());
autofill_manager_->autocomplete_history_manager_.reset(manager);
return manager;
}
// Convenience method to cast the FullCardRequest into a CardUnmaskDelegate.
CardUnmaskDelegate* full_card_unmask_delegate() {
DCHECK(autofill_manager_->full_card_request_);
return static_cast<CardUnmaskDelegate*>(
autofill_manager_->full_card_request_.get());
}
void DisableCreditCardAutofill() {
scoped_feature_list_.InitAndEnableFeature(
kAutofillCreditCardAblationExperiment);
}
// Wrappers around the TestAutofillExternalDelegate::GetSuggestions call that
// take a hardcoded number of expected results so callsites are cleaner.
void CheckSuggestions(int expected_page_id, const Suggestion& suggestion0) {
std::vector<Suggestion> suggestion_vector;
suggestion_vector.push_back(suggestion0);
external_delegate_->CheckSuggestions(expected_page_id, 1,
&suggestion_vector[0]);
}
void CheckSuggestions(int expected_page_id,
const Suggestion& suggestion0,
const Suggestion& suggestion1) {
std::vector<Suggestion> suggestion_vector;
suggestion_vector.push_back(suggestion0);
suggestion_vector.push_back(suggestion1);
external_delegate_->CheckSuggestions(expected_page_id, 2,
&suggestion_vector[0]);
}
void CheckSuggestions(int expected_page_id,
const Suggestion& suggestion0,
const Suggestion& suggestion1,
const Suggestion& suggestion2) {
std::vector<Suggestion> suggestion_vector;
suggestion_vector.push_back(suggestion0);
suggestion_vector.push_back(suggestion1);
suggestion_vector.push_back(suggestion2);
external_delegate_->CheckSuggestions(expected_page_id, 3,
&suggestion_vector[0]);
}
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
MockAutofillClient autofill_client_;
std::unique_ptr<MockAutofillDriver> autofill_driver_;
std::unique_ptr<TestAutofillManager> autofill_manager_;
std::unique_ptr<TestAutofillExternalDelegate> external_delegate_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
MockAutofillDownloadManager* download_manager_;
TestPersonalDataManager personal_data_;
base::test::ScopedFeatureList scoped_feature_list_;
variations::testing::VariationParamsManager variation_params_;
private:
int ToHistogramSample(AutofillMetrics::CardUploadDecisionMetric metric) {
for (int sample = 0; sample < metric + 1; ++sample)
if (metric & (1 << sample))
return sample;
NOTREACHED();
return 0;
}
void CreateTestAutofillProfiles() {
AutofillProfile profile1;
test::SetProfileInfo(&profile1, "Elvis", "Aaron", "Presley",
"theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.",
"Apt. 10", "Memphis", "Tennessee", "38116", "US",
"12345678901");
profile1.set_guid("00000000-0000-0000-0000-000000000001");
personal_data_.AddProfile(profile1);
AutofillProfile profile2;
test::SetProfileInfo(&profile2, "Charles", "Hardin", "Holley",
"buddy@gmail.com", "Decca", "123 Apple St.", "unit 6",
"Lubbock", "Texas", "79401", "US", "23456789012");
profile2.set_guid("00000000-0000-0000-0000-000000000002");
personal_data_.AddProfile(profile2);
AutofillProfile profile3;
test::SetProfileInfo(&profile3, "", "", "", "", "", "", "", "", "", "", "",
"");
profile3.set_guid("00000000-0000-0000-0000-000000000003");
personal_data_.AddProfile(profile3);
}
void CreateTestCreditCards() {
CreditCard credit_card1;
test::SetCreditCardInfo(&credit_card1, "Elvis Presley",
"4234567890123456", // Visa
"04", "2999", "1");
credit_card1.set_guid("00000000-0000-0000-0000-000000000004");
credit_card1.set_use_count(10);
credit_card1.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(5));
personal_data_.AddCreditCard(credit_card1);
CreditCard credit_card2;
test::SetCreditCardInfo(&credit_card2, "Buddy Holly",
"5187654321098765", // Mastercard
"10", "2998", "1");
credit_card2.set_guid("00000000-0000-0000-0000-000000000005");
credit_card2.set_use_count(5);
credit_card2.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(4));
personal_data_.AddCreditCard(credit_card2);
CreditCard credit_card3;
test::SetCreditCardInfo(&credit_card3, "", "", "", "", "");
credit_card3.set_guid("00000000-0000-0000-0000-000000000006");
personal_data_.AddCreditCard(credit_card3);
}
};
// Test that calling OnFormsSeen with an empty set of forms (such as when
// reloading a page or when the renderer processes a set of forms but detects
// no changes) does not load the forms again.
TEST_F(AutofillManagerTest, OnFormsSeen_Empty) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
FormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
0 /* FORMS_LOADED */, 1);
// No more forms, metric is not logged.
forms.clear();
FormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
0 /* FORMS_LOADED */, 1);
}
// Test that calling OnFormsSeen consecutively with a different set of forms
// will query for each separately.
TEST_F(AutofillManagerTest, OnFormsSeen_DifferentFormStructures) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
FormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
0 /* FORMS_LOADED */, 1);
download_manager_->VerifyLastQueriedForms(forms);
// Different form structure.
FormData form2;
form2.name = ASCIIToUTF16("MyForm");
form2.origin = GURL("https://myform.com/form.html");
form2.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Email", "email", "", "text", &field);
form2.fields.push_back(field);
forms.clear();
forms.push_back(form2);
FormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
0 /* FORMS_LOADED */, 2);
download_manager_->VerifyLastQueriedForms(forms);
}
// Test that when forms are seen, the renderer is updated with the predicted
// field types
TEST_F(AutofillManagerTest, OnFormsSeen_SendAutofillTypePredictionsToRenderer) {
// Set up a queryable form.
FormData form1;
test::CreateTestAddressFormData(&form1);
// Set up a non-queryable form.
FormData form2;
FormFieldData field;
test::CreateTestFormField("Querty", "qwerty", "", "text", &field);
form2.name = ASCIIToUTF16("NonQueryable");
form2.origin = form1.origin;
form2.action = GURL("https://myform.com/submit.html");
form2.fields.push_back(field);
// Package the forms for observation.
std::vector<FormData> forms{form1, form2};
// Setup expectations.
EXPECT_CALL(*autofill_driver_, SendAutofillTypePredictionsToRenderer(_))
.Times(2);
FormsSeen(forms);
}
// Test that no autofill suggestions are returned for a field with an
// unrecognized autocomplete attribute.
TEST_F(AutofillManagerTest, GetProfileSuggestions_UnrecognizedAttribute) {
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
// Set a valid autocomplete attribute for the first name.
test::CreateTestFormField("First name", "firstname", "", "text", &field);
field.autocomplete_attribute = "given-name";
form.fields.push_back(field);
// Set no autocomplete attribute for the middle name.
test::CreateTestFormField("Middle name", "middle", "", "text", &field);
field.autocomplete_attribute = "";
form.fields.push_back(field);
// Set an unrecognized autocomplete attribute for the last name.
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
field.autocomplete_attribute = "unrecognized";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Ensure that autocomplete manager is not called for suggestions either.
MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
// Suggestions should be returned for the first two fields.
GetAutofillSuggestions(form, form.fields[0]);
external_delegate_->CheckSuggestionCount(kDefaultPageID, 2);
GetAutofillSuggestions(form, form.fields[1]);
external_delegate_->CheckSuggestionCount(kDefaultPageID, 2);
// No suggestions should not be provided for the third field because of its
// unrecognized autocomplete attribute.
GetAutofillSuggestions(form, form.fields[2]);
external_delegate_->CheckNoSuggestions(kDefaultPageID);
}
// Test that when small forms are disabled (min required fields enforced) no
// suggestions are returned when there are less than three fields and none of
// them have an autocomplete attribute.
TEST_F(AutofillManagerTest,
GetProfileSuggestions_MinFieldsEnforced_NoAutocomplete) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Ensure that autocomplete manager is called for both fields.
MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(2);
GetAutofillSuggestions(form, form.fields[0]);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
GetAutofillSuggestions(form, form.fields[1]);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that when small forms are disabled (min required fields enforced)
// for a form with two fields with one that has an autocomplete attribute,
// suggestions are only made for the one that has the attribute.
TEST_F(AutofillManagerTest,
GetProfileSuggestions_MinFieldsEnforced_WithOneAutocomplete) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
field.autocomplete_attribute = "given-name";
form.fields.push_back(field);
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
field.autocomplete_attribute = "";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Check that suggestions are made for the field that has the autocomplete
// attribute.
GetAutofillSuggestions(form, form.fields[0]);
CheckSuggestions(kDefaultPageID, Suggestion("Charles", "", "", 1),
Suggestion("Elvis", "", "", 2));
// Check that there are no suggestions for the field without the autocomplete
// attribute.
GetAutofillSuggestions(form, form.fields[1]);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that suggestions are returned by default when there are less than
// three fields and none of them have an autocomplete attribute.
TEST_F(AutofillManagerTest,
GetProfileSuggestions_NoMinFieldsEnforced_NoAutocomplete) {
base::test::ScopedFeatureList features;
features.InitAndDisableFeature(
kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Ensure that autocomplete manager is called for both fields.
MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
GetAutofillSuggestions(form, form.fields[0]);
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "Charles Hardin Holley", "", 1),
Suggestion("Elvis", "Elvis Aaron Presley", "", 2));
GetAutofillSuggestions(form, form.fields[1]);
CheckSuggestions(kDefaultPageID,
Suggestion("Holley", "Charles Hardin Holley", "", 1),
Suggestion("Presley", "Elvis Aaron Presley", "", 2));
}
// Test that for form with two fields with one that has an autocomplete
// attribute, suggestions are made for both if small form support is enabled
// (no mininum number of fields enforced).
TEST_F(AutofillManagerTest,
GetProfileSuggestions_NoMinFieldsEnforced_WithOneAutocomplete) {
base::test::ScopedFeatureList features;
features.InitAndDisableFeature(
kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
field.autocomplete_attribute = "given-name";
form.fields.push_back(field);
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
field.autocomplete_attribute = "";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
GetAutofillSuggestions(form, form.fields[0]);
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "Charles Hardin Holley", "", 1),
Suggestion("Elvis", "Elvis Aaron Presley", "", 2));
GetAutofillSuggestions(form, form.fields[1]);
CheckSuggestions(kDefaultPageID,
Suggestion("Holley", "Charles Hardin Holley", "", 1),
Suggestion("Presley", "Elvis Aaron Presley", "", 2));
}
// Test that for a form with two fields with autocomplete attributes,
// suggestions are made for both fields. This is true even if a minimum number
// of fields is enforced.
TEST_F(AutofillManagerTest,
GetProfileSuggestions_SmallFormWithTwoAutocomplete) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(kAutofillEnforceMinRequiredFieldsForHeuristics);
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
field.autocomplete_attribute = "given-name";
form.fields.push_back(field);
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
field.autocomplete_attribute = "family-name";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
GetAutofillSuggestions(form, form.fields[0]);
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "Charles Hardin Holley", "", 1),
Suggestion("Elvis", "Elvis Aaron Presley", "", 2));
GetAutofillSuggestions(form, form.fields[1]);
CheckSuggestions(kDefaultPageID,
Suggestion("Holley", "Charles Hardin Holley", "", 1),
Suggestion("Presley", "Elvis Aaron Presley", "", 2));
}
// Test that we return all address profile suggestions when all form fields are
// empty.
TEST_F(AutofillManagerTest, GetProfileSuggestions_EmptyValue) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate. Inferred
// labels include full first relevant field, which in this case is the
// address line 1.
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
}
// Test that we return only matching address profile suggestions when the
// selected form field has been partially filled out.
TEST_F(AutofillManagerTest, GetProfileSuggestions_MatchCharacter) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "E", "text", &field);
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1));
}
// Tests that we return address profile suggestions values when the section
// is already autofilled, and that we merge identical values.
TEST_F(AutofillManagerTest,
GetProfileSuggestions_AlreadyAutofilledMergeValues) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// First name is already autofilled which will make the section appear as
// "already autofilled".
form.fields[0].is_autofilled = true;
// Two profiles have the same last name, and the third shares the same first
// letter for last name.
AutofillProfile profile1;
profile1.set_guid("00000000-0000-0000-0000-000000000103");
profile1.SetInfo(NAME_FIRST, ASCIIToUTF16("Robin"), "en-US");
profile1.SetInfo(NAME_LAST, ASCIIToUTF16("Grimes"), "en-US");
profile1.SetInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 Smith Blvd."),
"en-US");
personal_data_.AddProfile(profile1);
AutofillProfile profile2;
profile2.set_guid("00000000-0000-0000-0000-000000000124");
profile2.SetInfo(NAME_FIRST, ASCIIToUTF16("Carl"), "en-US");
profile2.SetInfo(NAME_LAST, ASCIIToUTF16("Grimes"), "en-US");
profile2.SetInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 Smith Blvd."),
"en-US");
personal_data_.AddProfile(profile2);
AutofillProfile profile3;
profile3.set_guid("00000000-0000-0000-0000-000000000126");
profile3.SetInfo(NAME_FIRST, ASCIIToUTF16("Aaron"), "en-US");
profile3.SetInfo(NAME_LAST, ASCIIToUTF16("Googler"), "en-US");
profile3.SetInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1600 Amphitheater pkwy"),
"en-US");
personal_data_.AddProfile(profile3);
FormFieldData field;
test::CreateTestFormField("Last Name", "lastname", "G", "text", &field);
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate. No labels,
// with duplicate values "Grimes" merged.
CheckSuggestions(
kDefaultPageID, Suggestion("Googler", "1600 Amphitheater pkwy", "", 1),
Suggestion("Grimes", "1234 Smith Blvd., Carl Grimes", "", 2),
Suggestion("Grimes", "1234 Smith Blvd., Robin Grimes", "", 3));
}
// Tests that we return address profile suggestions values when the section
// is already autofilled, and that they have no label.
TEST_F(AutofillManagerTest, GetProfileSuggestions_AlreadyAutofilledNoLabels) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// First name is already autofilled which will make the section appear as
// "already autofilled".
form.fields[0].is_autofilled = true;
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "E", "text", &field);
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate. No labels.
CheckSuggestions(kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1));
}
// Test that we return no suggestions when the form has no relevant fields.
TEST_F(AutofillManagerTest, GetProfileSuggestions_UnknownFields) {
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("http://myform.com/form.html");
form.action = GURL("http://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("Username", "username", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Password", "password", "", "password", &field);
form.fields.push_back(field);
test::CreateTestFormField("Quest", "quest", "", "quest", &field);
form.fields.push_back(field);
test::CreateTestFormField("Color", "color", "", "text", &field);
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
GetAutofillSuggestions(form, field);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that we cull duplicate profile suggestions.
TEST_F(AutofillManagerTest, GetProfileSuggestions_WithDuplicates) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Add a duplicate profile.
AutofillProfile duplicate_profile = *(personal_data_.GetProfileWithGUID(
"00000000-0000-0000-0000-000000000001"));
personal_data_.AddProfile(duplicate_profile);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
}
// Test that we return no suggestions when autofill is disabled.
TEST_F(AutofillManagerTest, GetProfileSuggestions_AutofillDisabledByUser) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Disable Autofill.
autofill_manager_->SetAutofillEnabled(false);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that we return all credit card profile suggestions when all form fields
// are empty.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_EmptyValue) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has whitespace in it.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_Whitespace) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
field.value = ASCIIToUTF16(" ");
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has stop characters in it, which should be removed.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_StopCharsOnly) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
field.value = ASCIIToUTF16("____-____-____-____");
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has some invisible unicode characters in it.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_InvisibleUnicodeOnly) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
field.value = base::string16({0x200E, 0x200F});
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has stop characters in it and some input.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_StopCharsWithInput) {
// Add a credit card with particular numbers that we will attempt to recall.
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "John Smith",
"5255667890123123", // Mastercard
"08", "2017", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000007");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
field.value = ASCIIToUTF16("5255-66__-____-____");
GetAutofillSuggestions(form, field);
// Test that we sent the right value to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("3123"),
"08/17", kMasterCard,
autofill_manager_->GetPackedCreditCardID(7)));
}
// Test that we return only matching credit card profile suggestions when the
// selected form field has been partially filled out.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_MatchCharacter) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Card Number", "cardnumber", "78", "text", &field);
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)));
}
// Test that we return credit card profile suggestions when the selected form
// field is not the credit card number field.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_NonCCNumber) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
#if defined(OS_ANDROID)
static const std::string kVisaSuggestion =
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456");
static const std::string kMcSuggestion =
std::string("Mastercard ") + test::ObfuscatedCardDigitsAsUTF8("8765");
#else
static const std::string kVisaSuggestion =
test::ObfuscatedCardDigitsAsUTF8("3456");
static const std::string kMcSuggestion =
test::ObfuscatedCardDigitsAsUTF8("8765");
#endif
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Elvis Presley", kVisaSuggestion, kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)),
Suggestion("Buddy Holly", kMcSuggestion, kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we will eventually return the credit card signin promo when there
// are no credit card suggestions and the promo is active. See the tests in
// AutofillExternalDelegateTest that test whether the promo is added.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_OnlySigninPromo) {
personal_data_.ClearCreditCards();
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
ON_CALL(autofill_client_, ShouldShowSigninPromo())
.WillByDefault(Return(true));
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo()).Times(2);
EXPECT_TRUE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Autocomplete suggestions are not queried.
MockAutocompleteHistoryManager* m = RecreateMockAutocompleteHistoryManager();
EXPECT_CALL(*m, OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
GetAutofillSuggestions(form, field);
// Test that we sent no values to the external delegate. It will add the promo
// before passing along the results.
external_delegate_->CheckNoSuggestions(kDefaultPageID);
EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
}
// Test that we return a warning explaining that credit card profile suggestions
// are unavailable when the page is secure, but the form action URL is valid but
// not secure.
TEST_F(AutofillManagerTest,
GetCreditCardSuggestions_SecureContext_FormActionNotHTTPS) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, /* is_https= */ true, false);
// However we set the action (target URL) to be HTTP after all.
form.action = GURL("http://myform.com/submit.html");
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion(l10n_util::GetStringUTF8(
IDS_AUTOFILL_WARNING_INSECURE_CONNECTION),
"", "", -1));
// Clear the test credit cards and try again -- we shouldn't return a warning.
personal_data_.ClearCreditCards();
GetAutofillSuggestions(form, field);
// Autocomplete suggestions are queried, but not Autofill.
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that we return credit card suggestions for secure pages that have an
// empty form action target URL.
TEST_F(AutofillManagerTest,
GetCreditCardSuggestions_SecureContext_EmptyFormAction) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
// Clear the form action.
form.action = GURL();
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return credit card suggestions for secure pages that have a
// form action set to "javascript:something".
TEST_F(AutofillManagerTest,
GetCreditCardSuggestions_SecureContext_JavascriptFormAction) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
// Have the form action be a javascript function (which is a valid URL).
form.action = GURL("javascript:alert('Hello');");
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card suggestions in the case that two cards
// have the same obfuscated number.
TEST_F(AutofillManagerTest, GetCreditCardSuggestions_RepeatedObfuscatedNumber) {
// Add a credit card with the same obfuscated number as Elvis's.
// |credit_card| will be owned by the mock PersonalDataManager.
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Elvis Presley",
"5231567890123456", // Mastercard
"05", "2999", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000007");
credit_card.set_use_date(AutofillClock::Now() -
base::TimeDelta::FromDays(15));
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[1];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("3456"),
"05/99", kMasterCard,
autofill_manager_->GetPackedCreditCardID(7)));
}
// Test that we return profile and credit card suggestions for combined forms.
TEST_F(AutofillManagerTest, GetAddressAndCreditCardSuggestions) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right address suggestions to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
const int kPageID2 = 2;
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
GetAutofillSuggestions(kPageID2, form, field);
// Test that we sent the credit card suggestions to the external delegate.
CheckSuggestions(
kPageID2,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"04/99", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
"10/98", kMasterCard,
autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that for non-https forms with both address and credit card fields, we
// only return address suggestions. Instead of credit card suggestions, we
// should return a warning explaining that credit card profile suggestions are
// unavailable when the form is not https.
TEST_F(AutofillManagerTest, GetAddressAndCreditCardSuggestionsNonHttps) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
CreateTestCreditCardFormData(&form, false, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right suggestions to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
const int kPageID2 = 2;
GetAutofillSuggestions(kPageID2, form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kPageID2,
Suggestion(l10n_util::GetStringUTF8(
IDS_AUTOFILL_WARNING_INSECURE_CONNECTION),
"", "", -1));
// Clear the test credit cards and try again -- we shouldn't return a warning.
personal_data_.ClearCreditCards();
GetAutofillSuggestions(form, field);
external_delegate_->CheckNoSuggestions(kDefaultPageID);
}
TEST_F(AutofillManagerTest,
ShouldShowAddressSuggestionsIfCreditCardAutofillDisabled) {
DisableCreditCardAutofill();
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
GetAutofillSuggestions(form, field);
// Check that address suggestions will still be available.
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
}
TEST_F(AutofillManagerTest,
ShouldNotShowCreditCardsSuggestionsIfCreditCardAutofillDisabled) {
DisableCreditCardAutofill();
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
GetAutofillSuggestions(form, field);
// Check that credit card suggestions will not be available.
external_delegate_->CheckNoSuggestions(kDefaultPageID);
}
TEST_F(AutofillManagerTest,
ShouldLogFormSubmitEventIfCreditCardAutofillDisabled) {
DisableCreditCardAutofill();
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
GetAutofillSuggestions(form, field);
base::HistogramTester histogram_tester;
FormSubmitted(form);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
AutofillMetrics::FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
}
// Test that we return normal autofill suggestions when trying to autofill
// already filled forms.
TEST_F(AutofillManagerTest, GetFieldSuggestionsWhenFormIsAutofilled) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Mark one of the fields as filled.
form.fields[2].is_autofilled = true;
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2));
}
// Test that nothing breaks when there are autocomplete suggestions but no
// autofill suggestions.
TEST_F(AutofillManagerTest, GetFieldSuggestionsForAutocompleteOnly) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
FormFieldData field;
test::CreateTestFormField("Some Field", "somefield", "", "text", &field);
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
GetAutofillSuggestions(form, field);
// Add some Autocomplete suggestions.
// This triggers the combined message send.
std::vector<base::string16> suggestions;
suggestions.push_back(ASCIIToUTF16("one"));
suggestions.push_back(ASCIIToUTF16("two"));
AutocompleteSuggestionsReturned(suggestions);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID, Suggestion("one", "", "", 0),
Suggestion("two", "", "", 0));
}
// Test that we do not return duplicate values drawn from multiple profiles when
// filling an already filled field.
TEST_F(AutofillManagerTest, GetFieldSuggestionsWithDuplicateValues) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// |profile| will be owned by the mock PersonalDataManager.
AutofillProfile profile;
test::SetProfileInfo(&profile, "Elvis", "", "", "", "", "", "", "", "", "",
"", "");
profile.set_guid("00000000-0000-0000-0000-000000000101");
personal_data_.AddProfile(profile);
FormFieldData& field = form.fields[0];
field.is_autofilled = true;
field.value = ASCIIToUTF16("Elvis");
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
CheckSuggestions(kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1));
}
TEST_F(AutofillManagerTest, GetProfileSuggestions_FancyPhone) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000103");
profile.SetInfo(NAME_FULL, ASCIIToUTF16("Natty Bumppo"), "en-US");
profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1800PRAIRIE"));
personal_data_.AddProfile(profile);
const FormFieldData& field = form.fields[9];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate. Inferred
// labels include the most private field of those that would be filled.
CheckSuggestions(
kDefaultPageID,
Suggestion("18007724743", "Natty Bumppo", "", 1), // 1800PRAIRIE
Suggestion("23456789012", "123 Apple St.", "", 2),
Suggestion("12345678901", "3734 Elvis Presley Blvd.", "", 3));
}
TEST_F(AutofillManagerTest, GetProfileSuggestions_ForPhonePrefixOrSuffix) {
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("http://myform.com/form.html");
form.action = GURL("http://myform.com/submit.html");
struct {
const char* const label;
const char* const name;
size_t max_length;
const char* const autocomplete_attribute;
} test_fields[] = {{"country code", "country_code", 1, "tel-country-code"},
{"area code", "area_code", 3, "tel-area-code"},
{"phone", "phone_prefix", 3, "tel-local-prefix"},
{"-", "phone_suffix", 4, "tel-local-suffix"},
{"Phone Extension", "ext", 5, "tel-extension"}};
FormFieldData field;
for (const auto& test_field : test_fields) {
test::CreateTestFormField(test_field.label, test_field.name, "", "text",
&field);
field.max_length = test_field.max_length;
field.autocomplete_attribute = std::string();
form.fields.push_back(field);
}
std::vector<FormData> forms(1, form);
FormsSeen(forms);
personal_data_.ClearProfiles();
AutofillProfile profile;
profile.set_guid("00000000-0000-0000-0000-000000000104");
profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1800FLOWERS"));
personal_data_.AddProfile(profile);
const FormFieldData& phone_prefix = form.fields[2];
GetAutofillSuggestions(form, phone_prefix);
// Test that we sent the right prefix values to the external delegate.
CheckSuggestions(kDefaultPageID, Suggestion("356", "1800FLOWERS", "", 1));
const FormFieldData& phone_suffix = form.fields[3];
GetAutofillSuggestions(form, phone_suffix);
// Test that we sent the right suffix values to the external delegate.
CheckSuggestions(kDefaultPageID, Suggestion("9377", "1800FLOWERS", "", 1));
}
// Test that we correctly fill an address form.
TEST_F(AutofillManagerTest, FillAddressForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000001";
AutofillProfile* profile = personal_data_.GetProfileWithGUID(guid);
ASSERT_TRUE(profile);
EXPECT_EQ(1U, profile->use_count());
EXPECT_NE(base::Time(), profile->use_date());
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, form.fields[0],
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
EXPECT_EQ(2U, profile->use_count());
EXPECT_NE(base::Time(), profile->use_date());
}
TEST_F(AutofillManagerTest, WillFillCreditCardNumber) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData* number_field = nullptr;
FormFieldData* name_field = nullptr;
FormFieldData* month_field = nullptr;
for (size_t i = 0; i < form.fields.size(); ++i) {
if (form.fields[i].name == ASCIIToUTF16("cardnumber"))
number_field = &form.fields[i];
else if (form.fields[i].name == ASCIIToUTF16("nameoncard"))
name_field = &form.fields[i];
else if (form.fields[i].name == ASCIIToUTF16("ccmonth"))
month_field = &form.fields[i];
}
// Empty form - whole form is Autofilled.
EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field));
EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
// If the user has entered a value, it won't be overridden.
number_field->value = ASCIIToUTF16("gibberish");
EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field));
EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field));
// But if that value is removed, it will be Autofilled.
number_field->value.clear();
EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
// When the number is already autofilled, we won't fill it.
number_field->is_autofilled = true;
EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field));
EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field));
// If another field is filled, we would still fill other non-filled fields in
// the section.
number_field->is_autofilled = false;
name_field->is_autofilled = true;
EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
}
// Test that we correctly log FIELD_WAS_AUTOFILLED event in UserHappiness.
TEST_F(AutofillManagerTest, FillCreditCardForm_LogFieldWasAutofill) {
// Set up our form data.
FormData form;
// Construct a form with 4 fields: cardholder name, card number,
// expiration date and cvc.
CreateTestCreditCardFormData(&form, true, true);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000004";
int response_page_id = 0;
FormData response_data;
base::HistogramTester histogram_tester;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
// Cardholder name, card number, expiration data were autofilled but cvc was
// not be autofilled.
histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
AutofillMetrics::FIELD_WAS_AUTOFILLED, 3);
}
// Test that we correctly fill a credit card form.
TEST_F(AutofillManagerTest, FillCreditCardForm_Simple) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000004";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardFormElvis(response_page_id, response_data,
kDefaultPageID, false);
}
// Test that whitespace is stripped from the credit card number.
TEST_F(AutofillManagerTest, FillCreditCardForm_StripCardNumberWhitespace) {
// Same as the SetUp(), but generate Elvis card with whitespace in credit
// card number. |credit_card| will be owned by the TestPersonalDataManager.
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Elvis Presley",
"4234 5678 9012 3456", // Visa
"04", "2999", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000008");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000008";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardFormElvis(response_page_id, response_data,
kDefaultPageID, false);
}
// Test that separator characters are stripped from the credit card number.
TEST_F(AutofillManagerTest, FillCreditCardForm_StripCardNumberSeparators) {
// Same as the SetUp(), but generate Elvis card with separator characters in
// credit card number. |credit_card| will be owned by the
// TestPersonalDataManager.
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Elvis Presley",
"4234-5678-9012-3456", // Visa
"04", "2999", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000009");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000009";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardFormElvis(response_page_id, response_data,
kDefaultPageID, false);
}
// Test that we correctly fill a credit card form with month input type.
// Test 1 of 4: Empty month, empty year
TEST_F(AutofillManagerTest, FillCreditCardForm_NoYearNoMonth) {
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
"4234567890654321", // Visa
"", "", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000007");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, true);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000007";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardYearMonthWithYearMonth(response_page_id, response_data,
kDefaultPageID, false, "", "");
}
// Test that we correctly fill a credit card form with month input type.
// Test 2 of 4: Non-empty month, empty year
TEST_F(AutofillManagerTest, FillCreditCardForm_NoYearMonth) {
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
"4234567890654321", // Visa
"04", "", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000007");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, true);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000007";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardYearMonthWithYearMonth(response_page_id, response_data,
kDefaultPageID, false, "", "04");
}
// Test that we correctly fill a credit card form with month input type.
// Test 3 of 4: Empty month, non-empty year
TEST_F(AutofillManagerTest, FillCreditCardForm_YearNoMonth) {
// Same as the SetUp(), but generate 4 credit cards with year month
// combination.
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
"4234567890654321", // Visa
"", "2999", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000007");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, true);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000007";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardYearMonthWithYearMonth(
response_page_id, response_data, kDefaultPageID, false, "2999", "");
}
// Test that we correctly fill a credit card form with month input type.
// Test 4 of 4: Non-empty month, non-empty year
TEST_F(AutofillManagerTest, FillCreditCardForm_YearMonth) {
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
"4234567890654321", // Visa
"04", "2999", "1");
credit_card.set_guid("00000000-0000-0000-0000-000000000007");
personal_data_.AddCreditCard(credit_card);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, true);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000007";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledCreditCardYearMonthWithYearMonth(
response_page_id, response_data, kDefaultPageID, false, "2999", "04");
}
// Test that we correctly fill a credit card form with first and last cardholder
// name.
TEST_F(AutofillManagerTest, FillCreditCardForm_SplitName) {
// Set up our form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("Card Name", "cardname", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Last Name", "cardlastname", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("CVC", "cvc", "", "text", &field);
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000004";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
ExpectFilledField("Card Name", "cardname", "Elvis", "text",
response_data.fields[0]);
ExpectFilledField("Last Name", "cardlastname", "Presley", "text",
response_data.fields[1]);
ExpectFilledField("Card Number", "cardnumber", "4234567890123456", "text",
response_data.fields[2]);
}
// Test that we correctly fill a combined address and credit card form.
TEST_F(AutofillManagerTest, FillAddressAndCreditCardForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// First fill the address data.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
{
SCOPED_TRACE("Address");
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, form.fields[0],
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
ExpectFilledAddressFormElvis(response_page_id, response_data,
kDefaultPageID, true);
}
// Now fill the credit card data.
const int kPageID2 = 2;
const char guid2[] = "00000000-0000-0000-0000-000000000004";
response_page_id = 0;
{
FillAutofillFormDataAndSaveResults(kPageID2, form, form.fields.back(),
MakeFrontendID(guid2, std::string()),
&response_page_id, &response_data);
SCOPED_TRACE("Credit card");
ExpectFilledCreditCardFormElvis(response_page_id, response_data, kPageID2,
true);
}
}
// Test that a field with an unrecognized autocomplete attribute is not filled.
TEST_F(AutofillManagerTest, FillAddressForm_UnrecognizedAttribute) {
FormData address_form;
address_form.name = ASCIIToUTF16("MyForm");
address_form.origin = GURL("https://myform.com/form.html");
address_form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
// Set a valid autocomplete attribute for the first name.
test::CreateTestFormField("First name", "firstname", "", "text", &field);
field.autocomplete_attribute = "given-name";
address_form.fields.push_back(field);
// Set no autocomplete attribute for the middle name.
test::CreateTestFormField("Middle name", "middle", "", "text", &field);
field.autocomplete_attribute = "";
address_form.fields.push_back(field);
// Set an unrecognized autocomplete attribute for the last name.
test::CreateTestFormField("Last name", "lastname", "", "text", &field);
field.autocomplete_attribute = "unrecognized";
address_form.fields.push_back(field);
std::vector<FormData> address_forms(1, address_form);
FormsSeen(address_forms);
// Fill the address form.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(
kDefaultPageID, address_form, address_form.fields[0],
MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
// The fist and middle names should be filled.
ExpectFilledField("First name", "firstname", "Elvis", "text",
response_data.fields[0]);
ExpectFilledField("Middle name", "middle", "Aaron", "text",
response_data.fields[1]);
// The last name should not be filled.
ExpectFilledField("Last name", "lastname", "", "text",
response_data.fields[2]);
}
// Test that non credit card related fields with the autocomplete attribute set
// to off are not filled on desktop when the feature to autofill all addresses
// is disabled.
TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOffRespected) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(kAutofillAlwaysFillAddresses);
FormData address_form;
address_form.name = ASCIIToUTF16("MyForm");
address_form.origin = GURL("https://myform.com/form.html");
address_form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First name", "firstname", "", "text", &field);
address_form.fields.push_back(field);
test::CreateTestFormField("Middle name", "middle", "", "text", &field);
field.should_autocomplete = false;
address_form.fields.push_back(field);
test::CreateTestFormField("Last name", "lastname", "", "text", &field);
field.should_autocomplete = true;
address_form.fields.push_back(field);
test::CreateTestFormField("Address Line 1", "addr1", "", "text", &field);
field.should_autocomplete = false;
address_form.fields.push_back(field);
std::vector<FormData> address_forms(1, address_form);
FormsSeen(address_forms);
// Fill the address form.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(
kDefaultPageID, address_form, address_form.fields[0],
MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
// The fist name should be filled.
ExpectFilledField("First name", "firstname", "Elvis", "text",
response_data.fields[0]);
// The middle name should not be filled on desktop.
if (IsDesktopPlatform()) {
ExpectFilledField("Middle name", "middle", "", "text",
response_data.fields[1]);
} else {
ExpectFilledField("Middle name", "middle", "Aaron", "text",
response_data.fields[1]);
}
// The last name should be filled.
ExpectFilledField("Last name", "lastname", "Presley", "text",
response_data.fields[2]);
// The address line 1 should not be filled on desktop.
if (IsDesktopPlatform()) {
ExpectFilledField("Address Line 1", "addr1", "", "text",
response_data.fields[3]);
} else {
ExpectFilledField("Address Line 1", "addr1", "3734 Elvis Presley Blvd.",
"text", response_data.fields[3]);
}
}
// Test that non credit card related fields with the autocomplete attribute set
// to off are filled on all platforms when the feature to autofill all addresses
// is enabled (default).
TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOffNotRespected) {
FormData address_form;
address_form.name = ASCIIToUTF16("MyForm");
address_form.origin = GURL("https://myform.com/form.html");
address_form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First name", "firstname", "", "text", &field);
address_form.fields.push_back(field);
test::CreateTestFormField("Middle name", "middle", "", "text", &field);
field.should_autocomplete = false;
address_form.fields.push_back(field);
test::CreateTestFormField("Last name", "lastname", "", "text", &field);
field.should_autocomplete = true;
address_form.fields.push_back(field);
test::CreateTestFormField("Address Line 1", "addr1", "", "text", &field);
field.should_autocomplete = false;
address_form.fields.push_back(field);
std::vector<FormData> address_forms(1, address_form);
FormsSeen(address_forms);
// Fill the address form.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(
kDefaultPageID, address_form, address_form.fields[0],
MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
// All fields should be filled.
ExpectFilledField("First name", "firstname", "Elvis", "text",
response_data.fields[0]);
ExpectFilledField("Middle name", "middle", "Aaron", "text",
response_data.fields[1]);
ExpectFilledField("Last name", "lastname", "Presley", "text",
response_data.fields[2]);
ExpectFilledField("Address Line 1", "addr1", "3734 Elvis Presley Blvd.",
"text", response_data.fields[3]);
}
// Test that a field with a value equal to it's placeholder attribute is filled.
TEST_F(AutofillManagerTest, FillAddressForm_PlaceholderEqualsValue) {
FormData address_form;
address_form.name = ASCIIToUTF16("MyForm");
address_form.origin = GURL("https://myform.com/form.html");
address_form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
// Set the same placeholder and value for each field.
test::CreateTestFormField("First name", "firstname", "", "text", &field);
field.placeholder = ASCIIToUTF16("First Name");
field.value = ASCIIToUTF16("First Name");
address_form.fields.push_back(field);
test::CreateTestFormField("Middle name", "middle", "", "text", &field);
field.placeholder = ASCIIToUTF16("Middle Name");
field.value = ASCIIToUTF16("Middle Name");
address_form.fields.push_back(field);
test::CreateTestFormField("Last name", "lastname", "", "text", &field);
field.placeholder = ASCIIToUTF16("Last Name");
field.value = ASCIIToUTF16("Last Name");
address_form.fields.push_back(field);
std::vector<FormData> address_forms(1, address_form);
FormsSeen(address_forms);
// Fill the address form.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(
kDefaultPageID, address_form, address_form.fields[0],
MakeFrontendID(std::string(), guid), &response_page_id, &response_data);
// All the fields should be filled.
ExpectFilledField("First name", "firstname", "Elvis", "text",
response_data.fields[0]);
ExpectFilledField("Middle name", "middle", "Aaron", "text",
response_data.fields[1]);
ExpectFilledField("Last name", "lastname", "Presley", "text",
response_data.fields[2]);
}
// Test that a credit card field with an unrecognized autocomplete attribute
// gets filled.
TEST_F(AutofillManagerTest, FillCreditCardForm_UnrecognizedAttribute) {
// Set up the form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
// Set a valid autocomplete attribute on the card name.
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
field.autocomplete_attribute = "cc-name";
form.fields.push_back(field);
// Set no autocomplete attribute on the card number.
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
field.autocomplete_attribute = "";
form.fields.push_back(field);
// Set an unrecognized autocomplete attribute on the expiration month.
test::CreateTestFormField("Expiration Date", "ccmonth", "", "text", &field);
field.autocomplete_attribute = "unrecognized";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000004";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
// The credit card name and number should be filled.
ExpectFilledField("Name on Card", "nameoncard", "Elvis Presley", "text",
response_data.fields[0]);
ExpectFilledField("Card Number", "cardnumber", "4234567890123456", "text",
response_data.fields[1]);
// The expiration month should be filled.
ExpectFilledField("Expiration Date", "ccmonth", "04/2999", "text",
response_data.fields[2]);
}
// Test that credit card fields are filled even if they have the autocomplete
// attribute set to off.
TEST_F(AutofillManagerTest, FillCreditCardForm_AutocompleteOff) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
// Set the autocomplete=off on all fields.
for (FormFieldData field : form.fields)
field.should_autocomplete = false;
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000004";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
// All fields should be filled.
ExpectFilledCreditCardFormElvis(response_page_id, response_data,
kDefaultPageID, false);
}
// Test that selecting an expired credit card fills everything except the
// expiration date.
TEST_F(AutofillManagerTest, FillCreditCardForm_ExpiredCard) {
personal_data_.ClearCreditCards();
CreditCard expired_card;
test::SetCreditCardInfo(&expired_card, "Homer Simpson",
"4234567890654321", // Visa
"05", "2000", "1");
expired_card.set_guid("00000000-0000-0000-0000-000000000009");
personal_data_.AddCreditCard(expired_card);
// Set up the form data.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
// Create a credit card form.
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
field.autocomplete_attribute = "cc-name";
form.fields.push_back(field);
std::vector<const char*> kCreditCardTypes = {"Visa", "Mastercard", "AmEx",
"discover"};
test::CreateTestSelectField("Card Type", "cardtype", "", kCreditCardTypes,
kCreditCardTypes, 4, &field);
field.autocomplete_attribute = "cc-type";
form.fields.push_back(field);
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
field.autocomplete_attribute = "cc-number";
form.fields.push_back(field);
test::CreateTestFormField("Expiration Month", "ccmonth", "", "text", &field);
field.autocomplete_attribute = "cc-exp-month";
form.fields.push_back(field);
test::CreateTestFormField("Expiration Year", "ccyear", "", "text", &field);
field.autocomplete_attribute = "cc-exp-year";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const char guid[] = "00000000-0000-0000-0000-000000000009";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(guid, std::string()),
&response_page_id, &response_data);
// The credit card name, type and number should be filled.
ExpectFilledField("Name on Card", "nameoncard", "Homer Simpson", "text",
response_data.fields[0]);
ExpectFilledField("Card Type", "cardtype", "Visa", "select-one",
response_data.fields[1]);
ExpectFilledField("Card Number", "cardnumber", "4234567890654321", "text",
response_data.fields[2]);
// The expiration month and year should not be filled.
ExpectFilledField("Expiration Month", "ccmonth", "", "text",
response_data.fields[3]);
ExpectFilledField("Expiration Year", "ccyear", "", "text",
response_data.fields[4]);
}
// Test that non-focusable field is ignored while inferring boundaries between
// sections, but not filled.
TEST_F(AutofillManagerTest, FillFormWithNonFocusableFields) {
// Create a form with both focusable and non-focusable fields.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First Name", "firstname", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("", "lastname", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("", "email", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Phone Number", "phonenumber", "", "tel", &field);
form.fields.push_back(field);
test::CreateTestFormField("", "email_", "", "text", &field);
field.is_focusable = false;
form.fields.push_back(field);
test::CreateTestFormField("Country", "country", "", "text", &field);
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Fill the form
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, form.fields[0],
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
// All the visible fields should be filled as all the fields belong to the
// same logical section.
ASSERT_EQ(6U, response_data.fields.size());
ExpectFilledField("First Name", "firstname", "Elvis", "text",
response_data.fields[0]);
ExpectFilledField("", "lastname", "Presley", "text", response_data.fields[1]);
ExpectFilledField("", "email", "theking@gmail.com", "text",
response_data.fields[2]);
ExpectFilledField("Phone Number", "phonenumber", "12345678901", "tel",
response_data.fields[3]);
ExpectFilledField("", "email_", "", "text", response_data.fields[4]);
ExpectFilledField("Country", "country", "United States", "text",
response_data.fields[5]);
}
// Test that we correctly fill a form that has multiple logical sections, e.g.
// both a billing and a shipping address.
TEST_F(AutofillManagerTest, FillFormWithMultipleSections) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
const size_t kAddressFormSize = form.fields.size();
test::CreateTestAddressFormData(&form);
for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) {
// Make sure the fields have distinct names.
form.fields[i].name = form.fields[i].name + ASCIIToUTF16("_");
}
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Fill the first section.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, form.fields[0],
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
{
SCOPED_TRACE("Address 1");
// The second address section should be empty.
ASSERT_EQ(response_data.fields.size(), 2 * kAddressFormSize);
for (size_t i = kAddressFormSize; i < form.fields.size(); ++i) {
EXPECT_EQ(base::string16(), response_data.fields[i].value);
}
// The first address section should be filled with Elvis's data.
response_data.fields.resize(kAddressFormSize);
ExpectFilledAddressFormElvis(response_page_id, response_data,
kDefaultPageID, false);
}
// Fill the second section, with the initiating field somewhere in the middle
// of the section.
const int kPageID2 = 2;
const char guid2[] = "00000000-0000-0000-0000-000000000001";
ASSERT_LT(9U, kAddressFormSize);
response_page_id = 0;
FillAutofillFormDataAndSaveResults(
kPageID2, form, form.fields[kAddressFormSize + 9],
MakeFrontendID(std::string(), guid2), &response_page_id, &response_data);
{
SCOPED_TRACE("Address 2");
ASSERT_EQ(response_data.fields.size(), form.fields.size());
// The first address section should be empty.
ASSERT_EQ(response_data.fields.size(), 2 * kAddressFormSize);
for (size_t i = 0; i < kAddressFormSize; ++i) {
EXPECT_EQ(base::string16(), response_data.fields[i].value);
}
// The second address section should be filled with Elvis's data.
FormData secondSection = response_data;
secondSection.fields.erase(secondSection.fields.begin(),
secondSection.fields.begin() + kAddressFormSize);
for