Index: components/autofill/core/browser/autofill_metrics.cc |
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc |
index e813b1836f15f987cf2b02cadc879399f5e49b74..77442395f201073a68feac7dc21890f545343393 100644 |
--- a/components/autofill/core/browser/autofill_metrics.cc |
+++ b/components/autofill/core/browser/autofill_metrics.cc |
@@ -5,6 +5,8 @@ |
#include "components/autofill/core/browser/autofill_metrics.h" |
#include <algorithm> |
+#include <utility> |
+#include <vector> |
#include "base/logging.h" |
#include "base/metrics/histogram_macros.h" |
@@ -12,6 +14,7 @@ |
#include "base/metrics/user_metrics.h" |
#include "base/time/time.h" |
#include "components/autofill/core/browser/autofill_experiments.h" |
+#include "components/autofill/core/browser/autofill_field.h" |
#include "components/autofill/core/browser/autofill_type.h" |
#include "components/autofill/core/browser/form_structure.h" |
#include "components/autofill/core/common/form_data.h" |
@@ -22,6 +25,28 @@ const char kUKMCardUploadDecisionEntryName[] = "Autofill.CardUploadDecision"; |
const char kUKMCardUploadDecisionMetricName[] = "UploadDecision"; |
const char kUKMDeveloperEngagementEntryName[] = "Autofill.DeveloperEngagement"; |
const char kUKMDeveloperEngagementMetricName[] = "DeveloperEngagement"; |
+const char kUKMMillisecondsSinceFormLoadedMetricName[] = |
+ "MillisecondsSinceFormLoaded"; |
+const char kUKMInteractedWithFormEntryName[] = "Autofill.InteractedWithForm"; |
+const char kUKMIsForCreditCardMetricName[] = "IsForCreditCard"; |
+const char kUKMLocalRecordTypeCountMetricName[] = "LocalRecordTypeCount"; |
+const char kUKMServerRecordTypeCountMetricName[] = "ServerRecordTypeCount"; |
+const char kUKMSuggestionsShownEntryName[] = "Autofill.SuggestionsShown"; |
+const char kUKMSelectedMaskedServerCardEntryName[] = |
+ "Autofill.SelectedMaskedServerCard"; |
+const char kUKMSuggestionFilledEntryName[] = "Autofill.SuggestionFilled"; |
+const char kUKMRecordTypeMetricName[] = "RecordType"; |
+const char kUKMTextFieldDidChangeEntryName[] = "Autofill.TextFieldDidChange"; |
+const char kUKMFieldTypeGroupMetricName[] = "FieldTypeGroup"; |
+const char kUKMHeuristicTypeMetricName[] = "HeuristicType"; |
+const char kUKMServerTypeMetricName[] = "ServerType"; |
+const char kUKMHtmlFieldTypeMetricName[] = "HtmlFieldType"; |
+const char kUKMHtmlFieldModeMetricName[] = "HtmlFieldMode"; |
+const char kUKMIsAutofilledMetricName[] = "IsAutofilled"; |
+const char kUKMIsEmptyMetricName[] = "IsEmpty"; |
+const char kUKMFormSubmittedEntryName[] = "Autofill.AutofillFormSubmitted"; |
+const char kUKMAutofillFormSubmittedStateMetricName[] = |
+ "AutofillFormSubmittedState"; |
} // namespace internal |
namespace autofill { |
@@ -616,7 +641,8 @@ void AutofillMetrics::LogProfileActionOnFormSubmitted( |
// static |
void AutofillMetrics::LogAutofillFormSubmittedState( |
- AutofillFormSubmittedState state) { |
+ AutofillFormSubmittedState state, |
+ AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) { |
UMA_HISTOGRAM_ENUMERATION("Autofill.FormSubmittedState", state, |
AUTOFILL_FORM_SUBMITTED_STATE_ENUM_SIZE); |
@@ -650,6 +676,7 @@ void AutofillMetrics::LogAutofillFormSubmittedState( |
NOTREACHED(); |
break; |
} |
+ form_interactions_ukm_logger->LogFormSubmitted(state); |
} |
// static |
@@ -706,7 +733,7 @@ void AutofillMetrics::LogCardUploadDecisionUkm( |
if (upload_decision >= AutofillMetrics::NUM_CARD_UPLOAD_DECISION_METRICS) |
return; |
- const std::map<std::string, int> metrics = { |
+ const std::vector<std::pair<const char*, int>> metrics = { |
{internal::kUKMCardUploadDecisionMetricName, |
static_cast<int>(upload_decision)}}; |
LogUkm(ukm_service, url, internal::kUKMCardUploadDecisionEntryName, metrics); |
@@ -716,18 +743,22 @@ void AutofillMetrics::LogCardUploadDecisionUkm( |
void AutofillMetrics::LogDeveloperEngagementUkm( |
ukm::UkmService* ukm_service, |
const GURL& url, |
- AutofillMetrics::DeveloperEngagementMetric metric) { |
- const std::map<std::string, int> form_structure_metrics = { |
- {internal::kUKMDeveloperEngagementMetricName, static_cast<int>(metric)}}; |
+ std::vector<AutofillMetrics::DeveloperEngagementMetric> metrics) { |
+ std::vector<std::pair<const char*, int>> form_structure_metrics; |
+ for (const auto it : metrics) |
+ form_structure_metrics.push_back( |
+ {internal::kUKMDeveloperEngagementMetricName, static_cast<int>(it)}); |
+ |
LogUkm(ukm_service, url, internal::kUKMDeveloperEngagementEntryName, |
form_structure_metrics); |
} |
// static |
-bool AutofillMetrics::LogUkm(ukm::UkmService* ukm_service, |
- const GURL& url, |
- const std::string& ukm_entry_name, |
- const std::map<std::string, int>& metrics) { |
+bool AutofillMetrics::LogUkm( |
+ ukm::UkmService* ukm_service, |
+ const GURL& url, |
+ const std::string& ukm_entry_name, |
+ const std::vector<std::pair<const char*, int>>& metrics) { |
if (!IsUkmLoggingEnabled() || !ukm_service || !url.is_valid() || |
metrics.empty()) { |
return false; |
@@ -739,16 +770,18 @@ bool AutofillMetrics::LogUkm(ukm::UkmService* ukm_service, |
ukm_service->GetEntryBuilder(source_id, ukm_entry_name.c_str()); |
for (auto it = metrics.begin(); it != metrics.end(); ++it) { |
- builder->AddMetric(it->first.c_str(), it->second); |
+ builder->AddMetric(it->first, it->second); |
} |
return true; |
} |
-AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card) |
+AutofillMetrics::FormEventLogger::FormEventLogger( |
+ bool is_for_credit_card, |
+ AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger) |
: is_for_credit_card_(is_for_credit_card), |
- is_server_data_available_(false), |
- is_local_data_available_(false), |
+ server_record_type_count_(0), |
+ local_record_type_count_(0), |
is_context_secure_(false), |
has_logged_interacted_(false), |
has_logged_suggestions_shown_(false), |
@@ -757,11 +790,15 @@ AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card) |
has_logged_will_submit_(false), |
has_logged_submitted_(false), |
logged_suggestion_filled_was_server_data_(false), |
- logged_suggestion_filled_was_masked_server_card_(false) {} |
+ logged_suggestion_filled_was_masked_server_card_(false), |
+ form_interactions_ukm_logger_(form_interactions_ukm_logger) {} |
void AutofillMetrics::FormEventLogger::OnDidInteractWithAutofillableForm() { |
if (!has_logged_interacted_) { |
has_logged_interacted_ = true; |
+ form_interactions_ukm_logger_->LogInteractedWithForm( |
+ is_for_credit_card_, local_record_type_count_, |
+ server_record_type_count_); |
Log(AutofillMetrics::FORM_EVENT_INTERACTED_ONCE); |
} |
} |
@@ -786,6 +823,8 @@ void AutofillMetrics::FormEventLogger::OnDidPollSuggestions( |
} |
void AutofillMetrics::FormEventLogger::OnDidShowSuggestions() { |
+ form_interactions_ukm_logger_->LogSuggestionsShown(); |
+ |
Log(AutofillMetrics::FORM_EVENT_SUGGESTIONS_SHOWN); |
if (!has_logged_suggestions_shown_) { |
has_logged_suggestions_shown_ = true; |
@@ -803,17 +842,22 @@ void AutofillMetrics::FormEventLogger::OnDidShowSuggestions() { |
void AutofillMetrics::FormEventLogger::OnDidSelectMaskedServerCardSuggestion() { |
DCHECK(is_for_credit_card_); |
+ form_interactions_ukm_logger_->LogSelectedMaskedServerCard(); |
+ |
Log(AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED); |
if (!has_logged_masked_server_card_suggestion_selected_) { |
has_logged_masked_server_card_suggestion_selected_ = true; |
- Log(AutofillMetrics |
- ::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE); |
+ Log(AutofillMetrics:: |
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED_ONCE); |
} |
} |
void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( |
const CreditCard& credit_card) { |
DCHECK(is_for_credit_card_); |
+ form_interactions_ukm_logger_->LogDidFillSuggestion( |
+ static_cast<int>(credit_card.record_type())); |
+ |
if (credit_card.record_type() == CreditCard::MASKED_SERVER_CARD) |
Log(AutofillMetrics::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED); |
else if (credit_card.record_type() == CreditCard::FULL_SERVER_CARD) |
@@ -829,8 +873,8 @@ void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( |
logged_suggestion_filled_was_masked_server_card_ = |
credit_card.record_type() == CreditCard::MASKED_SERVER_CARD; |
if (credit_card.record_type() == CreditCard::MASKED_SERVER_CARD) { |
- Log(AutofillMetrics |
- ::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE); |
+ Log(AutofillMetrics:: |
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED_ONCE); |
} else if (credit_card.record_type() == CreditCard::FULL_SERVER_CARD) { |
Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE); |
} else { |
@@ -845,6 +889,9 @@ void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( |
void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( |
const AutofillProfile& profile) { |
DCHECK(!is_for_credit_card_); |
+ form_interactions_ukm_logger_->LogDidFillSuggestion( |
+ static_cast<int>(profile.record_type())); |
+ |
if (profile.record_type() == AutofillProfile::SERVER_PROFILE) |
Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED); |
else |
@@ -855,8 +902,8 @@ void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( |
logged_suggestion_filled_was_server_data_ = |
profile.record_type() == AutofillProfile::SERVER_PROFILE; |
Log(profile.record_type() == AutofillProfile::SERVER_PROFILE |
- ? AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE |
- : AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE); |
+ ? AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_FILLED_ONCE |
+ : AutofillMetrics::FORM_EVENT_LOCAL_SUGGESTION_FILLED_ONCE); |
} |
base::RecordAction( |
@@ -904,8 +951,8 @@ void AutofillMetrics::FormEventLogger::OnFormSubmitted() { |
if (!has_logged_suggestion_filled_) { |
Log(AutofillMetrics::FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE); |
} else if (logged_suggestion_filled_was_masked_server_card_) { |
- Log(AutofillMetrics |
- ::FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE); |
+ Log(AutofillMetrics:: |
+ FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SUBMITTED_ONCE); |
} else if (logged_suggestion_filled_was_server_data_) { |
Log(AutofillMetrics::FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE); |
} else { |
@@ -937,15 +984,154 @@ void AutofillMetrics::FormEventLogger::Log(FormEvent event) const { |
// Logging again in a different histogram for segmentation purposes. |
// TODO(waltercacau): Re-evaluate if we still need such fine grained |
// segmentation. http://crbug.com/454018 |
- if (!is_server_data_available_ && !is_local_data_available_) |
+ if (server_record_type_count_ == 0 && local_record_type_count_ == 0) |
name += ".WithNoData"; |
- else if (is_server_data_available_ && !is_local_data_available_) |
+ else if (server_record_type_count_ > 0 && local_record_type_count_ == 0) |
name += ".WithOnlyServerData"; |
- else if (!is_server_data_available_ && is_local_data_available_) |
+ else if (server_record_type_count_ == 0 && local_record_type_count_ > 0) |
name += ".WithOnlyLocalData"; |
else |
name += ".WithBothServerAndLocalData"; |
LogUMAHistogramEnumeration(name, event, NUM_FORM_EVENTS); |
} |
+AutofillMetrics::FormInteractionsUkmLogger::FormInteractionsUkmLogger( |
+ ukm::UkmService* ukm_service) |
+ : ukm_service_(ukm_service) {} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::OnFormsLoaded( |
+ const GURL& url) { |
+ if (!IsUkmLoggingEnabled() || ukm_service_ == nullptr) |
+ return; |
+ |
+ url_ = url; |
+ form_loaded_timestamp_ = base::TimeTicks::Now(); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::LogInteractedWithForm( |
+ bool is_for_credit_card, |
+ size_t local_record_type_count, |
+ size_t server_record_type_count) { |
+ if (!CanLog()) |
+ return; |
+ |
+ if (source_id_ == -1) |
+ GetNewSourceID(); |
+ |
+ std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_service_->GetEntryBuilder( |
+ source_id_, internal::kUKMInteractedWithFormEntryName); |
+ builder->AddMetric(internal::kUKMIsForCreditCardMetricName, |
+ is_for_credit_card); |
+ builder->AddMetric(internal::kUKMLocalRecordTypeCountMetricName, |
+ local_record_type_count); |
+ builder->AddMetric(internal::kUKMServerRecordTypeCountMetricName, |
+ server_record_type_count); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::LogSuggestionsShown() { |
+ if (!CanLog()) |
+ return; |
+ |
+ if (source_id_ == -1) |
+ GetNewSourceID(); |
+ |
+ std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_service_->GetEntryBuilder( |
+ source_id_, internal::kUKMSuggestionsShownEntryName); |
+ builder->AddMetric(internal::kUKMMillisecondsSinceFormLoadedMetricName, |
+ MillisecondsSinceFormLoaded()); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::LogSelectedMaskedServerCard() { |
+ if (!CanLog()) |
+ return; |
+ |
+ if (source_id_ == -1) |
+ GetNewSourceID(); |
+ |
+ std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_service_->GetEntryBuilder( |
+ source_id_, internal::kUKMSelectedMaskedServerCardEntryName); |
+ builder->AddMetric(internal::kUKMMillisecondsSinceFormLoadedMetricName, |
+ MillisecondsSinceFormLoaded()); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::LogDidFillSuggestion( |
+ int record_type) { |
+ if (!CanLog()) |
+ return; |
+ |
+ if (source_id_ == -1) |
+ GetNewSourceID(); |
+ |
+ std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_service_->GetEntryBuilder( |
+ source_id_, internal::kUKMSuggestionFilledEntryName); |
+ builder->AddMetric(internal::kUKMRecordTypeMetricName, record_type); |
+ builder->AddMetric(internal::kUKMMillisecondsSinceFormLoadedMetricName, |
+ MillisecondsSinceFormLoaded()); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::LogTextFieldDidChange( |
+ const AutofillField& field) { |
+ if (!CanLog()) |
+ return; |
+ |
+ if (source_id_ == -1) |
+ GetNewSourceID(); |
+ |
+ std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_service_->GetEntryBuilder( |
+ source_id_, internal::kUKMTextFieldDidChangeEntryName); |
+ builder->AddMetric(internal::kUKMFieldTypeGroupMetricName, |
+ static_cast<int>(field.Type().group())); |
+ builder->AddMetric(internal::kUKMHeuristicTypeMetricName, |
+ static_cast<int>(field.heuristic_type())); |
+ builder->AddMetric(internal::kUKMServerTypeMetricName, |
+ static_cast<int>(field.server_type())); |
+ builder->AddMetric(internal::kUKMHtmlFieldTypeMetricName, |
+ static_cast<int>(field.html_type())); |
+ builder->AddMetric(internal::kUKMHtmlFieldModeMetricName, |
+ static_cast<int>(field.html_mode())); |
+ builder->AddMetric(internal::kUKMIsAutofilledMetricName, field.is_autofilled); |
+ builder->AddMetric(internal::kUKMIsEmptyMetricName, field.IsEmpty()); |
+ builder->AddMetric(internal::kUKMMillisecondsSinceFormLoadedMetricName, |
+ MillisecondsSinceFormLoaded()); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::LogFormSubmitted( |
+ AutofillFormSubmittedState state) { |
+ if (!CanLog()) |
+ return; |
+ |
+ if (source_id_ == -1) |
+ GetNewSourceID(); |
+ |
+ std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_service_->GetEntryBuilder( |
+ source_id_, internal::kUKMFormSubmittedEntryName); |
+ builder->AddMetric(internal::kUKMAutofillFormSubmittedStateMetricName, |
+ static_cast<int>(state)); |
+ builder->AddMetric(internal::kUKMMillisecondsSinceFormLoadedMetricName, |
+ MillisecondsSinceFormLoaded()); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::UpdateSourceURL( |
+ const GURL& url) { |
+ url_ = url; |
+ if (CanLog()) |
+ ukm_service_->UpdateSourceURL(source_id_, url_); |
+} |
+ |
+bool AutofillMetrics::FormInteractionsUkmLogger::CanLog() const { |
+ return IsUkmLoggingEnabled() && ukm_service_ && url_.is_valid(); |
+} |
+ |
+int64_t |
+AutofillMetrics::FormInteractionsUkmLogger::MillisecondsSinceFormLoaded() |
+ const { |
+ DCHECK(!form_loaded_timestamp_.is_null()); |
+ return (base::TimeTicks::Now() - form_loaded_timestamp_).InMilliseconds(); |
+} |
+ |
+void AutofillMetrics::FormInteractionsUkmLogger::GetNewSourceID() { |
+ source_id_ = ukm_service_->GetNewSourceID(); |
+ ukm_service_->UpdateSourceURL(source_id_, url_); |
+} |
+ |
} // namespace autofill |