blob: 87dccd93ac19629f0feeed01a45cc5714c262148 [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 <algorithm>
#include <vector>
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/prefs/pref_service.h"
#include "base/run_loop.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/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.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_manager.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/test_autofill_client.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/validation.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.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 "grit/components_strings.h"
#include "net/url_request/url_request_test_util.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 base::ASCIIToUTF16;
using base::UTF8ToUTF16;
using testing::_;
using testing::AtLeast;
using testing::SaveArg;
namespace autofill {
namespace {
const int kDefaultPageID = 137;
class MockAutofillClient : public TestAutofillClient {
public:
MockAutofillClient() {}
~MockAutofillClient() override {}
MOCK_METHOD1(ConfirmSaveCreditCardLocally,
void(const base::Closure& callback));
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
class TestPaymentsClient : public payments::PaymentsClient {
public:
TestPaymentsClient(net::URLRequestContextGetter* context_getter,
payments::PaymentsClientDelegate* delegate)
: PaymentsClient(context_getter, delegate), delegate_(delegate) {}
~TestPaymentsClient() override {}
void GetUploadDetails(const std::string& app_locale) override {
delegate_->OnDidGetUploadDetails(
app_locale == "en-US" ? AutofillClient::SUCCESS
: AutofillClient::PERMANENT_FAILURE,
base::ASCIIToUTF16("this is a context token"),
scoped_ptr<base::DictionaryValue>(nullptr));
}
void UploadCard(const payments::PaymentsClient::UploadRequestDetails&
request_details) override {
delegate_->OnDidUploadCard(AutofillClient::SUCCESS);
}
private:
payments::PaymentsClientDelegate* const delegate_;
DISALLOW_COPY_AND_ASSIGN(TestPaymentsClient);
};
class TestPersonalDataManager : public PersonalDataManager {
public:
TestPersonalDataManager()
: PersonalDataManager("en-US"),
num_times_save_imported_profile_called_(0) {
CreateTestAutofillProfiles(&web_profiles_);
CreateTestCreditCards(&local_credit_cards_);
}
using PersonalDataManager::set_database;
using PersonalDataManager::SetPrefService;
int num_times_save_imported_profile_called() {
return num_times_save_imported_profile_called_;
}
std::string SaveImportedProfile(const AutofillProfile& profile) override {
num_times_save_imported_profile_called_++;
AutofillProfile* imported_profile = new AutofillProfile(profile);
AddProfile(imported_profile);
return profile.guid();
}
AutofillProfile* GetProfileWithGUID(const char* guid) {
for (AutofillProfile* profile : GetProfiles()) {
if (!profile->guid().compare(guid))
return profile;
}
return NULL;
}
CreditCard* GetCreditCardWithGUID(const char* guid) {
for (CreditCard* card : GetCreditCards()) {
if (!card->guid().compare(guid))
return card;
}
return NULL;
}
void AddProfile(AutofillProfile* profile) {
profile->set_modification_date(base::Time::Now());
web_profiles_.push_back(profile);
}
void AddCreditCard(CreditCard* credit_card) {
credit_card->set_modification_date(base::Time::Now());
local_credit_cards_.push_back(credit_card);
}
void RecordUseOf(const AutofillDataModel& data_model) override {
CreditCard* credit_card = GetCreditCardWithGUID(data_model.guid().c_str());
if (credit_card)
credit_card->RecordAndLogUse();
AutofillProfile* profile = GetProfileWithGUID(data_model.guid().c_str());
if (profile)
profile->RecordAndLogUse();
}
void RemoveByGUID(const std::string& guid) override {
CreditCard* credit_card = GetCreditCardWithGUID(guid.c_str());
if (credit_card) {
local_credit_cards_.erase(
std::find(local_credit_cards_.begin(), local_credit_cards_.end(),
credit_card));
}
AutofillProfile* profile = GetProfileWithGUID(guid.c_str());
if (profile) {
web_profiles_.erase(
std::find(web_profiles_.begin(), web_profiles_.end(), profile));
}
}
void ClearAutofillProfiles() {
web_profiles_.clear();
}
void ClearCreditCards() {
local_credit_cards_.clear();
}
// Create Elvis card with whitespace in the credit card number.
void CreateTestCreditCardWithWhitespace() {
ClearCreditCards();
CreditCard* credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "Elvis Presley",
"4234 5678 9012 3456", // Visa
"04", "2012");
credit_card->set_guid("00000000-0000-0000-0000-000000000008");
local_credit_cards_.push_back(credit_card);
}
// Create Elvis card with separator characters in the credit card number.
void CreateTestCreditCardWithSeparators() {
ClearCreditCards();
CreditCard* credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "Elvis Presley",
"4234-5678-9012-3456", // Visa
"04", "2012");
credit_card->set_guid("00000000-0000-0000-0000-000000000009");
local_credit_cards_.push_back(credit_card);
}
void CreateTestCreditCardsYearAndMonth(const char* year, const char* month) {
ClearCreditCards();
CreditCard* credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "Miku Hatsune",
"4234567890654321", // Visa
month, year);
credit_card->set_guid("00000000-0000-0000-0000-000000000007");
local_credit_cards_.push_back(credit_card);
}
private:
void CreateTestAutofillProfiles(ScopedVector<AutofillProfile>* profiles) {
AutofillProfile* profile = new AutofillProfile;
test::SetProfileInfo(profile, "Elvis", "Aaron",
"Presley", "theking@gmail.com", "RCA",
"3734 Elvis Presley Blvd.", "Apt. 10",
"Memphis", "Tennessee", "38116", "US",
"12345678901");
profile->set_guid("00000000-0000-0000-0000-000000000001");
profiles->push_back(profile);
profile = new AutofillProfile;
test::SetProfileInfo(profile, "Charles", "Hardin",
"Holley", "buddy@gmail.com", "Decca",
"123 Apple St.", "unit 6", "Lubbock",
"Texas", "79401", "US", "23456789012");
profile->set_guid("00000000-0000-0000-0000-000000000002");
profiles->push_back(profile);
profile = new AutofillProfile;
test::SetProfileInfo(
profile, "", "", "", "", "", "", "", "", "", "", "", "");
profile->set_guid("00000000-0000-0000-0000-000000000003");
profiles->push_back(profile);
}
void CreateTestCreditCards(ScopedVector<CreditCard>* credit_cards) {
CreditCard* credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "Elvis Presley",
"4234567890123456", // Visa
"04", "2012");
credit_card->set_guid("00000000-0000-0000-0000-000000000004");
credit_cards->push_back(credit_card);
credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "Buddy Holly",
"5187654321098765", // Mastercard
"10", "2014");
credit_card->set_guid("00000000-0000-0000-0000-000000000005");
credit_cards->push_back(credit_card);
credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "", "", "", "");
credit_card->set_guid("00000000-0000-0000-0000-000000000006");
credit_cards->push_back(credit_card);
}
size_t num_times_save_imported_profile_called_;
DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager);
};
class TestAutofillDownloadManager : public AutofillDownloadManager {
public:
TestAutofillDownloadManager(AutofillDriver* driver,
PrefService* pref_service,
AutofillDownloadManager::Observer* observer)
: AutofillDownloadManager(driver, pref_service, observer) {}
bool StartQueryRequest(const std::vector<FormStructure*>& forms) override {
last_queried_forms_ = forms;
return true;
}
// Verify that the last queried forms equal |expected_forms|.
void VerifyLastQueriedForms(const std::vector<FormData>& expected_forms) {
ASSERT_EQ(expected_forms.size(), last_queried_forms_.size());
for (size_t i = 0; i < expected_forms.size(); ++i) {
EXPECT_EQ(*last_queried_forms_[i], expected_forms[i]);
}
}
private:
std::vector<FormStructure*> last_queried_forms_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillDownloadManager);
};
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", "2012", 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() : is_off_the_record_(false) {}
// Mock methods to enable testability.
MOCK_METHOD3(SendFormDataToRenderer, void(int query_id,
RendererFormDataAction action,
const FormData& data));
void SetIsOffTheRecord(bool is_off_the_record) {
is_off_the_record_ = is_off_the_record;
}
bool IsOffTheRecord() const override { return is_off_the_record_; }
private:
bool is_off_the_record_;
DISALLOW_COPY_AND_ASSIGN(MockAutofillDriver);
};
class TestAutofillManager : public AutofillManager {
public:
TestAutofillManager(AutofillDriver* driver,
AutofillClient* client,
TestPersonalDataManager* personal_data)
: AutofillManager(driver, client, personal_data),
personal_data_(personal_data),
autofill_enabled_(true),
credit_card_upload_enabled_(true),
credit_card_was_uploaded_(false),
expect_all_unknown_possible_types_(false) {
set_payments_client(
new TestPaymentsClient(driver->GetURLRequestContext(), this));
}
~TestAutofillManager() override {}
bool IsAutofillEnabled() const override { return autofill_enabled_; }
void set_autofill_enabled(bool autofill_enabled) {
autofill_enabled_ = autofill_enabled;
}
bool IsCreditCardUploadEnabled() override {
return credit_card_upload_enabled_;
}
void set_credit_card_upload_enabled(bool credit_card_upload_enabled) {
credit_card_upload_enabled_ = credit_card_upload_enabled;
}
bool credit_card_was_uploaded() { return credit_card_was_uploaded_; }
void set_expected_submitted_field_types(
const std::vector<ServerFieldTypeSet>& expected_types) {
expected_submitted_field_types_ = expected_types;
}
void UploadFormDataAsyncCallback(
const FormStructure* submitted_form,
const base::TimeTicks& load_time,
const base::TimeTicks& interaction_time,
const base::TimeTicks& submission_time) override {
run_loop_->Quit();
// If we have expected field types set, make sure they match.
if (!expected_submitted_field_types_.empty()) {
ASSERT_EQ(expected_submitted_field_types_.size(),
submitted_form->field_count());
for (size_t i = 0; i < expected_submitted_field_types_.size(); ++i) {
SCOPED_TRACE(
base::StringPrintf(
"Field %d with value %s", static_cast<int>(i),
base::UTF16ToUTF8(submitted_form->field(i)->value).c_str()));
const ServerFieldTypeSet& possible_types =
submitted_form->field(i)->possible_types();
EXPECT_EQ(expected_submitted_field_types_[i].size(),
possible_types.size());
for (ServerFieldTypeSet::const_iterator it =
expected_submitted_field_types_[i].begin();
it != expected_submitted_field_types_[i].end(); ++it) {
EXPECT_TRUE(possible_types.count(*it))
<< "Expected type: " << AutofillType(*it).ToString();
}
}
}
AutofillManager::UploadFormDataAsyncCallback(submitted_form,
load_time,
interaction_time,
submission_time);
}
// Resets the run loop so that it can wait for an asynchronous form
// submission to complete.
void ResetRunLoop() { run_loop_.reset(new base::RunLoop()); }
// Wait for the asynchronous OnWillSubmitForm() call to complete.
void WaitForAsyncOnWillSubmitForm() { run_loop_->Run(); }
void UploadFormData(const FormStructure& submitted_form) override {
submitted_form_signature_ = submitted_form.FormSignature();
}
const std::string GetSubmittedFormSignature() {
return submitted_form_signature_;
}
AutofillProfile* GetProfileWithGUID(const char* guid) {
return personal_data_->GetProfileWithGUID(guid);
}
CreditCard* GetCreditCardWithGUID(const char* guid) {
return personal_data_->GetCreditCardWithGUID(guid);
}
void AddProfile(AutofillProfile* profile) {
personal_data_->AddProfile(profile);
}
void AddCreditCard(CreditCard* credit_card) {
personal_data_->AddCreditCard(credit_card);
}
int GetPackedCreditCardID(int credit_card_id) {
std::string credit_card_guid =
base::StringPrintf("00000000-0000-0000-0000-%012d", credit_card_id);
return MakeFrontendID(credit_card_guid, std::string());
}
void AddSeenForm(FormStructure* form) {
form_structures()->push_back(form);
}
void ClearFormStructures() {
form_structures()->clear();
}
private:
void OnDidUploadCard(AutofillClient::PaymentsRpcResult result) override {
credit_card_was_uploaded_ = true;
};
// Weak reference.
TestPersonalDataManager* personal_data_;
bool autofill_enabled_;
bool credit_card_upload_enabled_;
bool credit_card_was_uploaded_;
bool expect_all_unknown_possible_types_;
scoped_ptr<base::RunLoop> run_loop_;
std::string submitted_form_signature_;
std::vector<ServerFieldTypeSet> expected_submitted_field_types_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
};
class TestAutofillExternalDelegate : public AutofillExternalDelegate {
public:
explicit TestAutofillExternalDelegate(AutofillManager* autofill_manager,
AutofillDriver* autofill_driver)
: AutofillExternalDelegate(autofill_manager, autofill_driver),
on_query_seen_(false),
on_suggestions_returned_seen_(false) {}
~TestAutofillExternalDelegate() override {}
void OnQuery(int query_id,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounds) override {
on_query_seen_ = true;
on_suggestions_returned_seen_ = false;
}
void OnSuggestionsReturned(
int query_id,
const std::vector<Suggestion>& suggestions) override {
on_suggestions_returned_seen_ = true;
query_id_ = query_id;
suggestions_ = suggestions;
}
void CheckSuggestions(int expected_page_id,
size_t expected_num_suggestions,
const Suggestion expected_suggestions[]) {
// Ensure that these results are from the most recent query.
EXPECT_TRUE(on_suggestions_returned_seen_);
EXPECT_EQ(expected_page_id, query_id_);
ASSERT_EQ(expected_num_suggestions, suggestions_.size());
for (size_t i = 0; i < expected_num_suggestions; ++i) {
SCOPED_TRACE(base::StringPrintf("i: %" PRIuS, i));
EXPECT_EQ(expected_suggestions[i].value, suggestions_[i].value);
EXPECT_EQ(expected_suggestions[i].label, suggestions_[i].label);
EXPECT_EQ(expected_suggestions[i].icon, suggestions_[i].icon);
EXPECT_EQ(expected_suggestions[i].frontend_id,
suggestions_[i].frontend_id);
}
}
// Wrappers around the above 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);
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);
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);
CheckSuggestions(expected_page_id, 3, &suggestion_vector[0]);
}
bool on_query_seen() const {
return on_query_seen_;
}
bool on_suggestions_returned_seen() const {
return on_suggestions_returned_seen_;
}
private:
// Records if OnQuery has been called yet.
bool on_query_seen_;
// Records if OnSuggestionsReturned has been called after the most recent
// call to OnQuery.
bool on_suggestions_returned_seen_;
// The query id of the most recent Autofill query.
int query_id_;
// The results returned by the most recent Autofill query.
std::vector<Suggestion> suggestions_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate);
};
} // namespace
class AutofillManagerTest : public testing::Test {
public:
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
personal_data_.set_database(autofill_client_.GetDatabase());
personal_data_.SetPrefService(autofill_client_.GetPrefs());
autofill_driver_.reset(new MockAutofillDriver());
request_context_ = new net::TestURLRequestContextGetter(
base::ThreadTaskRunnerHandle::Get());
autofill_driver_->SetURLRequestContext(request_context_.get());
autofill_manager_.reset(new TestAutofillManager(
autofill_driver_.get(), &autofill_client_, &personal_data_));
download_manager_ = new TestAutofillDownloadManager(
autofill_driver_.get(), autofill_client_.GetPrefs(),
autofill_manager_.get());
// AutofillManager takes ownership of |download_manager_|.
autofill_manager_->set_download_manager(download_manager_);
external_delegate_.reset(new TestAutofillExternalDelegate(
autofill_manager_.get(),
autofill_driver_.get()));
autofill_manager_->SetExternalDelegate(external_delegate_.get());
}
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>(NULL));
personal_data_.SetPrefService(NULL);
request_context_ = nullptr;
}
void GetAutofillSuggestions(int query_id,
const FormData& form,
const FormFieldData& field) {
autofill_manager_->OnQueryFormFieldAutofill(query_id, form, field,
gfx::RectF());
}
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_->ResetRunLoop();
if (autofill_manager_->OnWillSubmitForm(form, base::TimeTicks::Now()))
autofill_manager_->WaitForAsyncOnWillSubmitForm();
autofill_manager_->OnFormSubmitted(form);
}
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");
autofill_client_.set_is_context_secure(false);
}
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);
}
// Fills the fields in |form| with test data.
void ManuallyFillAddressForm(FormData* form) {
for (FormFieldData& field : form->fields) {
if (base::EqualsASCII(field.name, "firstname"))
field.value = ASCIIToUTF16("Flo");
else if (base::EqualsASCII(field.name, "lastname"))
field.value = ASCIIToUTF16("Master");
else if (base::EqualsASCII(field.name, "addr1"))
field.value = ASCIIToUTF16("123 Maple");
else if (base::EqualsASCII(field.name, "city"))
field.value = ASCIIToUTF16("Dallas");
else if (base::EqualsASCII(field.name, "state"))
field.value = ASCIIToUTF16("Texas");
else if (base::EqualsASCII(field.name, "zipcode"))
field.value = ASCIIToUTF16("77401");
else if (base::EqualsASCII(field.name, "country"))
field.value = ASCIIToUTF16("US");
}
}
// Tests if credit card data gets saved
void TestSaveCreditCards(bool is_https) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, is_https, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Edit the data, and submit
form.fields[1].value = ASCIIToUTF16("4111111111111111");
form.fields[2].value = ASCIIToUTF16("11");
form.fields[3].value = ASCIIToUTF16("2017");
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(1);
FormSubmitted(form);
}
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");
card->SetTypeForMaskedCard(kVisaCard);
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(0);
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _))
.Times(AtLeast(1));
autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form,
form->fields[0], *card);
#if defined(OS_IOS)
// Filling out the entire form on iOS requires requesting autofill on each
// of the form fields.
autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form,
form->fields[1], *card);
autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form,
form->fields[2], *card);
autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form,
form->fields[3], *card);
#endif // defined(OS_IOS)
}
protected:
base::MessageLoop message_loop_;
MockAutofillClient autofill_client_;
scoped_ptr<MockAutofillDriver> autofill_driver_;
scoped_ptr<TestAutofillManager> autofill_manager_;
scoped_ptr<TestAutofillExternalDelegate> external_delegate_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_;
TestPaymentsClient* payments_client_;
TestAutofillDownloadManager* download_manager_;
TestPersonalDataManager personal_data_;
};
class TestFormStructure : public FormStructure {
public:
explicit TestFormStructure(const FormData& form)
: FormStructure(form) {}
~TestFormStructure() override {}
void SetFieldTypes(const std::vector<ServerFieldType>& heuristic_types,
const std::vector<ServerFieldType>& server_types) {
ASSERT_EQ(field_count(), heuristic_types.size());
ASSERT_EQ(field_count(), server_types.size());
for (size_t i = 0; i < field_count(); ++i) {
AutofillField* form_field = field(i);
ASSERT_TRUE(form_field);
form_field->set_heuristic_type(heuristic_types[i]);
form_field->set_server_type(server_types[i]);
}
UpdateAutofillCount();
}
private:
DISALLOW_COPY_AND_ASSIGN(TestFormStructure);
};
// 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 no suggestions are returned when there are less than three fields
// and none of them have an autocomplete attribute.
TEST_F(AutofillManagerTest, GetProfileSuggestions_SmallFormNoAutocomplete) {
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);
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 for 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_SmallFormWithOneAutocomplete) {
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]);
external_delegate_->CheckSuggestions(kDefaultPageID,
Suggestion("Elvis", "", "", 1),
Suggestion("Charles", "", "", 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 for a form with two fields with autocomplete attributes,
// suggestions are made for both fields.
TEST_F(AutofillManagerTest,
GetProfileSuggestions_SmallFormWithTwoAutocomplete) {
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]);
external_delegate_->CheckSuggestions(
kDefaultPageID, Suggestion("Elvis", "Elvis Aaron Presley", "", 1),
Suggestion("Charles", "Charles Hardin Holley", "", 2));
GetAutofillSuggestions(form, form.fields[1]);
external_delegate_->CheckSuggestions(
kDefaultPageID, Suggestion("Presley", "Elvis Aaron Presley", "", 1),
Suggestion("Holley", "Charles Hardin Holley", "", 2));
}
// Test that we return all address profile suggestions when all form fields are
// empty.
TEST_F(AutofillManagerTest, GetProfileSuggestionsEmptyValue) {
// 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("Charles", "123 Apple St.", "", 2));
}
// Test that we return only matching address profile suggestions when the
// selected form field has been partially filled out.
TEST_F(AutofillManagerTest, GetProfileSuggestionsMatchCharacter) {
// 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.
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 = new AutofillProfile;
profile1->set_guid("00000000-0000-0000-0000-000000000103");
profile1->SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Robin"), "en-US");
profile1->SetInfo(AutofillType(NAME_LAST), ASCIIToUTF16("Grimes"), "en-US");
profile1->SetInfo(AutofillType(ADDRESS_HOME_LINE1),
ASCIIToUTF16("1234 Smith Blvd."), "en-US");
autofill_manager_->AddProfile(profile1);
AutofillProfile* profile2 = new AutofillProfile;
profile2->set_guid("00000000-0000-0000-0000-000000000124");
profile2->SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Carl"), "en-US");
profile2->SetInfo(AutofillType(NAME_LAST), ASCIIToUTF16("Grimes"), "en-US");
profile2->SetInfo(AutofillType(ADDRESS_HOME_LINE1),
ASCIIToUTF16("1234 Smith Blvd."), "en-US");
autofill_manager_->AddProfile(profile2);
AutofillProfile* profile3 = new AutofillProfile;
profile3->set_guid("00000000-0000-0000-0000-000000000126");
profile3->SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Aaron"), "en-US");
profile3->SetInfo(AutofillType(NAME_LAST), ASCIIToUTF16("Googler"), "en-US");
profile3->SetInfo(AutofillType(ADDRESS_HOME_LINE1),
ASCIIToUTF16("1600 Amphitheater pkwy"), "en-US");
autofill_manager_->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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Grimes", "" /* no label */, "", 1),
Suggestion("Googler", "" /* no label */, "", 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "" /* no label */, "", 1));
}
// Test that we return no suggestions when the form has no relevant fields.
TEST_F(AutofillManagerTest, GetProfileSuggestionsUnknownFields) {
// 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, GetProfileSuggestionsWithDuplicates) {
// 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 =
new AutofillProfile(
*(autofill_manager_->GetProfileWithGUID(
"00000000-0000-0000-0000-000000000001")));
autofill_manager_->AddProfile(duplicate_profile);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
// Test that we sent the right values to the external delegate.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("Charles", "123 Apple St.", "", 2));
}
// Test that we return no suggestions when autofill is disabled.
TEST_F(AutofillManagerTest, GetProfileSuggestionsAutofillDisabledByUser) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Disable Autofill.
autofill_manager_->set_autofill_enabled(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, GetCreditCardSuggestionsEmptyValue) {
// 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion(
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456",
"04/12", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(
"MasterCard\xC2\xA0\xE2\x8B\xAF"
"8765",
"10/14", kMasterCard, autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return only matching credit card profile suggestions when the
// selected form field has been partially filled out.
TEST_F(AutofillManagerTest, GetCreditCardSuggestionsMatchCharacter) {
// 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion(
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456",
"04/12", 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, GetCreditCardSuggestionsNonCCNumber) {
// 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 char* kVisaSuggestion =
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456";
static const char* kMcSuggestion =
"MasterCard\xC2\xA0\xE2\x8B\xAF"
"8765";
#else
static const char* kVisaSuggestion = "*3456";
static const char* kMcSuggestion = "*8765";
#endif
// Test that we sent the right values to the external delegate.
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 return a warning explaining that credit card profile suggestions
// are unavailable when the form is not secure.
TEST_F(AutofillManagerTest, GetCreditCardSuggestionsNonHTTPS) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, false, false);
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.
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);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that we return all credit card suggestions in the case that two cards
// have the same obfuscated number.
TEST_F(AutofillManagerTest, GetCreditCardSuggestionsRepeatedObfuscatedNumber) {
// Add a credit card with the same obfuscated number as Elvis's.
// |credit_card| will be owned by the mock PersonalDataManager.
CreditCard* credit_card = new CreditCard;
test::SetCreditCardInfo(credit_card, "Elvis Presley",
"5231567890123456", // Mastercard
"05", "2012");
credit_card->set_guid("00000000-0000-0000-0000-000000000007");
autofill_manager_->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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion(
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456",
"04/12", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(
"MasterCard\xC2\xA0\xE2\x8B\xAF"
"8765",
"10/14", kMasterCard, autofill_manager_->GetPackedCreditCardID(5)),
Suggestion(
"MasterCard\xC2\xA0\xE2\x8B\xAF"
"3456",
"05/12", 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("Charles", "123 Apple St.", "", 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.
external_delegate_->CheckSuggestions(
kPageID2,
Suggestion(
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456",
"04/12", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(
"MasterCard\xC2\xA0\xE2\x8B\xAF"
"8765",
"10/14", 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("Charles", "123 Apple St.", "", 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.
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);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Test that we return autocomplete-like 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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "", "", 1),
Suggestion("Charles", "", "", 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.
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 = new AutofillProfile;
test::SetProfileInfo(
profile, "Elvis", "", "", "", "", "", "", "", "", "", "", "");
profile->set_guid("00000000-0000-0000-0000-000000000101");
autofill_manager_->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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "", "", 1));
}
TEST_F(AutofillManagerTest, GetProfileSuggestionsFancyPhone) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
AutofillProfile* profile = new AutofillProfile;
profile->set_guid("00000000-0000-0000-0000-000000000103");
profile->SetInfo(AutofillType(NAME_FULL), ASCIIToUTF16("Natty Bumppo"),
"en-US");
profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
ASCIIToUTF16("1800PRAIRIE"));
autofill_manager_->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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("12345678901", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("23456789012", "123 Apple St.", "", 2),
Suggestion("18007724743", "Natty Bumppo", "", 3)); // 1800PRAIRIE
}
TEST_F(AutofillManagerTest, GetProfileSuggestionsForPhonePrefixOrSuffix) {
// 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 (size_t i = 0; i < arraysize(test_fields); ++i) {
test::CreateTestFormField(
test_fields[i].label, test_fields[i].name, "", "text", &field);
field.max_length = test_fields[i].max_length;
field.autocomplete_attribute = std::string();
form.fields.push_back(field);
}
std::vector<FormData> forms(1, form);
FormsSeen(forms);
AutofillProfile* profile = new AutofillProfile;
profile->set_guid("00000000-0000-0000-0000-000000000104");
profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1800FLOWERS"));
personal_data_.ClearAutofillProfiles();
autofill_manager_->AddProfile(profile);
// The sublabels here are somewhat braindead until crbug.com/493247 is fixed.
// TODO(estade): fix the bug and fix this test.
const FormFieldData& phone_prefix = form.fields[2];
GetAutofillSuggestions(form, phone_prefix);
// Test that we sent the right prefix values to the external delegate.
external_delegate_->CheckSuggestions(kDefaultPageID,
Suggestion("356", "18003569377", "", 1));
const FormFieldData& phone_suffix = form.fields[3];
GetAutofillSuggestions(form, phone_suffix);
// Test that we sent the right suffix values to the external delegate.
external_delegate_->CheckSuggestions(
kDefaultPageID, Suggestion("9377", "18003569377", "", 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 = autofill_manager_->GetProfileWithGUID(guid);
ASSERT_TRUE(profile);
EXPECT_EQ(0U, profile->use_count());
EXPECT_EQ(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(1U, 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 (except on iOS).
EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field));
#if defined(OS_IOS)
EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field));
#else
EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
#endif // defined(OS_IOS)
// 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 (except on iOS).
number_field->value.clear();
#if defined(OS_IOS)
EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field));
#else
EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field));
#endif // defined(OS_IOS)
// When part of the section is Autofilled, only fill the initiating field.
month_field->is_autofilled = true;
EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field));
EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field));
}
// Test that we correctly fill a credit card form.
TEST_F(AutofillManagerTest, FillCreditCardForm) {
// 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, FillCreditCardFormStripCardNumberWhitespace) {
// Same as the SetUp(), but generate Elvis card with whitespace in credit
// card number.
personal_data_.CreateTestCreditCardWithWhitespace();
// 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, FillCreditCardFormStripCardNumberSeparators) {
// Same as the SetUp(), but generate Elvis card with separator characters in
// credit card number.
personal_data_.CreateTestCreditCardWithSeparators();
// 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.
// 1. year empty, month empty
TEST_F(AutofillManagerTest, FillCreditCardFormNoYearNoMonth) {
// Same as the SetUp(), but generate 4 credit cards with year month
// combination.
personal_data_.CreateTestCreditCardsYearAndMonth("", "");
// 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.
// 2. year empty, month non-empty
TEST_F(AutofillManagerTest, FillCreditCardFormNoYearMonth) {
// Same as the SetUp(), but generate 4 credit cards with year month
// combination.
personal_data_.CreateTestCreditCardsYearAndMonth("", "04");
// 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.
// 3. year non-empty, month empty
TEST_F(AutofillManagerTest, FillCreditCardFormYearNoMonth) {
// Same as the SetUp(), but generate 4 credit cards with year month
// combination.
personal_data_.CreateTestCreditCardsYearAndMonth("2012", "");
// 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, "2012", "");
}
// Test that we correctly fill a credit card form with month input type.
// 4. year non-empty, month empty
TEST_F(AutofillManagerTest, FillCreditCardFormYearMonth) {
// Same as the SetUp(), but generate 4 credit cards with year month
// combination.
personal_data_.ClearCreditCards();
personal_data_.CreateTestCreditCardsYearAndMonth("2012", "04");
// 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, "2012", "04");
}
// 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 non credit card related fields with the autocomplete attribute set
// to off are not filled on desktop.
TEST_F(AutofillManagerTest, FillAddressForm_AutocompleteOff) {
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 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 non-focusable field is ignored while inferring boundaries between
// sections: http://crbug.com/231160
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);
// The whole form 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_", "theking@gmail.com", "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 (size_t i = 0; i < kAddressFormSize; ++i) {
// Restore the expected field names.
base::string16 name = secondSection.fields[i].name;
base::string16 original_name = name.substr(0, name.size() - 1);
secondSection.fields[i].name = original_name;
}
ExpectFilledAddressFormElvis(response_page_id, secondSection, kPageID2,
false);
}
}
// Test that we correctly fill a form that has author-specified sections, which
// might not match our expected section breakdown.
TEST_F(AutofillManagerTest, FillFormWithAuthorSpecifiedSections) {
// Create a form with a billing section and an unnamed section, interleaved.
// The billing section includes both address and credit card 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("", "country", "", "text", &field);
field.autocomplete_attribute = "section-billing country";
form.fields.push_back(field);
test::CreateTestFormField("", "firstname", "", "text", &field);
field.autocomplete_attribute = "given-name";
form.fields.push_back(field);
test::CreateTestFormField("", "lastname", "", "text", &field);
field.autocomplete_attribute = "family-name";
form.fields.push_back(field);
test::CreateTestFormField("", "address", "", "text", &field);
field.autocomplete_attribute = "section-billing address-line1";
form.fields.push_back(field);
test::CreateTestFormField("", "city", "", "text", &field);
field.autocomplete_attribute = "section-billing locality";
form.fields.push_back(field);
test::CreateTestFormField("", "state", "", "text", &field);
field.autocomplete_attribute = "section-billing region";
form.fields.push_back(field);
test::CreateTestFormField("", "zip", "", "text", &field);
field.autocomplete_attribute = "section-billing postal-code";
form.fields.push_back(field);
test::CreateTestFormField("", "ccname", "", "text", &field);
field.autocomplete_attribute = "section-billing cc-name";
form.fields.push_back(field);
test::CreateTestFormField("", "ccnumber", "", "text", &field);
field.autocomplete_attribute = "section-billing cc-number";
form.fields.push_back(field);
test::CreateTestFormField("", "ccexp", "", "text", &field);
field.autocomplete_attribute = "section-billing cc-exp";
form.fields.push_back(field);
test::CreateTestFormField("", "email", "", "text", &field);
field.autocomplete_attribute = "email";
form.fields.push_back(field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Fill the unnamed section.
const char guid[] = "00000000-0000-0000-0000-000000000001";
int response_page_id = 0;
FormData response_data;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, form.fields[1],
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
{
SCOPED_TRACE("Unnamed section");
EXPECT_EQ(kDefaultPageID, response_page_id);
EXPECT_EQ(ASCIIToUTF16("MyForm"), response_data.name);
EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.origin);
EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action);
ASSERT_EQ(11U, response_data.fields.size());
ExpectFilledField("", "country", "", "text", response_data.fields[0]);
ExpectFilledField("", "firstname", "Elvis", "text",
response_data.fields[1]);
ExpectFilledField("", "lastname", "Presley", "text",
response_data.fields[2]);
ExpectFilledField("", "address", "", "text", response_data.fields[3]);
ExpectFilledField("", "city", "", "text", response_data.fields[4]);
ExpectFilledField("", "state", "", "text", response_data.fields[5]);
ExpectFilledField("", "zip", "", "text", response_data.fields[6]);
ExpectFilledField("", "ccname", "", "text", response_data.fields[7]);
ExpectFilledField("", "ccnumber", "", "text", response_data.fields[8]);
ExpectFilledField("", "ccexp", "", "text", response_data.fields[9]);
ExpectFilledField("", "email", "theking@gmail.com", "text",
response_data.fields[10]);
}
// Fill the address portion of the billing section.
const int kPageID2 = 2;
const char guid2[] = "00000000-0000-0000-0000-000000000001";
response_page_id = 0;
FillAutofillFormDataAndSaveResults(kPageID2, form, form.fields[0],
MakeFrontendID(std::string(), guid2),
&response_page_id, &response_data);
{
SCOPED_TRACE("Billing address");
EXPECT_EQ(kPageID2, response_page_id);
EXPECT_EQ(ASCIIToUTF16("MyForm"), response_data.name);
EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.origin);
EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action);
ASSERT_EQ(11U, response_data.fields.size());
ExpectFilledField("", "country", "US", "text",
response_data.fields[0]);
ExpectFilledField("", "firstname", "", "text", response_data.fields[1]);
ExpectFilledField("", "lastname", "", "text", response_data.fields[2]);
ExpectFilledField("", "address", "3734 Elvis Presley Blvd.", "text",
response_data.fields[3]);
ExpectFilledField("", "city", "Memphis", "text", response_data.fields[4]);
ExpectFilledField("", "state", "Tennessee", "text",
response_data.fields[5]);
ExpectFilledField("", "zip", "38116", "text", response_data.fields[6]);
ExpectFilledField("", "ccname", "", "text", response_data.fields[7]);
ExpectFilledField("", "ccnumber", "", "text", response_data.fields[8]);
ExpectFilledField("", "ccexp", "", "text", response_data.fields[9]);
ExpectFilledField("", "email", "", "text", response_data.fields[10]);
}
// Fill the credit card portion of the billing section.
const int kPageID3 = 3;
const char guid3[] = "00000000-0000-0000-0000-000000000004";
response_page_id = 0;
FillAutofillFormDataAndSaveResults(
kPageID3, form, form.fields[form.fields.size() - 2],
MakeFrontendID(guid3, std::string()), &response_page_id, &response_data);
{
SCOPED_TRACE("Credit card");
EXPECT_EQ(kPageID3, response_page_id);
EXPECT_EQ(ASCIIToUTF16("MyForm"), response_data.name);
EXPECT_EQ(GURL("https://myform.com/form.html"), response_data.origin);
EXPECT_EQ(GURL("https://myform.com/submit.html"), response_data.action);
ASSERT_EQ(11U, response_data.fields.size());
ExpectFilledField("", "country", "", "text", response_data.fields[0]);
ExpectFilledField("", "firstname", "", "text", response_data.fields[1]);
ExpectFilledField("", "lastname", "", "text", response_data.fields[2]);
ExpectFilledField("", "address", "", "text", response_data.fields[3]);
ExpectFilledField("", "city", "", "text", response_data.fields[4]);
ExpectFilledField("", "state", "", "text", response_data.fields[5]);
ExpectFilledField("", "zip", "", "text", response_data.fields[6]);
ExpectFilledField("", "ccname", "Elvis Presley", "text",
response_data.fields[7]);
ExpectFilledField("", "ccnumber", "4234567890123456", "text",
response_data.fields[8]);
ExpectFilledField("", "ccexp", "04/2012", "text", response_data.fields[9]);
ExpectFilledField("", "email", "", "text", response_data.fields[10]);
}
}
// Test that we correctly fill a form that has a single logical section with
// multiple email address fields.
TEST_F(AutofillManagerTest, FillFormWithMultipleEmails) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
FormFieldData field;
test::CreateTestFormField("Confirm email", "email2", "", "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);
// The second email address should be filled.
EXPECT_EQ(ASCIIToUTF16("theking@gmail.com"),
response_data.fields.back().value);
// The remainder of the form should be filled as usual.
response_data.fields.pop_back();
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
}
// Test that we correctly fill a previously auto-filled form.
TEST_F(AutofillManagerTest, FillAutofilledForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Mark one of the address fields as autofilled.
form.fields[4].is_autofilled = true;
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;
FillAutofillFormDataAndSaveResults(kDefaultPageID, form, *form.fields.begin(),
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
{
SCOPED_TRACE("Address");
ExpectFilledForm(response_page_id, response_data, kDefaultPageID, "Elvis",
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
true, true, false);
}
// 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 1");
ExpectFilledCreditCardFormElvis(
response_page_id, response_data, kPageID2, true);
}
// Now set the credit card fields to also be auto-filled, and try again to
// fill the credit card data
for (std::vector<FormFieldData>::iterator iter = form.fields.begin();
iter != form.fields.end();
++iter) {
iter->is_autofilled = true;
}
const int kPageID3 = 3;
response_page_id = 0;
FillAutofillFormDataAndSaveResults(
kPageID3, form, form.fields[form.fields.size() - 2],
MakeFrontendID(guid2, std::string()), &response_page_id, &response_data);
{
SCOPED_TRACE("Credit card 2");
ExpectFilledForm(response_page_id, response_data, kPageID3, "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "2012", true, true,
false);
}
}
// Test that we correctly fill a phone number split across multiple fields.
TEST_F(AutofillManagerTest, FillPhoneNumber) {
// In one form, rely on the maxlength attribute to imply phone number parts.
// In the other form, rely on the autocompletetype attribute.
FormData form_with_maxlength;
form_with_maxlength.name = ASCIIToUTF16("MyMaxlengthPhoneForm");
form_with_maxlength.origin = GURL("http://myform.com/phone_form.html");
form_with_maxlength.action = GURL("http://myform.com/phone_submit.html");
FormData form_with_autocompletetype = form_with_maxlength;
form_with_autocompletetype.name = ASCIIToUTF16("MyAutocompletetypePhoneForm");
struct {
const char* label;
const char* name;
size_t max_length;
const char* 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", 3, "tel-extension" }
};
FormFieldData field;
const size_t default_max_length = field.max_length;
for (size_t i = 0; i < arraysize(test_fields); ++i) {
test::CreateTestFormField(
test_fields[i].label, test_fields[i].name, "", "text", &field);
field.max_length = test_fields[i].max_length;
field.autocomplete_attribute = std::string();
form_with_maxlength.fields.push_back(field);
field.max_length = default_max_length;
field.autocomplete_attribute = test_fields[i].autocomplete_attribute;
form_with_autocompletetype.fields.push_back(field);
}
std::vector<FormData> forms;
forms.push_back(form_with_maxlength);
forms.push_back(form_with_autocompletetype);
FormsSeen(forms);
// We should be able to fill prefix and suffix fields for US numbers.
AutofillProfile* work_profile = autofill_manager_->GetProfileWithGUID(
"00000000-0000-0000-0000-000000000002");
ASSERT_TRUE(work_profile != NULL);
work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
ASCIIToUTF16("16505554567"));
std::string guid(work_profile->guid());
int page_id = 1;
int response_page_id = 0;
FormData response_data1;
FillAutofillFormDataAndSaveResults(
page_id, form_with_maxlength, *form_with_maxlength.fields.begin(),
MakeFrontendID(std::string(), guid), &response_page_id, &response_data1);
EXPECT_EQ(1, response_page_id);
ASSERT_EQ(5U, response_data1.fields.size());
EXPECT_EQ(ASCIIToUTF16("1"), response_data1.fields[0].value);
EXPECT_EQ(ASCIIToUTF16("650"), response_data1.fields[1].value);
EXPECT_EQ(ASCIIToUTF16("555"), response_data1.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("4567"), response_data1.fields[3].value);
EXPECT_EQ(base::string16(), response_data1.fields[4].value);
page_id = 2;
response_page_id = 0;
FormData response_data2;
FillAutofillFormDataAndSaveResults(page_id, form_with_autocompletetype,
*form_with_autocompletetype.fields.begin(),
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data2);
EXPECT_EQ(2, response_page_id);
ASSERT_EQ(5U, response_data2.fields.size());
EXPECT_EQ(ASCIIToUTF16("1"), response_data2.fields[0].value);
EXPECT_EQ(ASCIIToUTF16("650"), response_data2.fields[1].value);
EXPECT_EQ(ASCIIToUTF16("555"), response_data2.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("4567"), response_data2.fields[3].value);
EXPECT_EQ(base::string16(), response_data2.fields[4].value);
// We should not be able to fill prefix and suffix fields for international
// numbers.
work_profile->SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("GB"));
work_profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
ASCIIToUTF16("447700954321"));
page_id = 3;
response_page_id = 0;
FormData response_data3;
FillAutofillFormDataAndSaveResults(
page_id, form_with_maxlength, *form_with_maxlength.fields.begin(),
MakeFrontendID(std::string(), guid), &response_page_id, &response_data3);
EXPECT_EQ(3, response_page_id);
ASSERT_EQ(5U, response_data3.fields.size());
EXPECT_EQ(ASCIIToUTF16("44"), response_data3.fields[0].value);
EXPECT_EQ(ASCIIToUTF16("7700"), response_data3.fields[1].value);
EXPECT_EQ(ASCIIToUTF16("954321"), response_data3.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("954321"), response_data3.fields[3].value);
EXPECT_EQ(base::string16(), response_data3.fields[4].value);
page_id = 4;
response_page_id = 0;
FormData response_data4;
FillAutofillFormDataAndSaveResults(page_id, form_with_autocompletetype,
*form_with_autocompletetype.fields.begin(),
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data4);
EXPECT_EQ(4, response_page_id);
ASSERT_EQ(5U, response_data4.fields.size());
EXPECT_EQ(ASCIIToUTF16("44"), response_data4.fields[0].value);
EXPECT_EQ(ASCIIToUTF16("7700"), response_data4.fields[1].value);
EXPECT_EQ(ASCIIToUTF16("954321"), response_data4.fields[2].value);
EXPECT_EQ(ASCIIToUTF16("954321"), response_data4.fields[3].value);
EXPECT_EQ(base::string16(), response_data4.fields[4].value);
}
// Test that we can still fill a form when a field has been removed from it.
TEST_F(AutofillManagerTest, FormChangesRemoveField) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Add a field -- we'll remove it again later.
FormFieldData field;
test::CreateTestFormField("Some", "field", "", "text", &field);
form.fields.insert(form.fields.begin() + 3, field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Now, after the call to |FormsSeen|, we remove the field before filling.
form.fields.erase(form.fields.begin() + 3);
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);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
}
// Test that we can still fill a form when a field has been added to it.
TEST_F(AutofillManagerTest, FormChangesAddField) {
// The offset of the phone field in the address form.
const int kPhoneFieldOffset = 9;
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Remove the phone field -- we'll add it back later.
std::vector<FormFieldData>::iterator pos =
form.fields.begin() + kPhoneFieldOffset;
FormFieldData field = *pos;
pos = form.fields.erase(pos);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Now, after the call to |FormsSeen|, we restore the field before filling.
form.fields.insert(pos, field);
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);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
}
// Test that we are able to save form data when forms are submitted.
TEST_F(AutofillManagerTest, FormSubmitted) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
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);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
// Simulate form submission. We should call into the PDM to try to save the
// filled data.
FormSubmitted(response_data);
EXPECT_EQ(1, personal_data_.num_times_save_imported_profile_called());
}
// Test that we are not saving form data when only the WillSubmitForm event is
// sent.
TEST_F(AutofillManagerTest, FormWillSubmitDoesNotSaveData) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
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);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
// Simulate OnWillSubmitForm(). We should *not* be calling into the PDM at
// this point (since the form was not submitted). Does not call
// OnFormSubmitted.
autofill_manager_->ResetRunLoop();
autofill_manager_->OnWillSubmitForm(response_data, base::TimeTicks::Now());
autofill_manager_->WaitForAsyncOnWillSubmitForm();
EXPECT_EQ(0, personal_data_.num_times_save_imported_profile_called());
}
// Test that when Autocomplete is enabled and Autofill is disabled, form
// submissions are still received by AutocompleteHistoryManager.
TEST_F(AutofillManagerTest, FormSubmittedAutocompleteEnabled) {
TestAutofillClient client;
autofill_manager_.reset(
new TestAutofillManager(autofill_driver_.get(), &client, NULL));
autofill_manager_->set_autofill_enabled(false);
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(), &client));
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m, OnWillSubmitForm(_)).Times(1);
FormSubmitted(form);
}
// Test that when Autofill is disabled, Autocomplete suggestions are still
// queried.
TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillDisabled) {
TestAutofillClient client;
autofill_manager_.reset(
new TestAutofillManager(autofill_driver_.get(), &client, NULL));
autofill_manager_->set_autofill_enabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const FormFieldData& field = form.fields[0];
// Expect Autocomplete manager to be called for suggestions.
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(), &client));
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m,
OnGetAutocompleteSuggestions(_, _, _, _)).Times(1);
GetAutofillSuggestions(form, field);
}
// Test that when Autofill is disabled and the field should not autocomplete,
// autocomplete is not queried for suggestions.
TEST_F(AutofillManagerTest,
AutocompleteSuggestions_AutofillDisabledAndFieldShouldNotAutocomplete) {
TestAutofillClient client;
autofill_manager_.reset(
new TestAutofillManager(autofill_driver_.get(), &client, NULL));
autofill_manager_->set_autofill_enabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
field.should_autocomplete = false;
// Autocomplete manager is not called for suggestions.
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(), &client));
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m,
OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
GetAutofillSuggestions(form, field);
}
// Test that we do not query for Autocomplete suggestions when there are
// Autofill suggestions available.
TEST_F(AutofillManagerTest, AutocompleteSuggestions_NoneWhenAutofillPresent) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const FormFieldData& field = form.fields[0];
// Autocomplete manager is not called for suggestions.
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(),
autofill_manager_->client()));
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m,
OnGetAutocompleteSuggestions(_, _, _, _)).Times(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.
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("Charles", "123 Apple St.", "", 2));
}
// Test that we query for Autocomplete suggestions when there are no Autofill
// suggestions available.
TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillEmpty) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// No suggestions matching "donkey".
FormFieldData field;
test::CreateTestFormField("Email", "email", "donkey", "email", &field);
// Autocomplete manager is called for suggestions because Autofill is empty.
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(),
autofill_manager_->client()));
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m,
OnGetAutocompleteSuggestions(_, _, _, _)).Times(1);
GetAutofillSuggestions(form, field);
}
// Test that we do not query for Autocomplete suggestions when there are no
// Autofill suggestions available, and that the field should not autocomplete.
TEST_F(
AutofillManagerTest,
AutocompleteSuggestions_NoneWhenAutofillEmptyFieldShouldNotAutocomplete) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// No suggestions matching "donkey".
FormFieldData field;
field.should_autocomplete = false;
test::CreateTestFormField("Email", "email", "donkey", "email", &field);
// Autocomplete manager is not called for suggestions.
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(),
autofill_manager_->client()));
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m,
OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
GetAutofillSuggestions(form, field);
}
TEST_F(AutofillManagerTest, AutocompleteOffRespectedForAutocomplete) {
TestAutofillClient client;
autofill_manager_.reset(
new TestAutofillManager(autofill_driver_.get(), &client, NULL));
autofill_manager_->set_autofill_enabled(false);
autofill_manager_->SetExternalDelegate(external_delegate_.get());
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(), &client));
MockAutocompleteHistoryManager* m = static_cast<
MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*m,
OnGetAutocompleteSuggestions(_, _, _, _)).Times(0);
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData* field = &form.fields[0];
field->should_autocomplete = false;
GetAutofillSuggestions(form, *field);
}
// Test that OnLoadedServerPredictions can obtain the FormStructure with the
// signature of the queried form and apply type predictions.
TEST_F(AutofillManagerTest, OnLoadedServerPredictions) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes();
autofill_manager_->AddSeenForm(form_structure);
// Similarly, a second form.
FormData form2;
form2.name = ASCIIToUTF16("MyForm");
form2.origin = GURL("http://myform.com/form.html");
form2.action = GURL("http://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("Last Name", "lastname", "", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Middle Name", "middlename", "", "text", &field);
form2.fields.push_back(field);
test::CreateTestFormField("Postal Code", "zipcode", "", "text", &field);
form2.fields.push_back(field);
TestFormStructure* form_structure2 = new TestFormStructure(form2);
form_structure2->DetermineHeuristicTypes();
autofill_manager_->AddSeenForm(form_structure2);
std::string xml = "<autofillqueryresponse>"
"<field autofilltype=\"3\" />" // First test form.
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"3\" />"
"<field autofilltype=\"2\" />"
"<field autofilltype=\"61\"/>"
"<field autofilltype=\"5\" />" // Second form.
"<field autofilltype=\"4\" />"
"<field autofilltype=\"35\"/>"
"</autofillqueryresponse>";
std::vector<std::string> signatures;
signatures.push_back(form_structure->FormSignature());
signatures.push_back(form_structure2->FormSignature());
base::HistogramTester histogram_tester;
autofill_manager_->OnLoadedServerPredictions(xml, signatures);
// Verify that FormStructure::ParseQueryResponse was called (here and below).
histogram_tester.ExpectBucketCount("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_RESPONSE_RECEIVED,
1);
histogram_tester.ExpectBucketCount("Autofill.ServerQueryResponse",
AutofillMetrics::QUERY_RESPONSE_PARSED,
1);
// We expect the server type to have been applied to the first field of the
// first form.
EXPECT_EQ(NAME_FIRST, form_structure->field(0)->Type().GetStorableType());
// We expect the server types to have been applied to the second form.
EXPECT_EQ(NAME_LAST, form_structure2->field(0)->Type().GetStorableType());
EXPECT_EQ(NAME_MIDDLE, form_structure2->field(1)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_ZIP,
form_structure2->field(2)->Type().GetStorableType());
}
// Test that OnLoadedServerPredictions does not call ParseQueryResponse if the
// AutofillManager has been reset between the time the query was sent and the
// response received.
TEST_F(AutofillManagerTest, OnLoadedServerPredictions_ResetManager) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes();
autofill_manager_->AddSeenForm(form_structure);
std::string xml = "<autofillqueryresponse>"
"<field autofilltype=\"3\" />" // This is tested below.
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"0\" />"
"<field autofilltype=\"3\" />"
"<field autofilltype=\"2\" />"
"<field autofilltype=\"61\"/>"
"</autofillqueryresponse>";
std::vector<std::string> signatures;
signatures.push_back(form_structure->FormSignature());
// Reset the manager (such as during a navigation).
autofill_manager_->Reset();
base::HistogramTester histogram_tester;
autofill_manager_->OnLoadedServerPredictions(xml, signatures);
// Verify that FormStructure::ParseQueryResponse was NOT called.
histogram_tester.ExpectTotalCount("Autofill.ServerQueryResponse", 0);
}
// Test that we are able to save form data when forms are submitted and we only
// have server data for the field types.
TEST_F(AutofillManagerTest, FormSubmittedServerTypes) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Simulate having seen this form on page load.
// |form_structure| will be owned by |autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes();
// Clear the heuristic types, and instead set the appropriate server types.
std::vector<ServerFieldType> heuristic_types, server_types;
for (size_t i = 0; i < form.fields.size(); ++i) {
heuristic_types.push_back(UNKNOWN_TYPE);
server_types.push_back(form_structure->field(i)->heuristic_type());
}
form_structure->SetFieldTypes(heuristic_types, server_types);
autofill_manager_->AddSeenForm(form_structure);
// 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);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
// Simulate form submission. We should call into the PDM to try to save the
// filled data.
FormSubmitted(response_data);
EXPECT_EQ(1, personal_data_.num_times_save_imported_profile_called());
}
// Test that we are able to save form data after the possible types have been
// determined. We do two submissions and verify that only at the second
// submission are the possible types able to be inferred.
TEST_F(AutofillManagerTest, FormSubmittedPossibleTypesTwoSubmissions) {
// Set up our form data.
FormData form;
std::vector<ServerFieldTypeSet> expected_types;
test::CreateTestAddressFormData(&form, &expected_types);
// 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);
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
personal_data_.ClearAutofillProfiles();
ASSERT_EQ(0u, personal_data_.GetProfiles().size());
// Simulate form submission. The first submission should not count the data
// towards possible types. Therefore we expect all UNKNOWN_TYPE entries.
ServerFieldTypeSet type_set;
type_set.insert(UNKNOWN_TYPE);
std::vector<ServerFieldTypeSet> unknown_types(expected_types.size(),
type_set);
autofill_manager_->set_expected_submitted_field_types(unknown_types);
FormSubmitted(response_data);
ASSERT_EQ(1u, personal_data_.GetProfiles().size());
// The second submission should now have data by which to infer types.
autofill_manager_->set_expected_submitted_field_types(expected_types);
FormSubmitted(response_data);
ASSERT_EQ(2u, personal_data_.GetProfiles().size());
}
// Test that the form signature for an uploaded form always matches the form
// signature from the query.
TEST_F(AutofillManagerTest, FormSubmittedWithDifferentFields) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Cache the expected form signature.
std::string signature = FormStructure(form).FormSignature();
// Change the structure of the form prior to submission.
// Websites would typically invoke JavaScript either on page load or on form
// submit to achieve this.
form.fields.pop_back();
FormFieldData field = form.fields[3];
form.fields[3] = form.fields[7];
form.fields[7] = field;
// Simulate form submission.
FormSubmitted(form);
EXPECT_EQ(signature, autofill_manager_->GetSubmittedFormSignature());
}
// Test that we do not save form data when submitted fields contain default
// values.
TEST_F(AutofillManagerTest, FormSubmittedWithDefaultValues) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
form.fields[3].value = ASCIIToUTF16("Enter your address");
// Convert the state field to a <select> popup, to make sure that we only
// reject default values for text fields.
ASSERT_TRUE(form.fields[6].name == ASCIIToUTF16("state"));
form.fields[6].form_control_type = "select-one";
form.fields[6].value = ASCIIToUTF16("Tennessee");
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[3],
MakeFrontendID(std::string(), guid),
&response_page_id, &response_data);
// Simulate form submission. We should call into the PDM to try to save the
// filled data.
FormSubmitted(response_data);
EXPECT_EQ(1, personal_data_.num_times_save_imported_profile_called());
// Set the address field's value back to the default value.
response_data.fields[3].value = ASCIIToUTF16("Enter your address");
// Simulate form submission. We should not call into the PDM to try to save
// the filled data, since the filled form is effectively missing an address.
FormSubmitted(response_data);
EXPECT_EQ(1, personal_data_.num_times_save_imported_profile_called());
}
// Tests that credit card data are saved for forms on https
TEST_F(AutofillManagerTest, ImportFormDataCreditCardHTTPS) {
TestSaveCreditCards(true);
}
// Tests that credit card data are saved for forms on http
TEST_F(AutofillManagerTest, ImportFormDataCreditCardHTTP) {
TestSaveCreditCards(false);
}
// Tests that credit card data are saved when autocomplete=off for CC field.
TEST_F(AutofillManagerTest, CreditCardSavedWhenAutocompleteOff) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, false, false);
// Set "autocomplete=off" for cardnumber field.
form.fields[1].should_autocomplete = false;
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Edit the data, and submit
form.fields[1].value = ASCIIToUTF16("4111111111111111");
form.fields[2].value = ASCIIToUTF16("11");
form.fields[3].value = ASCIIToUTF16("2017");
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(1);
FormSubmitted(form);
}
// Tests that credit card data are not saved when CC number does not pass the
// Luhn test.
TEST_F(AutofillManagerTest, InvalidCreditCardNumberIsNotSaved) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Edit the data, and submit.
std::string card("4408041234567890");
ASSERT_FALSE(autofill::IsValidCreditCardNumber(ASCIIToUTF16(card)));
form.fields[1].value = ASCIIToUTF16(card);
form.fields[2].value = ASCIIToUTF16("11");
form.fields[3].value = ASCIIToUTF16("2017");
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(0);
FormSubmitted(form);
}
TEST_F(AutofillManagerTest, DeterminePossibleFieldTypesForUpload) {
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("http://myform.com/form.html");
form.action = GURL("http://myform.com/submit.html");
std::vector<ServerFieldTypeSet> expected_types;
std::vector<base::string16> expected_values;
// These fields should all match.
FormFieldData field;
ServerFieldTypeSet types;
test::CreateTestFormField("", "1", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Elvis"));
types.clear();
types.insert(NAME_FIRST);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "2", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Aaron"));
types.clear();
types.insert(NAME_MIDDLE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "3", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("A"));
types.clear();
types.insert(NAME_MIDDLE_INITIAL);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "4", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Presley"));
types.clear();
types.insert(NAME_LAST);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "5", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Elvis Presley"));
types.clear();
types.insert(CREDIT_CARD_NAME);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "6", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Elvis Aaron Presley"));
types.clear();
types.insert(NAME_FULL);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "7", "", "email", &field);
expected_values.push_back(ASCIIToUTF16("theking@gmail.com"));
types.clear();
types.insert(EMAIL_ADDRESS);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "8", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("RCA"));
types.clear();
types.insert(COMPANY_NAME);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "9", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("3734 Elvis Presley Blvd."));
types.clear();
types.insert(ADDRESS_HOME_LINE1);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "10", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Apt. 10"));
types.clear();
types.insert(ADDRESS_HOME_LINE2);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "11", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Memphis"));
types.clear();
types.insert(ADDRESS_HOME_CITY);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "12", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Tennessee"));
types.clear();
types.insert(ADDRESS_HOME_STATE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "13", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("38116"));
types.clear();
types.insert(ADDRESS_HOME_ZIP);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "14", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("USA"));
types.clear();
types.insert(ADDRESS_HOME_COUNTRY);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "15", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("United States"));
types.clear();
types.insert(ADDRESS_HOME_COUNTRY);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "16", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("+1 (234) 567-8901"));
types.clear();
types.insert(PHONE_HOME_WHOLE_NUMBER);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "17", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("2345678901"));
types.clear();
types.insert(PHONE_HOME_CITY_AND_NUMBER);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "18", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("1"));
types.clear();
types.insert(PHONE_HOME_COUNTRY_CODE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "19", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("234"));
types.clear();
types.insert(PHONE_HOME_CITY_CODE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "20", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("5678901"));
types.clear();
types.insert(PHONE_HOME_NUMBER);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "21", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("567"));
types.clear();
types.insert(PHONE_HOME_NUMBER);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "22", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("8901"));
types.clear();
types.insert(PHONE_HOME_NUMBER);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "23", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("4234-5678-9012-3456"));
types.clear();
types.insert(CREDIT_CARD_NUMBER);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "24", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("04"));
types.clear();
types.insert(CREDIT_CARD_EXP_MONTH);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "25", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("April"));
types.clear();
types.insert(CREDIT_CARD_EXP_MONTH);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "26", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("2012"));
types.clear();
types.insert(CREDIT_CARD_EXP_4_DIGIT_YEAR);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "27", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("12"));
types.clear();
types.insert(CREDIT_CARD_EXP_2_DIGIT_YEAR);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "28", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("04/2012"));
types.clear();
types.insert(CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR);
form.fields.push_back(field);
expected_types.push_back(types);
// Make sure that we trim whitespace properly.
test::CreateTestFormField("", "29", "", "text", &field);
expected_values.push_back(ASCIIToUTF16(""));
types.clear();
types.insert(EMPTY_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "30", " ", "text", &field);
expected_values.push_back(ASCIIToUTF16(" "));
types.clear();
types.insert(EMPTY_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "31", " ", "text", &field);
expected_values.push_back(ASCIIToUTF16(" Elvis"));
types.clear();
types.insert(NAME_FIRST);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "32", " ", "text", &field);
expected_values.push_back(ASCIIToUTF16("Elvis "));
types.clear();
types.insert(NAME_FIRST);
form.fields.push_back(field);
expected_types.push_back(types);
// These fields should not match, as they differ by case.
test::CreateTestFormField("", "33", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("elvis"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "34", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("3734 Elvis Presley BLVD"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
// These fields should not match, as they are unsupported variants.
test::CreateTestFormField("", "35", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Elvis Aaron"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "36", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("Mr. Presley"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "37", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("3734 Elvis Presley"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "38", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("TN"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "39", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("38116-1023"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "20", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("5"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "20", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("56"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
test::CreateTestFormField("", "20", "", "text", &field);
expected_values.push_back(ASCIIToUTF16("901"));
types.clear();
types.insert(UNKNOWN_TYPE);
form.fields.push_back(field);
expected_types.push_back(types);
// Make sure the form is in the cache so that it is processed for Autofill
// upload.
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Once the form is cached, fill the values.
EXPECT_EQ(form.fields.size(), expected_values.size());
for (size_t i = 0; i < expected_values.size(); i++) {
form.fields[i].value = expected_values[i];
}
autofill_manager_->set_expected_submitted_field_types(expected_types);
FormSubmitted(form);
}
TEST_F(AutofillManagerTest, RemoveProfile) {
// Add and remove an Autofill profile.
AutofillProfile* profile = new AutofillProfile;
const char guid[] = "00000000-0000-0000-0000-000000000102";
profile->set_guid(guid);
autofill_manager_->AddProfile(profile);
int id = MakeFrontendID(std::string(), guid);
autofill_manager_->RemoveAutofillProfileOrCreditCard(id);
EXPECT_FALSE(autofill_manager_->GetProfileWithGUID(guid));
}
TEST_F(AutofillManagerTest, RemoveCreditCard) {
// Add and remove an Autofill credit card.
CreditCard* credit_card = new CreditCard;
const char guid[] = "00000000-0000-0000-0000-000000100007";
credit_card->set_guid(guid);
autofill_manager_->AddCreditCard(credit_card);
int id = MakeFrontendID(guid, std::string());
autofill_manager_->RemoveAutofillProfileOrCreditCard(id);
EXPECT_FALSE(autofill_manager_->GetCreditCardWithGUID(guid));
}
// Test our external delegate is called at the right time.
TEST_F(AutofillManagerTest, TestExternalDelegate) {
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field); // should call the delegate's OnQuery()
EXPECT_TRUE(external_delegate_->on_query_seen());
}
// Test to verify suggestions appears for forms having credit card number split
// across fields.
TEST_F(AutofillManagerTest, GetCreditCardSuggestionsForNumberSpitAcrossFields) {
// Set up our form data with credit card number split across fields.
FormData form;
form.name = ASCIIToUTF16("MyForm");
form.origin = GURL("https://myform.com/form.html");
form.action = GURL("https://myform.com/submit.html");
FormFieldData name_field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text",
&name_field);
form.fields.push_back(name_field);
// Add new 4 |card_number_field|s to the |form|.
FormFieldData card_number_field;
card_number_field.max_length = 4;
test::CreateTestFormField("Card Number", "cardnumber_1", "", "text",
&card_number_field);
form.fields.push_back(card_number_field);
test::CreateTestFormField("", "cardnumber_2", "", "text", &card_number_field);
form.fields.push_back(card_number_field);
test::CreateTestFormField("", "cardnumber_3", "", "text", &card_number_field);
form.fields.push_back(card_number_field);
test::CreateTestFormField("", "cardnumber_4", "", "text", &card_number_field);
form.fields.push_back(card_number_field);
FormFieldData exp_field;
test::CreateTestFormField("Expiration Date", "ccmonth", "", "text",
&exp_field);
form.fields.push_back(exp_field);
test::CreateTestFormField("", "ccyear", "", "text", &exp_field);
form.fields.push_back(exp_field);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
// Verify whether suggestions are populated correctly for one of the middle
// credit card number fields when filled partially.
FormFieldData number_field = form.fields[3];
number_field.value = ASCIIToUTF16("901");
// Get the suggestions for already filled credit card |number_field|.
GetAutofillSuggestions(form, number_field);
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion(
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456",
"04/12", kVisaCard, autofill_manager_->GetPackedCreditCardID(4)));
}
// Test that inputs detected to be CVC inputs are forced to
// !should_autocomplete for AutocompleteHistoryManager::OnWillSubmitForm.
TEST_F(AutofillManagerTest, DontSaveCvcInAutocompleteHistory) {
autofill_manager_->autocomplete_history_manager_.reset(
new MockAutocompleteHistoryManager(autofill_driver_.get(),
&autofill_client_));
FormData form_seen_by_ahm;
MockAutocompleteHistoryManager* mock_ahm =
static_cast<MockAutocompleteHistoryManager*>(
autofill_manager_->autocomplete_history_manager_.get());
EXPECT_CALL(*mock_ahm, OnWillSubmitForm(_))
.WillOnce(SaveArg<0>(&form_seen_by_ahm));
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* label;
const char* name;
const char* value;
ServerFieldType expected_field_type;
} fields[] = {
{"Card number", "1", "4234-5678-9012-3456", CREDIT_CARD_NUMBER},
{"Card verification code", "2", "123", CREDIT_CARD_VERIFICATION_CODE},
{"expiration date", "3", "04/2020", CREDIT_CARD_EXP_4_DIGIT_YEAR},
};
for (size_t i = 0; i < arraysize(fields); ++i) {
FormFieldData field;
test::CreateTestFormField(fields[i].label, fields[i].name, fields[i].value,
"text", &field);
form.fields.push_back(field);
}
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormSubmitted(form);
EXPECT_EQ(form.fields.size(), form_seen_by_ahm.fields.size());
ASSERT_EQ(arraysize(fields), form_seen_by_ahm.fields.size());
for (size_t i = 0; i < arraysize(fields); ++i) {
EXPECT_EQ(form_seen_by_ahm.fields[i].should_autocomplete,
fields[i].expected_field_type != CREDIT_CARD_VERIFICATION_CODE);
}
}
TEST_F(AutofillManagerTest, DontOfferToSavePaymentsCard) {
FormData form;
CreditCard card;
PrepareForRealPanResponse(&form, &card);
// Manually fill out |form| so we can use it in OnFormSubmitted.
for (size_t i = 0; i < form.fields.size(); ++i) {
if (form.fields[i].name == ASCIIToUTF16("cardnumber"))
form.fields[i].value = ASCIIToUTF16("4012888888881881");
else if (form.fields[i].name == ASCIIToUTF16("nameoncard"))
form.fields[i].value = ASCIIToUTF16("John H Dillinger");
else if (form.fields[i].name == ASCIIToUTF16("ccmonth"))
form.fields[i].value = ASCIIToUTF16("01");
else if (form.fields[i].name == ASCIIToUTF16("ccyear"))
form.fields[i].value = ASCIIToUTF16("2017");
}
AutofillManager::UnmaskResponse response;
response.should_store_pan = false;
response.cvc = ASCIIToUTF16("123");
autofill_manager_->OnUnmaskResponse(response);
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"4012888888881881");
autofill_manager_->OnFormSubmitted(form);
// The rest of this test is a regression test for http://crbug.com/483602.
// The goal is not to crash.
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _));
for (size_t i = 0; i < form.fields.size(); ++i) {
form.fields[i].value.clear();
}
autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, form,
form.fields[1], card);
autofill_manager_->OnUnmaskResponse(response);
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"4012888888881881");
form = FormData();
test::CreateTestAddressFormData(&form);
FormsSeen(std::vector<FormData>(1, form));
ManuallyFillAddressForm(&form);
autofill_manager_->OnFormSubmitted(form);
}
TEST_F(AutofillManagerTest, FillInUpdatedExpirationDate) {
FormData form;
CreditCard card;
PrepareForRealPanResponse(&form, &card);
AutofillManager::UnmaskResponse response;
response.should_store_pan = false;
response.cvc = ASCIIToUTF16("123");
response.exp_month = ASCIIToUTF16("02");
response.exp_year = ASCIIToUTF16("2018");
autofill_manager_->OnUnmaskResponse(response);
autofill_manager_->OnDidGetRealPan(AutofillClient::SUCCESS,
"4012888888881881");
EXPECT_EQ(ASCIIToUTF16("02"),
autofill_manager_->unmask_request_.card.GetRawInfo(
CREDIT_CARD_EXP_MONTH));
EXPECT_EQ(ASCIIToUTF16("2018"),
autofill_manager_->unmask_request_.card.GetRawInfo(
CREDIT_CARD_EXP_4_DIGIT_YEAR));
}
TEST_F(AutofillManagerTest, UploadCreditCard) {
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
FormsSeen(std::vector<FormData>(1, address_form));
ManuallyFillAddressForm(&address_form);
FormSubmitted(address_form);
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
// Edit the data, and submit
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("11");
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
FormSubmitted(credit_card_form);
EXPECT_TRUE(autofill_manager_->credit_card_was_uploaded());
}
TEST_F(AutofillManagerTest, DontUploadCreditCardIfFeatureNotEnabled) {
autofill_manager_->set_credit_card_upload_enabled(false);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
FormsSeen(std::vector<FormData>(1, address_form));
ManuallyFillAddressForm(&address_form);
FormSubmitted(address_form);
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
// Edit the data, and submit
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("11");
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// The save prompt should be shown instead of doing an upload.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(1);
FormSubmitted(credit_card_form);
EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
}
TEST_F(AutofillManagerTest, DontUploadCreditCardIfCvcUnavailable) {
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
FormsSeen(std::vector<FormData>(1, address_form));
ManuallyFillAddressForm(&address_form);
FormSubmitted(address_form);
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
// Edit the data, and submit
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("11");
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16(""); // CVC MISSING
// The save prompt should be shown instead of doing an upload.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(1);
FormSubmitted(credit_card_form);
EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
}
TEST_F(AutofillManagerTest, DontUploadCreditCardIfNoMatchingProfileAvailable) {
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
FormsSeen(std::vector<FormData>(1, address_form));
ManuallyFillAddressForm(&address_form);
FormSubmitted(address_form);
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
// Edit the data, and submit
// The address form has "Flo Master" but the credit card has "Bob Master".
credit_card_form.fields[0].value = ASCIIToUTF16("Bob Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("11");
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// The save prompt should be shown instead of doing an upload.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(1);
FormSubmitted(credit_card_form);
EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
}
TEST_F(AutofillManagerTest, DontUploadCreditCardIfUploadDetailsFails) {
// Anything other than "en-US" will cause GetUploadDetails to return a failure
// response.
autofill_manager_->set_app_locale("pt-BR");
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
FormData address_form;
test::CreateTestAddressFormData(&address_form);
FormsSeen(std::vector<FormData>(1, address_form));
ManuallyFillAddressForm(&address_form);
FormSubmitted(address_form);
// Set up our credit card form data.
FormData credit_card_form;
CreateTestCreditCardFormData(&credit_card_form, true, false);
FormsSeen(std::vector<FormData>(1, credit_card_form));
// Edit the data, and submit
credit_card_form.fields[0].value = ASCIIToUTF16("Flo Master");
credit_card_form.fields[1].value = ASCIIToUTF16("4111111111111111");
credit_card_form.fields[2].value = ASCIIToUTF16("11");
credit_card_form.fields[3].value = ASCIIToUTF16("2017");
credit_card_form.fields[4].value = ASCIIToUTF16("123");
// The save prompt should be shown instead of doing an upload.
EXPECT_CALL(autofill_client_, ConfirmSaveCreditCardLocally(_)).Times(1);
FormSubmitted(credit_card_form);
EXPECT_FALSE(autofill_manager_->credit_card_was_uploaded());
}
// Verify that typing "gmail" will match "theking@gmail.com" and
// "buddy@gmail.com" when substring matching is enabled.
TEST_F(AutofillManagerTest, DisplaySuggestionsWithMatchingTokens) {
// Token matching is currently behind a flag.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSuggestionsWithSubstringMatch);
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Email", "email", "gmail", "email", &field);
GetAutofillSuggestions(form, field);
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("theking@gmail.com", "3734 Elvis Presley Blvd.", "", 1),
Suggestion("buddy@gmail.com", "123 Apple St.", "", 2));
}
// Verify that typing "apple" will match "123 Apple St." when substring matching
// is enabled.
TEST_F(AutofillManagerTest, DisplaySuggestionsWithMatchingTokens_CaseIgnored) {
// Token matching is currently behind a flag.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSuggestionsWithSubstringMatch);
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Address Line 2", "addr2", "apple", "text", &field);
GetAutofillSuggestions(form, field);
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("123 Apple St., unit 6", "123 Apple St.", "", 1));
}
// Verify that typing "mail" will not match any of the "@gmail.com" email
// addresses when substring matching is enabled.
TEST_F(AutofillManagerTest, NoSuggestionForNonPrefixTokenMatch) {
// Token matching is currently behind a flag.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSuggestionsWithSubstringMatch);
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Email", "email", "mail", "email", &field);
GetAutofillSuggestions(form, field);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Verify that typing "pres" will match "Elvis Presley" when substring matching
// is enabled.
TEST_F(AutofillManagerTest, DisplayCreditCardSuggestionsWithMatchingTokens) {
// Token matching is currently behind a flag.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSuggestionsWithSubstringMatch);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "pres", "text",
&field);
GetAutofillSuggestions(form, field);
#if defined(OS_ANDROID)
static const char* kVisaSuggestion =
"Visa\xC2\xA0\xE2\x8B\xAF"
"3456";
#else
static const char* kVisaSuggestion = "*3456";
#endif
external_delegate_->CheckSuggestions(
kDefaultPageID, Suggestion("Elvis Presley", kVisaSuggestion, kVisaCard,
autofill_manager_->GetPackedCreditCardID(4)));
}
// Verify that typing "lvis" will not match any of the credit card name when
// substring matching is enabled.
TEST_F(AutofillManagerTest, NoCreditCardSuggestionsForNonPrefixTokenMatch) {
// Token matching is currently behind a flag.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSuggestionsWithSubstringMatch);
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "lvis", "text",
&field);
GetAutofillSuggestions(form, field);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
// Verify that typing "S" into the middle name field will match and order middle
// names "Shawn Smith" followed by "Adam Smith" i.e. prefix matched followed by
// substring matched.
TEST_F(AutofillManagerTest,
DisplaySuggestionsWithPrefixesPrecedeSubstringMatched) {
// Token matching is currently behind a flag.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableSuggestionsWithSubstringMatch);
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
AutofillProfile* profile1 = new AutofillProfile;
profile1->set_guid("00000000-0000-0000-0000-000000000103");
profile1->SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Robin"), "en-US");
profile1->SetInfo(AutofillType(NAME_MIDDLE), ASCIIToUTF16("Adam Smith"),
"en-US");
profile1->SetInfo(AutofillType(NAME_LAST), ASCIIToUTF16("Grimes"), "en-US");
profile1->SetInfo(AutofillType(ADDRESS_HOME_LINE1),
ASCIIToUTF16("1234 Smith Blvd."), "en-US");
autofill_manager_->AddProfile(profile1);
AutofillProfile* profile2 = new AutofillProfile;
profile2->set_guid("00000000-0000-0000-0000-000000000124");
profile2->SetInfo(AutofillType(NAME_FIRST), ASCIIToUTF16("Carl"), "en-US");
profile2->SetInfo(AutofillType(NAME_MIDDLE), ASCIIToUTF16("Shawn Smith"),
"en-US");
profile2->SetInfo(AutofillType(NAME_LAST), ASCIIToUTF16("Grimes"), "en-US");
profile2->SetInfo(AutofillType(ADDRESS_HOME_LINE1),
ASCIIToUTF16("1234 Smith Blvd."), "en-US");
autofill_manager_->AddProfile(profile2);
FormFieldData field;
test::CreateTestFormField("Middle Name", "middlename", "S", "text", &field);
GetAutofillSuggestions(form, field);
external_delegate_->CheckSuggestions(
kDefaultPageID,
Suggestion("Shawn Smith", "1234 Smith Blvd., Robin Adam Smith Grimes", "",
1),
Suggestion("Adam Smith", "1234 Smith Blvd., Carl Shawn Smith Grimes", "",
2));
}
TEST_F(AutofillManagerTest, ShouldUploadForm) {
FormData form;
form.name = ASCIIToUTF16("TestForm");
form.origin = GURL("http://example.com/form.html");
form.action = GURL("http://example.com/submit.html");
FormFieldData field;
test::CreateTestFormField("Name", "name", "", "text", &field);
form.fields.push_back(field);
test::CreateTestFormField("Email", "email", "", "text", &field);
form.fields.push_back(field);
FormStructure form_structure(form);
// Has less than 3 fields.
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(form_structure));
// Has less than 3 fields but has autocomplete attribute.
form.fields[0].autocomplete_attribute = "given-name";
FormStructure form_structure_2(form);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(form_structure_2));
// Has more than 3 fields, no autocomplete attribute.
form.fields[0].autocomplete_attribute = "";
test::CreateTestFormField("Country", "country", "", "text", &field);
form.fields.push_back(field);
FormStructure form_structure_3(form);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(form_structure_3));
// Has more than 3 fields and at least one autocomplete attribute.
form.fields[0].autocomplete_attribute = "given-name";
FormStructure form_structure_4(form);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(form_structure_4));
// Is off the record.
autofill_driver_->SetIsOffTheRecord(true);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(form_structure_4));
// Make sure it's reset for the next test case.
autofill_driver_->SetIsOffTheRecord(false);
EXPECT_TRUE(autofill_manager_->ShouldUploadForm(form_structure_4));
// Autofill disabled.
autofill_manager_->set_autofill_enabled(false);
EXPECT_FALSE(autofill_manager_->ShouldUploadForm(form_structure_3));
}
// Verify that no suggestions are shown on desktop for non credit card related
// fields if the initiating field has the "autocomplete" attribute set to off.
TEST_F(AutofillManagerTest, DisplaySuggestions_AutocompleteOff_AddressField) {
// Set up an address form.
FormData mixed_form;
mixed_form.name = ASCIIToUTF16("MyForm");
mixed_form.origin = GURL("https://myform.com/form.html");
mixed_form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("First name", "firstname", "", "text", &field);
field.should_autocomplete = false;
mixed_form.fields.push_back(field);
test::CreateTestFormField("Last name", "lastname", "", "text", &field);
field.should_autocomplete = true;
mixed_form.fields.push_back(field);
test::CreateTestFormField("Address", "address", "", "text", &field);
field.should_autocomplete = true;
mixed_form.fields.push_back(field);
std::vector<FormData> mixed_forms(1, mixed_form);
FormsSeen(mixed_forms);
// Suggestions should not be displayed on desktop for this field.
GetAutofillSuggestions(mixed_form, mixed_form.fields[0]);
if (IsDesktopPlatform()) {
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
} else {
EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
}
// Suggestions should always be displayed for all the other fields.
for (size_t i = 1U; i < mixed_form.fields.size(); ++i) {
GetAutofillSuggestions(mixed_form, mixed_form.fields[i]);
EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
}
}
// Verify that suggestions are shown on desktop for credit card related fields
// even if the initiating field field has the "autocomplete" attribute set to
// off.
TEST_F(AutofillManagerTest,
DisplaySuggestions_AutocompleteOff_CreditCardField) {
// Set up a credit card form.
FormData mixed_form;
mixed_form.name = ASCIIToUTF16("MyForm");
mixed_form.origin = GURL("https://myform.com/form.html");
mixed_form.action = GURL("https://myform.com/submit.html");
FormFieldData field;
test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
field.should_autocomplete = false;
mixed_form.fields.push_back(field);
test::CreateTestFormField("Card Number", "cardnumber", "", "text", &field);
field.should_autocomplete = true;
mixed_form.fields.push_back(field);
test::CreateTestFormField("Expiration Month", "ccexpiresmonth", "", "text",
&field);
field.should_autocomplete = false;
mixed_form.fields.push_back(field);
mixed_form.fields.push_back(field);
std::vector<FormData> mixed_forms(1, mixed_form);
FormsSeen(mixed_forms);
// Suggestions should always be displayed.
for (const FormFieldData& field : mixed_form.fields) {
GetAutofillSuggestions(mixed_form, field);
EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
}
}
} // namespace autofill