blob: df9c8152d498355a334c3daf89fdcea11faf0c05 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <utility>
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/common/test_autofill_types.mojom.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/password_generation_util.h"
#include "components/autofill/core/common/signatures_util.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
const std::vector<const char*> kOptions = {"Option1", "Option2", "Option3",
"Option4"};
namespace {
void CreateTestFieldDataPredictions(const std::string& signature,
FormFieldDataPredictions* field_predict) {
test::CreateTestSelectField("TestLabel", "TestName", "TestValue", kOptions,
kOptions, 4, &field_predict->field);
field_predict->signature = signature;
field_predict->heuristic_type = "TestSignature";
field_predict->server_type = "TestServerType";
field_predict->overall_type = "TestOverallType";
field_predict->parseable_name = "TestParseableName";
field_predict->section = "TestSection";
}
void CreateTestPasswordFormFillData(PasswordFormFillData* fill_data) {
fill_data->form_renderer_id = 1234;
fill_data->origin = GURL("https://foo.com/");
fill_data->action = GURL("https://foo.com/login");
test::CreateTestSelectField("TestUsernameFieldLabel", "TestUsernameFieldName",
"TestUsernameFieldValue", kOptions, kOptions, 4,
&fill_data->username_field);
test::CreateTestSelectField("TestPasswordFieldLabel", "TestPasswordFieldName",
"TestPasswordFieldValue", kOptions, kOptions, 4,
&fill_data->password_field);
fill_data->preferred_realm = "https://foo.com/";
base::string16 name;
PasswordAndRealm pr;
name = base::ASCIIToUTF16("Tom");
pr.password = base::ASCIIToUTF16("Tom_Password");
pr.realm = "https://foo.com/";
fill_data->additional_logins[name] = pr;
name = base::ASCIIToUTF16("Jerry");
pr.password = base::ASCIIToUTF16("Jerry_Password");
pr.realm = "https://bar.com/";
fill_data->additional_logins[name] = pr;
fill_data->wait_for_username = true;
}
void CreateTestPasswordForm(PasswordForm* form) {
form->scheme = PasswordForm::Scheme::SCHEME_HTML;
form->signon_realm = "https://foo.com/";
form->origin = GURL("https://foo.com/");
form->action = GURL("https://foo.com/login");
form->affiliated_web_realm = "https://foo.com/";
form->submit_element = base::ASCIIToUTF16("test_submit");
form->username_element = base::ASCIIToUTF16("username");
form->username_marked_by_site = true;
form->username_value = base::ASCIIToUTF16("test@gmail.com");
form->other_possible_usernames.push_back(ValueElementPair(
base::ASCIIToUTF16("Jerry_1"), base::ASCIIToUTF16("id1")));
form->other_possible_usernames.push_back(ValueElementPair(
base::ASCIIToUTF16("Jerry_2"), base::ASCIIToUTF16("id2")));
form->all_possible_passwords.push_back(
ValueElementPair(base::ASCIIToUTF16("pass1"), base::ASCIIToUTF16("el1")));
form->all_possible_passwords.push_back(
ValueElementPair(base::ASCIIToUTF16("pass2"), base::ASCIIToUTF16("el2")));
form->form_has_autofilled_value = true;
form->password_element = base::ASCIIToUTF16("password");
form->password_value = base::ASCIIToUTF16("test");
form->new_password_element = base::ASCIIToUTF16("new_password");
form->new_password_value = base::ASCIIToUTF16("new_password_value");
form->new_password_marked_by_site = false;
form->new_password_element = base::ASCIIToUTF16("confirmation_password");
form->preferred = false;
form->date_created = base::Time::Now();
form->date_synced = base::Time::Now();
form->blacklisted_by_user = false;
form->type = PasswordForm::Type::TYPE_GENERATED;
form->times_used = 999;
test::CreateTestAddressFormData(&form->form_data);
form->generation_upload_status =
PasswordForm::GenerationUploadStatus::POSITIVE_SIGNAL_SENT;
form->display_name = base::ASCIIToUTF16("test display name");
form->icon_url = GURL("https://foo.com/icon.png");
form->federation_origin = url::Origin::Create(GURL("http://wwww.google.com"));
form->skip_zero_click = false;
form->was_parsed_using_autofill_predictions = false;
form->is_public_suffix_match = true;
form->is_affiliation_based_match = true;
form->submission_event = SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
}
void CreateTestFormsPredictionsMap(FormsPredictionsMap* predictions) {
FormsPredictionsMap& result_map = *predictions;
// 1st element.
FormData form_data;
test::CreateTestAddressFormData(&form_data);
ASSERT_TRUE(form_data.fields.size() >= 4);
result_map[form_data][form_data.fields[0]] =
PasswordFormFieldPredictionType::PREDICTION_USERNAME;
result_map[form_data][form_data.fields[1]] =
PasswordFormFieldPredictionType::PREDICTION_CURRENT_PASSWORD;
result_map[form_data][form_data.fields[2]] =
PasswordFormFieldPredictionType::PREDICTION_NEW_PASSWORD;
result_map[form_data][form_data.fields[3]] =
PasswordFormFieldPredictionType::PREDICTION_NOT_PASSWORD;
// 2nd element.
form_data.fields.clear();
result_map[form_data] =
std::map<FormFieldData, PasswordFormFieldPredictionType>();
// 3rd element.
FormFieldData field_data;
test::CreateTestSelectField("TestLabel1", "TestName1", "TestValue1", kOptions,
kOptions, 4, &field_data);
form_data.fields.push_back(field_data);
test::CreateTestSelectField("TestLabel2", "TestName2", "TestValue2", kOptions,
kOptions, 4, &field_data);
form_data.fields.push_back(field_data);
result_map[form_data][form_data.fields[0]] =
PasswordFormFieldPredictionType::PREDICTION_NEW_PASSWORD;
result_map[form_data][form_data.fields[1]] =
PasswordFormFieldPredictionType::PREDICTION_CURRENT_PASSWORD;
}
void CreatePasswordGenerationUIData(
password_generation::PasswordGenerationUIData* data) {
data->bounds = gfx::RectF(1, 1, 200, 100);
data->max_length = 20;
data->generation_element = base::ASCIIToUTF16("generation_element");
data->text_direction = base::i18n::RIGHT_TO_LEFT;
CreateTestPasswordForm(&data->password_form);
}
void CheckEqualPasswordFormFillData(const PasswordFormFillData& expected,
const PasswordFormFillData& actual) {
EXPECT_EQ(expected.form_renderer_id, actual.form_renderer_id);
EXPECT_EQ(expected.origin, actual.origin);
EXPECT_EQ(expected.action, actual.action);
EXPECT_EQ(expected.username_field, actual.username_field);
EXPECT_EQ(expected.password_field, actual.password_field);
EXPECT_EQ(expected.preferred_realm, actual.preferred_realm);
{
EXPECT_EQ(expected.additional_logins.size(),
actual.additional_logins.size());
auto iter1 = expected.additional_logins.begin();
auto end1 = expected.additional_logins.end();
auto iter2 = actual.additional_logins.begin();
auto end2 = actual.additional_logins.end();
for (; iter1 != end1 && iter2 != end2; ++iter1, ++iter2) {
EXPECT_EQ(iter1->first, iter2->first);
EXPECT_EQ(iter1->second.password, iter2->second.password);
EXPECT_EQ(iter1->second.realm, iter2->second.realm);
}
ASSERT_EQ(iter1, end1);
ASSERT_EQ(iter2, end2);
}
EXPECT_EQ(expected.wait_for_username, actual.wait_for_username);
}
void CheckEqualPasswordFormGenerationData(
const PasswordFormGenerationData& expected,
const PasswordFormGenerationData& actual) {
EXPECT_EQ(expected.form_signature, actual.form_signature);
EXPECT_EQ(expected.field_signature, actual.field_signature);
ASSERT_EQ(expected.confirmation_field_signature.has_value(),
actual.confirmation_field_signature.has_value());
EXPECT_EQ(expected.confirmation_field_signature.value(),
actual.confirmation_field_signature.value());
}
void CheckEqualPassPasswordGenerationUIData(
const password_generation::PasswordGenerationUIData& expected,
const password_generation::PasswordGenerationUIData& actual) {
EXPECT_EQ(expected.bounds, actual.bounds);
EXPECT_EQ(expected.max_length, actual.max_length);
EXPECT_EQ(expected.generation_element, actual.generation_element);
EXPECT_EQ(expected.text_direction, actual.text_direction);
EXPECT_EQ(expected.password_form, actual.password_form);
}
} // namespace
class AutofillTypeTraitsTestImpl : public testing::Test,
public mojom::TypeTraitsTest {
public:
AutofillTypeTraitsTestImpl() {}
mojom::TypeTraitsTestPtr GetTypeTraitsTestProxy() {
mojom::TypeTraitsTestPtr proxy;
bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
return proxy;
}
// mojom::TypeTraitsTest:
void PassFormData(const FormData& s, PassFormDataCallback callback) override {
std::move(callback).Run(s);
}
void PassFormFieldData(const FormFieldData& s,
PassFormFieldDataCallback callback) override {
std::move(callback).Run(s);
}
void PassFormDataPredictions(
const FormDataPredictions& s,
PassFormDataPredictionsCallback callback) override {
std::move(callback).Run(s);
}
void PassFormFieldDataPredictions(
const FormFieldDataPredictions& s,
PassFormFieldDataPredictionsCallback callback) override {
std::move(callback).Run(s);
}
void PassPasswordFormFillData(
const PasswordFormFillData& s,
PassPasswordFormFillDataCallback callback) override {
std::move(callback).Run(s);
}
void PassPasswordFormGenerationData(
const PasswordFormGenerationData& s,
PassPasswordFormGenerationDataCallback callback) override {
std::move(callback).Run(s);
}
void PassPasswordGenerationUIData(
const password_generation::PasswordGenerationUIData& s,
PassPasswordGenerationUIDataCallback callback) override {
std::move(callback).Run(s);
}
void PassPasswordForm(const PasswordForm& s,
PassPasswordFormCallback callback) override {
std::move(callback).Run(s);
}
void PassFormsPredictionsMap(
const FormsPredictionsMap& s,
PassFormsPredictionsMapCallback callback) override {
std::move(callback).Run(s);
}
private:
base::MessageLoop loop_;
mojo::BindingSet<TypeTraitsTest> bindings_;
};
void ExpectFormFieldData(const FormFieldData& expected,
const base::Closure& closure,
const FormFieldData& passed) {
EXPECT_EQ(expected, passed);
closure.Run();
}
void ExpectFormData(const FormData& expected,
const base::Closure& closure,
const FormData& passed) {
EXPECT_EQ(expected, passed);
closure.Run();
}
void ExpectFormFieldDataPredictions(const FormFieldDataPredictions& expected,
const base::Closure& closure,
const FormFieldDataPredictions& passed) {
EXPECT_EQ(expected, passed);
closure.Run();
}
void ExpectFormDataPredictions(const FormDataPredictions& expected,
const base::Closure& closure,
const FormDataPredictions& passed) {
EXPECT_EQ(expected, passed);
closure.Run();
}
void ExpectPasswordFormFillData(const PasswordFormFillData& expected,
const base::Closure& closure,
const PasswordFormFillData& passed) {
CheckEqualPasswordFormFillData(expected, passed);
closure.Run();
}
void ExpectPasswordFormGenerationData(
const PasswordFormGenerationData& expected,
const base::Closure& closure,
const PasswordFormGenerationData& passed) {
CheckEqualPasswordFormGenerationData(expected, passed);
closure.Run();
}
void ExpectPasswordGenerationUIData(
const password_generation::PasswordGenerationUIData& expected,
base::OnceClosure closure,
const password_generation::PasswordGenerationUIData& passed) {
CheckEqualPassPasswordGenerationUIData(expected, passed);
std::move(closure).Run();
}
void ExpectPasswordForm(const PasswordForm& expected,
const base::Closure& closure,
const PasswordForm& passed) {
EXPECT_EQ(expected, passed);
closure.Run();
}
void ExpectFormsPredictionsMap(const FormsPredictionsMap& expected,
const base::Closure& closure,
const FormsPredictionsMap& passed) {
EXPECT_EQ(expected, passed);
closure.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldData) {
FormFieldData input;
test::CreateTestSelectField("TestLabel", "TestName", "TestValue", kOptions,
kOptions, 4, &input);
// Set other attributes to check if they are passed correctly.
input.id_attribute = base::ASCIIToUTF16("id");
input.name_attribute = base::ASCIIToUTF16("name");
input.autocomplete_attribute = "on";
input.placeholder = base::ASCIIToUTF16("placeholder");
input.css_classes = base::ASCIIToUTF16("class1");
input.aria_label = base::ASCIIToUTF16("aria label");
input.aria_description = base::ASCIIToUTF16("aria description");
input.max_length = 12345;
input.is_autofilled = true;
input.check_status = FormFieldData::CHECKED;
input.should_autocomplete = true;
input.role = FormFieldData::ROLE_ATTRIBUTE_PRESENTATION;
input.text_direction = base::i18n::RIGHT_TO_LEFT;
input.properties_mask = FieldPropertiesFlags::HAD_FOCUS;
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassFormFieldData(
input, base::Bind(&ExpectFormFieldData, input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassFormData) {
FormData input;
test::CreateTestAddressFormData(&input);
input.username_predictions = {1, 13, 2};
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassFormData(input,
base::Bind(&ExpectFormData, input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassFormFieldDataPredictions) {
FormFieldDataPredictions input;
CreateTestFieldDataPredictions("TestSignature", &input);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassFormFieldDataPredictions(
input,
base::Bind(&ExpectFormFieldDataPredictions, input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassFormDataPredictions) {
FormDataPredictions input;
test::CreateTestAddressFormData(&input.data);
input.signature = "TestSignature";
FormFieldDataPredictions field_predict;
CreateTestFieldDataPredictions("Tom", &field_predict);
input.fields.push_back(field_predict);
CreateTestFieldDataPredictions("Jerry", &field_predict);
input.fields.push_back(field_predict);
CreateTestFieldDataPredictions("NoOne", &field_predict);
input.fields.push_back(field_predict);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassFormDataPredictions(
input, base::Bind(&ExpectFormDataPredictions, input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassPasswordFormFillData) {
PasswordFormFillData input;
CreateTestPasswordFormFillData(&input);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassPasswordFormFillData(input, base::Bind(&ExpectPasswordFormFillData,
input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassPasswordFormGenerationData) {
FormData form;
test::CreateTestAddressFormData(&form);
FormSignature form_signature = CalculateFormSignature(form);
FieldSignature field_signature =
CalculateFieldSignatureForField(form.fields[0]);
FieldSignature confirmation_field_signature =
CalculateFieldSignatureForField(form.fields[1]);
PasswordFormGenerationData input(form_signature, field_signature);
input.confirmation_field_signature.emplace(confirmation_field_signature);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassPasswordFormGenerationData(
input,
base::Bind(&ExpectPasswordFormGenerationData, input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassPasswordGenerationUIData) {
password_generation::PasswordGenerationUIData input;
CreatePasswordGenerationUIData(&input);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassPasswordGenerationUIData(
input, base::BindOnce(&ExpectPasswordGenerationUIData, input,
loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassPasswordForm) {
PasswordForm input;
CreateTestPasswordForm(&input);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassPasswordForm(
input, base::Bind(&ExpectPasswordForm, input, loop.QuitClosure()));
loop.Run();
}
TEST_F(AutofillTypeTraitsTestImpl, PassFormsPredictionsMap) {
FormsPredictionsMap input;
CreateTestFormsPredictionsMap(&input);
base::RunLoop loop;
mojom::TypeTraitsTestPtr proxy = GetTypeTraitsTestProxy();
proxy->PassFormsPredictionsMap(
input, base::Bind(&ExpectFormsPredictionsMap, input, loop.QuitClosure()));
loop.Run();
}
} // namespace autofill