Commit bbcf3123 authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

[PM] Record the MIME type of a PageNode after a navigation event

Recording the MIME type of the main frame of a page will give us more
information about what the page contains. This will be useful to some
of the interventions like tab discarding who handle PDFs and regular
pages differently.

Bug: 1030399
Change-Id: I03cc93e913abb351f070a9cc68f808f601252656
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1955033
Auto-Submit: Sébastien Marchand <sebmarchand@chromium.org>
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Cr-Commit-Position: refs/heads/master@{#723440}
parent 49b99c4e
......@@ -128,7 +128,8 @@ void PageAlmostIdleDecoratorTest::TestPageAlmostIdleTransitions(bool timeout) {
// Post a navigation. The state should reset.
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(), 1,
GURL("https://www.example.org"));
GURL("https://www.example.org"),
"text/html");
page_data = Data::GetForTesting(page_node);
EXPECT_EQ(LIS::kLoadingNotStarted, page_data->load_idle_state_);
EXPECT_FALSE(page_data->idling_timer_.IsRunning());
......
......@@ -20,6 +20,7 @@ const char kExpectedQueueingTime[] = "ExpectedTaskQueueingDuration";
const base::TimeDelta kTestMetricsReportDelayTimeout =
kMetricsReportDelayTimeout + base::TimeDelta::FromSeconds(1);
const GURL kDummyUrl("http://www.example.org");
const std::string kHtmlMimeType = "text/html";
// TODO(crbug.com/759905) Enable on Windows once this bug is fixed.
#if defined(OS_WIN)
......@@ -58,7 +59,7 @@ TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstTitleUpdatedUMA) {
auto page_node = CreateNode<PageNodeImpl>();
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_node->SetIsVisible(true);
......@@ -91,7 +92,7 @@ TEST_F(MAYBE_MetricsCollectorTest,
auto page_node = CreateNode<PageNodeImpl>();
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
page_node->SetIsVisible(false);
page_node->OnTitleUpdated();
// The page is within 5 minutes after main frame navigation was committed,
......@@ -111,7 +112,7 @@ TEST_F(MAYBE_MetricsCollectorTest,
auto frame_node = CreateFrameNodeAutoId(process_node.get(), page_node.get());
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_node->SetIsVisible(true);
......@@ -147,7 +148,7 @@ TEST_F(
auto frame_node = CreateFrameNodeAutoId(process_node.get(), page_node.get());
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
page_node->SetIsVisible(false);
frame_node->OnNonPersistentNotificationCreated();
// The page is within 5 minutes after main frame navigation was committed,
......@@ -164,7 +165,7 @@ TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstFaviconUpdatedUMA) {
auto page_node = CreateNode<PageNodeImpl>();
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_node->SetIsVisible(true);
......@@ -197,7 +198,7 @@ TEST_F(MAYBE_MetricsCollectorTest,
auto page_node = CreateNode<PageNodeImpl>();
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
page_node->SetIsVisible(false);
page_node->OnFaviconUpdated();
// The page is within 5 minutes after main frame navigation was committed,
......@@ -224,7 +225,7 @@ TEST_F(MAYBE_MetricsCollectorTest, ResponsivenessMetric) {
ukm_recorder.UpdateSourceURL(id, url);
page_node->SetUkmSourceId(id);
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
kDummyID, kDummyUrl);
kDummyID, kDummyUrl, kHtmlMimeType);
for (int count = 1; count < kDefaultFrequencyUkmEQTReported; ++count) {
process_node->SetExpectedTaskQueueingDuration(
......
......@@ -26,6 +26,8 @@ namespace {
using performance_manager::NodeBase;
const std::string kHtmlMimeType = "text/html";
class TestChangeStream : public discards::mojom::GraphChangeStream {
public:
using FrameMap = std::map<int64_t, discards::mojom::FrameInfoPtr>;
......@@ -158,9 +160,9 @@ TEST_F(DiscardsGraphDumpImplTest, ChangeStream) {
const GURL kExampleUrl("http://www.example.org");
int64_t next_navigation_id = 1;
mock_graph.page->OnMainFrameNavigationCommitted(
false, now, next_navigation_id++, kExampleUrl);
false, now, next_navigation_id++, kExampleUrl, kHtmlMimeType);
mock_graph.other_page->OnMainFrameNavigationCommitted(
false, now, next_navigation_id++, kExampleUrl);
false, now, next_navigation_id++, kExampleUrl, kHtmlMimeType);
auto* main_frame = mock_graph.page->GetMainFrameNodeImpl();
main_frame->OnNavigationCommitted(kExampleUrl, /* same_document */ false);
......@@ -221,7 +223,7 @@ TEST_F(DiscardsGraphDumpImplTest, ChangeStream) {
// Test change notifications.
const GURL kAnotherURL("http://www.google.com/");
mock_graph.page->OnMainFrameNavigationCommitted(
false, now, next_navigation_id++, kAnotherURL);
false, now, next_navigation_id++, kAnotherURL, kHtmlMimeType);
size_t child_frame_id =
NodeBase::GetSerializationId(mock_graph.child_frame.get());
......
......@@ -102,7 +102,8 @@ void PageNodeImpl::OnMainFrameNavigationCommitted(
bool same_document,
base::TimeTicks navigation_committed_time,
int64_t navigation_id,
const GURL& url) {
const GURL& url,
const std::string& contents_mime_type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// This should never be invoked with a null navigation, nor should it be
// called twice for the same navigation.
......@@ -110,6 +111,7 @@ void PageNodeImpl::OnMainFrameNavigationCommitted(
DCHECK_NE(navigation_id_, navigation_id);
navigation_committed_time_ = navigation_committed_time;
navigation_id_ = navigation_id;
contents_mime_type_ = contents_mime_type;
main_frame_url_.SetAndMaybeNotify(this, url);
// No mainframe document change notification on same-document navigations.
......@@ -245,6 +247,11 @@ int64_t PageNodeImpl::navigation_id() const {
return navigation_id_;
}
const std::string& PageNodeImpl::contents_mime_type() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return contents_mime_type_;
}
void PageNodeImpl::set_usage_estimate_time(
base::TimeTicks usage_estimate_time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
......@@ -350,6 +357,11 @@ int64_t PageNodeImpl::GetNavigationID() const {
return navigation_id();
}
const std::string& PageNodeImpl::GetContentsMimeType() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return contents_mime_type();
}
base::TimeDelta PageNodeImpl::GetTimeSinceLastNavigation() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return TimeSinceLastNavigation();
......
......@@ -51,7 +51,8 @@ class PageNodeImpl
void OnMainFrameNavigationCommitted(bool same_document,
base::TimeTicks navigation_committed_time,
int64_t navigation_id,
const GURL& url);
const GURL& url,
const std::string& contents_mime_type);
// Returns the average CPU usage that can be attributed to this page over the
// last measurement period. CPU usage is expressed as the average percentage
......@@ -91,6 +92,7 @@ class PageNodeImpl
bool page_almost_idle() const;
const GURL& main_frame_url() const;
int64_t navigation_id() const;
const std::string& contents_mime_type() const;
void set_usage_estimate_time(base::TimeTicks usage_estimate_time);
void set_cumulative_cpu_usage_estimate(
......@@ -134,6 +136,7 @@ class PageNodeImpl
bool IsHoldingWebLock() const override;
bool IsHoldingIndexedDBLock() const override;
int64_t GetNavigationID() const override;
const std::string& GetContentsMimeType() const override;
base::TimeDelta GetTimeSinceLastNavigation() const override;
const FrameNode* GetMainFrameNode() const override;
const base::flat_set<const FrameNode*> GetMainFrameNodes() const override;
......@@ -199,6 +202,11 @@ class PageNodeImpl
// zero if the page has never committed a navigation.
int64_t navigation_id_ = 0;
// The MIME type of the content associated with the last committed navigation
// event for the main frame of this page or an empty string if the page has
// never committed a navigation
std::string contents_mime_type_;
// The unique ID of the browser context that this page belongs to.
const std::string browser_context_id_;
......
......@@ -20,6 +20,9 @@ namespace {
using PageNodeImplTest = GraphTestHarness;
const std::string kHtmlMimeType = "text/html";
const std::string kPdfMimeType = "application/pdf";
} // namespace
TEST_F(PageNodeImplTest, SafeDowncast) {
......@@ -124,9 +127,10 @@ TEST_F(PageNodeImplTest, TimeSinceLastNavigation) {
// 1st navigation.
GURL url("http://www.example.org");
mock_graph.page->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
10u, url);
10u, url, kHtmlMimeType);
EXPECT_EQ(url, mock_graph.page->main_frame_url());
EXPECT_EQ(10u, mock_graph.page->navigation_id());
EXPECT_EQ(kHtmlMimeType, mock_graph.page->contents_mime_type());
AdvanceClock(base::TimeDelta::FromSeconds(11));
EXPECT_EQ(base::TimeDelta::FromSeconds(11),
mock_graph.page->TimeSinceLastNavigation());
......@@ -134,9 +138,10 @@ TEST_F(PageNodeImplTest, TimeSinceLastNavigation) {
// 2nd navigation.
url = GURL("http://www.example.org/bobcat");
mock_graph.page->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
20u, url);
20u, url, kHtmlMimeType);
EXPECT_EQ(url, mock_graph.page->main_frame_url());
EXPECT_EQ(20u, mock_graph.page->navigation_id());
EXPECT_EQ(kHtmlMimeType, mock_graph.page->contents_mime_type());
AdvanceClock(base::TimeDelta::FromSeconds(17));
EXPECT_EQ(base::TimeDelta::FromSeconds(17),
mock_graph.page->TimeSinceLastNavigation());
......@@ -144,9 +149,21 @@ TEST_F(PageNodeImplTest, TimeSinceLastNavigation) {
// Test a same-document navigation.
url = GURL("http://www.example.org/bobcat#fun");
mock_graph.page->OnMainFrameNavigationCommitted(true, base::TimeTicks::Now(),
30u, url);
30u, url, kHtmlMimeType);
EXPECT_EQ(url, mock_graph.page->main_frame_url());
EXPECT_EQ(30u, mock_graph.page->navigation_id());
EXPECT_EQ(kHtmlMimeType, mock_graph.page->contents_mime_type());
AdvanceClock(base::TimeDelta::FromSeconds(17));
EXPECT_EQ(base::TimeDelta::FromSeconds(17),
mock_graph.page->TimeSinceLastNavigation());
// Test a navigation to a page with a different MIME type.
url = GURL("http://www.example.org/document.pdf");
mock_graph.page->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
40u, url, kPdfMimeType);
EXPECT_EQ(url, mock_graph.page->main_frame_url());
EXPECT_EQ(40u, mock_graph.page->navigation_id());
EXPECT_EQ(kPdfMimeType, mock_graph.page->contents_mime_type());
AdvanceClock(base::TimeDelta::FromSeconds(17));
EXPECT_EQ(base::TimeDelta::FromSeconds(17),
mock_graph.page->TimeSinceLastNavigation());
......@@ -275,14 +292,14 @@ TEST_F(PageNodeImplTest, ObserverWorks) {
EXPECT_CALL(obs, OnMainFrameUrlChanged(_))
.WillOnce(Invoke(&obs, &MockObserver::SetNotifiedPageNode));
// Expect no OnMainFrameDocumentChanged for same-document navigation
page_node->OnMainFrameNavigationCommitted(true, base::TimeTicks::Now(),
++navigation_id, kTestUrl);
page_node->OnMainFrameNavigationCommitted(
true, base::TimeTicks::Now(), ++navigation_id, kTestUrl, kHtmlMimeType);
EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
EXPECT_CALL(obs, OnMainFrameDocumentChanged(_))
.WillOnce(Invoke(&obs, &MockObserver::SetNotifiedPageNode));
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(),
++navigation_id, kTestUrl);
page_node->OnMainFrameNavigationCommitted(
false, base::TimeTicks::Now(), ++navigation_id, kTestUrl, kHtmlMimeType);
EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
EXPECT_CALL(obs, OnTitleUpdated(_))
......@@ -321,8 +338,14 @@ TEST_F(PageNodeImplTest, PublicInterface) {
EXPECT_EQ(page_node->ukm_source_id(), public_page_node->GetUkmSourceID());
EXPECT_EQ(page_node->lifecycle_state(),
public_page_node->GetLifecycleState());
page_node->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(), 10u,
GURL("https://foo.com"),
kHtmlMimeType);
EXPECT_EQ(page_node->navigation_id(), public_page_node->GetNavigationID());
EXPECT_EQ(page_node->main_frame_url(), public_page_node->GetMainFrameUrl());
EXPECT_EQ(page_node->contents_mime_type(),
public_page_node->GetContentsMimeType());
}
} // namespace performance_manager
......@@ -301,7 +301,7 @@ void PerformanceManagerTabHelper::DidFinishNavigation(
PostToGraph(FROM_HERE, &PageNodeImpl::OnMainFrameNavigationCommitted,
page_node_.get(), navigation_handle->IsSameDocument(),
navigation_committed_time, navigation_handle->GetNavigationId(),
url);
url, navigation_handle->GetWebContents()->GetContentsMimeType());
}
void PerformanceManagerTabHelper::TitleWasSet(content::NavigationEntry* entry) {
......
......@@ -84,6 +84,10 @@ class PageNode : public Node {
// See PageNodeObserver::OnMainFrameNavigationCommitted.
virtual int64_t GetNavigationID() const = 0;
// Returns the MIME type of the contents associated with the last committed
// navigation event for the main frame of this page.
virtual const std::string& GetContentsMimeType() const = 0;
// Returns "zero" if no navigation has happened, otherwise returns the time
// since the last navigation commit.
virtual base::TimeDelta GetTimeSinceLastNavigation() const = 0;
......
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