summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/autofill/autofill_download.cc14
-rw-r--r--chrome/browser/autofill/form_structure.cc40
-rw-r--r--chrome/browser/autofill/form_structure.h1
-rw-r--r--chrome/browser/autofill/form_structure_unittest.cc260
4 files changed, 301 insertions, 14 deletions
diff --git a/chrome/browser/autofill/autofill_download.cc b/chrome/browser/autofill/autofill_download.cc
index 95ee688..595accd 100644
--- a/chrome/browser/autofill/autofill_download.cc
+++ b/chrome/browser/autofill/autofill_download.cc
@@ -71,15 +71,10 @@ bool AutoFillDownloadManager::StartQueryRequest(
return false;
}
std::string form_xml;
- FormStructure::EncodeQueryRequest(forms, &form_xml);
-
FormRequestData request_data;
- request_data.form_signatures.reserve(forms.size());
- for (ScopedVector<FormStructure>::const_iterator it = forms.begin();
- it != forms.end();
- ++it) {
- request_data.form_signatures.push_back((*it)->FormSignature());
- }
+ if (!FormStructure::EncodeQueryRequest(forms, &request_data.form_signatures,
+ &form_xml))
+ return false;
request_data.request_type = AutoFillDownloadManager::REQUEST_QUERY;
@@ -102,7 +97,8 @@ bool AutoFillDownloadManager::StartUploadRequest(
return false;
}
std::string form_xml;
- form.EncodeUploadRequest(form_was_matched, &form_xml);
+ if (!form.EncodeUploadRequest(form_was_matched, &form_xml))
+ return false;
FormRequestData request_data;
request_data.form_signatures.push_back(form.FormSignature());
diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc
index 2e89f28..1d24e3e 100644
--- a/chrome/browser/autofill/form_structure.cc
+++ b/chrome/browser/autofill/form_structure.cc
@@ -105,6 +105,8 @@ FormStructure::~FormStructure() {}
bool FormStructure::EncodeUploadRequest(bool auto_fill_used,
std::string* encoded_xml) const {
+ DCHECK(encoded_xml);
+ encoded_xml->clear();
bool auto_fillable = IsAutoFillable();
DCHECK(auto_fillable); // Caller should've checked for search pages.
if (!auto_fillable)
@@ -129,7 +131,8 @@ bool FormStructure::EncodeUploadRequest(bool auto_fill_used,
// personaldata_manager_->GetDataPresent();
autofil_request_xml.SetAttr(buzz::QName(kAttributeDataPresent), "");
- EncodeFormRequest(FormStructure::UPLOAD, &autofil_request_xml);
+ if (!EncodeFormRequest(FormStructure::UPLOAD, &autofil_request_xml))
+ return false; // Malformed form, skip it.
// Obtain the XML structure as a string.
*encoded_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
@@ -140,7 +143,13 @@ bool FormStructure::EncodeUploadRequest(bool auto_fill_used,
// static
bool FormStructure::EncodeQueryRequest(const ScopedVector<FormStructure>& forms,
- std::string* encoded_xml) {
+ std::vector<std::string>* encoded_signatures,
+ std::string* encoded_xml) {
+ DCHECK(encoded_signatures);
+ DCHECK(encoded_xml);
+ encoded_xml->clear();
+ encoded_signatures->clear();
+ encoded_signatures->reserve(forms.size());
buzz::XmlElement autofil_request_xml(buzz::QName("autofillquery"));
// Attributes for the <autofillquery> element.
//
@@ -148,19 +157,32 @@ bool FormStructure::EncodeQueryRequest(const ScopedVector<FormStructure>& forms,
// For now these values are hacked from the toolbar code.
autofil_request_xml.SetAttr(buzz::QName(kAttributeClientVersion),
"6.1.1715.1442/en (GGLL)");
+ // Some badly formatted web sites repeat forms - detect that and encode only
+ // one form as returned data would be the same for all the repeated forms.
+ std::set<std::string> processed_forms;
for (ScopedVector<FormStructure>::const_iterator it = forms.begin();
it != forms.end();
++it) {
+ std::string signature((*it)->FormSignature());
+ if (processed_forms.find(signature) != processed_forms.end())
+ continue;
+ processed_forms.insert(signature);
buzz::XmlElement* encompassing_xml_element =
new buzz::XmlElement(buzz::QName("form"));
encompassing_xml_element->SetAttr(buzz::QName(kAttributeSignature),
- (*it)->FormSignature());
+ signature);
- (*it)->EncodeFormRequest(FormStructure::QUERY, encompassing_xml_element);
+ if (!(*it)->EncodeFormRequest(FormStructure::QUERY,
+ encompassing_xml_element))
+ continue; // Malformed form, skip it.
autofil_request_xml.AddElement(encompassing_xml_element);
+ encoded_signatures->push_back(signature);
}
+ if (!encoded_signatures->size())
+ return false;
+
// Obtain the XML structure as a string.
*encoded_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
*encoded_xml += autofil_request_xml.Str().c_str();
@@ -392,8 +414,16 @@ bool FormStructure::EncodeFormRequest(
buzz::XmlElement* encompassing_xml_element) const {
if (!field_count()) // Nothing to add.
return false;
+ // Some badly formatted web sites repeat fields - limit number of fields to
+ // 48, which is far larger than any valid form and XML still fits into 2K.
+ const size_t kMaxFieldsOnTheForm = 48;
+ if (field_count() > kMaxFieldsOnTheForm) {
+ // This is not a valid form, most certainly. Do not send request for the
+ // wrongly formatted forms.
+ return false;
+ }
// Add the child nodes for the form fields.
- for (size_t index = 0; index < field_count(); index++) {
+ for (size_t index = 0; index < field_count(); ++index) {
const AutoFillField* field = fields_[index];
if (request_type == FormStructure::UPLOAD) {
FieldTypeSet types = field->possible_types();
diff --git a/chrome/browser/autofill/form_structure.h b/chrome/browser/autofill/form_structure.h
index 7000056..77e106f4 100644
--- a/chrome/browser/autofill/form_structure.h
+++ b/chrome/browser/autofill/form_structure.h
@@ -48,6 +48,7 @@ class FormStructure {
// fields, first two of which would be for the first form, next 4 for the
// second, and the rest is for the third.
static bool EncodeQueryRequest(const ScopedVector<FormStructure>& forms,
+ std::vector<std::string>* encoded_signatures,
std::string* encoded_xml);
// Parses the field types from the server query response. |forms| must be the
diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc
index 73317a3..b5881d6 100644
--- a/chrome/browser/autofill/form_structure_unittest.cc
+++ b/chrome/browser/autofill/form_structure_unittest.cc
@@ -1285,4 +1285,264 @@ TEST(FormStructureTest, HeuristicsInfernoCC) {
form_structure->field(4)->heuristic_type());
}
+TEST(FormStructureTest, EncodeQueryRequest) {
+ FormData form;
+ form.method = ASCIIToUTF16("post");
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Name on Card"),
+ ASCIIToUTF16("name_on_card"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
+ ASCIIToUTF16("billing_address"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Card Number"),
+ ASCIIToUTF16("card_number"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration Date"),
+ ASCIIToUTF16("expiration_month"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Expiration Year"),
+ ASCIIToUTF16("expiration_year"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ ScopedVector<FormStructure> forms;
+ forms.push_back(new FormStructure(form));
+ std::vector<std::string> encoded_signatures;
+ std::string encoded_xml;
+ const char * const kSignature1 = "11337937696949187602";
+ const char * const kResponse1 =
+ "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillquery "
+ "clientversion=\"6.1.1715.1442/en (GGLL)\"><form signature=\""
+ "11337937696949187602\"><field signature=\"412125936\"/><field "
+ "signature=\"1917667676\"/><field signature=\"2226358947\"/><field "
+ "signature=\"747221617\"/><field signature=\"4108155786\"/></form>"
+ "</autofillquery>";
+ ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
+ &encoded_xml));
+ ASSERT_EQ(encoded_signatures.size(), 1U);
+ EXPECT_EQ(encoded_signatures[0], kSignature1);
+ EXPECT_EQ(encoded_xml, kResponse1);
+
+ // Add the same form, only one will be encoded, so EncodeQueryRequest() should
+ // return the same data.
+ forms.push_back(new FormStructure(form));
+ ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
+ &encoded_xml));
+ ASSERT_EQ(encoded_signatures.size(), 1U);
+ EXPECT_EQ(encoded_signatures[0], kSignature1);
+ EXPECT_EQ(encoded_xml, kResponse1);
+ // Add 5 address fields - this should be still a valid form.
+ for (size_t i = 0; i < 5; ++i) {
+ form.fields.push_back(
+ webkit_glue::FormField(ASCIIToUTF16("Address"),
+ ASCIIToUTF16("address"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ }
+
+ forms.push_back(new FormStructure(form));
+ ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
+ &encoded_xml));
+ ASSERT_EQ(encoded_signatures.size(), 2U);
+ EXPECT_EQ(encoded_signatures[0], kSignature1);
+ const char * const kSignature2 = "8308881815906226214";
+ EXPECT_EQ(encoded_signatures[1], kSignature2);
+ const char * const kResponse2 =
+ "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillquery "
+ "clientversion=\"6.1.1715.1442/en (GGLL)\"><form signature=\""
+ "11337937696949187602\"><field signature=\"412125936\"/><field signature="
+ "\"1917667676\"/><field signature=\"2226358947\"/><field signature=\""
+ "747221617\"/><field signature=\"4108155786\"/></form><form signature=\""
+ "8308881815906226214\"><field signature=\"412125936\"/><field signature="
+ "\"1917667676\"/><field signature=\"2226358947\"/><field signature=\""
+ "747221617\"/><field signature=\"4108155786\"/><field signature=\""
+ "509334676\"/><field signature=\"509334676\"/><field signature=\""
+ "509334676\"/><field signature=\"509334676\"/><field signature=\""
+ "509334676\"/></form></autofillquery>";
+ EXPECT_EQ(encoded_xml, kResponse2);
+
+ // Add 50 address fields - the form is not valid anymore, but previous ones
+ // are. The result should be the same as in previous test.
+ for (size_t i = 0; i < 50; ++i) {
+ form.fields.push_back(
+ webkit_glue::FormField(ASCIIToUTF16("Address"),
+ ASCIIToUTF16("address"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ }
+
+ forms.push_back(new FormStructure(form));
+ ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms, &encoded_signatures,
+ &encoded_xml));
+ ASSERT_EQ(encoded_signatures.size(), 2U);
+ EXPECT_EQ(encoded_signatures[0], kSignature1);
+ EXPECT_EQ(encoded_signatures[1], kSignature2);
+ EXPECT_EQ(encoded_xml, kResponse2);
+
+ // Check that we fail if there are only bad form(s).
+ ScopedVector<FormStructure> bad_forms;
+ bad_forms.push_back(new FormStructure(form));
+ EXPECT_FALSE(FormStructure::EncodeQueryRequest(bad_forms, &encoded_signatures,
+ &encoded_xml));
+ EXPECT_EQ(encoded_signatures.size(), 0U);
+ EXPECT_EQ(encoded_xml, "");
+}
+
+TEST(FormStructureTest, EncodeUploadRequest) {
+ scoped_ptr<FormStructure> form_structure;
+ std::vector<FieldTypeSet> possible_field_types;
+ FormData form;
+ form.method = ASCIIToUTF16("post");
+ form_structure.reset(new FormStructure(form));
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("First Name"),
+ ASCIIToUTF16("firstname"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(NAME_FIRST);
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Last Name"),
+ ASCIIToUTF16("lastname"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(NAME_LAST);
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("EMail"),
+ ASCIIToUTF16("email"),
+ string16(),
+ ASCIIToUTF16("email"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(EMAIL_ADDRESS);
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Phone"),
+ ASCIIToUTF16("phone"),
+ string16(),
+ ASCIIToUTF16("number"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(PHONE_HOME_WHOLE_NUMBER);
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Country"),
+ ASCIIToUTF16("country"),
+ string16(),
+ ASCIIToUTF16("select-one"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(ADDRESS_HOME_COUNTRY);
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Fax"),
+ ASCIIToUTF16("fax"),
+ string16(),
+ ASCIIToUTF16("tel"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(PHONE_FAX_WHOLE_NUMBER);
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
+ ASCIIToUTF16("address"),
+ string16(),
+ ASCIIToUTF16("radio"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(ADDRESS_HOME_LINE1);
+ form_structure.reset(new FormStructure(form));
+ std::string encoded_xml;
+ ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
+ for (size_t i = 0; i < form_structure->field_count(); ++i)
+ form_structure->set_possible_types(i, possible_field_types[i]);
+ EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+ EXPECT_EQ(encoded_xml,
+ "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+ "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+ "8269229441054798720\" autofillused=\"false\" datapresent=\"\"><field "
+ "signature=\"3763331450\" autofilltype=\"3\"/><field signature=\""
+ "3494530716\" autofilltype=\"5\"/><field signature=\"1029417091\" "
+ "autofilltype=\"9\"/><field signature=\"466116101\" autofilltype="
+ "\"14\"/><field signature=\"2799270304\" autofilltype=\"36\"/><field "
+ "signature=\"1876771436\" autofilltype=\"24\"/><field signature="
+ "\"263446779\" autofilltype=\"30\"/></autofillupload>");
+ EXPECT_TRUE(form_structure->EncodeUploadRequest(true, &encoded_xml));
+ EXPECT_EQ(encoded_xml,
+ "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+ "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+ "8269229441054798720\" autofillused=\"true\" datapresent=\"\"><field "
+ "signature=\"3763331450\" autofilltype=\"3\"/><field signature=\""
+ "3494530716\" autofilltype=\"5\"/><field signature=\"1029417091\" "
+ "autofilltype=\"9\"/><field signature=\"466116101\" autofilltype="
+ "\"14\"/><field signature=\"2799270304\" autofilltype=\"36\"/><field "
+ "signature=\"1876771436\" autofilltype=\"24\"/><field signature="
+ "\"263446779\" autofilltype=\"30\"/></autofillupload>");
+ // Add 5 address fields - this should be still a valid form.
+ for (size_t i = 0; i < 5; ++i) {
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
+ ASCIIToUTF16("address"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(ADDRESS_HOME_LINE1);
+ possible_field_types.back().insert(ADDRESS_HOME_LINE2);
+ possible_field_types.back().insert(ADDRESS_BILLING_LINE1);
+ possible_field_types.back().insert(ADDRESS_BILLING_LINE2);
+ }
+ form_structure.reset(new FormStructure(form));
+ ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
+ for (size_t i = 0; i < form_structure->field_count(); ++i)
+ form_structure->set_possible_types(i, possible_field_types[i]);
+ EXPECT_TRUE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+ EXPECT_EQ(encoded_xml,
+ "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><autofillupload "
+ "clientversion=\"6.1.1715.1442/en (GGLL)\" formsignature=\""
+ "2027360543766157144\" autofillused=\"false\" datapresent=\"\"><field "
+ "signature=\"3763331450\" autofilltype=\"3\"/><field signature=\""
+ "3494530716\" autofilltype=\"5\"/><field signature=\"1029417091\" "
+ "autofilltype=\"9\"/><field signature=\"466116101\" autofilltype=\"14\"/>"
+ "<field signature=\"2799270304\" autofilltype=\"36\"/><field signature=\""
+ "1876771436\" autofilltype=\"24\"/><field signature=\"263446779\" "
+ "autofilltype=\"30\"/><field signature=\"509334676\" autofilltype="
+ "\"30\"/><field signature=\"509334676\" autofilltype=\"31\"/><field "
+ "signature=\"509334676\" autofilltype=\"37\"/><field signature="
+ "\"509334676\" autofilltype=\"38\"/><field signature=\"509334676\" "
+ "autofilltype=\"30\"/><field signature=\"509334676\" autofilltype="
+ "\"31\"/><field signature=\"509334676\" autofilltype=\"37\"/><field "
+ "signature=\"509334676\" autofilltype=\"38\"/><field signature=\""
+ "509334676\" autofilltype=\"30\"/><field signature=\"509334676\" "
+ "autofilltype=\"31\"/><field signature=\"509334676\" "
+ "autofilltype=\"37\"/><field signature=\"509334676\" autofilltype="
+ "\"38\"/><field signature=\"509334676\" autofilltype=\"30\"/><field "
+ "signature=\"509334676\" autofilltype=\"31\"/><field signature="
+ "\"509334676\" autofilltype=\"37\"/><field signature=\"509334676\" "
+ "autofilltype=\"38\"/><field signature=\"509334676\" autofilltype="
+ "\"30\"/><field signature=\"509334676\" autofilltype=\"31\"/><field "
+ "signature=\"509334676\" autofilltype=\"37\"/><field signature="
+ "\"509334676\" autofilltype=\"38\"/></autofillupload>");
+ // Add 50 address fields - now the form is invalid.
+ for (size_t i = 0; i < 50; ++i) {
+ form.fields.push_back(webkit_glue::FormField(ASCIIToUTF16("Address"),
+ ASCIIToUTF16("address"),
+ string16(),
+ ASCIIToUTF16("text"),
+ 0));
+ possible_field_types.push_back(FieldTypeSet());
+ possible_field_types.back().insert(ADDRESS_HOME_LINE1);
+ possible_field_types.back().insert(ADDRESS_HOME_LINE2);
+ possible_field_types.back().insert(ADDRESS_BILLING_LINE1);
+ possible_field_types.back().insert(ADDRESS_BILLING_LINE2);
+ }
+ form_structure.reset(new FormStructure(form));
+ ASSERT_EQ(form_structure->field_count(), possible_field_types.size());
+ for (size_t i = 0; i < form_structure->field_count(); ++i)
+ form_structure->set_possible_types(i, possible_field_types[i]);
+ EXPECT_FALSE(form_structure->EncodeUploadRequest(false, &encoded_xml));
+ EXPECT_EQ(encoded_xml, "");
+}
+
} // namespace