Commit 356a84d0 authored by Annie Sullivan's avatar Annie Sullivan Committed by Commit Bot

Add a UKM observer to measure time spent in foreground.

The observer uses a repeated field because a tab or window can be
backgrounded and foregrounded multiple times.

Bug: 921703
Change-Id: If03a3444a237d7c5abf0740a0a3c9c684caea013
Reviewed-on: https://chromium-review.googlesource.com/c/1421681Reviewed-by: default avatarBryan McQuade <bmcquade@chromium.org>
Commit-Queue: Annie Sullivan <sullivan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#626232}
parent 382592cd
...@@ -956,6 +956,8 @@ jumbo_split_static_library("browser") { ...@@ -956,6 +956,8 @@ jumbo_split_static_library("browser") {
"page_load_metrics/observers/data_use_metrics_observer.h", "page_load_metrics/observers/data_use_metrics_observer.h",
"page_load_metrics/observers/document_write_page_load_metrics_observer.cc", "page_load_metrics/observers/document_write_page_load_metrics_observer.cc",
"page_load_metrics/observers/document_write_page_load_metrics_observer.h", "page_load_metrics/observers/document_write_page_load_metrics_observer.h",
"page_load_metrics/observers/foreground_duration_ukm_observer.cc",
"page_load_metrics/observers/foreground_duration_ukm_observer.h",
"page_load_metrics/observers/from_gws_page_load_metrics_observer.cc", "page_load_metrics/observers/from_gws_page_load_metrics_observer.cc",
"page_load_metrics/observers/from_gws_page_load_metrics_observer.h", "page_load_metrics/observers/from_gws_page_load_metrics_observer.h",
"page_load_metrics/observers/histogram_suffixes.cc", "page_load_metrics/observers/histogram_suffixes.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h"
#include "base/time/time.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
#include "chrome/common/page_load_metrics/page_load_timing.h"
#include "content/public/browser/navigation_handle.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source.h"
ForegroundDurationUKMObserver::ForegroundDurationUKMObserver() {}
ForegroundDurationUKMObserver::~ForegroundDurationUKMObserver() {}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
ForegroundDurationUKMObserver::OnStart(
content::NavigationHandle* navigation_handle,
const GURL& currently_committed_url,
bool started_in_foreground) {
currently_in_foreground_ = started_in_foreground;
if (currently_in_foreground_) {
last_time_shown_ = navigation_handle->NavigationStart();
}
return CONTINUE_OBSERVING;
}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
ForegroundDurationUKMObserver::OnCommit(
content::NavigationHandle* navigation_handle,
ukm::SourceId source_id) {
source_id_ = source_id;
return CONTINUE_OBSERVING;
}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
ForegroundDurationUKMObserver::FlushMetricsOnAppEnterBackground(
const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& info) {
RecordUkmIfInForeground();
return CONTINUE_OBSERVING;
}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
ForegroundDurationUKMObserver::OnHidden(
const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& info) {
RecordUkmIfInForeground();
return CONTINUE_OBSERVING;
}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
ForegroundDurationUKMObserver::OnShown() {
if (!currently_in_foreground_) {
last_time_shown_ = base::TimeTicks::Now();
currently_in_foreground_ = true;
}
return CONTINUE_OBSERVING;
}
void ForegroundDurationUKMObserver::OnComplete(
const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& info) {
RecordUkmIfInForeground();
}
void ForegroundDurationUKMObserver::RecordUkmIfInForeground() {
if (!currently_in_foreground_)
return;
base::TimeDelta foreground_duration =
base::TimeTicks::Now() - last_time_shown_;
ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
ukm::builders::PageForegroundSession(source_id_)
.SetForegroundDuration(foreground_duration.InMilliseconds())
.Record(ukm_recorder);
currently_in_foreground_ = false;
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_FOREGROUND_DURATION_UKM_OBSERVER_H_
#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_FOREGROUND_DURATION_UKM_OBSERVER_H_
#include "base/time/time.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
// Observer responsible for appending previews information to the PLM UKM
// report.
class ForegroundDurationUKMObserver
: public page_load_metrics::PageLoadMetricsObserver {
public:
ForegroundDurationUKMObserver();
~ForegroundDurationUKMObserver() override;
// page_load_metrics::PageLoadMetricsObserver:
ObservePolicy OnStart(content::NavigationHandle* navigation_handle,
const GURL& currently_committed_url,
bool started_in_foreground) override;
ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
ukm::SourceId source_id) override;
ObservePolicy FlushMetricsOnAppEnterBackground(
const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& info) override;
ObservePolicy OnHidden(
const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& info) override;
ObservePolicy OnShown() override;
void OnComplete(const page_load_metrics::mojom::PageLoadTiming& timing,
const page_load_metrics::PageLoadExtraInfo& info) override;
private:
bool currently_in_foreground_ = false;
base::TimeTicks last_time_shown_;
ukm::SourceId source_id_ = ukm::kInvalidSourceId;
void RecordUkmIfInForeground();
DISALLOW_COPY_AND_ASSIGN(ForegroundDurationUKMObserver);
};
#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_FOREGROUND_DURATION_UKM_OBSERVER_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
using UkmEntry = ukm::builders::PageForegroundSession;
class ForegroundDurationUKMObserverBrowserTest : public InProcessBrowserTest {
public:
ForegroundDurationUKMObserverBrowserTest() {}
~ForegroundDurationUKMObserverBrowserTest() override {}
void PreRunTestOnMainThread() override {
InProcessBrowserTest::PreRunTestOnMainThread();
test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
}
protected:
void StartHttpsServer(net::EmbeddedTestServer::ServerCertificate cert) {
https_test_server_ = std::make_unique<net::EmbeddedTestServer>(
net::EmbeddedTestServer::TYPE_HTTPS);
https_test_server_->SetSSLConfig(cert);
https_test_server_->ServeFilesFromSourceDirectory("chrome/test/data");
ASSERT_TRUE(https_test_server_->Start());
}
void ExpectMetricCountForUrl(const GURL& url,
const char* metric_name,
const int expected_count) {
int count = 0;
for (auto* entry :
test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName)) {
auto* source = test_ukm_recorder_->GetSourceForSourceId(entry->source_id);
if (source && source->url() == url) {
test_ukm_recorder_->EntryHasMetric(entry, metric_name);
count++;
}
}
EXPECT_EQ(count, expected_count);
}
void CloseAllTabs() {
TabStripModel* tab_strip_model = browser()->tab_strip_model();
content::WebContentsDestroyedWatcher destroyed_watcher(
tab_strip_model->GetActiveWebContents());
tab_strip_model->CloseAllTabs();
destroyed_watcher.Wait();
}
net::EmbeddedTestServer* https_test_server() {
return https_test_server_.get();
}
private:
std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
std::unique_ptr<net::EmbeddedTestServer> https_test_server_;
DISALLOW_COPY_AND_ASSIGN(ForegroundDurationUKMObserverBrowserTest);
};
IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, RecordSimple) {
StartHttpsServer(net::EmbeddedTestServer::CERT_OK);
GURL url = https_test_server()->GetURL("/simple.html");
ui_test_utils::NavigateToURL(browser(), url);
CloseAllTabs();
ExpectMetricCountForUrl(url, "ForegroundDuration", 1);
}
IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, TabSwitching) {
StartHttpsServer(net::EmbeddedTestServer::CERT_OK);
GURL url1 = https_test_server()->GetURL("/simple.html");
GURL url2 = https_test_server()->GetURL("/form.html");
ui_test_utils::NavigateToURL(browser(), url1);
ui_test_utils::NavigateToURLWithDisposition(
browser(), url2, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
TabStripModel* tab_strip_model = browser()->tab_strip_model();
EXPECT_EQ(2, tab_strip_model->count());
EXPECT_EQ(url1, tab_strip_model->GetWebContentsAt(0)->GetURL());
EXPECT_EQ(url2, tab_strip_model->GetWebContentsAt(1)->GetURL());
tab_strip_model->ActivateTabAt(0, true);
tab_strip_model->ActivateTabAt(1, true);
tab_strip_model->ActivateTabAt(0, true);
tab_strip_model->ActivateTabAt(1, true);
tab_strip_model->CloseAllTabs();
ExpectMetricCountForUrl(url1, "ForegroundDuration", 3);
ExpectMetricCountForUrl(url2, "ForegroundDuration", 3);
}
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h"
#include "chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h"
#include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
#include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h"
#include "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h"
#include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h"
#include "chrome/browser/page_load_metrics/observers/live_tab_count_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/live_tab_count_page_load_metrics_observer.h"
...@@ -100,6 +101,7 @@ void PageLoadMetricsEmbedder::RegisterObservers( ...@@ -100,6 +101,7 @@ void PageLoadMetricsEmbedder::RegisterObservers(
tracker->AddObserver( tracker->AddObserver(
std::make_unique<data_reduction_proxy::LoFiPageLoadMetricsObserver>()); std::make_unique<data_reduction_proxy::LoFiPageLoadMetricsObserver>());
tracker->AddObserver(std::make_unique<FromGWSPageLoadMetricsObserver>()); tracker->AddObserver(std::make_unique<FromGWSPageLoadMetricsObserver>());
tracker->AddObserver(std::make_unique<ForegroundDurationUKMObserver>());
tracker->AddObserver( tracker->AddObserver(
std::make_unique<DocumentWritePageLoadMetricsObserver>()); std::make_unique<DocumentWritePageLoadMetricsObserver>());
tracker->AddObserver( tracker->AddObserver(
......
...@@ -727,6 +727,7 @@ test("browser_tests") { ...@@ -727,6 +727,7 @@ test("browser_tests") {
"../browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc", "../browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc", "../browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/data_use_metrics_observer_browsertest.cc", "../browser/page_load_metrics/observers/data_use_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc",
"../browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc", "../browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/live_tab_count_page_load_metrics_observer_browsertest.cc", "../browser/page_load_metrics/observers/live_tab_count_page_load_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc", "../browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc",
......
...@@ -1711,6 +1711,20 @@ be describing additional metrics about the same event. ...@@ -1711,6 +1711,20 @@ be describing additional metrics about the same event.
</metric> </metric>
</event> </event>
<event name="PageForegroundSession">
<owner>sullivan@chromium.org</owner>
<summary>
Total time in foreground in milliseconds, recorded each time the page is
backgrounded. May be recorded multiple times for a single page visit.
</summary>
<metric name="ForegroundDuration">
<summary>
Total time in foreground in milliseconds, recorded each time the page is
backgrounded.
</summary>
</metric>
</event>
<event name="Intervention.DocumentWrite.ScriptBlock" singular="True"> <event name="Intervention.DocumentWrite.ScriptBlock" singular="True">
<owner>bmcquade@chromium.org</owner> <owner>bmcquade@chromium.org</owner>
<summary> <summary>
......
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