diff options
81 files changed, 707 insertions, 148 deletions
diff --git a/chrome/browser/autofill/autofill_field.cc b/chrome/browser/autofill/autofill_field.cc index 7058c53..974af94 100644 --- a/chrome/browser/autofill/autofill_field.cc +++ b/chrome/browser/autofill/autofill_field.cc @@ -43,7 +43,8 @@ AutofillField::AutofillField(const FormFieldData& field, AutofillField::~AutofillField() {} void AutofillField::set_heuristic_type(AutofillFieldType type) { - if (type >= 0 && type < MAX_VALID_FIELD_TYPE) { + if (type >= 0 && type < MAX_VALID_FIELD_TYPE && + type != FIELD_WITH_DEFAULT_VALUE) { heuristic_type_ = type; } else { NOTREACHED(); diff --git a/chrome/browser/autofill/autofill_field.h b/chrome/browser/autofill/autofill_field.h index 0b21098..e688fad 100644 --- a/chrome/browser/autofill/autofill_field.h +++ b/chrome/browser/autofill/autofill_field.h @@ -56,6 +56,9 @@ class AutofillField : public FormFieldData { // field). bool IsFieldFillable() const; + void set_default_value(const std::string& value) { default_value_ = value; } + const std::string& default_value() const { return default_value_; } + private: // The unique name of this field, generated by Autofill. string16 unique_name_; @@ -76,6 +79,9 @@ class AutofillField : public FormFieldData { // Used to track whether this field is a phone prefix or suffix. PhonePart phone_part_; + // The default value returned by the Autofill server. + std::string default_value_; + DISALLOW_COPY_AND_ASSIGN(AutofillField); }; diff --git a/chrome/browser/autofill/autofill_manager.cc b/chrome/browser/autofill/autofill_manager.cc index 4bba52b..b6c37cd 100644 --- a/chrome/browser/autofill/autofill_manager.cc +++ b/chrome/browser/autofill/autofill_manager.cc @@ -656,6 +656,26 @@ void AutofillManager::OnFillAutofillFormData(int query_id, // Mark the cached field as autofilled, so that we can detect when a user // edits an autofilled field (for metrics). form_structure->field(i)->is_autofilled = true; + } else if (cached_field->type() == FIELD_WITH_DEFAULT_VALUE && + cached_field->is_checkable) { + // For a form with radio buttons, like: + // <form> + // <input type="radio" name="sex" value="male">Male<br> + // <input type="radio" name="sex" value="female">Female + // </form> + // If the default value specified at the server is "female", then + // Autofill server responds back with following field mappings + // (fieldtype: FIELD_WITH_DEFAULT_VALUE, value: "female") + // (fieldtype: FIELD_WITH_DEFAULT_VALUE, value: "female") + // Note that, the field mapping is repeated twice to respond to both the + // input elements with the same name/signature in the form. + string16 default_value = UTF8ToUTF16(cached_field->default_value()); + // Mark the field checked if server says the default value of the field + // to be this field's value. + result.fields[i].is_checked = (default_value == result.fields[i].value); + // Mark the cached field as autofilled, so that we can detect when a user + // edits an autofilled field (for metrics). + form_structure->field(i)->is_autofilled = true; } } diff --git a/chrome/browser/autofill/autofill_manager_unittest.cc b/chrome/browser/autofill/autofill_manager_unittest.cc index cedc7a5..2b7100b 100644 --- a/chrome/browser/autofill/autofill_manager_unittest.cc +++ b/chrome/browser/autofill/autofill_manager_unittest.cc @@ -671,6 +671,10 @@ class AutofillManagerTest : public ChromeRenderViewHostTestHarness { autofill_manager_->OnFormsSeen(forms, base::TimeTicks()); } + void LoadServerPredictions(const std::string& response_xml) { + autofill_manager_->OnLoadedServerPredictions(response_xml); + } + void FormSubmitted(const FormData& form) { if (autofill_manager_->OnFormSubmitted(form, base::TimeTicks::Now())) autofill_manager_->WaitForAsyncFormSubmit(); @@ -1820,6 +1824,56 @@ TEST_F(AutofillManagerTest, FillCreditCardForm) { ExpectFilledCreditCardFormElvis(page_id, results, kDefaultPageID, false); } +TEST_F(AutofillManagerTest, FillCheckableElements) { + FormData form; + CreateTestAddressFormData(&form); + + // Add a checkbox field. + FormFieldData field; + autofill_test::CreateTestFormField( + "Checkbox", "checkbx", "fill-me", "checkbox", &field); + field.is_checkable = true; + form.fields.push_back(field); + autofill_test::CreateTestFormField( + "Checkbox", "checkbx", "fill-me", "checkbox", &field); + field.is_checkable = true; + form.fields.push_back(field); + + std::vector<FormData> forms(1, form); + FormsSeen(forms); + + // Replicate server response with XML. + const std::string response_xml = + "<autofillqueryresponse>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"0\"/>" + "<field autofilltype=\"61\" defaultvalue=\"fill-me\"/>" + "<field autofilltype=\"61\" defaultvalue=\"dont-fill-me\"/>" + "</autofillqueryresponse>"; + LoadServerPredictions(response_xml); + + GUIDPair guid("00000000-0000-0000-0000-000000000001", 0); + GUIDPair empty(std::string(), 0); + FillAutofillFormData(kDefaultPageID, form, form.fields[0], + PackGUIDs(empty, guid)); + int page_id = 0; + FormData results; + EXPECT_TRUE(GetAutofillFormDataFilledMessage(&page_id, &results)); + // Second to last field should be checked. + EXPECT_TRUE(results.fields[results.fields.size()-2].is_checked); + // Last field shouldn't be checked as values are not same. + EXPECT_FALSE(results.fields[results.fields.size()-1].is_checked); +} + // Test that we correctly fill a credit card form with month input type. // 1. year empty, month empty TEST_F(AutofillManagerTest, FillCreditCardFormNoYearNoMonth) { diff --git a/chrome/browser/autofill/autofill_server_field_info.h b/chrome/browser/autofill/autofill_server_field_info.h new file mode 100644 index 0000000..e07ec26 --- /dev/null +++ b/chrome/browser/autofill/autofill_server_field_info.h @@ -0,0 +1,20 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_AUTOFILL_AUTOFILL_SERVER_FIELD_INFO_H_ +#define CHROME_BROWSER_AUTOFILL_AUTOFILL_SERVER_FIELD_INFO_H_ + +#include <string> + +#include "chrome/browser/autofill/field_types.h" + +struct AutofillServerFieldInfo { + // The predicted type returned by the Autofill server for this field. + AutofillFieldType field_type; + // Default value to be used for the field (only applies to + // FIELD_WITH_DEFAULT_TYPE field type) + std::string default_value; +}; + +#endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_SERVER_FIELD_INFO_H_ diff --git a/chrome/browser/autofill/autofill_xml_parser.cc b/chrome/browser/autofill/autofill_xml_parser.cc index 92a1ede..1fdda9e 100644 --- a/chrome/browser/autofill/autofill_xml_parser.cc +++ b/chrome/browser/autofill/autofill_xml_parser.cc @@ -8,6 +8,7 @@ #include <string.h> #include "base/logging.h" +#include "chrome/browser/autofill/autofill_server_field_info.h" #include "third_party/libjingle/source/talk/xmllite/qname.h" AutofillXmlParser::AutofillXmlParser() @@ -28,10 +29,10 @@ void AutofillXmlParser::Error(buzz::XmlParseContext* context, } AutofillQueryXmlParser::AutofillQueryXmlParser( - std::vector<AutofillFieldType>* field_types, + std::vector<AutofillServerFieldInfo>* field_infos, UploadRequired* upload_required, std::string* experiment_id) - : field_types_(field_types), + : field_infos_(field_infos), upload_required_(upload_required), experiment_id_(experiment_id) { DCHECK(upload_required_); @@ -52,22 +53,21 @@ void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context, // |attrs| is a NULL-terminated list of (attribute, value) pairs. while (*attrs) { - buzz::QName attribute_qname = context->ResolveQName(attrs[0], true); + buzz::QName attribute_qname = context->ResolveQName(*attrs, true); + ++attrs; const std::string& attribute_name = attribute_qname.LocalPart(); if (attribute_name.compare("uploadrequired") == 0) { - if (strcmp(attrs[1], "true") == 0) + if (strcmp(*attrs, "true") == 0) *upload_required_ = UPLOAD_REQUIRED; - else if (strcmp(attrs[1], "false") == 0) + else if (strcmp(*attrs, "false") == 0) *upload_required_ = UPLOAD_NOT_REQUIRED; } else if (attribute_name.compare("experimentid") == 0) { - *experiment_id_ = attrs[1]; + *experiment_id_ = *attrs; } - - // Advance to the next (attribute, value) pair. - attrs += 2; + ++attrs; } } else if (element.compare("field") == 0) { - if (!attrs[0]) { + if (!*attrs) { // Missing the "autofilltype" attribute, abort. context->RaiseError(XML_ERROR_ABORTED); return; @@ -75,20 +75,29 @@ void AutofillQueryXmlParser::StartElement(buzz::XmlParseContext* context, // Determine the field type from the attribute value. There should be one // attribute (autofilltype) with an integer value. - AutofillFieldType field_type = UNKNOWN_TYPE; - buzz::QName attribute_qname = context->ResolveQName(attrs[0], true); - const std::string& attribute_name = attribute_qname.LocalPart(); - - if (attribute_name.compare("autofilltype") == 0) { - int value = GetIntValue(context, attrs[1]); - field_type = static_cast<AutofillFieldType>(value); - if (field_type < 0 || field_type > MAX_VALID_FIELD_TYPE) { - field_type = NO_SERVER_DATA; + AutofillServerFieldInfo field_info; + field_info.field_type = UNKNOWN_TYPE; + + // |attrs| is a NULL-terminated list of (attribute, value) pairs. + while (*attrs) { + buzz::QName attribute_qname = context->ResolveQName(*attrs, true); + ++attrs; + const std::string& attribute_name = attribute_qname.LocalPart(); + if (attribute_name.compare("autofilltype") == 0) { + int value = GetIntValue(context, *attrs); + if (value >= 0 && value < MAX_VALID_FIELD_TYPE) + field_info.field_type = static_cast<AutofillFieldType>(value); + else + field_info.field_type = NO_SERVER_DATA; + } else if (field_info.field_type == FIELD_WITH_DEFAULT_VALUE && + attribute_name.compare("defaultvalue") == 0) { + field_info.default_value = *attrs; } + ++attrs; } - // Record this field type. - field_types_->push_back(field_type); + // Record this field type, default value pair. + field_infos_->push_back(field_info); } } diff --git a/chrome/browser/autofill/autofill_xml_parser.h b/chrome/browser/autofill/autofill_xml_parser.h index da3d5bf..5ae9774 100644 --- a/chrome/browser/autofill/autofill_xml_parser.h +++ b/chrome/browser/autofill/autofill_xml_parser.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "chrome/browser/autofill/autofill_server_field_info.h" #include "chrome/browser/autofill/field_types.h" #include "chrome/browser/autofill/form_structure.h" #include "third_party/libjingle/source/talk/xmllite/xmlparser.h" @@ -66,7 +67,7 @@ class AutofillXmlParser : public buzz::XmlParseHandler { // unknown, other types are documented in chrome/browser/autofill/field_types.h. class AutofillQueryXmlParser : public AutofillXmlParser { public: - AutofillQueryXmlParser(std::vector<AutofillFieldType>* field_types, + AutofillQueryXmlParser(std::vector<AutofillServerFieldInfo>* field_infos, UploadRequired* upload_required, std::string* experiment_id); @@ -85,8 +86,8 @@ class AutofillQueryXmlParser : public AutofillXmlParser { // |value| is the string to convert. int GetIntValue(buzz::XmlParseContext* context, const char* attribute); - // The parsed field types. - std::vector<AutofillFieldType>* field_types_; + // The parsed <field type, default value> pairs. + std::vector<AutofillServerFieldInfo>* field_infos_; // A flag indicating whether the client should upload Autofill data when this // form is submitted. diff --git a/chrome/browser/autofill/autofill_xml_parser_unittest.cc b/chrome/browser/autofill/autofill_xml_parser_unittest.cc index a0a1024..2363862 100644 --- a/chrome/browser/autofill/autofill_xml_parser_unittest.cc +++ b/chrome/browser/autofill/autofill_xml_parser_unittest.cc @@ -6,6 +6,7 @@ #include <vector> #include "base/memory/scoped_ptr.h" +#include "base/string_number_conversions.h" #include "chrome/browser/autofill/autofill_xml_parser.h" #include "chrome/browser/autofill/field_types.h" #include "testing/gtest/include/gtest/gtest.h" @@ -20,31 +21,36 @@ TEST(AutofillQueryXmlParserTest, BasicQuery) { "<field autofilltype=\"1\" />" "<field autofilltype=\"3\" />" "<field autofilltype=\"2\" />" + "<field autofilltype=\"61\" defaultvalue=\"default\"/>" "</autofillqueryresponse>"; - // Create a vector of AutofillFieldTypes, to assign the parsed field types to. - std::vector<AutofillFieldType> field_types; + // Create a vector of AutofillServerFieldInfos, to assign the parsed field + // types to. + std::vector<AutofillServerFieldInfo> field_infos; UploadRequired upload_required = USE_UPLOAD_RATES; std::string experiment_id; // Create a parser. - AutofillQueryXmlParser parse_handler(&field_types, &upload_required, + AutofillQueryXmlParser parse_handler(&field_infos, &upload_required, &experiment_id); buzz::XmlParser parser(&parse_handler); parser.Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler.succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - ASSERT_EQ(4U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); - EXPECT_EQ(UNKNOWN_TYPE, field_types[1]); - EXPECT_EQ(NAME_FIRST, field_types[2]); - EXPECT_EQ(EMPTY_TYPE, field_types[3]); + ASSERT_EQ(5U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); + EXPECT_EQ(UNKNOWN_TYPE, field_infos[1].field_type); + EXPECT_EQ(NAME_FIRST, field_infos[2].field_type); + EXPECT_EQ(EMPTY_TYPE, field_infos[3].field_type); + EXPECT_EQ("", field_infos[3].default_value); + EXPECT_EQ(FIELD_WITH_DEFAULT_VALUE, field_infos[4].field_type); + EXPECT_EQ("default", field_infos[4].default_value); EXPECT_EQ(std::string(), experiment_id); } // Test parsing the upload required attribute. TEST(AutofillQueryXmlParserTest, TestUploadRequired) { - std::vector<AutofillFieldType> field_types; + std::vector<AutofillServerFieldInfo> field_infos; UploadRequired upload_required = USE_UPLOAD_RATES; std::string experiment_id; @@ -53,50 +59,50 @@ TEST(AutofillQueryXmlParserTest, TestUploadRequired) { "</autofillqueryresponse>"; scoped_ptr<AutofillQueryXmlParser> parse_handler( - new AutofillQueryXmlParser(&field_types, &upload_required, + new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(UPLOAD_REQUIRED, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string(), experiment_id); - field_types.clear(); + field_infos.clear(); xml = "<autofillqueryresponse uploadrequired=\"false\">" "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - parse_handler.reset(new AutofillQueryXmlParser(&field_types, &upload_required, + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); parser.reset(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string(), experiment_id); - field_types.clear(); + field_infos.clear(); xml = "<autofillqueryresponse uploadrequired=\"bad_value\">" "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - parse_handler.reset(new AutofillQueryXmlParser(&field_types, &upload_required, + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); parser.reset(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string(), experiment_id); } // Test parsing the experiment id attribute TEST(AutofillQueryXmlParserTest, ParseExperimentId) { - std::vector<AutofillFieldType> field_types; + std::vector<AutofillServerFieldInfo> field_infos; UploadRequired upload_required = USE_UPLOAD_RATES; std::string experiment_id; @@ -107,34 +113,34 @@ TEST(AutofillQueryXmlParserTest, ParseExperimentId) { "</autofillqueryresponse>"; scoped_ptr<AutofillQueryXmlParser> parse_handler( - new AutofillQueryXmlParser(&field_types, &upload_required, + new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string(), experiment_id); - field_types.clear(); + field_infos.clear(); // When the attribute is present, make sure we parse it. xml = "<autofillqueryresponse experimentid=\"FancyNewAlgorithm\">" "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - parse_handler.reset(new AutofillQueryXmlParser(&field_types, &upload_required, + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); parser.reset(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string("FancyNewAlgorithm"), experiment_id); - field_types.clear(); + field_infos.clear(); // Make sure that we can handle parsing both the upload required and the // experiment id attribute together. @@ -143,20 +149,20 @@ TEST(AutofillQueryXmlParserTest, ParseExperimentId) { "<field autofilltype=\"0\" />" "</autofillqueryresponse>"; - parse_handler.reset(new AutofillQueryXmlParser(&field_types, &upload_required, + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); parser.reset(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(UPLOAD_NOT_REQUIRED, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string("ServerSmartyPants"), experiment_id); } // Test badly formed XML queries. TEST(AutofillQueryXmlParserTest, ParseErrors) { - std::vector<AutofillFieldType> field_types; + std::vector<AutofillServerFieldInfo> field_infos; UploadRequired upload_required = USE_UPLOAD_RATES; std::string experiment_id; @@ -166,46 +172,62 @@ TEST(AutofillQueryXmlParserTest, ParseErrors) { "</autofillqueryresponse>"; scoped_ptr<AutofillQueryXmlParser> parse_handler( - new AutofillQueryXmlParser(&field_types, &upload_required, + new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); scoped_ptr<buzz::XmlParser> parser(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_FALSE(parse_handler->succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - EXPECT_EQ(0U, field_types.size()); + EXPECT_EQ(0U, field_infos.size()); EXPECT_EQ(std::string(), experiment_id); // Test an incorrect Autofill type. xml = "<autofillqueryresponse>" - "<field autofilltype=\"307\"/>" + "<field autofilltype=\"-1\"/>" "</autofillqueryresponse>"; - parse_handler.reset(new AutofillQueryXmlParser(&field_types, &upload_required, + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); parser.reset(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_TRUE(parse_handler->succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - ASSERT_EQ(1U, field_types.size()); + ASSERT_EQ(1U, field_infos.size()); // AutofillType was out of range and should be set to NO_SERVER_DATA. - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); + EXPECT_EQ(std::string(), experiment_id); + + // Test upper bound for the field type, MAX_VALID_FIELD_TYPE. + field_infos.clear(); + xml = "<autofillqueryresponse><field autofilltype=\"" + + base::IntToString(MAX_VALID_FIELD_TYPE) + "\"/></autofillqueryresponse>"; + + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, + &experiment_id)); + parser.reset(new buzz::XmlParser(parse_handler.get())); + parser->Parse(xml.c_str(), xml.length(), true); + EXPECT_TRUE(parse_handler->succeeded()); + EXPECT_EQ(USE_UPLOAD_RATES, upload_required); + ASSERT_EQ(1U, field_infos.size()); + // AutofillType was out of range and should be set to NO_SERVER_DATA. + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string(), experiment_id); // Test an incorrect Autofill type. - field_types.clear(); + field_infos.clear(); xml = "<autofillqueryresponse>" "<field autofilltype=\"No Type\"/>" "</autofillqueryresponse>"; - // Parse fails but an entry is still added to field_types. - parse_handler.reset(new AutofillQueryXmlParser(&field_types, &upload_required, + // Parse fails but an entry is still added to field_infos. + parse_handler.reset(new AutofillQueryXmlParser(&field_infos, &upload_required, &experiment_id)); parser.reset(new buzz::XmlParser(parse_handler.get())); parser->Parse(xml.c_str(), xml.length(), true); EXPECT_FALSE(parse_handler->succeeded()); EXPECT_EQ(USE_UPLOAD_RATES, upload_required); - ASSERT_EQ(1U, field_types.size()); - EXPECT_EQ(NO_SERVER_DATA, field_types[0]); + ASSERT_EQ(1U, field_infos.size()); + EXPECT_EQ(NO_SERVER_DATA, field_infos[0].field_type); EXPECT_EQ(std::string(), experiment_id); } diff --git a/chrome/browser/autofill/field_types.h b/chrome/browser/autofill/field_types.h index 832b94a..d45f1aa 100644 --- a/chrome/browser/autofill/field_types.h +++ b/chrome/browser/autofill/field_types.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_AUTOFILL_FIELD_TYPES_H_ #include <set> +#include <string> // NOTE: This list MUST not be modified. The server aggregates and stores these // types over several versions, so we must remain fully compatible with the @@ -77,9 +78,12 @@ enum AutofillFieldType { COMPANY_NAME = 60, + // Generic type whose default value is known. + FIELD_WITH_DEFAULT_VALUE = 61, + // No new types can be added. - MAX_VALID_FIELD_TYPE = 61, + MAX_VALID_FIELD_TYPE = 62, }; typedef std::set<AutofillFieldType> FieldTypeSet; diff --git a/chrome/browser/autofill/form_field.cc b/chrome/browser/autofill/form_field.cc index b8f941b..e722c5f 100644 --- a/chrome/browser/autofill/form_field.cc +++ b/chrome/browser/autofill/form_field.cc @@ -45,6 +45,10 @@ bool IsSelectField(const std::string& type) { return type == "select-one"; } +bool IsCheckable(const AutofillField* field) { + return field->is_checkable; +} + } // namespace // static @@ -54,6 +58,14 @@ void FormField::ParseFormFields(const std::vector<AutofillField*>& fields, std::vector<const AutofillField*> remaining_fields(fields.size()); std::copy(fields.begin(), fields.end(), remaining_fields.begin()); + // Ignore checkable fields as they interfere with parsers assuming context. + // Eg., while parsing address, "Is PO box" checkbox after ADDRESS_LINE1 + // interferes with correctly understanding ADDRESS_LINE2. + remaining_fields.erase( + std::remove_if(remaining_fields.begin(), remaining_fields.end(), + IsCheckable), + remaining_fields.end()); + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); bool parse_new_field_types = command_line.HasSwitch(switches::kEnableNewAutofillHeuristics); diff --git a/chrome/browser/autofill/form_field_unittest.cc b/chrome/browser/autofill/form_field_unittest.cc index 16b51a0..8ab1127 100644 --- a/chrome/browser/autofill/form_field_unittest.cc +++ b/chrome/browser/autofill/form_field_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_vector.h" #include "base/string16.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_field.h" @@ -114,3 +115,32 @@ TEST(FormFieldTest, Match) { EXPECT_FALSE(FormField::Match(&field, ASCIIToUTF16("\\bcr\\b"), FormField::MATCH_LABEL)); } + +// Test that we ignore checkable elements. +TEST(FormFieldTest, ParseFormFields) { + ScopedVector<AutofillField> fields; + FormFieldData field_data; + field_data.form_control_type = "text"; + + field_data.label = ASCIIToUTF16("Address line1"); + fields.push_back(new AutofillField(field_data, field_data.label)); + + field_data.is_checkable = true; + field_data.label = ASCIIToUTF16("Is PO Box"); + fields.push_back(new AutofillField(field_data, field_data.label)); + + // reset is_checkable to false. + field_data.is_checkable = false; + field_data.label = ASCIIToUTF16("Address line2"); + fields.push_back(new AutofillField(field_data, field_data.label)); + + FieldTypeMap field_type_map; + FormField::ParseFormFields(fields.get(), &field_type_map); + // Checkable element shouldn't interfere with inference of Address line2. + EXPECT_EQ(2U, field_type_map.size()); + + EXPECT_EQ(ADDRESS_HOME_LINE1, + field_type_map.find(ASCIIToUTF16("Address line1"))->second); + EXPECT_EQ(ADDRESS_HOME_LINE2, + field_type_map.find(ASCIIToUTF16("Address line2"))->second); +} diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc index d1ca6d1..81666e2 100644 --- a/chrome/browser/autofill/form_structure.cc +++ b/chrome/browser/autofill/form_structure.cc @@ -227,18 +227,28 @@ FormStructure::FormStructure(const FormData& form) source_url_(form.origin), target_url_(form.action), autofill_count_(0), + checkable_field_count_(0), upload_required_(USE_UPLOAD_RATES), server_experiment_id_("no server response"), - has_author_specified_types_(false) { + has_author_specified_types_(false), + experimental_form_filling_enabled_( + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExperimentalFormFilling)) { + // Copy the form fields. std::map<string16, size_t> unique_names; for (std::vector<FormFieldData>::const_iterator field = form.fields.begin(); field != form.fields.end(); field++) { - // Add all supported form fields (including with empty names) to the - // signature. This is a requirement for Autofill servers. - form_signature_field_names_.append("&"); - form_signature_field_names_.append(UTF16ToUTF8(field->name)); + // Skipping checkable elements when flag is not set, else these fields will + // interfere with existing field signatures with Autofill servers. + // TODO(ramankk): Add checkable elements only on whitelisted pages + if (!field->is_checkable || experimental_form_filling_enabled_) { + // Add all supported form fields (including with empty names) to the + // signature. This is a requirement for Autofill servers. + form_signature_field_names_.append("&"); + form_signature_field_names_.append(UTF16ToUTF8(field->name)); + } // Generate a unique name for this field by appending a counter to the name. // Make sure to prepend the counter with a non-numeric digit so that we are @@ -250,6 +260,9 @@ FormStructure::FormStructure(const FormData& form) string16 unique_name = field->name + ASCIIToUTF16("_") + base::IntToString16(unique_names[field->name]); fields_.push_back(new AutofillField(*field, unique_name)); + + if (field->is_checkable) + ++checkable_field_count_; } std::string method = UTF16ToUTF8(form.method); @@ -406,10 +419,10 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml, metric_logger.LogServerQueryMetric(AutofillMetrics::QUERY_RESPONSE_RECEIVED); // Parse the field types from the server response to the query. - std::vector<AutofillFieldType> field_types; + std::vector<AutofillServerFieldInfo> field_infos; UploadRequired upload_required; std::string experiment_id; - AutofillQueryXmlParser parse_handler(&field_types, &upload_required, + AutofillQueryXmlParser parse_handler(&field_infos, &upload_required, &experiment_id); buzz::XmlParser parser(&parse_handler); parser.Parse(response_xml.c_str(), response_xml.length(), true); @@ -423,7 +436,8 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml, bool query_response_overrode_heuristics = false; // Copy the field types into the actual form. - std::vector<AutofillFieldType>::iterator current_type = field_types.begin(); + std::vector<AutofillServerFieldInfo>::iterator current_info = + field_infos.begin(); for (std::vector<FormStructure*>::const_iterator iter = forms.begin(); iter != forms.end(); ++iter) { FormStructure* form = *iter; @@ -431,22 +445,26 @@ void FormStructure::ParseQueryResponse(const std::string& response_xml, form->server_experiment_id_ = experiment_id; for (std::vector<AutofillField*>::iterator field = form->fields_.begin(); - field != form->fields_.end(); ++field, ++current_type) { + field != form->fields_.end(); ++field, ++current_info) { // In some cases *successful* response does not return all the fields. // Quit the update of the types then. - if (current_type == field_types.end()) + if (current_info == field_infos.end()) break; // UNKNOWN_TYPE is reserved for use by the client. - DCHECK_NE(*current_type, UNKNOWN_TYPE); + DCHECK_NE(current_info->field_type, UNKNOWN_TYPE); AutofillFieldType heuristic_type = (*field)->type(); if (heuristic_type != UNKNOWN_TYPE) heuristics_detected_fillable_field = true; - (*field)->set_server_type(*current_type); + (*field)->set_server_type(current_info->field_type); if (heuristic_type != (*field)->type()) query_response_overrode_heuristics = true; + + // Copy default value into the field if available. + if (!current_info->default_value.empty()) + (*field)->set_default_value(current_info->default_value); } form->UpdateAutofillCount(); @@ -524,8 +542,7 @@ std::string FormStructure::FormSignature() const { bool FormStructure::IsAutofillable(bool require_method_post) const { // TODO(ramankk): Remove this check once we have better way of identifying the // cases to trigger experimental form filling. - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalFormFilling)) + if (experimental_form_filling_enabled_) return true; if (autofill_count() < kRequiredFillableFields) @@ -547,11 +564,13 @@ void FormStructure::UpdateAutofillCount() { bool FormStructure::ShouldBeParsed(bool require_method_post) const { // TODO(ramankk): Remove this check once we have better way of identifying the // cases to trigger experimental form filling. - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalFormFilling)) + if (experimental_form_filling_enabled_) return true; - if (field_count() < kRequiredFillableFields) + // Ignore counting checkable elements towards minimum number of elements + // required to parse. This avoids trying to crowdsource forms with few text + // or select elements. + if ((field_count() - checkable_field_count()) < kRequiredFillableFields) return false; // Rule out http(s)://*/search?... @@ -813,6 +832,10 @@ size_t FormStructure::field_count() const { return fields_.size(); } +size_t FormStructure::checkable_field_count() const { + return checkable_field_count_; +} + std::string FormStructure::server_experiment_id() const { return server_experiment_id_; } @@ -884,6 +907,10 @@ bool FormStructure::EncodeFormRequest( for (size_t index = 0; index < field_count(); ++index) { const AutofillField* field = fields_[index]; if (request_type == FormStructure::UPLOAD) { + // Don't upload checkable fields. + if (field->is_checkable) + continue; + FieldTypeSet types = field->possible_types(); // |types| could be empty in unit-tests only. for (FieldTypeSet::iterator field_type = types.begin(); @@ -898,6 +925,10 @@ bool FormStructure::EncodeFormRequest( encompassing_xml_element->AddElement(field_element); } } else { + // Skip putting checkable fields in the request if the flag is not set. + if (field->is_checkable && !experimental_form_filling_enabled_) + continue; + buzz::XmlElement *field_element = new buzz::XmlElement( buzz::QName(kXMLElementField)); field_element->SetAttr(buzz::QName(kAttributeSignature), diff --git a/chrome/browser/autofill/form_structure.h b/chrome/browser/autofill/form_structure.h index 45cf2bb..a83d9b0 100644 --- a/chrome/browser/autofill/form_structure.h +++ b/chrome/browser/autofill/form_structure.h @@ -127,6 +127,7 @@ class FormStructure { const AutofillField* field(size_t index) const; AutofillField* field(size_t index); size_t field_count() const; + size_t checkable_field_count() const; // Returns the number of fields that are able to be autofilled. size_t autofill_count() const { return autofill_count_; } @@ -192,6 +193,9 @@ class FormStructure { // A vector of all the input fields in the form. ScopedVector<AutofillField> fields_; + // The number of fields able to be checked. + size_t checkable_field_count_; + // The names of the form input elements, that are part of the form signature. // The string starts with "&" and the names are also separated by the "&" // character. E.g.: "&form_input1_name&form_input2_name&...&form_inputN_name" @@ -212,6 +216,9 @@ class FormStructure { // author, via the |autocompletetype| attribute. bool has_author_specified_types_; + // State of the kEnableExperimentalFormFilling flag. + bool experimental_form_filling_enabled_; + DISALLOW_COPY_AND_ASSIGN(FormStructure); }; diff --git a/chrome/browser/autofill/form_structure_unittest.cc b/chrome/browser/autofill/form_structure_unittest.cc index bd2bded..4dbc3ce 100644 --- a/chrome/browser/autofill/form_structure_unittest.cc +++ b/chrome/browser/autofill/form_structure_unittest.cc @@ -4,10 +4,12 @@ #include "chrome/browser/autofill/form_structure.h" +#include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/autofill/autofill_metrics.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/form_data.h" #include "chrome/common/form_field_data.h" #include "googleurl/src/gurl.h" @@ -215,6 +217,16 @@ TEST(FormStructureTest, ShouldBeParsed) { field.form_control_type = "text"; form.fields.push_back(field); + FormFieldData checkable_field; + checkable_field.is_checkable = true; + checkable_field.name = ASCIIToUTF16("radiobtn"); + checkable_field.form_control_type = "radio"; + form.fields.push_back(checkable_field); + + checkable_field.name = ASCIIToUTF16("checkbox"); + checkable_field.form_control_type = "checkbox"; + form.fields.push_back(checkable_field); + form_structure.reset(new FormStructure(form)); EXPECT_FALSE(form_structure->ShouldBeParsed(true)); @@ -1430,6 +1442,13 @@ TEST(FormStructureTest, EncodeQueryRequest) { field.name = ASCIIToUTF16("expiration_year"); form.fields.push_back(field); + // Add checkable field. + FormFieldData checkable_field; + checkable_field.is_checkable = true; + checkable_field.label = ASCIIToUTF16("Checkable1"); + checkable_field.name = ASCIIToUTF16("Checkable1"); + form.fields.push_back(checkable_field); + ScopedVector<FormStructure> forms; forms.push_back(new FormStructure(form)); std::vector<std::string> encoded_signatures; @@ -1487,15 +1506,16 @@ TEST(FormStructureTest, EncodeQueryRequest) { "signature=\"509334676\"/></form></autofillquery>"; EXPECT_EQ(kResponse2, encoded_xml); + FormData malformed_form(form); // 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) { field.label = ASCIIToUTF16("Address"); field.name = ASCIIToUTF16("address"); - form.fields.push_back(field); + malformed_form.fields.push_back(field); } - forms.push_back(new FormStructure(form)); + forms.push_back(new FormStructure(malformed_form)); ASSERT_TRUE(FormStructure::EncodeQueryRequest(forms.get(), &encoded_signatures, &encoded_xml)); @@ -1506,12 +1526,37 @@ TEST(FormStructureTest, EncodeQueryRequest) { // Check that we fail if there are only bad form(s). ScopedVector<FormStructure> bad_forms; - bad_forms.push_back(new FormStructure(form)); + bad_forms.push_back(new FormStructure(malformed_form)); EXPECT_FALSE(FormStructure::EncodeQueryRequest(bad_forms.get(), &encoded_signatures, &encoded_xml)); EXPECT_EQ(0U, encoded_signatures.size()); EXPECT_EQ("", encoded_xml); + + // Check the behaviour with kEnableExperimentalFormFilling switch on. + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalFormFilling); + // Add the previous form but with flag set. + ScopedVector<FormStructure> checkable_forms; + checkable_forms.push_back(new FormStructure(form)); + + ASSERT_TRUE(FormStructure::EncodeQueryRequest(checkable_forms.get(), + &encoded_signatures, + &encoded_xml)); + const char * const kSignature3 = "7747357776717901584"; + const char * const kResponse3 = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?><autofillquery " + "clientversion=\"6.1.1715.1442/en (GGLL)\" accepts=\"e\">" + "<form signature=\"7747357776717901584\"><field signature=\"412125936\"/>" + "<field signature=\"1917667676\"/><field signature=\"2226358947\"/><field" + " signature=\"747221617\"/><field signature=\"4108155786\"/><field " + "signature=\"3410250678\"/><field signature=\"509334676\"/><field " + "signature=\"509334676\"/><field signature=\"509334676\"/><field " + "signature=\"509334676\"/><field signature=\"509334676\"/></form>" + "</autofillquery>"; + ASSERT_EQ(1U, encoded_signatures.size()); + EXPECT_EQ(kSignature3, encoded_signatures[0]); + EXPECT_EQ(kResponse3, encoded_xml); } TEST(FormStructureTest, EncodeUploadRequest) { @@ -1557,6 +1602,16 @@ TEST(FormStructureTest, EncodeUploadRequest) { form.fields.push_back(field); possible_field_types.push_back(FieldTypeSet()); possible_field_types.back().insert(ADDRESS_HOME_COUNTRY); + + // Add checkable field. + FormFieldData checkable_field; + checkable_field.is_checkable = true; + checkable_field.label = ASCIIToUTF16("Checkable1"); + checkable_field.name = ASCIIToUTF16("Checkable1"); + form.fields.push_back(checkable_field); + possible_field_types.push_back(FieldTypeSet()); + possible_field_types.back().insert(ADDRESS_HOME_COUNTRY); + form_structure.reset(new FormStructure(form)); ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index db10520..0a4597a 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -206,6 +206,7 @@ 'browser/autofill/autofill_regexes.h', 'browser/autofill/autofill_scanner.cc', 'browser/autofill/autofill_scanner.h', + 'browser/autofill/autofill_server_field_info.h', 'browser/autofill/autofill_type.cc', 'browser/autofill/autofill_type.h', 'browser/autofill/autofill_xml_parser.cc', diff --git a/chrome/common/autofill_messages.h b/chrome/common/autofill_messages.h index ec032bf..d376883 100644 --- a/chrome/common/autofill_messages.h +++ b/chrome/common/autofill_messages.h @@ -32,6 +32,8 @@ IPC_STRUCT_TRAITS_BEGIN(FormFieldData) IPC_STRUCT_TRAITS_MEMBER(autocomplete_attribute) IPC_STRUCT_TRAITS_MEMBER(max_length) IPC_STRUCT_TRAITS_MEMBER(is_autofilled) + IPC_STRUCT_TRAITS_MEMBER(is_checked) + IPC_STRUCT_TRAITS_MEMBER(is_checkable) IPC_STRUCT_TRAITS_MEMBER(is_focusable) IPC_STRUCT_TRAITS_MEMBER(should_autocomplete) IPC_STRUCT_TRAITS_MEMBER(option_values) diff --git a/chrome/common/form_field_data.cc b/chrome/common/form_field_data.cc index 8ff3ce1..0a2205a 100644 --- a/chrome/common/form_field_data.cc +++ b/chrome/common/form_field_data.cc @@ -10,6 +10,8 @@ FormFieldData::FormFieldData() : max_length(0), is_autofilled(false), + is_checked(false), + is_checkable(false), is_focusable(false), should_autocomplete(false) { } @@ -54,6 +56,10 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field) { << " " << (field.is_autofilled ? "true" : "false") << " " + << (field.is_checked ? "true" : "false") + << " " + << (field.is_checkable ? "true" : "false") + << " " << (field.is_focusable ? "true" : "false") << " " << (field.should_autocomplete ? "true" : "false"); diff --git a/chrome/common/form_field_data.h b/chrome/common/form_field_data.h index 690e67a..e0179ee 100644 --- a/chrome/common/form_field_data.h +++ b/chrome/common/form_field_data.h @@ -30,6 +30,8 @@ struct FormFieldData { std::string autocomplete_attribute; size_t max_length; bool is_autofilled; + bool is_checked; + bool is_checkable; bool is_focusable; bool should_autocomplete; @@ -53,6 +55,8 @@ std::ostream& operator<<(std::ostream& os, const FormFieldData& field); EXPECT_EQ(expected.autocomplete_attribute, actual.autocomplete_attribute); \ EXPECT_EQ(expected.max_length, actual.max_length); \ EXPECT_EQ(expected.is_autofilled, actual.is_autofilled); \ + EXPECT_EQ(expected.is_checked, actual.is_checked); \ + EXPECT_EQ(expected.is_checkable, actual.is_checkable); \ } while (0) #endif // CHROME_COMMON_FORM_FIELD_DATA_H_ diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index 087dddc..7455dfd 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc @@ -214,6 +214,41 @@ TEST_F(FormAutofillTest, WebFormControlElementToFormFieldAutofilled) { EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); } +// We should be able to extract a radio or a checkbox field that has been +// autofilled. +TEST_F(FormAutofillTest, WebFormControlElementToClickableFormField) { + LoadHTML("<INPUT type=\"checkbox\" id=\"checkbox\" value=\"mail\"/>" + "<INPUT type=\"radio\" id=\"radio\" value=\"male\"/>"); + + WebFrame* frame = GetMainFrame(); + ASSERT_NE(static_cast<WebFrame*>(NULL), frame); + + WebElement web_element = frame->document().getElementById("checkbox"); + WebInputElement element = web_element.to<WebInputElement>(); + element.setAutofilled(true); + FormFieldData result; + WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result); + + FormFieldData expected; + expected.name = ASCIIToUTF16("checkbox"); + expected.value = ASCIIToUTF16("mail"); + expected.form_control_type = "checkbox"; + expected.is_autofilled = true; + expected.is_checkable = true; + EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); + + web_element = frame->document().getElementById("radio"); + element = web_element.to<WebInputElement>(); + element.setAutofilled(true); + WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result); + expected.name = ASCIIToUTF16("radio"); + expected.value = ASCIIToUTF16("male"); + expected.form_control_type = "radio"; + expected.is_autofilled = true; + expected.is_checkable = true; + EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); +} + // We should be able to extract a <select> field. TEST_F(FormAutofillTest, WebFormControlElementToFormFieldSelect) { LoadHTML("<SELECT id=\"element\"/>" @@ -265,8 +300,6 @@ TEST_F(FormAutofillTest, WebFormControlElementToFormFieldInvalidType) { LoadHTML("<FORM name=\"TestForm\" action=\"http://cnn.com\" method=\"post\">" " <INPUT type=\"hidden\" id=\"hidden\" value=\"apple\"/>" " <INPUT type=\"password\" id=\"password\" value=\"secret\"/>" - " <INPUT type=\"checkbox\" id=\"checkbox\" value=\"mail\"/>" - " <INPUT type=\"radio\" id=\"radio\" value=\"male\"/>" " <INPUT type=\"submit\" id=\"submit\" value=\"Send\"/>" "</FORM>"); @@ -292,21 +325,6 @@ TEST_F(FormAutofillTest, WebFormControlElementToFormFieldInvalidType) { expected.form_control_type = "password"; EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); - web_element = frame->document().getElementById("checkbox"); - element = web_element.to<WebFormControlElement>(); - WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result); - expected.name = ASCIIToUTF16("checkbox"); - expected.form_control_type = "checkbox"; - EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); - - web_element = frame->document().getElementById("radio"); - element = web_element.to<WebFormControlElement>(); - WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result); - expected.name = ASCIIToUTF16("radio"); - expected.form_control_type = "radio"; - EXPECT_FORM_FIELD_DATA_EQUALS(expected, result); - - web_element = frame->document().getElementById("submit"); element = web_element.to<WebFormControlElement>(); WebFormControlElementToFormField(element, autofill::EXTRACT_VALUE, &result); diff --git a/chrome/renderer/autofill/form_autofill_util.cc b/chrome/renderer/autofill/form_autofill_util.cc index 1c68601..179d786 100644 --- a/chrome/renderer/autofill/form_autofill_util.cc +++ b/chrome/renderer/autofill/form_autofill_util.cc @@ -46,8 +46,10 @@ using WebKit::WebVector; namespace { using autofill::ExtractAutofillableElements; -using autofill::IsTextInput; +using autofill::IsAutofillableInputElement; +using autofill::IsCheckableElement; using autofill::IsSelectElement; +using autofill::IsTextInput; // The maximum length allowed for form data. const size_t kMaxDataLength = 1024; @@ -70,7 +72,7 @@ bool HasTagName(const WebNode& node, const WebKit::WebString& tag) { bool IsAutofillableElement(const WebFormControlElement& element) { const WebInputElement* input_element = toWebInputElement(&element); - return IsTextInput(input_element) || IsSelectElement(element); + return IsAutofillableInputElement(input_element) || IsSelectElement(element); } // Appends |suffix| to |prefix| so that any intermediary whitespace is collapsed @@ -462,13 +464,12 @@ void ForEachMatchingFormField(const WebFormElement& form_element, bool is_initiating_element = (*element == initiating_element); + // Only autofill empty fields and the field that initiated the filling, + // i.e. the field the user is currently editing and interacting with. const WebInputElement* input_element = toWebInputElement(element); - if (IsTextInput(input_element)) { - // Only autofill empty fields and the field that initiated the filling, - // i.e. the field the user is currently editing and interacting with. - if (!is_initiating_element && !input_element->value().isEmpty()) - continue; - } + if (IsTextInput(input_element) && !is_initiating_element && + !input_element->value().isEmpty()) + continue; if (!element->isEnabled() || element->isReadOnly() || (only_focusable_elements && !element->isFocusable())) @@ -500,13 +501,15 @@ void FillFormField(const FormFieldData& data, // Clear the current IME composition (the underline), if there is one. input_element->document().frame()->unmarkText(); } - } else { - DCHECK(IsSelectElement(*field)); + } else if (IsSelectElement(*field)) { WebSelectElement select_element = field->to<WebSelectElement>(); if (select_element.value() != data.value) { select_element.setValue(data.value); select_element.dispatchFormControlChangeEvent(); } + } else { + DCHECK(IsCheckableElement(input_element)); + input_element->setChecked(data.is_checked, true); } } @@ -519,7 +522,8 @@ void PreviewFormField(const FormFieldData& data, if (data.value.empty()) return; - // Only preview input fields. + // Only preview input fields. Excludes checkboxes and radio buttons, as there + // is no provision for setSuggestedCheckedValue in WebInputElement. WebInputElement* input_element = toWebInputElement(field); if (!IsTextInput(input_element)) return; @@ -564,7 +568,25 @@ bool IsTextInput(const WebInputElement* element) { } bool IsSelectElement(const WebFormControlElement& element) { - return element.formControlType() == ASCIIToUTF16("select-one"); + // Is static for improving performance. + CR_DEFINE_STATIC_LOCAL(WebString, kSelectOne, ("select-one")); + return element.formControlType() == kSelectOne; +} + +bool IsCheckableElement(const WebInputElement* element) { + // Is static for improving performance. + CR_DEFINE_STATIC_LOCAL(WebString, kRadio, ("radio")); + CR_DEFINE_STATIC_LOCAL(WebString, kCheckbox, ("checkbox")); + + if (!element) + return false; + + WebString formControlType = element->formControlType(); + return formControlType == kCheckbox || formControlType == kRadio; +} + +bool IsAutofillableInputElement(const WebInputElement* element) { + return IsTextInput(element) || IsCheckableElement(element); } const string16 GetFormIdentifier(const WebFormElement& form) { @@ -625,7 +647,8 @@ void ExtractAutofillableElements( // TODO(jhawkins): WebKit currently doesn't handle the autocomplete // attribute for select control elements, but it probably should. WebInputElement* input_element = toWebInputElement(&control_elements[i]); - if (IsTextInput(input_element) && !input_element->autoComplete()) + if (IsAutofillableInputElement(input_element) && + !input_element->autoComplete()) continue; } @@ -657,11 +680,14 @@ void WebFormControlElementToFormField(const WebFormControlElement& element, return; const WebInputElement* input_element = toWebInputElement(&element); - if (IsTextInput(input_element)) { - field->max_length = input_element->maxLength(); + if (IsAutofillableInputElement(input_element)) { + if (IsTextInput(input_element)) + field->max_length = input_element->maxLength(); + field->is_autofilled = input_element->isAutofilled(); field->is_focusable = input_element->isFocusable(); field->should_autocomplete = input_element->autoComplete(); + field->is_checkable = IsCheckableElement(input_element); } else if (extract_mask & EXTRACT_OPTIONS) { // Set option strings on the field if available. DCHECK(IsSelectElement(element)); @@ -675,7 +701,7 @@ void WebFormControlElementToFormField(const WebFormControlElement& element, return; string16 value; - if (IsTextInput(input_element)) { + if (IsAutofillableInputElement(input_element)) { value = input_element->value(); } else { DCHECK(IsSelectElement(element)); @@ -752,7 +778,8 @@ bool WebFormElementToFormData( continue; const WebInputElement* input_element = toWebInputElement(&control_element); - if (requirements & REQUIRE_AUTOCOMPLETE && IsTextInput(input_element) && + if (requirements & REQUIRE_AUTOCOMPLETE && + IsAutofillableInputElement(input_element) && !input_element->autoComplete()) continue; @@ -954,7 +981,7 @@ bool FormWithElementIsAutofilled(const WebInputElement& element) { &control_elements); for (size_t i = 0; i < control_elements.size(); ++i) { WebInputElement* input_element = toWebInputElement(&control_elements[i]); - if (!IsTextInput(input_element)) + if (!IsAutofillableInputElement(input_element)) continue; if (input_element->isAutofilled()) @@ -965,3 +992,4 @@ bool FormWithElementIsAutofilled(const WebInputElement& element) { } } // namespace autofill + diff --git a/chrome/renderer/autofill/form_autofill_util.h b/chrome/renderer/autofill/form_autofill_util.h index 53ca6b7..5292567 100644 --- a/chrome/renderer/autofill/form_autofill_util.h +++ b/chrome/renderer/autofill/form_autofill_util.h @@ -55,6 +55,13 @@ bool IsTextInput(const WebKit::WebInputElement* element); // Returns true if |element| is a select element. bool IsSelectElement(const WebKit::WebFormControlElement& element); +// Returns true if |element| is a checkbox or a radio button element. +bool IsCheckableElement(const WebKit::WebInputElement* element); + +// Returns true if |element| is one of the input element that can be autofilled. +// {Text, Radiobutton, Checkbox} +bool IsAutofillableInputElement(const WebKit::WebInputElement* element); + // Returns the form's |name| attribute if non-empty; otherwise the form's |id| // attribute. const string16 GetFormIdentifier(const WebKit::WebFormElement& form); diff --git a/chrome/renderer/autofill/form_cache.cc b/chrome/renderer/autofill/form_cache.cc index cad8c78..ea92a42 100644 --- a/chrome/renderer/autofill/form_cache.cc +++ b/chrome/renderer/autofill/form_cache.cc @@ -43,6 +43,32 @@ const size_t kRequiredAutofillFields = 3; namespace autofill { +// 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) { + 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); + } +} + FormCache::FormCache() { } @@ -80,6 +106,12 @@ void FormCache::ExtractForms(const WebFrame& frame, element.toConst<WebSelectElement>(); initial_select_values_.insert(std::make_pair(select_element, select_element.value())); + } else { + const WebInputElement input_element = + element.toConst<WebInputElement>(); + if (IsCheckableElement(&input_element)) + initial_checked_state_.insert( + std::make_pair(input_element, input_element.isChecked())); } } @@ -119,25 +151,8 @@ void FormCache::ResetFrame(const WebFrame& frame) { web_documents_.erase(*it); } - std::vector<WebSelectElement> select_values_to_delete; - for (std::map<const WebSelectElement, string16>::const_iterator it = - initial_select_values_.begin(); - it != initial_select_values_.end(); ++it) { - WebFormElement form_element = it->first.form(); - if (form_element.isNull()) { - select_values_to_delete.push_back(it->first); - } else { - const WebFrame* element_frame = form_element.document().frame(); - if (!element_frame || element_frame == &frame) - select_values_to_delete.push_back(it->first); - } - } - - for (std::vector<WebSelectElement>::const_iterator it = - select_values_to_delete.begin(); - it != select_values_to_delete.end(); ++it) { - initial_select_values_.erase(*it); - } + RemoveOldElements(frame, &initial_select_values_); + RemoveOldElements(frame, &initial_checked_state_); } bool FormCache::ClearFormWithElement(const WebInputElement& element) { @@ -165,8 +180,7 @@ bool FormCache::ClearFormWithElement(const WebInputElement& element) { int length = input_element->value().length(); input_element->setSelectionRange(length, length); } - } else { - DCHECK(IsSelectElement(control_element)); + } else if (IsSelectElement(control_element)) { WebSelectElement select_element = control_element.to<WebSelectElement>(); std::map<const WebSelectElement, string16>::const_iterator @@ -176,6 +190,15 @@ bool FormCache::ClearFormWithElement(const WebInputElement& element) { select_element.setValue(initial_value_iter->second); select_element.dispatchFormControlChangeEvent(); } + } else { + WebInputElement input_element = control_element.to<WebInputElement>(); + DCHECK(IsCheckableElement(&input_element)); + std::map<const WebInputElement, bool>::const_iterator it = + initial_checked_state_.find(input_element); + if (it != initial_checked_state_.end() && + input_element.isChecked() != it->second) { + input_element.setChecked(it->second, true); + } } } diff --git a/chrome/renderer/autofill/form_cache.h b/chrome/renderer/autofill/form_cache.h index 43bd651..2906224 100644 --- a/chrome/renderer/autofill/form_cache.h +++ b/chrome/renderer/autofill/form_cache.h @@ -54,6 +54,9 @@ class FormCache { // The cached initial values for <select> elements. std::map<const WebKit::WebSelectElement, string16> initial_select_values_; + // The cached initial values for checkable <input> elements. + std::map<const WebKit::WebInputElement, bool> initial_checked_state_; + DISALLOW_COPY_AND_ASSIGN(FormCache); }; diff --git a/chrome/test/data/autofill/heuristics/output/02_checkout_advanceautoparts.com.out b/chrome/test/data/autofill/heuristics/output/02_checkout_advanceautoparts.com.out index 5b826ea..80b1077 100644 --- a/chrome/test/data/autofill/heuristics/output/02_checkout_advanceautoparts.com.out +++ b/chrome/test/data/autofill/heuristics/output/02_checkout_advanceautoparts.com.out @@ -1,3 +1,4 @@ +UNKNOWN_TYPE | billingShippingSame | Billing AddressUse form below for your billing address:* required fields*First Name: | false NAME_FIRST | billFirstName | *First Name: | NAME_LAST | billLastName | *Last Name: | ADDRESS_BILLING_LINE1 | billAddress1 | *Street Address 1: | @@ -9,6 +10,7 @@ PHONE_HOME_CITY_CODE | billDayPhonePart1 | ( | PHONE_HOME_NUMBER | billDayPhonePart2 | ) | PHONE_HOME_NUMBER | billDayPhonePart3 | *Day Phone: | EMAIL_ADDRESS | billEmail | *Email Address: | +UNKNOWN_TYPE | sendMeEmail | *Email Address: | checked NAME_FIRST | shipFirstName | *First Name: | NAME_LAST | shipLastName | *Last Name: | ADDRESS_HOME_LINE1 | shipAddress1 | *Street Address 1: | diff --git a/chrome/test/data/autofill/heuristics/output/02_checkout_ae.com.out b/chrome/test/data/autofill/heuristics/output/02_checkout_ae.com.out index e9fa3bb..7b23197 100644 --- a/chrome/test/data/autofill/heuristics/output/02_checkout_ae.com.out +++ b/chrome/test/data/autofill/heuristics/output/02_checkout_ae.com.out @@ -10,6 +10,9 @@ ADDRESS_HOME_LINE2 | address2 | Address | ADDRESS_HOME_CITY | city | City | ADDRESS_HOME_STATE | state | State | ADDRESS_HOME_ZIP | zip | Zip | +UNKNOWN_TYPE | shippingChoice | Shipping Method CLOSEWe ship using UPS and USPS Priority Mail within the continental United States, and USPS priority mail outside of the continental United States.Learn More about our shipping methods and prices.Place this order by 1PM EST to get it by the estimated dates below: | Standard +UNKNOWN_TYPE | shippingChoice | Shipping Method CLOSEWe ship using UPS and USPS Priority Mail within the continental United States, and USPS priority mail outside of the continental United States.Learn More about our shipping methods and prices.Place this order by 1PM EST to get it by the estimated dates below: | SecondDay +UNKNOWN_TYPE | shippingChoice | Standard3 - 7 business days$7dates: Jun 08 - Jun 14 Two Day2 business days$15date: Jun 07 Overnight1 business day$20date: Jun 06 | Overnight CREDIT_CARD_TYPE | ccType | Card Type: | CREDIT_CARD_NUMBER | ccNumber | Card Number: | CREDIT_CARD_EXP_MONTH | expMonth | Expiration: | 1 @@ -19,7 +22,10 @@ UNKNOWN_TYPE | birthMonthBMLField | Birthday: CLOSEWe need your birthday for the UNKNOWN_TYPE | birthDayBMLField | Birthday: CLOSEWe need your birthday for the Bill Me Later® credit check process. | UNKNOWN_TYPE | birthYearBMLField | Birthday: CLOSEWe need your birthday for the Bill Me Later® credit check process. | UNKNOWN_TYPE | SSN | Last 4 digits of your social security #: CLOSEWe need the last 4 digits of your SSN for the Bill Me Later® credit check process. If you do not have an SSN, you can still pay by Credit Card or PayPal. | +UNKNOWN_TYPE | agree | I agree to have the Terms and Conditions presented electronically. | yes +UNKNOWN_TYPE | agreeTs | I agree to the Bill Me Later® Terms and Conditions. | yes ADDRESS_HOME_COUNTRY | countryType | Country Type | usa +UNKNOWN_TYPE | billSameAsShip | My Billing & Shipping addresses are the same | yes ADDRESS_HOME_COUNTRY | country | Country, APO/FPO | US NAME_FIRST | firstName | First Name | NAME_LAST | lastName | Last Name | @@ -32,6 +38,12 @@ EMAIL_ADDRESS | email | Email CLOSEWe use this to send you an order confirmation EMAIL_ADDRESS | confirmEmail | Re-Type Email | PHONE_HOME_WHOLE_NUMBER | billingPhone | Billing Phone Number CLOSEThis must match the phone number on your credit card statement. Don't worry... we never share your number with anyone. | UNKNOWN_TYPE | accessPassNumber | My AEREWARD$ # CLOSEAEREWARD$ NumberEnter the number found on the back of your AEREWARD$ card to earn rewards for your purchase.Learn More about AEREWARD$ | +UNKNOWN_TYPE | aeRewardsSignUp | Sign up now and receive 25 points just for signing up! Learn More | true +UNKNOWN_TYPE | aeAccount | Create my AE Account.CLOSECreate an AE Account to:Save Your Personal Info For Next TimeCheckout FasterTrack An Order Quicker Sign up now and receive 25 points just for signing up! Learn More | true UNKNOWN_TYPE | birthMonthBillAddField | Birthday: CLOSEWe'd love to wish you a happy birthday when it's time! However, you need to be 13 or older to create an account. | UNKNOWN_TYPE | birthDayBillAddField | Birthday: CLOSEWe'd love to wish you a happy birthday when it's time! However, you need to be 13 or older to create an account. | UNKNOWN_TYPE | birthYearBillAddField | Birthday: CLOSEWe'd love to wish you a happy birthday when it's time! However, you need to be 13 or older to create an account. | +UNKNOWN_TYPE | aeEmail | AE | on +UNKNOWN_TYPE | aerieEmail | aerie | on +UNKNOWN_TYPE | kidsEmail | 77kids | on +UNKNOWN_TYPE | loyaltyTerms | I accept the Terms & Conditions | diff --git a/chrome/test/data/autofill/heuristics/output/02_checkout_bedbathandbeyond.com.out b/chrome/test/data/autofill/heuristics/output/02_checkout_bedbathandbeyond.com.out index af6cf0b..58d3631 100644 --- a/chrome/test/data/autofill/heuristics/output/02_checkout_bedbathandbeyond.com.out +++ b/chrome/test/data/autofill/heuristics/output/02_checkout_bedbathandbeyond.com.out @@ -18,6 +18,9 @@ PHONE_HOME_NUMBER | mob_phone_part2 | Mobile phone | PHONE_HOME_NUMBER | mob_phone_part3 | Mobile phone | EMAIL_ADDRESS | email_addr | *Email | EMAIL_ADDRESS | retype_email_addr | *Re-type email | +UNKNOWN_TYPE | promo_email_flag | Receive information on special offers and new arrivals at Bed Bath & Beyond. | Y +UNKNOWN_TYPE | mobile_offers_opt_in | Bed Bath & Beyond may deliver mobile offers and promotions via text message in the future. Check the box if you would like to receive these mobile offers and promotions on your mobile phone. View our Privacy policy. Message & data rates may apply. | Y +UNKNOWN_TYPE | shipping_options | Shipping | B NAME_FIRST | ship_first_nm | *First name | NAME_MIDDLE | ship_mid_nm | Middle name | NAME_LAST | ship_last_nm | *Last name | diff --git a/chrome/test/data/autofill/heuristics/output/02_checkout_cafepress.com.out b/chrome/test/data/autofill/heuristics/output/02_checkout_cafepress.com.out index 4683755..ca0c74d 100644 --- a/chrome/test/data/autofill/heuristics/output/02_checkout_cafepress.com.out +++ b/chrome/test/data/autofill/heuristics/output/02_checkout_cafepress.com.out @@ -9,6 +9,9 @@ UNKNOWN_TYPE | BillStateOther | State/Province* | ADDRESS_BILLING_ZIP | BillZip | Zip/Postal Code* | PHONE_HOME_WHOLE_NUMBER | BillPhone | Phone Number* | EMAIL_ADDRESS | BillEmail | Email Address* | +UNKNOWN_TYPE | cbStoreSpecial | | on +UNKNOWN_TYPE | ShipDestination | | billaddress +UNKNOWN_TYPE | ShipDestination | Ship to my billing address | shipaddress NAME_FULL | ShipName | Recipient Name* | ADDRESS_HOME_COUNTRY | ShipCountry | Country* | UNITED STATES ADDRESS_HOME_LINE1 | ShipStreet1 | Address* | @@ -17,8 +20,16 @@ ADDRESS_HOME_CITY | ShipCity | Town/City* | ADDRESS_HOME_STATE | ShipState | State/Province* | UNKNOWN_TYPE | ShipStateOther | State/Province* | ADDRESS_HOME_ZIP | ShipZip | Zip/Postal Code* | +UNKNOWN_TYPE | ShowGiftMsg | 2 Shipping Address | on UNKNOWN_TYPE | countdown | You have | 300 +UNKNOWN_TYPE | ApplyGiftWrap | 2 Shipping Address | on UNKNOWN_TYPE | txtCoupon | Apply Promo Code | +UNKNOWN_TYPE | PaymentMethod | | PayByCafeCash +UNKNOWN_TYPE | PaymentMethod | | PayByGC +UNKNOWN_TYPE | PaymentMethod | | PayByCCGC +UNKNOWN_TYPE | PaymentMethod | | PayByCC CREDIT_CARD_NUMBER | txtCCAccount | Credit Card No.* | CREDIT_CARD_EXP_MONTH | ccExp$MonthDrop | Expiration Date* | 06 (June) CREDIT_CARD_EXP_4_DIGIT_YEAR | ccExp$YearDrop | Expiration Date* | 2011 +UNKNOWN_TYPE | PaymentMethod | Expiration Date* | PayByCheck +UNKNOWN_TYPE | PaymentMethod | | PayByPayPal diff --git a/chrome/test/data/autofill/heuristics/output/03_checkout_cduniverse.com.out b/chrome/test/data/autofill/heuristics/output/03_checkout_cduniverse.com.out index 5017bf3..b5e2157 100644 --- a/chrome/test/data/autofill/heuristics/output/03_checkout_cduniverse.com.out +++ b/chrome/test/data/autofill/heuristics/output/03_checkout_cduniverse.com.out @@ -15,3 +15,6 @@ ADDRESS_HOME_CITY | HT_Ship_City | City | ADDRESS_HOME_STATE | HT_Ship_State | State/Province | ADDRESS_HOME_ZIP | HT_Ship_Zip | Zip/Postal Code | ADDRESS_HOME_COUNTRY | HT_Ship_Country | Country | +UNKNOWN_TYPE | HT_OK_to_email | Would it be OK if occasionally we notified you of special sales via email? | -1 +UNKNOWN_TYPE | HT_OK_to_email | Yes | 0 +UNKNOWN_TYPE | HT_PrefersHTML | Would it be OK if occasionally we notified you of special sales via email? | on diff --git a/chrome/test/data/autofill/heuristics/output/03_checkout_crutchfield.com.out b/chrome/test/data/autofill/heuristics/output/03_checkout_crutchfield.com.out index 10d6512..3891038 100644 --- a/chrome/test/data/autofill/heuristics/output/03_checkout_crutchfield.com.out +++ b/chrome/test/data/autofill/heuristics/output/03_checkout_crutchfield.com.out @@ -8,6 +8,9 @@ ADDRESS_HOME_STATE | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$s ADDRESS_HOME_ZIP | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$zip | Zip/Postal Code | PHONE_HOME_WHOLE_NUMBER | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$billphone2 | Billing Phone | EMAIL_ADDRESS | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$email2 | Email | +UNKNOWN_TYPE | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$chbox2 | Send me exclusive offers, deals and expert reviews. | on +UNKNOWN_TYPE | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$same | Shipping Address | same +UNKNOWN_TYPE | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$giftOrder | Shipping Address | gift NAME_FIRST | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$shippingFirstname | First Name | NAME_MIDDLE_INITIAL | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$shippingMi | M.I. | NAME_LAST | ctl00$ctl00$MainContentPlaceHolder$MainContentPlaceHolder$shippingLastname | Last Name | diff --git a/chrome/test/data/autofill/heuristics/output/03_checkout_gamestop.com.out b/chrome/test/data/autofill/heuristics/output/03_checkout_gamestop.com.out index f327e63..c2d2d13 100644 --- a/chrome/test/data/autofill/heuristics/output/03_checkout_gamestop.com.out +++ b/chrome/test/data/autofill/heuristics/output/03_checkout_gamestop.com.out @@ -10,6 +10,7 @@ ADDRESS_HOME_COUNTRY | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlace PHONE_HOME_WHOLE_NUMBER | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$textPhoneNumberDaytime | Phone Number: | EMAIL_ADDRESS | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$txtEmailAddress | Purchaser's Email: | EMAIL_ADDRESS | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$txtEmailAddressConfirm | Confirm Email: | +UNKNOWN_TYPE | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$AddressDetails$AddressDetails$chkEmailOptIn | Confirm Email: | on NAME_FIRST | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textFirstName | First Name: | NAME_LAST | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textLastName | Last Name: | ADDRESS_HOME_LINE1 | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textAddressLine1 | Address 1: | @@ -19,3 +20,4 @@ ADDRESS_HOME_STATE | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHo ADDRESS_HOME_ZIP | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textZip | Zip/Postal: | ADDRESS_HOME_COUNTRY | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$ddlCountry | Country: | US PHONE_HOME_WHOLE_NUMBER | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$aspShippingAddress$popAddressSelection$AddressDetails1$textPhoneNumberDaytime | Phone Number: | +UNKNOWN_TYPE | ctl00$ctl00$ctl00$BaseContentPlaceHolder$mainContentPlaceHolder$MainContentPlaceHolder$chkSameAsBillingAddress | | on diff --git a/chrome/test/data/autofill/heuristics/output/03_checkout_homedepot.com.out b/chrome/test/data/autofill/heuristics/output/03_checkout_homedepot.com.out index 70ecb00..9472e14 100644 --- a/chrome/test/data/autofill/heuristics/output/03_checkout_homedepot.com.out +++ b/chrome/test/data/autofill/heuristics/output/03_checkout_homedepot.com.out @@ -11,3 +11,4 @@ PHONE_HOME_NUMBER | fieldphone3_1 | *Phone Number on Record: | PHONE_HOME_CITY_CODE | altfieldphone1_1 | Alternate Phone: | PHONE_HOME_NUMBER | altfieldphone2_1 | Alternate Phone: | PHONE_HOME_NUMBER | altfieldphone3_1 | Alternate Phone: | +UNKNOWN_TYPE | isBillingAddress_1 | Alternate Phone: | on diff --git a/chrome/test/data/autofill/heuristics/output/03_checkout_hsn.com.out b/chrome/test/data/autofill/heuristics/output/03_checkout_hsn.com.out index 645885b..a7c12cd 100644 --- a/chrome/test/data/autofill/heuristics/output/03_checkout_hsn.com.out +++ b/chrome/test/data/autofill/heuristics/output/03_checkout_hsn.com.out @@ -1,3 +1,4 @@ +UNKNOWN_TYPE | Body$BillingIsShippingCheckboxB | Enter billing information (as it appears on your statement) | on NAME_FIRST | Body$BillingAddress$_firstName | First Name | NAME_LAST | Body$BillingAddress$_lastName | Last Name | ADDRESS_BILLING_LINE1 | Body$BillingAddress$_address1 | Address Line 1 | @@ -6,8 +7,17 @@ ADDRESS_BILLING_CITY | Body$BillingAddress$_city | City | ADDRESS_BILLING_STATE | Body$BillingAddress$_state | State | ADDRESS_BILLING_ZIP | Body$BillingAddress$_zipcode | Zip Code | PHONE_HOME_WHOLE_NUMBER | Body$BillingAddress$_PrimaryPhone | Primary Phone | +UNKNOWN_TYPE | Body$BillingAddress$rdoPrimary | | H +UNKNOWN_TYPE | Body$BillingAddress$rdoPrimary | | M +UNKNOWN_TYPE | Body$BillingAddress$rdoPrimary | | W PHONE_HOME_WHOLE_NUMBER | Body$BillingAddress$_Alt1Phone | Alternate Phone2(optional) | +UNKNOWN_TYPE | Body$BillingAddress$rdoAlt1 | | H +UNKNOWN_TYPE | Body$BillingAddress$rdoAlt1 | | M +UNKNOWN_TYPE | Body$BillingAddress$rdoAlt1 | | W +UNKNOWN_TYPE | Body$MobileAlerts | Enter billing information (as it appears on your statement) | on EMAIL_ADDRESS | Body$NewEmailAddress2 | Email Address | +UNKNOWN_TYPE | Body$WeeklyNewsletterSignup12 | Email Address | on +UNKNOWN_TYPE | Body$TSNewsletterSignup2 | Email Address | on NAME_FIRST | Body$ShippingAddress$_firstName | First Name | NAME_LAST | Body$ShippingAddress$_lastName | Last Name | ADDRESS_HOME_LINE1 | Body$ShippingAddress$_address1 | Address Line 1 | @@ -16,8 +26,13 @@ ADDRESS_HOME_CITY | Body$ShippingAddress$_city | City | ADDRESS_HOME_STATE | Body$ShippingAddress$_state | State | ADDRESS_HOME_ZIP | Body$ShippingAddress$_zipcode | Zip Code | PHONE_HOME_WHOLE_NUMBER | Body$ShippingAddress$_telephone | Phone Number | +UNKNOWN_TYPE | PaymentTypeSelection | | 0 CREDIT_CARD_NUMBER | Body$CCNumber | Card Number | CREDIT_CARD_EXP_MONTH | Body$CCExpirationDateMonth | Expiration Date | 0 CREDIT_CARD_EXP_4_DIGIT_YEAR | Body$CCExpirationDateYear | Expiration Date | 0 CREDIT_CARD_NAME | Body$CCNameOnCard | Name on Card | +UNKNOWN_TYPE | IsDebitCard | Is this a Debit Card? | 1 +UNKNOWN_TYPE | IsDebitCard | Yes | 0 +UNKNOWN_TYPE | Body$SaveCC4Later | Is this a Debit Card? | on +UNKNOWN_TYPE | PaymentTypeSelection | OR | 1 UNKNOWN_TYPE | Body$NewPasswordHint | Password Hint (optional) | diff --git a/chrome/test/data/autofill/heuristics/output/04_checkout_jr.com.out b/chrome/test/data/autofill/heuristics/output/04_checkout_jr.com.out index acdb256..4b105bb 100644 --- a/chrome/test/data/autofill/heuristics/output/04_checkout_jr.com.out +++ b/chrome/test/data/autofill/heuristics/output/04_checkout_jr.com.out @@ -8,6 +8,9 @@ ADDRESS_BILLING_ZIP | billingAddress.postalCode | * | ADDRESS_BILLING_COUNTRY | billingAddress.country | * | US PHONE_HOME_WHOLE_NUMBER | billingAddress.phoneNumber | * | EMAIL_ADDRESS | customer.emailAddress | * | +UNKNOWN_TYPE | customer.optIn | Yes, send me J&R's promotional email newsletter. | on +UNKNOWN_TYPE | storePickup | Pickup In-Store (Park Row, New York NY) | on +UNKNOWN_TYPE | shipToBillingAddress | Ship to my billing address | on NAME_FIRST | shippingAddress.firstName | * | NAME_LAST | shippingAddress.lastName | * | ADDRESS_HOME_LINE1 | shippingAddress.address1 | * | @@ -22,3 +25,4 @@ UNKNOWN_TYPE | customOrderHeader.salespersonNumber | Salesperson Number | UNKNOWN_TYPE | customOrderHeader.giftFromName | Gift From | UNKNOWN_TYPE | customOrderHeader.giftMessage | Gift Message | EMAIL_ADDRESS | customOrderHeader.giftEmailAddress | Gift Email | +UNKNOWN_TYPE | customOrderHeader.giftHidePrices | Hide prices on the recipient's invoice and products on gift email. | on diff --git a/chrome/test/data/autofill/heuristics/output/04_checkout_kohls.com.out b/chrome/test/data/autofill/heuristics/output/04_checkout_kohls.com.out index bfd1f7f..4e6cca0 100644 --- a/chrome/test/data/autofill/heuristics/output/04_checkout_kohls.com.out +++ b/chrome/test/data/autofill/heuristics/output/04_checkout_kohls.com.out @@ -10,6 +10,9 @@ PHONE_HOME_NUMBER | BILL_PHONE<>exchange | Exchange | UNKNOWN_TYPE | BILL_PHONE<>extension | Extension | PHONE_HOME_WHOLE_NUMBER | bill_phone | Contact Phone: | EMAIL_ADDRESS | CURRENT_USER<>email | E-mail Address: | +UNKNOWN_TYPE | EMAIL_OPT_STATUS_ARRAY<>opt_status | Yes, sign me up for Sale Alerts. (optional) | true +UNKNOWN_TYPE | indShipIsBillTo | Yes | true +UNKNOWN_TYPE | indShipIsBillTo | Yes No | false NAME_FIRST | SHIP_TO_ADDRESS<>firstName | First Name: | NAME_LAST | SHIP_TO_ADDRESS<>lastName | Last Name: | ADDRESS_HOME_LINE1 | SHIP_TO_ADDRESS<>address1 | Address: | diff --git a/chrome/test/data/autofill/heuristics/output/04_checkout_lowes.com.out b/chrome/test/data/autofill/heuristics/output/04_checkout_lowes.com.out index 71d7185..3286920 100644 --- a/chrome/test/data/autofill/heuristics/output/04_checkout_lowes.com.out +++ b/chrome/test/data/autofill/heuristics/output/04_checkout_lowes.com.out @@ -9,9 +9,10 @@ ADDRESS_HOME_CITY | city | City: | ADDRESS_HOME_STATE | state | State: | ADDRESS_HOME_ZIP | zipCode | ZIP Code: | ADDRESS_HOME_CITY | taxGeoCode | Municipality: As an additional way to make sure you receive your order, we ask that you select the name of your municipality (city, town, borough, village, etc.) followed by the county, township, or parish in which you reside. | +UNKNOWN_TYPE | billingAddress | Please enter the phone number and e-mail address associated with this billing address.E-mail Address: Contact Phone: | on EMAIL_ADDRESS | email1 | E-mail Address: | PHONE_HOME_CITY_CODE | billphone1 | Contact Phone: | PHONE_HOME_NUMBER | billphone2 | Contact Phone: | PHONE_HOME_NUMBER | billphone3 | Contact Phone: | -EMAIL_ADDRESS | selfAddress | This is also my billing address. Please enter the phone number and e-mail address associated with this billing address.E-mail Address: Contact Phone: | 0 +EMAIL_ADDRESS | selfAddress | Please enter the phone number and e-mail address associated with this billing address.E-mail Address: Contact Phone: | 0 UNKNOWN_TYPE | save-address | | on diff --git a/chrome/test/data/autofill/heuristics/output/05_checkout_macys.com.out b/chrome/test/data/autofill/heuristics/output/05_checkout_macys.com.out index 4debb59..af9430e 100644 --- a/chrome/test/data/autofill/heuristics/output/05_checkout_macys.com.out +++ b/chrome/test/data/autofill/heuristics/output/05_checkout_macys.com.out @@ -1,3 +1,4 @@ +UNKNOWN_TYPE | selectedShippingAddress | Add a new shipping address | newAddress NAME_FIRST | currentShipment.shipmentAddress.firstName | First Name: | NAME_LAST | currentShipment.shipmentAddress.lastName | Last Name: | ADDRESS_HOME_LINE1 | currentShipment.shipmentAddress.address1 | Address: | diff --git a/chrome/test/data/autofill/heuristics/output/05_checkout_nordstrom.com.out b/chrome/test/data/autofill/heuristics/output/05_checkout_nordstrom.com.out index ed9bf04ba..682d075 100644 --- a/chrome/test/data/autofill/heuristics/output/05_checkout_nordstrom.com.out +++ b/chrome/test/data/autofill/heuristics/output/05_checkout_nordstrom.com.out @@ -10,6 +10,7 @@ ADDRESS_BILLING_CITY | ctl00$mainContentPlaceHolder$billingAddressForm$city | Ci ADDRESS_BILLING_STATE | ctl00$mainContentPlaceHolder$billingAddressForm$stateProvince | State/Province | -1 ADDRESS_BILLING_ZIP | ctl00$mainContentPlaceHolder$billingAddressForm$zipCode | Zip/Postal Code | ADDRESS_BILLING_COUNTRY | ctl00$mainContentPlaceHolder$billingAddressForm$country | Country | 249 +UNKNOWN_TYPE | ctl00$mainContentPlaceHolder$shippingSameAsBilling | | on NAME_FIRST | ctl00$mainContentPlaceHolder$shippingAddressForm$firstName | First Name | NAME_MIDDLE_INITIAL | ctl00$mainContentPlaceHolder$shippingAddressForm$middleInitial | M.I. | NAME_LAST | ctl00$mainContentPlaceHolder$shippingAddressForm$lastName | Last Name | diff --git a/chrome/test/data/autofill/heuristics/output/05_checkout_officemax.com.out b/chrome/test/data/autofill/heuristics/output/05_checkout_officemax.com.out index 5c468cb..5d460a1 100644 --- a/chrome/test/data/autofill/heuristics/output/05_checkout_officemax.com.out +++ b/chrome/test/data/autofill/heuristics/output/05_checkout_officemax.com.out @@ -9,5 +9,6 @@ ADDRESS_HOME_ZIP | zip | *Zip Code: | PHONE_HOME_WHOLE_NUMBER | phone | *Phone number: | EMAIL_ADDRESS | /atg/commerce/order/purchase/ShippingGroupFormHandler.emailAddress | *Email Address: | EMAIL_ADDRESS | /atg/commerce/order/purchase/ShippingGroupFormHandler.confirmEmailAddress | *Confirm Email Address: | +UNKNOWN_TYPE | emailOptIn | Yes! Send me exclusive coupons and special online savings via OfficeMax email.OfficeMax is committed to safeguarding your privacy. Our Privacy Policy outlines how OfficeMax handles your information. | https://www.officemax.com:443/ UNKNOWN_TYPE | /atg/commerce/order/purchase/ShippingGroupFormHandler.maxPerksNumber | MaxPerks® ID: < What is this? | UNKNOWN_TYPE | TaxExemptID | Tax Exempt ID: < What is this? | diff --git a/chrome/test/data/autofill/heuristics/output/05_checkout_overstock.com.out b/chrome/test/data/autofill/heuristics/output/05_checkout_overstock.com.out index 5912be0..bc119ff 100644 --- a/chrome/test/data/autofill/heuristics/output/05_checkout_overstock.com.out +++ b/chrome/test/data/autofill/heuristics/output/05_checkout_overstock.com.out @@ -7,6 +7,8 @@ ADDRESS_BILLING_STATE | BillingState | State | CA ADDRESS_BILLING_ZIP | BillingZipCode | Zip | 95014 PHONE_HOME_WHOLE_NUMBER | BillingDaytimePhone | Day Phone | 4088737223 PHONE_HOME_WHOLE_NUMBER | BillingEveningPhone | Evening Phone | +UNKNOWN_TYPE | checkbox2 | *Required Field | on +UNKNOWN_TYPE | diffShip | *Required Field | on NAME_FIRST | ShippingFirstName | First Name | NAME_LAST | ShippingLastName | Last Name | ADDRESS_HOME_LINE1 | lineone | Address Line 1 | 7540 Donegal Dr @@ -16,10 +18,15 @@ ADDRESS_HOME_CITY | city | City | Cupertino ADDRESS_HOME_STATE | state | State | CA ADDRESS_HOME_ZIP | zip | Zip | 95014 UNKNOWN_TYPE | product6496917 | Black-plated Tungsten Carbide Comfort Fit Band (8 mm) Options: 10 1 | GROUND6496917 +UNKNOWN_TYPE | CC | | CreditCardValue CREDIT_CARD_NUMBER | CC_number | Credit Card #: | CREDIT_CARD_EXP_MONTH | exp_month | Expiration Date: | 0 CREDIT_CARD_EXP_4_DIGIT_YEAR | exp_year | Expiration Date: | +UNKNOWN_TYPE | CC | | PayPal +UNKNOWN_TYPE | CC | | bml +UNKNOWN_TYPE | UsePromoCode | See Terms | on UNKNOWN_TYPE | PromoCode | See Terms | +UNKNOWN_TYPE | UseGiftCards | See Terms | on UNKNOWN_TYPE | GiftCardNumber0 | Gift Card 1: | UNKNOWN_TYPE | PINNumber0 | PIN: | UNKNOWN_TYPE | GiftCardNumber1 | Gift Card 2: | diff --git a/chrome/test/data/autofill/heuristics/output/05_checkout_petco.com.out b/chrome/test/data/autofill/heuristics/output/05_checkout_petco.com.out index ed7e6cc..116ec69 100644 --- a/chrome/test/data/autofill/heuristics/output/05_checkout_petco.com.out +++ b/chrome/test/data/autofill/heuristics/output/05_checkout_petco.com.out @@ -1,6 +1,7 @@ NAME_FIRST | ctl00$ctl00$cphBody$cphBody$txtSA_FirstName | First Name * | NAME_LAST | ctl00$ctl00$cphBody$cphBody$txtSA_LastName | Last Name * | ADDRESS_HOME_LINE1 | ctl00$ctl00$cphBody$cphBody$txtSA_Address1 | Address Line 1 * | +UNKNOWN_TYPE | ctl00$ctl00$cphBody$cphBody$cbSA_IsPOBox | P.O. Box | on ADDRESS_HOME_LINE2 | ctl00$ctl00$cphBody$cphBody$txtSA_Address2 | Address Line 2 | ADDRESS_HOME_CITY | ctl00$ctl00$cphBody$cphBody$txtSA_City | City * | ADDRESS_HOME_STATE | ctl00$ctl00$cphBody$cphBody$ddlSA_State | State * | @@ -9,3 +10,5 @@ PHONE_HOME_CITY_CODE | ctl00$ctl00$cphBody$cphBody$txtSA_Phone1 | Phone Number * PHONE_HOME_NUMBER | ctl00$ctl00$cphBody$cphBody$txtSA_Phone2 | ZIP Code * | PHONE_HOME_NUMBER | ctl00$ctl00$cphBody$cphBody$txtSA_Phone3 | ZIP Code * | UNKNOWN_TYPE | ctl00$ctl00$cphBody$cphBody$txtSA_PhoneExt | Ext. | +UNKNOWN_TYPE | ctl00$ctl00$cphBody$cphBody$cbSA_MatchBilling | This is also my billing address | on +UNKNOWN_TYPE | ctl00$ctl00$cphBody$cphBody$cbSA_EmailSignup | Send me newsletters with exclusive online discounts, special announcements and health and behavior tips for my pet. | on diff --git a/chrome/test/data/autofill/heuristics/output/06_checkout_petsmart.com.out b/chrome/test/data/autofill/heuristics/output/06_checkout_petsmart.com.out index 60e27b9..fc3469e 100644 --- a/chrome/test/data/autofill/heuristics/output/06_checkout_petsmart.com.out +++ b/chrome/test/data/autofill/heuristics/output/06_checkout_petsmart.com.out @@ -9,3 +9,5 @@ UNKNOWN_TYPE | altBillState | • Other State/Province: | ADDRESS_BILLING_ZIP | billZip | • Zip/Postal Code: | PHONE_HOME_WHOLE_NUMBER | billPhone | • Telephone: | EMAIL_ADDRESS | guestEmail | • Email Address: | +UNKNOWN_TYPE | shipOptions | Enter Addresses | useShip +UNKNOWN_TYPE | shipOptions | Ship to the above billing address Ship to a different address | provideNew diff --git a/chrome/test/data/autofill/heuristics/output/06_checkout_qvc.com.out b/chrome/test/data/autofill/heuristics/output/06_checkout_qvc.com.out index 165b652..f0f8e58 100644 --- a/chrome/test/data/autofill/heuristics/output/06_checkout_qvc.com.out +++ b/chrome/test/data/autofill/heuristics/output/06_checkout_qvc.com.out @@ -15,6 +15,7 @@ UNKNOWN_TYPE | BilltoHpExt | * Home Phone: | PHONE_HOME_CITY_CODE | BilltoWpArea | Work Phone: | PHONE_HOME_NUMBER | BilltoWpExchange | Work Phone: | UNKNOWN_TYPE | BilltoWpExt | Work Phone: | +UNKNOWN_TYPE | SameAsBilltoCheckbox | Same as Bill-To: | 1 UNKNOWN_TYPE | ShiptoFirstName | * Name: | ADDRESS_HOME_LINE1 | ShiptoAddress1 | * Address Line 1: | ADDRESS_HOME_LINE2 | ShiptoAddress2 | Address Line 2: | @@ -22,3 +23,5 @@ ADDRESS_HOME_CITY | ShiptoCity | City: | ADDRESS_HOME_STATE | ShiptoState | State/Province: | AL ADDRESS_HOME_ZIP | ShiptoZipCode | * Postal Code: | ADDRESS_HOME_COUNTRY | ShiptoCountry | * Country: | US +UNKNOWN_TYPE | ShiptoRadiobutton | Use this address for: | ThisOrderOnly +UNKNOWN_TYPE | ShiptoRadiobutton | This order only | PermanentShipto diff --git a/chrome/test/data/autofill/heuristics/output/06_checkout_sears.com.out b/chrome/test/data/autofill/heuristics/output/06_checkout_sears.com.out index fef4cb6..5fe6242 100644 --- a/chrome/test/data/autofill/heuristics/output/06_checkout_sears.com.out +++ b/chrome/test/data/autofill/heuristics/output/06_checkout_sears.com.out @@ -1,6 +1,7 @@ EMAIL_ADDRESS | address_email | Email* | ne00_99@yahoo.com NAME_FIRST | shipping_firstName | First Name* | NAME_LAST | shipping_lastName | Last Name* | +UNKNOWN_TYPE | shipping_country | First Name* | US ADDRESS_HOME_LINE1 | shipping_address1 | Street Address Line 1* | ADDRESS_HOME_LINE2 | shipping_address2 | Street Address Line 2 | ADDRESS_HOME_CITY | shipping_city | City* | @@ -9,8 +10,10 @@ ADDRESS_HOME_ZIP | shipping_zipCode | ZIP Code* | PHONE_HOME_WHOLE_NUMBER | shipping_day1 | Phone Number* | UNKNOWN_TYPE | shipping_ext1 | Ext. | ADDRESS_HOME_STATE | shipping_county | County | UNKNOWN +UNKNOWN_TYPE | billingAddressCheckBox | Same as Delivery/Shipping Address | on NAME_FIRST | firstName | First Name* | NAME_LAST | lastName | Last Name* | +UNKNOWN_TYPE | country | First Name* | US ADDRESS_HOME_LINE1 | address1 | Street Address Line 1* | ADDRESS_HOME_LINE2 | address2 | Street Address Line 2 | ADDRESS_HOME_CITY | city | City* | diff --git a/chrome/test/data/autofill/heuristics/output/06_checkout_target.com.out b/chrome/test/data/autofill/heuristics/output/06_checkout_target.com.out index dc38dba..50ac7cd 100644 --- a/chrome/test/data/autofill/heuristics/output/06_checkout_target.com.out +++ b/chrome/test/data/autofill/heuristics/output/06_checkout_target.com.out @@ -5,3 +5,6 @@ ADDRESS_HOME_CITY | city | City*: | ADDRESS_HOME_STATE | state | State*: | ADDRESS_HOME_ZIP | zip | Zip Code*: | PHONE_HOME_WHOLE_NUMBER | voice | Phone Number*: | +UNKNOWN_TYPE | order.188:217866256151.ShippingSpeed | (3-5 business days) | std-us +UNKNOWN_TYPE | order.188:217866256151.ShippingSpeed | (2 business days) | second +UNKNOWN_TYPE | order.188:217866256151.ShippingSpeed | Standard Shipping Two-Day Shipping One-Day Shipping | next diff --git a/chrome/test/data/autofill/heuristics/output/06_checkout_urbanoutfitters.com.out b/chrome/test/data/autofill/heuristics/output/06_checkout_urbanoutfitters.com.out index 98072ba..9d2cec1 100644 --- a/chrome/test/data/autofill/heuristics/output/06_checkout_urbanoutfitters.com.out +++ b/chrome/test/data/autofill/heuristics/output/06_checkout_urbanoutfitters.com.out @@ -2,6 +2,7 @@ UNKNOWN_TYPE | shipto | Select a Saved Shipping Address | NAME_FIRST | shippingFirstName | | First Name NAME_LAST | shippingLastName | | Last Name ADDRESS_HOME_LINE1 | shippingAddress | | Street Address +UNKNOWN_TYPE | shippingPobox | | true ADDRESS_HOME_LINE2 | shippingAddress2 | | Apt / Flr / Bldg (optional) ADDRESS_HOME_CITY | shippingCity | | City ADDRESS_HOME_STATE | shippingStates | | @@ -9,9 +10,12 @@ ADDRESS_HOME_ZIP | shippingPostalCode | | Postal Code ADDRESS_HOME_COUNTRY | shippingCountries | | PHONE_HOME_WHOLE_NUMBER | shippingPhone | | Phone PHONE_HOME_WHOLE_NUMBER | altShippingPhone | | Alternate Phone (optional) +UNKNOWN_TYPE | billingIsShipping | | true +UNKNOWN_TYPE | defaultShipping | | true NAME_FIRST | billingFirstName | | First Name NAME_LAST | billingLastName | | Last Name ADDRESS_BILLING_LINE1 | billingAddress | | Street Address +UNKNOWN_TYPE | billingPobox | | true ADDRESS_BILLING_LINE2 | billingAddress2 | | Apt / Flr / Bldg (optional) ADDRESS_BILLING_CITY | billingCity | | City ADDRESS_BILLING_STATE | billingStates | | @@ -19,9 +23,11 @@ ADDRESS_BILLING_ZIP | billingPostalCode | | Postal Code ADDRESS_BILLING_COUNTRY | billingCountries | | PHONE_HOME_WHOLE_NUMBER | billingPhone | | Phone PHONE_HOME_WHOLE_NUMBER | altBillingPhone | | Alternate Phone (optional) +UNKNOWN_TYPE | defaultBilling | | true UNKNOWN_TYPE | savedCreditCard | | CREDIT_CARD_TYPE | payment_cardtype | | CREDIT_CARD_NUMBER | payment_acctnum | | Card Number (no spaces or dashes) CREDIT_CARD_EXP_MONTH | expmonth | | CREDIT_CARD_EXP_4_DIGIT_YEAR | expyear | | CREDIT_CARD_VERIFICATION_CODE | payment_cidnew | | CID / Security Code +UNKNOWN_TYPE | makeDefaultCreditCard | | true diff --git a/chrome/test/data/autofill/heuristics/output/07_checkout_williams-sonoma.com.out b/chrome/test/data/autofill/heuristics/output/07_checkout_williams-sonoma.com.out index 30dc665..796ea41 100644 --- a/chrome/test/data/autofill/heuristics/output/07_checkout_williams-sonoma.com.out +++ b/chrome/test/data/autofill/heuristics/output/07_checkout_williams-sonoma.com.out @@ -6,5 +6,8 @@ ADDRESS_HOME_STATE | shipTos[0].address.state | State* | ADDRESS_HOME_ZIP | shipTos[0].address.zip | Zip* | PHONE_HOME_WHOLE_NUMBER | shipTos[0].address.dayPhone | Daytime Phone* | PHONE_HOME_WHOLE_NUMBER | shipTos[0].address.eveningPhone | Alternate Phone | +UNKNOWN_TYPE | shipTos[0].billingAddressUpdate | Yes, use this shipping address for my billing address. | on EMAIL_ADDRESS | shipTos[0].address.emailAddr | Email* | EMAIL_ADDRESS | shipTos[0].confirmEmailAddr | Confirm Email* | +UNKNOWN_TYPE | shipTos[0].shipType | | Standard +UNKNOWN_TYPE | shipTos[0].shipType | Standard (5-7 business days) Rush (2-3 business days) | Rush diff --git a/chrome/test/data/autofill/heuristics/output/08_register_adobe.com.out b/chrome/test/data/autofill/heuristics/output/08_register_adobe.com.out index aff2f0c..e1bb4b6 100644 --- a/chrome/test/data/autofill/heuristics/output/08_register_adobe.com.out +++ b/chrome/test/data/autofill/heuristics/output/08_register_adobe.com.out @@ -2,3 +2,5 @@ EMAIL_ADDRESS | adobeId | E-Mail AddressThis will be your Adobe ID | NAME_FIRST | firstName | First Name | NAME_LAST | lastName | Last Name | ADDRESS_HOME_COUNTRY | countryCode | Country | +UNKNOWN_TYPE | agreeToTou | I have read and agree to the and the | on +UNKNOWN_TYPE | hostedOptIn | Yes! I would like to receive communications relating to Adobe, its products and services including product releases, product upgrades, seminars, events, surveys, training and special offers, and Adobe, and its agents may use data I have provided in accordance with the | on diff --git a/chrome/test/data/autofill/heuristics/output/08_register_amazon.com.out b/chrome/test/data/autofill/heuristics/output/08_register_amazon.com.out index d8c9168..f49c7e9 100644 --- a/chrome/test/data/autofill/heuristics/output/08_register_amazon.com.out +++ b/chrome/test/data/autofill/heuristics/output/08_register_amazon.com.out @@ -1,3 +1,5 @@ +UNKNOWN_TYPE | action | | new-user +UNKNOWN_TYPE | action | Create a new account (Recommended for Business accounts) Use existing Amazon customer account | sign-in UNKNOWN_TYPE | userName | First and Last Name: | EMAIL_ADDRESS | email | E-mail Address: | EMAIL_ADDRESS | emailCheck | Re-type E-mail Address: | diff --git a/chrome/test/data/autofill/heuristics/output/08_register_aol.com.out b/chrome/test/data/autofill/heuristics/output/08_register_aol.com.out index 5cd5839..8afd4fe 100644 --- a/chrome/test/data/autofill/heuristics/output/08_register_aol.com.out +++ b/chrome/test/data/autofill/heuristics/output/08_register_aol.com.out @@ -5,6 +5,8 @@ UNKNOWN_TYPE | verifyPasswordHint | Password | Retype password UNKNOWN_TYPE | wlw-select_key:{actionForm.dobMonth} | Select Month | UNKNOWN_TYPE | {actionForm.dobDay} | Select Month | Day (dd) UNKNOWN_TYPE | {actionForm.dobYear} | Select Month | Year (yyyy) +UNKNOWN_TYPE | wlw-radio_button_group_key:{actionForm.gender} | Gender | Female +UNKNOWN_TYPE | wlw-radio_button_group_key:{actionForm.gender} | Gender | Male ADDRESS_HOME_ZIP | {actionForm.zipCode} | Zip Code | UNKNOWN_TYPE | wlw-select_key:{actionForm.acctSecurityQuestion} | Set a Security Question | UNKNOWN_TYPE | {actionForm.acctSecurityAnswer} | Set a Security Question | Your Answer diff --git a/chrome/test/data/autofill/heuristics/output/08_register_continental.com.out b/chrome/test/data/autofill/heuristics/output/08_register_continental.com.out index 5f19833..053e6ec8 100644 --- a/chrome/test/data/autofill/heuristics/output/08_register_continental.com.out +++ b/chrome/test/data/autofill/heuristics/output/08_register_continental.com.out @@ -1,10 +1,18 @@ -ADDRESS_HOME_STATE | ctl00$CustomerHeader$ddlCountries | CountryClose Please select your location or where you receive credit card billing statements to see pricing in your local currency.Available Languages:Save this preference | US +ADDRESS_HOME_STATE | ctl00$CustomerHeader$ddlCountries | CountryClose Please select your location or where you receive credit card billing statements to see pricing in your local currency.Available Languages: | US +UNKNOWN_TYPE | ctl00$CustomerHeader$rdlang | Available Languages: | en-us +UNKNOWN_TYPE | ctl00$CustomerHeader$rdlang | Available Languages: | es +UNKNOWN_TYPE | ctl00$CustomerHeader$rdlang | Available Languages: | rd3 +UNKNOWN_TYPE | ctl00$CustomerHeader$chkSave | Save this preference | on UNKNOWN_TYPE | ctl00$ContentInfo$Name$cboTitle$cboTitle | Title: | NAME_FIRST | ctl00$ContentInfo$Name$FName$txtFName | First Name: | NAME_MIDDLE_INITIAL | ctl00$ContentInfo$Name$MName$txtMName | Middle Initial (optional): | NAME_LAST | ctl00$ContentInfo$Name$LName$txtLName | Last Name: | UNKNOWN_TYPE | ctl00$ContentInfo$Name$suffix$txtSuffix | Suffix (optional): | +UNKNOWN_TYPE | ctl00$ContentInfo$MemberAge$EnrollmentAge | | rdoAdult +UNKNOWN_TYPE | ctl00$ContentInfo$MemberAge$EnrollmentAge | This OnePass account is for an adult 18 years of age or older. This OnePass account is for a minor under the age of 18. | rdoMinor UNKNOWN_TYPE | ctl00$ContentInfo$BirthDate$txtDOB | Minor’s Date of Birth: | mm/dd/yyyy +UNKNOWN_TYPE | ctl00$ContentInfo$AddressType$AddressType | Address Type: | rdoAddTypeHome +UNKNOWN_TYPE | ctl00$ContentInfo$AddressType$AddressType | Home Business/Other | rdoAddTypeBusiness ADDRESS_HOME_LINE1 | ctl00$ContentInfo$Address$address1$txtAddress1 | Street Address: | ADDRESS_HOME_LINE2 | ctl00$ContentInfo$Address$address2$txtAddress2 | Street Address: | UNKNOWN_TYPE | ctl00$ContentInfo$Address$address3$txtAddress2 | Street Address: | @@ -20,6 +28,10 @@ UNKNOWN_TYPE | ctl00$ContentInfo$BusinessPhone$txtExt$txtPhoneExt | Ext./PIN (op ADDRESS_HOME_COUNTRY | ctl00$ContentInfo$BusinessPhone$cboCountry$cboCountry | Country: | US UNKNOWN_TYPE | ctl00$ContentInfo$HomeAirport$txtAirport | Home Airport (optional): | EMAIL_ADDRESS | ctl00$ContentInfo$Email$txtEmail | E-mail Address: | +UNKNOWN_TYPE | ctl00$ContentInfo$chkSubOpStatement | | on +UNKNOWN_TYPE | ctl00$ContentInfo$chkSubopnewsoffers | | on +UNKNOWN_TYPE | ctl00$ContentInfo$chkSubcocomspecials | | on +UNKNOWN_TYPE | ctl00$ContentInfo$chkSubtripnotes | | on UNKNOWN_TYPE | ctl00$ContentInfo$UsernamePassword$username$txtUsername | Username: | UNKNOWN_TYPE | ctl00$ContentInfo$PINPasswordReminder$PINReminder1$txtPINReminder | PIN Reminder: (cannot include any numbers) | UNKNOWN_TYPE | ctl00$ContentInfo$SecurityQuestionAnswer$Question$txtSecurity | Security Question: | diff --git a/chrome/test/data/autofill/heuristics/output/09_register_deviantart.com.out b/chrome/test/data/autofill/heuristics/output/09_register_deviantart.com.out index 5db87ae7..daa7e97 100644 --- a/chrome/test/data/autofill/heuristics/output/09_register_deviantart.com.out +++ b/chrome/test/data/autofill/heuristics/output/09_register_deviantart.com.out @@ -1,3 +1,6 @@ +UNKNOWN_TYPE | existingAccount | Are you a new customer? | 0 +UNKNOWN_TYPE | existingAccount | Are you a new customer? Create a new Buyer Account I have an existing deviantART account (email or username) | 1 EMAIL_ADDRESS | emailAddress | Email Address | +UNKNOWN_TYPE | remember_me | Stay logged in | 1 NAME_FULL | name | Full Name | ADDRESS_HOME_COUNTRY | country | Country | 0 diff --git a/chrome/test/data/autofill/heuristics/output/09_register_ebay.com.out b/chrome/test/data/autofill/heuristics/output/09_register_ebay.com.out index 4627851..4cfba51 100644 --- a/chrome/test/data/autofill/heuristics/output/09_register_ebay.com.out +++ b/chrome/test/data/autofill/heuristics/output/09_register_ebay.com.out @@ -19,6 +19,7 @@ UNKNOWN_TYPE | birthdate2 | Date of birth, Month | 0 UNKNOWN_TYPE | birthdate1 | Date of birth, Day | 0 UNKNOWN_TYPE | birthdate3 | Year of birth, four digit format. | 0 UNKNOWN_TYPE | tokentext | For added security - opens in a new window or tab, please enter the verification code hidden in the image. | +UNKNOWN_TYPE | acceptq1 | I agree that:I accept the User Agreement - opens in a new window or tab and Privacy Policy.I may receive communications from eBay and can change my notification preferences in My eBay.I'm at least 18 years old. | 1 UNKNOWN_TYPE | uword1 | Give us some word and we'll suggest some user IDs for you. Word 1 | UNKNOWN_TYPE | uword2 | Word 2 | UNKNOWN_TYPE | uword3 | Word 3 | diff --git a/chrome/test/data/autofill/heuristics/output/09_register_ecomm.dell.com.out b/chrome/test/data/autofill/heuristics/output/09_register_ecomm.dell.com.out index 498b239..d1707fe 100644 --- a/chrome/test/data/autofill/heuristics/output/09_register_ecomm.dell.com.out +++ b/chrome/test/data/autofill/heuristics/output/09_register_ecomm.dell.com.out @@ -7,4 +7,6 @@ ADDRESS_HOME_CITY | address$ctl00$address$addressValidator$_EditView$city | City ADDRESS_HOME_STATE | address$ctl00$address$addressValidator$_EditView$region$ctl01 | CityState | ADDRESS_HOME_ZIP | address$ctl00$address$addressValidator$_EditView$postal_code | Zip Code4-digit Ext. | UNKNOWN_TYPE | address$ctl00$address$addressValidator$_EditView$postal_code2 | Zip Code4-digit Ext. | +UNKNOWN_TYPE | address$ctl00$address$addressValidator$OverrideAddress | Problems? | on EMAIL_ADDRESS | email$ctl07 | Email Address (used to sign into your account) | +UNKNOWN_TYPE | Subscription | | on diff --git a/chrome/test/data/autofill/heuristics/output/09_register_epson.com.out b/chrome/test/data/autofill/heuristics/output/09_register_epson.com.out index 42fd2ef..6650d56 100644 --- a/chrome/test/data/autofill/heuristics/output/09_register_epson.com.out +++ b/chrome/test/data/autofill/heuristics/output/09_register_epson.com.out @@ -1,3 +1,4 @@ NAME_FIRST | fname | * First Name | NAME_LAST | lname | * Last Name | EMAIL_ADDRESS | emLogin | * E-mail address | +UNKNOWN_TYPE | wantMsg | | on diff --git a/chrome/test/data/autofill/heuristics/output/09_register_google.com.out b/chrome/test/data/autofill/heuristics/output/09_register_google.com.out index 815f67d..18ac19c 100644 --- a/chrome/test/data/autofill/heuristics/output/09_register_google.com.out +++ b/chrome/test/data/autofill/heuristics/output/09_register_google.com.out @@ -2,6 +2,8 @@ NAME_FIRST | FirstName | First name: | NAME_LAST | LastName | Last name: | UNKNOWN_TYPE | UsernameSelector | | header EMAIL_ADDRESS | Email | | +UNKNOWN_TYPE | PersistentCookie | Re-enter password: | yes +UNKNOWN_TYPE | smhck | Re-enter password: | 1 UNKNOWN_TYPE | selection | Security question: | choosequestion UNKNOWN_TYPE | ownquestion | Security question: | UNKNOWN_TYPE | IdentityAnswer | Answer: | diff --git a/chrome/test/data/autofill/heuristics/output/10_register_gymboree.com.out b/chrome/test/data/autofill/heuristics/output/10_register_gymboree.com.out index 5fcbb9f..f42e13b 100644 --- a/chrome/test/data/autofill/heuristics/output/10_register_gymboree.com.out +++ b/chrome/test/data/autofill/heuristics/output/10_register_gymboree.com.out @@ -10,3 +10,6 @@ ADDRESS_HOME_STATE | LOYALTY_ADDRESS<>state_cd | State/Province* | ADDRESS_HOME_ZIP | LOYALTY_ADDRESS<>postal | Zip/Postal Code*! | PHONE_HOME_WHOLE_NUMBER | LOYALTY_ADDRESS<>phone | Daytime Phone* | UNKNOWN_TYPE | LOYALTY_ACCOUNT<>ATR_USER_Password_Hint | Password Hint* | +UNKNOWN_TYPE | LOYALTY_ADDRESS<>ATR_indBillAsRewards | Password Hint*! | true +UNKNOWN_TYPE | LOYALTY_ACCOUNT<>sendEmail | Save the address above as my default billing address. I would like to receive promotions and special offers from Gymboree. | true +UNKNOWN_TYPE | accept | I have read and accept the terms and conditions of Gymboree Rewards. (Rewards information and offers will be emailed to you.) | on diff --git a/chrome/test/data/autofill/heuristics/output/10_register_hotels.com.out b/chrome/test/data/autofill/heuristics/output/10_register_hotels.com.out index 5535ff7..a651faa 100644 --- a/chrome/test/data/autofill/heuristics/output/10_register_hotels.com.out +++ b/chrome/test/data/autofill/heuristics/output/10_register_hotels.com.out @@ -12,3 +12,6 @@ ADDRESS_HOME_COUNTRY | profileInformation.customerContact.country | Country* | U PHONE_HOME_WHOLE_NUMBER | profileInformation.customerContact.primaryPhone | Phone number | COMPANY_NAME | profileInformation.businessName | Company name | UNKNOWN_TYPE | profileInformation.currency | Preferred currency | USD +UNKNOWN_TYPE | profileInformation.customerContact.loyaltyAccountDesired | Sign me up to get 1 free night anywhere for every 10 nights I stay with Hotels.com. By enrolling, I agree to the full Terms and Conditions of the program. Learn more. | true +UNKNOWN_TYPE | subscribeNewsletter | Email me exclusive coupons, deals and travel information from hotels.com | true +UNKNOWN_TYPE | termsConditionsConfirm | I have read and accepted the Terms and Conditions and Privacy Policy for this website* | true diff --git a/chrome/test/data/autofill/heuristics/output/10_register_imdb.com.out b/chrome/test/data/autofill/heuristics/output/10_register_imdb.com.out index d61d001..886a00a 100644 --- a/chrome/test/data/autofill/heuristics/output/10_register_imdb.com.out +++ b/chrome/test/data/autofill/heuristics/output/10_register_imdb.com.out @@ -1,5 +1,7 @@ EMAIL_ADDRESS | email1 | E-mail: | EMAIL_ADDRESS | email2 | Confirm E-mail: | +UNKNOWN_TYPE | gender | Sex: | M +UNKNOWN_TYPE | gender | Male | F UNKNOWN_TYPE | year | Year of Birth: | ADDRESS_HOME_ZIP | postal | ZIP/Postal Code: | ADDRESS_HOME_COUNTRY | country | Country: | US diff --git a/chrome/test/data/autofill/heuristics/output/10_register_live.com.out b/chrome/test/data/autofill/heuristics/output/10_register_live.com.out index 0675335..8e45ebab 100644 --- a/chrome/test/data/autofill/heuristics/output/10_register_live.com.out +++ b/chrome/test/data/autofill/heuristics/output/10_register_live.com.out @@ -9,4 +9,7 @@ UNKNOWN_TYPE | iSQ | Question: | 0 UNKNOWN_TYPE | iSA | Secret answer: | NAME_FIRST | iFirstName | First name: | NAME_LAST | iLastName | Last name: | +UNKNOWN_TYPE | profile_gender | | m +UNKNOWN_TYPE | profile_gender | | f UNKNOWN_TYPE | iBirthYear | Birth year: | Example: 1990 +UNKNOWN_TYPE | iOptinEmail | Send me email with promotional offers and survey invitations from Windows Live, Bing, and MSN. (You can unsubscribe at any time.) | on diff --git a/chrome/test/data/autofill/heuristics/output/11_register_livejournal.com.out b/chrome/test/data/autofill/heuristics/output/11_register_livejournal.com.out index 9e8ee32..6f1e66c 100644 --- a/chrome/test/data/autofill/heuristics/output/11_register_livejournal.com.out +++ b/chrome/test/data/autofill/heuristics/output/11_register_livejournal.com.out @@ -4,3 +4,4 @@ UNKNOWN_TYPE | Widget[CreateAccount]_gender | Gender: | UNKNOWN_TYPE | Widget[CreateAccount]_bday_mm | Birthdate: | 1 UNKNOWN_TYPE | Widget[CreateAccount]_bday_dd | Birthdate: | UNKNOWN_TYPE | Widget[CreateAccount]_bday_yyyy | Birthdate: | +UNKNOWN_TYPE | Widget[CreateAccount]_news | Yes, send me LiveJournal announcements via email. | 1 diff --git a/chrome/test/data/autofill/heuristics/output/11_register_macys.com.out b/chrome/test/data/autofill/heuristics/output/11_register_macys.com.out index 1292791..fbdf796 100644 --- a/chrome/test/data/autofill/heuristics/output/11_register_macys.com.out +++ b/chrome/test/data/autofill/heuristics/output/11_register_macys.com.out @@ -9,8 +9,14 @@ UNKNOWN_TYPE | BirthMonth | Birth date | NOSELECTION UNKNOWN_TYPE | BirthDay | | NOSELECTION UNKNOWN_TYPE | BirthYear | | NOSELECTION UNKNOWN_TYPE | Gender | Gender | NOSELECTION +UNKNOWN_TYPE | NewsLetter | We'll let you know about exclusive sales and events,both online and in-store. | NewsLetter +UNKNOWN_TYPE | MobileMarketing | Yes, please text me about exclusive sales and events, both online and in-store. We'll send your first text message within 48 hours. | MobileMarketing PHONE_HOME_CITY_CODE | MobilePhoneAreaCode | | PHONE_HOME_NUMBER | MobilePhoneExchangeNbr | - | PHONE_HOME_NUMBER | MobilePhoneSubscriberNbr | - | +UNKNOWN_TYPE | addacard | Yes, I'd like to add my Macy's Card to my profile. | on UNKNOWN_TYPE | MaskedAccountNumber | Macy's Account Number: | UNKNOWN_TYPE | SSN4 | Last 4 digits of SSN: | +UNKNOWN_TYPE | addToWallet | Save this store card in your macys.com wallet for faster checkout. | addToWallet +UNKNOWN_TYPE | emailAlert | Receive email notification when statements are ready for review andwhen payments are due. | emailAlert +UNKNOWN_TYPE | paperStatementDelivery | I want to turn off paper statement delivery and receive my statements online. | paperStatementDelivery diff --git a/chrome/test/data/autofill/heuristics/output/11_register_myspace.com.out b/chrome/test/data/autofill/heuristics/output/11_register_myspace.com.out index 0c1f23d..279c12c 100644 --- a/chrome/test/data/autofill/heuristics/output/11_register_myspace.com.out +++ b/chrome/test/data/autofill/heuristics/output/11_register_myspace.com.out @@ -1,3 +1,7 @@ +UNKNOWN_TYPE | accountType | Account TypeWhat's this? | 2 +UNKNOWN_TYPE | accountType | Personal | 7 +UNKNOWN_TYPE | accountType | Musician | 15 +UNKNOWN_TYPE | accountType | Comedian | 9 NAME_FIRST | tbxFirstName | First Name | NAME_LAST | tbxLastName | Last Name | UNKNOWN_TYPE | tbxMusicianName | Artist Name | @@ -7,3 +11,5 @@ EMAIL_ADDRESS | tbxEmail | Email | UNKNOWN_TYPE | ddlMonth | Birthday | UNKNOWN_TYPE | ddlDay | | UNKNOWN_TYPE | ddlYear | | +UNKNOWN_TYPE | rblGender | Gender | M +UNKNOWN_TYPE | rblGender | Male | F diff --git a/chrome/test/data/autofill/heuristics/output/11_register_newegg.com.out b/chrome/test/data/autofill/heuristics/output/11_register_newegg.com.out index af2f9f2..924fbd3 100644 --- a/chrome/test/data/autofill/heuristics/output/11_register_newegg.com.out +++ b/chrome/test/data/autofill/heuristics/output/11_register_newegg.com.out @@ -17,6 +17,8 @@ PHONE_HOME_CITY_CODE | BDayPhone_tel1 | Daytime Phone | PHONE_HOME_NUMBER | BDayPhone_tel2 | Exchange | PHONE_HOME_NUMBER | BDayPhone_tel3 | Last four digits | UNKNOWN_TYPE | BDayPhone_ext1 | Ext | +UNKNOWN_TYPE | same | Is this your shipping address?* | 1 +UNKNOWN_TYPE | same | Yes No | 0 NAME_FIRST | SFirstName | First Name* | NAME_MIDDLE_INITIAL | SMI | MI | NAME_LAST | SLastName | Last Name* | @@ -37,3 +39,5 @@ UNKNOWN_TYPE | education | Education | 0 UNKNOWN_TYPE | hob | Where did you hear about Newegg.com? | 0 UNKNOWN_TYPE | FirstPurchase | Is this your first Newegg.com purchase? | 0 UNKNOWN_TYPE | GameHours | How many hours per week do you play PC games? | 0 +UNKNOWN_TYPE | Spam | Sign me up for exclusive newsletter deals, sweepstakes, and 24-hour sales only available to subscribers | 1 +UNKNOWN_TYPE | SMS | I would like to receive SMS messages via my wireless device. | 1 diff --git a/chrome/test/data/autofill/heuristics/output/12_register_officedepot.com.out b/chrome/test/data/autofill/heuristics/output/12_register_officedepot.com.out index f5212b9..fea11d1 100644 --- a/chrome/test/data/autofill/heuristics/output/12_register_officedepot.com.out +++ b/chrome/test/data/autofill/heuristics/output/12_register_officedepot.com.out @@ -20,6 +20,7 @@ CREDIT_CARD_NUMBER | paymentFormInfo.creditCardNumber | Credit Card Number: | CREDIT_CARD_EXP_MONTH | paymentFormInfo.creditCardExpMonth | Expiration Date: | CREDIT_CARD_EXP_4_DIGIT_YEAR | paymentFormInfo.creditCardExpYear | / | -1 CREDIT_CARD_VERIFICATION_CODE | paymentFormInfo.creditCardCvv | CID | +UNKNOWN_TYPE | sameAsBilling | Currently Office Depot is unable to process orders online for delivery to APO/FPO, PO Box, and export addresses. Please click here for additional ordering options * Indicates required field | on NAME_FIRST | addrsForm[2].firstName | *First Name: | NAME_MIDDLE_INITIAL | addrsForm[2].middleInitial | Middle Initial: | NAME_LAST | addrsForm[2].lastName | *Last Name: | @@ -35,3 +36,4 @@ PHONE_HOME_NUMBER | addrsForm[2].phoneNumber3 | - | UNKNOWN_TYPE | addrsForm[2].phoneNumber4 | ext. | EMAIL_ADDRESS | addrsForm[2].email | *Email Address: | UNKNOWN_TYPE | loginForm.loginName | *Login Name: | +UNKNOWN_TYPE | loginForm.autoLogin | *Password Confirm: retype your password | on diff --git a/chrome/test/data/autofill/heuristics/output/12_register_pyramidcollection.com.out b/chrome/test/data/autofill/heuristics/output/12_register_pyramidcollection.com.out index 16e2d49..b17bcfb 100644 --- a/chrome/test/data/autofill/heuristics/output/12_register_pyramidcollection.com.out +++ b/chrome/test/data/autofill/heuristics/output/12_register_pyramidcollection.com.out @@ -19,3 +19,4 @@ ADDRESS_HOME_COUNTRY | SC3 | Country * | 0000 ADDRESS_HOME_ZIP | SZ1 | Zip Code * | PHONE_HOME_WHOLE_NUMBER | SP2 | Day Phone * | PHONE_HOME_WHOLE_NUMBER | SP3 | Evening Phone | +UNKNOWN_TYPE | sameAsBilling | Email Address * First Name * Last Name Address Line 1 First Name Last Name | on diff --git a/chrome/test/data/autofill/heuristics/output/12_register_rediff.com.out b/chrome/test/data/autofill/heuristics/output/12_register_rediff.com.out index 628660d..3d9bed8 100644 --- a/chrome/test/data/autofill/heuristics/output/12_register_rediff.com.out +++ b/chrome/test/data/autofill/heuristics/output/12_register_rediff.com.out @@ -1,11 +1,14 @@ NAME_FULL | name | : | UNKNOWN_TYPE | login | : | EMAIL_ADDRESS | altemail | : | +UNKNOWN_TYPE | chk_altemail | | on UNKNOWN_TYPE | hintq | : | UNKNOWN_TYPE | mothername | : | UNKNOWN_TYPE | DOB_Day | : | UNKNOWN_TYPE | DOB_Month | : | UNKNOWN_TYPE | DOB_Year | : | +UNKNOWN_TYPE | gender | : | m +UNKNOWN_TYPE | gender | Male | f ADDRESS_HOME_COUNTRY | country | : | 99 ADDRESS_HOME_CITY | city | : | UNKNOWN_TYPE | othercity | City : | diff --git a/chrome/test/data/autofill/heuristics/output/12_register_rei.com.out b/chrome/test/data/autofill/heuristics/output/12_register_rei.com.out index f8946ee..c35912ae 100644 --- a/chrome/test/data/autofill/heuristics/output/12_register_rei.com.out +++ b/chrome/test/data/autofill/heuristics/output/12_register_rei.com.out @@ -3,3 +3,4 @@ NAME_MIDDLE_INITIAL | middleName | Middle Initial: | NAME_LAST | lastName | Last Name:* | ADDRESS_HOME_ZIP | zipCode | ZIP (Postal) Code:* | EMAIL_ADDRESS | email1 | E-mail Address:* | +UNKNOWN_TYPE | gearmail | | y diff --git a/chrome/test/data/autofill/heuristics/output/13_register_rocketlawyer.com.out b/chrome/test/data/autofill/heuristics/output/13_register_rocketlawyer.com.out index bdfc780..5219e25 100644 --- a/chrome/test/data/autofill/heuristics/output/13_register_rocketlawyer.com.out +++ b/chrome/test/data/autofill/heuristics/output/13_register_rocketlawyer.com.out @@ -3,3 +3,4 @@ NAME_FIRST | ctl00$ctl00$ctl00$SiteMasterBody$ContentPlaceHolder1$ContentPlaceHo NAME_LAST | ctl00$ctl00$ctl00$SiteMasterBody$ContentPlaceHolder1$ContentPlaceHolder1$txtLastName | Last Name * | EMAIL_ADDRESS | ctl00$ctl00$ctl00$SiteMasterBody$ContentPlaceHolder1$ContentPlaceHolder1$txtUserName | Email Address * | EMAIL_ADDRESS | ctl00$ctl00$ctl00$SiteMasterBody$ContentPlaceHolder1$ContentPlaceHolder1$txtConfirmUserName | Confirm Email Address * | +UNKNOWN_TYPE | ctl00$ctl00$ctl00$SiteMasterBody$ContentPlaceHolder1$ContentPlaceHolder1$chkNewsletter | Yes, send me Rocket Lawyer partner offers, which are sent no more than twice per month and are from Rocket Lawyer's trusted business partners. | on diff --git a/chrome/test/data/autofill/heuristics/output/13_register_signup.clicksor.com.out b/chrome/test/data/autofill/heuristics/output/13_register_signup.clicksor.com.out index d10e60e..cd72aa2 100644 --- a/chrome/test/data/autofill/heuristics/output/13_register_signup.clicksor.com.out +++ b/chrome/test/data/autofill/heuristics/output/13_register_signup.clicksor.com.out @@ -10,4 +10,5 @@ ADDRESS_HOME_CITY | city | City: | ADDRESS_HOME_STATE | province | State: | ADDRESS_HOME_ZIP | zipCode | Zip code: | ADDRESS_HOME_COUNTRY | country | Country: | US +UNKNOWN_TYPE | termcheck | Country: | ON UNKNOWN_TYPE | securityCode | Enter the security code shown below: | diff --git a/chrome/test/data/autofill/heuristics/output/13_register_signup.live.com.out b/chrome/test/data/autofill/heuristics/output/13_register_signup.live.com.out index 0675335..8e45ebab 100644 --- a/chrome/test/data/autofill/heuristics/output/13_register_signup.live.com.out +++ b/chrome/test/data/autofill/heuristics/output/13_register_signup.live.com.out @@ -9,4 +9,7 @@ UNKNOWN_TYPE | iSQ | Question: | 0 UNKNOWN_TYPE | iSA | Secret answer: | NAME_FIRST | iFirstName | First name: | NAME_LAST | iLastName | Last name: | +UNKNOWN_TYPE | profile_gender | | m +UNKNOWN_TYPE | profile_gender | | f UNKNOWN_TYPE | iBirthYear | Birth year: | Example: 1990 +UNKNOWN_TYPE | iOptinEmail | Send me email with promotional offers and survey invitations from Windows Live, Bing, and MSN. (You can unsubscribe at any time.) | on diff --git a/chrome/test/data/autofill/heuristics/output/13_register_sourceforge.net.out b/chrome/test/data/autofill/heuristics/output/13_register_sourceforge.net.out index fae3fb3..0f270d8 100644 --- a/chrome/test/data/autofill/heuristics/output/13_register_sourceforge.net.out +++ b/chrome/test/data/autofill/heuristics/output/13_register_sourceforge.net.out @@ -9,5 +9,8 @@ UNKNOWN_TYPE | X3WlBZtvcy22yEf0KrDfhs46rigU | Security Question: | UNKNOWN_TYPE | X3XlRdtrBz0a6O_kXqynrr46rigU | Security Answer: | UNKNOWN_TYPE | X0WBbd4KZLSgCIb8WlZZNJ3g3fVk | Job Title: | UNKNOWN_TYPE | X229ZZcPc31emF7VTU0RPmITuTNc | Number of Employees: | +UNKNOWN_TYPE | X12VEYcbdixhIflk8_zHDFWB72qk | | siteupdates +UNKNOWN_TYPE | X12VEYcbdixhIflk8_zHDFWB72qk | | research +UNKNOWN_TYPE | X12VEYcbdixhIflk8_zHDFWB72qk | | thirdparty UNKNOWN_TYPE | X1GJbe8rKlh_p74K4nXnhkGtC-8Q | You seem to have CSS turned off. Please don't fill out this field. | UNKNOWN_TYPE | X1GJbe8rKlx_p74K4nXnhkGtC-8Q | You seem to have CSS turned off. Please don't fill out this field. | diff --git a/chrome/test/data/autofill/heuristics/output/13_register_supershuttle.com.out b/chrome/test/data/autofill/heuristics/output/13_register_supershuttle.com.out index 879489a..5f14a5f 100644 --- a/chrome/test/data/autofill/heuristics/output/13_register_supershuttle.com.out +++ b/chrome/test/data/autofill/heuristics/output/13_register_supershuttle.com.out @@ -5,3 +5,4 @@ NAME_LAST | ctl00$cphRight$Registration1$txtLastName | Last Name | PHONE_HOME_WHOLE_NUMBER | ctl00$cphRight$Registration1$txtCellPhone | Contact or Cell Phone Number | PHONE_HOME_COUNTRY_CODE | ctl00$cphRight$Registration1$txtCountryCode | If outside the US (Country Code/Phone Number) | PHONE_HOME_CITY_AND_NUMBER | ctl00$cphRight$Registration1$txtIntPhoneNumber | Contact or Cell Phone Number | +UNKNOWN_TYPE | ctl00$cphRight$Registration1$chkAcceptSpecialOffers | Email me regarding SuperShuttle special offers and promotions | on diff --git a/chrome/test/data/autofill/heuristics/output/14_register_target.com.out b/chrome/test/data/autofill/heuristics/output/14_register_target.com.out index 86af5f9..92dc099 100644 --- a/chrome/test/data/autofill/heuristics/output/14_register_target.com.out +++ b/chrome/test/data/autofill/heuristics/output/14_register_target.com.out @@ -1,3 +1,6 @@ UNKNOWN_TYPE | userName | Your name:* | EMAIL_ADDRESS | email | Your email address:* | EMAIL_ADDRESS | emailCheck | Re-enter email address:* | +UNKNOWN_TYPE | subscribeEmail | Yes, please send me e-mails about special offers, exclusives and promotions from Target. | 1 +UNKNOWN_TYPE | ageCheck | | yes +UNKNOWN_TYPE | ageCheck | Yes No | no diff --git a/chrome/test/data/autofill/heuristics/output/14_register_threadless.com.out b/chrome/test/data/autofill/heuristics/output/14_register_threadless.com.out index 01983b6..970a420 100644 --- a/chrome/test/data/autofill/heuristics/output/14_register_threadless.com.out +++ b/chrome/test/data/autofill/heuristics/output/14_register_threadless.com.out @@ -1,3 +1,4 @@ UNKNOWN_TYPE | create_username | Desired username | EMAIL_ADDRESS | email | Email | +UNKNOWN_TYPE | join_newsletter | Join our newsletter and be first to know about new tees and great deals! | on UNKNOWN_TYPE | recaptcha_response_field | Type the words above Type the numbers you hear | diff --git a/chrome/test/data/autofill/heuristics/output/15_crbug_53075.out b/chrome/test/data/autofill/heuristics/output/15_crbug_53075.out index a31a732..fdb5c1fd 100644 --- a/chrome/test/data/autofill/heuristics/output/15_crbug_53075.out +++ b/chrome/test/data/autofill/heuristics/output/15_crbug_53075.out @@ -11,6 +11,7 @@ ADDRESS_HOME_CITY | ecomms_town | Town / City: | ADDRESS_HOME_STATE | ecomms_county | County: | ADDRESS_HOME_ZIP | ecomms_postcode | Postcode: | ADDRESS_HOME_COUNTRY | ecomms_country | Country: | 224 +UNKNOWN_TYPE | delivery_address | Address Details Address1: Address2: Town / City: County: | 1 UNKNOWN_TYPE | del_title | Title: | NAME_FIRST | del_first_name | First Name: | NAME_LAST | del_last_name | Last Name: | diff --git a/chrome/test/data/autofill/heuristics/output/15_crbug_64569.out b/chrome/test/data/autofill/heuristics/output/15_crbug_64569.out index e828b7a..fc966fb 100644 --- a/chrome/test/data/autofill/heuristics/output/15_crbug_64569.out +++ b/chrome/test/data/autofill/heuristics/output/15_crbug_64569.out @@ -1,8 +1,11 @@ +UNKNOWN_TYPE | payment_group | Payment Type We accept Visa, Mastercard, Discover, American Express, and PayPal. | cc +UNKNOWN_TYPE | payment_group | Payment Type We accept Visa, Mastercard, Discover, American Express, and PayPal. | paypal CREDIT_CARD_NAME | ccFullName | (as it appears on the card) | CREDIT_CARD_NUMBER | ccNumber | (no dashes or spaces) | CREDIT_CARD_EXP_MONTH | ccExpMonth | Expiration date | 1 CREDIT_CARD_EXP_4_DIGIT_YEAR | ccExpYear | Your name (as it appears on the card) Credit card number (no dashes or spaces) Expiration date | 2011 CREDIT_CARD_VERIFICATION_CODE | ccSecurity | Security code | +UNKNOWN_TYPE | sameinfo | First name Last name | on NAME_FIRST | addrFirstName | First name | NAME_LAST | addrLastName | Last name | ADDRESS_HOME_LINE1 | addrStreet1 | (street address, PO box, company name) | diff --git a/chrome/test/data/autofill/heuristics/output/16_crbug_87517.out b/chrome/test/data/autofill/heuristics/output/16_crbug_87517.out index 329f677..f0efa59 100644 --- a/chrome/test/data/autofill/heuristics/output/16_crbug_87517.out +++ b/chrome/test/data/autofill/heuristics/output/16_crbug_87517.out @@ -10,10 +10,19 @@ ADDRESS_HOME_COUNTRY | CC_COUNTRY | Country | United States PHONE_HOME_WHOLE_NUMBER | dphone | Telephone | EMAIL_ADDRESS | demail | Email * | UNKNOWN_TYPE | amt | $ | +UNKNOWN_TYPE | tributeSelect | Name * | on +UNKNOWN_TYPE | DonationType | Name * | OneTime +UNKNOWN_TYPE | DonationType | This is a one time donation | Recurs UNKNOWN_TYPE | ccrecurring | I would like to make this a recurring donation deducted | Monthly UNKNOWN_TYPE | remLen | ( You may enter up to 500 characters. ) | 500 +UNKNOWN_TYPE | tribute | | IHO +UNKNOWN_TYPE | tribute | In Honor Of | IMO NAME_FULL | Tribute_Name | Name: | UNKNOWN_TYPE | Tribute_occasion | Occasion: | +UNKNOWN_TYPE | Tribute_Disclosure | Occasion: | on +UNKNOWN_TYPE | Tribute_Notification | I wish to remain anonymous | on +UNKNOWN_TYPE | Tribute_IncludeAmount | | 1 +UNKNOWN_TYPE | Tribute_IncludeAmount | Include the amount | 0 NAME_FULL | Tribute_NotifyName | Name: | EMAIL_ADDRESS | Tribute_Email | Email: | ADDRESS_HOME_LINE1 | Tribute_NotifyAddr | Street: | @@ -25,6 +34,7 @@ CREDIT_CARD_NUMBER | ccard | Credit Card Number * | CREDIT_CARD_VERIFICATION_CODE | csc | CSC Number * What Is This? | CREDIT_CARD_EXP_MONTH | ExpMon | Month | 1 CREDIT_CARD_EXP_4_DIGIT_YEAR | ExpYear | Year | 11 +UNKNOWN_TYPE | SameAddress | Billing Address - | checkbox ADDRESS_HOME_LINE1 | CC_Addr | Address 1 * | ADDRESS_HOME_LINE2 | CC_Addr2 | Address 2 | ADDRESS_HOME_CITY | CC_City | City / State / Zip * | diff --git a/chrome/test/data/autofill/heuristics/output/16_crbug_98152.out b/chrome/test/data/autofill/heuristics/output/16_crbug_98152.out index f30ea74..96a0bd8 100644 --- a/chrome/test/data/autofill/heuristics/output/16_crbug_98152.out +++ b/chrome/test/data/autofill/heuristics/output/16_crbug_98152.out @@ -4,6 +4,7 @@ CREDIT_CARD_EXP_MONTH | CCForm.expirationMonth | Expiration date | 9 CREDIT_CARD_EXP_4_DIGIT_YEAR | CCForm.expirationYear | Expiration date | 2011 CREDIT_CARD_NAME | CCForm.name | Name as it appears on card | CREDIT_CARD_VERIFICATION_CODE | CCForm.cid | | +UNKNOWN_TYPE | isBillingAddress | Make the most of your shopping experience with the Walmart Discover® or Walmart Credit Card®. Learn More or Apply Now. Debit cards (also called check cards, ATM cards or bank cards) are accepted if they have a Visa or MasterCard logo. | on COMPANY_NAME | CCForm.companyName | Company Name | ADDRESS_HOME_LINE1 | addressForm.street1 | Address Line 1 | ADDRESS_HOME_LINE2 | addressForm.street2 | Address Line 2 | diff --git a/chrome/test/data/autofill/heuristics/output/16_crbug_98269.out b/chrome/test/data/autofill/heuristics/output/16_crbug_98269.out index 1a62e8e..7627710 100644 --- a/chrome/test/data/autofill/heuristics/output/16_crbug_98269.out +++ b/chrome/test/data/autofill/heuristics/output/16_crbug_98269.out @@ -1,3 +1,4 @@ +UNKNOWN_TYPE | PaymentMethod | | BL PHONE_HOME_CITY_CODE | txtHomePhone1 | * Home Phone: | PHONE_HOME_NUMBER | txtHomePhone2 | * Home Phone: | PHONE_HOME_NUMBER | txtHomePhone3 | * Home Phone: | @@ -6,9 +7,13 @@ UNKNOWN_TYPE | txtSSN | XXX-XX- | UNKNOWN_TYPE | selBirthMonth | * Date of Birth: | Month UNKNOWN_TYPE | selBirthDate | * Date of Birth: | Date UNKNOWN_TYPE | selBirthYear | * Date of Birth: | Year +UNKNOWN_TYPE | chkTAC | * | on +UNKNOWN_TYPE | PaymentMethod | | CK +UNKNOWN_TYPE | PaymentMethod | | AddNew CREDIT_CARD_TYPE | cardType | Type: | VI CREDIT_CARD_NUMBER | CreditCardNumber | Number: | CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR | CreditCardExpYYMM | Expiration: | 092011 CREDIT_CARD_VERIFICATION_CODE | CVV | Security Code: | +UNKNOWN_TYPE | useGiftCard | QVC Gift Cards | on UNKNOWN_TYPE | GiftCardNum | Card Number: | UNKNOWN_TYPE | GiftCardPIN | Security ID Number: | diff --git a/chrome/test/data/autofill/heuristics/output/16_crbug_98286.out b/chrome/test/data/autofill/heuristics/output/16_crbug_98286.out index 84dbe6e..65ec560 100644 --- a/chrome/test/data/autofill/heuristics/output/16_crbug_98286.out +++ b/chrome/test/data/autofill/heuristics/output/16_crbug_98286.out @@ -4,3 +4,4 @@ CREDIT_CARD_NUMBER | txtCreditCardNumber | *Card number: | CREDIT_CARD_EXP_MONTH | drpdwnExpirationMonth | *Expiration date: | 00 CREDIT_CARD_EXP_4_DIGIT_YEAR | drpdwnExpirationYear | *Expiration date: | 2011 CREDIT_CARD_VERIFICATION_CODE | txtVisaVerificationNumber | VISA Card Verification # | +UNKNOWN_TYPE | chkUnreadable | I can't read the numbers | on diff --git a/chrome/test/data/autofill/heuristics/output/20_register_alaskaair.com.out b/chrome/test/data/autofill/heuristics/output/20_register_alaskaair.com.out index 354c8a1..e2af6c2 100644 --- a/chrome/test/data/autofill/heuristics/output/20_register_alaskaair.com.out +++ b/chrome/test/data/autofill/heuristics/output/20_register_alaskaair.com.out @@ -1,3 +1,5 @@ +UNKNOWN_TYPE | FormUserControl$_mileagePlanNumber$_mileagePlanChoice | Mileage Plan™ Number * | _needMileagePlanNbr +UNKNOWN_TYPE | FormUserControl$_mileagePlanNumber$_mileagePlanChoice | I have an Alaska Airlines Mileage Plan Number | _haveMileagePlanNbr UNKNOWN_TYPE | FormUserControl$_mileagePlanNumber$_loyaltyNumber$_loyaltyNumber | Mileage Plan Number | NAME_FIRST | FormUserControl$_personalIdentification$_firstName$_name | Legal First Name* | UNKNOWN_TYPE | FormUserControl$_personalIdentification$_title$_title | Title | @@ -28,4 +30,8 @@ EMAIL_ADDRESS | FormUserControl$_contactInformation$_emailAddress$_emailAddressT UNKNOWN_TYPE | FormUserControl$_userIdPassword$_userId$_userId | Create a User ID* | UNKNOWN_TYPE | FormUserControl$_secretQuestion$_question | Secret Question* | UNKNOWN_TYPE | FormUserControl$_secretQuestion$_answer | Please choose a secret question and provide the answer. You will need to answer the question again in case you forget your password. Make sure you choose a question and answer that are easy for you to remember, but difficult for other people to know.Secret Question* Answer* | +UNKNOWN_TYPE | FormUserControl$_subscriptionsOffers$_insiderNewsletter$_subscriptionCheckBox | Insider NewsletterA weekly email personalized to provide you with an insider glimpse of the best deals we have to offer - across the board. | on ADDRESS_HOME_CITY | FormUserControl$_subscriptionsOffers$_primaryDepartureCity$_primaryDepartureCity$_city | Primary Departure City | +UNKNOWN_TYPE | FormUserControl$_subscriptionsOffers$_eStatements$_subscriptionCheckBox | Mileage Plan E-Statements and Partner OffersA monthly recap of your Mileage Plan activity along with program news, exclusive partner offers, and countless ways to earn free travel faster. | on +UNKNOWN_TYPE | FormUserControl$_subscriptionsOffers$_asQXAnnouncements$_subscriptionCheckBox | Alaska AnnouncementsOccasional email that puts you "in the know" about sales, promotions, and other important travel information. | on +UNKNOWN_TYPE | FormUserControl$_mpTermsAndConditions$_iAgree | Mileage Plan™ Terms & Conditions* I acknowledge that I have reviewed these Mileage Plan Terms and Conditions | on |