Commit 3a71a194 authored by Vadym Doroshenko's avatar Vadym Doroshenko Committed by Commit Bot

Create form manager on SINGLE_USERNAME server prediction.

Now, form manager is created only for password forms. In order to fill username
field during username first flow, form manager needs to be created for username-only
forms. This CL implements it.

Bug: 959776
Change-Id: I2252c8e07aa04c606dfb5edadaea6675fecc96d5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1735575
Commit-Queue: Vadym Doroshenko <dvadym@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#684274}
parent d6913fa0
......@@ -585,7 +585,8 @@ FormStructure::FormStructure(const FormData& form)
form_parsed_timestamp_(base::TimeTicks::Now()),
passwords_were_revealed_(false),
password_symbol_vote_(0),
developer_engagement_metrics_(0) {
developer_engagement_metrics_(0),
unique_renderer_id_(form.unique_renderer_id) {
// Copy the form fields.
std::map<base::string16, size_t> unique_names;
for (const FormFieldData& field : form.fields) {
......@@ -1360,6 +1361,7 @@ FormData FormStructure::ToFormData() const {
data.url = source_url_;
data.action = target_url_;
data.main_frame_origin = main_frame_origin_;
data.unique_renderer_id = unique_renderer_id_;
for (size_t i = 0; i < fields_.size(); ++i) {
data.fields.push_back(FormFieldData(*fields_[i]));
......
......@@ -357,6 +357,8 @@ class FormStructure {
value_from_dynamic_change_form_ = v;
}
uint32_t unique_renderer_id() const { return unique_renderer_id_; }
private:
friend class AutofillMergeTest;
friend class FormStructureTest;
......@@ -625,6 +627,8 @@ class FormStructure {
bool value_from_dynamic_change_form_ = false;
uint32_t unique_renderer_id_;
DISALLOW_COPY_AND_ASSIGN(FormStructure);
};
......
......@@ -352,6 +352,14 @@ bool IsOnlyNewParserEnabled() {
#endif
}
bool HasSingleUsernameVote(const FormStructure& form) {
for (const auto& field : form) {
if (field->server_type() == autofill::SINGLE_USERNAME)
return true;
}
return false;
}
} // namespace
// static
......@@ -1307,18 +1315,38 @@ void PasswordManager::MaybeSavePasswordHash(
}
void PasswordManager::ProcessAutofillPredictions(
password_manager::PasswordManagerDriver* driver,
const std::vector<autofill::FormStructure*>& forms) {
PasswordManagerDriver* driver,
const std::vector<FormStructure*>& forms) {
std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
if (password_manager_util::IsLoggingActive(client_))
if (password_manager_util::IsLoggingActive(client_)) {
logger.reset(
new BrowserSavePasswordProgressLogger(client_->GetLogManager()));
}
if (IsNewFormParsingForFillingEnabled()) {
for (const autofill::FormStructure* form : forms)
for (const FormStructure* form : forms)
predictions_[form->form_signature()] = ConvertToFormPredictions(*form);
for (auto& manager : form_managers_)
manager->ProcessServerPredictions(predictions_);
// Create form managers for non-password forms with single usernames.
for (const FormStructure* form : forms) {
if (form->has_password_field())
continue;
if (!HasSingleUsernameVote(*form))
continue;
if (FindMatchedManagerByRendererId(form->unique_renderer_id(),
form_managers_, driver)) {
// The form manager is already created.
continue;
}
FormData form_data = form->ToFormData();
auto* manager = CreateFormManager(driver, form_data);
manager->ProcessServerPredictions(predictions_);
}
}
// Leave only forms that contain fields that are useful for password manager.
......
......@@ -277,7 +277,7 @@ class PasswordManager : public FormSubmissionObserver {
// Create NewPasswordFormManager for |form|, adds the newly created one to
// |form_managers_| and returns it.
NewPasswordFormManager* CreateFormManager(PasswordManagerDriver* driver,
const autofill::FormData& forms);
const autofill::FormData& form);
// Passes |form| to NewPasswordFormManager that manages it for using it after
// detecting submission success for saving. |driver| is needed to determine
......
......@@ -3882,4 +3882,40 @@ TEST_F(PasswordManagerTest, StartLeakDetection) {
}
#endif // !defined(OS_IOS)
// Check that a non-password form with SINGLE_USERNAME prediction is filled.
TEST_F(PasswordManagerTest, FillSingleUsername) {
NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true);
EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
.WillRepeatedly(Return(true));
PasswordForm saved_match(MakeSavedForm());
EXPECT_CALL(*store_, GetLogins(_, _))
.WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match)));
// Create FormdData for a form with 1 text field.
FormData form_data;
const uint32_t form_id = 1001;
form_data.unique_renderer_id = form_id;
form_data.url = GURL("example.com");
FormFieldData field;
field.form_control_type = "text";
const uint32_t field_id = 10;
field.unique_renderer_id = field_id;
form_data.fields.push_back(field);
// Set SINGLE_USERNAME predictions for the field.
FormStructure form_structure(form_data);
form_structure.field(0)->set_server_type(autofill::SINGLE_USERNAME);
PasswordFormFillData fill_data;
EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
manager()->ProcessAutofillPredictions(&driver_, {&form_structure});
EXPECT_EQ(form_id, fill_data.form_renderer_id);
EXPECT_EQ(saved_match.username_value, fill_data.username_field.value);
EXPECT_EQ(saved_match.username_value, fill_data.username_field.value);
EXPECT_EQ(field_id, fill_data.username_field.unique_renderer_id);
EXPECT_EQ(saved_match.password_value, fill_data.password_field.value);
EXPECT_EQ(std::numeric_limits<uint32_t>::max(),
fill_data.password_field.unique_renderer_id);
}
} // namespace password_manager
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment