Commit ff02e6d9 authored by estade's avatar estade Committed by Commit bot

Autofill: one FormCache per WebFrame.

BUG=425756

Review URL: https://codereview.chromium.org/803673002

Cr-Commit-Position: refs/heads/master@{#308419}
parent 1328cb0f
......@@ -195,8 +195,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
const FormData& form = forms[0];
......@@ -255,8 +255,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
......@@ -486,8 +486,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
......@@ -566,8 +566,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the textarea element we want to find.
......@@ -656,8 +656,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
......@@ -744,8 +744,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
......@@ -816,8 +816,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
......@@ -891,8 +891,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
const size_t expected_size = unowned ? 1 : 2;
ASSERT_EQ(expected_size, forms.size());
......@@ -974,8 +974,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Get the input element we want to find.
......@@ -1070,8 +1070,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
......@@ -1166,8 +1166,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
......@@ -1232,8 +1232,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
......@@ -1286,8 +1286,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
......@@ -1340,8 +1340,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Set the auto-filled attribute.
......@@ -1394,8 +1394,8 @@ class FormAutofillTest : public ChromeRenderViewTest {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Set the autofilled attribute.
......@@ -2087,8 +2087,8 @@ TEST_F(FormAutofillTest, ExtractMultipleForms) {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(2U, forms.size());
// First form.
......@@ -2150,12 +2150,12 @@ TEST_F(FormAutofillTest, OnlyExtractNewForms) {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
// Second call should give nothing as there are no new forms.
forms = form_cache.ExtractNewForms(*web_frame);
forms = form_cache.ExtractNewForms();
ASSERT_TRUE(forms.empty());
// Append to the current form will re-extract.
......@@ -2167,7 +2167,7 @@ TEST_F(FormAutofillTest, OnlyExtractNewForms) {
"document.getElementById('testform').appendChild(newInput);");
msg_loop_.RunUntilIdle();
forms = form_cache.ExtractNewForms(*web_frame);
forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
const std::vector<FormFieldData>& fields = forms[0].fields;
......@@ -2220,7 +2220,7 @@ TEST_F(FormAutofillTest, OnlyExtractNewForms) {
msg_loop_.RunUntilIdle();
web_frame = GetMainFrame();
forms = form_cache.ExtractNewForms(*web_frame);
forms = form_cache.ExtractNewForms();
ASSERT_EQ(1U, forms.size());
const std::vector<FormFieldData>& fields2 = forms[0].fields;
......@@ -2250,8 +2250,8 @@ TEST_F(FormAutofillTest, ExtractFormsTooFewFields) {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_TRUE(forms.empty());
}
......@@ -2265,8 +2265,8 @@ TEST_F(FormAutofillTest, ExtractFormsSkippedForms) {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_TRUE(forms.empty());
}
......@@ -2278,8 +2278,8 @@ TEST_F(FormAutofillTest, ExtractFormsNoFields) {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_TRUE(forms.empty());
}
......@@ -2297,8 +2297,8 @@ TEST_F(FormAutofillTest, ExtractFormsTooFewFieldsSkipsCheckable) {
WebFrame* web_frame = GetMainFrame();
ASSERT_NE(nullptr, web_frame);
FormCache form_cache;
std::vector<FormData> forms = form_cache.ExtractNewForms(*web_frame);
FormCache form_cache(*web_frame);
std::vector<FormData> forms = form_cache.ExtractNewForms();
ASSERT_TRUE(forms.empty());
}
......
......@@ -133,6 +133,7 @@ AutofillAgent::AutofillAgent(content::RenderFrame* render_frame,
PasswordAutofillAgent* password_autofill_agent,
PasswordGenerationAgent* password_generation_agent)
: content::RenderFrameObserver(render_frame),
form_cache_(*render_frame->GetWebFrame()),
password_autofill_agent_(password_autofill_agent),
password_generation_agent_(password_generation_agent),
legacy_(render_frame->GetRenderView(), this),
......@@ -179,8 +180,7 @@ bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
}
void AutofillAgent::DidCommitProvisionalLoad(bool is_new_navigation) {
// TODO(estade): |form_cache_| shouldn't track multiple frames.
form_cache_.ResetFrame(*render_frame()->GetWebFrame());
form_cache_.Reset();
}
void AutofillAgent::DidFinishDocumentLoad() {
......@@ -191,7 +191,7 @@ void AutofillAgent::FrameDetached(WebFrame* frame) {
if (frame != render_frame()->GetWebFrame())
return;
form_cache_.ResetFrame(*frame);
form_cache_.Reset();
}
void AutofillAgent::WillSubmitForm(WebLocalFrame* frame,
......@@ -760,7 +760,7 @@ void AutofillAgent::ProcessForms() {
base::TimeTicks forms_seen_timestamp = base::TimeTicks::Now();
WebLocalFrame* frame = render_frame()->GetWebFrame();
std::vector<FormData> forms = form_cache_.ExtractNewForms(*frame);
std::vector<FormData> forms = form_cache_.ExtractNewForms();
// Always communicate to browser process for topmost frame.
if (!forms.empty() || !frame->parent()) {
......
......@@ -9,7 +9,6 @@
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_predictions.h"
#include "grit/components_strings.h"
#include "third_party/WebKit/public/platform/WebString.h"
......@@ -42,32 +41,6 @@ namespace autofill {
namespace {
// Helper function to discard state of various WebFormElements when they go out
// of web frame's scope. This is done to release memory that we no longer need
// to hold.
// K should inherit from WebFormControlElement as the function looks to extract
// WebFormElement for K.form().
template <class K, class V>
void RemoveOldElements(const WebFrame& frame, std::map<const K, V>* states) {
std::vector<K> to_remove;
for (typename std::map<const K, V>::const_iterator it = states->begin();
it != states->end(); ++it) {
const WebFormElement& form_element = it->first.form();
if (form_element.isNull()) {
to_remove.push_back(it->first);
} else {
const WebFrame* element_frame = form_element.document().frame();
if (!element_frame || element_frame == &frame)
to_remove.push_back(it->first);
}
}
for (typename std::vector<K>::const_iterator it = to_remove.begin();
it != to_remove.end(); ++it) {
states->erase(*it);
}
}
void LogDeprecationMessages(const WebFormControlElement& element) {
std::string autocomplete_attribute =
base::UTF16ToUTF8(element.getAttribute("autocomplete"));
......@@ -96,27 +69,24 @@ bool ShouldIgnoreForm(size_t num_editable_elements,
} // namespace
FormCache::FormCache() {
FormCache::FormCache(const WebFrame& frame) : frame_(frame) {
}
FormCache::~FormCache() {
}
std::vector<FormData> FormCache::ExtractNewForms(const WebFrame& frame) {
std::vector<FormData> FormCache::ExtractNewForms() {
std::vector<FormData> forms;
WebDocument document = frame.document();
WebDocument document = frame_.document();
if (document.isNull())
return forms;
if (!ContainsKey(documents_to_synthetic_form_map_, document))
documents_to_synthetic_form_map_[document] = FormData();
WebVector<WebFormElement> web_forms;
document.forms(web_forms);
// Log an error message for deprecated attributes, but only the first time
// the form is parsed.
bool log_deprecation_messages = !ContainsKey(parsed_forms_, &frame);
bool log_deprecation_messages = parsed_forms_.empty();
const ExtractMask extract_mask =
static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS);
......@@ -144,9 +114,9 @@ std::vector<FormData> FormCache::ExtractNewForms(const WebFrame& frame) {
return forms;
if (form.fields.size() >= kRequiredAutofillFields &&
!ContainsKey(parsed_forms_[&frame], form)) {
!ContainsKey(parsed_forms_, form)) {
forms.push_back(form);
parsed_forms_[&frame].insert(form);
parsed_forms_.insert(form);
}
}
......@@ -161,41 +131,32 @@ std::vector<FormData> FormCache::ExtractNewForms(const WebFrame& frame) {
if (ShouldIgnoreForm(num_editable_elements, control_elements.size()))
return forms;
FormData form;
FormData synthetic_form;
if (!UnownedFormElementsAndFieldSetsToFormData(fieldsets, control_elements,
nullptr, document.url(),
REQUIRE_NONE, extract_mask,
&form, nullptr)) {
&synthetic_form, nullptr)) {
return forms;
}
num_fields_seen += form.fields.size();
num_fields_seen += synthetic_form.fields.size();
if (num_fields_seen > kMaxParseableFields)
return forms;
if (form.fields.size() >= kRequiredAutofillFields &&
!parsed_forms_[&frame].count(form)) {
forms.push_back(form);
parsed_forms_[&frame].insert(form);
documents_to_synthetic_form_map_[document] = form;
if (synthetic_form.fields.size() >= kRequiredAutofillFields &&
!parsed_forms_.count(synthetic_form)) {
forms.push_back(synthetic_form);
parsed_forms_.insert(synthetic_form);
synthetic_form_ = synthetic_form;
}
return forms;
}
void FormCache::ResetFrame(const WebFrame& frame) {
std::vector<WebDocument> documents_to_delete;
for (const auto& it : documents_to_synthetic_form_map_) {
const WebFrame* document_frame = it.first.frame();
if (!document_frame || document_frame == &frame)
documents_to_delete.push_back(it.first);
}
for (const auto& it : documents_to_delete)
documents_to_synthetic_form_map_.erase(it);
parsed_forms_[&frame].clear();
RemoveOldElements(frame, &initial_select_values_);
RemoveOldElements(frame, &initial_checked_state_);
void FormCache::Reset() {
synthetic_form_ = FormData();
parsed_forms_.clear();
initial_select_values_.clear();
initial_checked_state_.clear();
}
bool FormCache::ClearFormWithElement(const WebFormControlElement& element) {
......@@ -261,47 +222,39 @@ bool FormCache::ShowPredictions(const FormDataPredictions& form) {
std::vector<WebFormControlElement> control_elements;
// First check the synthetic forms.
// First check the synthetic form.
bool found_synthetic_form = false;
for (const auto& it : documents_to_synthetic_form_map_) {
const FormData& form_data = it.second;
if (!form_data.SameFormAs(form.data))
continue;
if (form.data.SameFormAs(synthetic_form_)) {
found_synthetic_form = true;
WebDocument document = it.first;
WebDocument document = frame_.document();
control_elements =
GetUnownedAutofillableFormFieldElements(document.all(), nullptr);
break;
}
if (!found_synthetic_form) {
// Find the real form by searching through the WebDocuments.
bool found_form = false;
WebFormElement form_element;
for (const auto& it : documents_to_synthetic_form_map_) {
WebVector<WebFormElement> web_forms;
it.first.forms(web_forms);
for (size_t i = 0; i < web_forms.size(); ++i) {
form_element = web_forms[i];
// Note: matching on the form name here which is not guaranteed to be
// unique for the page, nor is it guaranteed to be non-empty. Ideally,
// we would have a way to uniquely identify the form cross-process. For
// now, we'll check form name and form action for identity.
// Also note that WebString() == WebString(string16()) does not evaluate
// to |true| -- WebKit distinguishes between a "null" string (lhs) and
// an "empty" string (rhs). We don't want that distinction, so forcing
// to string16.
base::string16 element_name = GetFormIdentifier(form_element);
GURL action(form_element.document().completeURL(form_element.action()));
if (element_name == form.data.name && action == form.data.action) {
found_form = true;
control_elements =
ExtractAutofillableElementsInForm(form_element, REQUIRE_NONE);
break;
}
WebVector<WebFormElement> web_forms;
frame_.document().forms(web_forms);
for (size_t i = 0; i < web_forms.size(); ++i) {
form_element = web_forms[i];
// Note: matching on the form name here which is not guaranteed to be
// unique for the page, nor is it guaranteed to be non-empty. Ideally,
// we would have a way to uniquely identify the form cross-process. For
// now, we'll check form name and form action for identity.
// Also note that WebString() == WebString(string16()) does not evaluate
// to |true| -- WebKit distinguishes between a "null" string (lhs) and
// an "empty" string (rhs). We don't want that distinction, so forcing
// to string16.
base::string16 element_name = GetFormIdentifier(form_element);
GURL action(form_element.document().completeURL(form_element.action()));
if (element_name == form.data.name && action == form.data.action) {
found_form = true;
control_elements =
ExtractAutofillableElementsInForm(form_element, REQUIRE_NONE);
break;
}
}
......
......@@ -10,6 +10,7 @@
#include <vector>
#include "base/strings/string16.h"
#include "components/autofill/core/common/form_data.h"
namespace blink {
class WebDocument;
......@@ -23,21 +24,20 @@ class WebSelectElement;
namespace autofill {
struct FormData;
struct FormDataPredictions;
// Manages the forms in a RenderView.
// Manages the forms in a single RenderFrame.
class FormCache {
public:
FormCache();
explicit FormCache(const blink::WebFrame& frame);
~FormCache();
// Scans the DOM in |frame| extracting and storing forms that have not been
// Scans the DOM in |frame_| extracting and storing forms that have not been
// seen before. Returns the extracted forms.
std::vector<FormData> ExtractNewForms(const blink::WebFrame& frame);
std::vector<FormData> ExtractNewForms();
// Resets the forms for the specified |frame|.
void ResetFrame(const blink::WebFrame& frame);
// Resets the forms.
void Reset();
// Clears the values of all input elements in the form that contains
// |element|. Returns false if the form is not found.
......@@ -58,13 +58,15 @@ class FormCache {
const std::vector<blink::WebFormControlElement>& control_elements,
bool log_deprecation_messages);
// The cached web frames and their corresponding synthetic FormData.
// The frame this FormCache is associated with.
const blink::WebFrame& frame_;
// The cached forms. Used to prevent re-extraction of forms.
std::set<FormData> parsed_forms_;
// The synthetic FormData is for all the fieldsets in the document without a
// form owner.
std::map<blink::WebDocument, FormData> documents_to_synthetic_form_map_;
// The cached forms per frame. Used to prevent re-extraction of forms.
std::map<const blink::WebFrame*, std::set<FormData> > parsed_forms_;
FormData synthetic_form_;
// The cached initial values for <select> elements.
std::map<const blink::WebSelectElement, base::string16>
......
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