blob: 937a85bbb49a2451b4b5cf62ce01fac8b7763a44 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/omnibox/browser/omnibox_metrics_provider.h"
#include <memory>
#include <string>
#include "base/memory/scoped_refptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/omnibox/browser/actions/contextual_search_action.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_match_type.h"
#include "components/omnibox/browser/autocomplete_provider.h"
#include "components/omnibox/browser/autocomplete_result.h"
#include "components/omnibox/browser/fake_autocomplete_provider.h"
#include "components/omnibox/browser/match_compare.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/omnibox_log.h"
#include "components/omnibox/browser/omnibox_popup_selection.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "third_party/metrics_proto/omnibox_scoring_signals.pb.h"
#include "ui/base/window_open_disposition.h"
using ScoringSignals = ::metrics::OmniboxEventProto::Suggestion::ScoringSignals;
using OmniboxScoringSignals = ::metrics::OmniboxScoringSignals;
class OmniboxMetricsProviderTest : public testing::Test {
public:
OmniboxMetricsProviderTest() = default;
~OmniboxMetricsProviderTest() override = default;
void SetUp() override {
autocomplete_provider_ =
new FakeAutocompleteProvider(AutocompleteProvider::TYPE_SEARCH);
metrics_provider_ = std::make_unique<OmniboxMetricsProvider>();
}
void TearDown() override { metrics_provider_.reset(); }
OmniboxLog BuildOmniboxLog(const AutocompleteResult& result,
size_t selected_index,
SessionData session_data) {
return OmniboxLog(
/*text=*/u"my text", /*just_deleted_text=*/false,
/*input_type=*/metrics::OmniboxInputType::URL,
/*in_keyword_mode=*/false,
/*entry_method=*/
metrics::OmniboxEventProto_KeywordModeEntryMethod_INVALID,
/*is_popup_open=*/false,
/*selection=*/OmniboxPopupSelection(selected_index),
/*disposition=*/WindowOpenDisposition::CURRENT_TAB,
/*is_paste_and_go=*/false,
/*tab_id=*/SessionID::NewUnique(),
/*current_page_classification=*/
metrics::OmniboxEventProto_PageClassification_NTP_REALBOX,
/*elapsed_time_since_user_first_modified_omnibox=*/base::TimeDelta(),
/*completed_length=*/0,
/*elapsed_time_since_last_change_to_default_match=*/base::TimeDelta(),
/*result=*/result, /*destination_url=*/GURL("https://www.example.com/"),
/*is_incognito=*/false,
/*is_zero_suggest=*/false,
/*session=*/session_data);
}
AutocompleteMatch BuildMatch(AutocompleteMatch::Type type) {
return AutocompleteMatch(autocomplete_provider_.get(), /*relevance=*/0,
/*deletable=*/false, type);
}
void RecordMetrics(const OmniboxLog& log) {
metrics_provider_->RecordMetrics(log);
}
void RecordContextualSearchPrecisionRecallUsage(const OmniboxLog& log) {
metrics_provider_->RecordContextualSearchPrecisionRecallUsage(log);
}
void RecordLogAndVerifyScoringSignals(
const OmniboxLog& log,
OmniboxScoringSignals& expected_scoring_signals) {
// Clear the event cache so we start with a clean slate.
metrics_provider_->omnibox_events_cache.clear_omnibox_event();
metrics_provider_->RecordOmniboxEvent(log);
EXPECT_EQ(metrics_provider_->omnibox_events_cache.omnibox_event_size(), 1);
const metrics::OmniboxEventProto& omnibox_event =
metrics_provider_->omnibox_events_cache.omnibox_event(0);
for (int i = 0; i < omnibox_event.suggestion_size(); i++) {
const metrics::OmniboxEventProto::Suggestion& suggestion =
omnibox_event.suggestion(i);
// Scoring signals should not be logged when in incognito/off-the-record
// mode, regardless of result type.
if (log.is_incognito) {
EXPECT_FALSE(suggestion.has_scoring_signals());
continue;
}
// When not in incognito, scoring signals should only be logged for the
// proper suggestion types. Check that the signals are logged correctly
// for URL types and Search types, while not being logged for any others.
if (suggestion.has_result_type()) {
EXPECT_TRUE(suggestion.has_scoring_signals());
if (suggestion.result_type() ==
metrics::
OmniboxEventProto_Suggestion_ResultType_SEARCH_WHAT_YOU_TYPED) {
EXPECT_EQ(suggestion.scoring_signals().search_suggest_relevance(),
expected_scoring_signals.search_suggest_relevance());
EXPECT_EQ(suggestion.scoring_signals().is_search_suggest_entity(),
expected_scoring_signals.is_search_suggest_entity());
} else {
EXPECT_EQ(
suggestion.scoring_signals()
.first_bookmark_title_match_position(),
expected_scoring_signals.first_bookmark_title_match_position());
EXPECT_EQ(suggestion.scoring_signals().allowed_to_be_default_match(),
expected_scoring_signals.allowed_to_be_default_match());
EXPECT_EQ(suggestion.scoring_signals().length_of_url(),
expected_scoring_signals.length_of_url());
}
} else {
EXPECT_FALSE(suggestion.has_scoring_signals());
}
}
// Clear the event cache.
metrics_provider_->omnibox_events_cache.clear_omnibox_event();
}
protected:
base::test::TaskEnvironment task_environment_;
scoped_refptr<FakeAutocompleteProvider> autocomplete_provider_;
std::unique_ptr<OmniboxMetricsProvider> metrics_provider_;
};
TEST_F(OmniboxMetricsProviderTest, RecordMetrics_SingleURL) {
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::URL_WHAT_YOU_TYPED)});
SessionData session;
session.typed_suggestions_shown_in_session = true;
session.typed_url_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/0,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordMetrics(log);
// Verify the UMA histograms.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
// Verify the UKM event.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
static_cast<uint64_t>(ClientSummarizedResultType::kUrl));
}
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::URL_WHAT_YOU_TYPED)});
SessionData session;
session.zero_prefix_suggestions_shown_in_session = true;
session.zero_prefix_url_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/0,
/*session_data=*/session);
log.text = u"";
log.ukm_source_id = ukm::NoURLSourceId();
RecordMetrics(log);
// Verify the UMA histograms.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kUrl, /*expected_count=*/1);
// Verify the UKM event.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
static_cast<uint64_t>(ClientSummarizedResultType::kUrl));
}
}
TEST_F(OmniboxMetricsProviderTest, RecordMetrics_SingleSearch) {
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches({BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST)});
SessionData session;
session.typed_suggestions_shown_in_session = true;
session.typed_search_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/0,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordMetrics(log);
// Verify the UMA histograms.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
// Verify the UKM event.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
}
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches({BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST)});
SessionData session;
session.zero_prefix_suggestions_shown_in_session = true;
session.zero_prefix_search_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/0,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordMetrics(log);
// Verify the UMA histograms.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kSearch, /*expected_count=*/1);
// Verify the UKM event.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
}
}
TEST_F(OmniboxMetricsProviderTest, RecordContextualSearchMetrics) {
// Contextual search suggestion shown, but not selected.
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteMatch match =
BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST);
match.subtypes.insert(omnibox::SUBTYPE_CONTEXTUAL_SEARCH);
match.takeover_action =
base::MakeRefCounted<ContextualSearchFulfillmentAction>(
match.destination_url, match.type, true);
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST), match});
SessionData session;
session.contextual_search_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/0,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordContextualSearchPrecisionRecallUsage(log);
// Verify the UMA histograms.
histogram_tester.ExpectTotalCount(
"Omnibox.ContextualSearchSuggestion.Precision", /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.ContextualSearchSuggestion.Precision", false,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount(
"Omnibox.ContextualSearchSuggestion.Recall",
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.ContextualSearchSuggestion.Recall", true,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount(
"Omnibox.ContextualSearchSuggestion.Usage",
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.ContextualSearchSuggestion.Usage", false,
/*expected_count=*/1);
RecordMetrics(log);
// Verify the UKM event and the full set of metrics.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(entry,
ukm::builders::Omnibox_SuggestionUsed::
kZeroPrefixContextualSearchShownName,
true);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixLensActionShownName,
false);
}
// Contextual search suggestion shown and selected.
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteMatch match =
BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST);
match.subtypes.insert(omnibox::SUBTYPE_CONTEXTUAL_SEARCH);
match.takeover_action =
base::MakeRefCounted<ContextualSearchFulfillmentAction>(
match.destination_url, match.type, true);
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST), match});
SessionData session;
session.contextual_search_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/1,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordContextualSearchPrecisionRecallUsage(log);
// Verify the UMA histograms.
histogram_tester.ExpectTotalCount(
"Omnibox.ContextualSearchSuggestion.Precision", /*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.ContextualSearchSuggestion.Precision", true,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount(
"Omnibox.ContextualSearchSuggestion.Recall",
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.ContextualSearchSuggestion.Recall", true,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount(
"Omnibox.ContextualSearchSuggestion.Usage",
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.ContextualSearchSuggestion.Usage", true, /*expected_count=*/1);
RecordMetrics(log);
// Verify the UKM event and the full set of metrics.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(entry,
ukm::builders::Omnibox_SuggestionUsed::
kZeroPrefixContextualSearchShownName,
true);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixLensActionShownName,
false);
}
// Google Lens action shown, but not selected.
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteMatch match =
BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST);
match.subtypes.insert(omnibox::SUBTYPE_CONTEXTUAL_SEARCH);
match.takeover_action =
base::MakeRefCounted<ContextualSearchOpenLensAction>();
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST), match});
SessionData session;
session.lens_action_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/0,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordContextualSearchPrecisionRecallUsage(log);
// Verify the UMA histograms.
histogram_tester.ExpectTotalCount("Omnibox.LensAction.Precision", 1);
histogram_tester.ExpectBucketCount("Omnibox.LensAction.Precision", false,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount("Omnibox.LensAction.Recall", 1);
histogram_tester.ExpectBucketCount("Omnibox.LensAction.Recall", true,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount("Omnibox.LensAction.Usage", 1);
histogram_tester.ExpectBucketCount("Omnibox.LensAction.Usage", false,
/*expected_count=*/1);
RecordMetrics(log);
// Verify the UKM event and the full set of metrics.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(entry,
ukm::builders::Omnibox_SuggestionUsed::
kZeroPrefixContextualSearchShownName,
false);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixLensActionShownName,
true);
}
// Google Lens action shown and selected.
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteMatch match =
BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST);
match.subtypes.insert(omnibox::SUBTYPE_CONTEXTUAL_SEARCH);
match.takeover_action =
base::MakeRefCounted<ContextualSearchOpenLensAction>();
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST), match});
SessionData session;
session.lens_action_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/1,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
RecordContextualSearchPrecisionRecallUsage(log);
// Verify the UMA histograms.
histogram_tester.ExpectTotalCount("Omnibox.LensAction.Precision", 1);
histogram_tester.ExpectBucketCount("Omnibox.LensAction.Precision", true,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount("Omnibox.LensAction.Recall", 1);
histogram_tester.ExpectBucketCount("Omnibox.LensAction.Recall", true,
/*expected_count=*/1);
histogram_tester.ExpectTotalCount("Omnibox.LensAction.Usage", 1);
histogram_tester.ExpectBucketCount("Omnibox.LensAction.Usage", true,
/*expected_count=*/1);
RecordMetrics(log);
// Verify the UKM event and the full set of metrics.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(entry,
ukm::builders::Omnibox_SuggestionUsed::
kZeroPrefixContextualSearchShownName,
false);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixLensActionShownName,
true);
}
}
TEST_F(OmniboxMetricsProviderTest, RecordMetrics_MultipleSearch) {
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::URL_WHAT_YOU_TYPED),
BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST),
BuildMatch(AutocompleteMatch::Type::URL_WHAT_YOU_TYPED)});
SessionData session;
session.typed_suggestions_shown_in_session = true;
session.typed_search_suggestions_shown_in_session = true;
session.typed_url_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/1,
/*session_data=*/session);
log.ukm_source_id = ukm::NoURLSourceId();
log.elapsed_time_since_user_focused_omnibox = base::Milliseconds(10);
RecordMetrics(log);
// Verify the UMA histograms.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.TypedSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
// Verify the UKM event and the full set of metrics.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kPageClassificationName,
static_cast<uint64_t>(
metrics::OmniboxEventProto_PageClassification_NTP_REALBOX));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kProviderTypeName,
static_cast<uint64_t>(metrics::OmniboxEventProto_ProviderType_SEARCH));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeName,
static_cast<uint64_t>(
metrics::OmniboxEventProto_Suggestion::SEARCH_SUGGEST));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kSelectedIndexName, 1ul);
// With exponential bucketing scheme with a standard spacing of 2.0, 10
// falls into the 8-16 bucket as the boundaries of the buckets increase
// exponentially, e.g., 1, 2, 4, 8, 16, etc.
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kTimeSinceLastFocusMsName,
8ul);
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kTypedLengthName, 7ul);
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kTypingDurationMsName,
0ul);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixSearchShownName,
false);
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixUrlShownName,
false);
ukm_recorder.ExpectEntryMetric(entry,
ukm::builders::Omnibox_SuggestionUsed::
kZeroPrefixContextualSearchShownName,
false);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixLensActionShownName,
false);
}
{
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches({BuildMatch(AutocompleteMatch::Type::HISTORY_URL),
BuildMatch(AutocompleteMatch::Type::SEARCH_SUGGEST),
BuildMatch(AutocompleteMatch::Type::HISTORY_URL)});
SessionData session;
session.zero_prefix_suggestions_shown_in_session = true;
session.zero_prefix_search_suggestions_shown_in_session = true;
session.zero_prefix_url_suggestions_shown_in_session = true;
OmniboxLog log = BuildOmniboxLog(result, /*selected_index=*/1,
/*session_data=*/session);
log.text = u"";
log.ukm_source_id = ukm::NoURLSourceId();
log.elapsed_time_since_user_focused_omnibox = base::Milliseconds(10);
RecordMetrics(log);
// Verify the UMA histograms.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kSearch,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ClientSummarizedResultType.ByPageContext.NTP_"
"REALBOX",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionShown.ZeroSuggest.ClientSummarizedResultType."
"ByPageContext.NTP_REALBOX",
ClientSummarizedResultType::kUrl,
/*expected_count=*/1);
// Verify the UKM event and the full set of metrics.
const char* entry_name = ukm::builders::Omnibox_SuggestionUsed::kEntryName;
EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kPageClassificationName,
static_cast<uint64_t>(
metrics::OmniboxEventProto_PageClassification_NTP_REALBOX));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kProviderTypeName,
static_cast<uint64_t>(metrics::OmniboxEventProto_ProviderType_SEARCH));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeName,
static_cast<uint64_t>(
metrics::OmniboxEventProto_Suggestion::SEARCH_SUGGEST));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kSelectedIndexName, 1ul);
// With exponential bucketing scheme with a standard spacing of 2.0, 10
// falls into the 8-16 bucket as the boundaries of the buckets increase
// exponentially, e.g., 1, 2, 4, 8, 16, etc.
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kTimeSinceLastFocusMsName,
8ul);
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kTypedLengthName, 0ul);
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kTypingDurationMsName,
0ul);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixSearchShownName,
true);
ukm_recorder.ExpectEntryMetric(
entry, ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixUrlShownName,
true);
ukm_recorder.ExpectEntryMetric(entry,
ukm::builders::Omnibox_SuggestionUsed::
kZeroPrefixContextualSearchShownName,
false);
ukm_recorder.ExpectEntryMetric(
entry,
ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixLensActionShownName,
false);
}
}
TEST_F(OmniboxMetricsProviderTest, RecordMetrics_InvalidUkmSourceId) {
base::HistogramTester histogram_tester;
ukm::TestAutoSetUkmRecorder ukm_recorder;
AutocompleteResult result;
result.AppendMatches(
{BuildMatch(AutocompleteMatch::Type::URL_WHAT_YOU_TYPED)});
OmniboxLog log =
BuildOmniboxLog(result, /*selected_index=*/0, /*session_data=*/{});
RecordMetrics(log);
// Verify the UMA histogram.
histogram_tester.ExpectBucketCount(
"Omnibox.SuggestionUsed.ClientSummarizedResultType",
ClientSummarizedResultType::kUrl, 1);
// Verify the UKM event was not logged due to invalid ukm source id.
EXPECT_EQ(
ukm_recorder
.GetEntriesByName(ukm::builders::Omnibox_SuggestionUsed::kEntryName)
.size(),
0ul);
}
// TODO(b/261895038): This test is flaky on android. Currently scoring signals
// logging is only enabled on desktop, so disable for mobile.
#if !(BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID))
TEST_F(OmniboxMetricsProviderTest, LogScoringSignals) {
// Enable feature flag to log scoring signals.
OmniboxFieldTrial::ScopedMLConfigForTesting scoped_ml_config;
scoped_ml_config.GetMLConfig().log_url_scoring_signals = true;
// Populate a set of scoring signals with some test values. This will be used
// to ensure the scoring signals are being propagated correctly.
OmniboxScoringSignals expected_url_scoring_signals;
expected_url_scoring_signals.set_first_bookmark_title_match_position(3);
expected_url_scoring_signals.set_allowed_to_be_default_match(true);
expected_url_scoring_signals.set_length_of_url(20);
OmniboxScoringSignals expected_search_scoring_signals;
expected_search_scoring_signals.set_search_suggest_relevance(1000);
expected_search_scoring_signals.set_is_search_suggest_entity(true);
// Create matches and populate the scoring signals. Signals should only be
// logged for non-search suggestions.
ACMatches matches = {
BuildMatch(AutocompleteMatchType::Type::BOOKMARK_TITLE),
BuildMatch(AutocompleteMatchType::Type::SEARCH_WHAT_YOU_TYPED)};
for (auto& match : matches) {
match.scoring_signals = AutocompleteMatch::IsSearchHistoryType(match.type)
? expected_search_scoring_signals
: expected_url_scoring_signals;
}
AutocompleteResult result;
result.AppendMatches(matches);
// Create the log and call simulate logging.
OmniboxLog log =
BuildOmniboxLog(result, /*selected_index=*/1, /*session_data=*/{});
RecordLogAndVerifyScoringSignals(log, *matches[0].scoring_signals);
// Now, "turn on" incognito mode, scoring signals should not be logged.
log.is_incognito = true;
RecordLogAndVerifyScoringSignals(log, *matches[0].scoring_signals);
}
#endif // !(BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID))