| 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()
|
|
|