Commit e74720b3 authored by Ryan Sturm's avatar Ryan Sturm Committed by Commit Bot

Recording UKM for home page and default search navigations

This CL records when the navigation was the user's registered home page
or DSE (for both starting URL and committed URL).

Bug: 1044295
Change-Id: I25dbaff66720ef8d16ba1fb12225055bb020f2f7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2013802Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Commit-Queue: Ryan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#736162}
parent 7899e8da
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/prerender/prerender_origin.h" #include "chrome/browser/prerender/prerender_origin.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/features.h" #include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h" #include "components/content_settings/core/common/pref_names.h"
...@@ -26,6 +28,7 @@ ...@@ -26,6 +28,7 @@
#include "components/page_load_metrics/browser/page_load_metrics_util.h" #include "components/page_load_metrics/browser/page_load_metrics_util.h"
#include "components/page_load_metrics/browser/protocol_util.h" #include "components/page_load_metrics/browser/protocol_util.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "net/base/load_timing_info.h" #include "net/base/load_timing_info.h"
...@@ -69,6 +72,29 @@ int32_t LayoutShiftUmaValue(float shift_score) { ...@@ -69,6 +72,29 @@ int32_t LayoutShiftUmaValue(float shift_score) {
return static_cast<int>(roundf(std::min(shift_score, 10.0f) * 10.0f)); return static_cast<int>(roundf(std::min(shift_score, 10.0f) * 10.0f));
} }
bool IsDefaultSearchEngine(content::BrowserContext* browser_context,
const GURL& url) {
if (!browser_context)
return false;
auto* template_service = TemplateURLServiceFactory::GetForProfile(
Profile::FromBrowserContext(browser_context));
if (!template_service)
return false;
return template_service->IsSearchResultsPageFromDefaultSearchProvider(url);
}
bool IsUserHomePage(content::BrowserContext* browser_context, const GURL& url) {
if (!browser_context)
return false;
return url.spec() == Profile::FromBrowserContext(browser_context)
->GetPrefs()
->GetString(prefs::kHomePage);
}
} // namespace } // namespace
// static // static
...@@ -94,13 +120,18 @@ UkmPageLoadMetricsObserver::ObservePolicy UkmPageLoadMetricsObserver::OnStart( ...@@ -94,13 +120,18 @@ UkmPageLoadMetricsObserver::ObservePolicy UkmPageLoadMetricsObserver::OnStart(
content::NavigationHandle* navigation_handle, content::NavigationHandle* navigation_handle,
const GURL& currently_committed_url, const GURL& currently_committed_url,
bool started_in_foreground) { bool started_in_foreground) {
browser_context_ = navigation_handle->GetWebContents()->GetBrowserContext();
start_url_is_default_search_ =
IsDefaultSearchEngine(browser_context_, navigation_handle->GetURL());
start_url_is_home_page_ =
IsUserHomePage(browser_context_, navigation_handle->GetURL());
if (!started_in_foreground) { if (!started_in_foreground) {
was_hidden_ = true; was_hidden_ = true;
return CONTINUE_OBSERVING; return CONTINUE_OBSERVING;
} }
browser_context_ = navigation_handle->GetWebContents()->GetBrowserContext();
// When OnStart is invoked, we don't yet know whether we're observing a web // When OnStart is invoked, we don't yet know whether we're observing a web
// page load, vs another kind of load (e.g. a download or a PDF). Thus, // page load, vs another kind of load (e.g. a download or a PDF). Thus,
// metrics and source information should not be recorded here. Instead, we // metrics and source information should not be recorded here. Instead, we
...@@ -159,6 +190,7 @@ UkmPageLoadMetricsObserver::ObservePolicy UkmPageLoadMetricsObserver::OnCommit( ...@@ -159,6 +190,7 @@ UkmPageLoadMetricsObserver::ObservePolicy UkmPageLoadMetricsObserver::OnCommit(
is_signed_exchange_inner_response_ = is_signed_exchange_inner_response_ =
navigation_handle->IsSignedExchangeInnerResponse(); navigation_handle->IsSignedExchangeInnerResponse();
RecordNoStatePrefetchMetrics(navigation_handle, source_id); RecordNoStatePrefetchMetrics(navigation_handle, source_id);
RecordGeneratedNavigationUKM(source_id, navigation_handle->GetURL());
navigation_is_cross_process_ = !navigation_handle->IsSameProcess(); navigation_is_cross_process_ = !navigation_handle->IsSameProcess();
navigation_entry_offset_ = navigation_handle->GetNavigationEntryOffset(); navigation_entry_offset_ = navigation_handle->GetNavigationEntryOffset();
main_document_sequence_number_ = navigation_handle->GetWebContents() main_document_sequence_number_ = navigation_handle->GetWebContents()
...@@ -679,3 +711,23 @@ bool UkmPageLoadMetricsObserver::IsOfflinePreview( ...@@ -679,3 +711,23 @@ bool UkmPageLoadMetricsObserver::IsOfflinePreview(
return false; return false;
#endif #endif
} }
void UkmPageLoadMetricsObserver::RecordGeneratedNavigationUKM(
ukm::SourceId source_id,
const GURL& committed_url) {
bool final_url_is_home_page = IsUserHomePage(browser_context_, committed_url);
bool final_url_is_default_search =
IsDefaultSearchEngine(browser_context_, committed_url);
if (!final_url_is_home_page && !final_url_is_default_search &&
!start_url_is_home_page_ && !start_url_is_default_search_) {
return;
}
ukm::builders::GeneratedNavigation builder(source_id);
builder.SetFinalURLIsHomePage(final_url_is_home_page);
builder.SetFinalURLIsDefaultSearchEngine(final_url_is_default_search);
builder.SetFirstURLIsHomePage(start_url_is_home_page_);
builder.SetFirstURLIsDefaultSearchEngine(start_url_is_default_search_);
builder.Record(ukm::UkmRecorder::Get());
}
...@@ -126,6 +126,11 @@ class UkmPageLoadMetricsObserver ...@@ -126,6 +126,11 @@ class UkmPageLoadMetricsObserver
content::NavigationHandle* navigation_handle, content::NavigationHandle* navigation_handle,
ukm::SourceId source_id); ukm::SourceId source_id);
// Records the metrics related to Generate URLs (Home page, default search
// engine) for starting URL and committed URL.
void RecordGeneratedNavigationUKM(ukm::SourceId source_id,
const GURL& committed_url);
// Guaranteed to be non-null during the lifetime of |this|. // Guaranteed to be non-null during the lifetime of |this|.
network::NetworkQualityTracker* network_quality_tracker_; network::NetworkQualityTracker* network_quality_tracker_;
...@@ -166,6 +171,14 @@ class UkmPageLoadMetricsObserver ...@@ -166,6 +171,14 @@ class UkmPageLoadMetricsObserver
// True if the page main resource is inner response of a signed exchange. // True if the page main resource is inner response of a signed exchange.
bool is_signed_exchange_inner_response_ = false; bool is_signed_exchange_inner_response_ = false;
// Whether the first URL in the redirect chain matches the default search
// engine template.
bool start_url_is_default_search_ = false;
// Whether the first URL in the redirect chain matches the user's home page
// URL.
bool start_url_is_home_page_ = false;
// The number of main frame redirects that occurred before commit. // The number of main frame redirects that occurred before commit.
uint32_t main_frame_request_redirect_count_ = 0; uint32_t main_frame_request_redirect_count_ = 0;
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include "base/trace_event/traced_value.h" #include "base/trace_event/traced_value.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/search_test_utils.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings.h"
...@@ -23,6 +26,7 @@ ...@@ -23,6 +26,7 @@
#include "components/page_load_metrics/browser/page_load_tracker.h" #include "components/page_load_metrics/browser/page_load_tracker.h"
#include "components/page_load_metrics/common/test/page_load_metrics_test_util.h" #include "components/page_load_metrics/common/test/page_load_metrics_test_util.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/test/navigation_simulator.h" #include "content/public/test/navigation_simulator.h"
#include "net/base/ip_endpoint.h" #include "net/base/ip_endpoint.h"
...@@ -44,6 +48,7 @@ using testing::Return; ...@@ -44,6 +48,7 @@ using testing::Return;
namespace { namespace {
using PageLoad = ukm::builders::PageLoad; using PageLoad = ukm::builders::PageLoad;
using GeneratedNavigation = ukm::builders::GeneratedNavigation;
const char kTestUrl1[] = "https://www.google.com/"; const char kTestUrl1[] = "https://www.google.com/";
const char kTestUrl2[] = "https://www.example.com/"; const char kTestUrl2[] = "https://www.example.com/";
...@@ -87,6 +92,9 @@ class UkmPageLoadMetricsObserverTest ...@@ -87,6 +92,9 @@ class UkmPageLoadMetricsObserverTest
EXPECT_CALL(mock_network_quality_provider_, GetDownstreamThroughputKbps()) EXPECT_CALL(mock_network_quality_provider_, GetDownstreamThroughputKbps())
.Times(AnyNumber()) .Times(AnyNumber())
.WillRepeatedly(Return(int32_t())); .WillRepeatedly(Return(int32_t()));
TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile(),
base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor));
} }
MockNetworkQualityProvider& mock_network_quality_provider() { MockNetworkQualityProvider& mock_network_quality_provider() {
...@@ -1514,6 +1522,102 @@ TEST_F(UkmPageLoadMetricsObserverTest, ...@@ -1514,6 +1522,102 @@ TEST_F(UkmPageLoadMetricsObserverTest,
} }
} }
TEST_F(UkmPageLoadMetricsObserverTest, NotSearchOrHomePage) {
static const char kOtherURL[] = "https://www.other.com";
NavigateAndCommit(GURL(kOtherURL));
// Simulate closing the tab.
DeleteContents();
std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
tester()->test_ukm_recorder().GetMergedEntriesByName(
GeneratedNavigation::kEntryName);
EXPECT_EQ(0ul, merged_entries.size());
}
TEST_F(UkmPageLoadMetricsObserverTest, HomePageReported) {
static const char kOtherURL[] = "https://www.homepage.com/";
Profile::FromBrowserContext(browser_context())
->GetPrefs()
->SetString(prefs::kHomePage, kOtherURL);
NavigateAndCommit(GURL(kOtherURL));
// Simulate closing the tab.
DeleteContents();
std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
tester()->test_ukm_recorder().GetMergedEntriesByName(
GeneratedNavigation::kEntryName);
EXPECT_EQ(1ul, merged_entries.size());
for (const auto& kv : merged_entries) {
tester()->test_ukm_recorder().ExpectEntrySourceHasUrl(kv.second.get(),
GURL(kOtherURL));
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(),
GeneratedNavigation::kFirstURLIsDefaultSearchEngineName, false);
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(),
GeneratedNavigation::kFinalURLIsDefaultSearchEngineName, false);
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(), GeneratedNavigation::kFirstURLIsHomePageName, true);
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(), GeneratedNavigation::kFinalURLIsHomePageName, true);
}
}
TEST_F(UkmPageLoadMetricsObserverTest, DefaultSearchReported) {
static const char kShortName[] = "test";
static const char kSearchURL[] =
"https://www.searchurl.com/search?q={searchTerms}";
static const char kSearchURLWithQuery[] =
"https://www.searchurl.com/search?q=somequery";
TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(
Profile::FromBrowserContext(browser_context()));
ASSERT_TRUE(model);
search_test_utils::WaitForTemplateURLServiceToLoad(model);
ASSERT_TRUE(model->loaded());
TemplateURLData data;
data.SetShortName(base::ASCIIToUTF16(kShortName));
data.SetKeyword(data.short_name());
data.SetURL(kSearchURL);
// Set the DSE to the test URL.
TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data));
ASSERT_TRUE(template_url);
model->SetUserSelectedDefaultSearchProvider(template_url);
NavigateAndCommit(GURL(kSearchURLWithQuery));
// Simulate closing the tab.
DeleteContents();
std::map<ukm::SourceId, ukm::mojom::UkmEntryPtr> merged_entries =
tester()->test_ukm_recorder().GetMergedEntriesByName(
GeneratedNavigation::kEntryName);
EXPECT_EQ(1ul, merged_entries.size());
for (const auto& kv : merged_entries) {
tester()->test_ukm_recorder().ExpectEntrySourceHasUrl(
kv.second.get(), GURL(kSearchURLWithQuery));
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(),
GeneratedNavigation::kFirstURLIsDefaultSearchEngineName, true);
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(),
GeneratedNavigation::kFinalURLIsDefaultSearchEngineName, true);
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(), GeneratedNavigation::kFirstURLIsHomePageName, false);
tester()->test_ukm_recorder().ExpectEntryMetric(
kv.second.get(), GeneratedNavigation::kFinalURLIsHomePageName, false);
}
}
class TestOfflinePreviewsUkmPageLoadMetricsObserver class TestOfflinePreviewsUkmPageLoadMetricsObserver
: public UkmPageLoadMetricsObserver { : public UkmPageLoadMetricsObserver {
public: public:
......
...@@ -3571,6 +3571,42 @@ be describing additional metrics about the same event. ...@@ -3571,6 +3571,42 @@ be describing additional metrics about the same event.
</metric> </metric>
</event> </event>
<event name="GeneratedNavigation" singular="True">
<owner>ryansturm@chromium.org</owner>
<owner>avi@chromium.org</owner>
<summary>
Logged when the user navigated to their home page or their default search
engine. Recorded if the first URL or the final URL matches the pattern for
Default Search or matches the user's home page URL. Recorded upon commit
(even if the page was not foreground).
</summary>
<metric name="FinalURLIsDefaultSearchEngine">
<summary>
If the navigation committed URL matches the template URL of the user's
Default Search Engine.
</summary>
</metric>
<metric name="FinalURLIsHomePage">
<summary>
If the navigation committed URL matches the user's home page URL. Not
recorded on Android because home page is managed outside of Chrome.
</summary>
</metric>
<metric name="FirstURLIsDefaultSearchEngine">
<summary>
If the navigation starting URL matches the template URL of the user's
Default Search Engine.
</summary>
</metric>
<metric name="FirstURLIsHomePage">
<summary>
If the navigation starting URL (first URL in the redirect chain) matches
the user's home page URL. Not recorded on Android because home page is
managed outside of Chrome.
</summary>
</metric>
</event>
<event name="GoogleDocsOfflineExtension"> <event name="GoogleDocsOfflineExtension">
<owner>rhalavati@chromium.org</owner> <owner>rhalavati@chromium.org</owner>
<owner>chrome-privacy-core@google.com</owner> <owner>chrome-privacy-core@google.com</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment