Index: components/autofill/content/renderer/password_autofill_agent.cc |
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc |
index 51a16769c8209b2febc1529cdefd4983f43ae6d8..212eef1913636fe4d376f0826c5d5bf3a8df9195 100644 |
--- a/components/autofill/content/renderer/password_autofill_agent.cc |
+++ b/components/autofill/content/renderer/password_autofill_agent.cc |
@@ -599,6 +599,23 @@ void AnnotateFormsWithSignatures( |
} |
} |
+// Returns true iff there is a password field in |frame|. |
+bool HasPasswordField(const blink::WebLocalFrame& frame) { |
+ CR_DEFINE_STATIC_LOCAL(blink::WebString, kPassword, ("password")); |
+ |
+ const blink::WebElementCollection elements = frame.GetDocument().All(); |
+ for (blink::WebElement element = elements.FirstItem(); !element.IsNull(); |
+ element = elements.NextItem()) { |
+ if (element.IsFormControlElement()) { |
+ const blink::WebFormControlElement& control = |
+ element.To<blink::WebFormControlElement>(); |
+ if (control.FormControlType() == kPassword) |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
} // namespace |
//////////////////////////////////////////////////////////////////////////////// |
@@ -609,6 +626,7 @@ PasswordAutofillAgent::PasswordAutofillAgent(content::RenderFrame* render_frame) |
logging_state_active_(false), |
was_username_autofilled_(false), |
was_password_autofilled_(false), |
+ sent_request_to_store_(false), |
binding_(this) { |
// PasswordAutofillAgent is guaranteed to outlive |render_frame|. |
render_frame->GetInterfaceRegistry()->AddInterface( |
@@ -1118,20 +1136,33 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) { |
} |
} |
- if (password_forms.empty() && !only_visible) { |
- // We need to send the PasswordFormsRendered message regardless of whether |
- // there are any forms visible, as this is also the code path that triggers |
- // showing the infobar. |
- return; |
- } |
- |
if (only_visible) { |
+ // Send the PasswordFormsRendered message regardless of whether |
+ // |password_forms| is empty. The empty |password_forms| are a possible |
+ // signal to the browser that a pending login attempt succeeded. |
blink::WebFrame* main_frame = render_frame()->GetWebFrame()->Top(); |
bool did_stop_loading = !main_frame || !main_frame->IsLoading(); |
GetPasswordManagerDriver()->PasswordFormsRendered(password_forms, |
did_stop_loading); |
} else { |
- GetPasswordManagerDriver()->PasswordFormsParsed(password_forms); |
+ // If there is a password field, but the list of password forms is empty for |
+ // some reason, add a dummy form to the list. It will cause a request to the |
+ // store. Therefore, saved passwords will be available for filling on click. |
+ if (!sent_request_to_store_ && password_forms.empty() && |
+ HasPasswordField(*frame)) { |
+ // Set everything that |FormDigest| needs. |
+ password_forms.push_back(PasswordForm()); |
+ password_forms.back().scheme = PasswordForm::SCHEME_HTML; |
+ password_forms.back().origin = |
+ form_util::GetCanonicalOriginForDocument(frame->GetDocument()); |
+ GURL::Replacements rep; |
+ rep.SetPathStr(""); |
+ password_forms.back().signon_realm = |
+ password_forms.back().origin.ReplaceComponents(rep).spec(); |
+ sent_request_to_store_ = true; |
+ } |
+ if (!password_forms.empty()) |
+ GetPasswordManagerDriver()->PasswordFormsParsed(password_forms); |
} |
} |
@@ -1565,6 +1596,7 @@ void PasswordAutofillAgent::FrameClosing() { |
web_input_to_password_info_.clear(); |
provisionally_saved_form_.Reset(); |
field_value_and_properties_map_.clear(); |
+ sent_request_to_store_ = false; |
} |
void PasswordAutofillAgent::ClearPreview( |