Index: chrome/browser/autofill/form_structure.cc |
diff --git a/chrome/browser/autofill/form_structure.cc b/chrome/browser/autofill/form_structure.cc |
index ce38d808c215a582f94f3e9117a90aa37694c022..fc335fd6e713172dc578468b52bcb28b7dd4d381 100644 |
--- a/chrome/browser/autofill/form_structure.cc |
+++ b/chrome/browser/autofill/form_structure.cc |
@@ -41,6 +41,42 @@ const char kXMLElementField[] = "field"; |
// The number of fillable fields necessary for a form to be fillable. |
const size_t kRequiredFillableFields = 3; |
+// Helper for |EncodeUploadRequest()| that creates a bit field corresponding to |
+// |available_field_types| and returns the hex representation as a string. |
+std::string EncodeFieldTypes(const FieldTypeSet& available_field_types) { |
+ // There are |MAX_VALID_FIELD_TYPE| different field types and 8 bits per byte, |
+ // so we need ceil(MAX_VALID_FIELD_TYPE / 8) bytes to encode the bit field. |
+ const size_t kNumBytes = (MAX_VALID_FIELD_TYPE + 0x7) / 8; |
+ |
+ // Pack the types in |available_field_types| into |bit_field|. |
+ std::vector<uint8> bit_field(kNumBytes, 0); |
+ for (FieldTypeSet::const_iterator field_type = available_field_types.begin(); |
+ field_type != available_field_types.end(); |
+ ++field_type) { |
+ // Set the appropriate bit in the field. The bit we set is the one |
+ // |field_type| % 8 from the left of the byte. |
+ const size_t byte = *field_type / 8; |
+ const size_t bit = 0x80 >> (*field_type % 8); |
+ DCHECK(byte < bit_field.size()); |
+ bit_field[byte] |= bit; |
+ } |
+ |
+ // Discard any trailing zeroes. |
+ // If there are no available types, we return the empty string. |
+ size_t data_end = bit_field.size(); |
+ for (; data_end > 0 && !bit_field[data_end - 1]; --data_end) { |
+ } |
+ |
+ // Print all meaningfull bytes into a string. |
+ std::string data_presence; |
+ data_presence.reserve(data_end * 2 + 1); |
+ for (size_t i = 0; i < data_end; ++i) { |
+ base::StringAppendF(&data_presence, "%02x", bit_field[i]); |
+ } |
+ |
+ return data_presence; |
+} |
+ |
} // namespace |
FormStructure::FormStructure(const FormData& form) |
@@ -99,14 +135,28 @@ void FormStructure::DetermineHeuristicTypes() { |
} |
} |
-bool FormStructure::EncodeUploadRequest(bool autofill_used, |
- std::string* encoded_xml) const { |
- DCHECK(encoded_xml); |
- encoded_xml->clear(); |
- bool autofillable = ShouldBeParsed(true); |
- DCHECK(autofillable); // Caller should've checked for search pages. |
- if (!autofillable) |
+bool FormStructure::EncodeUploadRequest( |
+ const FieldTypeSet& available_field_types, |
+ bool form_was_autofilled, |
+ std::string* encoded_xml) const { |
+ if (!ShouldBeParsed(true)) { |
+ NOTREACHED(); // Caller should've checked for search pages. |
return false; |
+ } |
+ |
+ // Verify that |available_field_types| agrees with the possible field types we |
+ // are uploading. |
+ for (std::vector<AutofillField*>::const_iterator field = begin(); |
+ field != end(); |
+ ++field) { |
+ for (FieldTypeSet::const_iterator type = (*field)->possible_types().begin(); |
+ type != (*field)->possible_types().end(); |
+ ++type) { |
+ DCHECK(*type == UNKNOWN_TYPE || |
+ *type == EMPTY_TYPE || |
+ available_field_types.count(*type)); |
+ } |
+ } |
// Set up the <autofillupload> element and its attributes. |
buzz::XmlElement autofill_request_xml( |
@@ -116,14 +166,15 @@ bool FormStructure::EncodeUploadRequest(bool autofill_used, |
autofill_request_xml.SetAttr(buzz::QName(kAttributeFormSignature), |
FormSignature()); |
autofill_request_xml.SetAttr(buzz::QName(kAttributeAutofillUsed), |
- autofill_used ? "true" : "false"); |
+ form_was_autofilled ? "true" : "false"); |
autofill_request_xml.SetAttr(buzz::QName(kAttributeDataPresent), |
- ConvertPresenceBitsToString().c_str()); |
+ EncodeFieldTypes(available_field_types).c_str()); |
if (!EncodeFormRequest(FormStructure::UPLOAD, &autofill_request_xml)) |
return false; // Malformed form, skip it. |
// Obtain the XML structure as a string. |
+ encoded_xml->clear(); |
*encoded_xml = kXMLDeclaration; |
*encoded_xml += autofill_request_xml.Str().c_str(); |
@@ -540,42 +591,3 @@ bool FormStructure::EncodeFormRequest( |
} |
return true; |
} |
- |
-std::string FormStructure::ConvertPresenceBitsToString() const { |
- std::vector<uint8> presence_bitfield; |
- // Determine all of the field types that were autofilled. Pack bits into |
- // |presence_bitfield|. The necessary size for |presence_bitfield| is |
- // ceil((MAX_VALID_FIELD_TYPE + 7) / 8) bytes (uint8). |
- presence_bitfield.resize((MAX_VALID_FIELD_TYPE + 0x7) / 8); |
- for (size_t i = 0; i < presence_bitfield.size(); ++i) |
- presence_bitfield[i] = 0; |
- |
- for (size_t i = 0; i < field_count(); ++i) { |
- const AutofillField* field = fields_[i]; |
- FieldTypeSet types = field->possible_types(); |
- // |types| could be empty in unit-tests only. |
- for (FieldTypeSet::iterator field_type = types.begin(); |
- field_type != types.end(); ++field_type) { |
- DCHECK(presence_bitfield.size() > (static_cast<size_t>(*field_type) / 8)); |
- // Set bit in the bitfield: byte |field_type| / 8, bit in byte |
- // |field_type| % 8 from the left. |
- presence_bitfield[*field_type / 8] |= (0x80 >> (*field_type % 8)); |
- } |
- } |
- |
- std::string data_presence; |
- data_presence.reserve(presence_bitfield.size() * 2 + 1); |
- |
- // Skip trailing zeroes. If all mask is 0 - return empty string. |
- size_t data_end = presence_bitfield.size(); |
- for (; data_end > 0 && !presence_bitfield[data_end - 1]; --data_end) { |
- } |
- |
- // Print all meaningfull bytes into the string. |
- for (size_t i = 0; i < data_end; ++i) { |
- base::StringAppendF(&data_presence, "%02x", presence_bitfield[i]); |
- } |
- |
- return data_presence; |
-} |
- |