Commit 31ba8c6c authored by vasilii's avatar vasilii Committed by Commit bot

Password manager should autofill a dynamic form added and processed before the page was loaded.

Currently AutofillAgent::DidAssociateFormControlsDynamically ignores the notification if the frame isn't loaded. That makes no sense because the page may never be loaded due to some slow resource. Even if it will, password autofill shouldn't wait for the page load event. It's needed primarily for the successful submission detection.

BUG=713645

Review-Url: https://codereview.chromium.org/2849653003
Cr-Commit-Position: refs/heads/master@{#468136}
parent 180f23bb
...@@ -1307,6 +1307,46 @@ IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, ...@@ -1307,6 +1307,46 @@ IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
CheckElementValue("password", "12345"); CheckElementValue("password", "12345");
} }
// https://crbug.com/713645
// Navigate to a page that can't load some of the subresources. Create a hidden
// form when the body is loaded. Make the form visible. Chrome should autofill
// the form.
// The fact that the form is hidden isn't super important but reproduces the
// actual bug.
IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase, SlowPageFill) {
// At first let us save a credential to the password store.
scoped_refptr<password_manager::TestPasswordStore> password_store =
static_cast<password_manager::TestPasswordStore*>(
PasswordStoreFactory::GetForProfile(
browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
.get());
autofill::PasswordForm signin_form;
signin_form.signon_realm = embedded_test_server()->base_url().spec();
signin_form.origin = embedded_test_server()->base_url();
signin_form.action = embedded_test_server()->base_url();
signin_form.username_value = base::ASCIIToUTF16("admin");
signin_form.password_value = base::ASCIIToUTF16("12345");
password_store->AddLogin(signin_form);
GURL url =
embedded_test_server()->GetURL("/password/infinite_password_form.html");
ui_test_utils::NavigateToURLWithDisposition(
browser(), url, WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_NONE);
// Wait for autofill.
BubbleObserver bubble_observer(WebContents());
bubble_observer.WaitForManagementState();
// Show the form and make sure that the password was autofilled.
std::string show_form =
"document.getElementsByTagName('form')[0].style.display = 'block'";
ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), show_form));
CheckElementValue("username", "admin");
CheckElementValue("password", "12345");
}
// Test that if there was no previous page load then the PasswordManagerDriver // Test that if there was no previous page load then the PasswordManagerDriver
// does not think that there were SSL errors on the current page. The test opens // does not think that there were SSL errors on the current page. The test opens
// a new tab with a URL for which the embedded test server issues a basic auth // a new tab with a URL for which the embedded test server issues a basic auth
......
<!--
This page has a resource that takes a very long time to load. Nevetheless, a
hidden password form is created dynamically. It should be autofilled and
successful submission should be detected.
-->
<html>
<head>
<script src="form_utils.js"></script>
<script>
function addDynamicForm() {
var form = createSimplePasswordForm();
form.style.display = 'none';
document.body.appendChild(form);
}
document.addEventListener("DOMContentLoaded", function(event) {
// Add the form some time after the DOM was loaded. It means that the form
// won't be detected during DidFinishDocumentLoad() stage.
setTimeout(addDynamicForm);
});
</script>
<title>Test dynamically created password form</title>
</head>
<body>
<img src="/slow?100">
</body>
</html>
...@@ -737,16 +737,12 @@ bool AutofillAgent::IsUserGesture() const { ...@@ -737,16 +737,12 @@ bool AutofillAgent::IsUserGesture() const {
} }
void AutofillAgent::DidAssociateFormControlsDynamically() { void AutofillAgent::DidAssociateFormControlsDynamically() {
blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); // If the control flow is here than the document was at least loaded. The
// whole page doesn't have to be loaded.
// Frame is only processed if it has finished loading, otherwise you can end ProcessForms();
// up with a partially parsed form. password_autofill_agent_->OnDynamicFormsSeen();
if (frame && !frame->IsLoading()) { if (password_generation_agent_)
ProcessForms(); password_generation_agent_->OnDynamicFormsSeen();
password_autofill_agent_->OnDynamicFormsSeen();
if (password_generation_agent_)
password_generation_agent_->OnDynamicFormsSeen();
}
} }
void AutofillAgent::DidCompleteFocusChangeInFrame() { void AutofillAgent::DidCompleteFocusChangeInFrame() {
......
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