[Passwords] Fix for showing the Save prompt after deleting the password
Bug: 1069376
Change-Id: Ied89b907d20859ea44ea4611f0705a9cd722a395
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2148602
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Reviewed-by: Vadym Doroshenko <dvadym@chromium.org>
Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805789}
This commit is contained in:

committed by
Commit Bot

parent
9c6535819d
commit
090e52a01b
chrome/renderer/autofill
fake_mojo_password_manager_driver.ccfake_mojo_password_manager_driver.hpassword_autofill_agent_browsertest.ccpassword_generation_agent_browsertest.cc
components
autofill
content
common
renderer
core
common
password_manager
tools/metrics/histograms
weblayer/browser
@ -67,16 +67,12 @@ void FakeMojoPasswordManagerDriver::CheckSafeBrowsingReputation(
|
||||
called_check_safe_browsing_reputation_cnt_++;
|
||||
}
|
||||
|
||||
void FakeMojoPasswordManagerDriver::ShowManualFallbackForSaving(
|
||||
void FakeMojoPasswordManagerDriver::InformAboutUserInput(
|
||||
const autofill::FormData& form_data) {
|
||||
called_show_manual_fallback_for_saving_count_++;
|
||||
called_inform_about_user_input_count_++;
|
||||
form_data_maybe_submitted_ = form_data;
|
||||
}
|
||||
|
||||
void FakeMojoPasswordManagerDriver::HideManualFallbackForSaving() {
|
||||
called_show_manual_fallback_for_saving_count_ = 0;
|
||||
}
|
||||
|
||||
void FakeMojoPasswordManagerDriver::FocusedInputChanged(
|
||||
autofill::mojom::FocusedFieldType focused_field_type) {
|
||||
last_focused_field_type_ = focused_field_type;
|
||||
|
@ -111,8 +111,8 @@ class FakeMojoPasswordManagerDriver
|
||||
return called_check_safe_browsing_reputation_cnt_;
|
||||
}
|
||||
|
||||
int called_show_manual_fallback_for_saving_count() const {
|
||||
return called_show_manual_fallback_for_saving_count_;
|
||||
int called_inform_about_user_input_count() const {
|
||||
return called_inform_about_user_input_count_;
|
||||
}
|
||||
|
||||
autofill::mojom::FocusedFieldType last_focused_field_type() const {
|
||||
@ -143,9 +143,8 @@ class FakeMojoPasswordManagerDriver
|
||||
void CheckSafeBrowsingReputation(const GURL& form_action,
|
||||
const GURL& frame_url) override;
|
||||
|
||||
void ShowManualFallbackForSaving(
|
||||
const autofill::FormData& form_data) override;
|
||||
void HideManualFallbackForSaving() override;
|
||||
void InformAboutUserInput(const autofill::FormData& form_data) override;
|
||||
|
||||
void FocusedInputChanged(
|
||||
autofill::mojom::FocusedFieldType focused_field_type) override;
|
||||
void LogFirstFillingResult(autofill::FormRendererId form_renderer_id,
|
||||
@ -181,9 +180,8 @@ class FakeMojoPasswordManagerDriver
|
||||
// Records number of times CheckSafeBrowsingReputation() gets called.
|
||||
int called_check_safe_browsing_reputation_cnt_ = 0;
|
||||
|
||||
// Records the number of request to show manual fallback for password saving.
|
||||
// If it is zero, the fallback is not available.
|
||||
int called_show_manual_fallback_for_saving_count_ = 0;
|
||||
// Records the number of request to inform about user input.
|
||||
int called_inform_about_user_input_count_ = 0;
|
||||
|
||||
// Records the last focused field type that FocusedInputChanged() was called
|
||||
// with.
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "third_party/blink/public/web/win/web_font_rendering.h"
|
||||
#endif
|
||||
|
||||
using autofill::FormRendererId;
|
||||
using autofill::FormTracker;
|
||||
using autofill::mojom::FocusedFieldType;
|
||||
using autofill::mojom::PasswordFormFieldPredictionType;
|
||||
@ -461,8 +462,8 @@ class PasswordAutofillAgentTest : public ChromeRenderViewTest {
|
||||
password_element_.UniqueRendererFormControlId());
|
||||
WebFormElement form = password_element_.Form();
|
||||
fill_data_.form_renderer_id =
|
||||
form.IsNull() ? autofill::FormRendererId()
|
||||
: autofill::FormRendererId(form.UniqueRendererFormId());
|
||||
form.IsNull() ? FormRendererId()
|
||||
: FormRendererId(form.UniqueRendererFormId());
|
||||
}
|
||||
|
||||
void UpdateUsernameAndPasswordElements() {
|
||||
@ -674,18 +675,18 @@ class PasswordAutofillAgentTest : public ChromeRenderViewTest {
|
||||
<< "Some expected masks are missed in FormData";
|
||||
}
|
||||
|
||||
autofill::FormRendererId GetFormUniqueRendererId(const WebString& form_id) {
|
||||
FormRendererId GetFormUniqueRendererId(const WebString& form_id) {
|
||||
WebLocalFrame* frame = GetMainFrame();
|
||||
if (!frame)
|
||||
return autofill::FormRendererId();
|
||||
return FormRendererId();
|
||||
WebFormElement web_form =
|
||||
frame->GetDocument().GetElementById(form_id).To<WebFormElement>();
|
||||
return autofill::FormRendererId(web_form.UniqueRendererFormId());
|
||||
return FormRendererId(web_form.UniqueRendererFormId());
|
||||
}
|
||||
|
||||
void ExpectFormDataWithUsernameAndPasswordsAndEvent(
|
||||
const autofill::FormData& form_data,
|
||||
autofill::FormRendererId form_renderer_id,
|
||||
FormRendererId form_renderer_id,
|
||||
const std::string& username_value,
|
||||
const std::string& password_value,
|
||||
const std::string& new_password_value,
|
||||
@ -698,7 +699,7 @@ class PasswordAutofillAgentTest : public ChromeRenderViewTest {
|
||||
}
|
||||
|
||||
void ExpectFormSubmittedWithUsernameAndPasswords(
|
||||
autofill::FormRendererId form_renderer_id,
|
||||
FormRendererId form_renderer_id,
|
||||
const std::string& username_value,
|
||||
const std::string& password_value,
|
||||
const std::string& new_password_value) {
|
||||
@ -712,7 +713,7 @@ class PasswordAutofillAgentTest : public ChromeRenderViewTest {
|
||||
}
|
||||
|
||||
void ExpectSameDocumentNavigationWithUsernameAndPasswords(
|
||||
autofill::FormRendererId form_renderer_id,
|
||||
FormRendererId form_renderer_id,
|
||||
const std::string& username_value,
|
||||
const std::string& password_value,
|
||||
const std::string& new_password_value,
|
||||
@ -959,7 +960,7 @@ TEST_F(PasswordAutofillAgentTest, NoFillingOnSignupForm_NoMetrics) {
|
||||
WebFormElement form_element =
|
||||
document.GetElementById("LoginTestForm").To<WebFormElement>();
|
||||
fill_data_.form_renderer_id =
|
||||
autofill::FormRendererId(form_element.UniqueRendererFormId());
|
||||
FormRendererId(form_element.UniqueRendererFormId());
|
||||
|
||||
SimulateOnFillPasswordForm(fill_data_);
|
||||
histogram_tester_.ExpectTotalCount(
|
||||
@ -1482,7 +1483,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
// Neither field should have been autocompleted.
|
||||
CheckTextFieldsDOMState("user1", false, std::string(), false);
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(0, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Only password field should be autocompleted.
|
||||
EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
|
||||
@ -1490,7 +1491,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
ASCIIToUTF16(kAlicePassword)));
|
||||
CheckTextFieldsDOMState("user1", false, kAlicePassword, true);
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(1, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Try Filling with a different password. Only password should be changed.
|
||||
EXPECT_TRUE(password_autofill_agent_->FillSuggestion(
|
||||
@ -1498,7 +1499,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
ASCIIToUTF16(kCarolPassword)));
|
||||
CheckTextFieldsDOMState("user1", false, kCarolPassword, true);
|
||||
base::RunLoop().RunUntilIdle();
|
||||
EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count());
|
||||
}
|
||||
|
||||
// Tests that |FillSuggestion| properly fills the password if the username field
|
||||
@ -1807,7 +1808,7 @@ TEST_F(PasswordAutofillAgentTest, DontTryToShowTouchToFillSignUpForm) {
|
||||
WebFormElement form_element =
|
||||
document.GetElementById("LoginTestForm").To<WebFormElement>();
|
||||
fill_data_.form_renderer_id =
|
||||
autofill::FormRendererId(form_element.UniqueRendererFormId());
|
||||
FormRendererId(form_element.UniqueRendererFormId());
|
||||
|
||||
SimulateOnFillPasswordForm(fill_data_);
|
||||
|
||||
@ -2100,7 +2101,7 @@ TEST_F(PasswordAutofillAgentTest, NoCredentialsOnPasswordClick) {
|
||||
// PasswordAutofillAgent can still remember the username and the password
|
||||
// typed by the user.
|
||||
TEST_F(PasswordAutofillAgentTest,
|
||||
DISABLED_RememberLastNonEmptyUsernameAndPasswordOnSubmit_ScriptCleared) {
|
||||
RememberLastNonEmptyUsernameAndPasswordOnSubmit_ScriptCleared) {
|
||||
LoadHTML(kSignupFormHTML);
|
||||
WebInputElement username_element = GetInputElementByID("random_info");
|
||||
ASSERT_FALSE(username_element.IsNull());
|
||||
@ -2128,8 +2129,9 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
|
||||
// Observe that the PasswordAutofillAgent still remembered the last non-empty
|
||||
// username and password and sent that to the browser.
|
||||
ExpectFormSubmittedWithUsernameAndPasswords(GetFormUniqueRendererId("form"),
|
||||
"username", "", "random");
|
||||
ExpectFormSubmittedWithUsernameAndPasswords(
|
||||
FormRendererId(username_element.Form().UniqueRendererFormId()),
|
||||
"username", "", "random");
|
||||
fake_driver_.form_data_submitted();
|
||||
}
|
||||
|
||||
@ -2157,7 +2159,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
// Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the
|
||||
// new password instead of the current password.
|
||||
TEST_F(PasswordAutofillAgentTest,
|
||||
DISABLED_RememberLastNonEmptyUsernameAndPasswordOnSubmit_New) {
|
||||
RememberLastNonEmptyUsernameAndPasswordOnSubmit_New) {
|
||||
const char kNewPasswordFormHTML[] =
|
||||
"<FORM name='LoginTestForm' action='http://www.bidule.com'>"
|
||||
" <INPUT type='text' id='username' autocomplete='username'/>"
|
||||
@ -2180,7 +2182,8 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
// Observe that the PasswordAutofillAgent still remembered the last non-empty
|
||||
// password and sent that to the browser.
|
||||
ExpectFormSubmittedWithUsernameAndPasswords(
|
||||
GetFormUniqueRendererId("LoginTestForm"), "temp", "", "random");
|
||||
FormRendererId(username_element_.Form().UniqueRendererFormId()), "temp",
|
||||
"", "random");
|
||||
}
|
||||
|
||||
// The user first accepts a suggestion, but then overwrites the password. This
|
||||
@ -2812,7 +2815,7 @@ TEST_F(PasswordAutofillAgentTest, NoForm_PromptForAJAXSubmitWithoutNavigation) {
|
||||
FireAjaxSucceeded();
|
||||
|
||||
ExpectSameDocumentNavigationWithUsernameAndPasswords(
|
||||
autofill::FormRendererId(), "Bob", "mypassword", "",
|
||||
FormRendererId(), "Bob", "mypassword", "",
|
||||
SubmissionIndicatorEvent::XHR_SUCCEEDED);
|
||||
}
|
||||
|
||||
@ -2836,7 +2839,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
base::RunLoop().RunUntilIdle();
|
||||
|
||||
ExpectSameDocumentNavigationWithUsernameAndPasswords(
|
||||
autofill::FormRendererId(), "Bob", "mypassword", "",
|
||||
FormRendererId(), "Bob", "mypassword", "",
|
||||
SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
|
||||
}
|
||||
|
||||
@ -2871,7 +2874,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
PromptForAJAXSubmitAfterDeletingParentElement) {
|
||||
LoadHTML(kDivWrappedFormHTML);
|
||||
UpdateUsernameAndPasswordElements();
|
||||
autofill::FormRendererId renderer_id = GetFormUniqueRendererId("form");
|
||||
FormRendererId renderer_id = GetFormUniqueRendererId("form");
|
||||
|
||||
SimulateUsernameTyping("Bob");
|
||||
SimulatePasswordTyping("mypassword");
|
||||
@ -3304,7 +3307,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
FireAjaxSucceeded();
|
||||
|
||||
ExpectSameDocumentNavigationWithUsernameAndPasswords(
|
||||
autofill::FormRendererId(), "Alice", "mypassword", "",
|
||||
FormRendererId(), "Alice", "mypassword", "",
|
||||
SubmissionIndicatorEvent::XHR_SUCCEEDED);
|
||||
}
|
||||
}
|
||||
@ -3330,7 +3333,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
base::RunLoop().RunUntilIdle();
|
||||
|
||||
ExpectSameDocumentNavigationWithUsernameAndPasswords(
|
||||
autofill::FormRendererId(), "Alice", "mypassword", "",
|
||||
FormRendererId(), "Alice", "mypassword", "",
|
||||
SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
|
||||
}
|
||||
|
||||
@ -3468,8 +3471,7 @@ TEST_F(PasswordAutofillAgentTest,
|
||||
SameDocumentNavigationSubmissionUsernameIsEmpty) {
|
||||
username_element_.SetValue(WebString());
|
||||
SimulatePasswordTyping("random");
|
||||
autofill::FormRendererId renderer_id =
|
||||
GetFormUniqueRendererId("LoginTestForm");
|
||||
FormRendererId renderer_id = GetFormUniqueRendererId("LoginTestForm");
|
||||
|
||||
// Simulate that JavaScript removes the submitted form from DOM. That means
|
||||
// that a submission was successful.
|
||||
@ -3557,42 +3559,41 @@ TEST_F(PasswordAutofillAgentTest, NoForm_MultipleAJAXEventsWithoutSubmission) {
|
||||
|
||||
TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving) {
|
||||
EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(_, _)).Times(0);
|
||||
// The users enters a username. No password - no fallback.
|
||||
// The users enters a username. Inform the driver regardless.
|
||||
SimulateUsernameTyping(kUsernameName);
|
||||
EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(1, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// The user enters a password.
|
||||
SimulatePasswordTyping(kPasswordName);
|
||||
// SimulateUsernameTyping/SimulatePasswordTyping calls
|
||||
// PasswordAutofillAgent::UpdateStateForTextChange only once.
|
||||
EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Remove one character from the password value.
|
||||
SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true);
|
||||
EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(3, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Add one character to the username value.
|
||||
SetFocused(username_element_);
|
||||
SimulateUserTypingASCIICharacter('a', true);
|
||||
EXPECT_EQ(3, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(4, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Remove username value.
|
||||
SimulateUsernameTyping("");
|
||||
EXPECT_EQ(4, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(5, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Change the password. Despite of empty username the fallback is still
|
||||
// there.
|
||||
// Change the password.
|
||||
SetFocused(password_element_);
|
||||
SimulateUserTypingASCIICharacter('a', true);
|
||||
EXPECT_EQ(5, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(6, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Remove password value. The fallback should be disabled.
|
||||
// Remove password value. Inform the driver too.
|
||||
SimulatePasswordTyping("");
|
||||
EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(7, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// The user enters new password. Show the fallback again.
|
||||
// The user enters new password.
|
||||
SimulateUserTypingASCIICharacter('a', true);
|
||||
EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(8, fake_driver_.called_inform_about_user_input_count());
|
||||
}
|
||||
|
||||
TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving_PasswordChangeForm) {
|
||||
@ -3600,37 +3601,37 @@ TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving_PasswordChangeForm) {
|
||||
UpdateUrlForHTML(kPasswordChangeFormHTML);
|
||||
UpdateUsernameAndPasswordElements();
|
||||
|
||||
// No password to save yet - no fallback.
|
||||
// No password to save yet - still we should inform the driver.
|
||||
SimulateUsernameTyping(kUsernameName);
|
||||
EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(1, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// The user enters in the current password field. The fallback should be
|
||||
// available to save the entered value.
|
||||
SimulatePasswordTyping(kPasswordName);
|
||||
// SimulateUsernameTyping/SimulatePasswordTyping calls
|
||||
// PasswordAutofillAgent::UpdateStateForTextChange only once.
|
||||
EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// The user types into the new password field. The fallback should be updated.
|
||||
// The user types into the new password field. Inform the driver.
|
||||
WebInputElement new_password = GetInputElementByID("newpassword");
|
||||
ASSERT_FALSE(new_password.IsNull());
|
||||
SetFocused(new_password);
|
||||
SimulateUserTypingASCIICharacter('a', true);
|
||||
EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(3, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Edits of the confirmation password field trigger fallback updates.
|
||||
// Edits of the confirmation password field trigger informing the driver.
|
||||
WebInputElement confirmation_password =
|
||||
GetInputElementByID("confirmpassword");
|
||||
ASSERT_FALSE(confirmation_password.IsNull());
|
||||
SetFocused(confirmation_password);
|
||||
SimulateUserTypingASCIICharacter('a', true);
|
||||
EXPECT_EQ(3, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(4, fake_driver_.called_inform_about_user_input_count());
|
||||
|
||||
// Clear all password fields. The fallback should be disabled.
|
||||
// Clear all password fields. The driver should be informed.
|
||||
SimulatePasswordTyping("");
|
||||
SimulateUserInputChangeForElement(&new_password, "");
|
||||
SimulateUserInputChangeForElement(&confirmation_password, "");
|
||||
EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(5, fake_driver_.called_inform_about_user_input_count());
|
||||
}
|
||||
|
||||
// Tests that information about Gaia reauthentication form is sent to the
|
||||
|
@ -895,21 +895,20 @@ TEST_F(PasswordGenerationAgentTest, FallbackForSaving) {
|
||||
LoadHTMLWithUserGesture(kAccountCreationFormHTML);
|
||||
SimulateElementRightClick("first_password");
|
||||
SelectGenerationFallbackAndExpect(true);
|
||||
EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(0, fake_driver_.called_inform_about_user_input_count());
|
||||
base::string16 password = base::ASCIIToUTF16("random_password");
|
||||
EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(_, Eq(password)))
|
||||
.WillOnce(testing::InvokeWithoutArgs([this]() {
|
||||
// Make sure that generation event was propagated to the browser before
|
||||
// the fallback showing. Otherwise, the fallback for saving provides a
|
||||
// save bubble instead of a confirmation bubble.
|
||||
EXPECT_EQ(0,
|
||||
fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(0, fake_driver_.called_inform_about_user_input_count());
|
||||
}));
|
||||
password_generation_->GeneratedPasswordAccepted(password);
|
||||
fake_driver_.Flush();
|
||||
// Two fallback requests are expected because generation changes either new
|
||||
// password and confirmation fields.
|
||||
EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count());
|
||||
EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count());
|
||||
}
|
||||
|
||||
TEST_F(PasswordGenerationAgentTest, FormClassifierDisabled) {
|
||||
|
@ -96,13 +96,10 @@ interface PasswordManagerDriver {
|
||||
// Notification that this password form was submitted by the user.
|
||||
PasswordFormSubmitted(FormData form_data);
|
||||
|
||||
// Notification that a user starts typing in password fields and the omnibox
|
||||
// icon with anchored save/update prompt should be available.
|
||||
ShowManualFallbackForSaving(FormData form_data);
|
||||
|
||||
// Notification that there is no user input in password fields and the
|
||||
// save/update prompt anchored to the omnibox icon should be removed.
|
||||
HideManualFallbackForSaving();
|
||||
// Notification that a user has modified a password field. This is fired both
|
||||
// when typing new characters and deleting characters, so the password field
|
||||
// in `form_data` may or may not be empty
|
||||
InformAboutUserInput(FormData form_data);
|
||||
|
||||
// Notification that same-document navigation happened. We use this as a
|
||||
// signal for successful login.
|
||||
|
@ -33,6 +33,7 @@ class FormTracker : public content::RenderFrameObserver {
|
||||
SELECT_CHANGED,
|
||||
};
|
||||
|
||||
// TODO(crbug.com/1126017): Find a better name for this method.
|
||||
// Invoked when form needs to be saved because of |source|, |element| is
|
||||
// valid if the callback caused by source other than
|
||||
// WILL_SEND_SUBMIT_EVENT, |form| is valid for the callback caused by
|
||||
|
@ -356,17 +356,6 @@ bool FormHasPasswordField(const FormData& form) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Whether any of the fields in |form| is a non-empty password field.
|
||||
bool FormHasNonEmptyPasswordField(const FormData& form) {
|
||||
for (const auto& field : form.fields) {
|
||||
if (field.IsPasswordInputElement()) {
|
||||
if (!field.value.empty() || !field.typed_value.empty())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AnnotateFieldWithParsingResult(WebDocument doc,
|
||||
FieldRendererId renderer_id,
|
||||
const std::string& text) {
|
||||
@ -564,7 +553,7 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
|
||||
field_data_manager_->UpdateFieldDataMap(element_id, element_value,
|
||||
FieldPropertiesFlags::kUserTyped);
|
||||
|
||||
ProvisionallySavePassword(element.Form(), element, RESTRICTION_NONE);
|
||||
InformBrowserAboutUserInput(element.Form(), element);
|
||||
|
||||
if (element.IsPasswordFieldForAutofill()) {
|
||||
auto iter = password_to_username_.find(element);
|
||||
@ -659,8 +648,7 @@ void PasswordAutofillAgent::FillPasswordFieldAndSave(
|
||||
DCHECK(password_input);
|
||||
DCHECK(password_input->IsPasswordFieldForAutofill());
|
||||
FillField(password_input, credential);
|
||||
ProvisionallySavePassword(password_input->Form(), *password_input,
|
||||
RESTRICTION_NONE);
|
||||
InformBrowserAboutUserInput(password_input->Form(), *password_input);
|
||||
}
|
||||
|
||||
bool PasswordAutofillAgent::PreviewSuggestion(
|
||||
@ -1454,29 +1442,23 @@ void PasswordAutofillAgent::ClearPreview(WebInputElement* username,
|
||||
password->SetAutofillState(password_autofill_state_);
|
||||
}
|
||||
}
|
||||
void PasswordAutofillAgent::ProvisionallySavePassword(
|
||||
void PasswordAutofillAgent::InformBrowserAboutUserInput(
|
||||
const WebFormElement& form,
|
||||
const WebInputElement& element,
|
||||
ProvisionallySaveRestriction restriction) {
|
||||
const WebInputElement& element) {
|
||||
DCHECK(!form.IsNull() || !element.IsNull());
|
||||
if (!FrameCanAccessPasswordManager())
|
||||
return;
|
||||
SetLastUpdatedFormAndField(form, element);
|
||||
std::unique_ptr<FormData> form_data =
|
||||
(form.IsNull() ? GetFormDataFromUnownedInputElements()
|
||||
: GetFormDataFromWebForm(form));
|
||||
form.IsNull() ? GetFormDataFromUnownedInputElements()
|
||||
: GetFormDataFromWebForm(form);
|
||||
if (!form_data)
|
||||
return;
|
||||
|
||||
bool has_password = FormHasNonEmptyPasswordField(*form_data);
|
||||
if (restriction == RESTRICTION_NON_EMPTY_PASSWORD && !has_password)
|
||||
if (!FormHasPasswordField(*form_data))
|
||||
return;
|
||||
|
||||
if (!FrameCanAccessPasswordManager())
|
||||
return;
|
||||
|
||||
if (has_password)
|
||||
GetPasswordManagerDriver()->ShowManualFallbackForSaving(*form_data);
|
||||
else
|
||||
GetPasswordManagerDriver()->HideManualFallbackForSaving();
|
||||
GetPasswordManagerDriver()->InformAboutUserInput(*form_data);
|
||||
|
||||
browser_has_form_to_process_ = true;
|
||||
}
|
||||
@ -1639,8 +1621,7 @@ void PasswordAutofillAgent::OnProvisionallySaveForm(
|
||||
}
|
||||
|
||||
DCHECK_EQ(ElementChangeSource::WILL_SEND_SUBMIT_EVENT, source);
|
||||
ProvisionallySavePassword(form, input_element,
|
||||
RESTRICTION_NON_EMPTY_PASSWORD);
|
||||
InformBrowserAboutUserInput(form, input_element);
|
||||
}
|
||||
|
||||
void PasswordAutofillAgent::OnFormSubmitted(const WebFormElement& form) {
|
||||
|
@ -243,12 +243,6 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
|
||||
private:
|
||||
using OnPasswordField = util::StrongAlias<class OnPasswordFieldTag, bool>;
|
||||
|
||||
// Ways to restrict which passwords are saved in ProvisionallySavePassword.
|
||||
enum ProvisionallySaveRestriction {
|
||||
RESTRICTION_NONE,
|
||||
RESTRICTION_NON_EMPTY_PASSWORD
|
||||
};
|
||||
|
||||
// Enumeration representing possible Touch To Fill states. This is used to
|
||||
// make sure that Touch To Fill will only be shown in response to the first
|
||||
// password form focus during a frame's life time and to suppress the soft
|
||||
@ -397,14 +391,12 @@ class PasswordAutofillAgent : public content::RenderFrameObserver,
|
||||
void FillPasswordFieldAndSave(blink::WebInputElement* password_input,
|
||||
const base::string16& credential);
|
||||
|
||||
// Saves |form| and |input| in |provisionally_saved_form_|, as long as it
|
||||
// satisfies |restriction|. |form| and |input| are the elements user has just
|
||||
// been interacting with before the form save. |form| or |input| can be null
|
||||
// but not both at the same time. For example: if the form is unowned, |form|
|
||||
// will be null; if the user has submitted the form, |input| will be null.
|
||||
void ProvisionallySavePassword(const blink::WebFormElement& form,
|
||||
const blink::WebInputElement& input,
|
||||
ProvisionallySaveRestriction restriction);
|
||||
// |form| and |input| are the elements user has just been interacting with
|
||||
// before the form save. |form| or |input| can be null but not both at the
|
||||
// same time. For example: if the form is unowned, |form| will be null; if the
|
||||
// user has submitted the form, |input| will be null.
|
||||
void InformBrowserAboutUserInput(const blink::WebFormElement& form,
|
||||
const blink::WebInputElement& input);
|
||||
|
||||
// This function attempts to fill |username_element| and |password_element|
|
||||
// with values from |fill_data|. The |username_element| and |password_element|
|
||||
|
@ -50,10 +50,7 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
|
||||
|
||||
void PasswordFormSubmitted(const autofill::FormData& form_data) override {}
|
||||
|
||||
void ShowManualFallbackForSaving(
|
||||
const autofill::FormData& form_data) override {}
|
||||
|
||||
void HideManualFallbackForSaving() override {}
|
||||
void InformAboutUserInput(const autofill::FormData& form_data) override {}
|
||||
|
||||
void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
|
||||
submission_indication_event) override {}
|
||||
|
@ -142,6 +142,16 @@ bool FormData::IdentityComparator::operator()(const FormData& a,
|
||||
FormFieldData::IdentityComparator());
|
||||
}
|
||||
|
||||
bool FormHasNonEmptyPasswordField(const FormData& form) {
|
||||
for (const auto& field : form.fields) {
|
||||
if (field.IsPasswordInputElement()) {
|
||||
if (!field.value.empty() || !field.typed_value.empty())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const FormData& form) {
|
||||
os << base::UTF16ToUTF8(form.name) << " " << form.url << " " << form.action
|
||||
<< " " << form.main_frame_origin << " " << form.is_form_tag << " "
|
||||
|
@ -120,6 +120,9 @@ struct FormData {
|
||||
#endif
|
||||
};
|
||||
|
||||
// Whether any of the fields in |form| is a non-empty password field.
|
||||
bool FormHasNonEmptyPasswordField(const FormData& form);
|
||||
|
||||
// For testing.
|
||||
std::ostream& operator<<(std::ostream& os, const FormData& form);
|
||||
|
||||
|
@ -34,7 +34,7 @@ enum class BadMessageReason {
|
||||
CPMD_BAD_ORIGIN_PASSWORD_NO_LONGER_GENERATED = 6,
|
||||
CPMD_BAD_ORIGIN_PRESAVE_GENERATED_PASSWORD = 7,
|
||||
CPMD_BAD_ORIGIN_SAVE_GENERATION_FIELD_DETECTED_BY_CLASSIFIER = 8,
|
||||
CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING = 9,
|
||||
CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE = 9,
|
||||
CPMD_BAD_ORIGIN_AUTOMATIC_GENERATION_STATUS_CHANGED = 10,
|
||||
CPMD_BAD_ORIGIN_SHOW_MANUAL_PASSWORD_GENERATION_POPUP = 11,
|
||||
CPMD_BAD_ORIGIN_SHOW_PASSWORD_EDITING_POPUP = 12,
|
||||
|
@ -246,15 +246,16 @@ void ContentPasswordManagerDriver::PasswordFormSubmitted(
|
||||
LogSiteIsolationMetricsForSubmittedForm(render_frame_host_);
|
||||
}
|
||||
|
||||
void ContentPasswordManagerDriver::ShowManualFallbackForSaving(
|
||||
void ContentPasswordManagerDriver::InformAboutUserInput(
|
||||
const autofill::FormData& form_data) {
|
||||
if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
|
||||
render_frame_host_, form_data.url,
|
||||
BadMessageReason::CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING))
|
||||
BadMessageReason::CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE))
|
||||
return;
|
||||
GetPasswordManager()->ShowManualFallbackForSaving(this, form_data);
|
||||
GetPasswordManager()->OnInformAboutUserInput(this, form_data);
|
||||
|
||||
if (client_->IsIsolationForPasswordSitesEnabled()) {
|
||||
if (FormHasNonEmptyPasswordField(form_data) &&
|
||||
client_->IsIsolationForPasswordSitesEnabled()) {
|
||||
// This function signals that a password field has been filled (whether by
|
||||
// the user, JS, autofill, or some other means) or a password form has been
|
||||
// submitted. Use this as a heuristic to start site-isolating the form's
|
||||
@ -266,10 +267,6 @@ void ContentPasswordManagerDriver::ShowManualFallbackForSaving(
|
||||
}
|
||||
}
|
||||
|
||||
void ContentPasswordManagerDriver::HideManualFallbackForSaving() {
|
||||
GetPasswordManager()->HideManualFallbackForSaving();
|
||||
}
|
||||
|
||||
void ContentPasswordManagerDriver::SameDocumentNavigation(
|
||||
autofill::mojom::SubmissionIndicatorEvent submission_indication_event) {
|
||||
GetPasswordManager()->OnPasswordFormSubmittedNoChecks(
|
||||
|
@ -100,9 +100,7 @@ class ContentPasswordManagerDriver
|
||||
const std::vector<autofill::FormData>& visible_forms_data,
|
||||
bool did_stop_loading) override;
|
||||
void PasswordFormSubmitted(const autofill::FormData& form_data) override;
|
||||
void ShowManualFallbackForSaving(
|
||||
const autofill::FormData& form_data) override;
|
||||
void HideManualFallbackForSaving() override;
|
||||
void InformAboutUserInput(const autofill::FormData& form_data) override;
|
||||
void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
|
||||
submission_indication_event) override;
|
||||
void RecordSavePasswordProgress(const std::string& log) override;
|
||||
|
@ -488,8 +488,8 @@ void PasswordManager::OnUserModifiedNonPasswordField(
|
||||
renderer_id, value, base::Time::Now(), driver_id);
|
||||
}
|
||||
|
||||
void PasswordManager::ShowManualFallbackForSaving(PasswordManagerDriver* driver,
|
||||
const FormData& form_data) {
|
||||
void PasswordManager::OnInformAboutUserInput(PasswordManagerDriver* driver,
|
||||
const FormData& form_data) {
|
||||
PasswordFormManager* manager = ProvisionallySaveForm(form_data, driver, true);
|
||||
|
||||
if (manager && form_data.is_gaia_with_skip_save_password_form) {
|
||||
@ -504,7 +504,7 @@ void PasswordManager::ShowManualFallbackForSaving(PasswordManagerDriver* driver,
|
||||
if (client_ && client_->GetMetricsRecorder())
|
||||
client_->GetMetricsRecorder()->RecordFormManagerAvailable(availability);
|
||||
|
||||
ShowManualFallbackForSavingImpl(manager, form_data);
|
||||
ShowManualFallbackForSaving(manager, form_data);
|
||||
}
|
||||
|
||||
void PasswordManager::HideManualFallbackForSaving() {
|
||||
@ -724,8 +724,7 @@ void PasswordManager::UpdateStateOnUserInput(
|
||||
if (manager->UpdateStateOnUserInput(form_id, field_id, field_value)) {
|
||||
ProvisionallySaveForm(*manager->observed_form(), driver, true);
|
||||
if (manager->is_submitted() && !manager->HasGeneratedPassword()) {
|
||||
ShowManualFallbackForSavingImpl(manager.get(),
|
||||
*manager->observed_form());
|
||||
ShowManualFallbackForSaving(manager.get(), *manager->observed_form());
|
||||
} else {
|
||||
HideManualFallbackForSaving();
|
||||
}
|
||||
@ -1197,10 +1196,19 @@ void PasswordManager::TryToFindPredictionsToPossibleUsernameData() {
|
||||
}
|
||||
}
|
||||
|
||||
void PasswordManager::ShowManualFallbackForSavingImpl(
|
||||
void PasswordManager::ShowManualFallbackForSaving(
|
||||
PasswordFormManager* form_manager,
|
||||
const FormData& form_data) {
|
||||
if (!form_manager || !form_manager->is_submitted())
|
||||
// Where `form_manager` is nullptr, make sure the manual fallback isn't
|
||||
// shown. One scenario where this is relevant is when the user inputs some
|
||||
// password and then removes it. Upon removing the password, the
|
||||
// `form_manager` will become nullptr.
|
||||
if (!form_manager) {
|
||||
HideManualFallbackForSaving();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!form_manager->is_submitted())
|
||||
return;
|
||||
|
||||
if (!client_->GetProfilePasswordStore()->IsAbleToSavePasswords() ||
|
||||
|
@ -166,10 +166,10 @@ class PasswordManager : public PasswordManagerInterface {
|
||||
autofill::FieldRendererId renderer_id,
|
||||
const base::string16& value);
|
||||
|
||||
// Handles a request to show manual fallback for password saving, i.e. the
|
||||
// omnibox icon with the anchored hidden prompt.
|
||||
void ShowManualFallbackForSaving(PasswordManagerDriver* driver,
|
||||
const autofill::FormData& form_data);
|
||||
// Handles user input and decides whether to show manual fallback for password
|
||||
// saving, i.e. the omnibox icon with the anchored hidden prompt.
|
||||
void OnInformAboutUserInput(PasswordManagerDriver* driver,
|
||||
const autofill::FormData& form_data);
|
||||
|
||||
// Handles a request to hide manual fallback for password saving.
|
||||
void HideManualFallbackForSaving();
|
||||
@ -320,8 +320,8 @@ class PasswordManager : public PasswordManagerInterface {
|
||||
|
||||
// Handles a request to show manual fallback for password saving, i.e. the
|
||||
// omnibox icon with the anchored hidden prompt. todo
|
||||
void ShowManualFallbackForSavingImpl(PasswordFormManager* form_manager,
|
||||
const autofill::FormData& form_data);
|
||||
void ShowManualFallbackForSaving(PasswordFormManager* form_manager,
|
||||
const autofill::FormData& form_data);
|
||||
|
||||
// Returns the timeout for the disabling Password Manager's prompts.
|
||||
base::TimeDelta GetTimeoutForDisablingPrompts();
|
||||
|
@ -913,7 +913,7 @@ TEST_P(PasswordManagerTest, DontSaveAlreadySavedCredential) {
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, incomplete_match.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, incomplete_match.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
|
||||
FormMatches(incomplete_match));
|
||||
@ -924,7 +924,7 @@ TEST_P(PasswordManagerTest, DontSaveAlreadySavedCredential) {
|
||||
// because the credential is already in the store.
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)).Times(0);
|
||||
EXPECT_CALL(client_, HideManualFallbackForSaving());
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
|
||||
// The user submits the form. No prompt should pop up. The credential is
|
||||
// updated in background.
|
||||
@ -939,6 +939,42 @@ TEST_P(PasswordManagerTest, DontSaveAlreadySavedCredential) {
|
||||
user_action_tester.GetActionCount("PasswordManager_LoginPassed"));
|
||||
}
|
||||
|
||||
TEST_P(PasswordManagerTest, DoNotSaveWhenUserDeletesPassword) {
|
||||
PasswordForm form(MakeSimpleForm());
|
||||
PasswordForm stored_form = form;
|
||||
stored_form.password_value = ASCIIToUTF16("old_password");
|
||||
EXPECT_CALL(*store_, GetLogins(_, _))
|
||||
.WillRepeatedly(WithArg<1>(InvokeConsumer(store_.get(), stored_form)));
|
||||
|
||||
ON_CALL(client_, IsSavingAndFillingEnabled(form.url))
|
||||
.WillByDefault(Return(true));
|
||||
|
||||
std::vector<FormData> observed = {form.form_data};
|
||||
manager()->OnPasswordFormsParsed(&driver_, observed);
|
||||
|
||||
// The user is typing a credential manually, the fallback should be available.
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
|
||||
// The user deletes the password, no manuall fallback should be shown.
|
||||
PasswordForm empty_password_form(form);
|
||||
empty_password_form.password_value.clear();
|
||||
empty_password_form.form_data.fields[1].value.clear();
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr).Times(0);
|
||||
EXPECT_CALL(client_, HideManualFallbackForSaving());
|
||||
manager()->OnInformAboutUserInput(&driver_, empty_password_form.form_data);
|
||||
|
||||
// The user submits the form. No prompt should pop up.
|
||||
OnPasswordFormSubmitted(empty_password_form.form_data);
|
||||
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr).Times(0);
|
||||
observed.clear();
|
||||
manager()->DidNavigateMainFrame(true);
|
||||
manager()->OnPasswordFormsParsed(&driver_, observed);
|
||||
}
|
||||
|
||||
// Tests that on Chrome sign-in form credentials are not saved.
|
||||
TEST_P(PasswordManagerTest, DoNotSaveOnChromeSignInForm) {
|
||||
FormData form_data(MakeSimpleFormData());
|
||||
@ -957,7 +993,7 @@ TEST_P(PasswordManagerTest, DoNotSaveOnChromeSignInForm) {
|
||||
FormData typed_credentials(form_data);
|
||||
typed_credentials.fields[1].value = ASCIIToUTF16("pw");
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)).Times(0);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form_data);
|
||||
|
||||
// The user submits the form. No prompt should pop up.
|
||||
OnPasswordFormSubmitted(form_data);
|
||||
@ -992,7 +1028,7 @@ TEST_P(PasswordManagerTest,
|
||||
EXPECT_CALL(client_, HideManualFallbackForSaving());
|
||||
// The call to manual fallback with |form| equal to already saved should close
|
||||
// the fallback, but it should not prevent sending metrics.
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0);
|
||||
EXPECT_CALL(*store_, UpdateLogin(_));
|
||||
|
||||
@ -1812,7 +1848,7 @@ TEST_P(PasswordManagerTest, SameDocumentNavigation) {
|
||||
.WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms(store_.get())));
|
||||
manager()->OnPasswordFormsParsed(&driver_, observed);
|
||||
manager()->OnPasswordFormsRendered(&driver_, observed, true);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
|
||||
@ -1843,7 +1879,7 @@ TEST_P(PasswordManagerTest, SameDocumentBlockedSite) {
|
||||
.WillRepeatedly(Return(true));
|
||||
manager()->OnPasswordFormsParsed(&driver_, observed);
|
||||
manager()->OnPasswordFormsRendered(&driver_, observed, true);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_))
|
||||
@ -2466,7 +2502,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSaving) {
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form));
|
||||
|
||||
@ -2476,7 +2512,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSaving) {
|
||||
new_form.form_data.fields[0].value = new_form.username_value;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, new_form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, new_form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
|
||||
FormMatches(new_form));
|
||||
@ -2516,7 +2552,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSaving_SlowBackend) {
|
||||
|
||||
// There is no response from the store. Don't show the fallback.
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)).Times(0);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form_data);
|
||||
|
||||
// The storage responded. The fallback can be shown.
|
||||
ASSERT_TRUE(store_consumer);
|
||||
@ -2525,7 +2561,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSaving_SlowBackend) {
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form_data);
|
||||
}
|
||||
|
||||
TEST_P(PasswordManagerTest, ManualFallbackForSaving_GeneratedPassword) {
|
||||
@ -2549,7 +2585,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSaving_GeneratedPassword) {
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->OnPresaveGeneratedPassword(&driver_, form.form_data,
|
||||
form.password_value);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form));
|
||||
|
||||
@ -2560,7 +2596,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSaving_GeneratedPassword) {
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->OnPresaveGeneratedPassword(&driver_, form.form_data,
|
||||
form.password_value);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
|
||||
// A user removes the generated password. The presaved password is removed,
|
||||
// the fallback is disabled.
|
||||
@ -2829,7 +2865,7 @@ TEST_P(PasswordManagerTest, ProcessingOtherSubmissionTypes) {
|
||||
observed.push_back(form_data);
|
||||
manager()->OnPasswordFormsParsed(&driver_, observed);
|
||||
manager()->OnPasswordFormsRendered(&driver_, observed, true);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form_data);
|
||||
|
||||
auto submitted_form_data = form_data;
|
||||
submitted_form_data.fields[0].value = ASCIIToUTF16("username");
|
||||
@ -2915,7 +2951,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSavingNewParser) {
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form));
|
||||
|
||||
@ -2925,7 +2961,7 @@ TEST_P(PasswordManagerTest, ManualFallbackForSavingNewParser) {
|
||||
new_form.form_data.fields[0].value = new_form.username_value;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, new_form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, new_form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
|
||||
FormMatches(new_form));
|
||||
@ -3066,7 +3102,7 @@ TEST_P(PasswordManagerTest, SavingAfterUserTypingAndNavigation) {
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
|
||||
FormMatches(form));
|
||||
@ -3245,7 +3281,7 @@ TEST_P(PasswordManagerTest, ReportMissingFormManager) {
|
||||
manager()->OnPasswordFormSubmitted(nullptr, form_data);
|
||||
break;
|
||||
case MissingFormManagerTestCase::Signal::Manual:
|
||||
manager()->ShowManualFallbackForSaving(nullptr, form_data);
|
||||
manager()->OnInformAboutUserInput(nullptr, form_data);
|
||||
break;
|
||||
case MissingFormManagerTestCase::Signal::None:
|
||||
break;
|
||||
@ -3355,7 +3391,7 @@ TEST_P(PasswordManagerTest, FillingAndSavingFallbacksOnNonPasswordForm) {
|
||||
std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save;
|
||||
EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false))
|
||||
.WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save)));
|
||||
manager()->ShowManualFallbackForSaving(&driver_, credit_card_form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, credit_card_form.form_data);
|
||||
ASSERT_TRUE(form_manager_to_save);
|
||||
EXPECT_THAT(form_manager_to_save->GetPendingCredentials(),
|
||||
FormMatches(credit_card_form));
|
||||
@ -3677,7 +3713,7 @@ TEST_P(PasswordManagerTest, NoPromptAutofillAssistantManuallyCuratedScript) {
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
PasswordForm form(MakeSimpleForm());
|
||||
manager()->OnPasswordFormsParsed(&driver_, {form.form_data});
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form.form_data);
|
||||
|
||||
manager()->DidNavigateMainFrame(true /* form_may_be_submitted */);
|
||||
manager()->OnPasswordFormsRendered(&driver_, {} /* observed */,
|
||||
@ -3708,8 +3744,8 @@ TEST_P(PasswordManagerTest,
|
||||
PasswordForm form2(MakeSimpleForm());
|
||||
manager()->OnPasswordFormsParsed(&driver_,
|
||||
{form1.form_data, form2.form_data});
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form1.form_data);
|
||||
manager()->ShowManualFallbackForSaving(&driver_, form2.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form1.form_data);
|
||||
manager()->OnInformAboutUserInput(&driver_, form2.form_data);
|
||||
|
||||
// Simulate submission in different ways depending on whether
|
||||
// |owned_submitted_form_manager_| should be set and |form_managers_| should
|
||||
|
@ -6432,7 +6432,7 @@ Called by update_bad_message_reasons.py.-->
|
||||
<int value="7" label="CPMD_BAD_ORIGIN_PRESAVE_GENERATED_PASSWORD"/>
|
||||
<int value="8"
|
||||
label="CPMD_BAD_ORIGIN_SAVE_GENERATION_FIELD_DETECTED_BY_CLASSIFIER"/>
|
||||
<int value="9" label="CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING"/>
|
||||
<int value="9" label="CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE"/>
|
||||
<int value="10" label="CPMD_BAD_ORIGIN_AUTOMATIC_GENERATION_STATUS_CHANGED"/>
|
||||
<int value="11"
|
||||
label="CPMD_BAD_ORIGIN_SHOW_MANUAL_PASSWORD_GENERATION_POPUP"/>
|
||||
|
@ -38,16 +38,16 @@ class PasswordManagerDriverFactory::PasswordManagerDriver
|
||||
const std::vector<autofill::FormData>& visible_forms_data,
|
||||
bool did_stop_loading) override {}
|
||||
void PasswordFormSubmitted(const autofill::FormData& form_data) override {}
|
||||
void ShowManualFallbackForSaving(
|
||||
const autofill::FormData& form_data) override {
|
||||
void InformAboutUserInput(const autofill::FormData& form_data) override {
|
||||
if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
|
||||
render_frame_host_, form_data.url,
|
||||
password_manager::BadMessageReason::
|
||||
CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING)) {
|
||||
CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (site_isolation::SiteIsolationPolicy::
|
||||
if (FormHasNonEmptyPasswordField(form_data) &&
|
||||
site_isolation::SiteIsolationPolicy::
|
||||
IsIsolationForPasswordSitesEnabled()) {
|
||||
// This function signals that a password field has been filled (whether by
|
||||
// the user, JS, autofill, or some other means) or a password form has
|
||||
@ -59,7 +59,6 @@ class PasswordManagerDriverFactory::PasswordManagerDriver
|
||||
form_data.url);
|
||||
}
|
||||
}
|
||||
void HideManualFallbackForSaving() override {}
|
||||
void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent
|
||||
submission_indication_event) override {}
|
||||
void RecordSavePasswordProgress(const std::string& log) override {}
|
||||
|
Reference in New Issue
Block a user