Index: chrome/browser/autofill/autofill_manager.cc |
=================================================================== |
--- chrome/browser/autofill/autofill_manager.cc (revision 71419) |
+++ chrome/browser/autofill/autofill_manager.cc (working copy) |
@@ -219,14 +219,15 @@ |
cached_upload_form_structure = NULL; |
} |
- DeterminePossibleFieldTypesForUpload(cached_upload_form_structure); |
+ std::string data_present = DeterminePossibleFieldTypesForUpload( |
+ cached_upload_form_structure); |
// TODO(isherman): Consider uploading to server here rather than in |
// HandleSubmit(). |
if (!upload_form_structure_->IsAutoFillable(true)) |
return; |
- HandleSubmit(); |
+ HandleSubmit(data_present); |
} |
void AutoFillManager::OnFormsSeen(const std::vector<FormData>& forms) { |
@@ -484,64 +485,82 @@ |
return prefs->GetBoolean(prefs::kAutoFillEnabled); |
} |
-void AutoFillManager::DeterminePossibleFieldTypesForUpload( |
+std::string AutoFillManager::DeterminePossibleFieldTypesForUpload( |
const FormStructure* cached_upload_form_structure) { |
+ // Mark bits present for the upload for data_present field. |
+ 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) >> 3); |
+ for (size_t i = 0; i < presence_bitfield.size(); ++i) |
+ presence_bitfield[i] = 0; |
+ |
for (size_t i = 0; i < upload_form_structure_->field_count(); i++) { |
const AutoFillField* field = upload_form_structure_->field(i); |
FieldTypeSet field_types; |
personal_data_->GetPossibleFieldTypes(field->value(), &field_types); |
- DCHECK(!field_types.empty()); |
- upload_form_structure_->set_possible_types(i, field_types); |
if (field->form_control_type() == ASCIIToUTF16("select-one")) { |
// TODO(isherman): <select> fields don't support |is_autofilled()|. Since |
// this is heavily relied upon by our metrics, we just don't log anything |
// for all <select> fields. Better to have less data than misleading data. |
- continue; |
- } |
+ } else { |
+ // Log various quality metrics. |
+ metric_logger_->Log(AutoFillMetrics::FIELD_SUBMITTED); |
+ if (field_types.find(EMPTY_TYPE) == field_types.end() && |
+ field_types.find(UNKNOWN_TYPE) == field_types.end()) { |
+ if (field->is_autofilled()) { |
+ metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILLED); |
+ } else { |
+ metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED); |
- // Log various quality metrics. |
- metric_logger_->Log(AutoFillMetrics::FIELD_SUBMITTED); |
- if (field_types.find(EMPTY_TYPE) == field_types.end() && |
- field_types.find(UNKNOWN_TYPE) == field_types.end()) { |
- if (field->is_autofilled()) { |
- metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILLED); |
- } else { |
- metric_logger_->Log(AutoFillMetrics::FIELD_AUTOFILL_FAILED); |
+ AutoFillFieldType heuristic_type = cached_upload_form_structure? |
+ cached_upload_form_structure->field(i)->heuristic_type() : |
+ UNKNOWN_TYPE; |
+ if (heuristic_type == UNKNOWN_TYPE) |
+ metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN); |
+ else if (field_types.count(heuristic_type)) |
+ metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH); |
+ else |
+ metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH); |
- AutoFillFieldType heuristic_type = cached_upload_form_structure? |
- cached_upload_form_structure->field(i)->heuristic_type() : |
- UNKNOWN_TYPE; |
- if (heuristic_type == UNKNOWN_TYPE) |
- metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_UNKNOWN); |
- else if (field_types.count(heuristic_type)) |
- metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MATCH); |
- else |
- metric_logger_->Log(AutoFillMetrics::FIELD_HEURISTIC_TYPE_MISMATCH); |
+ AutoFillFieldType server_type = cached_upload_form_structure? |
+ cached_upload_form_structure->field(i)->server_type() : |
+ NO_SERVER_DATA; |
+ if (server_type == NO_SERVER_DATA) |
+ metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN); |
+ else if (field_types.count(server_type)) |
+ metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_MATCH); |
+ else |
+ metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH); |
+ } |
- AutoFillFieldType server_type = cached_upload_form_structure? |
- cached_upload_form_structure->field(i)->server_type() : |
- NO_SERVER_DATA; |
- if (server_type == NO_SERVER_DATA) |
- metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_UNKNOWN); |
- else if (field_types.count(server_type)) |
- metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_MATCH); |
- else |
- metric_logger_->Log(AutoFillMetrics::FIELD_SERVER_TYPE_MISMATCH); |
+ |
+ // TODO(isherman): Other things we might want to log here: |
+ // * Per Vadim's email, a combination of (1) whether heuristics fired, |
+ // (2) whether the server returned something interesting, (3) whether |
+ // the user filled the field |
+ // * Whether the server type matches the heursitic type |
+ // - Perhaps only if at least one of the types is not unknown/no data. |
} |
+ } |
+ DCHECK(!field_types.empty()); |
+ if (field_types.size() > 1) { |
+ // If there is more than one possibility, do not poison the crowd-sourced |
+ // data by returning UNKNOWN_TYPE. |
+ field_types.clear(); |
+ field_types.insert(UNKNOWN_TYPE); |
+ } |
+ upload_form_structure_->set_possible_types(i, field_types); |
+ SetPresenceBit(*(field_types.begin()), &presence_bitfield); |
+ } |
- // TODO(isherman): Other things we might want to log here: |
- // * Per Vadim's email, a combination of (1) whether heuristics fired, |
- // (2) whether the server returned something interesting, (3) whether |
- // the user filled the field |
- // * Whether the server type matches the heursitic type |
- // - Perhaps only if at least one of the types is not unknown/no data. |
- } |
- } |
+ return ConvertPresenceBitsToString(presence_bitfield); |
} |
-void AutoFillManager::HandleSubmit() { |
+void AutoFillManager::HandleSubmit(std::string const& data_present) { |
// If there wasn't enough data to import then we don't want to send an upload |
// to the server. |
// TODO(jhawkins): Import form data from |form_structures_|. That will |
@@ -557,8 +576,11 @@ |
personal_data_->GetImportedFormData(&profile, &credit_card); |
if (!credit_card) { |
- UploadFormData(); |
+ data_autofilled_.clear(); |
+ UploadFormData(data_present); |
return; |
+ } else { |
+ data_autofilled_ = data_present; |
} |
// Show an infobar to offer to save the credit card info. |
@@ -568,7 +590,7 @@ |
} |
} |
-void AutoFillManager::UploadFormData() { |
+void AutoFillManager::UploadFormData(std::string const& data_present) { |
if (!disable_download_manager_requests_ && upload_form_structure_.get()) { |
bool was_autofilled = false; |
// Check if the form among last 3 forms that were auto-filled. |
@@ -578,8 +600,9 @@ |
for (it = autofilled_forms_signatures_.begin(); |
it != autofilled_forms_signatures_.end() && total_form_checked < 3; |
++it, ++total_form_checked) { |
- if (*it == upload_form_structure_->FormSignature()) |
+ if (*it == upload_form_structure_->FormSignature()) { |
was_autofilled = true; |
+ } |
} |
// Remove outdated form signatures. |
if (total_form_checked == 3 && it != autofilled_forms_signatures_.end()) { |
@@ -587,7 +610,8 @@ |
autofilled_forms_signatures_.end()); |
} |
download_manager_.StartUploadRequest(*(upload_form_structure_.get()), |
- was_autofilled); |
+ was_autofilled, |
+ data_present.c_str()); |
} |
} |
@@ -596,10 +620,34 @@ |
form_structures_.reset(); |
} |
+void AutoFillManager::SetPresenceBit(AutoFillFieldType field_type, |
+ std::vector<uint8>* bitfield) { |
+ DCHECK(bitfield); |
+ DCHECK(bitfield->size() > (static_cast<size_t>(field_type) >> 3)); |
+ // Set bit in the bitfield: byte |field_type| / 8, bit in byte |
+ // |field_type| % 8 from the left. |
+ (*bitfield)[field_type >> 3] |= (0x80 >> (field_type & 7)); |
+} |
+ |
+std::string AutoFillManager::ConvertPresenceBitsToString( |
+ std::vector<uint8> const& bitfield) { |
+ std::string present_data; |
+ present_data.reserve(bitfield.size() * 2 + 1); |
+ // Skip leading zeroes. If all mask is 0 - return empty string. |
+ size_t data_end = bitfield.size(); |
+ for (; data_end > 0 && !bitfield[data_end - 1]; --data_end) { |
+ } |
+ // Print all non-zero bytes into the string. |
+ for (size_t i = 0; i < data_end; ++i) { |
+ base::StringAppendF(&present_data, "%02x", bitfield[i]); |
+ } |
+ return present_data; |
+} |
+ |
void AutoFillManager::OnInfoBarClosed(bool should_save) { |
if (should_save) |
personal_data_->SaveImportedCreditCard(); |
- UploadFormData(); |
+ UploadFormData(data_autofilled_); |
} |
AutoFillManager::AutoFillManager() |